/*
* @(#)StreamProcessBase
*
* 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.File;
import java.io.InputStream;
import java.io.IOException;
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.xinput.XInputFile;
import net.sourceforge.dvb.projectx.parser.CommonParsing;
/**
* main thread
*/
public class StreamProcessBase extends Object {
public int ERRORCODE = 0;
public int MainBufferSize = 8192000;
public static double sync_value_1;
public static double sync_value_2;
public static double sync_value_3;
public static double sync_value_4;
/**
*
*/
public StreamProcessBase()
{
init();
}
/**
*
*/
public void init()
{
MainBufferSize = Integer.parseInt(Common.getSettings().getProperty(Keys.KEY_MainBuffer));
if (MainBufferSize <= 0)
MainBufferSize = 4096000;
}
/**
*
*/
public boolean pause()
{
return Common.waitingMainProcess();
}
/**
*
*/
public String FramesToTime(int framenumber, double framelength)
{
return String.valueOf(Math.round(framenumber * framelength / 90.0));
}
/**
* pts value to time value
*/
public String formatFrameTime(double time_value)
{
return Common.formatTime_1((long) (time_value / 90.0));
}
/**
* loadTempVideoPts
*/
public long[][] loadTempVideoPts(String videofile_pts, boolean debug)
{
if (videofile_pts.equals("-1"))
return null;
if (debug)
System.out.println("-> loading video PTS logfile...");
XInputFile xInputFile = new XInputFile(new File(videofile_pts));
int vlogsize = ((int)xInputFile.length() / 16) - 1;
long[][] vptsval = new long[2][vlogsize];
byte[] data = new byte[(int)xInputFile.length() - 16];
int pos = 0;
int j = 0;
boolean reducedPts = Common.getCollection().getSettings().getBooleanProperty(Keys.KEY_Video_cutPts);
try {
InputStream pts_file = xInputFile.getInputStream();
pts_file.skip(16); //header
pts_file.read(data, 0, data.length);
for (int i = 0; i < vlogsize; i += 2 )
{
vptsval[0][j] = CommonParsing.getValue(data, pos, 8, !CommonParsing.BYTEREORDERING);
pos += 8;
vptsval[0][j + 1] = CommonParsing.getValue(data, pos, 8, !CommonParsing.BYTEREORDERING);
pos += 8;
vptsval[1][j] = CommonParsing.getValue(data, pos, 8, !CommonParsing.BYTEREORDERING);
pos += 8;
vptsval[1][j + 1] = CommonParsing.getValue(data, pos, 8, !CommonParsing.BYTEREORDERING);
pos += 8;
if (debug)
System.out.println("#s " + i + " _ " + j + " _ " + vptsval[0][j] + " #e " + (j + 1) + " _" + vptsval[0][j + 1] + " /#s " + i + " _" + vptsval[1][j] + " #e " + (j + 1) + " _" + vptsval[1][j + 1]);
// ignore equal time boundary
if (reducedPts && j > 0 && Math.abs(vptsval[0][j] - vptsval[0][j - 1]) < 3 && Math.abs(vptsval[1][j] - vptsval[1][j - 1]) < 3)
{
vptsval[0][j - 1] = vptsval[0][j + 1];
vptsval[1][j - 1] = vptsval[1][j + 1];
}
else
j += 2;
}
pts_file.close();
} catch (Exception e) {
Common.setExceptionMessage(e);
return null;
}
if (j > 0 && j < vlogsize)
{
long[][] vptsval2 = new long[2][j];
for (int i = 0; i < j; i++)
{
vptsval2[0][i] = vptsval[0][i];
vptsval2[1][i] = vptsval[1][i];
}
Common.setMessage("-> " + Resource.getString("video.msg.pts.start_end", Common.formatTime_1(vptsval2[0][0] / 90)) + " " + Common.formatTime_1(vptsval2[0][vptsval2[0].length - 1] / 90));
Common.setMessage("-> check sync at cut gaps only");
return vptsval2;
}
Common.setMessage("-> " + Resource.getString("video.msg.pts.start_end", Common.formatTime_1(vptsval[0][0] / 90)) + " " + Common.formatTime_1(vptsval[0][vptsval[0].length - 1] / 90));
return vptsval;
}
/**
* loadTempOtherPts
*/
public long[][] loadTempOtherPts(String filename_pts, String message_1, String message_2, String message_3, String message_4, int es_streamtype, boolean ignoreErrors, boolean debug)
{
if (filename_pts.equals("-1"))
return null;
if (debug)
System.out.println("-> loading PTS logfile...");
XInputFile xInputFile = new XInputFile(new File(filename_pts));
int logsize = (int)xInputFile.length() / 16;
long[][] ptsval = new long[2][logsize + 1];
ptsval[0][logsize] = -1;
ptsval[1][logsize] = -1;
int readbuffer = 512000; // 32000 indices 2*8
byte[] data = new byte[readbuffer];
int pos = 0;
try {
InputStream pts_file = xInputFile.getInputStream();
int aa = 0;
long ptsVal;
long ptsPos;
for (int a = 0; a < logsize; a++)
{
if (pos % readbuffer == 0)
{
pts_file.read(data, 0, readbuffer);
pos = 0;
}
ptsVal = CommonParsing.getValue(data, pos, 8, !CommonParsing.BYTEREORDERING);
pos += 8;
ptsPos = CommonParsing.getValue(data, pos, 8, !CommonParsing.BYTEREORDERING);
pos += 8;
if (debug)
System.out.println(" #" + aa + "/" + a + " _" + ptsVal + " / " + ptsPos);
if (aa > 0 && ptsVal <= ptsval[0][aa - 1])
{
if (aa > 1 && Math.abs(ptsVal - ptsval[0][aa - 2]) < 150000 && Math.abs(ptsVal - ptsval[0][aa - 1]) > 500000)
{
aa--;
if (debug)
System.out.print(" <!^> ");
}
else
{
if (debug)
System.out.print(" <!v> ");
continue;
}
}
ptsval[0][aa] = ptsVal;
ptsval[1][aa] = ptsPos;
aa++;
}
if (aa < logsize)
{
Common.setMessage(Resource.getString(message_1, " " + (logsize - aa)));
long tmp[][] = new long[2][aa];
System.arraycopy(ptsval[0], 0, tmp[0], 0, aa);
System.arraycopy(ptsval[1], 0, tmp[1], 0, aa);
ptsval[0] = new long[aa + 1];
System.arraycopy(tmp[0], 0, ptsval[0], 0, aa);
ptsval[0][aa]= -1;
ptsval[1] = new long[aa + 1];
System.arraycopy(tmp[1], 0, ptsval[1], 0, aa);
ptsval[1][aa]= -1;
}
pts_file.close();
if (es_streamtype == CommonParsing.TELETEXT && ((ptsval[0][0] == 0xFFFFFFFFL) || (ptsval[0][0] == 0)))
{
// missing pts values
Common.setMessage(Resource.getString(message_4));
ignoreErrors = true;
}
if (ignoreErrors)
{
long[] tmp = { ptsval[0][0], ptsval[1][0] };
ptsval[0] = new long[2];
ptsval[0][0] = tmp[0];
ptsval[0][1]= - 1;
ptsval[1] = new long[2];
ptsval[1][0] = tmp[1];
ptsval[1][1]= - 1;
Common.setMessage(Resource.getString(message_2));
}
} catch (Exception e) {
Common.setExceptionMessage(e);
return null;
}
Common.setMessage("-> " + Resource.getString(message_3, Common.formatTime_1(ptsval[0][0] / 90)) + " " + Common.formatTime_1(ptsval[0][ptsval[0].length - 2] / 90));
return ptsval;
}
/**
*
*/
public int checkPTSMatch(long video_pts_values[], long data_pts_values[])
{
if (data_pts_values[0] < video_pts_values[0])
{
if (data_pts_values[data_pts_values.length - 2] < video_pts_values[0])
{
/**
* maybe does match later, jump just to end
*/
Common.setMessage(Resource.getString("checkpts.1st.latter"));
return (data_pts_values.length - 2);
}
else
{
/**
* maybe does match later, jump just to this position
*/
int end = data_pts_values.length - 1;
for (int i = 0; i < end; i++)
{
if (data_pts_values[i + 1] > video_pts_values[0])
return i;
}
return 0;
}
}
else
{
if (data_pts_values[0] >= video_pts_values[video_pts_values.length - 1])
{
Common.setMessage(Resource.getString("checkpts.last.ends"));
return -1;
}
/**
* does match anywhere, no pre-jump
*/
else
return 0;
}
}
/**
*
*/
public String infoPTSMatch(String filename_pts, String videofile_pts, boolean video_pts, boolean data_pts)
{
if ( !videofile_pts.equals("-1") && !filename_pts.equals("-1") && !video_pts && data_pts)
return "? ";
else
return "";
}
/**
* synccheck A/V
*/
public boolean SyncCheck(int[] vw, double timecount, double frametimelength, long timeline, int writtenframes, long[] vptsval, long[] vtime, boolean awrite, boolean debug)
{
return SyncCheck(vw, timecount, frametimelength, timeline, writtenframes, vptsval, vtime, awrite, debug, "");
}
/**
* synccheck A/V
*/
public boolean SyncCheck(int[] vw, double timecount, double frametimelength, long timeline, int writtenframes, long[] vptsval, long[] vtime, boolean awrite, boolean debug, String src)
{
int v = vw[0];
int w = vw[1];
// w = gop end time index
if (w < vptsval.length)
{
sync_value_1 = (double)(timeline - vptsval[w + 1]);
sync_value_2 = (double)(timecount - vtime[w + 1]);
if (debug)
System.out.println("A " + src + " / " + awrite + "/" + v + "/" + w + "/ " + writtenframes + " #nve " + vtime[w + 1] + " /nae " + timecount + " #nvp " + vptsval[w + 1] + " /nap " + timeline + " /sy " + sync_value_2 + "/" + sync_value_1 + "/" + (sync_value_2 - sync_value_1));
// GOP ende �bereinstimmung <= halbe framel�nge, mit Timecode Diff Auswertung
// schreibpause setzen, n�chstes gop ende zur berechnung vormerken
if (Math.abs(sync_value_2) <= (frametimelength / 2.0))
{
awrite = false;
w += 2;
}
// GOP ende �bereinstimmung <= halbe framel�nge, mit PTS Diff Auswertung
// schreibpause setzen, n�chstes gop ende zur berechnung vormerken
else if (Math.abs(sync_value_1) <= (frametimelength / 2.0))
{
awrite = false;
w += 2;
}
if (debug)
System.out.println("B " + src + " / " + awrite + "/" + v + "/" + w);
}
// v = gop start time index
if (v < vptsval.length)
{
boolean show = false;
for (; !awrite && v < vptsval.length; v += 2)
{
sync_value_3 = (double)(timeline - vptsval[v]); // PTS Unterschied, frame start zu gop start
sync_value_4 = (double)(timecount - vtime[v]); // timecode Unterschied, frame start zu gop start
if (debug)
System.out.println("C " + awrite + "/" + v + "/" + w + "/ " + writtenframes + " #cve " + vtime[v] + " /cae " + timecount + " #cvp " + vptsval[v] + " /cap " + timeline + " /sy " + sync_value_4 + "/" + sync_value_3 + "/" + (sync_value_4 - sync_value_3));
// schreibpause, GOP start �bereinstimmung <= halbe framel�nge, mit PTS Diff Auswertung
// schreibpause aufheben, n�chsten gop start zur berechnung vormerken
if (!awrite && Math.abs(sync_value_3) <= (frametimelength / 2.0))
{
awrite = true;
show = true;
w = v;
v += 2;
break;
}
// schreibpause, GOP start �bereinstimmung <= halbe framel�nge, mit Timecode Diff + PTS Auswertung
// schreibpause aufheben, n�chsten gop start zur berechnung vormerken
else if (!awrite && Math.abs(Math.abs(sync_value_4) - Math.abs(sync_value_3)) <= (frametimelength / 2.0))
{
awrite = true;
show = true;
w = v; // eine Variable wuerde eigentlich auch reichen
v += 2;
break;
}
if (sync_value_3 < 0)
break;
}
if (debug)
System.out.println("D " + src + " / " + awrite + "/" + v + "/" + w);
// schreibmodus an, halbe framel�nge + pts start ist gr��er als n�chster gop start
// schreibpause
if (v < vptsval.length && awrite && (timecount + (frametimelength / 2.0)) > vtime[v] )
awrite = false;
if (debug)
System.out.println("E " + src + " / " + awrite + "/" + v + "/" + w);
if (show && awrite)
Common.getGuiInterface().showAVOffset("" + (int)(sync_value_3 / 90) + "/" + (int)(sync_value_4 / 90) + "/" + (int)((sync_value_4 - sync_value_3) / 90));
}
vw[0] = v;
vw[1] = w;
vw[2] = (int) (sync_value_2 - sync_value_1);
vw[3] = (int) (sync_value_4 - sync_value_3);
return awrite;
}
}