1 /*
2  * @(#)StreamDemultiplexer
3  *
4  * Copyright (c) 2005-2009 by dvb.matt, All Rights Reserved.
5  *
6  * This file is part of ProjectX, a free Java based demux utility.
7  * By the authors, ProjectX is intended for educational purposes only,
8  * as a non-commercial test project.
9  *
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  *
25  */
26 
27 package net.sourceforge.dvb.projectx.parser;
28 
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 import java.io.File;
33 import java.io.ByteArrayOutputStream;
34 import java.io.DataOutputStream;
35 import java.io.BufferedOutputStream;
36 import java.io.FileOutputStream;
37 import java.io.IOException;
38 import java.io.BufferedWriter;
39 import java.io.FileWriter;
40 
41 import net.sourceforge.dvb.projectx.io.IDDBufferedOutputStream;
42 
43 import net.sourceforge.dvb.projectx.common.Resource;
44 import net.sourceforge.dvb.projectx.common.Keys;
45 import net.sourceforge.dvb.projectx.common.Common;
46 import net.sourceforge.dvb.projectx.common.JobProcessing;
47 import net.sourceforge.dvb.projectx.common.JobCollection;
48 
49 import net.sourceforge.dvb.projectx.parser.CommonParsing;
50 import net.sourceforge.dvb.projectx.video.Video;
51 
52 /**
53  * demuxes all packetized data
54  */
55 public class StreamDemultiplexer extends Object {
56 
57 	private boolean ptsover = false;
58 	private boolean misshead = false;
59 	private boolean first = true;
60 	private boolean overlap = false;
61 	private boolean seqhead = false;
62 	private boolean isPTSwritten = false;
63 	private boolean isEnabled = true;
64 //
65     private boolean isH264 = false;
66 
67 	private boolean WriteNonVideo;
68 	private boolean WriteVideo;
69 	private boolean Debug;
70 	private boolean DecodeVBI;
71 	private boolean RebuildPTS;
72 	private boolean RebuildPictPTS;
73 	private boolean Streamtype_MpgVideo;
74 	private boolean Streamtype_MpgAudio;
75 	private boolean Streamtype_Ac3Audio;
76 	private boolean Streamtype_PcmAudio;
77 	private boolean Streamtype_Teletext;
78 	private boolean Streamtype_Subpicture;
79 	private boolean AddSequenceEndcode;
80 	private boolean RenameVideo;
81 	private boolean CreateD2vIndex;
82 	private boolean CreateM2sIndex;
83 	private boolean SplitProjectFile;
84 	private boolean CreateCellTimes;
85     private boolean CreateInfoIndex;
86     private boolean AppendPidToFileName;
87     private boolean AppendLangToFileName;
88     private boolean EnableHDDemux;
89 
90 	private long AddOffset = 0;
91 	private long target_position = 0;
92 	private long ptsoffset = 0;
93 	private long pts = -1;
94 	private long lastPTS = -1;
95 
96 	private int pack = -1;
97 	private int pes_ID = 0;
98 	private int newID = 0;
99 	private int PID = 0;
100 	private int es_streamtype = 0;
101 	private int subid = 0x1FF;
102 	private int pes_streamtype = 0;
103 	private int lfn = -1;
104 	private int buffersize = 1024;
105 	private int sourcetype = 0;
106 	private int[] MPGVideotype = { -1 }; // 0 =m1v, 1 = m2v, 2 = h264  -- changed at goptest
107 
108 	private int StreamNumber = -1;
109 
110 	private String FileName = "";
111 	private String parentname = "";
112 	private String[] type = { "ac", "tt", "mp", "mv", "pc", "sp", "vp" };
113 	private String[] source = { ".$spes$", ".$ppes$", ".$ts$", ".$pva$" };
114 //	private String[] videoext = { ".mpv", ".mpv", ".m1v", ".m2v" };
115 	private String[] videoext = { ".mpv", ".mpv", ".264", ".m1v", ".m2v", ".264" };
116 
117 	private IDDBufferedOutputStream out;
118 	private DataOutputStream pts_log;
119 	private ByteArrayOutputStream vidbuf;
120 	private ByteArrayOutputStream vptsbytes;
121 	private ByteArrayOutputStream packet;
122 	private DataOutputStream vpts;
123 
124 	private byte[] subpicture_header = { 0x53, 0x50, 0, 0, 0, 0, 0, 0, 0, 0 };
125 	private byte[] lpcm_header = { 0x50, 0x43, 0x4D, 0, 0, 0, 0, 0, 0, 0 }; //'PCM'+5b(pts)+2b(size)
126 
127 	/**
128 	 *
129 	 */
StreamDemultiplexer(JobCollection collection)130 	public StreamDemultiplexer(JobCollection collection)
131 	{
132 		getSettings(collection);
133 	}
134 
135 	/**
136 	 *
137 	 */
StreamDemultiplexer(JobCollection collection, long val)138 	public StreamDemultiplexer(JobCollection collection, long val)
139 	{
140 		getSettings(collection);
141 		ptsoffset = val;
142 	}
143 
144 	/**
145 	 * Object yet intialized
146 	 */
getNum()147 	public int getNum()
148 	{
149 		return lfn;
150 	}
151 
152 	/**
153 	 * get PID for later selection
154 	 */
getPID()155 	public int getPID()
156 	{
157 		return PID;
158 	}
159 
160 	/**
161 	 * returns PES pes_ID for later selection
162 	 */
getID()163 	public int getID()
164 	{
165 		return pes_ID;
166 	}
167 
168 	/**
169 	 * set PID for later selection
170 	 */
setPID(int val)171 	public void setPID(int val)
172 	{
173 		PID = val;
174 	}
175 
176 	/**
177 	 * set pes_ID for later selection
178 	 */
setID(int val)179 	public void setID(int val)
180 	{
181 		pes_ID = val;
182 	}
183 
184 	/**
185 	 * set newID for later selection /or subid
186 	 */
setnewID(int val)187 	public void setnewID(int val)
188 	{
189 		newID = val;
190 	}
191 
192 	/**
193 	 * returns newID for later selection /or subid
194 	 */
getnewID()195 	public int getnewID()
196 	{
197 		return newID;
198 	}
199 
200 	/**
201 	 * returns packet counter
202 	 */
getPackCount()203 	public int getPackCount()
204 	{
205 		return pack;
206 	}
207 
208 	/**
209 	 * returns es_streamtype
210 	 */
getType()211 	public int getType()
212 	{
213 		return es_streamtype;
214 	}
215 
216 	/**
217 	 * sets stream tpye, vdr/es/mpeg1/2...
218 	 */
setStreamType(int val)219 	public void setStreamType(int val)
220 	{
221 		pes_streamtype = val;
222 	}
223 
224 	/**
225 	 * returns stream tpye, vdr/es/mpeg1/2...
226 	 */
getStreamType()227 	public int getStreamType()
228 	{
229 		return pes_streamtype;
230 	}
231 
232 	/**
233 	 * sets type
234 	 */
setType(int val)235 	public void setType(int val)
236 	{
237 		es_streamtype = val;
238 	}
239 
240 	/**
241 	 * sets subid
242 	 */
setsubID(int val)243 	public void setsubID(int val)
244 	{
245 		subid = val;
246 	}
247 
248 	/**
249 	 * returns subid
250 	 */
subID()251 	public int subID()
252 	{
253 		return subid;
254 	}
255 
256 	/**
257 	 * is it TTX?
258 	 */
isTTX()259 	public boolean isTTX()
260 	{
261 		return es_streamtype == CommonParsing.TELETEXT;
262 	}
263 
264 	/**
265 	 * set ttx
266 	 */
setTTX(boolean b)267 	public void setTTX(boolean b)
268 	{
269 		if (b)
270 			es_streamtype = CommonParsing.TELETEXT;
271 	}
272 
273 	/**
274 	 * last PTS
275 	 */
getPTS()276 	public long getPTS()
277 	{
278 		return pts;
279 	}
280 
281 	/**
282 	 * PTS offset if needed
283 	 */
PTSOffset(long val)284 	public void PTSOffset(long val)
285 	{
286 		ptsoffset = val;
287 	}
288 
289 	/**
290 	 *
291 	 */
setStreamNumber(int val)292 	public void setStreamNumber(int val)
293 	{
294 		StreamNumber = val;
295 	}
296 
297 	/**
298 	 *
299 	 */
getStreamNumber()300 	public int getStreamNumber()
301 	{
302 		return StreamNumber;
303 	}
304 
305 	/**
306 	 * stream type preselector
307 	 */
setStreamEnabled(boolean b)308 	public void setStreamEnabled(boolean b)
309 	{
310 		isEnabled = b;
311 	}
312 
313 	/**
314 	 * stream type preselector
315 	 */
StreamEnabled()316 	public boolean StreamEnabled()
317 	{
318 		switch(newID>>>4)
319 		{
320 		case 0xE:  //video
321 			return Streamtype_MpgVideo;
322 
323 		case 0xC:  //mpa
324 		case 0xD:
325 			return Streamtype_MpgAudio;
326 
327 		case 0x8:  //ac3,mpg
328 			return Streamtype_Ac3Audio;
329 
330 		case 0xA:  //lpcm,mpg
331 			return Streamtype_PcmAudio;
332 
333 		case 0x9:  //ttx
334 			return Streamtype_Teletext;
335 
336 		case 0x2:  //subpic
337 		case 0x3:
338 			return Streamtype_Subpicture;
339 
340 		default:
341 			return isEnabled;
342 		}
343 	}
344 
345 
346 	/**
347 	 *
348 	 */
getSettings(JobCollection collection)349 	private void getSettings(JobCollection collection)
350 	{
351 		Streamtype_MpgVideo = collection.getSettings().getBooleanProperty(Keys.KEY_Streamtype_MpgVideo);
352 		Streamtype_MpgAudio = collection.getSettings().getBooleanProperty(Keys.KEY_Streamtype_MpgAudio);
353 		Streamtype_Ac3Audio = collection.getSettings().getBooleanProperty(Keys.KEY_Streamtype_Ac3Audio);
354 		Streamtype_PcmAudio = collection.getSettings().getBooleanProperty(Keys.KEY_Streamtype_PcmAudio);
355 		Streamtype_Teletext = collection.getSettings().getBooleanProperty(Keys.KEY_Streamtype_Teletext);
356 		Streamtype_Subpicture = collection.getSettings().getBooleanProperty(Keys.KEY_Streamtype_Subpicture);
357 		AddOffset = collection.getSettings().getBooleanProperty(Keys.KEY_additionalOffset) ? 90L * collection.getSettings().getIntProperty(Keys.KEY_ExportPanel_additionalOffset_Value) : 0;    // time offset for data
358 		WriteNonVideo = collection.getSettings().getBooleanProperty(Keys.KEY_WriteOptions_writeAudio);
359 		WriteVideo = collection.getSettings().getBooleanProperty(Keys.KEY_WriteOptions_writeVideo);
360 		Debug = collection.getSettings().getBooleanProperty(Keys.KEY_DebugLog);
361 		DecodeVBI = collection.getSettings().getBooleanProperty(Keys.KEY_Streamtype_Vbi);
362 		RebuildPTS = collection.getSettings().getBooleanProperty(Keys.KEY_SubtitlePanel_rebuildPTS);
363 		RebuildPictPTS = collection.getSettings().getBooleanProperty(Keys.KEY_SubtitlePanel_rebuildPictPTS);
364 		AddSequenceEndcode = collection.getSettings().getBooleanProperty(Keys.KEY_VideoPanel_addEndcode);
365 		RenameVideo = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_renameVideo);
366 		CreateD2vIndex = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_createD2vIndex);
367 		CreateM2sIndex = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_createM2sIndex);
368 		SplitProjectFile = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_splitProjectFile);
369 		CreateCellTimes = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_createCellTimes);
370         CreateInfoIndex = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_createInfoIndex);
371         AppendPidToFileName = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_appendPidToFileName);
372         AppendLangToFileName = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_appendLangToFileName);
373         EnableHDDemux = collection.getSettings().getBooleanProperty(Keys.KEY_enableHDDemux);
374 	}
375 
376 	/**
377 	 *
378 	 */
setFileName()379 	private void setFileName()
380 	{
381 		FileName = parentname + source[sourcetype] + lfn + "-" + Long.toHexString(0xFFFFFFL & System.currentTimeMillis()).toUpperCase();
382 	}
383 
384 	/**
385 	 * init nonVideo streams
386 	 */
initNonVideo(JobCollection collection, String _name)387 	private void initNonVideo(JobCollection collection, String _name)
388 	{
389 		parentname = _name;
390 
391 		setFileName();
392 
393 		target_position = 0;
394 
395 		getSettings(collection);
396 
397 		try {
398 			out = new IDDBufferedOutputStream(new FileOutputStream(FileName), buffersize);
399 			pts_log = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(FileName + ".pts"), 65535));
400 
401 		} catch (IOException e) {
402 
403 			Common.setExceptionMessage(e);
404 		}
405 	}
406 
407 	/**
408 	 * main init nonVideo
409 	 */
init(JobCollection collection, String _name, int _buffersize, int _lfn, int _parsertype)410 	public void init(JobCollection collection, String _name, int _buffersize, int _lfn, int _parsertype)
411 	{
412 		lfn = _lfn;
413 		buffersize = _buffersize;
414 		sourcetype = _parsertype;
415 
416 		initNonVideo(collection, _name);
417 	}
418 
419 	/**
420 	 * re-init nonVideo
421 	 */
init2(JobCollection collection, String _name)422 	public void init2(JobCollection collection, String _name)
423 	{
424 		initNonVideo(collection, _name);
425 	}
426 
427 	/**
428 	 * process nonvideo data = 1 pespacket from demux
429 	 */
write(JobProcessing job_processing, byte[] pes_packet, boolean pes_hasHeader)430 	public void write(JobProcessing job_processing, byte[] pes_packet, boolean pes_hasHeader)
431 	{
432 		write(job_processing, pes_packet, 0, pes_packet.length, pes_hasHeader);
433 	}
434 
435 	/**
436 	 * process nonvideo data = 1 pespacket from demux
437 	 */
write(JobProcessing job_processing, byte[] pes_packet, int pes_packetoffset, int pes_payloadlength, boolean pes_hasHeader)438 	public void write(JobProcessing job_processing, byte[] pes_packet, int pes_packetoffset, int pes_payloadlength, boolean pes_hasHeader)
439 	{
440 		boolean pes_isAligned = false;
441 
442 		int pes_extensionlength = 0;
443 		int offset = pes_packetoffset;
444 		int _es_streamtype = CommonParsing.AC3_AUDIO;
445 
446 		pack++;
447 
448 		if (pes_hasHeader)
449 		{
450 			if (CommonParsing.validateStartcode(pes_packet, offset) < 0)
451 			{
452 				Common.setMessage(Resource.getString("demux.error.audio.startcode") + " " + pack + " (" + Integer.toHexString(PID) + "/" + Integer.toHexString(pes_ID) + "/" + Integer.toHexString(newID) + "/" + es_streamtype + ")");
453 				return;
454 			}
455 
456 			pes_ID = CommonParsing.getPES_IdField(pes_packet, offset);
457 			pes_payloadlength = CommonParsing.getPES_LengthField(pes_packet, offset);
458 			pes_isAligned = (pes_streamtype == CommonParsing.PES_AV_TYPE || pes_streamtype == CommonParsing.MPEG2PS_TYPE) && (4 & pes_packet[6 + offset]) != 0;
459 
460 			if (pes_ID == CommonParsing.PADDING_STREAM_CODE)
461 				return;
462 
463 			if (pes_streamtype == CommonParsing.MPEG1PS_TYPE)
464 			{
465 				skiploop:
466 				while(true)
467 				{
468 					switch (0xC0 & pes_packet[6 + offset])
469 					{
470 					case 0x40:
471 						offset += 2;
472 						continue skiploop;
473 
474 					case 0x80:
475 						offset += 3;
476 						continue skiploop;
477 
478 					case 0xC0:
479 						offset++;
480 						continue skiploop;
481 
482 					case 0:
483 						break;
484 					}
485 
486 					switch (0x30 & pes_packet[6 + offset])
487 					{
488 					case 0x20:  //PTS
489 						pes_extensionlength = 5;
490 						break skiploop;
491 
492 					case 0x30:  //PTS+DTS
493 						pes_extensionlength = 10;
494 						break skiploop;
495 
496 					case 0x10:  //DTS
497 						offset += 5;
498 						break skiploop;
499 
500 					case 0:
501 						offset++;
502 						break skiploop;
503 					}
504 				}
505 			}
506 
507 			else
508 			{
509 				pes_extensionlength = CommonParsing.getPES_ExtensionLengthField(pes_packet, offset);
510 
511 				if (pes_ID == CommonParsing.PRIVATE_STREAM_1_CODE && pes_extensionlength == 0x24 && (0xFF & pes_packet[9 + pes_extensionlength + offset])>>>4 == 1)
512 					_es_streamtype = CommonParsing.TELETEXT;
513 
514 				// workaround uk freesat teletext
515 				else if (pes_ID == CommonParsing.PRIVATE_STREAM_1_CODE && pes_extensionlength == 0x24 && (0xFF & pes_packet[9 + pes_extensionlength + offset]) == 0x99)
516 					_es_streamtype = CommonParsing.TELETEXT;
517 
518 				/**
519 				 * no PTS in PES_extension
520 				 */
521 				if ((0x80 & pes_packet[7 + offset]) == 0)
522 				{
523 					offset += pes_extensionlength;
524 					pes_extensionlength = 0;
525 				}
526 
527 				offset += 3;
528 			}
529 
530 			es_streamtype = pes_ID == CommonParsing.PRIVATE_STREAM_1_CODE ? _es_streamtype : CommonParsing.MPEG_AUDIO;
531 			subid = ((es_streamtype == CommonParsing.AC3_AUDIO || es_streamtype == CommonParsing.DTS_AUDIO || es_streamtype == CommonParsing.TELETEXT) && ((pes_streamtype == CommonParsing.PES_AV_TYPE && (pes_isAligned || es_streamtype == CommonParsing.TELETEXT)) || pes_streamtype == CommonParsing.MPEG2PS_TYPE)) ? (0xFF & pes_packet[9 + (0xFF & pes_packet[8 + pes_packetoffset]) + pes_packetoffset]) : 0;
532 
533 			// workaround uk freesat teletext
534 			if (isTTX())
535 				subid &= 0x1F;
536 
537 			switch (subid>>>4)
538 			{
539 			case 8:
540 				if (pes_streamtype == CommonParsing.PES_AV_TYPE || pes_streamtype == CommonParsing.MPEG1PS_TYPE)
541 				{
542 					subid = 0;
543 					break;
544 				}
545 
546 			case 1:
547 			case 2:
548 			case 3:
549 			case 9:
550 			case 0xA:
551 				break;
552 
553 			case 0:
554 				if (pes_isAligned && subid == 0x09)
555 					break;
556 
557 			default:
558 				if (pes_streamtype != CommonParsing.MPEG2PS_TYPE)
559 					subid = 0;
560 			}
561 
562 
563 			switch (subid>>>4)
564 			{
565 			case 0xA: //LPCM from MPG-PS
566 				es_streamtype = CommonParsing.LPCM_AUDIO;
567 				break;
568 
569 			case 2:   //SubPic 0-31 from MPG-PS
570 			case 3:   //SubPic 32-63 from MPG-PS
571 				es_streamtype = CommonParsing.SUBPICTURE;
572 				break;
573 
574 			case 8:   //AC3-DTS from MPG-PS
575 			case 1:   //TTX
576 			case 0:   //AC3-DTS from PES/VDR
577 				break;
578 
579 			case 9:   //VBI from TS,MPG2
580 				if (pes_isAligned)
581 				{
582 					if (pes_streamtype == CommonParsing.MPEG1PS_TYPE || pes_streamtype == CommonParsing.PES_AV_TYPE)
583 						subid = 0;
584 
585 					if (DecodeVBI)
586 						VBI.parsePES(pes_packet, pes_packetoffset);
587 
588 					return;
589 				}
590 				break;
591 
592 			default:
593 				return;
594 			}
595 
596 			pes_payloadlength -= (offset - pes_packetoffset + pes_extensionlength);
597 			offset += 6;
598 		}
599 
600 		if (!WriteNonVideo)
601 			return;
602 
603 		if (out == null)
604 			return;
605 
606 		try {
607 
608 			// recreate PTS
609 			if (RebuildPTS && es_streamtype == CommonParsing.TELETEXT)
610 			{
611 				if (job_processing.getBorrowedPts() != lastPTS)
612 				{
613 					lastPTS = job_processing.getBorrowedPts();
614 
615 					pts_log.writeLong(lastPTS);
616 					pts_log.writeLong(target_position);
617 
618 					if (Debug)
619 						System.out.println(" stolen ttx PTS: " + lastPTS + " /ao " + AddOffset + " /tp " + target_position);
620 				}
621 			}
622 
623 			//recreate subpicture
624 			else if (RebuildPictPTS && es_streamtype == CommonParsing.SUBPICTURE)
625 			{
626 				if (job_processing.getBorrowedPts() != lastPTS)
627 				{
628 					lastPTS = job_processing.getBorrowedPts();
629 					pts = lastPTS; //to rewrite into sp file
630 
631 					pts_log.writeLong(lastPTS);
632 					pts_log.writeLong(target_position);
633 
634 					if (Debug)
635 						System.out.println(" stolen subpic PTS: " + lastPTS + " /ao " + AddOffset + " /tp " + target_position);
636 				}
637 			}
638 
639 			/**
640 			 * read out source PTS
641 			 */
642 			else if (pes_extensionlength > 0 && pes_payloadlength >= 0)
643 			{
644 //--> �ndern
645 				pts = CommonParsing.getPTSfromBytes(pes_packet, offset); //returns 32bit
646 
647 				pts -= job_processing.getNextFileStartPts();
648 				pts &= 0xFFFFFFFFL; //trim to 32bit
649 
650 				if ( (pts & 0xFF000000L) == 0xFF000000L )
651 					ptsover = true;      // bit 33 was set
652 
653 				if (ptsover && pts < 0xF0000000L)
654 					pts |= 0x100000000L;
655 //<--
656 				pts += ptsoffset;
657 				pts += AddOffset;
658 
659 				if (lastPTS != pts)
660 				{
661 					if ((es_streamtype == CommonParsing.MPEG_AUDIO || es_streamtype == CommonParsing.AC3_AUDIO || es_streamtype == CommonParsing.DTS_AUDIO || es_streamtype == CommonParsing.LPCM_AUDIO)
662 							&& lastPTS != -1 && Math.abs(lastPTS - pts) > 100000)
663 						Common.setMessage("!> ID 0x" + Integer.toHexString(pes_ID).toUpperCase() + " (sub 0x" + Integer.toHexString(subid).toUpperCase() + ") packet# " + pack + ", big PTS difference: this " + pts + ", prev. " + lastPTS);
664 
665 					pts_log.writeLong(pts);
666 					pts_log.writeLong(target_position);
667 				}
668 
669 				if (Debug)
670 					System.out.println(" pda PTS: " + pts + "/ " + AddOffset + "/ " + target_position);
671 
672 				lastPTS = pts;
673 			}
674 
675 			/**
676 			 * save re-build PTS, taken from 1st mpa
677 			 */
678 			if (newID == 0xC0 && job_processing.getBorrowedPts() != lastPTS)
679 				job_processing.setBorrowedPts(lastPTS);
680 
681 			/**
682 			 * skip subid and info fields
683 			 */
684 			switch(subid>>>4)
685 			{
686 			case 0xA: //LPCM, keep info fields 6 bytes
687 				offset += 1; //7
688 				pes_payloadlength -= 1; //7
689 				break;
690 
691 			case 8: //AC3-DTS
692 				offset += 4;
693 				pes_payloadlength -= 4;
694 				break;
695 
696 			case 1: //TTX
697 				offset += 1;
698 				pes_payloadlength -= 1;
699 				break;
700 
701 			case 2: //subpic  0.31
702 			case 3: //subpic 32.63
703 				offset += 1;
704 				pes_payloadlength -= 1;
705 			}
706 
707 			if (subid == 0x09)
708 			{
709 				offset += 4;
710 				pes_payloadlength -= 4;
711 			}
712 
713 
714 			if (pes_payloadlength <= 0)
715 				return;
716 
717 			if (pes_extensionlength > 0)
718 			{
719 				switch(es_streamtype)
720 				{
721 				case CommonParsing.SUBPICTURE:
722 					CommonParsing.setValue(subpicture_header, 2, 8, CommonParsing.BYTEREORDERING, pts);
723 
724 					target_position += writePacket(subpicture_header);
725 
726 					/**
727 					 * DVB subs adaption
728 					 */
729 					if (CommonParsing.nextBits(pes_packet, (offset + pes_extensionlength) * 8, 16) == 0xF)
730 					{
731 						out.write(0xFF & (pes_payloadlength + 3)>>>8);
732 						out.write(0xFF & (pes_payloadlength + 3));
733 						out.write(0); //padding
734 
735 						target_position += 3;
736 					}
737 
738 					break;
739 
740 				case CommonParsing.LPCM_AUDIO:
741 					CommonParsing.setValue(lpcm_header, 3, 5, CommonParsing.BYTEREORDERING, pts);
742 
743 					lpcm_header[8] = (byte)(0xFF & pes_payloadlength>>>8);
744 					lpcm_header[9] = (byte)(0xFF & pes_payloadlength);
745 
746 					target_position += writePacket(lpcm_header);
747 				}
748 			}
749 
750 			/**
751 			 * DVB subs adaption, prevent lost packets
752 			 */
753 			else if (es_streamtype == CommonParsing.SUBPICTURE && pes_isAligned && CommonParsing.nextBits(pes_packet, (offset + pes_extensionlength) * 8, 16) == 0xF)
754 		//	else if (es_streamtype == CommonParsing.SUBPICTURE && CommonParsing.nextBits(pes_packet, (offset + pes_extensionlength) * 8, 16) == 0xF)
755 			{
756 				CommonParsing.setValue(subpicture_header, 2, 8, CommonParsing.BYTEREORDERING, 0);
757 
758 				target_position += writePacket(subpicture_header);
759 
760 				out.write(0xFF & (pes_payloadlength + 3)>>>8);
761 				out.write(0xFF & (pes_payloadlength + 3));
762 				out.write(0); //padding!
763 
764 				target_position += 3;
765 			}
766 
767 			if (subid == 0x09)
768 				for (int i = 0; i < pes_payloadlength; i += 3)
769 					target_position += writePacket(pes_packet, offset + pes_extensionlength + i, 2);
770 
771 			else
772 				target_position += writePacket(pes_packet, offset + pes_extensionlength, pes_payloadlength);
773 
774 		} catch (IOException e) {
775 
776 			Common.setExceptionMessage(e);
777 		}
778 	}
779 
780 	/**
781 	 *
782 	 */
close(JobProcessing job_processing, String _vptslog)783 	public String[] close(JobProcessing job_processing, String _vptslog)
784 	{
785 		String pts_log_name = FileName + ".pts";
786 		String parameters[] = { FileName, pts_log_name, type[es_streamtype], parentname };
787 
788 		try {
789 
790 			if (out == null)
791 			{
792 				parameters[0] = "";
793 				return parameters;
794 			}
795 
796 			out.flush();
797 			out.close();
798 
799 			pts_log.flush();
800 			pts_log.close();
801 
802 			if (new File(pts_log_name).length() < 10)
803 				CommonParsing.logAlias(job_processing, _vptslog, pts_log_name);
804 
805 			if (new File(FileName).length() < 10)
806 			{
807 				Common.setMessage("-> temp. Filesize < 10 Bytes");
808 
809 				new File(FileName).delete();
810 				new File(pts_log_name).delete();
811 
812 				parameters[0] = "";
813 			}
814 
815 			else
816 			{
817 				if (AppendPidToFileName)
818 					parameters[3] = parentname + formatIDString(getPID(), getID(), subID());
819 
820 				if (AppendLangToFileName)
821 					parameters[3] += job_processing.getAudioStreamLanguage(getPID());
822 			}
823 
824 		} catch (IOException e) {
825 
826 			Common.setExceptionMessage(e);
827 		}
828 
829 		return parameters;
830 	}
831 
832 	/**
833 	 *
834 	 */
formatIDString(int pid, int id, int subid)835 	private String formatIDString(int pid, int id, int subid)
836 	{
837 		String str = "";
838 
839 		str += "{0x" + Common.adaptString(Integer.toHexString(pid).toUpperCase(), 4);
840 		str += "-0x" + Common.adaptString(Integer.toHexString(id).toUpperCase(), 2);
841 		str += "-0x" + Common.adaptString(Integer.toHexString(subid).toUpperCase(), 2);
842 		str += "}";
843 
844 		return str;
845 	}
846 
847 	/**
848 	 *
849 	 */
initVideo(JobCollection collection, String _name, int _buffersize, int _lfn, int _parsertype)850 	public void initVideo(JobCollection collection, String _name, int _buffersize, int _lfn, int _parsertype)
851 	{
852 		getSettings(collection);
853 
854 		parentname = _name;
855 		lfn = _lfn;
856 		buffersize = _buffersize;
857 		sourcetype = _parsertype;
858 
859 		setFileName();
860 
861 		es_streamtype = CommonParsing.MPEG_VIDEO;
862 		MPGVideotype[0] = -1;
863 
864 		try {
865 			out = new IDDBufferedOutputStream(new FileOutputStream(FileName), buffersize);
866 
867 			if (CreateM2sIndex)
868 				out.InitIdd(FileName, 1);
869 
870             if (CreateInfoIndex)
871                 out.InitInfo(FileName);
872 
873 			pts_log = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(FileName + ".pts"), 65535));
874 			pts_log.write(CommonParsing.PTSVideoHeader);
875 
876 			packet = new ByteArrayOutputStream();
877 			vidbuf = new ByteArrayOutputStream();
878 			vptsbytes = new ByteArrayOutputStream();
879 			vpts = new DataOutputStream(vptsbytes);
880 
881 		} catch (IOException e) {
882 
883 			Common.setExceptionMessage(e);
884 		}
885 	}
886 
initVideo2(JobCollection collection, String _name)887 	public void initVideo2(JobCollection collection, String _name)
888 	{
889 		getSettings(collection);
890 
891 		parentname = _name;
892 		setFileName();
893 
894 		first = true;
895 		MPGVideotype[0] = -1;
896 
897 		try {
898 			out = new IDDBufferedOutputStream(new FileOutputStream(FileName), buffersize);
899 
900 			if (CreateM2sIndex)
901 				out.InitIdd(FileName, 1);
902 
903             if (CreateInfoIndex)
904                 out.InitInfo(FileName);
905 
906 			pts_log = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(FileName + ".pts"), 65535));
907 			pts_log.write(CommonParsing.PTSVideoHeader);
908 
909 			packet.reset();
910 	 		vidbuf.reset();
911 			vptsbytes.reset();
912 
913 		} catch (IOException e) {
914 
915 			Common.setExceptionMessage(e);
916 		}
917 	}
918 
919 
920 	/**
921 	 * clean Up for next foreign inputfile in case of multiple
922 	 */
resetVideo()923 	public void resetVideo()
924 	{
925 		if (vidbuf != null)
926 			vidbuf.reset();
927 
928 		if (packet != null)
929 			packet.reset();
930 
931 		if (vptsbytes != null)
932 			vptsbytes.reset();
933 
934 		first = true;
935 	}
936 
closeVideo(JobProcessing job_processing, String workouts)937 	public String closeVideo(JobProcessing job_processing, String workouts)
938 	{
939 		String logfile = "-1";
940 
941 		List cell = job_processing.getCellTimes();
942 
943 		int[] clv = job_processing.getStatusVariables();
944 
945 		try {
946 
947 			if (AddSequenceEndcode && job_processing.getExportedVideoFrameNumber() > 0)
948 			{
949 				if (MPGVideotype[0] < 2)
950 				{
951 					out.write(Video.getSequenceEndCode());
952 
953 					job_processing.countMediaFilesExportLength(+4);
954 					job_processing.countAllMediaFilesExportLength(+4);
955 				}
956 
957 				else // h264
958 				{
959 					out.write(new byte[]{0, 0, 0, 1, 0xA});
960 
961 					job_processing.countMediaFilesExportLength(+5);
962 					job_processing.countAllMediaFilesExportLength(+5);
963 				}
964 			}
965 
966 			packet.close();
967 			vidbuf.flush();
968 			vidbuf.close();
969 			out.flush();
970 			out.close();
971 			pts_log.flush();
972 			pts_log.close();
973 			vpts.flush();
974 			vpts.close();
975 			vptsbytes.flush();
976 			vptsbytes.close();
977 
978 			String videofile = "";
979 
980 			if (new File(FileName).length() < 10)
981 			{
982 				new File(FileName).delete();
983 
984 				if (!WriteVideo && new File(FileName + ".pts").length() > 16)
985 					logfile = FileName + ".pts";
986 
987 				else
988 					new File(FileName + ".pts").delete();
989 			}
990 
991 			else
992 			{
993 				//int ot = (RenameVideo || CreateD2vIndex || SplitProjectFile) ? 0 : 2;
994 				int ot = (RenameVideo || CreateD2vIndex || SplitProjectFile) ? 0 : 3;
995 
996 				videofile = parentname;
997 
998 				if (AppendPidToFileName)
999 					videofile += formatIDString(getPID(), getID(), subID());
1000 
1001 				videofile += videoext[MPGVideotype[0] + ot];
1002 				File newfile = new File(videofile);
1003 
1004 				if (newfile.exists())
1005 					newfile.delete();
1006 
1007 				Common.renameTo(new File(FileName), newfile);
1008 
1009 				logfile = FileName + ".pts";
1010 
1011 				CommonParsing.setVideoHeader(job_processing, videofile, logfile, clv, MPGVideotype);
1012 
1013 				/**
1014 				 * celltimes.txt
1015 				 */
1016 				if (CreateCellTimes && !cell.isEmpty())
1017 				{
1018 					BufferedWriter cellout = new BufferedWriter(new FileWriter(workouts + "CellTimes.txt"));
1019 
1020 					for (int i = 0; i < cell.size(); i++)
1021 					{
1022 						cellout.write(cell.get(i).toString());
1023 						cellout.newLine();
1024 					}
1025 
1026 					cellout.close();
1027 
1028 					Common.setMessage(Resource.getString("demux.msg.celltimes", workouts));
1029 
1030 					long fl = new File(workouts + "CellTimes.txt").length();
1031 
1032 					job_processing.countMediaFilesExportLength(fl);
1033 					job_processing.countAllMediaFilesExportLength(fl);
1034 				}
1035 
1036 				cell.clear();
1037 			}
1038 
1039 			if (CreateM2sIndex)
1040 			{
1041 				if (new File(videofile).exists())
1042 				{
1043                     String tmpFN = videofile.toString().substring(0, videofile.toString().lastIndexOf("."));
1044 					out.renameVideoIddTo(tmpFN);
1045 				}
1046 
1047 				else
1048 					out.deleteIdd();
1049 			}
1050 
1051             if (CreateInfoIndex)
1052 			{
1053                 if (new File(videofile).exists())
1054 				{
1055                     String tmpFN = videofile.toString();
1056                     out.renameVideoInfoTo(tmpFN);
1057                 }
1058 
1059                 else
1060                     out.deleteInfo();
1061             }
1062 
1063 		} catch (IOException e) {
1064 
1065 			Common.setExceptionMessage(e);
1066 		}
1067 
1068 		return logfile;
1069 	}
1070 
1071 
1072 
1073 	/**
1074 	 * temporary redirected access to goptest from video-es
1075 	 */
writeVideoES(JobProcessing job_processing, IDDBufferedOutputStream _out, byte[] _vidbuf, byte[] _vptsbytes, DataOutputStream _pts_log, String _parentname, int[] _MPGVideotype, List _CutpointList, List _ChapterpointList, boolean _doWrite)1076 	public void writeVideoES(JobProcessing job_processing, IDDBufferedOutputStream _out, byte[] _vidbuf, byte[] _vptsbytes, DataOutputStream _pts_log, String _parentname, int[] _MPGVideotype, List _CutpointList, List _ChapterpointList, boolean _doWrite)
1077 	{
1078 		job_processing.getGop().goptest(job_processing, _out, _vidbuf, _vptsbytes, _pts_log, _parentname, _MPGVideotype, _CutpointList, _ChapterpointList, _doWrite);
1079 	}
1080 
1081 	/**
1082 	 * write video
1083 	 * data = 1 pespacket from demux
1084 	 */
writeVideo(JobProcessing job_processing, byte[] pes_packet, boolean pes_hasHeader, List CutpointList, List ChapterpointList)1085 	public void writeVideo(JobProcessing job_processing, byte[] pes_packet, boolean pes_hasHeader, List CutpointList, List ChapterpointList)
1086 	{
1087 		writeVideo(job_processing, pes_packet, 0, pes_packet.length, pes_hasHeader, CutpointList, ChapterpointList);
1088 	}
1089 
1090 	/**
1091 	 * write video
1092 	 * data = 1 pespacket from demux
1093 	 */
writeVideo(JobProcessing job_processing, byte[] pes_packet, int pes_packetoffset, int pes_payloadlength, boolean pes_hasHeader, List CutpointList, List ChapterpointList)1094 	public void writeVideo(JobProcessing job_processing, byte[] pes_packet, int pes_packetoffset, int pes_payloadlength, boolean pes_hasHeader, List CutpointList, List ChapterpointList)
1095 	{
1096 		int pes_extensionlength = 0;
1097 		int offset = pes_packetoffset;
1098 		byte[] data = null;
1099 
1100 		int[] clv = job_processing.getStatusVariables();
1101 
1102 		pack++;
1103 
1104 		if (!pes_hasHeader)
1105 		{
1106 			if (job_processing.getPvaVideoPts() != -1)
1107 			{
1108 				offset -= 4;
1109 				pes_extensionlength += 4;
1110 			}
1111 		}
1112 
1113 		else
1114 		{
1115 			if (CommonParsing.validateStartcode(pes_packet, offset) < 0)
1116 			{
1117 				Common.setMessage(Resource.getString("demux.error.video.startcode") + " " + pack + " (" + Integer.toHexString(PID) + "/" + Integer.toHexString(pes_ID) + "/" + Integer.toHexString(newID) + "/" + es_streamtype + ")");
1118 				return;
1119 			}
1120 
1121 			pes_ID = CommonParsing.getPES_IdField(pes_packet, offset);
1122 			pes_payloadlength = CommonParsing.getPES_LengthField(pes_packet, offset);
1123 
1124 			if (pes_streamtype == CommonParsing.MPEG1PS_TYPE)
1125 			{
1126 				skiploop:
1127 				while(true)
1128 				{
1129 					switch (0xC0 & pes_packet[6 + offset])
1130 					{
1131 					case 0x40:
1132 						offset += 2;
1133 						continue skiploop;
1134 
1135 					case 0x80:
1136 						offset += 3;
1137 						continue skiploop;
1138 
1139 					case 0xC0:
1140 						offset++;
1141 						continue skiploop;
1142 
1143 					case 0:
1144 						break;
1145 					}
1146 
1147 					switch (0x30 & pes_packet[6 + offset])
1148 					{
1149 					case 0x20:  //PTS
1150 						pes_extensionlength = 5;
1151 						break skiploop;
1152 
1153 					case 0x30:  //PTS + DTS
1154 						pes_extensionlength = 10;
1155 						break skiploop;
1156 
1157 					case 0x10:  //DTS
1158 						offset += 5;
1159 						break skiploop;
1160 
1161 					case 0:
1162 						offset++;
1163 						break skiploop;
1164 					}
1165 				}
1166 			}
1167 
1168 			else
1169 			{
1170 				pes_extensionlength = CommonParsing.getPES_ExtensionLengthField(pes_packet, offset);
1171 
1172 				if ((0x80 & pes_packet[7 + offset]) == 0)
1173 				{
1174 					offset += pes_extensionlength;
1175 					pes_extensionlength = 0;
1176 				}
1177 
1178 				offset += 3;
1179 			}
1180 
1181 			pes_payloadlength -= (offset - pes_packetoffset + pes_extensionlength);
1182 			offset += 6;
1183 		}
1184 
1185 		/**
1186 		 * read pts
1187 		 */
1188 		if (pes_extensionlength > 0 && pes_payloadlength >= 0)
1189 		{
1190 //--> �ndern
1191 			pts = !pes_hasHeader ? job_processing.getPvaVideoPts() : CommonParsing.getPTSfromBytes(pes_packet, offset); //returns 32bit
1192 
1193 			pts -= job_processing.getNextFileStartPts();
1194 
1195 			pts &= 0xFFFFFFFFL;  // trim to 32bit
1196 
1197 			if ( (pts & 0xFF000000L) == 0xFF000000L )
1198 				ptsover = true;      // bit 33 was set
1199 
1200 			if (ptsover && pts < 0xF0000000L)
1201 
1202 				pts |= 0x100000000L;
1203 //<--
1204 			pts += ptsoffset;
1205 
1206 			if (Debug)
1207 				System.out.println(" pdv PTS: " + pts);
1208 
1209 			isPTSwritten = false;
1210 		}
1211 
1212 		try {
1213 
1214 			if (pes_payloadlength <= 0)
1215 				Common.setMessage(Resource.getString("demux.error.video.payload") + " (" + pack + "/" + pes_packet.length + "/" + offset + "/" + pes_extensionlength + "/" + pes_payloadlength + ")");
1216 
1217 			else
1218 				packet.write(pes_packet, offset + pes_extensionlength, pes_payloadlength);
1219 
1220 			packet.flush();
1221 
1222 /** simple demux
1223 	byte[] ddd = new byte[pes_payloadlength];
1224 	System.arraycopy(pes_packet, offset + pes_extensionlength, ddd, 0, pes_payloadlength);
1225 
1226 	job_processing.getGop().h264test(job_processing, out, ddd, vptsbytes.toByteArray(), pts_log, parentname, MPGVideotype, CutpointList, ChapterpointList);
1227 
1228 			packet.reset();
1229 
1230 	if (1 == 1)
1231 		return;
1232 **/
1233 			data = packet.toByteArray();
1234 
1235 			packet.reset();
1236 
1237 			boolean gop = false;
1238 			boolean packetfirstframe = true;
1239 
1240 			int nal_unit = 0;
1241 			int nal_ref = 0;
1242 
1243 			packloop:
1244 			for (int i = 0, j = 0, k = 0, id, returncode; i < data.length - 3; i++)
1245 			{
1246 				if ((returncode = CommonParsing.validateStartcode(data, i)) < 0)
1247 				{
1248 					i += (-returncode) - 1;
1249 					continue packloop;
1250 				}
1251 
1252 				id = CommonParsing.getPES_IdField(data, i);
1253 
1254 // mpeg4 part
1255 				//optional deactivator
1256 				if (!EnableHDDemux)
1257 					isH264 = false;
1258 
1259 				if (isH264)
1260 				{
1261 					if (i == 0 || data[i - 1] != 0 || (0x80 & id) != 0)  // not 00 00 00 01 0XXX-XXXX
1262 						continue packloop;
1263 
1264 					i--; // return to startcode
1265 					nal_ref  = 3 & id>>5;
1266 					nal_unit = 0x1F & id;
1267 
1268 					if (Debug)
1269 						System.out.println("i " + i + " /NAL ref " + nal_ref + " /unit " + nal_unit);
1270 
1271 					switch (nal_unit)
1272 					{
1273 					case 1:   // non IDR pic data
1274 					case 5:   // IDR pic data
1275 
1276 						if (!isPTSwritten && pts != -1)
1277 						{
1278 							vpts.writeLong(pts);
1279 							vpts.writeLong((long) k);
1280 							vpts.flush();
1281 
1282 							isPTSwritten = true;
1283 						}
1284 						break;
1285 
1286 					case 7:   // sequence param set // 9-7-8-6-1  ; 9-7-6-8-6-1
1287 
1288 						vidbuf.write(data, 0, j); // save last data until run-in
1289 
1290 						if (!first)
1291 							job_processing.getGop().h264test(job_processing, out, vidbuf.toByteArray(), vptsbytes.toByteArray(), pts_log, parentname, MPGVideotype, CutpointList, ChapterpointList);
1292 
1293 						vptsbytes.reset();
1294 						vidbuf.reset();
1295 
1296 						if (!isPTSwritten && pts != -1)
1297 						{
1298 							vpts.writeLong(pts);
1299 							vpts.writeLong((long) 0);
1300 							vpts.flush();
1301 
1302 							isPTSwritten = true;
1303 						}
1304 
1305 						first = false;
1306 						gop = true;
1307 
1308 						// save new data from run-in
1309 						// expects there's no next seq param set
1310 						vidbuf.write(data, j, data.length - j);
1311 
1312 						break;
1313 
1314 					case 9:   // run-in
1315 						j = i;
1316 						k = vidbuf.size();
1317 						break;
1318 					}
1319 
1320 					i += 2;
1321 					continue packloop;
1322 				}
1323 //
1324 
1325 				// 00 00 00 01 + 0XX0-1001 lead-in, toggle with mpeg1-2, shall be set once
1326 				else if (MPGVideotype[0] < 0)
1327 				{
1328 					isH264 = i > 0 && data[i - 1] == 0 && (0x9F & id) == 9;
1329 				}
1330 
1331 				if (isH264) // last return, never been called after that
1332 					continue packloop;
1333 
1334 
1335 
1336 				/**
1337 				 * new frame at first
1338 				 */
1339 				if (!isPTSwritten && packetfirstframe && id == CommonParsing.PICTURE_START_CODE)
1340 				{
1341 					if (MPGVideotype[0] < 0)
1342 						MPGVideotype[0] = 0;
1343 
1344 					if (misshead && i < 3)
1345 					{
1346 						misshead = false;
1347 						continue packloop;
1348 					}
1349 
1350 					if (pts != -1)
1351 					{
1352 						vpts.writeLong(pts);
1353 						vpts.writeLong((long)vidbuf.size());
1354 						vpts.flush();
1355 					}
1356 
1357 					isPTSwritten = true;
1358 					packetfirstframe = false;
1359 					i += 8;
1360 				}
1361 
1362 				else if (id == CommonParsing.SEQUENCE_HEADER_CODE || id == CommonParsing.SEQUENCE_END_CODE || id == CommonParsing.GROUP_START_CODE)
1363 				{
1364 					if (MPGVideotype[0] < 0)
1365 						MPGVideotype[0] = 0;
1366 
1367 					if (id == CommonParsing.SEQUENCE_HEADER_CODE)
1368 						seqhead = true;
1369 
1370 					if (id == CommonParsing.GROUP_START_CODE && seqhead && vidbuf.size() < 400)
1371 					{
1372 						seqhead = false;
1373 						continue packloop;
1374 					}
1375 
1376 					vidbuf.write(data, j, i);
1377 
1378 					if (!first)
1379 						job_processing.getGop().goptest(job_processing, out, vidbuf.toByteArray(), vptsbytes.toByteArray(), pts_log, parentname, MPGVideotype, CutpointList, ChapterpointList);
1380 
1381 					vptsbytes.reset();
1382 					vidbuf.reset();
1383 
1384 					/**
1385 					 * split size reached
1386 					 */
1387 					if (job_processing.getSplitSize() > 0 && job_processing.getSplitSize() < job_processing.getAllMediaFilesExportLength())
1388 						return;
1389 
1390 					/**
1391 					 * d2v split reached
1392 					 */
1393 					if (SplitProjectFile && job_processing.getProjectFileExportLength() > job_processing.getProjectFileSplitSize())
1394 					{
1395 						int part = job_processing.getProjectFileD2V().getPart() + 1;
1396 						String newpart = parentname + "[" + part + "].mpv";
1397 
1398 						/**
1399 						 * sequence end code
1400 						 */
1401 						if (WriteVideo && AddSequenceEndcode && job_processing.getExportedVideoFrameNumber() > 0 )
1402 						{
1403 							out.write(Video.getSequenceEndCode());
1404 
1405 							job_processing.countMediaFilesExportLength(+4);
1406 							job_processing.countAllMediaFilesExportLength(+4);
1407 						}
1408 
1409 						out.flush();
1410 						out.close();
1411 						//System.gc();
1412 
1413 						out = new IDDBufferedOutputStream( new FileOutputStream(newpart), buffersize);
1414 
1415 						/**
1416 						 * M2S idd
1417 						 */
1418 						if (CreateM2sIndex)
1419 							out.InitIdd(newpart, 1);
1420 
1421                         if (CreateInfoIndex)
1422                             out.InitInfo(newpart);
1423 
1424 						job_processing.getProjectFileD2V().setFile(newpart);
1425 						job_processing.setProjectFileExportLength(0);
1426 					}
1427 
1428 					if (!isPTSwritten && packetfirstframe)
1429 					{
1430 						if (pts != -1)
1431 						{
1432 							vpts.writeLong(pts);
1433 							vpts.writeLong(vidbuf.size());
1434 							vpts.flush();
1435 						}
1436 
1437 						isPTSwritten = true;
1438 					}
1439 
1440 
1441 					if (id == CommonParsing.SEQUENCE_END_CODE)
1442 					{
1443 						Common.setMessage(Resource.getString("demux.msg.skip.sec") + " " + clv[6]);
1444 
1445 						first = true;
1446 						job_processing.setSequenceHeader(false);
1447 
1448 						i += 3;
1449 						continue packloop;
1450 					}
1451 					else
1452 						vidbuf.write(data, i, data.length - i);
1453 
1454 
1455 					if (id == CommonParsing.GROUP_START_CODE)
1456 					{
1457 						job_processing.setSequenceHeader(false);
1458 
1459 						if (job_processing.getSplitPart() > 0)
1460 							first = false;
1461 					}
1462 					else if (id == CommonParsing.SEQUENCE_HEADER_CODE)
1463 					{
1464 						job_processing.setSequenceHeader(true);
1465 						first = false;
1466 					}
1467 
1468 					gop = true;
1469 					misshead = false;
1470 					break packloop;
1471 				}
1472 			} // end packloop
1473 
1474 			if (!gop)
1475 			{
1476 				if (data.length > 2)
1477 				{
1478 					vidbuf.write(data, 0, data.length - 3);
1479 					packet.write(data, data.length - 3, 3);
1480 					misshead = true;
1481 				}
1482 				else
1483 					vidbuf.write(data);
1484 			}
1485 
1486 		} catch (IOException e) {
1487 
1488 			Common.setExceptionMessage(e);
1489 		}
1490 
1491 		if (vidbuf.size() > 6144000)
1492 		{
1493 			vptsbytes.reset();
1494 			vidbuf.reset();
1495 			packet.reset();
1496 
1497 			Common.setMessage(Resource.getString("demux.error.gop.toobig"));
1498 
1499 			misshead = false;
1500 			first = true;
1501 		}
1502 	}
1503 
1504 	/**
1505 	 * simply write the packet
1506 	 */
writePacket(byte[] packet)1507 	private int writePacket(byte[] packet) throws IOException
1508 	{
1509 		return writePacket(packet, 0, packet.length);
1510 	}
1511 
1512 	/**
1513 	 * simply write the packet
1514 	 */
writePacket(byte[] packet, int offset, int length)1515 	private int writePacket(byte[] packet, int offset, int length) throws IOException
1516 	{
1517 		if (offset < 0 || offset >= packet.length)
1518 		{
1519 			Common.setMessage("!> packet writing: index out of bounds, ignore it.. (" + Integer.toHexString(getPID()) + " / " + Integer.toHexString(getID()) + " / " + Integer.toHexString(getnewID()) + " / " + getPackCount() + " -- " + packet.length + " / " + offset + " / " + length + ") @ PTS " + Common.formatTime_1(lastPTS / 90));
1520 			return 0;
1521 		}
1522 
1523 		if (offset + length > packet.length)
1524 		{
1525 			Common.setMessage("!> packet writing: length index out of bounds, shortened.. (" + Integer.toHexString(getPID()) + " / " + Integer.toHexString(getID()) + " / " + Integer.toHexString(getnewID()) + " / " + getPackCount() + " -- " + packet.length + " / " + offset + " / " + length + ") @ PTS " + Common.formatTime_1(lastPTS / 90));
1526 			length = packet.length - offset;
1527 		}
1528 
1529 		out.write(packet, offset, length);
1530 
1531 		return length;
1532 	}
1533 
1534 }
1535 
1536