/*
* @(#)CommonParsing
*
* Copyright (c) 2005-2009 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.IOException;
import java.io.File;
import java.io.RandomAccessFile;
import java.io.PrintWriter;
import java.io.FileOutputStream;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.ArrayList;
import java.util.List;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import net.sourceforge.dvb.projectx.common.Resource;
import net.sourceforge.dvb.projectx.common.Settings;
import net.sourceforge.dvb.projectx.common.Common;
import net.sourceforge.dvb.projectx.common.Keys;
import net.sourceforge.dvb.projectx.common.JobProcessing;
/**
* common stuff for parsing functions
*/
public class CommonParsing extends Object {
public final static boolean BYTEREORDERING = true;
public final static int SECONDARY_PES_PARSER = 0;
public final static int PRIMARY_PES_PARSER = 1;
public final static int TS_PARSER = 2;
public final static int PVA_PARSER = 3;
public final static int ES_VIDEO_PARSER = 4;
public final static int ES_AUDIO_PARSER = 5;
public final static int ES_SUBPICTURE_PARSER = 6;
//max 31, more defined by a subtype
public final static int Unsupported = 0; // "unsupported"
public final static int PES_AV_TYPE = 1; // "PES (Video/Audio/TTX)"
public final static int MPEG1PS_TYPE = 2; // "MPEG-1 PS/SS (Video/Audio PES)"
public final static int MPEG2PS_TYPE = 3; // "MPEG-2 PS/SS (Video/Audio PES)"
public final static int PVA_TYPE = 4; // "PVA (Video/Audio PES)"
public final static int TS_TYPE = 5; // "DVB/MPEG2 TS"
public final static int PES_MPA_TYPE = 6; // "PES (MPEG Audio)"
public final static int PES_PS1_TYPE = 7; // "PES (private stream 1)"
public final static int ES_MPV_TYPE = 8; // "ES (MPEG Video)"
public final static int ES_MPA_TYPE = 9; // "ES (MPEG Audio)"
public final static int ES_AC3_TYPE = 10; // "ES (AC-3 Audio)"
public final static int ES_AC3_A_TYPE = 11; // "ES (AC-3 Audio) (psb. SMPTE)"
public final static int ES_DTS_TYPE = 12; // "ES (DTS Audio)"
public final static int ES_DTS_A_TYPE = 13; // "ES (DTS Audio) (psb. SMPTE)"
public final static int ES_RIFF_TYPE = 14; // "ES (RIFF Audio)"
public final static int ES_cRIFF_TYPE = 15; // "ES (compressed RIFF Audio)"
public final static int ES_SUP_TYPE = 16; // "ES (Subpicture 2-bit RLE)"
public final static int PJX_PTS_TYPE = 31; // "PjX PTS File"
public final static int ES_TYPE = 1; // "ElementaryStream"
public final static int TS_TYPE_TF5X00 = TS_TYPE | 1<<8; // "DVB/MPEG2 TS TF5X00"
public final static int TS_TYPE_TF5X00C = TS_TYPE | 2<<8; // "DVB/MPEG2 TS TF5X00C"
public final static int TS_TYPE_TF4000 = TS_TYPE | 3<<8; // "DVB/MPEG2 TS TF4000"
public final static int TS_TYPE_HANDAN = TS_TYPE | 4<<8; // "DVB/MPEG2 TS HANDAN"
public final static int TS_TYPE_192BYTE = TS_TYPE | 5<<8; // "DVB/MPEG2 TS 192b"
public final static int TS_TYPE_COMAG = TS_TYPE | 6<<8; // "DVB/MPEG2 TS COMAG"
// "ElementaryStream"
public final static int UNKNOWN = -1;
public final static int AC3_AUDIO = 0;
public final static int TELETEXT = 1;
public final static int MPEG_AUDIO = 2;
public final static int MPEG_VIDEO = 3;
public final static int LPCM_AUDIO = 4;
public final static int SUBPICTURE = 5;
public final static int DTS_AUDIO = 6; //handled with in AC3_AUDIO so far
public final static int WAV_AUDIO = 7;
public final static int AAC_AUDIO = 8;
public final static int ACTION_UNDEFINED = -1;
public final static int ACTION_DEMUX = 0;
public final static int ACTION_TO_VDR = 1;
public final static int ACTION_TO_M2P = 2;
public final static int ACTION_TO_PVA = 3;
public final static int ACTION_TO_TS = 4;
public final static int ACTION_FILTER = 5;
public final static int ACTION_COPY = 6;
public final static int CUTMODE_BYTE = 0;
public final static int CUTMODE_GOP = 1;
public final static int CUTMODE_FRAME = 2;
public final static int CUTMODE_PTS = 3;
public final static int CUTMODE_TIME = 4;
public final static int PICTURE_START_CODE = 0;
public final static int SLICE_START_CODE_MIN = 1;
public final static int SLICE_START_CODE_MAX = 0xAF;
public final static int USER_DATA_START_CODE = 0xB2;
public final static int SEQUENCE_HEADER_CODE = 0xB3;
public final static int EXTENSION_START_CODE = 0xB5;
public final static int SEQUENCE_END_CODE = 0xB7;
public final static int GROUP_START_CODE = 0xB8;
public final static int SYSTEM_END_CODE = 0xB9;
public final static int PACK_START_CODE = 0xBA;
public final static int SYSTEM_START_CODE = 0xBB;
public final static int PROGRAM_STREAM_MAP_CODE= 0xBC;
public final static int PRIVATE_STREAM_1_CODE = 0xBD;
public final static int PADDING_STREAM_CODE = 0xBE;
public final static int PRIVATE_STREAM_2_CODE = 0xBF;
public final static int ECM_STREAM_CODE = 0xF0;
public final static int EMM_STREAM_CODE = 0xF1;
public final static int DSM_CC_STREAM_CODE = 0xF2;
public final static int FRAME_I_TYPE = 1;
public final static int FRAME_P_TYPE = 2;
public final static int FRAME_B_TYPE = 3;
public final static int FRAME_D_TYPE = 4;
public final static int MAX_BITRATE_VALUE = 262143; //3FFFF *400 = 104857200 bps
public final static int MAX_SD_BITRATE_VALUE = 37500; // *400 = 15000000 bps
public static byte[] PTSVideoHeader = { 0x50, 0x4A, 0x58, 0x5F, 0x50, 0x54, 0x53, 0x56, 0x49, 0x44, 0x31, 0x30, 0x30, 0, 0, 0 }; //'PJX_PTSVID100'
private static int Pva_PidToExtract = -1;
private static boolean Pva_PidExtraction = false;
private static boolean InfoScan = false;
private static boolean qbreak = false;
private static boolean qpause = false;
private static boolean _bool = false;
private static int _cutcount = 0;
private static double _videoframerate = 3600.0;
private static long AudioProcessingFlags = 0;
private CommonParsing()
{}
/**
*
*/
public static boolean isInfoScan()
{
return InfoScan;
}
/**
*
*/
public static void setInfoScan(boolean b)
{
InfoScan = b;
}
/**
*
*/
public static boolean isProcessCancelled()
{
return qbreak;
}
/**
*
*/
public static void setProcessCancelled(boolean b)
{
qbreak = b;
}
/**
*
*/
public static boolean isProcessPausing()
{
return qpause;
}
/**
*
*/
public static void setProcessPausing(boolean b)
{
qpause = b;
}
/**
*
*/
public static long getAudioProcessingFlags()
{
return AudioProcessingFlags;
}
/**
*
*/
public static void setAudioProcessingFlags(long val)
{
AudioProcessingFlags = val;
}
/**
*
*/
public static double getVideoFramerate()
{
return _videoframerate;
}
/**
*
*/
public static void setVideoFramerate(double val)
{
_videoframerate = val;
}
/**
*
*/
public static int getCutCounter()
{
return _cutcount;
}
/**
*
*/
public static void setCutCounter(int val)
{
_cutcount = val;
}
/**
*
*/
public static boolean getCutStatus()
{
return _bool;
}
/**
*
*/
public static void setCutStatus(boolean b)
{
_bool = b;
}
/**
*
*/
public static boolean getPvaPidExtraction()
{
return Pva_PidExtraction;
}
/**
*
*/
public static void setPvaPidExtraction(boolean b)
{
Pva_PidExtraction = b;
}
/**
*
*/
public static int getPvaPidToExtract()
{
return Pva_PidToExtract;
}
/**
*
*/
public static void setPvaPidToExtract(int val)
{
Pva_PidToExtract = val;
}
/**
* returns pts value from pes_extension
*
* @param1 - source array
* @param2 - array offset
* @return - pts
*/
public static long getPTSfromBytes(byte[] array, int offset)
{
return getPTSfromBytes(array, offset, true);
}
/**
* returns pts value from pes_extension
*
* @param1 - source array
* @param2 - array offset
* @param3 - trim to positive 32bit value
* @return - pts
*/
public static long getPTSfromBytes(byte[] array, int offset, boolean trim)
{
long pts = (6 & array[offset])<<29 |
(0xFF & array[offset + 1])<<22 |
(0xFE & array[offset + 2])<<14 |
(0xFF & array[offset + 3])<<7 |
(0xFE & array[offset + 4])>>>1;
if (trim)
pts &= 0xFFFFFFFFL;
return pts;
}
/**
* returns pts value from pes_extension
*
* @param1 - source array
* @param2 - array offset
* @param3 - trim to positive 32bit value
* @return - pts
*/
public static long readPTS(byte[] array, int offset, int length, boolean bytereordering, boolean trim)
{
long value = getValue(array, offset, length, bytereordering);
if (trim)
value &= 0xFFFFFFFFL;
return value;
}
/**
*
*/
public static void setValue(byte[] array, int offset, int length, boolean bytereordering, long value)
{
for (int i = 0; bytereordering && i < length; i++)
array[i + offset] = (byte)(0xFFL & (value>>>(i * 8)));
for (int i = 0, j = length - 1; !bytereordering && i < length; i++, j--)
array[i + offset] = (byte)(0xFFL & (value>>>(j * 8)));
}
/**
* returns value
*
* @param1 - source array
* @param2 - array offset
* @param3 -
* @return -
*/
public static long getValue(byte[] array, int offset, int length, boolean bytereordering)
{
long value = 0;
try {
for (int i = 0; bytereordering && i < length; i++)
value |= (0xFFL & array[i + offset])<<(i * 8);
for (int i = 0, j = length - 1; !bytereordering && i < length; i++, j--)
value |= (0xFFL & array[i + offset])<<(j * 8);
} catch (Exception e) {
Common.setMessage("!> array index error (" + offset + "/" + length + "/" + array.length + ")");
return 0;
}
return value;
}
public static int getIntValue(byte[] array, int offset, int length, boolean bytereordering)
{
return ((int) getValue(array, offset, length, bytereordering));
}
/**
*
*/
public static void setPES_PTSField(byte[] array, int offset, long value)
{
array[9 + offset] = (byte)(0x21 | (0xE & (value>>>29)));
array[10 + offset] = (byte)(0xFF & (value>>>22));
array[11 + offset] = (byte)(1 | (0xFE & (value>>>14)));
array[12 + offset] = (byte)(0xFF & (value>>>7));
array[13 + offset] = (byte)(1 | (0xFE & (value<<1)));
}
/**
*
*/
public static void setPES_LengthField(byte[] array, int offset, int value)
{
array[4 + offset] = (byte)(0xFF & value>>>8);
array[5 + offset] = (byte)(0xFF & value);
}
/**
*
*/
public static void setPES_IdField(byte[] array, int offset, int value)
{
array[3 + offset] = (byte)(0xFF & value);
}
/**
*
*/
public static void setPES_SubIdField(byte[] array, int offset, int pes_headerlength, int pes_extensionlength, int value)
{
array[pes_headerlength + pes_extensionlength + offset] = (byte)(0xFF & value);
}
/**
*
*/
public static int getPES_LengthField(byte[] array, int offset)
{
int value = (0xFF & array[4 + offset])<<8 | (0xFF & array[5 + offset]);
return value;
}
/**
*
*/
public static int getPES_IdField(byte[] array, int offset)
{
int value = 0xFF & array[3 + offset];
return value;
}
/**
*
*/
public static int getPES_ExtensionLengthField(byte[] array, int offset)
{
int value = 0xFF & array[8 + offset];
return value;
}
/**
*
*/
public static boolean clearBit33ofPTS(byte[] array, int offset)
{
if ((0x80 & array[7 + offset]) != 0)
{
array[9 + offset] &= ~8;
return true;
}
return false;
}
/**
*
*/
public static boolean clearBit33ofDTS(byte[] array, int offset)
{
if ((0x40 & array[7 + offset]) != 0)
{
array[9 + 5 + offset] &= ~8;
return true;
}
return false;
}
/**
*
*/
public static int nextBits(byte buffer[], int BitPos, int N)
{
int Pos, Val;
Pos = BitPos>>>3;
Val = (0xFF & buffer[Pos])<<24 |
(0xFF & buffer[Pos + 1])<<16 |
(0xFF & buffer[Pos + 2])<<8 |
(0xFF & buffer[Pos + 3]);
Val <<= BitPos & 7;
Val >>>= 32-N;
return Val;
}
/**
* check startcode
* return int of skip'able data (negative)
*/
public static int validateStartcode(byte[] pes_packet, int offset)
{
if (pes_packet[2 + offset] == 1)
{
if (pes_packet[1 + offset] == 0)
if (pes_packet[offset] == 0)
return 0;
}
else if (pes_packet[2 + offset] == 0)
{
if (pes_packet[1 + offset] == 0)
return -1;
else
return -2;
}
return -3;
}
/**
* check startcode
* return int of skip'able data (negative)
*/
public static int validateMp4Startcode(byte[] pes_packet, int offset)
{
if (pes_packet[3 + offset] == 1)
{
if (pes_packet[2 + offset] == 0)
if (pes_packet[1 + offset] == 0)
if (pes_packet[offset] == 0)
return 0;
}
else if (pes_packet[3 + offset] == 0)
{
if (pes_packet[2 + offset] == 0)
{
if (pes_packet[1 + offset] == 0)
return -1;
else
return -2;
}
else
return -3;
}
return -4;
}
/**
* skip leading bytes before first valid startcodes and return fixed array
*/
public static boolean alignSyncword(byte[] pes_packet, int pes_offset, int es_streamtype)
{
int pes_payloadlength = getPES_LengthField(pes_packet, pes_offset);
int pes_headerlength = 9;
int pes_packetlength = pes_headerlength - 3 + pes_payloadlength;
int pes_extensionlength = getPES_ExtensionLengthField(pes_packet, pes_offset);
int offset = pes_headerlength + pes_extensionlength;
int i, j, k;
boolean found = false;
packloop:
for (i = offset, j = pes_packetlength - 3, k = offset + pes_offset; i < j; i++, k++)
{
switch (es_streamtype)
{
case MPEG_VIDEO:
if (pes_packet[k] != 0 || pes_packet[1 + k] != 0 || pes_packet[2 + k] != 1 || pes_packet[3 + k] != (byte)SEQUENCE_HEADER_CODE)
continue packloop;
found = true;
break packloop;
case AC3_AUDIO:
case DTS_AUDIO:
if ((pes_packet[k] != 0xB || pes_packet[1 + k] != 0x77) && (pes_packet[k] != 0x7F || pes_packet[1 + k] != (byte)0xFE || pes_packet[2 + k] != (byte)0x80 || pes_packet[3 + k] != 1))
continue packloop;
found = true;
break packloop;
case MPEG_AUDIO:
if ( pes_packet[k] != (byte)0xFF || (0xF0 & pes_packet[1 + k]) != 0xF0)
continue packloop;
found = true;
break packloop;
}
}
if (found)
{
System.arraycopy(pes_packet, i + pes_offset, pes_packet, offset + pes_offset, pes_packetlength - i);
pes_payloadlength -= (i - offset);
setPES_LengthField(pes_packet, pes_offset, pes_payloadlength);
}
return found;
}
/**
* create PTS alias
*/
public static void logAlias(JobProcessing job_processing, String _vptslog, String _datalog)
{
File vpts = new File(_vptslog);
try {
RandomAccessFile log = new RandomAccessFile(_datalog, "rw");
log.seek(0);
if (vpts.exists() && vpts.length() > 0)
{
RandomAccessFile vlog = new RandomAccessFile(_vptslog, "r");
long p = vlog.readLong();
if (!job_processing.hasElementaryVideoStream() && job_processing.getSplitPart() == 0)
job_processing.setFirstAudioPts(p);
log.writeLong(job_processing.getFirstAudioPts() + (Common.getSettings().getBooleanProperty(Keys.KEY_additionalOffset) ? 90L * Common.getSettings().getIntProperty(Keys.KEY_ExportPanel_additionalOffset_Value) : 0));
vlog.close();
}
else
log.writeLong(0L + (Common.getSettings().getBooleanProperty(Keys.KEY_additionalOffset) ? Common.getSettings().getIntProperty(Keys.KEY_ExportPanel_additionalOffset_Value) : 0));
log.writeLong(0L);
log.close();
Common.setMessage("");
Common.setMessage(Resource.getString("all.msg.pts.faked"));
} catch (IOException e) {
Common.setExceptionMessage(e);
}
}
/**
* split reset
*/
public static void resetSplitMode(JobProcessing job_processing, String vptslog)
{
if ( vptslog.equals("-1") && job_processing.getSplitSize() > 0 )
{
job_processing.setSplitSize(0);
Common.setMessage(Resource.getString("splitreset.novideo"));
}
}
/**
* parse cut long value
*/
public static String parseCutValue(long value)
{
if (Common.getSettings().getIntProperty(Keys.KEY_CutMode) != CUTMODE_TIME)
return String.valueOf(value);
String str = "";
long frametime = 1;
value /= 90;
DateFormat time = new SimpleDateFormat("H:mm:ss:");
time.setTimeZone(TimeZone.getTimeZone("GMT+0:00"));
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("GMT+0:00"));
cal.setTime(new Date(value));
int frame = (cal.get(14) / ((int)frametime));
str = time.format(new Date(value)) + (frame < 10 ? "0" : "") + frame;
return str;
}
/**
* parse cut field value
*/
public static long parseCutValue(String value, boolean demux)
{
if (value == null)
return 0;
value = value.trim();
try {
if (Common.getSettings().getIntProperty(Keys.KEY_CutMode) != CUTMODE_TIME)
return Long.parseLong(value);
} catch (Exception e) {
return -1L;
}
int i;
if ( (i = value.indexOf(" ")) > -1)
value = value.substring(0, i);
value = value.replace('.',':');
if (value.indexOf(":") < 0)
return Long.parseLong(value);
StringTokenizer st = new StringTokenizer(value, ":");
String str = null;
long val = 0;
long frametime = !demux ? 90 : (long)_videoframerate;
long mp[] = { 324000000L, 5400000L, 90000L, frametime }; //h,m,s,f
for (int a=0; st.hasMoreTokens() && a < 4; a++)
{
str = st.nextToken();
val += (mp[a] * Long.parseLong(str));
}
return val;
}
/**
* video timelength read from ptslogfile
*/
public static long calcVideoTime(String logfile)
{
long vtime = 0;
try {
long vlogsize = new File(logfile).length();
RandomAccessFile vlog = new RandomAccessFile(logfile, "r");
vlog.seek(vlogsize - 8);
vtime = vlog.readLong();
vlog.close();
}
catch (IOException e) {
Common.setExceptionMessage(e);
}
return vtime;
}
/**
* make cut
*/
public static boolean makecut(JobProcessing job_processing, long comparePoint, List ctemp)
{
return makecut(job_processing, null, 0, comparePoint, new ArrayList(), 0, ctemp, 0, new ArrayList());
}
/**
* make cut
*/
public static boolean makecut(JobProcessing job_processing, String cuts_filename, long startPTS, long comparePoint, List newcut, int lastframes, List ctemp, int gopnumber, List cell)
{
if (ctemp.isEmpty())
return true;
long[] abc;
if ( _cutcount < ctemp.size() )
{
if ( comparePoint > parseCutValue(ctemp.get(_cutcount).toString(), true) )
{
/**
* ungerade == cutout
*/
if ((_cutcount & 1) == 1)
{
_bool = false;
for (int c = newcut.size() - 1; c >- 1; c--)
{
abc = (long[])newcut.get(c);
if ( abc[0] < parseCutValue(ctemp.get(_cutcount).toString(), true) )
{
_bool = true;
Common.setMessage(Resource.getString("msg.cuts.cutin", "" + gopnumber, "" + lastframes, "" + Common.formatTime_1((long)(lastframes * (double)(_videoframerate / 90.0f)) )) + " (" + comparePoint + ")");
saveCuts(comparePoint, startPTS, lastframes, cuts_filename);
// if (lastframes > 0)
// cell.add("" + lastframes); // celltimes for cutin
break;
}
}
if (!_bool)
{
Common.setMessage(Resource.getString("msg.cuts.cutout", "" + gopnumber) + " (" + comparePoint + ")");
saveCuts(comparePoint, startPTS, lastframes, cuts_filename);
}
_cutcount++;
return _bool;
}
/**
* gerade == cutin
*/
else
{
_bool = true;
_cutcount++;
Common.setMessage(Resource.getString("msg.cuts.cutin", "" + gopnumber, "" + lastframes, "" + Common.formatTime_1((long)(lastframes * (double)(_videoframerate / 90.0f)) )) + " (" + comparePoint + ")");
saveCuts(comparePoint, startPTS, lastframes, cuts_filename);
// if (lastframes > 0)
// cell.add("" + lastframes); // celltimes for cutin
if (_cutcount >= ctemp.size())
return _bool;
for (int c = newcut.size() - 1; c >- 1; c--)
{
abc = (long[])newcut.get(c);
if ( abc[0] < parseCutValue(ctemp.get(_cutcount).toString(), true) )
{
_cutcount++;
break;
}
}
return _bool;
}
}
}
else
{
if (!_bool && job_processing.getCutComparePoint() == 10000000)
job_processing.setCutComparePoint(comparePoint);
}
return _bool;
}
/**
* saves the cutpoint list from coll specials
*/
private static void saveCuts(long cutposition, long startPTS, long lastframes, String cuts_filename)
{
if ( Common.getSettings().getBooleanProperty(Keys.KEY_ExternPanel_exportPts) && cuts_filename != null)
{
try {
cuts_filename += ".Xpl";
PrintWriter pts_writer = new PrintWriter(new FileOutputStream(cuts_filename, lastframes > 0));
if (new File(cuts_filename).length() == 0)
pts_writer.println(Keys.KEY_CutMode[0] + "=3"); // PTS cut mode fixed for file
pts_writer.println(startPTS);
pts_writer.close();
Common.setMessage(Resource.getString("msg.savecut", "" + startPTS));
} catch (IOException e) {
Common.setExceptionMessage(e);
}
}
}
/**
* set 1. videoheader
*/
public static void setVideoHeader(JobProcessing job_processing, String videofile, String logfile, int[] clv, int[] MPGVideotype)
{
long time = 0;
String videotype[] = { "(m1v)", "(m2v)", "(h264)" };
String frames_used[] = {
Resource.getString("video.msg.io.non"),
Resource.getString("video.msg.io.int"),
Resource.getString("video.msg.io.pro"),
Resource.getString("video.msg.io.int_pro")
};
if (new File(logfile).exists())
{
time = (calcVideoTime(logfile) / 90);
String vt = Common.formatTime_1( time / 10 * 10 );
Common.setMessage(Resource.getString("video.msg.length", "" + job_processing.getExportedVideoFrameNumber()) + " " + vt);
Common.setMessage(Resource.getString("video.msg.gop.summary", "" + (0x7FFF & clv[9]>>>15), "" + (0x7FFF & clv[9]), "" + frames_used[clv[9]>>>30]));
if (clv[8] > 0)
Common.setMessage(Resource.getString("video.error.pts.same", "" + clv[8]));
job_processing.getSummaryInfo().add(Resource.getString("video.summary", videotype[MPGVideotype[0]], "" + job_processing.getExportedVideoFrameNumber(), "" + vt) + "'" + videofile + "'");
}
if (MPGVideotype[0] > 1) // h264 without modif.
{
Common.setMessage(Resource.getString("video.msg.bitrate.avg", "" + ((job_processing.getMinBitrate() + job_processing.getMaxBitrate()) / 2 * 400), "" + (job_processing.getMinBitrate() * 400) + "/" + (job_processing.getMaxBitrate() * 400)));
Common.setMessage(Resource.getString("msg.newfile") + " " + videofile);
return;
}
try {
RandomAccessFile pv2 = new RandomAccessFile(videofile, "rw");
if (Common.getSettings().getIntProperty(Keys.KEY_ChangeBitrateInAllSequences) > 0)
{
if (time == 0)
Common.setMessage(Resource.getString("video.msg.bitrate.avg", "" + ((job_processing.getMinBitrate() + job_processing.getMaxBitrate()) / 2 * 400), "" + (job_processing.getMinBitrate() * 400) + "/" + (job_processing.getMaxBitrate() * 400)));
else
Common.setMessage(Resource.getString("video.msg.bitrate.avgnom", "" + ((pv2.length() * 8000L) / time), "" + (job_processing.getMinBitrate() * 400) + "/" + (job_processing.getMaxBitrate() * 400)));
}
else if (Common.getSettings().getBooleanProperty(Keys.KEY_DebugLog))
System.out.println();
if (!Common.getSettings().getBooleanProperty(Keys.KEY_WriteOptions_writeVideo))
{
pv2.close();
return;
}
int max_bitrate_value = 22500; // 9.0Mbit, (video only)
/**
* bitraten
*/
if (Common.getSettings().getIntProperty(Keys.KEY_ChangeBitrateInFirstSequence) > 0)
{
int newmux = (Common.getSettings().getIntProperty(Keys.KEY_ChangeBitrateInFirstSequence) == 3) ? job_processing.getMaxBitrate() : max_bitrate_value;
if (Common.getSettings().getIntProperty(Keys.KEY_ChangeBitrateInFirstSequence) == 2 && job_processing.getMaxBitrate() < max_bitrate_value)
newmux = job_processing.getMaxBitrate();
if (Common.getSettings().getIntProperty(Keys.KEY_ChangeBitrateInFirstSequence) == 1)
{
if (time == 0)
newmux = (job_processing.getMinBitrate() + job_processing.getMaxBitrate()) / 2; // old calcul. avg.
else
{
newmux = (int)(((pv2.length() * 8000L) / time) / 400);
if (newmux < 0 || newmux > max_bitrate_value)
newmux = (job_processing.getMinBitrate() + job_processing.getMaxBitrate()) / 2; // old calcul. avg.
}
}
if (Common.getSettings().getIntProperty(Keys.KEY_ChangeBitrateInFirstSequence) == 4)
{
newmux = 0x3FFFF;
Common.setMessage(Resource.getString("video.msg.bitrate.vbr"));
}
else
Common.setMessage(Resource.getString("video.msg.bitrate.val", "" + (newmux*400)));
pv2.seek(8);
newmux = (newmux<<14) | ((pv2.readInt()<<18)>>>18);
pv2.seek(8);
pv2.writeInt(newmux);
}
/**
* patch resolution DVD-conform
*/
//JLA14082003+
//0: no patch, 1:patch unconditionally, 2:patch if <>720|352, 3:pach if <>720|704|352
if (Common.getSettings().getIntProperty(Keys.KEY_ConditionalHorizontalPatch) != 0)
{
pv2.seek(4);
int resolutionOrig = pv2.readInt();
int hresOrg = (resolutionOrig>>>20);
int resolution = (0xFFFFF & resolutionOrig) | Common.getSettings().getIntProperty(Keys.KEY_ConditionalHorizontalResolution)<<20;
boolean doPatch;
switch (Common.getSettings().getIntProperty(Keys.KEY_ConditionalHorizontalPatch))
{
case 2:
doPatch = hresOrg != 720 && hresOrg != 352;
break;
case 3:
doPatch = hresOrg != 720 && hresOrg != 704 && hresOrg != 352;
break;
default:
doPatch = true;
}
if(doPatch)
{
pv2.seek(4);
pv2.writeInt(resolution);
Common.setMessage(Resource.getString("video.msg.resolution", "" + (resolutionOrig>>>20)+"*"+((0xFFF00&resolutionOrig)>>>8)) + " " + (resolution>>>20)+"*"+((0xFFF00&resolution)>>>8));
}
}
//JLA14082003-
pv2.close();
Common.setMessage(Resource.getString("msg.newfile") + " " + videofile);
} catch (IOException e) {
Common.setExceptionMessage(e);
}
}
/**
* vdr_dvbsub determination
*/
public static int getExtension2_Id(byte[] pes_packet, int pes_headerlength, int pes_payloadlength, int pesID, boolean pes_isMpeg2, long file_position)
{
boolean extension_error = false;
int pes_extension2_id = -1;
if (!pes_isMpeg2)
return pes_extension2_id;
else if (pesID != PRIVATE_STREAM_1_CODE && (0xE0 & pesID) != 0xC0 && (0xF0 & pesID) != 0xE0) //not pD, Aud, Vid
return pes_extension2_id;
//read flags
int pes_shift = pes_headerlength; //points to 1st appendix
pes_shift += (0x80 & pes_packet[7]) != 0 ? 5 : 0; //pes_pts
pes_shift += (0x40 & pes_packet[7]) != 0 ? 5 : 0; //pes_dts
pes_shift += (0x20 & pes_packet[7]) != 0 ? 6 : 0; //pes_escr
pes_shift += (0x10 & pes_packet[7]) != 0 ? 3 : 0; //pes_esrate
pes_shift += (4 & pes_packet[7]) != 0 ? 1 : 0; //pes_copy
pes_shift += (2 & pes_packet[7]) != 0 ? 2 : 0; //pes_crc
boolean pes_ext1 = (1 & pes_packet[7]) != 0; //ext1
boolean pes_ext2 = false; //ext2
int pes_extension_length = 0xFF & pes_packet[8]; //all data must be inside extension
if (pes_headerlength + pes_extension_length < pes_shift)
extension_error = true;
else if (pes_ext1 && pes_headerlength + pes_extension_length < pes_shift + 1)
extension_error = true;
else if (pes_ext1)
{
int shift = pes_shift;
if (6 + pes_payloadlength < pes_shift + 1)
extension_error = true;
else
{
pes_shift += (0x80 & pes_packet[shift]) != 0 ? 16 : 0; //pes_private
pes_shift += (0x40 & pes_packet[shift]) != 0 ? 1 : 0; //pes_packfield
pes_shift += (0x20 & pes_packet[shift]) != 0 ? 2 : 0; //pes_sequ_counter
pes_shift += (0x10 & pes_packet[shift]) != 0 ? 2 : 0; //pes_P-STD
// marker 3 bits
pes_ext2 = (1 & pes_packet[shift]) != 0; //ext2
pes_shift++; //skip flag_fields of ext1
if (pes_headerlength + pes_extension_length < pes_shift)
extension_error = true;
else if (pes_ext2)
{
int pes_ext2_length = 0x7F & pes_packet[pes_shift];
pes_shift++; //skip length_fields of ext2
if (6 + pes_payloadlength < pes_shift + pes_ext2_length)
extension_error = true;
else if (pes_headerlength + pes_extension_length < pes_shift + pes_ext2_length)
extension_error = true;
else if (pesID == PRIVATE_STREAM_1_CODE)
pes_extension2_id = 0xFF & pes_packet[pes_shift]; //read byte0 (res.) of ext2
}
}
}
if (extension_error)
Common.setMessage("!> error in pes_extension of pes-ID 0x" + Integer.toHexString(pesID).toUpperCase() + " @ pos: " + file_position + " (" + (6 + pes_payloadlength) + " / " + (pes_headerlength + pes_extension_length) + " / " + (pes_shift + 1) + " / " + pes_ext1 + " / " + pes_ext2 + ")");
return pes_extension2_id;
}
}