/* * @(#)StreamParser * * Copyright (c) 2005-2006 by dvb.matt, All rights reserved. * * This file is part of ProjectX, a free Java based demux utility. * By the authors, ProjectX is intended for educational purposes only, * as a non-commercial test project. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ package net.sourceforge.dvb.projectx.parser; import java.io.File; import java.io.InputStream; import java.io.IOException; import java.io.PushbackInputStream; import java.io.FileOutputStream; import java.util.Arrays; import java.util.List; import java.util.ArrayList; import java.util.Hashtable; import net.sourceforge.dvb.projectx.common.Common; import net.sourceforge.dvb.projectx.common.Resource; import net.sourceforge.dvb.projectx.common.Keys; import net.sourceforge.dvb.projectx.common.JobCollection; import net.sourceforge.dvb.projectx.common.JobProcessing; import net.sourceforge.dvb.projectx.io.StandardBuffer; import net.sourceforge.dvb.projectx.xinput.XInputFile; import net.sourceforge.dvb.projectx.xinput.StreamInfo; import net.sourceforge.dvb.projectx.parser.CommonParsing; import net.sourceforge.dvb.projectx.parser.StreamConverter; import net.sourceforge.dvb.projectx.parser.StreamDemultiplexer; import net.sourceforge.dvb.projectx.parser.StreamParserBase; /** * main thread */ public class StreamParserPESPrimary extends StreamParserBase { private boolean Message_2; private boolean Debug; private boolean SimpleMPG; private boolean GetEnclosedPackets; private boolean IgnoreScrambledPackets; private boolean PreviewAllGops; private boolean DumpDroppedGop; private boolean Overlap; /** * */ public StreamParserPESPrimary() { super(); } /** * primary PES Parser */ public String parseStream(JobCollection collection, XInputFile aXInputFile, int _pes_streamtype, int action, String vptslog) { JobProcessing job_processing = collection.getJobProcessing(); setFileName(collection, job_processing, aXInputFile); Debug = collection.getSettings().getBooleanProperty(Keys.KEY_DebugLog); Message_2 = collection.getSettings().getBooleanProperty(Keys.KEY_MessagePanel_Msg2); SimpleMPG = collection.getSettings().getBooleanProperty(Keys.KEY_simpleMPG); GetEnclosedPackets = collection.getSettings().getBooleanProperty(Keys.KEY_Input_getEnclosedPackets); IgnoreScrambledPackets = collection.getSettings().getBooleanProperty(Keys.KEY_TS_ignoreScrambled); PreviewAllGops = collection.getSettings().getBooleanProperty(Keys.KEY_Preview_AllGops); DumpDroppedGop = collection.getSettings().getBooleanProperty(Keys.KEY_dumpDroppedGop); CreateD2vIndex = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_createD2vIndex); SplitProjectFile = collection.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_splitProjectFile); Overlap = collection.getSettings().getBooleanProperty(Keys.KEY_ExportPanel_Export_Overlap); setOverheadSize(collection); boolean isTeletext = false; boolean missing_startcode = false; boolean scrambling_messaged = false; boolean pes_isMpeg2; boolean pes_alignment; boolean pes_scrambled; boolean containsPts = false; boolean usePidfilter = false; boolean isZeroPacket = false; boolean isZeroSubPacket = false; boolean ende = false; boolean foundObject; int Infoscan_Value = Integer.parseInt(collection.getSettings().getProperty(Keys.KEY_ExportPanel_Infoscan_Value)); int CutMode = collection.getSettings().getIntProperty(Keys.KEY_CutMode); int pes_streamtype = _pes_streamtype; int pes_payloadlength; int pes_packetlength; int pes_extensionlength; int pes_headerlength = 9; int pes_packetoffset = 6; int pes_extension2_id; int pesID; int subID; int offset; int returncode = 0; int vob_ID = 0; int cell_ID = 0; int ZeroPacketPayload = 0x17FA; int tmp_value1 = 0; int pesID0 = 0; //first video stream ID int dumped_packets = 0; job_processing.clearStatusVariables(); int[] clv = job_processing.getStatusVariables(); int[] newID = { 0x80, 0x90, 0xC0, 0xE0, 0xA0, 0x20 }; byte[] pes_packet = new byte[0x10010]; byte[] buffered_data; long count = 0; long base; long size = count; long qexit; long ptsoffset = 0; long lastpts = 0; long startPoint = 0; long starts[] = new long[collection.getPrimaryInputFileSegments()]; long Overlap_Value = 1048576L * (collection.getSettings().getIntProperty(Keys.KEY_ExportPanel_Overlap_Value) + 1); vptslog = "-1"; //fix String file_id = aXInputFile.getFileID(); streamconverter = new StreamConverter(); Hashtable substreams = new Hashtable(); StandardBuffer sb; demuxList = job_processing.getPrimaryPESDemuxList(); /** * re-read old streams, for next split part */ if (job_processing.getSplitPart() == 0) demuxList.clear(); else { for (int i = 0; i < demuxList.size(); i++) { streamdemultiplexer = (StreamDemultiplexer) demuxList.get(i); if (streamdemultiplexer.getnewID() != 0) newID[streamdemultiplexer.getType()]++; if (streamdemultiplexer.getNum() == -1) continue; if (streamdemultiplexer.getType() == CommonParsing.MPEG_VIDEO) { streamdemultiplexer.initVideo2(collection, fparent); if (pesID0 == 0) //? pesID0 = streamdemultiplexer.getID(); } else streamdemultiplexer.init2(collection, fparent); } } /** * init conversions */ String mpeg_type_str = (Keys.ITEMS_FileTypes[pes_streamtype]).toString().toLowerCase(); mpeg_type_str = "[" + mpeg_type_str.substring(0, mpeg_type_str.indexOf(' ')) + "]"; initConversion(collection, fparent + (job_processing.getSplitSize() == 0 ? mpeg_type_str : ""), action, CommonParsing.ACTION_TO_VDR, job_processing.getSplitPart()); /** * d2v projectfile */ if (CreateD2vIndex || SplitProjectFile) job_processing.getProjectFileD2V().Init(fparent); job_processing.setMinBitrate(CommonParsing.MAX_BITRATE_VALUE); job_processing.setMaxBitrate(0); job_processing.setExportedVideoFrameNumber(0); job_processing.setEndPtsOfGop(-10000); job_processing.setSequenceHeader(true); job_processing.setAllMediaFilesExportLength(0); job_processing.setProjectFileExportLength(0); job_processing.setCutByteposition(0); /** * pid inclusion */ int[] predefined_Pids = collection.getPIDsAsInteger(); int[] include = new int[predefined_Pids.length]; for (int i = 0; i < include.length; i++) include[i] = 0xFF & predefined_Pids[i]; if (include.length > 0) { Arrays.sort(include); String str = " "; for (int i = 0; i < include.length; i++) str += "0x" + Integer.toHexString(include[i]).toUpperCase() + " "; Common.setMessage(Resource.getString("parsePrimaryPES.special.pes") + ": {" + str + "}"); usePidfilter = true; } try { /** * determine start & end byte pos. of each file segment */ for (int i = 0; i < starts.length; i++) { aXInputFile = (XInputFile) collection.getInputFile(i); starts[i] = size; size += aXInputFile.length(); } aXInputFile = (XInputFile) collection.getInputFile(job_processing.getFileNumber()); /** * set start & end byte pos. of first file segment */ count = starts[job_processing.getFileNumber()]; size = count + aXInputFile.length(); /** * split skipping first, for next split part */ if (job_processing.getSplitSize() > 0) { startPoint = job_processing.getLastHeaderBytePosition(); startPoint -= !Overlap ? 0 : Overlap_Value; job_processing.setLastGopTimecode(0); job_processing.setLastGopPts(0); job_processing.setLastSimplifiedPts(0); } List CutpointList = collection.getCutpointList(); List ChapterpointList = collection.getChapterpointList(); /** * jump near to first cut-in point to collect more audio */ if (CutMode == CommonParsing.CUTMODE_BYTE && CutpointList.size() > 0 && CommonParsing.getCutCounter() == 0 && (!PreviewAllGops || action != CommonParsing.ACTION_DEMUX)) startPoint = Long.parseLong(CutpointList.get(CommonParsing.getCutCounter()).toString()) - ((action == CommonParsing.ACTION_DEMUX) ? OverheadSize : 0); if (startPoint < 0) startPoint = count; // =0 else if (startPoint < count) { for (int i = starts.length; i > 0; i--) if (starts[i - 1] > startPoint) job_processing.countFileNumber(-1); } else if (startPoint > count) { for (int i = job_processing.getFileNumber() + 1; i < starts.length; i++) { if (starts[i] > startPoint) break; else job_processing.countFileNumber(+1); } } aXInputFile = (XInputFile) collection.getInputFile(job_processing.getFileNumber()); count = starts[job_processing.getFileNumber()]; if (job_processing.getFileNumber() > 0) Common.setMessage(Resource.getString("parsePrimaryPES.continue") + ": " + aXInputFile); base = count; size = count + aXInputFile.length(); PushbackInputStream in = new PushbackInputStream(aXInputFile.getInputStream(startPoint - base), pes_packet.length); count += (startPoint - base); Common.updateProgressBar((action == CommonParsing.ACTION_DEMUX ? Resource.getString("parsePrimaryPES.demuxing") : Resource.getString("parsePrimaryPES.converting")) + " " + Resource.getString("parsePrimaryPES.avpes.file") + " " + aXInputFile.getName(), (count - base), (size - base)); qexit = count + (0x100000L * Infoscan_Value); //yield(); bigloop: while (true) { loop: while (count < size) { pes_streamtype = _pes_streamtype; // reset to original type Common.updateProgressBar(count, size); //yield(); while (pause()) {} if (CommonParsing.isProcessCancelled() || (CommonParsing.isInfoScan() && count > qexit)) { CommonParsing.setProcessCancelled(false); job_processing.setSplitSize(0); break bigloop; } /** * after last cut out, still read some packets to collect some audio */ if (job_processing.getCutComparePoint() + 20 < job_processing.getSourceVideoFrameNumber()) { ende = true; break bigloop; } /** * cut mode bytepos + min 1 cutpoint */ if (CutMode == CommonParsing.CUTMODE_BYTE && CutpointList.size() > 0) { if (CommonParsing.getCutCounter() == CutpointList.size() && (CommonParsing.getCutCounter() & 1) == 0) if (count > Long.parseLong(CutpointList.get(CommonParsing.getCutCounter() - 1).toString()) + (action == CommonParsing.ACTION_DEMUX ? OverheadSize : 64000)) { ende = true; break bigloop; } } in.read(pes_packet, 0, pes_packetoffset); pesID = CommonParsing.getPES_IdField(pes_packet, 0); /** * */ if ((returncode = CommonParsing.validateStartcode(pes_packet, 0)) < 0 || pesID < CommonParsing.SYSTEM_END_CODE) { returncode = returncode < 0 ? -returncode : 4; if (Message_2 && !missing_startcode) Common.setMessage(Resource.getString("parsePrimaryPES.missing.startcode") + " " + count); in.read(pes_packet, pes_packetoffset, pes_packet.length - pes_packetoffset); int i = returncode; for (; i < pes_packet.length - 3; ) { returncode = CommonParsing.validateStartcode(pes_packet, i); if (returncode < 0) { i += -returncode; continue; } else { in.unread(pes_packet, i, pes_packet.length - i); count += i; missing_startcode = true; continue loop; } } in.unread(pes_packet, i, pes_packet.length - i); count += i; missing_startcode = true; continue loop; } if (Message_2 && missing_startcode) Common.setMessage(Resource.getString("parsePrimaryPES.found.startcode") + " " + count); missing_startcode = false; if (pes_streamtype == CommonParsing.MPEG1PS_TYPE || pes_streamtype == CommonParsing.MPEG2PS_TYPE || SimpleMPG) { switch (pesID) { case CommonParsing.SYSTEM_END_CODE: in.unread(pes_packet, 4, 2); Common.setMessage("-> skip system_end_code @ " + count); count += 4; continue loop; case CommonParsing.PACK_START_CODE: if ((0xC0 & pes_packet[4]) == 0) //mpg1 { in.skip(pes_packetoffset); count += 12; continue loop; } else if ((0xC0 & pes_packet[4]) == 0x40) //mpg2 { in.read(pes_packet, pes_packetoffset, 8); offset = 7 & pes_packet[13]; count += 14; in.read(pes_packet, 14, offset); if (offset > 0) { for (int i = 0; i < offset; i++) if (pes_packet[14 + i] != -1) { in.unread(pes_packet, 14, offset); Common.setMessage("!> wrong pack header stuffing @ " + count); missing_startcode = true; continue loop; } } count += offset; continue loop; } else { in.unread(pes_packet, 4, 2); count += 4; continue loop; } case CommonParsing.PRIVATE_STREAM_2_CODE: //determine cellids pes_payloadlength = CommonParsing.getPES_LengthField(pes_packet, 0); in.read(pes_packet, pes_packetoffset, pes_payloadlength); if (pes_packet[pes_packetoffset] == 1) //substream id 1 { int cellid = 0xFF & pes_packet[0x22]; int vobid = (0xFF & pes_packet[0x1F])<<8 | (0xFF & pes_packet[0x20]); if (cell_ID != cellid || vob_ID != vobid) { Common.setMessage(Resource.getString("parsePrimaryPES.split.cellids", "" + vobid, "" + cellid, "" + count, "" + clv[6], "" + job_processing.getExportedVideoFrameNumber())); if (collection.getSettings().getBooleanProperty(Keys.KEY_VOB_resetPts)) { // ptsoffset = nextFilePTS(collection, CommonParsing.PRIMARY_PES_PARSER, pes_streamtype, lastpts, job_processing.getFileNumber(), (count - base)); ptsoffset = nextFilePTS(collection, CommonParsing.PRIMARY_PES_PARSER, pes_streamtype, lastpts, ptsoffset, job_processing.getFileNumber(), (count - base)); if (ptsoffset == -1) ptsoffset = 0; else { for (int i = 0; i < demuxList.size(); i++) { streamdemultiplexer = (StreamDemultiplexer)demuxList.get(i); streamdemultiplexer.PTSOffset(ptsoffset); if (streamdemultiplexer.getID() == pesID0) streamdemultiplexer.resetVideo(); } job_processing.setSequenceHeader(true); job_processing.setNewVideoStream(true); // job_processing.addCellTime(String.valueOf(job_processing.getExportedVideoFrameNumber())); } } } cell_ID = cellid; vob_ID = vobid; } count += (pes_packetoffset + pes_payloadlength); continue loop; case CommonParsing.SYSTEM_START_CODE: case CommonParsing.PROGRAM_STREAM_MAP_CODE: case CommonParsing.PADDING_STREAM_CODE: case CommonParsing.ECM_STREAM_CODE: case CommonParsing.EMM_STREAM_CODE: case CommonParsing.DSM_CC_STREAM_CODE: case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7: case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF: pes_payloadlength = CommonParsing.getPES_LengthField(pes_packet, 0); in.skip(pes_payloadlength); count += (pes_packetoffset + pes_payloadlength); continue loop; } } if ( (0xF0 & pesID) != 0xE0 && (0xE0 & pesID) != 0xC0 && pesID != CommonParsing.PRIVATE_STREAM_1_CODE) { in.unread(pes_packet, 3, pes_packetoffset - 3); count += 3; continue loop; } /** * mark for split at sequenceheader */ job_processing.setLastHeaderBytePosition(count); job_processing.setCutByteposition(count); pes_payloadlength = CommonParsing.getPES_LengthField(pes_packet, 0); /** * zeropackets of video only as PES from TS allowed */ isZeroPacket = pes_payloadlength == 0 && (0xF0 & pesID) == 0xE0; if (isZeroPacket) pes_payloadlength = ZeroPacketPayload; in.read(pes_packet, pes_packetoffset, pes_payloadlength + 4); pes_packetlength = pes_packetoffset + pes_payloadlength; pes_isMpeg2 = (0xC0 & pes_packet[6]) == 0x80; /** * determine next startcode in zero packets */ if (isZeroPacket) { if (Debug) System.out.println("A " + Resource.getString("parsePrimaryPES.packet.length") + " " + count); //start after pes header for (int i = pes_packetoffset + (pes_isMpeg2 ? 3 : 1); isZeroPacket && i <= pes_packetlength; ) { if ((returncode = CommonParsing.validateStartcode(pes_packet, i)) < 0 || CommonParsing.getPES_IdField(pes_packet, i) < CommonParsing.SYSTEM_END_CODE) { i += (returncode < 0 ? -returncode : 4); continue; } /** * next header found before max. size of ZeroPacketPayload * handle packet as normal, the 4 added bytes will be unread in the next startcode check */ in.unread(pes_packet, i + 4, pes_packetlength - i); pes_packetlength = i; pes_payloadlength = pes_packetlength - pes_packetoffset; isZeroPacket = false; } CommonParsing.setPES_LengthField(pes_packet, 0, pes_payloadlength); } /** * check next startcode */ if (GetEnclosedPackets && !isZeroPacket && CommonParsing.validateStartcode(pes_packet, pes_packetlength) < 0) { if (count + pes_packetlength < size) { if (Message_2 && !missing_startcode) Common.setMessage(Resource.getString("parsePrimaryPES.miss.startcode2", String.valueOf(count + pes_packetlength), String.valueOf(count), Integer.toHexString(pesID).toUpperCase())); missing_startcode = true; in.unread(pes_packet, pes_packetoffset, pes_payloadlength + 4); count += pes_packetoffset; continue loop; } } else in.unread(pes_packet, pes_packetlength, 4); clv[5]++; if (Debug) System.out.println(Resource.getString("parsePrimaryPES.packs") + ": " + pesID + "/" + clv[5] + "/" + (pes_packetlength) + "/" + ((count * 100 / size)) + "% " + (count)); pes_extensionlength = CommonParsing.getPES_ExtensionLengthField(pes_packet, 0); pes_isMpeg2 = (0xC0 & pes_packet[6]) == 0x80; pes_alignment = pes_isMpeg2 && (4 & pes_packet[6]) != 0; pes_scrambled = pes_isMpeg2 && (0x30 & pes_packet[6]) != 0; count += pes_packetlength; zeropacketloop: do { /** * exit loop */ if (isZeroPacket && count >= size) break zeropacketloop; /** * read videos zerosubpacket data in a loop, if packet data is greater than max. ZeroPacketPayload * the first read header data is re-used, we read only the rest */ if (isZeroSubPacket) { if (Debug) System.out.println("B " + Resource.getString("parsePrimaryPES.packet.length") + " " + count + " / " + pes_isMpeg2); pes_payloadlength = ZeroPacketPayload; pes_packetlength = pes_packetoffset + pes_payloadlength; offset = pes_isMpeg2 ? 3 : 1; in.read(pes_packet, pes_packetoffset + offset, pes_payloadlength - offset + 4); in.unread(pes_packet, pes_packetlength, 4); for (int i = pes_packetoffset + offset; isZeroPacket && i <= pes_packetlength; ) { if ((returncode = CommonParsing.validateStartcode(pes_packet, i)) < 0 || CommonParsing.getPES_IdField(pes_packet, i) < CommonParsing.SYSTEM_END_CODE) { i += (returncode < 0 ? -returncode : 4); continue; } /** * next header found before max. size of ZeroPacketPayload * handle packet as normal, the 4 added bytes will be unread in the next startcode check */ in.unread(pes_packet, i, pes_packetlength - i); pes_packetlength = i; pes_payloadlength = pes_packetlength - pes_packetoffset; // set isZeroPacket to false, if next startcode was found isZeroPacket = false; } CommonParsing.setValue(pes_packet, pes_packetoffset, offset, false, pes_isMpeg2 ? (0xF3 & pes_packet[pes_packetoffset])<<16 : 0x0F); // values of pes scrambling and copyright/copy prot. are taken from orig. CommonParsing.setPES_LengthField(pes_packet, 0, pes_payloadlength); count += (pes_payloadlength - offset); } isZeroSubPacket = isZeroPacket; /** * check scrambling */ if (IgnoreScrambledPackets) { // cannot work with scrambled data if (pes_scrambled) { if (!scrambling_messaged) { scrambling_messaged = true; Common.setMessage(Resource.getString("parseTS.scrambled", Integer.toHexString(pesID).toUpperCase(), String.valueOf(clv[5]), String.valueOf(count - pes_packetlength))); } continue zeropacketloop; } else if (scrambling_messaged) { Common.setMessage(Resource.getString("parseTS.clear", Integer.toHexString(pesID).toUpperCase(), String.valueOf(clv[5]), String.valueOf(count - pes_packetlength))); scrambling_messaged = false; } } /** * vdr_dvbsub determination */ pes_extension2_id = CommonParsing.getExtension2_Id(pes_packet, pes_headerlength, pes_payloadlength, pesID, pes_isMpeg2, job_processing.getLastHeaderBytePosition()); isTeletext = false; subID = 0; if (pesID == CommonParsing.PRIVATE_STREAM_1_CODE && pes_payloadlength > 2) { offset = pes_headerlength + pes_extensionlength; if (offset < pes_packetlength) { subID = 0xFF & pes_packet[offset]; isTeletext = pes_extensionlength == 0x24 && subID>>>4 == 1; // vdr 1.5.x dvb-subs container if (pes_payloadlength >= 4 && subID>>>4 == 2) { tmp_value1 = CommonParsing.getIntValue(pes_packet, offset, 4, !CommonParsing.BYTEREORDERING); //vdr 1.5.x start packet of dvb-sub || subsequent packet if ((pes_alignment && (0xF0FFFFFF & tmp_value1) == 0x20010000) || (!pes_alignment && (0xF0FFFFFF & tmp_value1) == 0x20010001)) { for (int i = offset, j = offset + 4; i < j; i++) pes_packet[i] = (byte) 0xFF; pes_extensionlength += 4; pes_packet[8] = (byte)(pes_extensionlength); pes_payloadlength -= 4; //pes_extension2_id = 1; pes_extension2_id = subID = tmp_value1>>>24; pes_streamtype = CommonParsing.MPEG2PS_TYPE; //will be resetted before next packet if (pes_alignment) pes_packet[offset + 4] = (byte)(subID); } } //subpic in vdr_pes before 1.5.x if (pes_alignment && !isTeletext && (subID>>>4 == 2 || subID>>>4 == 3)) pes_streamtype = CommonParsing.MPEG2PS_TYPE; //will be resetted before next packet if (pes_streamtype != CommonParsing.MPEG1PS_TYPE && pes_streamtype != CommonParsing.MPEG2PS_TYPE && !isTeletext) subID = 0; //disables LPCM too } else if (pes_streamtype != CommonParsing.MPEG1PS_TYPE) //? { pes_extensionlength = pes_payloadlength - 3; pes_packet[8] = (byte)(pes_extensionlength); } /** * packet buffering esp. of subpics from vdr or other pes */ if (pes_extension2_id != -1) { String str = String.valueOf(pes_extension2_id); offset = pes_headerlength + pes_extensionlength; if ( !substreams.containsKey(str)) substreams.put(str, new StandardBuffer()); sb = (StandardBuffer) substreams.get(str); // buffer raw packet data if (!pes_alignment) { sb.write(pes_packet, offset, pes_packetlength - offset); continue zeropacketloop; } // start packet, buffer this and get last completed packet else { buffered_data = sb.getData(); sb.reset(); sb.write(pes_packet, 0, pes_packetlength); if (buffered_data == null || buffered_data.length < 10) continue zeropacketloop; pes_packetlength = buffered_data.length; if (pes_packetlength > 0x10005) { Common.setMessage("!> sub packet too long: 0x" + Integer.toHexString(pesID).toUpperCase() + " /ext2_id " + pes_extension2_id); pes_packetlength = 0x10005; } pes_payloadlength = pes_packetlength - pes_packetoffset; System.arraycopy(buffered_data, 0, pes_packet, 0, pes_packetlength); CommonParsing.setPES_LengthField(pes_packet, 0, pes_payloadlength); buffered_data = null; } } } /** * pesID, subID inclusion */ if (usePidfilter) { if (Arrays.binarySearch(include, pesID) < 0 && Arrays.binarySearch(include, subID) < 0) continue zeropacketloop; } /** * raw id filter extraction */ if (action == CommonParsing.ACTION_FILTER) { if (subID != 0) pes_packet[6] |= 4; //set alignment streamconverter.write(job_processing, pes_packet, 0, pes_packetlength, null, job_processing.getCutByteposition(), CommonParsing.isInfoScan(), CutpointList); continue zeropacketloop; } foundObject = false; /** * find ID object */ for (int i = 0; i < demuxList.size(); i++) { streamdemultiplexer = (StreamDemultiplexer) demuxList.get(i); foundObject = pesID == streamdemultiplexer.getID() && subID == streamdemultiplexer.subID() && isTeletext == streamdemultiplexer.isTTX(); if (foundObject) break; } /** * create new ID object */ if (!foundObject) { /** * dump startpacket */ if (DumpDroppedGop) { String dumpname = fparent + "(" + Integer.toHexString(pesID) + "-" + Integer.toHexString(subID) + "#" + (dumped_packets++) + "@" + (count - pes_packetlength) + ").bin"; FileOutputStream dump = new FileOutputStream(dumpname); dump.write(pes_packet, 0, pes_packetlength); dump.flush(); dump.close(); Common.setMessage(Resource.getString("parsePrimaryPES.dump.1st") + ": " + dumpname); } String IDtype = ""; switch (0xF0 & pesID) { case 0xE0: IDtype = Resource.getString("idtype.mpeg.video"); streamdemultiplexer = new StreamDemultiplexer(collection, ptsoffset); streamdemultiplexer.setID(pesID); streamdemultiplexer.setType(CommonParsing.MPEG_VIDEO); streamdemultiplexer.setnewID(newID[CommonParsing.MPEG_VIDEO]++); streamdemultiplexer.setsubID(0); streamdemultiplexer.setStreamType(pes_streamtype); demuxList.add(streamdemultiplexer); if (pesID0 == 0 || pesID0 == pesID) { if (action == CommonParsing.ACTION_DEMUX) streamdemultiplexer.initVideo(collection, fparent, MainBufferSize, demuxList.size(), CommonParsing.PRIMARY_PES_PARSER); else IDtype += " " + Resource.getString("idtype.mapped.to") + Integer.toHexString(streamdemultiplexer.getnewID()).toUpperCase(); pesID0 = pesID; } else IDtype += Resource.getString("idtype.ignored"); break; case 0xC0: case 0xD0: IDtype = Resource.getString("idtype.mpeg.audio"); streamdemultiplexer = new StreamDemultiplexer(collection, ptsoffset); streamdemultiplexer.setID(pesID); streamdemultiplexer.setType(CommonParsing.MPEG_AUDIO); streamdemultiplexer.setnewID(newID[CommonParsing.MPEG_AUDIO]++); streamdemultiplexer.setsubID(0); streamdemultiplexer.setStreamType(pes_streamtype); demuxList.add(streamdemultiplexer); if (action == CommonParsing.ACTION_DEMUX) streamdemultiplexer.init(collection, fparent, MainBufferSize / demuxList.size(), demuxList.size(), CommonParsing.PRIMARY_PES_PARSER); else IDtype += " " + Resource.getString("idtype.mapped.to") + Integer.toHexString(streamdemultiplexer.getnewID()).toUpperCase(); break; } switch (pesID) { case CommonParsing.PRIVATE_STREAM_1_CODE: IDtype = Resource.getString("idtype.private.stream"); IDtype += (isTeletext ? " TTX " : "") + (subID != 0 ? " (SubID 0x" + Integer.toHexString(subID).toUpperCase() + ")" : ""); streamdemultiplexer = new StreamDemultiplexer(collection, ptsoffset); streamdemultiplexer.setID(pesID); streamdemultiplexer.setsubID(subID); streamdemultiplexer.setTTX(isTeletext); if (isTeletext) { streamdemultiplexer.setnewID(newID[CommonParsing.TELETEXT]++); streamdemultiplexer.setType(CommonParsing.TELETEXT); } else { switch(subID>>>4) { case 0: if (pes_streamtype != CommonParsing.MPEG1PS_TYPE && pes_streamtype != CommonParsing.MPEG2PS_TYPE) { streamdemultiplexer.setnewID(newID[CommonParsing.AC3_AUDIO]++); streamdemultiplexer.setType(CommonParsing.AC3_AUDIO); } break; case 8: streamdemultiplexer.setnewID(newID[CommonParsing.AC3_AUDIO]++); streamdemultiplexer.setType(CommonParsing.AC3_AUDIO); break; case 0xA: streamdemultiplexer.setnewID(newID[CommonParsing.LPCM_AUDIO]++); streamdemultiplexer.setType(CommonParsing.LPCM_AUDIO); break; case 2: case 3: streamdemultiplexer.setnewID(newID[CommonParsing.SUBPICTURE]++); streamdemultiplexer.setType(CommonParsing.SUBPICTURE); break; default: streamdemultiplexer.setType(CommonParsing.UNKNOWN); } } streamdemultiplexer.setStreamType(pes_streamtype); demuxList.add(streamdemultiplexer); if (action == CommonParsing.ACTION_DEMUX) { switch (streamdemultiplexer.getType()) { case CommonParsing.AC3_AUDIO: case CommonParsing.DTS_AUDIO: case CommonParsing.TELETEXT: case CommonParsing.SUBPICTURE: case CommonParsing.LPCM_AUDIO: streamdemultiplexer.init(collection, fparent, MainBufferSize / demuxList.size(), demuxList.size(), CommonParsing.PRIMARY_PES_PARSER); break; default: IDtype += Resource.getString("idtype.ignored"); } } else { if (pes_streamtype != CommonParsing.MPEG1PS_TYPE && pes_streamtype != CommonParsing.MPEG2PS_TYPE) IDtype += " " + Resource.getString("idtype.mapped.to") + Integer.toHexString(streamdemultiplexer.getnewID()).toUpperCase(); else if (isTeletext || subID>>>4 == 8) IDtype += " " + Resource.getString("idtype.mapped.to") + Integer.toHexString(streamdemultiplexer.getnewID()).toUpperCase(); else IDtype += Resource.getString("idtype.ignored"); } if (action == CommonParsing.ACTION_TO_VDR) { if ((pes_streamtype == CommonParsing.MPEG1PS_TYPE || pes_streamtype == CommonParsing.MPEG2PS_TYPE) && subID>>>4 != 8) IDtype += Resource.getString("idtype.ignored"); } break; } Common.setMessage(Resource.getString("parsePrimaryPES.found.pesid") + Integer.toHexString(pesID).toUpperCase() + " " + IDtype + " @ " + job_processing.getCutByteposition()); } if (!streamdemultiplexer.StreamEnabled()) continue zeropacketloop; /** * packet to streamdemultiplexer */ if (action == CommonParsing.ACTION_DEMUX) { if (streamdemultiplexer.getType() == CommonParsing.MPEG_VIDEO) { if (pesID0 != streamdemultiplexer.getID()) continue zeropacketloop; streamdemultiplexer.writeVideo(job_processing, pes_packet, 0, pes_packetlength, true, CutpointList, ChapterpointList); } else streamdemultiplexer.write(job_processing, pes_packet, 0, pes_packetlength, true); if (streamdemultiplexer.getPTS() > lastpts) lastpts = streamdemultiplexer.getPTS(); } /** * packet to streamconverter */ else streamconverter.write(job_processing, pes_packet, streamdemultiplexer, job_processing.getCutByteposition(), CommonParsing.isInfoScan(), CutpointList); } while (isZeroPacket); if (action != CommonParsing.ACTION_DEMUX) job_processing.setLastHeaderBytePosition(count); /** * split size reached */ if (job_processing.getSplitSize() > 0 && job_processing.getSplitSize() < job_processing.getAllMediaFilesExportLength()) break loop; } if (job_processing.getSplitSize() > 0 && job_processing.getSplitSize() < job_processing.getAllMediaFilesExportLength()) break bigloop; /** * next file segment */ if (job_processing.getFileNumber() < collection.getPrimaryInputFileSegments() - 1) { in.close(); //System.gc(); if (collection.getSettings().getBooleanProperty(Keys.KEY_Input_concatenateForeignRecords) && action == CommonParsing.ACTION_DEMUX) { ptsoffset = nextFilePTS(collection, CommonParsing.PRIMARY_PES_PARSER, pes_streamtype, lastpts, job_processing.getFileNumber() + 1); if (ptsoffset == -1) ptsoffset = 0; else { for (int i = 0; i < demuxList.size(); i++) { streamdemultiplexer = (StreamDemultiplexer) demuxList.get(i); streamdemultiplexer.PTSOffset(ptsoffset); if (streamdemultiplexer.getID() == pesID0) // ?? streamdemultiplexer.resetVideo(); } job_processing.setSequenceHeader(true); job_processing.setNewVideoStream(true); // job_processing.addCellTime(String.valueOf(job_processing.getExportedVideoFrameNumber())); } } XInputFile nextXInputFile = (XInputFile) collection.getInputFile(job_processing.countFileNumber(+1)); count = size; base = count; size += nextXInputFile.length(); in = new PushbackInputStream(nextXInputFile.getInputStream(), 0x10010); Common.setMessage(Resource.getString("parsePrimaryPES.actual.written") + " " + job_processing.getExportedVideoFrameNumber()); Common.setMessage(Resource.getString("parsePrimaryPES.switch") + " " + nextXInputFile + " (" + Common.formatNumber(nextXInputFile.length()) + " bytes) @ " + base); Common.updateProgressBar((action == CommonParsing.ACTION_DEMUX ? Resource.getString("parsePrimaryPES.demuxing") : Resource.getString("parsePrimaryPES.converting")) + " " + Resource.getString("parsePrimaryPES.avpes.file") + " " + nextXInputFile.getName()); } else break bigloop; } /** * file end reached for split */ if ( (count >= size || ende) && job_processing.getSplitSize() > 0 ) job_processing.setSplitLoopActive(false); in.close(); vptslog = processElementaryStreams(vptslog, action, clv, collection, job_processing); } catch (IOException e2) { Common.setExceptionMessage(e2); } return vptslog; } }