--------------------------------------------------------------------------------
-                                                                              -
-                              Project X 0.81.5                                -
-                                                                              -
--------------------------------------------------------------------------------

 History:

 01.10.2003 fix: fix of last change (2003/09/28)
 29.09.2003 update: AC3.bin
 28.09.2003 fix: quickinfo didn't work, if first cut-in point was greater than
            quickinfosize (on BytePos cut)
 28.09.2003 fix: prevent to overwrite TS sourcefile on 'toTS', if output directory
            is the same as input
 28.09.2003 change: 'toTS': simply align video/audio startcodes/synchwords in
            first pes-packet of each pid and for each split part (same as 'toMPG')
 27.09.2003 @fix?: stuttering audio on toTS
 27.09.2003 change: picture pre-scaling modified
 18.09.2003 fix: array exception, caused by erroneous TS packets
 18.09.2003 fix: first PMT entry might not be read out correctly
 13.09.2003 fix: wrong entry in RIFF header for subchunk2size (PCM datasize)
 13.09.2003 fix: array exception, caused by to small (psb. erroneous filtered) GOP
            arrays
 12.09.2003 fix: chroma irritations on field encoded macroblocks
            doubleclick onto preview area opens a dialog to save a 24bit bitmap of
            last shown picture in original size (auto numbered)
 06.09.2003 fix: missing data on binary extraction from HexViewer
 04.09.2003 change: ignore bsid (AC3) when verifying frames
 02.09.2003 enhancement: preview also supports color formats 4:2:2/4:4:4 (high
            profiles)

--------------------------------------------------------------------------------

 29.08.2003 fix dvb.matt: bad/incomplete/short slices may cause black preview
            pictures and for every following picture
 26.08.2003 enhancement TheHorse: Preview slider move & cut keyboard keys
 24.08.2003 enhancement dvb.matt: show expected export filesize in cut dialog
 16.06.2003 fix dvb.matt: extendend look-up for usable data in unscrambled marked
            TS-packets (bad flags in recordings)
 15.08.2003 release: dvb.matt Project X 0.81
 14.08.2003 extension: java.lang (patch horizontal resolution of the 1st sequence
            header)
 08.08.2003 suggestion: message log if the following nonVideo stream cannot handled
            by its own PTS data (because it's missing)
 06.08.2003 extension: java.lang (idd)
 29.07.2003 fix: remove a little bit more cross coloured speckles in preview
 23.07.2003 fix: exception while parsing bad/wrong AC3-frames (bad index)
 20.07.2003 fix: remove cross coloured speckles in preview
 19.07.2003 fix: enabled cut- and split- pointer didn't work properly in case of
            more than 2 inputfiles
 19.07.2003 fix: preview didn't jump properly among fileborders in case of more
            than 2 inputfiles
 13.07.2003 Project X 0.8 relaesed

--------------------------------------------------------------------------------

 Codes:

--------------------------------------------------------------------------------
- 01.10.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: fix of last change (2003/09/28)

@X.java
@inner class makeVDR
@method writeTS(), line ~10735

fix of last change #3 (2003/09/28)

(1) replace method writeTS

	/**** TFraw mpeg-ts ******/  //DM01102003 fix
	public long[] writeTS(byte[] data, long[] options, PIDdemux demux, int overhead) {    // data = 1 pespacket from demux
		toTS=true;
		int datalength=0, ptslength=0, shift=0;    // TS packet max. 188, start ID on new pespack with pts
		boolean pcr=false;
		buf.reset();

		try 
		{
		int type = demux.getType();
		int newID = demux.getnewID();       // read new mapped ID
		if (type==3 && newID>0xE0) 
			return options;      // ignore more video
		if (type==4) 
			return options;        // return, lpcm not accept
		if (type!=3 && !video && cBox[23].isSelected()) 
			return options; // must start with video  

		if (data.length>overhead) { 

			int i=0;
			for (;i<IDs.size();i++) {          // new ID arrived, save for PMT
				if (newID==(0xFF&Integer.parseInt(IDs.get(i).toString()))) 
					break;
			}

			datalength = data.length-overhead;

			if (type==0 && demux.getStreamType()==2) {  //adapt ac3 from mpg-ps
				datalength-=4;
				int size = datalength-6;
				int head = 9+(0xFF&data[8]);
				data[4] = (byte)(size>>>8);    // correct length info
				data[5] = (byte)(0xFF&size);   //   --"--

				byte[] data2 = new byte[datalength];
				System.arraycopy(data,0,data2,0,head);
				System.arraycopy(data,head+4,data2,head,datalength-head);
				data=data2;
			}

			if (i==IDs.size()) {
				int newID2 = newID;
				if (newID2<0x90) 
					newID2 |= 0x200;
				if (newID2<0xC0) 
					newID2 |= 0x300;
				if (newID2<0xE0) 
					newID2 |= 0x100;

				if (!qinfo){
					if (newID!=0xE0 && !video && cBox[23].isSelected()) 
						return options; // must start with video  
					if (type!=1)
						data = searchHeader(data,type,overhead);
					if (data.length==0) 
						return options;
				}
				IDs.add(""+newID2);
			}

			if (!writedata[0] && (0xF0&data[3])==0xE0 ) 
				return options;
			else if (!writedata[1] && (0xF0&data[3])!=0xE0 ) 
				return options;

			TSHead[2] = TSHead2[2] = (byte)(0xFF&newID);

			if ((0x80&data[7])!=0) 
				data[9] &= ~8;     // in PTS delete bit 33 PTS
			if ((0x40&data[7])!=0) 
				data[14] &= ~8;    // in DTS  -"-
			if (type==3) 
				data[4]=data[5]=0;

			/*** tf special ****/
			if (first) {
				tf.init(name,cBox[37].isSelected(),cBox[42].isSelected());
				if (cBox[35].isSelected()) 
					buf.write(tf.getHead1());
				first=false; 
			}

			boolean hasPTS=false;
			if ((0x80&data[7])!=0)
				hasPTS=true;

			int countID=3;
			long pcrbase=0;

			if (hasPTS && tf.getfirstID()==(0xFF&newID)) {
				long pts = 0xFFFFFFFFL & ( (6&data[9])<<29 | (255&data[10])<<22 | (254&data[11])<<14 | (255&data[12])<<7 | (254&data[13])>>>1 );
				pcrbase = (pts-options[57]);
				if ( (pts & 0xFF000000L)==0xFF000000L ) 
					ptsover=true;
				if (ptsover && pts<0xF0000000L) 
					pts |= 0x100000000L;
				time[1]=pts;
				pcr=true;
				if (time[0]==-1) 
					time[0]=time[1];
			}

			switch (0xF0&newID) {
			case 0x80: { 
				countID=newID-0x6C; 
				break; 
			}
			case 0x90: { 
				countID=newID-0x8C; 
				break; 
			}
			case 0xC0:
			case 0xD0: { 
				countID=newID-0x9C; 
				break; 
			}
			case 0xE0: { countID=1;
				if (hasPTS) {
					pcr=false;

					/*** looking for I or P-Frameheader ***/
					for (int a=9;a<datalength+overhead-6;a++) {
						if (data[a]!=0 || data[a+1]!=0 || data[a+2]!=1 || data[a+3]!=0) 
							continue;
						if ((0x38&data[a+5])==0x8){
							pcr=true; 
							video=true; 
						}
						break;
					}
				}
				break;
			}
			}

			if (type==3 && !video && cBox[23].isSelected()) 
				return options; // must start with video  

			if (30000L*pmtcount <= options[41]) {
				buf.write(tf.getPat());
				if (cBox[41].isSelected()) 
					buf.write(tf.getAutoPmt());
				else 
					buf.write(tf.getPmt());
				pmtcount++;
			}

			if (pcr && cBox[41].isSelected() && cBox[42].isSelected()) {
				buf.write(tf.getTTX(ttc,data,calctime.format(new java.util.Date((pcrbase+options[57])/90))));
			}

			if (pcr && cBox[36].isSelected()) {
				if (!cBox[46].isSelected()) 
					buf.write(tf.getPCR(pcrbase,counter[countID],(0xFF&newID))); // no payload==no counter++
				else 
					buf.write(tf.getPCR(pcrbase,++counter[countID],(0xFF&newID)));
			}

			int a=0;
			while (a<datalength) {
				if (a==0) {
					if (datalength-a < 183) {
						TSHead[3] = (byte)(0x30 | (0xF&++counter[countID]));
						int stuff = 182-(datalength-a);
						adapt[0] = (byte)(stuff+1);
						buf.write(TSHead); 
						buf.write(adapt); 
						buf.write(fills,6,stuff);
						buf.write(data,a,datalength-a); 
						a+=(datalength-a);
					} else if (datalength-a == 184) {
						TSHead[3] = (byte)(0x10 | (0xF&++counter[countID]));
						buf.write(TSHead); 
						buf.write(data,a,184); 
						a+=184;
					} else if (datalength-a < 185) {
						TSHead[3] = (byte)(0x30 | (0xF&++counter[countID]));
						adapt[0] = 1;
						buf.write(TSHead); 
						buf.write(adapt); 
						buf.write(data,a,182); 
						a+=182;
					} else {
						TSHead[3] = (byte)(0x10 | (0xF&++counter[countID]));
						buf.write(TSHead); 
						buf.write(data,a,184); 
						a+=184;
					}
				} else if (datalength-a < 183) {
					TSHead2[3] = (byte)(0x30 | (0xF&++counter[countID]));
					int stuff = 182-(datalength-a);
					adapt[0] = (byte)(stuff+1);
					buf.write(TSHead2); 
					buf.write(adapt); 
					buf.write(fills,6,stuff);
					buf.write(data,a,datalength-a); 
					a+=(datalength-a);
				} else if (datalength-a == 184) {
					TSHead2[3] = (byte)(0x10 | (0xF&++counter[countID]));
					buf.write(TSHead2); 
					buf.write(data,a,184); 
					a+=184;
				} else if (datalength-a < 185) {
					TSHead2[3] = (byte)(0x30 | (0xF&++counter[countID]));
					adapt[0] = 1;
					buf.write(TSHead2); 
					buf.write(adapt); 
					buf.write(data,a,182); 
					a+=182;
				} else {
					TSHead2[3] = (byte)(0x10 | (0xF&++counter[countID]));
					buf.write(TSHead2); 
					buf.write(data,a,184); 
					a+=184;
				}
				options[39]+=188; 
				options[41]+=188;
			}
			buf.writeTo(out);
			buf.reset();
		}
		}
		catch (IOException e) { 
			Msg("writeTS error4"+e); 
		}
		return options;
	}

--------------------------------------------------------------------------------
- 28.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: quickinfo didn't work, if first cut-in point was greater than quickinfosize (on BytePos cut)

@X.java
@inner class WORK
@method pesparse(), line ~4784
@method vdrparse(), line ~5156
@method rawparse(), line ~5768
@method pvaparse(), line ~6624

(1) add/change variable qexit in all 4 methods

...
	long qexit = count+options[56]; //add

	morepva:
	while (true) {
		...
			if (qbreak || (qinfo && count>qexit)) { //changed
				qbreak=false; 
				break morepva; 
			}
...

--------------------------------------------------------------------------------
- 28.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: prevent to overwrite TS sourcefile on 'toTS', if output directory is the same as input

@X.java
@inner class WORK
@method rawparse(), line ~5661

(1) change line

...
	else if (ToVDR==4) 
		makevdr.init(fparent+"(ts).ts",options,bs); //changed
...

--------------------------------------------------------------------------------
- 28.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@change: 'toTS': simply align video/audio startcodes/synchwords in first pes-packet of each pid and for each split part (same as 'toMPG')

@X.java
@inner class makeVDR
@method writeTS(), line ~10735

notes:
- splitting on 'toMPG/toTS(toPVA)' without overlap will always discard some data trough these alignments.
- although that's better for most players, the complete media content cannot be restored if you want to merge all the new parts again, later..
- 'toVDR' does not align any packetized media content in first pes-packets.

(1) replace method writeTS

	public long[] writeTS(byte[] data, long[] options, PIDdemux demux, int overhead) {    // data = 1 pespacket from demux
		toTS=true;
		int datalength=0, ptslength=0, shift=0;    // TS packet max. 188, start ID on new pespack with pts
		boolean pcr=false;
		buf.reset();

		try 
		{
		int type = demux.getType();
		int newID = demux.getnewID();       // read new mapped ID
		if (type==3 && newID>0xE0) 
			return options;      // ignore more video
		if (type==4) 
			return options;        // return, lpcm not accept
		if (type!=3 && !video && cBox[23].isSelected()) 
			return options; // must start with video  

		if (data.length>overhead) { 

			int i=0;
			for (;i<IDs.size();i++) {          // new ID arrived, save for PMT
				if (newID==(0xFF&Integer.parseInt(IDs.get(i).toString()))) 
					break;
			}
			if (i==IDs.size()) {
				int newID2 = newID;
				if (newID2<0x90) 
					newID2 |= 0x200;
				if (newID2<0xC0) 
					newID2 |= 0x300;
				if (newID2<0xE0) 
					newID2 |= 0x100;

				if (!qinfo){
					if (newID!=0xE0 && !video && cBox[23].isSelected()) 
						return options; // must start with video  
					if (type!=1)
						data = searchHeader(data,type,overhead);
					if (data.length==0) 
						return options;
				}
				IDs.add(""+newID2);
			}

			if (!writedata[0] && (0xF0&data[3])==0xE0 ) 
				return options;
			else if (!writedata[1] && (0xF0&data[3])!=0xE0 ) 
				return options;

			TSHead[2] = TSHead2[2] = (byte)(0xFF&newID);
			datalength = data.length-overhead;

			if ((0x80&data[7])!=0) 
				data[9] &= ~8;     // in PTS delete bit 33 PTS
			if ((0x40&data[7])!=0) 
				data[14] &= ~8;    // in DTS  -"-

			if (type==0 && demux.getStreamType()==2) {  //adapt ac3 from mpg-ps
				datalength-=4;
				int size = datalength-6;
				int head = 9+(0xFF&data[8]);
				data[4] = (byte)(size>>>8);    // correct length info
				data[5] = (byte)(0xFF&size);   //   --"--

				byte[] data2 = new byte[datalength];
				System.arraycopy(data,0,data2,0,head);
				System.arraycopy(data,head+4,data2,head,datalength-head);
				data=data2;
			}
			else if (type==3) 
				data[4]=data[5]=0;

			/*** tf special ****/
			if (first) {
				tf.init(name,cBox[37].isSelected(),cBox[42].isSelected());
				if (cBox[35].isSelected()) 
					buf.write(tf.getHead1());
				first=false; 
			}

			boolean hasPTS=false;
			if ((0x80&data[7])!=0)
				hasPTS=true;

			int countID=3;
			long pcrbase=0;

			if (hasPTS && tf.getfirstID()==(0xFF&newID)) {
				long pts = 0xFFFFFFFFL & ( (6&data[9])<<29 | (255&data[10])<<22 | (254&data[11])<<14 | (255&data[12])<<7 | (254&data[13])>>>1 );
				pcrbase = (pts-options[57]);
				if ( (pts & 0xFF000000L)==0xFF000000L ) 
					ptsover=true;
				if (ptsover && pts<0xF0000000L) 
					pts |= 0x100000000L;
				time[1]=pts;
				pcr=true;
				if (time[0]==-1) 
					time[0]=time[1];
			}

			switch (0xF0&newID) {
			case 0x80: { 
				countID=newID-0x6C; 
				break; 
			}
			case 0x90: { 
				countID=newID-0x8C; 
				break; 
			}
			case 0xC0:
			case 0xD0: { 
				countID=newID-0x9C; 
				break; 
			}
			case 0xE0: { countID=1;
				if (hasPTS) {
					pcr=false;

					/*** looking for I or P-Frameheader ***/
					for (int a=9;a<datalength+overhead-6;a++) {
						if (data[a]!=0 || data[a+1]!=0 || data[a+2]!=1 || data[a+3]!=0) 
							continue;
						if ((0x38&data[a+5])==0x8){
							pcr=true; 
							video=true; 
						}
						break;
					}
				}
				break;
			}
			}

			if (type==3 && !video && cBox[23].isSelected()) 
				return options; // must start with video  

			if (30000L*pmtcount <= options[41]) {
				buf.write(tf.getPat());
				if (cBox[41].isSelected()) 
					buf.write(tf.getAutoPmt());
				else 
					buf.write(tf.getPmt());
				pmtcount++;
			}

			if (pcr && cBox[41].isSelected() && cBox[42].isSelected()) {
				buf.write(tf.getTTX(ttc,data,calctime.format(new java.util.Date((pcrbase+options[57])/90))));
			}

			if (pcr && cBox[36].isSelected()) {
				if (!cBox[46].isSelected()) 
					buf.write(tf.getPCR(pcrbase,counter[countID],(0xFF&newID))); // no payload==no counter++
				else 
					buf.write(tf.getPCR(pcrbase,++counter[countID],(0xFF&newID)));
			}

			int a=0;
			while (a<datalength) {
				if (a==0) {
					if (datalength-a < 183) {
						TSHead[3] = (byte)(0x30 | (0xF&++counter[countID]));
						int stuff = 182-(datalength-a);
						adapt[0] = (byte)(stuff+1);
						buf.write(TSHead); 
						buf.write(adapt); 
						buf.write(fills,6,stuff);
						buf.write(data,a,datalength-a); 
						a+=(datalength-a);
					} else if (datalength-a == 184) {
						TSHead[3] = (byte)(0x10 | (0xF&++counter[countID]));
						buf.write(TSHead); 
						buf.write(data,a,184); 
						a+=184;
					} else if (datalength-a < 185) {
						TSHead[3] = (byte)(0x30 | (0xF&++counter[countID]));
						adapt[0] = 1;
						buf.write(TSHead); 
						buf.write(adapt); 
						buf.write(data,a,182); 
						a+=182;
					} else {
						TSHead[3] = (byte)(0x10 | (0xF&++counter[countID]));
						buf.write(TSHead); 
						buf.write(data,a,184); 
						a+=184;
					}
				} else if (datalength-a < 183) {
					TSHead2[3] = (byte)(0x30 | (0xF&++counter[countID]));
					int stuff = 182-(datalength-a);
					adapt[0] = (byte)(stuff+1);
					buf.write(TSHead2); 
					buf.write(adapt); 
					buf.write(fills,6,stuff);
					buf.write(data,a,datalength-a); 
					a+=(datalength-a);
				} else if (datalength-a == 184) {
					TSHead2[3] = (byte)(0x10 | (0xF&++counter[countID]));
					buf.write(TSHead2); 
					buf.write(data,a,184); 
					a+=184;
				} else if (datalength-a < 185) {
					TSHead2[3] = (byte)(0x30 | (0xF&++counter[countID]));
					adapt[0] = 1;
					buf.write(TSHead2); 
					buf.write(adapt); 
					buf.write(data,a,182); 
					a+=182;
				} else {
					TSHead2[3] = (byte)(0x10 | (0xF&++counter[countID]));
					buf.write(TSHead2); 
					buf.write(data,a,184); 
					a+=184;
				}
				options[39]+=188; 
				options[41]+=188;
			}
			buf.writeTo(out);
			buf.reset();
		}
		}
		catch (IOException e) { 
			Msg("writeTS error4"+e); 
		}
		return options;
	}
--------------------------------------------------------------------------------
- 27.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix?: stuttering audio on toTS

@X.java
@inner class makeVDR
@method writeTS(), line ~10730

(a) packet counter changed to ++counter[countID] (counts before writing) (not important, but more conform than before)
(b) always write PES header (don't discard anymore), even without PTS (and PCR)

(1) replace method writeTS

	/**** TFraw mpeg-ts ******/  //DM27092003 fix?
	public long[] writeTS(byte[] data, long[] options, PIDdemux demux, int overhead) {    // data = 1 pespacket from demux
		toTS=true;
		int datalength=0, ptslength=0, shift=0;    // TS packet max. 188, start ID on new pespack with pts
		boolean pcr=false;
		buf.reset();

		try 
		{
		int type = demux.getType();
		int newID = demux.getnewID();       // read new mapped ID
		if (type==3 && newID>0xE0) 
			return options;      // ignore more video
		if (type==4) 
			return options;        // return, lpcm not accept
		if (type!=3 && !video && cBox[23].isSelected()) 
			return options; // must start with video  

		if (qinfo) {
			int i=0;
			for (;i<IDs.size();i++) {          // new ID arrived, save for PMT
				if (newID==(0xFF&Integer.parseInt(IDs.get(i).toString()))) 
					break;
			}
			if (i==IDs.size()) {
				int newID2 = newID;
				if (newID2<0x90) 
					newID2 |= 0x200;
				if (newID2<0xC0) 
					newID2 |= 0x300;
				if (newID2<0xE0) 
					newID2 |= 0x100;
				IDs.add(""+newID2);
			}
		}

		if (data.length>overhead) { 
			if (!writedata[0] && (0xF0&data[3])==0xE0 ) 
				return options;
			else if (!writedata[1] && (0xF0&data[3])!=0xE0 ) 
				return options;

			TSHead[2] = TSHead2[2] = (byte)(0xFF&newID);
			datalength = data.length-overhead;

			if ((0x80&data[7])!=0) 
				data[9] &= ~8;     // in PTS delete bit 33 PTS
			if ((0x40&data[7])!=0) 
				data[14] &= ~8;    // in DTS  -"-

			if (type==0 && demux.getStreamType()==2) {  //adapt ac3 from mpg-ps
				datalength-=4;
				int size = datalength-6;
				int head = 9+(0xFF&data[8]);
				data[4] = (byte)(size>>>8);    // correct length info
				data[5] = (byte)(0xFF&size);   //   --"--

				byte[] data2 = new byte[datalength];
				System.arraycopy(data,0,data2,0,head);
				System.arraycopy(data,head+4,data2,head,datalength-head);
				data=data2;
			}
			else if (type==3) 
				data[4]=data[5]=0;

			/*** tf special ****/
			if (first) {
				tf.init(name,cBox[37].isSelected(),cBox[42].isSelected());
				if (cBox[35].isSelected()) 
					buf.write(tf.getHead1());
				first=false; 
			}

			boolean hasPTS=false;
			if ((0x80&data[7])!=0)
				hasPTS=true;

			int countID=3;
			long pcrbase=0;

			if (hasPTS && tf.getfirstID()==(0xFF&newID)) {
				long pts = 0xFFFFFFFFL & ( (6&data[9])<<29 | (255&data[10])<<22 | (254&data[11])<<14 | (255&data[12])<<7 | (254&data[13])>>>1 );
				pcrbase = (pts-options[57]);
				if ( (pts & 0xFF000000L)==0xFF000000L ) 
					ptsover=true;
				if (ptsover && pts<0xF0000000L) 
					pts |= 0x100000000L;
				time[1]=pts;
				pcr=true;
				if (time[0]==-1) 
					time[0]=time[1];
			}

			switch (0xF0&newID) {
			case 0x80: { 
				countID=newID-0x6C; 
				break; 
			}
			case 0x90: { 
				countID=newID-0x8C; 
				break; 
			}
			case 0xC0:
			case 0xD0: { 
				countID=newID-0x9C; 
				break; 
			}
			case 0xE0: { countID=1;
				if (hasPTS) {
					pcr=false;

					/*** looking for I or P-Frameheader ***/
					for (int a=9;a<datalength+overhead-6;a++) {
						if (data[a]!=0 || data[a+1]!=0 || data[a+2]!=1 || data[a+3]!=0) 
							continue;
						//  if ((0x38&data[a+5])==0x8 || (0x38&data[a+5])==0x10)
						if ((0x38&data[a+5])==0x8){
							pcr=true; 
							video=true; 
						}
						break;
					}
				}
				break;
			}
			}

			if (type==3 && !video && cBox[23].isSelected()) 
				return options; // must start with video  

			if (30000L*pmtcount <= options[41]) {
				buf.write(tf.getPat());
				if (cBox[41].isSelected()) 
					buf.write(tf.getAutoPmt());
				else 
					buf.write(tf.getPmt());
				pmtcount++;
			}

			if (pcr && cBox[41].isSelected() && cBox[42].isSelected()) {
				buf.write(tf.getTTX(ttc,data,calctime.format(new java.util.Date((pcrbase+options[57])/90))));
			}

			if (pcr && cBox[36].isSelected()) {
				if (!cBox[46].isSelected()) 
					buf.write(tf.getPCR(pcrbase,counter[countID],(0xFF&newID))); // no payload==no counter++
				else 
					buf.write(tf.getPCR(pcrbase,++counter[countID],(0xFF&newID)));
			}

			int a=0;
			while (a<datalength) {
				if (a==0) {
					if (datalength-a < 183) {
						TSHead[3] = (byte)(0x30 | (0xF&++counter[countID]));
						int stuff = 182-(datalength-a);
						adapt[0] = (byte)(stuff+1);
						buf.write(TSHead); 
						buf.write(adapt); 
						buf.write(fills,6,stuff);
						buf.write(data,a,datalength-a); 
						a+=(datalength-a);
					} else if (datalength-a == 184) {
						TSHead[3] = (byte)(0x10 | (0xF&++counter[countID]));
						buf.write(TSHead); 
						buf.write(data,a,184); 
						a+=184;
					} else if (datalength-a < 185) {
						TSHead[3] = (byte)(0x30 | (0xF&++counter[countID]));
						adapt[0] = 1;
						buf.write(TSHead); 
						buf.write(adapt); 
						buf.write(data,a,182); 
						a+=182;
					} else {
						TSHead[3] = (byte)(0x10 | (0xF&++counter[countID]));
						buf.write(TSHead); 
						buf.write(data,a,184); 
						a+=184;
					}
				} else if (datalength-a < 183) {
					TSHead2[3] = (byte)(0x30 | (0xF&++counter[countID]));
					int stuff = 182-(datalength-a);
					adapt[0] = (byte)(stuff+1);
					buf.write(TSHead2); 
					buf.write(adapt); 
					buf.write(fills,6,stuff);
					buf.write(data,a,datalength-a); 
					a+=(datalength-a);
				} else if (datalength-a == 184) {
					TSHead2[3] = (byte)(0x10 | (0xF&++counter[countID]));
					buf.write(TSHead2); 
					buf.write(data,a,184); 
					a+=184;
				} else if (datalength-a < 185) {
					TSHead2[3] = (byte)(0x30 | (0xF&++counter[countID]));
					adapt[0] = 1;
					buf.write(TSHead2); 
					buf.write(adapt); 
					buf.write(data,a,182); 
					a+=182;
				} else {
					TSHead2[3] = (byte)(0x10 | (0xF&++counter[countID]));
					buf.write(TSHead2); 
					buf.write(data,a,184); 
					a+=184;
				}
				options[39]+=188; 
				options[41]+=188;
			}
			buf.writeTo(out);
			buf.reset();
		}
		}
		catch (IOException e) { 
			Msg("writeTS error4"+e); 
		}
		return options;
	}

--------------------------------------------------------------------------------
- 27.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@change: picture pre-scaling modified

@MPVD.java
@inner class Picture

(1) add/move variables
(2) replace 4 methods


[code]
private Graphics2D big;  //add
private BufferedImage Bimage; //already exists
private int pixels2[] = new int[256*192]; //moved

public void Decode_Picture(){
	if (picture_structure==FRAME_PICTURE && Second_Field>0)
		Second_Field = 0;

	if (picture_coding_type!=B_TYPE){
		pf_forward = pf_backward;
		pf_backward = pf_current;
	}

	Update_Picture_Buffers();
	picture_data();
	scale_Picture();
	repaint();

	if (picture_structure!=FRAME_PICTURE)
		Second_Field ^= Second_Field;
}

public void scale_Picture() {
	int nx=256, ny=192;
	float Y=0, X=0, Ydecimate = vertical_size/(float)ny, Xdecimate = horizontal_size/(float)nx;
	for (int y=0; Y<vertical_size && y<ny; Y+=Ydecimate,y++,X=0)
		for (int x=0; X<horizontal_size && x<nx; X+=Xdecimate,x++)
			pixels2[x+(y*nx)] = pixels[(int)X+((int)Y*horizontal_size)];

	Bimage.setRGB(0,0,nx,ny,pixels2,0,nx);
}

public void paint(Graphics g) {
	int x[] = { 10,10,30 };
	int y[] = { 198,218,208 };

	String INFO = ""+Coded_Picture_Width+"*"+Coded_Picture_Height+" "+picture_coding_type_string[picture_coding_type]+"("+temporal_reference+") "+progressive_string[progressive_frame]+" "+aspect_ratio_string[aspect_ratio_information]
			+" "+video_format_S[video_format]+" "+(1&profile_and_level_indication>>>7)+"|"+
			prof[7&profile_and_level_indication>>>4]+"@"+lev[15&profile_and_level_indication];

	big.clearRect(0,192,256,232);
	big.setColor(Color.white);
	big.drawString(INFO,36,205);
	big.drawString(TC,36,220);

	if (PLAY){
		big.setColor(Color.green);
		big.fillPolygon(x,y,3);
	}else{
		big.setColor(Color.red);
		big.fillRect(10,198,20,20);
	}
	if (ERROR1){
		big.setColor(Color.red);
		big.drawString("error while decoding frame",10,15);
	}
	if (ERROR2){
		big.setColor(Color.red);
		big.drawString("cannot find sequence header",10,30);
	}
	if (ERROR1 || ERROR2){
		big.drawLine(0,35,256,192);
		big.drawLine(256,35,0,192);
	}
	g.drawImage(Bimage, 0, 0, this);
}

public void run() {
	Bimage = new BufferedImage(256,232, BufferedImage.TYPE_INT_RGB);
	big = Bimage.createGraphics();
}

--------------------------------------------------------------------------------
- 18.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: array exception, caused by erroneous TS packets

bad packets will be dropped now
(nevertheless it will psb. crash on private_data (pesID==0x1BD))

@X.java
@internal class WORK
@method rawparse(), line ~5824

(1) replace code block

			counter = (0xf & push189[3]);								  // packet counter 0..f
			addlength = (addfield>1) ? (0xff & push189[4])+1 : 0;  // adaption field length
			
			//DM18092003+ fix
			progress.setValue((int)((count-base)*100/(size-base))+1);
			yield();
			
			// pid inclusion
			includeloop:
			while (include.length>0) {
				for (int v=0; v<include.length; v++)
					if (pid==include[v])
						break includeloop;
				continue pvaloop;
			}
			
			if ((addfield&1)==0)
				continue pvaloop;
			
			if (addlength>183 || (addlength>180 && start))
				error=true;
			
			if (error){
				Msg("--> PID 0x"+Integer.toHexString(pid).toUpperCase()+" -> TS bit error in packet "+packet+" @ pos. "+(count-188)+", dropping..");
				continue pvaloop;
			}
			
			// PES id, if packet start
			pesID = (start) ? ((255&push189[4+addlength])<<24 | (255&push189[5+addlength])<<16 |
					(255&push189[6+addlength])<<8 | (255&push189[7+addlength])) : 0;
			// PSI id, if packet start
			psiID = (start) ? pesID>>>16 : 0;
			
			ttx = false;
			if (pesID==0x1BD)
				ttx = ((0xFF&push189[12+addlength])==0x24 && (0xFF&push189[13+addlength+(0xFF&push189[12+addlength])])==0x10) ? true : false;
			//DM18092003-
			
			int pidcheck=-1;
			for (int a=0;a<TSPidlist.size();a++) {		// find PID object

--------------------------------------------------------------------------------
- 18.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: first PMT entry might not be read out correctly

@SCAN.java
@method PMTcheck(), line ~336

(1) change line

		pidsearch:
		for (int b=8, r=8; b<pmt.length-6; b++) { //DM18092003 fix
			r=b;

--------------------------------------------------------------------------------
- 13.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: wrong entry in RIFF header for subchunk2size (PCM datasize)

@MPAD.java
@method fillRIFF(), line ~1714

...
	riff.seek(40);
	riff.writeInt(littleEndian(len-36,4));  //data-size //DM13092003 fix
...

--------------------------------------------------------------------------------
- 13.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: array exception, caused by to small (psb. erroneous filtered) GOP arrays

@X.java
@method goptest(), line ~11078

public static void goptest(MyBufferedOutputStream vseq, byte[] gop, byte[] pts, DataOutputStream log, String dumpname) {

	//DM13092003+ fix
	if (gop.length<12){
		Msg(" GOP#"+(clv[6])+" - lack of data, ignored..");
		return;
	}
	//DM13092003-

	if (pts.length==0) {
	...

--------------------------------------------------------------------------------
- 12.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: chroma irritations on field encoded macroblocks

doubleclick onto preview area opens a dialog to save a 24bit bitmap of
last shown picture in original size (auto numbered)

@MPVD.java
@inner class Picture

(1) add new global variables to this inner class
line ~87

public class Picture extends JPanel implements Runnable {

private JFileChooser chooser;  //DM02092003
private int bmpCount=0; //DM02092003
...

--------------------------------------------------------------------------------

(2) add mouse Listener into method Picture
@method Picture(), ~line96

public Picture(){
	setBackground(Color.black);
	setVisible(true);
	chooser = new JFileChooser(); //<-EDIT03092003
	setToolTipText("doubleclick to save as bmp"); // <- VORSCHLAG 1 Tooltip!
	//DM02092003+
	addMouseListener(new MouseAdapter() {
		public void mouseClicked(MouseEvent e) {
			if (e.getClickCount() > 1)
				saveBMP();
		}
	});
	//DM02092003-
}

--------------------------------------------------------------------------------

(3) add new variable + 2 new methods to inner class Picture
line ~2518

//DM02092003+
private byte bmpHead[] = {
	0x42, 0x4D, //'B','M'
	0, 0, 0, 0, // real filesize 32bit, little endian (pixels.length*3 + header(0x36))
	0, 0, 0, 0,
	0x36, 0, 0, 0, //bitmap info size
	0x28, 0, 0, 0,
	0, 0, 0, 0, //hsize
	0, 0, 0, 0, //vsize
	1, 0,  //nplane
	0x18, 0, //bitcount 24b
	0, 0, 0, 0, //ncompr
	0, 0, 0, 0, //image bytesize
	(byte)0x88, 0xB, 0, 0, (byte)0x88, 0xE, 0, 0, //nxpm,nypm
	0, 0, 0, 0, 0, 0, 0, 0 //nclrused,nclrimp
};

public void littleEndian(byte[] array, int aPos, int value) {
	for (int a=0;a<4;a++)
		array[aPos+a] = (byte)(value>>(a*8) &0xFF);
}

public void saveBMP() {
	if (pixels.length==0)
		return;

	//VORSCHLAG 2(a)+ //12092003
	if (bmpCount==0){
		File dir= new File(X.outfield2.getText());
		if(dir.isDirectory() && X.comBox[13].getItemCount()>0)
			chooser.setCurrentDirectory(dir);
		else if (!X.list2.isSelectionEmpty())
			chooser.setCurrentDirectory(new File(X.list2.getSelectedValues()[0].toString()));
	}
	//VORSCHLAG 2(a)-

	String newfile = "X_pic_"+bmpCount+".bmp";
	chooser.setSelectedFile(new File(newfile));
	chooser.rescanCurrentDirectory();
	chooser.setDialogTitle("save picture");

	int retval = chooser.showSaveDialog(this);
	if(retval == JFileChooser.APPROVE_OPTION) {
		File theFile = chooser.getSelectedFile();
		if(theFile != null && !theFile.isDirectory()) {
			newfile = theFile.getAbsolutePath();
		}
	} else
		return;

	byte bmp24[] = new byte[3];
	littleEndian(bmpHead,2,(54+pixels.length*3));
	littleEndian(bmpHead,18,horizontal_size);
	littleEndian(bmpHead,22,vertical_size);
	littleEndian(bmpHead,34,(pixels.length*3));

	try{
	BufferedOutputStream BMPfile = new BufferedOutputStream(new FileOutputStream(newfile),2048000);
	BMPfile.write(bmpHead);
	for (int a=vertical_size-1; a>=0; a--)
		for (int b=0; b<horizontal_size; b++){
			for (int c=0; c<3; c++)
				bmp24[c] = (byte)(pixels[b+a*horizontal_size]>>(c*8) &0xFF);
			BMPfile.write(bmp24);
		}
	BMPfile.flush();
	BMPfile.close();
	bmpCount++;
	}catch (IOException e){ }
}
//DM02092003-

--------------------------------------------------------------------------------
- 06.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@fix: missing data on binary extraction from HexViewer

@HEXVIEWER.java
@method savefile(), line ~190

(1) replace method savefile()

//DM06092003+  changed
public void savefile(long startPos, long size) {
	long len = new File(file).length();
	size = (startPos+size>len) ? (len-startPos) : size;

	if (startPos>=len || startPos<0 || size<1)
		return;

	String newfile = file+"(0x"+Long.toHexString(startPos)+" to 0x"+Long.toHexString(startPos+size)+").bin";
	chooser.setSelectedFile(new File(newfile));
	chooser.rescanCurrentDirectory();

	int retval = chooser.showSaveDialog(this);
	if(retval == JFileChooser.APPROVE_OPTION) {
		File theFile = chooser.getSelectedFile();
		if(theFile != null && !theFile.isDirectory()) {
			newfile = theFile.getAbsolutePath();
		}
	} else
		return;

	try
	{
	int buf=3072000;
	BufferedInputStream hex = new BufferedInputStream(new FileInputStream(file),buf);
	BufferedOutputStream hex1 = new BufferedOutputStream(new FileOutputStream(newfile),buf);
	long filePos=0, endPos=startPos+size;

	while (filePos < startPos)
		filePos += hex.skip(startPos-filePos);

	byte data[];
	int datalen;
	while (filePos < endPos) {
		datalen = (endPos-filePos) < (long)buf ? (int)(endPos-filePos) : buf;
		data = new byte[datalen];
		datalen = hex.read(data);
		hex1.write(data,0,datalen);
		filePos += datalen;
	}
	hex.close();
	hex1.flush();
	hex1.close();
	}
	catch (IOException e) {
		HexArea.setText(".. cannot access file : "+file);
	}
}
//DM06092003-

--------------------------------------------------------------------------------
- 04.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@change: ignore bsid (AC3) when verifying frames

@X.java

(ac3data[5]!=frame[5]) change to ( (7&ac3data[5]) != (7&frame[5]) )

--------------------------------------------------------------------------------
- 02.09.2003 X0.81.5                                                  dvb.matt -
--------------------------------------------------------------------------------

@enhancement: preview also supports color formats 4:2:2/4:4:4 (high profiles)

@MPVD.java
@inner class Picture

(1) replace method Add_Block()
~line2070

//DM02092003+ changed
public void Add_Block(int comp, int bx, int by, int dct_type[], boolean addflag){

	int cc, iincr;
	int rfp;
	short Block_Ptr[] = block[comp];

	/* derive color component index */
	cc = cc_table[comp];

	if (cc==0){
		if (picture_structure==FRAME_PICTURE){	//progressive
			if (dct_type[0]>0){
				rfp = current_frame[0] + Coded_Picture_Width*(by+((comp&2)>>1)) + bx + ((comp&1)<<3);
				iincr = (Coded_Picture_Width<<1) - 8;
			}else{
				rfp = current_frame[0] + Coded_Picture_Width*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
				iincr = Coded_Picture_Width - 8;
			}
		}else{
			rfp = current_frame[0] + (Coded_Picture_Width<<1)*(by+((comp&2)<<2)) + bx + ((comp&1)<<3);
			iincr = (Coded_Picture_Width<<1) - 8;
		}
	}else{
		// chrominance
		// scale coordinates
		if (chroma_format!=CHROMA444) bx >>= 1;
		//if (chroma_format==CHROMA420) by >>= 1; // disabled

		if (picture_structure==FRAME_PICTURE){  //progressive
			if (dct_type[0]>0 && chroma_format!=CHROMA420){
				// field DCT coding
				rfp = current_frame[cc] + Chroma_Width*(by+((comp&2)>>1)) + bx + (comp&8);
				iincr = (Chroma_Width<<1) - 8;
			}else{
				// frame DCT coding
				rfp = current_frame[cc] + Chroma_Width*(by+((comp&2)<<2)) + bx + (comp&8);
				iincr = Chroma_Width - 8;
			}
		}else{
			// field picture
			rfp = current_frame[cc] + (Chroma_Width<<1)*(by+((comp&2)<<2)) + bx + (comp&8);
			iincr = (Chroma_Width<<1) - 8;
		}
	}
	iincr += 8;

	int val,luma,pPos, r,g,b;
	if (cc==0){	//lumi
		for (int y=0;y<8;y++)
			for (int x=0;x<8;x++){
				val = Block_Ptr[x+(y*8)]+((picture_coding_type==I_TYPE)?128:0);
				val = val<0 ? 0 : (val>255 ? 255 : val);
				pixels[rfp+x+(y*iincr)] += val<<16 | val<<8 | val;
			}
	}else{	 //chroma cc1 = Cb, cc2=Cr
		if (chroma_format!=CHROMA444){
			rfp<<=1;
			iincr<<=1;
		}
		for (int y=0; y<16; y++){
			for (int x=0; x<16; x++){
				val = Block_Ptr[(x>>1) + (8*(chroma_format!=CHROMA420?(y>>1):((y&1)==0?((y>>1)&~dct_type[0]):((y>>1)|dct_type[0]))))]; //DM12092003
				pPos = rfp+(x>>(chroma_format==CHROMA444?1:0))+((y>>(chroma_format!=CHROMA420?1:0)) *iincr);
				luma = pixels[pPos];
				if (cc==1){
					r = (0xFF&luma>>>16);
					g = (int)((double)(0xFF&luma>>>8) -0.34414*val);
					b = (int)((double)(0xFF&luma) +1.722*val);
					g = g<0 ? 0 : (g>255 ? 255 : g);
					b = b<0 ? 0 : (b>255 ? 255 : b);
				}else{
					r = (int)((double)(0xFF&luma>>>16) +1.402*val);
					g = (int)((double)(0xFF&luma>>>8) -0.71414*val);
					b = (0xFF&luma);
					r = r<0 ? 0 : (r>255 ? 255 : r);
					g = g<0 ? 0 : (g>255 ? 255 : g);
				}
				pixels[pPos] = r<<16|g<<8|b;
				if (chroma_format==CHROMA444)
					x++;
			}
			if (chroma_format!=CHROMA420)
				y++;
		}
	}
}
//DM02092003-

--------------------------------------------------------------------------------
- 29.08.2003 X0.81.4 (Fix)                                            dvb.matt -
--------------------------------------------------------------------------------

@fix: bad/incomplete/short slices may cause black preview pictures and for every following picture
(re-start necessary)

@MPVD.java
@inner class Picture
@method slice(), line ~1437
(change return value: 0 to -1)


	for (;;){
	...
		if (MBAinc[0]==1) { /* not skipped */
			if (decode_macroblock(macroblock_type, motion_type, dct_type, PMV,
				dc_dct_pred, motion_vertical_field_select, dmvector)<1) {
					Fault_Flag = 0;
					return -1; // return 0;   // trigger: go to next slice
			}
		}else{ /* MBAinc[0]!=1: skipped macroblock */
			skipped_macroblock(dc_dct_pred, PMV, motion_type,
					motion_vertical_field_select, macroblock_type);
		}
	...
	}

--------------------------------------------------------------------------------
- 26.08.2003 X0.81.3 (enhancement)                                    TheHorse -
--------------------------------------------------------------------------------

Preview slider move & cut keyboard keys:

[cursor left/right]: move one I-frame in preview (standard)
[shift + cursor]   : move with speed index 1 (1/10 from >>/<<)
[strg + cursor]    : move with speed index 2 (equal to >>/<<)
[alt + cursor]     : move with speed index 3 (10x >>/<<)
[page_up/page_down]: move with speed index 4 (standard)
[pos1/home]        : move to start of movie (standard)
[end]              : move to end of movie (standard)

[a]: add point
[d]: del point
[n]: next cutpoint
[p]: previous cutpoint

Note: Slider must be activated (klick on it) for keyboard keys.
      [n] and [p] keys cutpoints are current slider position.

Hint: [alt] key switch to intern Mnemonic-(Key-Accelerator) mode.
      By pressing [alt] alone the other keys are locked.
      To unlock the keys press [alt] again.

X.java
internal class COLLECTION line ~2339

KeyListener S_keyListener = new KeyAdapter() {
	public void keyPressed(KeyEvent e) {
		int i=0;
		int ic=0;
		int offs=0;
		int keyval=e.getKeyCode();
		switch(e.getKeyChar()) {
			case 'p':
				ic=comBox[14].getItemCount();
				if (ic>0) {
					i=ic-1;
					if(lastpos>Long.parseLong(comBox[14].getItemAt(0).toString())) {
						while(lastpos<=Long.parseLong(comBox[14].getItemAt(i).toString()))
							i--;
					}
					comBox[14].setSelectedIndex(i);
				}
				return;
			case 'n':
				ic=comBox[14].getItemCount();
				if (ic>0) {
					if(lastpos<Long.parseLong(comBox[14].getItemAt(ic-1).toString())) {
						while(lastpos>=Long.parseLong(comBox[14].getItemAt(i).toString()))
							i++;
					}
					comBox[14].setSelectedIndex(i);
				}
				return;
			case 'a':
				cutadd.doClick();
				return;
			case 'd':
				cutdel.doClick();
				return;
		}
		if (e.isShiftDown())
			offs=62500;
		else if (e.isControlDown())
			offs=312500;
		else if (e.isAltDown())
			offs=3125000;
		else
			return;
		switch (keyval) {
			case KeyEvent.VK_RIGHT:
				search.setValue(search.getValue()+offs);
				break;
			case KeyEvent.VK_LEFT:
				search.setValue(search.getValue()-offs);
		}
	}
};
search.addKeyListener(S_keyListener);

--------------------------------------------------------------------------------
- 24.08.2003 X0.81.2 (enhancement)                                    dvb.matt -
--------------------------------------------------------------------------------

show expected export filesize in cut dialog
   restrictions:
      - byte pos. cut only
      - secondary streams, ignored IDs/PIDs and streamtype (PES<->ES) may cause different sizes as expected

X.java
internal class COLLECTION
(a)subclass CutListener, method actionPerformed(), line ~2414
(b)method entry(), line ~2750
(c)method loadlist(), line ~2874


change a,b,c to:

getExpectedSize(); //DM24082003 //pointscount.setText(""+comBox[14].getItemCount());


(d)add method getExpectedSize() to this inner class, e.g. line ~2880

//DM24082003+
public void getExpectedSize() {
	//DM24082003+ add fix 081.2a
	if (previewList.size()==0){
		pointscount.setText(""+comBox[14].getItemCount());
		return;
	}
	//DM24082003-
	long newSize[] = new long[comBox[14].getItemCount()];
	long start=0, diff=0, end;
	for (int a=0; a<newSize.length; a++)
		newSize[a] = Long.parseLong(comBox[14].getItemAt(a).toString());
	if (newSize.length==0 || (newSize.length&1)==1)
		end = ((long[]) (( (Object[])previewList.get(previewList.size()-1) )[1]) )[1];
	else
		end = newSize[newSize.length-1];

	for (int a=0; a<newSize.length; a+=2){
		diff += newSize[a]-start;
		start = a+1<newSize.length ? newSize[a+1] : start;
	}
	String length = comBox[17].getSelectedIndex()==0 ? (" / exp.Size: "+((end-diff)/1048576L)+"MB") : "";
	pointscount.setText(""+comBox[14].getItemCount() + length);
}
//DM24082003-

--------------------------------------------------------------------------------
- 16.08.2003 X0.81.1 (Fix 1)                                          dvb.matt -
--------------------------------------------------------------------------------

@fix:
# extendend look-up for usable data in unscrambled marked TS-packets (bad flags in recordings)
# to enable:
- you have to fill the PID list manually with the wanted (but still ignored) PID numbers
# each 'bad' start_packet will be logged

deu:
# manche TS Dateien enthalten wohl verschlsselte Daten obwohl diese als nicht-verschlsselt gekennzeichnet sind.
# bei manueller bernahme der ignorierten PIDs in die PID Liste wird hiermit nun nicht 'abgebrochen' sondern weiterhin nach einem offenen Startcode gesucht.


@X.java
@internal class: WORK
@method: rawparse(), line: ~5939

Code:

	...
	type+=" (0x"+Long.toHexString(count-188).toUpperCase()+" #"+packet+") ";  //pos + packno
	Msg("--> PID 0x"+Integer.toHexString(pid).toUpperCase()+" "+type+" -> ignored");
	//DM16082003+ fix 081.1  //*** replacement
	if (abc.size()==0 || type.indexOf("pay")==-1)
		TSPid.setneeded(false);
	else
		TSPid.setID(-1);
	//DM16082003-
	continue pvaloop;
	...

--------------------------------------------------------------------------------
- 15.08.2003 X081 release                                             dvb.matt -
--------------------------------------------------------------------------------

minor changes in descriptions of buttons etc.
all known fixes (1-5) and extensions (made by java.lang) are implemented
.idd export function now available for all input videotypes

--------------------------------------------------------------------------------
- 14.08.2003                                               extension java.lang -
--------------------------------------------------------------------------------

patch horizontal resolution of the 1st sequence header:
conditional patching added, you can now specify:

  -never,
  -ever ,
  -if <> 720 or 352
  -if <> 720 or 704 or 352

this feature is useful if you're using dvd-authoring progs like TMPGEncDVDAuthor.

--------------------------------------------------------------------------------
- 06.08.2003                                               extension java.lang -
--------------------------------------------------------------------------------

Modififications are done to export a file readable by the program
Mpeg2Schnitt@Martin Dienert (prog version 0.5, idd-format version 2).
These modifications are are surrounded by inline comments i.E. JLA+ JLA-.
Short usage: select checkbox "Mpeg2Schnitt" in the d2v pane if you want an *.idd file.
known restrictions:

  - file splitting/cutting not implemented yet
  - only a few tests are done
  - works only in demux mode (rawparse)

--------------------------------------------------------------------------------
- ??.08.2003                                             Suggestion / notFix 5 -
--------------------------------------------------------------------------------

@X.java
@method logAlias(), line ~11477

@suggestion: message log if the following nonVideo stream cannot handled by its own PTS data (because it's missing)

	...
	log.close();
	Msg("--> using faked PTS in following data"); // *** add
	}
	...

--------------------------------------------------------------------------------
- 23.07.2003                                                             Fix 4 -
--------------------------------------------------------------------------------

@AUDIO.java
@class: AUDIO
@method: ---, line: ~302

@fix: exception while parsing bad/wrong AC3-frames (bad index)

	int ac3_bitrate_index[] =  {
	...
	320000,384000,448000,512000,576000,640000,
	// 0,0 // *** change to:
	0,0,0,0,0,0,0,0,0,0,0,0,0  // *** new; arraysize should be 0x20
	};

--------------------------------------------------------------------------------
- 29.07.2003                                                            Fix 3a -
--------------------------------------------------------------------------------

@MPVD.java
@internal class: Picture
@method: Add_Block(), line: ~2133, ~2145

@fix: remove a little bit more cross coloured speckles in preview

	if (cc==1){
	...
	g = g<0 ? 0 : (g>255 ? 255 : g); // replacement of  g = (g<0) ? 0 : (0xFF&g);
	b = b<0 ? 0 : (b>255 ? 255 : b); // replacement of  b = (b<0) ? 0 : (0xFF&b);
	...
	}else if (cc==2){
	...
	r = r<0 ? 0 : (r>255 ? 255 : r); // replacement of  r = (r<0) ? 0 : (0xFF&r);
	g = g<0 ? 0 : (g>255 ? 255 : g); // replacement of  g = (g<0) ? 0 : (0xFF&g);
	...
	}

--------------------------------------------------------------------------------
- 20.07.2003                                                             Fix 3 -
--------------------------------------------------------------------------------

@MPVD.java
@internal class: Picture
@method: Add_Block(), line: ~2125++

@fix: remove cross coloured speckles in preview

	if (cc==1){
	for (int y=0;y<16;y++)
	for (int x=0;x<16;x++){
	val = chroma[x+(y*16)];
	luma = pixels[(bx<<1)+x+(((by<<1)+y)*horizontal_size)];
	r = (0xFF&luma>>>16);
	// g = (0xFF&luma>>>8); //*** removed
	// b = (0xFF&luma); // *** removed
	g = (int)((double)(0xFF&luma>>>8) -0.34414*val); // *** changed
	b = (int)((double)(0xFF&luma) +1.722*val); // *** changed
	g = (g<0) ? 0 : (0xFF&g); // *** added
	b = (b<0) ? 0 : (0xFF&b); // *** added
	pixels[(bx<<1)+x+(((by<<1)+y)*horizontal_size)] = r<<16|g<<8|b;
	}
	}else if (cc==2){
	for (int y=0;y<16;y++)
	for (int x=0;x<16;x++){
	val = chroma[x+(y*16)];
	luma = pixels[(bx<<1)+x+(((by<<1)+y)*horizontal_size)];
	b = (0xFF&luma);
	// r = (0xFF&luma>>>16); // *** removed
	// g = (0xFF&luma>>>8); // *** removed
	r = (int)((double)(0xFF&luma>>>16) +1.402*val); // *** changed
	g = (int)((double)(0xFF&luma>>>8) -0.71414*val); // *** changed
	r = (r<0) ? 0 : (0xFF&r); // *** added
	g = (g<0) ? 0 : (0xFF&g); // *** added
	pixels[(bx<<1)+x+(((by<<1)+y)*horizontal_size)] = r<<16|g<<8|b;
	}
	}

--------------------------------------------------------------------------------
- 19.07.2003                                                             Fix 2 -
--------------------------------------------------------------------------------

@X.java
@internal class: WORK
@method: vdrparse(), line: ~5014
@method: rawparse(), line: ~5616
@method: pvaparse(), line: ~6445

@fix: enabled cut- and split- pointer didn't work properly in case of more than 2 inputfiles

	if (startPoint < 0)
	...
	else if (startPoint < count){
	...
	}
	else if (startPoint > count){
	// for (int a=1; a < starts.length; a++){   *** old
	for (int a=FileNumber+1; a < starts.length; a++){  // *** new
	if (starts[a] > startPoint)
	break;
	else
	FileNumber++;
	}
	}

--------------------------------------------------------------------------------
- 19.07.2003                                                             Fix 1 -
--------------------------------------------------------------------------------

@X.java
@internal class: PREVIEW
@method: load(), line: ~2146

@fix: preview didn't jump properly among fileborders in case of more than 2 inputfiles

	for (int a=0;a<previewList.size();a++){
	...
	if (startposition < end){
	...
	if (end-startposition < size && a<previewList.size()-1){
	...
	// }else  *** old
	} // *** new
	break;
	}
	}

--------------------------------------------------------------------------------

0.80  12.07.2003
# collection specials
 + GUI re-arranged, preview scaled to 256*192
 + load/save external file for cutpoints
# Fix byteposition cut:
 + did not jump effective just to the file before the first cut-in, in case of more than 2 inputfiles
# coming: estimated play time
 + ATM: shows only time of ES MPA/AC3
# preview:
 + in addition to the slider: backward/forward knobs
# now shows the progress percentage in frametitle / taskbar
# new CL-option:
 + load cutpoint list in textform: "-p <file:pointlist>" , interpreted as choosen in the cut type menu (collection specials, p17)

-----------

# Fix TS:
 + stuffing packets (Pid 0x1FFF) will be ignored
 + PMT quickinfo in filemenu: shows the Pids, def. as user private data (0x80..) e.g. AC3 bei NBC(HDTV)
# preview:
 + search for sequenceheader in 2,5MB
 + info while processing/ if error
# ac3.bin
 + silent AC3 2/0 DS 384kbps frame added
# AC3
 + now supports lower bitrates (32..80kbps)
 + extended Loginfos

----------

# collection specials:
 + no more extra pre-skipping (use first cut-in point of "use bytepos. for cuts" instead)
 + global: create a subdirectory for each collection for output files
 + fix preview: NTSC (and other Resol.) should work, (MPEG1 has no Preview)
 + preview + bytepos.-cut works for multiple infiles of the same type (VDR,PVA,MPEG2PS,TS)
# no limitations at output-split, multiple infiles and overlap-output
# mpa decoder:
 + output motorola byte order
 + disable RIFF headers (-> raw PCM, do not have the 2/4GB limitation)
 + downmix to mono
 + split stereo: set in the "conversion" menu
 + amplify by factor

-----------

# collection specials:
 + open with doubleclick (l/r)
# new: preview (i-frame) window for mpeg2 types (PVA,VDR,MPEG2-PS/ES,TS)  (colortype MPEG4:2:0)
 + due to performance, simple scaled to QCIF-resol.
 + "ins" removed -> automatic sort if adding
 + demux only: cut using byteposition (gop aligned) (PVA,VDR,MPEG12,TS)
 + define points with slider or cursors (gop-aligned), "add" oder "del" a point
 + jump to point, if a point is selected from pointlist
 + symbols:   (same info for frame-/gop-number cut)
  * export gop: green arrow
  * ignore gop: red square
# MPA decoder:
 + now supports MPEG-2.5 layer1,2 (emphasis bit1 detection)
 + resample 48khz to 44.1 or 32khz (linear interpolation)

------------

# collection specials:
 + context menu (specialsmenu,sendto,add,remove)
# TTX:
 + UT-SUP Hint: do not use odd Pointsizes (bad entry in RLE-Interlace)
# cut hint:
 + first video cut-in shall not be placed to far from start, if used "PES-Video" with "ES-Audio"
# Fix: patch to interlace/progressive Exception
# neu: video2:
 + add Sequenceheader to GOPs without
 + GOP-Graph: if a Sequenceheaders exists: a yellow rectangle is shown left to the first cyan I-Frame
# TTX:
 + 2nd SUP Yoffset per job (alternate UT (e.g. special zoom position)
 + example: one UT-File ("24;8;32;110;520;720;576;-1") , two UT-Files ("24;8;32;110;520;720;576;96")  -> Y 96
# TTX:
 + Paritycheck (if failed, replaced by "graphic black"/ space),
# new:
 + (demux) limit Video-Export to special H-Resolutions
 + cut-Settings re-arranged in "coll. specials" dialog
# CellTimes.txt:
 + entry also for cut-in points
# Audio:
 + decode MPEG1+2 Layer1+2 to WAV (std is stereo-pcm output)
# Audio:
 + "discard every xxx frame",

------------

# PVA:
 + Fix: crash on process start
 + check for discontinuity in PVA-packs
# TS:
 + shows "useful" PIDs with leading "ok>"
 + pressing "i" fills the pidlist with the useful Pids, if it wasn't empty.
# VDR/MPG:
 + search area f. VideoPES(packsize0) increased
# TTX:
 + change chars f. country-code2:  '','' zu '','' (nordisch Ling.., not verified..)
 + decode up to 6 pages per Streamfile and job
 + Fix: if ttx StartPTS arrive later as first VideoPTS, no page were decoded
 + UT-SUP: empty lines will not exported
# GUI - bitrate monitor:
 + GOPs with more than 15, instead of "..." now a red "Overflow" is set.
# new: PVA/VDR/MPG/TS:
 + create CellTimes.txt entry on multiple Inputfiles ( Clips)
  (except: "concatenate diff. recs. " is OFF in case of VDR/PVA )
# GUI:
 + new: support Drag&Drop, D&D move+copy ( <-  Filenamelist)
 + drop Files into "main" Coll.-area or on all tabs rider
 + D&D-Copymode (hold Ctrl) creates a new coll. for each selected file as with "+<"
# Hint:
 + d2v file may not suit with NTSC sources
