summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--command/Makefile2
-rw-r--r--command/audio.cpp120
-rw-r--r--command/audio.h10
-rw-r--r--command/audio_gain_analysis.cpp423
-rw-r--r--command/audio_gain_analysis.h102
-rw-r--r--command/demux.cpp1247
-rw-r--r--command/demux.h331
-rw-r--r--command/global.h30
-rw-r--r--command/markad-standalone.cpp477
-rw-r--r--command/markad-standalone.h11
-rw-r--r--command/marks.cpp1
-rw-r--r--command/pes2es.cpp102
-rw-r--r--command/pes2es.h96
-rw-r--r--command/queue.cpp504
-rw-r--r--command/queue.h161
-rw-r--r--command/ts2pkt.cpp224
-rw-r--r--command/ts2pkt.h140
-rw-r--r--command/video.cpp243
-rw-r--r--command/video.h66
19 files changed, 1827 insertions, 2463 deletions
diff --git a/command/Makefile b/command/Makefile
index 95d7da4..e1ab816 100644
--- a/command/Makefile
+++ b/command/Makefile
@@ -37,7 +37,7 @@ INCLUDES += -I..
### The object files (add further files here):
-OBJS = markad-standalone.o decoder.o marks.o streaminfo.o video.o audio.o audio_gain_analysis.o demux.o queue.o ts2pkt.o pes2es.o
+OBJS = markad-standalone.o decoder.o marks.o streaminfo.o video.o audio.o demux.o
### The main target:
diff --git a/command/audio.cpp b/command/audio.cpp
index 46fa57a..082010f 100644
--- a/command/audio.cpp
+++ b/command/audio.cpp
@@ -11,11 +11,6 @@
#include <stdlib.h>
#include <string.h>
-extern "C"
-{
-#include "debug.h"
-}
-
#include "audio.h"
cMarkAdAudio::cMarkAdAudio(MarkAdContext *maContext)
@@ -31,12 +26,21 @@ cMarkAdAudio::cMarkAdAudio(MarkAdContext *maContext)
cMarkAdAudio::~cMarkAdAudio()
{
- Clear();
ResetMark();
+ Clear();
+}
+
+void cMarkAdAudio::Clear()
+{
+ channels=0;
+ if (result.CommentBefore) free(result.CommentBefore);
+ if (result.CommentAfter) free(result.CommentAfter);
+ memset(&result,0,sizeof(result));
}
void cMarkAdAudio::ResetMark()
{
+ if (!mark.Type) return;
if (mark.Comment) free(mark.Comment);
mark.Comment=NULL;
mark.Position=0;
@@ -68,55 +72,6 @@ bool cMarkAdAudio::AddMark(int Type, int Position, const char *Comment)
return true;
}
-bool cMarkAdAudio::AnalyzeGain(int FrameNumber)
-{
- if (!macontext->Audio.Data.Valid) return false;
-
- int samples=macontext->Audio.Data.SampleBufLen/
- sizeof(*macontext->Audio.Data.SampleBuf)/
- macontext->Audio.Info.Channels;
-
- double left[samples];
- double right[samples];
-
- for (int i=0; i<samples; i++)
- {
- left[i]=macontext->Audio.Data.SampleBuf[0+(i*2)];
- right[i]=macontext->Audio.Data.SampleBuf[1+(i*2)];
- }
-
- if (FrameNumber!=lastframe_gain)
- {
- if ((lastframe_gain>0) && (audiogain.AnalyzedSamples()>=(3*samples)))
- {
- double gain = audiogain.GetGain();
- printf("%05i %+.2f db\n",lastframe_gain,gain);
- }
- audiogain.Init(macontext->Audio.Info.SampleRate);
- lastframe_gain=-1;
- }
-
- if (audiogain.AnalyzeSamples(left,right,samples,2)!=GAIN_ANALYSIS_OK)
- {
- lastframe_gain=-1;
- return false;
- }
- else
- {
- lastframe_gain=FrameNumber;
- }
- return true;
-}
-
-void cMarkAdAudio::Clear()
-{
- channels=0;
- lastframe_gain=-1;
- if (result.CommentBefore) free(result.CommentBefore);
- if (result.CommentAfter) free(result.CommentAfter);
- memset(&result,0,sizeof(result));
-}
-
bool cMarkAdAudio::ChannelChange(int a, int b)
{
if ((a==0) || (b==0)) return false;
@@ -124,24 +79,6 @@ bool cMarkAdAudio::ChannelChange(int a, int b)
return false;
}
-MarkAdPos *cMarkAdAudio::Process2ndPass(int FrameNumber)
-{
- if (!FrameNumber) return NULL;
-#if 0
- if (AnalyzeGain(FrameNumber))
- {
- if (result.CommentBefore) free(result.CommentBefore);
- if (asprintf(&result.CommentBefore,"audio silence detection (%i)",FrameNumber)==-1)
- {
- result.CommentBefore=NULL;
- }
- result.FrameNumberBefore=FrameNumber;
- return &result;
- }
-#endif
- return NULL;
-}
-
MarkAdMark *cMarkAdAudio::Process(int FrameNumber, int FrameNumberNext)
{
if ((!FrameNumber) || (!FrameNumberNext)) return NULL;
@@ -155,38 +92,33 @@ MarkAdMark *cMarkAdAudio::Process(int FrameNumber, int FrameNumberNext)
snprintf(buf,255,"audio channel change from %i to %i (", channels,
macontext->Audio.Info.Channels);
- if (macontext->Info.Channels)
+ if (macontext->Audio.Info.Channels>2)
{
- if (macontext->Info.Channels==macontext->Audio.Info.Channels)
- {
- char nbuf[20];
- snprintf(nbuf,sizeof(nbuf),"%i)*",FrameNumberNext);
- nbuf[19]=0;
- strcat(buf,nbuf);
- AddMark(MT_CHANNELSTART,FrameNumberNext,buf);
- }
- else
- {
- char nbuf[20];
- snprintf(nbuf,sizeof(nbuf),"%i)",framelast);
- nbuf[19]=0;
- strcat(buf,nbuf);
- AddMark(MT_CHANNELSTOP,framelast,buf);
- }
+ char nbuf[20];
+ snprintf(nbuf,sizeof(nbuf),"%i)*",FrameNumberNext);
+ nbuf[19]=0;
+ strcat(buf,nbuf);
+ AddMark(MT_CHANNELSTART,FrameNumberNext,buf);
}
else
{
char nbuf[20];
- snprintf(nbuf,sizeof(nbuf),"%i)?",FrameNumber);
+ snprintf(nbuf,sizeof(nbuf),"%i)",framelast);
nbuf[19]=0;
strcat(buf,nbuf);
- AddMark(MT_CHANNELCHANGE,FrameNumber,buf);
+ AddMark(MT_CHANNELSTOP,framelast,buf);
}
free(buf);
}
channels=macontext->Audio.Info.Channels;
framelast=FrameNumber;
- return &mark;
+ if (mark.Position)
+ {
+ return &mark;
+ }
+ else
+ {
+ return NULL;
+ }
}
-
diff --git a/command/audio.h b/command/audio.h
index 651d056..6bb2b2e 100644
--- a/command/audio.h
+++ b/command/audio.h
@@ -10,23 +10,15 @@
#include "global.h"
-#include "audio_gain_analysis.h"
-
class cMarkAdAudio
{
private:
- //int framenumber;
MarkAdContext *macontext;
MarkAdMark mark;
void ResetMark();
bool AddMark(int Type, int Position, const char *Comment);
- int lastframe_gain;
- double lastgain;
- cMarkAdAudioGainAnalysis audiogain;
- bool AnalyzeGain(int FrameNumber);
-
int channels;
bool ChannelChange(int a, int b);
int framelast;
@@ -36,9 +28,7 @@ public:
cMarkAdAudio(MarkAdContext *maContext);
~cMarkAdAudio();
MarkAdMark *Process(int FrameNumber, int FrameNumberBefore);
- MarkAdPos *Process2ndPass(int FrameNumber);
void Clear();
};
-
#endif
diff --git a/command/audio_gain_analysis.cpp b/command/audio_gain_analysis.cpp
deleted file mode 100644
index b5abf9b..0000000
--- a/command/audio_gain_analysis.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * ReplayGainAnalysis - analyzes input samples and give the recommended dB change
- * Copyright (C) 2001-2009 David Robinson and Glen Sawyer
- * Improvements and optimizations added by Frank Klemm, and by Marcel Müller
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * concept and filter values by David Robinson (David@Robinson.org)
- * -- blame him if you think the idea is flawed
- * original coding by Glen Sawyer (mp3gain@hotmail.com)
- * -- blame him if you think this runs too slowly, or the coding is otherwise flawed
- *
- * lots of code improvements by Frank Klemm ( http://www.uni-jena.de/~pfk/mpp/ )
- * -- credit him for all the _good_ programming ;)
- *
- *
- * For an explanation of the concepts and the basic algorithms involved, go to:
- * http://www.replaygain.org/
- */
-
-/*
- * Here's the deal. Call
- *
- * InitGainAnalysis ( long samplefreq );
- *
- * to initialize everything. Call
- *
- * AnalyzeSamples ( const Float_t* left_samples,
- * const Float_t* right_samples,
- * size_t num_samples,
- * int num_channels );
- *
- * as many times as you want, with as many or as few samples as you want.
- * If mono, pass the sample buffer in through left_samples, leave
- * right_samples NULL, and make sure num_channels = 1.
- *
- * GetGain()
- *
- * will return the recommended dB level change for all samples analyzed
- * SINCE THE LAST TIME you called InitGainAnalysis().
- *
- */
-
-/*
- * So here's the main source of potential code confusion:
- *
- * The filters applied to the incoming samples are IIR filters,
- * meaning they rely on up to <filter order> number of previous samples
- * AND up to <filter order> number of previous filtered samples.
- *
- * I set up the AnalyzeSamples routine to minimize memory usage and interface
- * complexity. The speed isn't compromised too much (I don't think), but the
- * internal complexity is higher than it should be for such a relatively
- * simple routine.
- *
- * Optimization/clarity suggestions are welcome.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "audio_gain_analysis.h"
-
-const Float_t cMarkAdAudioGainAnalysis::ABYule[12][2*YULE_ORDER + 1] =
-{
- {0.006471345933032, -7.22103125152679, -0.02567678242161, 24.7034187975904, 0.049805860704367, -52.6825833623896, -0.05823001743528, 77.4825736677539, 0.040611847441914, -82.0074753444205, -0.010912036887501, 63.1566097101925, -0.00901635868667, -34.889569769245, 0.012448886238123, 13.2126852760198, -0.007206683749426, -3.09445623301669, 0.002167156433951, 0.340344741393305, -0.000261819276949},
- {0.015415414474287, -7.19001570087017, -0.07691359399407, 24.4109412087159, 0.196677418516518, -51.6306373580801, -0.338855114128061, 75.3978476863163, 0.430094579594561, -79.4164552507386, -0.415015413747894, 61.0373661948115, 0.304942508151101, -33.7446462547014, -0.166191795926663, 12.8168791146274, 0.063198189938739, -3.01332198541437, -0.015003978694525, 0.223619893831468, 0.001748085184539},
- {0.021776466467053, -5.74819833657784, -0.062376961003801, 16.246507961894, 0.107731165328514, -29.9691822642542, -0.150994515142316, 40.027597579378, 0.170334807313632, -40.3209196052655, -0.157984942890531, 30.8542077487718, 0.121639833268721, -17.5965138737281, -0.074094040816409, 7.10690214103873, 0.031282852041061, -1.82175564515191, -0.00755421235941, 0.223619893831468, 0.00117925454213 },
- {0.03857599435200, -3.84664617118067, -0.02160367184185, 7.81501653005538, -0.00123395316851, -11.34170355132042, -0.00009291677959, 13.05504219327545, -0.01655260341619, -12.28759895145294, 0.02161526843274, 9.48293806319790, -0.02074045215285, -5.87257861775999, 0.00594298065125, 2.75465861874613, 0.00306428023191, -0.86984376593551, 0.00012025322027, 0.13919314567432, 0.00288463683916 },
- {0.05418656406430, -3.47845948550071, -0.02911007808948, 6.36317777566148, -0.00848709379851, -8.54751527471874, -0.00851165645469, 9.47693607801280, -0.00834990904936, -8.81498681370155, 0.02245293253339, 6.85401540936998, -0.02596338512915, -4.39470996079559, 0.01624864962975, 2.19611684890774, -0.00240879051584, -0.75104302451432, 0.00674613682247, 0.13149317958808, -0.00187763777362 },
- {0.15457299681924, -2.37898834973084, -0.09331049056315, 2.84868151156327, -0.06247880153653, -2.64577170229825, 0.02163541888798, 2.23697657451713, -0.05588393329856, -1.67148153367602, 0.04781476674921, 1.00595954808547, 0.00222312597743, -0.45953458054983, 0.03174092540049, 0.16378164858596, -0.01390589421898, -0.05032077717131, 0.00651420667831, 0.02347897407020, -0.00881362733839 },
- {0.30296907319327, -1.61273165137247, -0.22613988682123, 1.07977492259970, -0.08587323730772, -0.25656257754070, 0.03282930172664, -0.16276719120440, -0.00915702933434, -0.22638893773906, -0.02364141202522, 0.39120800788284, -0.00584456039913, -0.22138138954925, 0.06276101321749, 0.04500235387352, -0.00000828086748, 0.02005851806501, 0.00205861885564, 0.00302439095741, -0.02950134983287 },
- {0.33642304856132, -1.49858979367799, -0.25572241425570, 0.87350271418188, -0.11828570177555, 0.12205022308084, 0.11921148675203, -0.80774944671438, -0.07834489609479, 0.47854794562326, -0.00469977914380, -0.12453458140019, -0.00589500224440, -0.04067510197014, 0.05724228140351, 0.08333755284107, 0.00832043980773, -0.04237348025746, -0.01635381384540, 0.02977207319925, -0.01760176568150 },
- {0.44915256608450, -0.62820619233671, -0.14351757464547, 0.29661783706366, -0.22784394429749, -0.37256372942400, -0.01419140100551, 0.00213767857124, 0.04078262797139, -0.42029820170918, -0.12398163381748, 0.22199650564824, 0.04097565135648, 0.00613424350682, 0.10478503600251, 0.06747620744683, -0.01863887810927, 0.05784820375801, -0.03193428438915, 0.03222754072173, 0.00541907748707 },
- {0.56619470757641, -1.04800335126349, -0.75464456939302, 0.29156311971249, 0.16242137742230, -0.26806001042947, 0.16744243493672, 0.00819999645858, -0.18901604199609, 0.45054734505008, 0.30931782841830, -0.33032403314006, -0.27562961986224, 0.06739368333110, 0.00647310677246, -0.04784254229033, 0.08647503780351, 0.01639907836189, -0.03788984554840, 0.01807364323573, -0.00588215443421 },
- {0.58100494960553, -0.51035327095184, -0.53174909058578, -0.31863563325245, -0.14289799034253, -0.20256413484477, 0.17520704835522, 0.14728154134330, 0.02377945217615, 0.38952639978999, 0.15558449135573, -0.23313271880868, -0.25344790059353, -0.05246019024463, 0.01628462406333, -0.02505961724053, 0.06920467763959, 0.02442357316099, -0.03721611395801, 0.01818801111503, -0.00749618797172 },
- {0.53648789255105, -0.25049871956020, -0.42163034350696, -0.43193942311114, -0.00275953611929, -0.03424681017675, 0.04267842219415, -0.04678328784242, -0.10214864179676, 0.26408300200955, 0.14590772289388, 0.15113130533216, -0.02459864859345, -0.17556493366449, -0.11202315195388, -0.18823009262115, -0.04060034127000, 0.05477720428674, 0.04788665548180, 0.04704409688120, -0.02217936801134 }
-};
-
-const Float_t cMarkAdAudioGainAnalysis::ABButter[12][2*BUTTER_ORDER + 1] =
-{
- {0.99308203517541, -1.98611621154089, -1.98616407035082, 0.986211929160751, 0.99308203517541 },
- {0.992472550461293,-1.98488843762334, -1.98494510092258, 0.979389350028798, 0.992472550461293},
- {0.989641019334721,-1.97917472731008, -1.97928203866944, 0.979389350028798, 0.989641019334721},
- {0.98621192462708, -1.97223372919527, -1.97242384925416, 0.97261396931306, 0.98621192462708 },
- {0.98500175787242, -1.96977855582618, -1.97000351574484, 0.97022847566350, 0.98500175787242 },
- {0.97938932735214, -1.95835380975398, -1.95877865470428, 0.95920349965459, 0.97938932735214 },
- {0.97531843204928, -1.95002759149878, -1.95063686409857, 0.95124613669835, 0.97531843204928 },
- {0.97316523498161, -1.94561023566527, -1.94633046996323, 0.94705070426118, 0.97316523498161 },
- {0.96454515552826, -1.92783286977036, -1.92909031105652, 0.93034775234268, 0.96454515552826 },
- {0.96009142950541, -1.91858953033784, -1.92018285901082, 0.92177618768381, 0.96009142950541 },
- {0.95856916599601, -1.91542108074780, -1.91713833199203, 0.91885558323625, 0.95856916599601 },
- {0.94597685600279, -1.88903307939452, -1.89195371200558, 0.89487434461664, 0.94597685600279 }
-};
-
-void cMarkAdAudioGainAnalysis::filterYule (const Float_t* input, Float_t* output, size_t nSamples, const Float_t* kernel)
-{
- // for each filter:
- // [0] 48 kHz, [1] 44.1 kHz, [2] 32 kHz, [3] 24 kHz, [4] 22050 Hz,
- // [5] 16 kHz, [6] 12 kHz, [7] is 11025 Hz, [8] 8 kHz
-
- // When calling these filter procedures, make sure that ip[-order] and op[-order] point to real data!
-
- while (nSamples--)
- {
- *output = 1e-10 /* 1e-10 is a hack to avoid slowdown because of denormals */
- + input [0] * kernel[0]
- - output[-1] * kernel[1]
- + input [-1] * kernel[2]
- - output[-2] * kernel[3]
- + input [-2] * kernel[4]
- - output[-3] * kernel[5]
- + input [-3] * kernel[6]
- - output[-4] * kernel[7]
- + input [-4] * kernel[8]
- - output[-5] * kernel[9]
- + input [-5] * kernel[10]
- - output[-6] * kernel[11]
- + input [-6] * kernel[12]
- - output[-7] * kernel[13]
- + input [-7] * kernel[14]
- - output[-8] * kernel[15]
- + input [-8] * kernel[16]
- - output[-9] * kernel[17]
- + input [-9] * kernel[18]
- - output[-10]* kernel[19]
- + input [-10]* kernel[20];
- ++output;
- ++input;
- }
-}
-
-void cMarkAdAudioGainAnalysis::filterButter (const Float_t* input, Float_t* output, size_t nSamples, const Float_t* kernel)
-{
-
- while (nSamples--)
- {
- *output =
- input [0] * kernel[0]
- - output[-1] * kernel[1]
- + input [-1] * kernel[2]
- - output[-2] * kernel[3]
- + input [-2] * kernel[4];
- ++output;
- ++input;
- }
-}
-
-int cMarkAdAudioGainAnalysis::ResetSampleFrequency ( long samplefreq )
-{
- // returns a INIT_GAIN_ANALYSIS_OK if successful, INIT_GAIN_ANALYSIS_ERROR if not
- int i;
-
- // zero out initial values
- for ( i = 0; i < MAX_ORDER; i++ )
- linprebuf[i] = lstepbuf[i] = loutbuf[i] = rinprebuf[i] = rstepbuf[i] = routbuf[i] = 0.;
-
- switch ( (int)(samplefreq) )
- {
- case 96000:
- freqindex = 0;
- break;
- case 88200:
- freqindex = 1;
- break;
- case 64000:
- freqindex = 2;
- break;
- case 48000:
- freqindex = 3;
- break;
- case 44100:
- freqindex = 4;
- break;
- case 32000:
- freqindex = 5;
- break;
- case 24000:
- freqindex = 6;
- break;
- case 22050:
- freqindex = 7;
- break;
- case 16000:
- freqindex = 8;
- break;
- case 12000:
- freqindex = 9;
- break;
- case 11025:
- freqindex = 10;
- break;
- case 8000:
- freqindex = 11;
- break;
- default:
- return INIT_GAIN_ANALYSIS_ERROR;
- }
-
- sampleWindow = (int) ceil (samplefreq * RMS_WINDOW_TIME);
-
- lsum = 0.;
- rsum = 0.;
- totsamp = 0;
-
- memset ( A, 0, sizeof(A) );
-
- return INIT_GAIN_ANALYSIS_OK;
-}
-
-int cMarkAdAudioGainAnalysis::Init(long samplefreq)
-{
- if (ResetSampleFrequency(samplefreq) != INIT_GAIN_ANALYSIS_OK)
- {
- return INIT_GAIN_ANALYSIS_ERROR;
- }
-
- linpre = linprebuf + MAX_ORDER;
- rinpre = rinprebuf + MAX_ORDER;
- lstep = lstepbuf + MAX_ORDER;
- rstep = rstepbuf + MAX_ORDER;
- lout = loutbuf + MAX_ORDER;
- rout = routbuf + MAX_ORDER;
-
- memset ( B, 0, sizeof(B) );
-
- gnum_samples=0;
-
- return INIT_GAIN_ANALYSIS_OK;
-}
-
-static __inline double fsqr(const double d)
-{
- return d*d;
-}
-
-int cMarkAdAudioGainAnalysis::AnalyzeSamples ( const Float_t* left_samples, const Float_t* right_samples, size_t num_samples, int num_channels )
-{
- // returns GAIN_ANALYSIS_OK if successful, GAIN_ANALYSIS_ERROR if not
- const Float_t* curleft;
- const Float_t* curright;
- long batchsamples;
- long cursamples;
- long cursamplepos;
- int i;
-
- if ( num_samples == 0 )
- return GAIN_ANALYSIS_OK;
-
- gnum_samples+=num_samples;
-
- cursamplepos = 0;
- batchsamples = (long)num_samples;
-
- switch ( num_channels)
- {
- case 1:
- right_samples = left_samples;
- case 2:
- break;
- default:
- return GAIN_ANALYSIS_ERROR;
- }
-
- if ( num_samples < MAX_ORDER )
- {
- memcpy ( linprebuf + MAX_ORDER, left_samples , num_samples * sizeof(Float_t) );
- memcpy ( rinprebuf + MAX_ORDER, right_samples, num_samples * sizeof(Float_t) );
- }
- else
- {
- memcpy ( linprebuf + MAX_ORDER, left_samples, MAX_ORDER * sizeof(Float_t) );
- memcpy ( rinprebuf + MAX_ORDER, right_samples, MAX_ORDER * sizeof(Float_t) );
- }
-
- while ( batchsamples > 0 )
- {
- cursamples = batchsamples > sampleWindow-totsamp ? sampleWindow - totsamp : batchsamples;
- if ( cursamplepos < MAX_ORDER )
- {
- curleft = linpre+cursamplepos;
- curright = rinpre+cursamplepos;
- if (cursamples > MAX_ORDER - cursamplepos )
- cursamples = MAX_ORDER - cursamplepos;
- }
- else
- {
- curleft = left_samples + cursamplepos;
- curright = right_samples + cursamplepos;
- }
-
- YULE_FILTER ( curleft , lstep + totsamp, cursamples, ABYule[freqindex]);
- YULE_FILTER ( curright, rstep + totsamp, cursamples, ABYule[freqindex]);
-
- BUTTER_FILTER ( lstep + totsamp, lout + totsamp, cursamples, ABButter[freqindex]);
- BUTTER_FILTER ( rstep + totsamp, rout + totsamp, cursamples, ABButter[freqindex]);
-
- curleft = lout + totsamp; // Get the squared values
- curright = rout + totsamp;
-
- i = cursamples % 16;
- while (i--)
- {
- lsum += fsqr(*curleft++);
- rsum += fsqr(*curright++);
- }
- i = cursamples / 16;
- while (i--)
- {
- lsum += fsqr(curleft[0])
- + fsqr(curleft[1])
- + fsqr(curleft[2])
- + fsqr(curleft[3])
- + fsqr(curleft[4])
- + fsqr(curleft[5])
- + fsqr(curleft[6])
- + fsqr(curleft[7])
- + fsqr(curleft[8])
- + fsqr(curleft[9])
- + fsqr(curleft[10])
- + fsqr(curleft[11])
- + fsqr(curleft[12])
- + fsqr(curleft[13])
- + fsqr(curleft[14])
- + fsqr(curleft[15]);
- curleft += 16;
- rsum += fsqr(curright[0])
- + fsqr(curright[1])
- + fsqr(curright[2])
- + fsqr(curright[3])
- + fsqr(curright[4])
- + fsqr(curright[5])
- + fsqr(curright[6])
- + fsqr(curright[7])
- + fsqr(curright[8])
- + fsqr(curright[9])
- + fsqr(curright[10])
- + fsqr(curright[11])
- + fsqr(curright[12])
- + fsqr(curright[13])
- + fsqr(curright[14])
- + fsqr(curright[15]);
- curright += 16;
- }
-
- batchsamples -= cursamples;
- cursamplepos += cursamples;
- totsamp += cursamples;
- if ( totsamp == sampleWindow ) // Get the Root Mean Square (RMS) for this set of samples
- {
- double val = STEPS_per_dB * 10. * log10 ( (lsum+rsum) / totsamp * 0.5 + 1.e-37 );
- int ival = (int) val;
- if ( ival < 0 ) ival = 0;
- if ( ival >= (int)(sizeof(A)/sizeof(*A)) ) ival = sizeof(A)/sizeof(*A) - 1;
- A [ival]++;
- lsum = rsum = 0.;
- memmove ( loutbuf , loutbuf + totsamp, MAX_ORDER * sizeof(Float_t) );
- memmove ( routbuf , routbuf + totsamp, MAX_ORDER * sizeof(Float_t) );
- memmove ( lstepbuf, lstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) );
- memmove ( rstepbuf, rstepbuf + totsamp, MAX_ORDER * sizeof(Float_t) );
- totsamp = 0;
- }
- if ( totsamp > sampleWindow )
- // somehow I really screwed up: Error in programming!
- // Contact author about totsamp > sampleWindow
- return GAIN_ANALYSIS_ERROR;
- }
- if ( num_samples < MAX_ORDER )
- {
- memmove ( linprebuf,linprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) );
- memmove ( rinprebuf,rinprebuf + num_samples, (MAX_ORDER-num_samples) * sizeof(Float_t) );
- memcpy ( linprebuf + MAX_ORDER - num_samples, left_samples,num_samples * sizeof(Float_t) );
- memcpy ( rinprebuf + MAX_ORDER - num_samples, right_samples,num_samples * sizeof(Float_t) );
- }
- else
- {
- memcpy ( linprebuf, left_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) );
- memcpy ( rinprebuf, right_samples + num_samples - MAX_ORDER, MAX_ORDER * sizeof(Float_t) );
- }
-
- return GAIN_ANALYSIS_OK;
-}
-
-Float_t cMarkAdAudioGainAnalysis::analyzeResult ( Uint32_t* Array, size_t len )
-{
- Uint32_t elems;
- Int32_t upper;
- size_t i;
-
- elems = 0;
- for ( i = 0; i < len; i++ )
- elems += Array[i];
- if ( elems == 0 )
- return GAIN_NOT_ENOUGH_SAMPLES;
-
- upper = (Int32_t) ceil (elems * (1. - RMS_PERCENTILE));
- for ( i = len; i-- > 0; )
- {
- if ( (upper -= Array[i]) <= 0 )
- break;
- }
-
- return (Float_t) ((Float_t)PINK_REF - (Float_t)i / (Float_t)STEPS_per_dB);
-}
-
-Float_t cMarkAdAudioGainAnalysis::GetGain ( void )
-{
- return analyzeResult ( A, sizeof(A)/sizeof(*A) );
-}
diff --git a/command/audio_gain_analysis.h b/command/audio_gain_analysis.h
deleted file mode 100644
index abed123..0000000
--- a/command/audio_gain_analysis.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * ReplayGainAnalysis - analyzes input samples and give the recommended dB change
- * Copyright (C) 2001-2009 David Robinson and Glen Sawyer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * concept and filter values by David Robinson (David@Robinson.org)
- * -- blame him if you think the idea is flawed
- * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA
- * -- blame him if you think this runs too slowly, or the coding is otherwise flawed
- *
- * For an explanation of the concepts and the basic algorithms involved, go to:
- * http://www.replaygain.org/
- */
-
-#ifndef GAIN_ANALYSIS_H
-#define GAIN_ANALYSIS_H
-
-#include <stddef.h>
-
-#define GAIN_NOT_ENOUGH_SAMPLES -24601
-#define GAIN_ANALYSIS_ERROR 0
-#define GAIN_ANALYSIS_OK 1
-
-#define INIT_GAIN_ANALYSIS_ERROR 0
-#define INIT_GAIN_ANALYSIS_OK 1
-
-typedef double Float_t; // Type used for filtering
-
-class cMarkAdAudioGainAnalysis
-{
-private:
- typedef unsigned int Uint32_t;
- typedef signed int Int32_t;
-
-#define YULE_ORDER 10
-#define BUTTER_ORDER 2
-#define YULE_FILTER filterYule
-#define BUTTER_FILTER filterButter
-#define RMS_PERCENTILE 0.95 // percentile which is louder than the proposed level
-#define MAX_SAMP_FREQ 96000. // maximum allowed sample frequency [Hz]
-#define RMS_WINDOW_TIME 0.050 // Time slice size [s]
-#define STEPS_per_dB 100. // Table entries per dB
-#define MAX_dB 120. // Table entries for 0...MAX_dB (normal max. values are 70...80 dB)
-
-#define MAX_ORDER (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER)
-#define MAX_SAMPLES_PER_WINDOW (size_t) (MAX_SAMP_FREQ * RMS_WINDOW_TIME + 1) // max. Samples per Time slice
-#define PINK_REF 64.82 //298640883795 // calibration value
-
- Float_t linprebuf [MAX_ORDER * 2];
- Float_t* linpre; // left input samples, with pre-buffer
- Float_t lstepbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
- Float_t* lstep; // left "first step" (i.e. post first filter) samples
- Float_t loutbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
- Float_t* lout; // left "out" (i.e. post second filter) samples
- Float_t rinprebuf [MAX_ORDER * 2];
- Float_t* rinpre; // right input samples ...
- Float_t rstepbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
- Float_t* rstep;
- Float_t routbuf [MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
- Float_t* rout;
- long sampleWindow; // number of samples required to reach number of milliseconds required for RMS window
- long totsamp;
- int gnum_samples;
- double lsum;
- double rsum;
- int freqindex;
- int first;
- Uint32_t A [(size_t)(STEPS_per_dB * MAX_dB)];
- Uint32_t B [(size_t)(STEPS_per_dB * MAX_dB)];
-
- static const Float_t ABButter[12][2*BUTTER_ORDER + 1];
- static const Float_t ABYule[12][2*YULE_ORDER + 1];
-
- void filterButter (const Float_t* input, Float_t* output, size_t nSamples, const Float_t* kernel);
- void filterYule (const Float_t* input, Float_t* output, size_t nSamples, const Float_t* kernel);
-
- int ResetSampleFrequency ( long samplefreq );
- Float_t analyzeResult ( Uint32_t* Array, size_t len );
-public:
- int Init( long samplefreq );
- int AnalyzeSamples ( const Float_t* left_samples, const Float_t* right_samples, size_t num_samples, int num_channels );
- int AnalyzedSamples()
- {
- return (int) gnum_samples;
- };
- Float_t GetGain(void);
-};
-
-#endif /* GAIN_ANALYSIS_H */
diff --git a/command/demux.cpp b/command/demux.cpp
index 6f58dde..9c9bcc8 100644
--- a/command/demux.cpp
+++ b/command/demux.cpp
@@ -5,282 +5,1201 @@
*
*/
+#include <string.h>
#include "demux.h"
+extern "C"
+{
+#include "debug.h"
+}
-#include <string.h>
+#include <stdlib.h>
-cMarkAdDemux::cMarkAdDemux()
+#ifndef TS_SIZE
+#define TS_SIZE 188
+#endif
+
+cPaketQueue::cPaketQueue(const char *Name, int Size)
{
- ts2pkt=NULL;
- pes2audioes=NULL;
- pes2videoes=NULL;
- pause=false;
- pause_retval=0;
- min_needed=0;
- skip=0;
- queue = new cMarkAdPaketQueue(NULL,2176);
+ maxqueue=Size;
+ if (Name)
+ {
+ name=strdup(Name);
+ }
+ else
+ {
+ name=NULL;
+ }
+ buffer=(uchar *) malloc(Size+8);
+ if (!buffer) maxqueue=0;
+ memset(&pktinfo,0,sizeof(pktinfo));
+ percent=-1;
+ mpercent=0;
+ Clear();
}
-cMarkAdDemux::~cMarkAdDemux()
+void cPaketQueue::Clear()
{
- if (ts2pkt) delete ts2pkt;
- if (pes2audioes) delete pes2audioes;
- if (pes2videoes) delete pes2videoes;
- if (queue) delete queue;
+ inptr=outptr=0;
+ pktinfo.pkthdr=-1;
+ scanner=0xFFFFFFFF;
+ scannerstart=-1;
+ skipped=0;
}
-void cMarkAdDemux::Clear()
+cPaketQueue::~cPaketQueue()
{
- if (ts2pkt) ts2pkt->Clear();
- if (pes2audioes) pes2audioes->Clear();
- if (pes2videoes) pes2videoes->Clear();
- if (queue) queue->Clear();
- pause=false;
- pause_retval=0;
- min_needed=0;
- skip=0;
+ if (name)
+ {
+ tsyslog("buffer usage : %-15s %3i%%",name,mpercent);
+ free((void *) name);
+ }
+ if (buffer) free(buffer);
}
-void cMarkAdDemux::ProcessVDR(MarkAdPid Pid, uchar *Data, int Count, MarkAdPacket *Pkt)
+void cPaketQueue::Resize(int NewSize, const char *NewName)
{
- if (!Pkt) return;
+ if (NewName)
+ {
+ if (name) free((void *) name);
+ name=strdup(NewName);
+ }
+ if (inptr<NewSize)
+ {
+ buffer=(uchar *) realloc(buffer,NewSize+8);
+ if (buffer)
+ {
+ maxqueue=NewSize;
+ }
+ else
+ {
+ maxqueue=0;
+ Clear();
+ }
+ }
+}
- if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) || (Pid.Type==MARKAD_PIDTYPE_AUDIO_MP2))
+int cPaketQueue::findpktheader(int start, int *streamsize,int *headersize, bool longstartcode, bool pesonly=false)
+{
+ if ((!streamsize) || (!headersize)) return -1;
+ if (!start) start=outptr;
+ if (start>=inptr) return -1;
+ *streamsize=0;
+ if (longstartcode)
+ {
+ *headersize=4; // 0x0 0x0 0x0 0x1
+ }
+ else
+ {
+ *headersize=3; // 0x0 0x0 0x1
+ }
+ int i;
+
+ if (scanner!=0xFFFFFFFF)
+ {
+ scanner<<=8;
+ scanner|=buffer[start++];
+ }
+
+ bool found=false;
+ for (i=start; i<inptr; i++)
+ {
+ if (longstartcode)
+ {
+ if (scanner==1L)
+ {
+ found=true;
+ break;
+ }
+ if ((scanner & 0xFFFFFFF0)==0x1E0L)
+ {
+ found=true;
+ break;
+ }
+ }
+ else
+ {
+ if ((scanner & 0x00FFFFFF)==1L)
+ {
+ if (pesonly)
+ {
+ if (buffer[i]>=0xBC)
+ {
+ found=true;
+ break;
+ }
+ }
+ else
+ {
+ found=true;
+ break;
+ }
+ }
+ }
+ scanner<<=8;
+ scanner|=buffer[i];
+ }
+ if (!found)
{
- if (!pes2audioes) pes2audioes=new cMarkAdPES2ES((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) ?
- "PES2ES AC3" : "PES2ES MP2");
- if (!pes2audioes) return;
- pes2audioes->Process(Pid,Data,Count,Pkt);
+ if (longstartcode)
+ {
+ if (scanner==1L)
+ {
+ found=true;
+ }
+ if ((scanner & 0xFFFFFFF0)==0x1E0L)
+ {
+ found=true;
+ }
+ }
+ else
+ {
+ if (((scanner & 0x00FFFFFF)==1L) && (!pesonly))
+ {
+ found=true;
+ }
+ }
}
- if ((Pid.Type==MARKAD_PIDTYPE_VIDEO_H262) || (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264))
+ if (i==inptr)
{
- if (!pes2videoes)
+ if (found)
{
- if (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264)
+ if (!start)
{
- pes2videoes=new cMarkAdPES2ES("PES2H264ES",425984);
+ scanner=0xFFFFFFFF;
+ return -1;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ if (longstartcode) i--;
+ if (buffer[i]>=0xBC) // do we have a PES packet?
+ {
+#define PESHDRSIZE 6
+ if ((i+PESHDRSIZE)>inptr)
+ {
+ return -1; // we need more data (for streamsize and headersize)
+ }
+
+ *streamsize=(buffer[i+1]<<8)+buffer[i+2];
+ if (*streamsize) (*streamsize)+=PESHDRSIZE; // 6 Byte PES-Header
+ if (longstartcode)
+ {
+ struct PESHDROPT *peshdropt=(struct PESHDROPT *) &buffer[i+3];
+ if (peshdropt->MarkerBits==0x2)
+ {
+ *headersize=PESHDRSIZE+sizeof(struct PESHDROPT)+
+ peshdropt->Length;
}
else
{
- pes2videoes=new cMarkAdPES2ES("PES2H262ES",65536);
+ *headersize=PESHDRSIZE;
}
}
- if (!pes2videoes) return;
- pes2videoes->Process(Pid,Data,Count,Pkt);
}
- return;
+ return i-3;
}
-void cMarkAdDemux::ProcessTS(MarkAdPid Pid, uchar *Data, int Count, MarkAdPacket *Pkt)
+int cPaketQueue::findaudioheader(int start, int *framesize, int *headersize, bool ac3)
{
- if (!Pkt) return;
+ if ((!framesize) || (!headersize)) return -1;
+ if (!start) start=outptr;
+ if (start>=inptr) return -1;
+ (*framesize)=0;
+ if (ac3)
+ {
+ (*headersize)=2;
+ }
+ else
+ {
+ (*headersize)=3;
+ }
+ int i;
- MarkAdPacket pkt;
- memset(&pkt,0,sizeof(pkt));
+ if (scanner!=0xFFFFFFFF)
+ {
+ scanner<<=8;
+ scanner|=buffer[start++];
+ }
+ else
+ {
+ scanner<<=8;
+ scanner|=buffer[start++];
+ scanner<<=8;
+ scanner|=buffer[start++];
+ }
- if (!ts2pkt)
+ for (i=start; i<inptr; i++)
{
- switch (Pid.Type)
+
+ if (ac3)
{
- case MARKAD_PIDTYPE_VIDEO_H264:
- ts2pkt=new cMarkAdTS2Pkt("TS2H264",819200);
- break;
+ if ((scanner & 0x0000FFFF)==0xB77L) break;
+ }
+ else
+ {
+ if ((scanner & 0x0000FFE0)==0xFFE0L) break;
+ }
- case MARKAD_PIDTYPE_VIDEO_H262:
- ts2pkt=new cMarkAdTS2Pkt("TS2H262",262144);
- break;
+ scanner<<=8;
+ scanner|=buffer[i];
+ }
+ if (i==inptr) return -1;
- case MARKAD_PIDTYPE_AUDIO_AC3:
- ts2pkt=new cMarkAdTS2Pkt("TS2PES AC3",32768);
- break;
+ i-=2;
+
+ if (ac3)
+ {
+ struct AC3HDR *ac3hdr = (struct AC3HDR *) &buffer[i];
+
+ if (ac3hdr->SampleRateIndex==3) return -1; // reserved
+ if (ac3hdr->FrameSizeIndex>=38) return -1; // reserved
- case MARKAD_PIDTYPE_AUDIO_MP2:
- ts2pkt=new cMarkAdTS2Pkt("TS2PES MP2",16384);
+ if (framesize)
+ {
+ int bitRatesAC3[3][38] = // all values are specified as kbits/s
+ {
+ { 64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192,
+ 224, 224, 256, 256, 320, 320, 384, 384, 448, 448, 512, 512,
+ 640, 640, 768, 768, 896, 896, 1024, 1024, 1152, 1152, 1280, 1280 }, // 48kHz
+
+ { 69, 70, 87, 88, 104, 105, 121, 122, 139, 140, 174, 175, 208, 209,
+ 243, 244, 278, 279, 348, 349, 417, 418, 487, 488, 557, 558,
+ 696, 697, 835, 836, 975, 976, 1114, 1115, 1253, 1254, 1393, 1394 }, // 44.1kHz
+
+ { 96, 96, 120, 120, 144, 144, 168, 168, 192, 192, 240, 240, 288,
+ 288, 336, 336, 384, 384, 480, 480, 576, 576, 672, 672, 768,
+ 768, 960, 960, 1152, 1152, 1344, 1344, 1536, 1536, 1728, 1728, 1920,1920 } // 32kHz
+ };
+
+ *framesize=2*bitRatesAC3[ac3hdr->SampleRateIndex][ac3hdr->FrameSizeIndex];
+ }
+ return i;
+ }
+ else
+ {
+ struct MP2HDR *mp2hdr = (struct MP2HDR *) &buffer[i];
+ if (mp2hdr->MpegID==1) return -1; // reserved
+ if (mp2hdr->Layer==0) return -1; // reserved
+ if (mp2hdr->BitRateIndex==0xF) return -1; // forbidden
+ if (mp2hdr->SampleRateIndex==3) return -1; //reserved
+ if (mp2hdr->Emphasis==2) return -1; // reserved
+
+ if (framesize)
+ {
+ int bitRates[3][3][16] = // all values are specified as kbits/s
+ {
+ {
+ { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1 }, // M1, L1
+ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1 }, // M1, L2
+ { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 } // M1, L3
+ },
+ {
+ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, // M2, L1
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, // M2, L2
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 } // M2, L3
+ },
+ {
+ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, // M2.5, L1
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, // M2.5, L2
+ { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 } // M2.5, L3
+ }
+ };
+
+ int samplingFrequencies[3][4] = // all values are specified in Hz
+ {
+ { 44100, 48000, 32000, -1 }, // MPEG 1
+ { 22050, 24000, 16000, -1 }, // MPEG 2
+ { 32000, 16000, 8000, -1 } // MPEG 2.5
+ };
+
+
+ int slots_per_frame[3][3] =
+ {
+ { 12, 144, 144 }, // MPEG 1, Layer I, II, III
+ { 12, 144, 72 }, // MPEG 2, Layer I, II, III
+ { 12, 144, 72 } // MPEG 2.5, Layer I, II, III
+ };
+
+ int mpegIndex;
+ switch (mp2hdr->MpegID)
+ {
+ case 0:
+ mpegIndex=2;
+ break;
+ case 2:
+ mpegIndex=1;
+ break;
+ case 3:
+ mpegIndex=0;
+ break;
+ default:
+ mpegIndex=0; // just to get rid of compiler warnings ;)
+ }
+ int layerIndex = 3 - mp2hdr->Layer;
+
+ // Layer I (i. e., layerIndex == 0) has a larger slot size
+ int slotSize = (layerIndex == 0) ? 4 : 1; // bytes
+ int sf = samplingFrequencies[mpegIndex][mp2hdr->SampleRateIndex];
+
+ if (mp2hdr->BitRateIndex == 0)
+ *framesize = 0; // "free" Bitrate -> we don't support this!
+ else
+ {
+ int br = 1000 * bitRates[mpegIndex][layerIndex][mp2hdr->BitRateIndex]; // bits/s
+ int N = slots_per_frame[mpegIndex][layerIndex] * br / sf; // slots
+
+ *framesize = (N + mp2hdr->Padding) * slotSize; // bytes
+ }
+ }
+ return i;
+ }
+}
+
+int cPaketQueue::FindPesHeader(int Start)
+{
+ int start=outptr+Start;
+ int ssize,hsize;
+ int pos=findpktheader(start,&ssize,&hsize,false,true);
+ if (pos==-1) return -1;
+ pos-=outptr;
+ return pos;
+}
+
+bool cPaketQueue::Put(uchar *Data, int Size)
+{
+ if (!buffer) return false;
+ if ((inptr) && (inptr==outptr)) inptr=outptr=0;
+
+ if (outptr)
+ {
+ if (outptr>(inptr-outptr))
+ {
+ memcpy(buffer,&buffer[outptr],inptr-outptr);
+ if (scannerstart==inptr) scannerstart-=outptr;
+ inptr-=outptr;
+ if (pktinfo.pkthdr==outptr) pktinfo.pkthdr=0;
+ outptr=0;
+ }
+ }
+
+ if ((inptr+Size)>maxqueue)
+ {
+ if (name)
+ {
+ esyslog("buffer %s full",name);
+ }
+ else
+ {
+ esyslog("buffer full");
+ }
+ mpercent=100;
+ Clear();
+ return false;
+ }
+
+ memcpy(&buffer[inptr],Data,Size);
+ inptr+=Size;
+
+ int npercent=(int) ((inptr*100)/maxqueue);
+ if (npercent>mpercent) mpercent=npercent;
+
+ if ((npercent>90) && (name) && (npercent!=percent))
+ {
+ dsyslog("buffer %s usage: %3i%%",
+ name,npercent);
+ percent=npercent;
+ }
+
+ return true;
+}
+
+uchar *cPaketQueue::Get(int *Size)
+{
+ if (!buffer) return NULL;
+ if (!Size) return NULL;
+ if (Length()<*Size)
+ {
+ *Size=0;
+ return NULL;
+ }
+ uchar *ret=&buffer[outptr];
+ outptr+=*Size;
+ return ret;
+}
+
+uchar *cPaketQueue::Peek(int Size)
+{
+ if (!buffer) return NULL;
+ if (!Size) return NULL;
+ if (Length()<Size) return NULL;
+ uchar *ret=&buffer[outptr];
+ return ret;
+}
+
+uchar *cPaketQueue::GetPacket(int *Size, int Type)
+{
+ if (!Size) return NULL;
+ *Size=0;
+ if (Length()<4) return NULL;
+
+ skipped=0;
+ if (pktinfo.pkthdr==-1)
+ {
+ scanner=0xFFFFFFFF;
+ scannerstart=outptr;
+ switch (Type)
+ {
+ case PACKET_AC3:
+ pktinfo.pkthdr=findaudioheader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,true);
+ break;
+ case PACKET_MP2:
+ pktinfo.pkthdr=findaudioheader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,false);
break;
+ case PACKET_H264:
+ pktinfo.pkthdr=findpktheader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,true);
+ break;
+ default:
+ pktinfo.pkthdr=findpktheader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,false);
+ break;
+ }
+
+ if (pktinfo.pkthdr==-1)
+ {
+ return NULL;
+ }
+ else
+ {
+ if (pktinfo.pkthdr!=outptr)
+ {
+ skipped=pktinfo.pkthdr-outptr;
+ }
+ }
+ scannerstart=pktinfo.pkthdr+pktinfo.pktsyncsize;
+ }
+
+ int streamsize,pktsyncsize,pkthdr=-1;
+
+ if (pktinfo.streamsize)
+ {
+ if ((pktinfo.pkthdr+pktinfo.streamsize)>inptr)
+ {
+ return NULL; // need more data
+ }
+ else
+ {
+ scannerstart=pktinfo.pkthdr+pktinfo.streamsize;
+ scanner=0xFFFFFFFF;
+ }
+ }
+
+ switch (Type)
+ {
+ case PACKET_AC3:
+ pkthdr=findaudioheader(scannerstart,&streamsize,&pktsyncsize,true);
+ break;
+ case PACKET_MP2:
+ pkthdr=findaudioheader(scannerstart,&streamsize,&pktsyncsize,false);
+ break;
+ case PACKET_H264:
+ pkthdr=findpktheader(scannerstart,&streamsize,&pktsyncsize,true);
+ break;
+ default:
+ pkthdr=findpktheader(scannerstart,&streamsize,&pktsyncsize,false);
+ break;
+ }
+
+ if (pkthdr==-1)
+ {
+ if ((pktinfo.streamsize) && ((inptr-outptr)>pktinfo.streamsize))
+ {
+ // no startcode right after streamsize?
+ // output streamsize packet
+ scannerstart=pktinfo.pkthdr+pktinfo.streamsize;
+ streamsize=pktsyncsize=0;
+ pkthdr=-1;
+ }
+ else
+ {
+ scannerstart=inptr;
+ return NULL;
}
}
- if (!ts2pkt) return;
+ else
+ {
+ scannerstart=pkthdr+pktsyncsize;
+ }
+
+ uchar *ptr=&buffer[pktinfo.pkthdr];
+
+ if (pktinfo.streamsize)
+ {
+ *Size=pktinfo.streamsize;
+ }
+ else
+ {
+ *Size=pkthdr-pktinfo.pkthdr;
+ }
+ if (pkthdr==-1)
+ {
+ outptr=pktinfo.pkthdr+pktinfo.streamsize;
+ }
+ else
+ {
+ outptr=pkthdr;
+ }
+
+ pktinfo.pkthdr=pkthdr;
+ pktinfo.streamsize=streamsize;
+ pktinfo.pktsyncsize=pktsyncsize;
- if (!ts2pkt->Process(Pid,Data,Count,&pkt))
+ return ptr;
+}
+
+// ----------------------------------------------------------------------------
+
+cTS2Pkt::cTS2Pkt(int Pid, const char *QueueName, int QueueSize, bool H264)
+{
+ queue=new cPaketQueue(QueueName,QueueSize);
+ pid=Pid;
+ h264=H264;
+ firstsync=false;
+ Clear();
+}
+
+cTS2Pkt::~cTS2Pkt()
+{
+ if (queue)
{
- if (pes2audioes) pes2audioes->Clear();
- return;
+ if (skipped) esyslog("buffer skipped: %-15s %i bytes",queue->Name(),skipped);
+ delete queue;
}
+}
- if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) || (Pid.Type==MARKAD_PIDTYPE_AUDIO_MP2))
+void cTS2Pkt::Clear()
+{
+ sync=false;
+ counter=-1;
+ skipped=0;
+ noticeFILLER=false;
+ noticeSEQUENCE=false;
+ noticeSTREAM=false;
+ if (queue) queue->Clear();
+}
+
+bool cTS2Pkt::Process(uchar *TSData, int TSSize, AvPacket *Pkt)
+{
+ if (!Pkt) return false;
+ if (TSData)
{
- if (!pes2audioes) pes2audioes=new cMarkAdPES2ES((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) ?
- "PES2ES AC3" : "PES2ES MP2");
- if (!pes2audioes) return;
- pes2audioes->Process(Pid,pkt.Data,pkt.Length,Pkt);
+ if (TSSize!=TS_SIZE) return false;
+
+ struct TSHDR *tshdr = (struct TSHDR *) TSData;
+
+ int ppid=(tshdr->PidH << 8) | tshdr->PidL;
+ if (ppid!=pid)
+ {
+ return false;
+ }
+
+ if ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter))
+ {
+ if (counter==(int) tshdr->Counter)
+ {
+ skipped+=TS_SIZE;
+ return true; // duplicate paket -> just ignore
+ }
+ // sequence error
+ if (!noticeSEQUENCE)
+ {
+ noticeSEQUENCE=true;
+ isyslog("sequence error");
+ }
+ if (queue)
+ {
+ skipped+=queue->Length();
+ queue->Clear();
+ }
+ counter=-1;
+ sync=false;
+ if (!tshdr->PayloadStart) return true;
+ }
+ counter=tshdr->Counter;
+
+ if (tshdr->PayloadStart)
+ {
+ firstsync=sync=true;
+ }
+ if (!sync)
+ {
+ if (firstsync) skipped+=TS_SIZE; // only count skipped bytes after first sync
+ return true; // not synced
+ }
+
+ // we just ignore the infos in the adaption field (e.g. OPCR/PCR)
+ if ((tshdr->AFC!=1) && (tshdr->AFC!=3))
+ {
+ return true;
+ }
+
+ int buflen=TS_SIZE+1;
+ uchar *buf=NULL;
+
+ if (tshdr->AFC==1)
+ {
+ // payload only
+ buflen=TS_SIZE-sizeof(struct TSHDR);
+ buf=&TSData[sizeof(struct TSHDR)];
+ }
+
+ if (tshdr->AFC==3)
+ {
+ // adaption field + payload
+ int alen=TSData[4]+1;
+ if (alen>(TS_SIZE-(int) sizeof(struct TSHDR))) alen=TS_SIZE-(int) sizeof(struct TSHDR);
+ buflen=TS_SIZE-(sizeof(struct TSHDR)+alen);
+ buf=&TSData[sizeof(struct TSHDR)+alen];
+ }
+
+ if (!buflen)
+ {
+ // no data? -> impossible?
+ return false;
+ }
+
+ if (tshdr->PayloadStart)
+ {
+ if ((buf[0]!=0) && (buf[1]!=0))
+ {
+ if (!noticeSTREAM)
+ {
+ isyslog("stream error");
+ noticeSTREAM=true;
+ }
+ skipped+=TS_SIZE;
+ sync=false;
+ if (buflen<7) return false;
+ // add a pseudo padding stream
+ buf[0]=0;
+ buf[1]=0;
+ buf[2]=1;
+ buf[3]=0xbe;
+ buf[4]=0;
+ buf[5]=buflen-6;
+ }
+ }
+ queue->Put(buf,buflen);
}
- if ((Pid.Type==MARKAD_PIDTYPE_VIDEO_H262) || (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264))
+ Pkt->Data=queue->GetPacket(&Pkt->Length,h264 ? PACKET_H264 : PACKET_H262);
+ if (Pkt->Data)
{
- if ((pkt.Data) && ((pkt.Data[3] & 0xF0)==0xE0) && (pkt.Data[4]!=0) && (pkt.Data[5]!=0))
+ Pkt->Type=h264 ? PACKET_H264 : PACKET_H262;
+ if ((h264) && ((Pkt->Data[4] & 0x1F)==0x0C))
{
- ts2pkt->InjectVideoPES(pkt.Data,pkt.Length);
- pkt.Data=NULL;
- pkt.Length=0;
+ if (!noticeFILLER)
+ {
+ isyslog("H264 video stream with filler nalu");
+ noticeFILLER=true;
+ }
+ skipped+=Pkt->Length; // thats not accurate!
+ Pkt->Data=NULL;
+ Pkt->Length=0;
+ Pkt->Type=0;
}
- Pkt->Data=pkt.Data;
- Pkt->Length=pkt.Length;
- Pkt->Skipped=pkt.Skipped;
}
- return;
+ else
+ {
+ Pkt->Length=0;
+ Pkt->Type=0;
+ }
+ return true;
}
-int cMarkAdDemux::GetMinNeeded(MarkAdPid Pid, uchar *Data, int Count, bool *Offcnt)
+// ----------------------------------------------------------------------------
+
+cPES2ES::cPES2ES(int PacketType, const char *QueueName, int QueueSize)
{
- if (Pid.Num>=0) return TS_SIZE;
+ queue = new cPaketQueue(QueueName,QueueSize);
+ ptype=PacketType;
+ Clear();
+}
- uchar *qData=queue->Peek(PESHDRSIZE);
- if (!qData)
+cPES2ES::~cPES2ES()
+{
+ if (queue)
{
- int len=PESHDRSIZE-queue->Length();
- int cnt=(Count>len) ? len : Count;
- queue->Put(Data,cnt);
- return -cnt;
+ if (skipped) esyslog("buffer skipped: %-15s %i bytes",queue->Name(),skipped);
+ delete queue;
}
+}
- int stream=qData[3];
+void cPES2ES::Clear()
+{
+ skipped=0;
+ if (queue) queue->Clear();
+}
- if ((qData[0]==0) && (qData[1]==0) && (qData[2]==1) && (stream>0xBC))
+bool cPES2ES::Process(uchar *PESData, int PESSize, AvPacket *ESPkt)
+{
+ if (!ESPkt) return false;
+ if (PESData)
{
- int needed=qData[4]*256+qData[5];
+ struct PESHDR *peshdr=(struct PESHDR *) PESData;
+
+ // first check some simple things
+ if ((peshdr->Sync1!=0) && (peshdr->Sync2!=0) && (peshdr->Sync3!=1)) return false;
+ if (peshdr->StreamID<=0xBC) return false;
- if (((Pid.Type==MARKAD_PIDTYPE_VIDEO_H262) ||
- (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264)) && ((stream & 0xF0)!=0xE0))
+ int Length=(peshdr->LenH<<8)+peshdr->LenL;
+ if (Length)
{
- // ignore 6 header bytes from queue->Put above
- queue->Clear();
- if (Offcnt) *Offcnt=true;
- return -needed;
+ Length+=sizeof(PESHDR);
+ if (Length!=PESSize)
+ {
+ skipped+=Length;
+ return true;
+ }
}
- if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_MP2) && ((stream & 0xF0)!=0xC0))
+
+ if (peshdr->StreamID==0xBE)
{
- // ignore 6 header bytes from queue->Put above
queue->Clear();
- if (Offcnt) *Offcnt=true;
- return -needed;
+ return true;
}
- if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) && (stream!=0xBD))
+
+ switch (ptype)
{
- // ignore 6 header bytes from queue->Put above
- queue->Clear();
- if (Offcnt) *Offcnt=true;
- return -needed;
+ case PACKET_H262:
+ if (peshdr->StreamID!=0xE0) return true; // ignore packets not for us!
+ break;
+ case PACKET_H264:
+ if (peshdr->StreamID!=0xE0) return true; // ignore packets not for us!
+ break;
+ case PACKET_AC3:
+ if (peshdr->StreamID!=0xBD) return true; // ignore packets not for us!
+ break;
+ case PACKET_MP2:
+ if (peshdr->StreamID!=0xC0) return true; // ignore packets not for us!
+ break;
+ default:
+ break;
+ }
+
+ struct PESHDROPT *peshdropt=(struct PESHDROPT *) &PESData[sizeof(struct PESHDR)];
+
+ uchar *buf;
+ int buflen;
+
+ if (peshdropt->MarkerBits==0x2)
+ {
+ // we have an optional PES header
+ int bpos=sizeof(struct PESHDR)+sizeof(struct PESHDROPT)+
+ peshdropt->Length;
+ buf=&PESData[bpos];
+ buflen=PESSize-bpos;
+ }
+ else
+ {
+ int bpos=sizeof(struct PESHDR);
+ buf=&PESData[bpos];
+ buflen=PESSize-bpos;
}
- return needed+PESHDRSIZE;
+ queue->Put(buf,buflen);
+ }
+ ESPkt->Data=queue->GetPacket(&ESPkt->Length,ptype);
+ if (ESPkt->Data)
+ {
+ ESPkt->Type=ptype;
}
else
{
- queue->Clear();
- if (Offcnt) *Offcnt=true;
- return -1; // skip one byte (maybe we get another header!)
+ ESPkt->Type=0;
+ ESPkt->Length=0;
}
+ skipped+=queue->Skipped();
+ return true;
}
-void cMarkAdDemux::VDRTSAddPATPMT2Offset(MarkAdPid Pid, uchar *Data, int Count, bool *Offcnt)
+// ----------------------------------------------------------------------------
+
+cDemux::cDemux(int VPid, int DPid, int APid, bool H264, bool VDRCount)
{
- if (Pid.Num<0) return;
- if (Count<2) return;
- if ((Data[0]==0x47) && (Data[1]==0x40) && ((Data[2]==0) || (Data[2]==0x84))) *Offcnt=false;
+ vpid=(VPid!=0) ? VPid : -1;
+ dpid=(DPid!=0) ? DPid : -1;
+ apid=(APid!=0) ? APid : -1;
+ TS=false;
+ if ((vpid>0) || (dpid>0) || (apid>0)) TS=true;
+ pes2videoes=NULL;
+ pes2audioes_mp2=NULL;
+ pes2audioes_ac3=NULL;
+ ts2pkt_vpid=NULL;
+ ts2pkt_dpid=NULL;
+ ts2pkt_apid=NULL;
+ h264=H264;
+ vdrcount=VDRCount;
+ queue = new cPaketQueue("DEMUX",5640);
+ skipped=0;
+ Clear();
}
-int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, MarkAdPacket *Pkt)
+cDemux::~cDemux()
{
- if ((!Data) && (!Count) && (!Pkt)) return -1;
+ if (skipped) tsyslog("buffer skipped: %-15s %i bytes",queue->Name(),skipped);
+ if (queue) delete queue;
+
+ if (ts2pkt_vpid) delete ts2pkt_vpid;
+ if (pes2videoes) delete pes2videoes;
- uchar *in=NULL;
- int inlen=0;
- int retval=0;
+ if (ts2pkt_dpid) delete ts2pkt_dpid;
+ if (pes2audioes_ac3) delete pes2audioes_ac3;
+
+ if (ts2pkt_apid) delete ts2pkt_apid;
+ if (pes2audioes_mp2) delete pes2audioes_mp2;
+
+}
+
+int cDemux::Skipped()
+{
+ int val=skipped;
+ if (pes2videoes) val+=pes2videoes->Skipped();
+ if (pes2audioes_mp2) val+=pes2audioes_mp2->Skipped();
+ if (pes2audioes_ac3) val+=pes2audioes_ac3->Skipped();
+ if (ts2pkt_vpid) val+=ts2pkt_vpid->Skipped();
+ if (ts2pkt_dpid) val+=ts2pkt_dpid->Skipped();
+ if (ts2pkt_apid) val+=ts2pkt_apid->Skipped();
+ return val;
+}
- if (!pause)
+void cDemux::Clear()
+{
+ if (pes2videoes) pes2videoes->Clear();
+ if (pes2audioes_mp2) pes2audioes_mp2->Clear();
+ if (pes2audioes_ac3) pes2audioes_ac3->Clear();
+ if (ts2pkt_vpid) ts2pkt_vpid->Clear();
+ if (ts2pkt_dpid) ts2pkt_dpid->Clear();
+ if (ts2pkt_apid) ts2pkt_apid->Clear();
+
+ if (queue) queue->Clear();
+ offset=0;
+ vdroffset=0;
+ last_bplen=0;
+ from_oldfile=0;
+ stream_or_pid=0;
+}
+
+bool cDemux::isvideopes(uchar *data, int count)
+{
+ if (!data) return false;
+ if (count<6) return false;
+ if ((data[0]==0) && (data[1]==0) && (data[2]==1) &&
+ ((data[3] & 0xF0)==0xE0) &&
+ ((data[4]!=0) || (data[5]!=0))) return true;
+ return false;
+}
+
+int cDemux::checkts(uchar *data, int count, int &pid)
+{
+ if (count<(int) sizeof(struct TSHDR)) return -1;
+ if (data[0]!=0x47) return 1;
+
+ struct TSHDR *tshdr = (struct TSHDR *) data;
+ if ((tshdr->AFC<=0) || (tshdr->AFC>3)) return 1;
+
+ pid = (tshdr->PidH << 8) | tshdr->PidL;
+ return 0;
+}
+
+int cDemux::fillqueue(uchar *data, int count, int &stream_or_pid, int &packetsize, int &readout)
+{
+#define PEEKBUF 6
+ stream_or_pid=packetsize=readout=0;
+
+ uchar *qData=NULL;
+
+ while (!(qData=queue->Peek(PEEKBUF)))
{
- Pkt->Data=NULL;
- Pkt->Length=0;
- Pkt->Skipped=0;
- Pkt->Offcnt=false;
+ int len=PEEKBUF-queue->Length();
+ int cnt=(count>len) ? len : count;
+ if (!queue->Put(data,cnt)) return -1;
+ readout+=cnt;
+ data+=cnt;
+ count-=cnt;
+ if (queue->Length()<PEEKBUF) return cnt; // we need more data!
+ }
- if (!min_needed)
+ if (!TS)
+ {
+ if ((qData[0]==0) && (qData[1]==0) && (qData[2]==1) && (qData[3]>=0xBC))
{
- if (skip)
+ stream_or_pid=qData[3];
+ packetsize=PEEKBUF+(qData[4]*256+qData[5]);
+ }
+ else
+ {
+ skipped++;
+ stream_or_pid=0;
+ packetsize=1;
+ return 0;
+ }
+ }
+ else
+ {
+ int error_skipbytes=checkts(qData,PEEKBUF,stream_or_pid);
+ if (error_skipbytes==-1) return -1;
+ if (error_skipbytes)
+ {
+ skipped+=error_skipbytes;
+ stream_or_pid=0;
+ packetsize=1;
+ return error_skipbytes; // no useable data found, try next!
+ }
+ packetsize=TS_SIZE;
+ }
+
+ int needed=packetsize+PEEKBUF;
+ while (!(qData=queue->Peek(needed)))
+ {
+ int len=needed-queue->Length();
+ int cnt=(count>len) ? len : count;
+ if (!queue->Put(data,cnt)) return -1;
+ readout+=cnt;
+ data+=cnt;
+ count-=cnt;
+ if (queue->Length()<needed) return cnt; // we need more data!
+ }
+ if (!TS)
+ {
+ // check length of PES-paket
+ qData=queue->Peek(packetsize+PEEKBUF);
+ if (qData)
+ {
+ int start=packetsize;
+ if ((qData[start]!=0) || (qData[start+1]!=0) || (qData[start+2]!=1) || (qData[start+3]<0xBC))
{
- int t_skip=skip;
- skip=0;
- Pkt->Offcnt=true;
- return t_skip;
+ int start=queue->FindPesHeader(1);
+ if (start)
+ {
+ // broken PES in queue, skip it
+ packetsize=start;
+ skipped+=start;
+ stream_or_pid=0;
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
}
-
- int t_min_needed=GetMinNeeded(Pid,Data,Count,&Pkt->Offcnt);
- if (t_min_needed==0)
+ }
+ }
+ else
+ {
+ qData=queue->Peek(packetsize+PEEKBUF);
+ if (qData)
+ {
+ int start=packetsize;
+ int pid;
+ int ret=checkts(&qData[start],PEEKBUF,pid);
+ if (ret==-1)
{
return -1;
}
- if (t_min_needed<0)
+ if (ret)
{
- if (-t_min_needed>Count)
- {
- skip=-t_min_needed-Count;
- return Count;
- }
- if (t_min_needed==-1) Pkt->Skipped++;
- return -t_min_needed;
+ return -1;
}
- min_needed=t_min_needed;
}
+ }
+ return 0;
+}
- int needed=min_needed-queue->Length();
+bool cDemux::needmoredata()
+{
+ if (!stream_or_pid) return true;
- if (Count>needed)
+ if (!TS)
+ {
+ switch (stream_or_pid)
{
- queue->Put(Data,needed);
- retval=needed;
+ case 0xE0:
+ if (pes2videoes) return pes2videoes->NeedMoreData();
+ break;
+ case 0xC0:
+ if (pes2audioes_mp2) return pes2audioes_mp2->NeedMoreData();
+ break;
+ case 0xBD:
+ if (pes2audioes_ac3) return pes2audioes_ac3->NeedMoreData();
+ break;
}
- else
+ }
+
+ if (TS)
+ {
+ if ((stream_or_pid==vpid) && (ts2pkt_vpid))
{
- queue->Put(Data,Count);
- retval=Count;
+ if (pes2videoes) return pes2videoes->NeedMoreData();
+ return ts2pkt_vpid->NeedMoreData();
}
- if (queue->Length()<min_needed)
+ if ((stream_or_pid==dpid) && (ts2pkt_dpid))
{
- return Count;
+ if (pes2audioes_ac3) return pes2audioes_ac3->NeedMoreData();
+ return ts2pkt_dpid->NeedMoreData();
+ }
+ if ((stream_or_pid==apid) && (ts2pkt_apid))
+ {
+ if (pes2audioes_mp2) return pes2audioes_mp2->NeedMoreData();
+ return ts2pkt_apid->NeedMoreData();
}
- inlen=min_needed;
- in=queue->Get(&inlen);
- min_needed=0;
}
+ return false;
+}
- if (Pid.Num>=0)
+bool cDemux::vdraddpatpmt(uchar *data, int count)
+{
+ // TS-VDR adds pat/pmt to the output, e.g. if
+ // a picture starts @376, vdr outputs 0 (!)
+ int pid;
+ if (checkts(data,count,pid)!=0) return false;
+ if ((!pid) || (pid==132))
{
- ProcessTS(Pid, in, inlen, Pkt);
+ last_bplen=0;
+ vdroffset+=count;
}
else
{
- ProcessVDR(Pid, in, inlen, Pkt);
+ last_bplen=vdroffset+count;
+ vdroffset=0;
}
+ return true;
+}
- if (Pkt->Data)
+void cDemux::addoffset()
+{
+ offset+=last_bplen;
+ if (from_oldfile)
{
- if (!pause_retval) pause_retval=retval;
- pause=true;
- return 0;
+ from_oldfile-=last_bplen;
+ if (!from_oldfile) offset=0;
}
+ last_bplen=0;
+}
+
+void cDemux::NewFile()
+{
+ from_oldfile=queue->Length();
+}
+
+int cDemux::Process(uchar *Data, int Count, AvPacket *pkt)
+{
+ if (!pkt) return -1;
+ pkt->Data=NULL;
+ pkt->Length=0;
+
+ bool add=needmoredata();
- if (pause)
+ int bplen=0,readout=0;
+ uchar *bpkt=NULL;
+ if (add)
+ {
+ addoffset();
+ int advance=fillqueue(Data,Count,stream_or_pid,bplen,readout);
+ if (advance<0) return -1;
+ if (advance) return advance;
+ bpkt=queue->Get(&bplen);
+ if (!bpkt) return -1;
+ last_bplen=bplen;
+ if (vdrcount) vdraddpatpmt(bpkt,bplen);
+ }
+
+ if (!TS)
+ {
+ switch (stream_or_pid)
+ {
+ case 0xE0:
+ if (!pes2videoes)
+ {
+ if (h264)
+ {
+ pes2videoes=new cPES2ES(PACKET_H264,"PES2H264ES",524288);
+ }
+ else
+ {
+ pes2videoes=new cPES2ES(PACKET_H262,"PES2H262ES",65536);
+ }
+ }
+ if (!pes2videoes->Process(bpkt,bplen,pkt)) return -1;
+ break;
+ case 0xC0:
+ if (!pes2audioes_mp2) pes2audioes_mp2=new cPES2ES(PACKET_MP2,"PES2MP2",16384);
+ if (!pes2audioes_mp2->Process(bpkt,bplen,pkt)) return -1;
+ break;
+ case 0xBD:
+ if (!pes2audioes_ac3) pes2audioes_ac3=new cPES2ES(PACKET_AC3,"PES2AC3");
+ if (!pes2audioes_ac3->Process(bpkt,bplen,pkt)) return -1;
+ break;
+ default:
+ stream_or_pid=0;
+ break;
+ }
+ }
+ if (TS)
{
- if (pause_retval)
+ if (stream_or_pid==vpid)
+ {
+ if (!ts2pkt_vpid)
+ {
+ if (h264)
+ {
+ ts2pkt_vpid=new cTS2Pkt(vpid,"TS2H264",524288,true);
+ }
+ else
+ {
+ ts2pkt_vpid=new cTS2Pkt(vpid,"TS2H262",65536);
+ }
+ }
+ if (!ts2pkt_vpid->Process(bpkt,bplen,pkt)) return -1;
+ if (isvideopes(pkt->Data,pkt->Length) || pes2videoes)
+ {
+ AvPacket tpkt;
+ memcpy(&tpkt,pkt,sizeof(AvPacket));
+ memset(pkt,0,sizeof(AvPacket));
+ if (!pes2videoes)
+ {
+ ts2pkt_vpid->Resize(3*tpkt.Length,"TS2PES");
+ if (h264)
+ {
+ pes2videoes=new cPES2ES(PACKET_H264,"PES2H264ES",524288);
+ }
+ else
+ {
+ pes2videoes=new cPES2ES(PACKET_H262,"PES2H262ES",65536);
+ }
+ }
+ if (!pes2videoes->Process(tpkt.Data,tpkt.Length,pkt)) return -1;
+ }
+ }
+ else if (stream_or_pid==dpid)
{
- retval=pause_retval;
- pause_retval=0;
+ AvPacket tpkt={NULL,0,0};
+ if (!ts2pkt_dpid) ts2pkt_dpid=new cTS2Pkt(dpid,"TS2PES AC3");
+ if (!ts2pkt_dpid->Process(bpkt,bplen,&tpkt)) return -1;
+ if (!pes2audioes_ac3) pes2audioes_ac3=new cPES2ES(PACKET_AC3,"PES2AC3");
+ if (!pes2audioes_ac3->Process(tpkt.Data,tpkt.Length,pkt)) return -1;
}
- pause=false;
+ else if (stream_or_pid==apid)
+ {
+ AvPacket tpkt={NULL,0,0};
+ if (!ts2pkt_apid) ts2pkt_apid=new cTS2Pkt(apid,"TS2PES MP2",16384);
+ if (!ts2pkt_apid->Process(bpkt,bplen,&tpkt)) return -1;
+ if (!pes2audioes_mp2) pes2audioes_mp2=new cPES2ES(PACKET_MP2,"PES2MP2",16384);
+ if (!pes2audioes_mp2->Process(tpkt.Data,tpkt.Length,pkt)) return -1;
+ }
+ else stream_or_pid=0;
}
-
- Pkt->Offcnt=true;
- VDRTSAddPATPMT2Offset(Pid, in, inlen, &Pkt->Offcnt);
- return retval;
+ return add ? readout : 0;
}
diff --git a/command/demux.h b/command/demux.h
index 0c91c7a..4213479 100644
--- a/command/demux.h
+++ b/command/demux.h
@@ -8,39 +8,322 @@
#ifndef __demux_h_
#define __demux_h_
-#ifndef TS_SIZE
-#define TS_SIZE 188
+#include <stdint.h>
+
+#ifndef uchar
+typedef unsigned char uchar;
#endif
-#define PESHDRSIZE 6
+#define PACKET_MASK 0xF0
+#define PACKET_VIDEO 0x10
+#define PACKET_H262 0x10 // 0x00 0x00 0x01 (PES / H262)
+#define PACKET_H264 0x11 // 0x00 0x00 0x00 0x01 (H264)
+#define PACKET_AUDIO 0x20
+#define PACKET_AC3 0x20
+#define PACKET_MP2 0x21
+
+typedef struct AvPacket
+{
+ uchar *Data;
+ int Length;
+ int Type;
+} AvPacket;
+
+struct TSHDR
+{
+unsigned Sync:
+ 8;
+unsigned PidH:
+ 5;
+unsigned Priority:
+ 1;
+unsigned PayloadStart:
+ 1;
+unsigned TError:
+ 1;
+unsigned PidL:
+ 8;
+unsigned Counter:
+ 4;
+unsigned AFC:
+ 2;
+unsigned TSC:
+ 2;
+};
+
+struct PESHDR
+{
+ uchar Sync1;
+ uchar Sync2;
+ uchar Sync3;
+ uchar StreamID;
+ uchar LenH;
+ uchar LenL;
+};
+
+#pragma pack(1)
+struct PESHDROPT
+{
+unsigned OOC:
+ 1;
+unsigned CY:
+ 1;
+unsigned DAI:
+ 1;
+unsigned PESP:
+ 1;
+unsigned PESSC:
+ 2;
+unsigned MarkerBits:
+ 2;
+unsigned EXT:
+ 1;
+unsigned CRC:
+ 1;
+unsigned ACI:
+ 1;
+unsigned TM:
+ 1;
+unsigned RATE:
+ 1;
+unsigned ESCR:
+ 1;
+unsigned PTSDTS:
+ 2;
+unsigned Length:
+ 8;
+};
+#pragma pack()
+
+// ----------------------------------------------------------------------------
+
+class cPaketQueue
+{
+ struct MP2HDR
+ {
+unsigned Sync1:
+ 8;
+unsigned Protection:
+ 1;
+unsigned Layer:
+ 2;
+unsigned MpegID:
+ 2;
+unsigned Sync2:
+ 3;
+unsigned Private:
+ 1;
+unsigned Padding:
+ 1;
+unsigned SampleRateIndex:
+ 2;
+unsigned BitRateIndex:
+ 4;
+unsigned Emphasis:
+ 2;
+unsigned Original:
+ 1;
+unsigned Copyright:
+ 1;
+unsigned ModeExt:
+ 2;
+unsigned Mode:
+ 2;
+ };
+
+#pragma pack(1)
+ struct AC3HDR
+ {
+unsigned Sync1:
+ 8;
+unsigned Sync2:
+ 8;
+unsigned CRC1:
+ 8;
+unsigned CRC2:
+ 8;
+unsigned FrameSizeIndex:
+ 6;
+unsigned SampleRateIndex:
+ 2;
+ };
+#pragma pack()
+
+private:
+ const char *name;
+ struct pktinfo
+ {
+ int pkthdr;
+ int pktsyncsize;
+ int streamsize;
+ bool ispes;
+ } pktinfo;
+
+ int percent;
+ int mpercent; // max percentage use
+
+ uchar *buffer;
+ int maxqueue;
+ int inptr;
+ int outptr;
+
+ int skipped;
-#include "queue.h"
-#include "ts2pkt.h"
-#include "pes2es.h"
+ uint32_t scanner;
+ int scannerstart;
-class cMarkAdDemux
+ int findaudioheader(int start, int *framesize, int *headersize, bool ac3);
+ int findpktheader(int start, int *streamsize,int *headersize, bool longstartcode, bool pesonly);
+public:
+ cPaketQueue(const char *Name, int Size=32768);
+ ~cPaketQueue();
+ int Length()
+ {
+ return inptr-outptr;
+ }
+ const char *Name()
+ {
+ return name;
+ }
+ void Clear();
+ int Skipped()
+ {
+ return skipped;
+ }
+ bool Put(uchar *Data, int Size);
+ uchar *Get(int *Size);
+ uchar *Peek(int Size);
+ uchar *GetPacket(int *Size, int Type);
+ void Resize(int NewSize, const char *NewName=NULL);
+ bool NeedMoreData()
+ {
+ if (scannerstart==-1) return true;
+ if (pktinfo.streamsize)
+ {
+ return (((inptr-pktinfo.pkthdr)-outptr)<=(pktinfo.streamsize+6));
+ }
+ else
+ {
+ return ((scannerstart==inptr) || (scannerstart==outptr));
+ }
+ }
+ int FindPesHeader(int Start);
+};
+
+// ----------------------------------------------------------------------------
+
+class cTS2Pkt
{
+private:
+ cPaketQueue *queue;
+ int counter;
+ bool sync;
+ bool firstsync;
+ int skipped;
+ int pid;
+ bool h264;
+ bool noticeFILLER;
+ bool noticeSEQUENCE;
+ bool noticeSTREAM;
+public:
+ cTS2Pkt(int Pid, const char *QueueName="TS2Pkt", int QueueSize=32768, bool H264=false);
+ ~cTS2Pkt();
+ void Clear();
+ int Skipped()
+ {
+ return skipped;
+ }
+ bool Process(uchar *TSData, int TSSize, AvPacket *Pkt);
+ void Resize(int NewQueueSize, const char *NewQueueName)
+ {
+ queue->Resize(NewQueueSize, NewQueueName);
+ }
+ bool NeedMoreData()
+ {
+ if (queue)
+ {
+ return queue->NeedMoreData();
+ }
+ else
+ {
+ return false;
+ }
+ }
+};
+// ----------------------------------------------------------------------------
+
+class cPES2ES
+{
private:
- cMarkAdTS2Pkt *ts2pkt;
- cMarkAdPES2ES *pes2audioes;
- cMarkAdPES2ES *pes2videoes;
- cMarkAdPaketQueue *queue;
-
- bool pause;
- int pause_retval;
- int min_needed;
- int skip;
-
- int GetMinNeeded(MarkAdPid Pid, uchar *Data, int Count, bool *Offcnt);
- void ProcessTS(MarkAdPid Pid, uchar *Data, int Count, MarkAdPacket *pkt);
- void ProcessVDR(MarkAdPid Pid, uchar *Data, int Count, MarkAdPacket *pkt);
- void VDRTSAddPATPMT2Offset(MarkAdPid Pid, uchar *Data, int Count, bool *Offcnt);
+ cPaketQueue *queue;
+ int skipped;
+ int ptype;
+ bool h264;
+public:
+ cPES2ES(int PacketType, const char *QueueName="PES2ES", int QueueSize=32768);
+ ~cPES2ES();
+ void Clear();
+ bool Process(uchar *PESData, int PESSize, AvPacket *ESPkt);
+ int Skipped()
+ {
+ return skipped;
+ }
+ bool NeedMoreData()
+ {
+ if (queue)
+ {
+ return queue->NeedMoreData();
+ }
+ else
+ {
+ return false;
+ }
+ }
+};
+
+// ----------------------------------------------------------------------------
+
+class cDemux
+{
+private:
+ int vpid,dpid,apid;
+ int stream_or_pid;
+ int skipped;
+ bool h264;
+ bool TS;
+ uint64_t offset;
+ int from_oldfile;
+ int last_bplen;
+
+ bool vdrcount;
+ int vdroffset;
+ bool vdraddpatpmt(uchar *data, int count);
+
+ void addoffset();
+
+ cPaketQueue *queue;
+ cPES2ES *pes2videoes;
+ cPES2ES *pes2audioes_mp2;
+ cPES2ES *pes2audioes_ac3;
+ cTS2Pkt *ts2pkt_vpid;
+ cTS2Pkt *ts2pkt_dpid;
+ cTS2Pkt *ts2pkt_apid;
+ bool needmoredata();
+ int checkts(uchar *data, int count, int &pid);
+ bool isvideopes(uchar *data, int count);
+ int fillqueue(uchar *data, int count, int &stream_or_pid, int &packetsize, int &readout);
public:
- cMarkAdDemux();
- ~cMarkAdDemux();
+ cDemux(int VPid, int DPid, int APid, bool H264=false, bool VDRCount=false);
+ ~cDemux();
void Clear();
- int Process(MarkAdPid Pid, uchar *Data, int Count, MarkAdPacket *pkt);
+ int Skipped();
+ void NewFile();
+ uint64_t Offset()
+ {
+ return offset;
+ }
+ int Process(uchar *Data, int Count, AvPacket *pkt);
};
#endif
diff --git a/command/global.h b/command/global.h
index 52764ee..bfd4703 100644
--- a/command/global.h
+++ b/command/global.h
@@ -34,23 +34,21 @@ typedef unsigned char uchar;
#define MT_ASSUMEDSTART 0x21
#define MT_ASSUMEDSTOP 0x22
-#define MT_ASPECTCHANGE 0x30
-#define MT_ASPECTSTART 0x31
-#define MT_ASPECTSTOP 0x32
+#define MT_LOGOCHANGE 0x30
+#define MT_LOGOSTART 0x31
+#define MT_LOGOSTOP 0x32
-#define MT_CHANNELCHANGE 0x40
-#define MT_CHANNELSTART 0x41
-#define MT_CHANNELSTOP 0x42
+#define MT_BORDERCHANGE 0x40
+#define MT_BORDERSTART 0x41
+#define MT_BORDERSTOP 0x42
-#define MT_LOGOCHANGE 0x50
-#define MT_LOGOSTART 0x51
-#define MT_LOGOSTOP 0x52
+#define MT_ASPECTCHANGE 0x50
+#define MT_ASPECTSTART 0x51
+#define MT_ASPECTSTOP 0x52
-#define MT_BORDERCHANGE 0x60
-#define MT_BORDERSTART 0x61
-#define MT_BORDERSTOP 0x62
-
-#define MT_SILENCECHANGE 0x90
+#define MT_CHANNELCHANGE 0x60
+#define MT_CHANNELSTART 0x61
+#define MT_CHANNELSTOP 0x62
#define MT_MOVED 0xE0
#define MT_ALL 0xFF
@@ -125,9 +123,11 @@ typedef struct MarkAdContext
struct Info
{
+
+ MarkAdAspectRatio AspectRatio;
int Channels;
+
char *ChannelName;
- MarkAdAspectRatio AspectRatio;
MarkAdPid VPid;
MarkAdPid APid;
MarkAdPid DPid;
diff --git a/command/markad-standalone.cpp b/command/markad-standalone.cpp
index 3d129a6..70d9aa7 100644
--- a/command/markad-standalone.cpp
+++ b/command/markad-standalone.cpp
@@ -179,6 +179,32 @@ int cOSDMessage::Send(const char *format, ...)
return 0;
}
+void cMarkAdStandalone::AddStartMark()
+{
+#if 0
+ char *buf;
+ if (asprintf(&buf,"start of recording (0)")!=-1)
+ {
+ MarkAdMark Mark;
+ Mark.Position=0;
+ Mark.Type=MT_COMMONSTART;
+ Mark.Comment=buf;
+ AddMark(&Mark);
+ free(buf);
+ }
+#endif
+
+ if (tStart)
+ {
+ iStart=-(tStart*macontext.Video.Info.FramesPerSecond);
+ }
+ CalculateStopPosition(-iStart,macontext.Video.Info.FramesPerSecond*MAXRANGE);
+ if (tStart==1)
+ {
+ tStart=iStart=0;
+ }
+}
+
void cMarkAdStandalone::CalculateStopPosition(int startframe, int delta)
{
if (!length) return;
@@ -199,29 +225,7 @@ void cMarkAdStandalone::CalculateStopPosition(int startframe, int delta)
}
}
-void cMarkAdStandalone::AddStartMark()
-{
- if (tStart<2)
- {
- char *buf;
- if (asprintf(&buf,"start of recording (0)")!=-1)
- {
- marks.Add(MT_COMMONSTART,0,buf);
- isyslog("%s",buf);
- free(buf);
- }
- }
- if (tStart)
- {
- iStart=-(tStart*macontext.Video.Info.FramesPerSecond);
- }
- CalculateStopPosition(-iStart,macontext.Video.Info.FramesPerSecond*MAXRANGE);
- if (tStart==1)
- {
- tStart=iStart=0;
- }
-}
-
+#if 0
void cMarkAdStandalone::CheckStartStop(int frame, bool checkend)
{
MarkAdMark mark;
@@ -233,7 +237,7 @@ void cMarkAdStandalone::CheckStartStop(int frame, bool checkend)
clMark *before_iStart=marks.GetPrev(iStart,MT_START,0xF);
clMark *after_iStart=marks.GetNext(iStart,MT_START,0xF);
- int MAXMARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*MAXRANGE);
+ int MAXMARKDIFF=MAXRANGE*macontext.Video.Info.FramesPerSecond;
int type=0;
int newpos=0;
int delta_before=MAXMARKDIFF;
@@ -352,12 +356,11 @@ void cMarkAdStandalone::CheckStartStop(int frame, bool checkend)
AddMark(&mark);
free(buf);
}
-
- int MARKDIFF=length/6;
- if (MARKDIFF>MAXRANGE) MARKDIFF=MAXRANGE;
- MARKDIFF=(int) (MARKDIFF*macontext.Video.Info.FramesPerSecond);
- iStartCheck=iStart+MARKDIFF;
- CalculateStopPosition(iStart,MARKDIFF);
+ int MAXMARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*MAXRANGE);
+ iStartCheck=iStart+MAXMARKDIFF;
+ int CHECKPOINT=(int) ((length*macontext.Video.Info.FramesPerSecond)/18);
+ if (CHECKPOINT>MAXMARKDIFF) CHECKPOINT=MAXMARKDIFF;
+ CalculateStopPosition(iStart,CHECKPOINT);
}
if ((iStop<0) && (lastiframe>-iStop))
{
@@ -597,7 +600,7 @@ void cMarkAdStandalone::AddMark(MarkAdMark *Mark)
}
if (prev->type==MT_ASPECTSTART)
{
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*240);
+ int MARKDIFF=(int) macontext.Video.Info.FramesPerSecond;
if ((Mark->Position-prev->position)<MARKDIFF)
{
if (Mark->Comment) isyslog("%s",Mark->Comment);
@@ -793,12 +796,75 @@ void cMarkAdStandalone::AddMark(MarkAdMark *Mark)
marks.Del((uchar) MT_BORDERSTOP);
}
}
- if (Mark->Position>chkLEFT) CheckFirstMark();
+ if ((iStart==0) && (!marksAligned)) CheckFirstMark();
if (marksAligned) CheckLogoMarks(marks.GetLast());
if ((Mark->Comment) && (!loggedAlready)) isyslog("%s",Mark->Comment);
marks.Add(Mark->Type,Mark->Position,Mark->Comment);
}
+#endif
+
+void cMarkAdStandalone::AddMark(MarkAdMark *Mark)
+{
+ if (!Mark) return;
+ if (!Mark->Type) return;
+
+ if ((Mark->Type & 0x0F)==MT_STOP)
+ {
+ clMark *prev=marks.GetPrev(Mark->Position,(Mark->Type & 0xF0)|MT_START);
+ if (prev)
+ {
+ int MARKDIFF;
+ if ((Mark->Type & 0xF0)==MT_LOGOCHANGE)
+ {
+ MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*240);
+ }
+ else
+ {
+ MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*10);
+ }
+ if ((Mark->Position-prev->position)<MARKDIFF)
+ {
+ if (Mark->Comment) isyslog("%s",Mark->Comment);
+ double distance=(Mark->Position-prev->position)/macontext.Video.Info.FramesPerSecond;
+ isyslog("mark distance too short (%.1fs), deleting %i,%i",distance,
+ prev->position,Mark->Position);
+ marks.Del(prev);
+ return;
+ }
+ }
+ }
+
+ clMark *prev=marks.GetLast();
+ if (prev)
+ {
+ if ((prev->type & 0x0F)==(Mark->Type & 0x0F))
+ {
+ int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*30);
+ int diff=abs(Mark->Position-prev->position);
+ if (diff<MARKDIFF)
+ {
+ if (Mark->Comment) isyslog("%s",Mark->Comment);
+ if (prev->type>Mark->Type)
+ {
+ isyslog("previous mark (%i) stronger than actual mark, deleting %i",
+ prev->position, Mark->Position);
+ return;
+ }
+ else
+ {
+ isyslog("actual mark stronger then previous mark, deleting %i",prev->position);
+ marks.Del(prev);
+ marks.Add(Mark->Type,Mark->Position,Mark->Comment);
+ return;
+ }
+ }
+ }
+ }
+
+ isyslog("%s",Mark->Comment);
+ marks.Add(Mark->Type,Mark->Position,Mark->Comment);
+}
void cMarkAdStandalone::SaveFrame(int frame)
{
@@ -825,6 +891,7 @@ void cMarkAdStandalone::SaveFrame(int frame)
fclose(pFile);
}
+#if 0
void cMarkAdStandalone::CheckBroadcastLength()
{
if (length) return;
@@ -838,6 +905,7 @@ void cMarkAdStandalone::CheckBroadcastLength()
isyslog("got broadcast length of %im from index",length/60);
reprocess=true;
}
+#endif
bool cMarkAdStandalone::CheckIndexGrowing()
{
@@ -950,12 +1018,12 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu
if (Mark1 && Mark2)
{
if (!(*Mark1) || !(*Mark2)) return false;
- if (*Mark1==*Mark2) pn=1;
- if (*Mark1!=*Mark2) pn=3;
+ if (*Mark1==*Mark2) pn=mSTART;
+ if (*Mark1!=*Mark2) pn=mAFTER;
}
else
{
- pn=2;
+ pn=mBEFORE;
}
if (!Reset(false))
@@ -992,13 +1060,13 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu
if (f==-1) return false;
int dataread;
- if (pn==1)
+ if (pn==mSTART)
{
dsyslog("processing file %05i (start mark)",Number);
}
else
{
- dsyslog("processing file %05i %s",Number,(pn==3) ? "(after mark)" : "(before mark)");
+ dsyslog("processing file %05i %s",Number,(pn==mAFTER) ? "(after mark)" : "(before mark)");
}
if (lseek(f,Offset,SEEK_SET)!=Offset)
@@ -1007,32 +1075,30 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu
return false;
}
- uint64_t offset=Offset;
- int offset_add=0;
while ((dataread=read(f,data,datalen))>0)
{
if (abort) break;
- if ((video_demux) && (video) && (decoder) && (streaminfo))
+ if ((demux) && (video) && (decoder) && (streaminfo))
{
uchar *tspkt = data;
int tslen = dataread;
while (tslen>0)
{
- int len=video_demux->Process(macontext.Info.VPid,tspkt,tslen,&vpkt);
+ int len=demux->Process(tspkt,tslen,&pkt);
if (len<0)
{
- esyslog("error demuxing video");
+ esyslog("error demuxing file");
abort=true;
break;
}
else
{
- if (vpkt.Data)
+ if ((pkt.Data) && ((pkt.Type & PACKET_MASK)==PACKET_VIDEO))
{
bool dRes=false;
- if (streaminfo->FindVideoInfos(&macontext,vpkt.Data,vpkt.Length))
+ if (streaminfo->FindVideoInfos(&macontext,pkt.Data,pkt.Length))
{
actframe++;
framecnt2++;
@@ -1051,16 +1117,16 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu
dRes=true;
}
}
- if (pn>1) dRes=decoder->DecodeVideo(&macontext,vpkt.Data,vpkt.Length);
+ if (pn>mSTART) dRes=decoder->DecodeVideo(&macontext,pkt.Data,pkt.Length);
if (dRes)
{
if ((actframe-iframe)<=3)
{
- if (pn>1) pos=video->Process2ndPass(lastiframe,Frames,(pn==2));
+ if (pn>mSTART) pos=video->Process2ndPass(lastiframe,Frames,(pn==mBEFORE));
//SaveFrame(lastiframe);
framecounter++;
}
- if ((pos) && (pn==3))
+ if ((pos) && (pn==mAFTER))
{
// found overlap
ChangeMarks(Mark1,Mark2,pos);
@@ -1071,54 +1137,10 @@ bool cMarkAdStandalone::ProcessFile2ndPass(clMark **Mark1, clMark **Mark2,int Nu
}
tspkt+=len;
tslen-=len;
- if (!vpkt.Offcnt)
- {
- offset_add+=len;
- }
- else
- {
- offset+=offset_add;
- offset+=len;
- offset_add=0;
- }
}
}
}
-#if 0
- if ((mp2_demux) && (audio) && (pn!=3))
- {
- uchar *tspkt = data;
- int tslen = dataread;
-
- while (tslen>0)
- {
- int len=mp2_demux->Process(macontext.Info.APid,tspkt,tslen,&apkt);
- if (len<0)
- {
- esyslog("error demuxing mp2-audio");
- break;
- }
- else
- {
- if (apkt.Data)
- {
- if (apkt.Timestamp) audiotime=apkt.Timestamp;
- if (abs(audiotime-lastiframetime)<DELTATIME)
- {
- if (decoder->DecodeMP2(&macontext,apkt.Data,apkt.length))
- {
- pos=audio->Process2ndPass(iframe);
- if (pos) ChangeMarks(Mark1,NULL,pos);
- }
- }
- }
- tspkt+=len;
- tslen-=len;
- }
- }
- }
-#endif
if (abort)
{
close(f);
@@ -1161,24 +1183,7 @@ void cMarkAdStandalone::Process2ndPass()
bool infoheader=false;
clMark *p1=NULL,*p2=NULL;
-#if 0
- p1=marks.GetFirst();
- if (!p1) return;
- if (p1->position>0)
- {
- isyslog("2nd pass");
- infoheader=true;
- off_t offset;
- int number,frame,iframes;
- int frange=macontext.Video.Info.FramesPerSecond*120;
-
- if (marks.ReadIndex(directory,isTS,p1->position-(frange/10),frange,&number,&offset,&frame,&iframes))
- {
- ProcessFile2ndPass(&p1,&p1,number,offset,frame,iframes);
- }
- }
-#endif
- if (marks.Count()<4) return; // here we cannot do much
+ if (marks.Count()<4) return; // we cannot do much without marks
p1=marks.GetFirst();
if (!p1) return;
@@ -1232,7 +1237,7 @@ bool cMarkAdStandalone::ProcessFile(int Number)
if (!directory) return false;
if (!Number) return false;
- if (!CheckIndexGrowing()) CheckBroadcastLength();
+ CheckIndexGrowing();
if (abort) return false;
@@ -1256,159 +1261,121 @@ bool cMarkAdStandalone::ProcessFile(int Number)
int dataread;
dsyslog("processing file %05i",Number);
- uint64_t offset=0;
- int offset_add=0;
+ demux->NewFile();
while ((dataread=read(f,data,datalen))>0)
{
if (abort) break;
-
- if ((video_demux) && (video) && (streaminfo))
+ if ((demux) && (video) && (streaminfo))
{
uchar *tspkt = data;
int tslen = dataread;
-
while (tslen>0)
{
- int len=video_demux->Process(macontext.Info.VPid,tspkt,tslen,&vpkt);
+ int len=demux->Process(tspkt,tslen,&pkt);
if (len<0)
{
- esyslog("error demuxing video");
+ esyslog("error demuxing");
abort=true;
break;
}
else
{
- if (vpkt.Data)
+ if (pkt.Data)
{
- if ((macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264) && (!noticeFILLER))
+ if ((pkt.Type & PACKET_MASK)==PACKET_VIDEO)
{
- if ((vpkt.Data[4] & 0x1F)==0x0C)
+ bool dRes=false;
+ if (streaminfo->FindVideoInfos(&macontext,pkt.Data,pkt.Length))
{
- isyslog("H264 video stream with filler nalu");
- noticeFILLER=true;
- }
- }
+ if ((macontext.Video.Info.Height) && (!noticeHEADER))
+ {
+ isyslog("%s %ix%i%c%0.f",(macontext.Video.Info.Height>576) ? "HDTV" : "SDTV",
+ macontext.Video.Info.Width,
+ macontext.Video.Info.Height,
+ macontext.Video.Info.Interlaced ? 'i' : 'p',
+ macontext.Video.Info.FramesPerSecond);
+ noticeHEADER=true;
+ }
- bool dRes=false;
- if (streaminfo->FindVideoInfos(&macontext,vpkt.Data,vpkt.Length))
- {
- if ((macontext.Video.Info.Height) && (!noticeHEADER))
- {
- isyslog("%s %ix%i%c%0.f",(macontext.Video.Info.Height>576) ? "HDTV" : "SDTV",
- macontext.Video.Info.Width,
- macontext.Video.Info.Height,
- macontext.Video.Info.Interlaced ? 'i' : 'p',
- macontext.Video.Info.FramesPerSecond);
- noticeHEADER=true;
- }
+ if (!framecnt)
+ {
+ AddStartMark();
+ }
+ if (macontext.Config->GenIndex)
+ {
+ marks.WriteIndex(directory,isTS,demux->Offset(),macontext.Video.Info.Pict_Type,Number);
+ }
+ framecnt++;
- if (!framecnt)
- {
- AddStartMark();
+ if (macontext.Video.Info.Pict_Type==MA_I_TYPE)
+ {
+ lastiframe=iframe;
+#if 0
+ CheckStartStop(lastiframe);
+ if (lastiframe>chkLEFT) CheckAspectRatio_and_AudioChannels();
+#endif
+ iframe=framecnt-1;
+ dRes=true;
+ }
}
-
- if (macontext.Config->GenIndex)
+ if (macontext.Video.Info.FramesPerSecond<0)
{
- marks.WriteIndex(directory,isTS,offset,macontext.Video.Info.Pict_Type,Number);
+ macontext.Video.Info.FramesPerSecond*=-1;
+ isyslog("using framerate of %.f",macontext.Video.Info.FramesPerSecond);
}
- framecnt++;
- if (macontext.Video.Info.Pict_Type==MA_I_TYPE)
+ if ((decoder) && (bDecodeVideo))
+ dRes=decoder->DecodeVideo(&macontext,pkt.Data,pkt.Length);
+ if (dRes)
{
- lastiframe=iframe;
- CheckStartStop(lastiframe);
- if (lastiframe>chkLEFT) CheckAspectRatio_and_AudioChannels();
- iframe=framecnt-1;
- dRes=true;
+ if ((framecnt-iframe)<=3)
+ {
+ MarkAdMarks *vmarks=video->Process(lastiframe,iframe);
+ if (vmarks)
+ {
+ for (int i=0; i<vmarks->Count; i++)
+ {
+ AddMark(&vmarks->Number[i]);
+ }
+ }
+ SaveFrame(lastiframe); // TODO: JUST FOR DEBUGGING!
+ }
}
}
- if (macontext.Video.Info.FramesPerSecond<0)
- {
- macontext.Video.Info.FramesPerSecond*=-1;
- isyslog("using framerate of %.f",macontext.Video.Info.FramesPerSecond);
- }
- if ((decoder) && (bDecodeVideo))
- dRes=decoder->DecodeVideo(&macontext,vpkt.Data,vpkt.Length);
- if (dRes)
+ if ((pkt.Type & PACKET_MASK)==PACKET_AC3)
{
- if ((framecnt-iframe)<=3)
+ if (streaminfo->FindAC3AudioInfos(&macontext,pkt.Data,pkt.Length))
{
- MarkAdMarks *vmarks;
- vmarks=video->Process(lastiframe,iframe);
- if (vmarks)
+ if ((!isTS) && (!noticeVDR_AC3))
{
- for (int i=0; i<vmarks->Count; i++)
+ isyslog("found AC3%s",macontext.Config->AC3Always ? "*" : "");
+ noticeVDR_AC3=true;
+ }
+ if ((framecnt-iframe)<=3)
+ {
+ MarkAdMark *amark=audio->Process(lastiframe,iframe);
+ if (amark)
{
- AddMark(&vmarks->Number[i]);
+ AddMark(amark);
}
}
- //SaveFrame(lastiframe); // TODO: JUST FOR DEBUGGING!
}
}
}
- if (vpkt.Skipped)
- {
- errcnt+=vpkt.Skipped;
- }
- tspkt+=len;
- tslen-=len;
- if (!vpkt.Offcnt)
- {
- offset_add+=len;
- }
- else
- {
- offset+=offset_add;
- offset+=len;
- offset_add=0;
- }
- }
- }
- }
- if ((ac3_demux) && (streaminfo) && (audio))
- {
- uchar *tspkt = data;
- int tslen = dataread;
-
- while (tslen>0)
- {
- int len=ac3_demux->Process(macontext.Info.DPid,tspkt,tslen,&apkt);
- if (len<0)
- {
- esyslog("error demuxing ac3-audio");
- break;
- }
- else
- {
- if (apkt.Data)
- {
- if (streaminfo->FindAC3AudioInfos(&macontext,apkt.Data,apkt.Length))
- {
- if ((!isTS) && (!noticeVDR_AC3))
- {
- isyslog("found AC3%s",macontext.Config->AC3Always ? "*" : "");
- noticeVDR_AC3=true;
- }
- MarkAdMark *amark;
- amark=audio->Process(lastiframe,iframe);
- if (amark) AddMark(amark);
- }
- }
tspkt+=len;
tslen-=len;
}
}
}
-
if (((gotendmark) && (!macontext.Config->GenIndex)) || (reprocess))
{
if (f!=-1) close(f);
return true;
}
- if (!CheckIndexGrowing()) CheckBroadcastLength();
+ CheckIndexGrowing();
if (abort)
{
if (f!=-1) close(f);
@@ -1429,8 +1396,7 @@ bool cMarkAdStandalone::Reset(bool FirstPass)
gotendmark=false;
- memset(&vpkt,0,sizeof(vpkt));
- memset(&apkt,0,sizeof(apkt));
+ memset(&pkt,0,sizeof(pkt));
iStart=iStartCheck=iStop=iStopCheck=0;
chkLEFT=INT_MAX;
@@ -1453,9 +1419,7 @@ bool cMarkAdStandalone::Reset(bool FirstPass)
ret=decoder->Clear();
}
if (streaminfo) streaminfo->Clear();
- if (video_demux) video_demux->Clear();
- if (ac3_demux) ac3_demux->Clear();
- if (mp2_demux) mp2_demux->Clear();
+ if (demux) demux->Clear();
if (video) video->Clear();
if (audio) audio->Clear();
return ret;
@@ -1480,8 +1444,9 @@ void cMarkAdStandalone::ProcessFile()
{
if (lastiframe)
{
+#if 0
CheckStartStop(lastiframe,true);
-
+#endif
if ((!gotendmark) && ((iStop<0) || (!tStart)))
{
char *buf;
@@ -1497,10 +1462,12 @@ void cMarkAdStandalone::ProcessFile()
}
}
}
-
+#if 0
CheckLastMark();
CheckLogoMarks();
+#endif
}
+ skipped=demux->Skipped();
}
void cMarkAdStandalone::Process()
@@ -1559,7 +1526,7 @@ void cMarkAdStandalone::Process()
}
}
}
- SaveInfo();
+ //SaveInfo();
}
else
{
@@ -1671,7 +1638,6 @@ bool cMarkAdStandalone::SaveInfo()
{
if (fprintf(w,"X %i %02i %s 4:3 LetterBox\n",stream_content,
component_type_43+component_type_add,lang)<=0) err=true;
- setVideo43_done=true;
setVideo43LB_done=true;
}
if (setVideo169)
@@ -1899,6 +1865,7 @@ bool cMarkAdStandalone::LoadInfo()
startTime=0;
length=0;
}
+ dsyslog("startTime=%s",ctime(&startTime));
}
if (line[0]=='T')
{
@@ -1967,19 +1934,14 @@ bool cMarkAdStandalone::LoadInfo()
macontext.Info.Channels=2;
}
}
- else
- // if we have DolbyDigital 5.1 disable video decoding
- if (strchr(descr,'5'))
- {
- bDecodeVideo=false;
- macontext.Info.Channels=6;
- macontext.Video.Options.IgnoreAspectRatio=true;
- isyslog("broadcast with DolbyDigital5.1, disabling video decoding");
- }
- else
- {
- setAudio20=true;
- }
+ // if we have DolbyDigital 5.1 disable video decoding
+ if (strchr(descr,'5'))
+ {
+ bDecodeVideo=false;
+ macontext.Info.Channels=6;
+ macontext.Video.Options.IgnoreAspectRatio=true;
+ isyslog("broadcast with DolbyDigital5.1, disabling video decoding");
+ }
}
}
}
@@ -2342,16 +2304,13 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
indexFile=NULL;
streaminfo=NULL;
- video_demux=NULL;
- ac3_demux=NULL;
- mp2_demux=NULL;
+ demux=NULL;
decoder=NULL;
video=NULL;
audio=NULL;
osd=NULL;
- memset(&vpkt,0,sizeof(vpkt));
- memset(&apkt,0,sizeof(apkt));
+ memset(&pkt,0,sizeof(pkt));
setAudio51=false;
setAudio20=false;
@@ -2365,7 +2324,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
noticeHEADER=false;
noticeFILLER=false;
- errcnt=0;
+ skipped=0;
sleepcnt=0;
waittime=iwaittime=0;
@@ -2479,6 +2438,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
}
if (asprintf(&indexFile,"%s/index.vdr",Directory)==-1) indexFile=NULL;
}
+ macontext.Info.APid.Num=0; // till now we do just nothing with stereo-sound
if (!LoadInfo())
{
@@ -2519,42 +2479,33 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
{
if (isTS)
{
- dsyslog("using %s-video (0x%04x)",
+ dsyslog("found %s-video (0x%04x)",
macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264 ? "H264": "H262",
macontext.Info.VPid.Num);
}
else
{
- dsyslog("using %s-video",
+ dsyslog("found %s-video",
macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264 ? "H264": "H262");
}
- video_demux = new cMarkAdDemux();
+ demux=new cDemux(macontext.Info.VPid.Num,macontext.Info.DPid.Num,macontext.Info.APid.Num,
+ macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264,true);
}
else
{
- video_demux=NULL;
+ demux=NULL;
}
if (macontext.Info.APid.Num)
{
if (macontext.Info.APid.Num!=-1)
- dsyslog("using MP2 (0x%04x)",macontext.Info.APid.Num);
- mp2_demux = new cMarkAdDemux();
- }
- else
- {
- mp2_demux=NULL;
+ dsyslog("found MP2 (0x%04x)",macontext.Info.APid.Num);
}
if (macontext.Info.DPid.Num)
{
if (macontext.Info.DPid.Num!=-1)
- dsyslog("using AC3 (0x%04x)%s",macontext.Info.DPid.Num,macontext.Config->AC3Always ? "*" : "");
- ac3_demux = new cMarkAdDemux();
- }
- else
- {
- ac3_demux=NULL;
+ dsyslog("found AC3 (0x%04x)%s",macontext.Info.DPid.Num,macontext.Config->AC3Always ? "*" : "");
}
if (!abort)
@@ -2581,9 +2532,9 @@ cMarkAdStandalone::~cMarkAdStandalone()
{
if ((!abort) && (!duplicate))
{
- if (errcnt>20)
+ if (skipped)
{
- isyslog("skipped %i bytes in video stream",errcnt);
+ isyslog("skipped %i bytes",skipped);
}
gettimeofday(&tv2,&tz);
@@ -2620,9 +2571,7 @@ cMarkAdStandalone::~cMarkAdStandalone()
if (macontext.Info.ChannelName) free(macontext.Info.ChannelName);
if (indexFile) free(indexFile);
- if (video_demux) delete video_demux;
- if (ac3_demux) delete ac3_demux;
- if (mp2_demux) delete mp2_demux;
+ if (demux) delete demux;
if (decoder) delete decoder;
if (video) delete video;
if (audio) delete audio;
@@ -3328,7 +3277,7 @@ int main(int argc, char *argv[])
if (!cmasta) return -1;
if (!bPass2Only) cmasta->Process();
- if (!bPass1Only) cmasta->Process2ndPass();
+ //if (!bPass1Only) cmasta->Process2ndPass();
delete cmasta;
return 0;
}
diff --git a/command/markad-standalone.h b/command/markad-standalone.h
index 78f0ea9..6f7797d 100644
--- a/command/markad-standalone.h
+++ b/command/markad-standalone.h
@@ -26,7 +26,6 @@
#define MAXRANGE 420 /* range to search for start/stop marks in seconds */
-
class cOSDMessage
{
private:
@@ -156,19 +155,19 @@ unsigned Descriptor_Length:
8;
};
+ enum { mSTART=0x1, mBEFORE, mAFTER };
+
static const char frametypes[8];
const char *directory;
- cMarkAdDemux *video_demux;
- cMarkAdDemux *ac3_demux;
- cMarkAdDemux *mp2_demux;
+ cDemux *demux;
cMarkAdDecoder *decoder;
cMarkAdVideo *video;
cMarkAdAudio *audio;
cMarkAdStreamInfo *streaminfo;
cOSDMessage *osd;
- MarkAdPacket vpkt,apkt;
+ AvPacket pkt;
MarkAdContext macontext;
@@ -214,7 +213,7 @@ unsigned Descriptor_Length:
int iStop; // posttimer as index value
int iStopCheck; // check position for iStop
- int errcnt; // Skipped bytes in stream
+ int skipped; // Skipped bytes in whole file
bool setAudio51; // set audio to 5.1 in info
bool setAudio20; // set audio to 2.0 in info
diff --git a/command/marks.cpp b/command/marks.cpp
index 130ff42..f06416d 100644
--- a/command/marks.cpp
+++ b/command/marks.cpp
@@ -485,7 +485,6 @@ void clMarks::WriteIndex(const char *Directory, bool isTS, uint64_t Offset,
indexfd=open(ipath,O_WRONLY|O_CREAT|O_TRUNC,0644);
free(ipath);
if (indexfd==-1) return;
- if (Offset>376) WriteIndex(isTS,0,1,Number);
}
WriteIndex(isTS,Offset,FrameType,Number);
return;
diff --git a/command/pes2es.cpp b/command/pes2es.cpp
deleted file mode 100644
index c78afd6..0000000
--- a/command/pes2es.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * pes2es.cpp: A program for the Video Disk Recorder
- *
- * See the README file for copyright information and how to reach the author.
- *
- */
-
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "pes2es.h"
-#include <stdio.h>
-cMarkAdPES2ES::cMarkAdPES2ES(const char *QueueName, int QueueSize)
-{
- queue = new cMarkAdPaketQueue(QueueName,QueueSize);
- type=0;
-}
-
-cMarkAdPES2ES::~cMarkAdPES2ES()
-{
- if (queue) delete queue;
-}
-
-void cMarkAdPES2ES::Clear()
-{
- if (queue) queue->Clear();
-}
-
-void cMarkAdPES2ES::Process(MarkAdPid Pid, uchar *PESData, int PESSize, MarkAdPacket *ESPkt)
-{
- if (!ESPkt) return;
-
- if (PESData)
- {
- struct PESHDR *peshdr=(struct PESHDR *) PESData;
-
- // first check some simple things
- if ((peshdr->Sync1!=0) && (peshdr->Sync2!=0) && (peshdr->Sync3!=1))
- {
- Clear();
- return;
- }
-
- if (peshdr->StreamID<=0xBC) return;
-
- int Length=(peshdr->LenH<<8)+peshdr->LenL;
- if (Length) Length+=sizeof(PESHDR);
- if (Length!=PESSize)
- {
- if ((peshdr->StreamID & 0xF0)==0xE0) return;
- Clear();
- return;
- }
-
- switch (Pid.Type)
- {
- case MARKAD_PIDTYPE_VIDEO_H262:
- if ((peshdr->StreamID & 0xF0)!=0xE0) return;
- type=MA_PACKET_PKT;
- break;
- case MARKAD_PIDTYPE_VIDEO_H264:
- if ((peshdr->StreamID & 0xF0)!=0xE0) return;
- type=MA_PACKET_H264;
- break;
- case MARKAD_PIDTYPE_AUDIO_AC3:
- if (peshdr->StreamID!=0xBD) return;
- type=MA_PACKET_AC3;
- break;
- case MARKAD_PIDTYPE_AUDIO_MP2:
- if ((peshdr->StreamID<0xC0) || (peshdr->StreamID>0xDF)) return;
- type=MA_PACKET_MP2;
- break;
- default:
- Clear();
- return;
- }
-
- struct PESHDROPT *peshdropt=(struct PESHDROPT *) &PESData[sizeof(struct PESHDR)];
-
- uchar *buf;
- int buflen;
-
- if (peshdropt->MarkerBits==0x2)
- {
- // we have an optional PES header
- int bpos=sizeof(struct PESHDR)+sizeof(struct PESHDROPT)+
- peshdropt->Length;
- buf=&PESData[bpos];
- buflen=PESSize-bpos;
- }
- else
- {
- int bpos=sizeof(struct PESHDR);
- buf=&PESData[bpos];
- buflen=PESSize-bpos;
- }
- queue->Put(buf,buflen);
- }
- if (type) ESPkt->Data=queue->GetPacket(&ESPkt->Length,type);
- return;
-}
diff --git a/command/pes2es.h b/command/pes2es.h
deleted file mode 100644
index bfeaaaa..0000000
--- a/command/pes2es.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * pes2es.h: A program for the Video Disk Recorder
- *
- * See the README file for copyright information and how to reach the author.
- *
- */
-
-#ifndef __pes2es_h_
-#define __pes2es_h_
-
-#ifndef uchar
-typedef unsigned char uchar;
-#endif
-
-#include "global.h"
-#include "queue.h"
-
-struct PESHDR
-{
- uchar Sync1;
- uchar Sync2;
- uchar Sync3;
- uchar StreamID;
- uchar LenH;
- uchar LenL;
-};
-
-#pragma pack(1)
-struct PESHDROPT
-{
-unsigned OOC:
- 1;
-unsigned CY:
- 1;
-unsigned DAI:
- 1;
-unsigned PESP:
- 1;
-unsigned PESSC:
- 2;
-unsigned MarkerBits:
- 2;
-unsigned EXT:
- 1;
-unsigned CRC:
- 1;
-unsigned ACI:
- 1;
-unsigned TM:
- 1;
-unsigned RATE:
- 1;
-unsigned ESCR:
- 1;
-unsigned PTSDTS:
- 2;
-unsigned Length:
- 8;
-};
-
-struct PESHDROPTPTS
-{
-unsigned Marker1:
- 1;
-unsigned PTS32_30:
- 3;
-unsigned Fixed:
- 4;
-unsigned PTS29_15_H:
- 8;
-unsigned Marker2:
- 1;
-unsigned PTS29_15_L:
- 7;
-unsigned PTS14_0_H:
- 8;
-unsigned Marker3:
- 1;
-unsigned PTS14_0_L:
- 7;
-};
-#pragma pack()
-
-class cMarkAdPES2ES
-{
-private:
- cMarkAdPaketQueue *queue;
- int type;
-public:
- cMarkAdPES2ES(const char *QueueName="PES2ES", int QueueSize=32768);
- ~cMarkAdPES2ES();
- void Clear();
- void Process(MarkAdPid Pid, uchar *PESData, int PESSize, MarkAdPacket *ESPkt);
-};
-
-#endif
diff --git a/command/queue.cpp b/command/queue.cpp
deleted file mode 100644
index 65188e4..0000000
--- a/command/queue.cpp
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * queue.cpp: A program for the Video Disk Recorder
- *
- * See the README file for copyright information and how to reach the author.
- *
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-extern "C"
-{
-#include "debug.h"
-}
-
-#include "queue.h"
-
-cMarkAdPaketQueue::cMarkAdPaketQueue(const char *Name, int Size)
-{
- inptr=0;
- outptr=0;
- memset(&pktinfo,0,sizeof(pktinfo));
- pktinfo.pkthdr=-1;
- maxqueue=Size;
- if (Name)
- {
- name=strdup(Name);
- }
- else
- {
- name=NULL;
- }
- buffer=(uchar *) malloc(Size+1);
- if (!buffer) maxqueue=0;
- scanner=0xFFFFFFFF;
- scannerstart=-1;
- percent=-1;
- mpercent=0;
-}
-
-cMarkAdPaketQueue::~cMarkAdPaketQueue()
-{
- if (name)
- {
- tsyslog("buffer usage: %-15s %3i%%",name,mpercent);
- free(name);
- }
- if (buffer) free(buffer);
-}
-
-bool cMarkAdPaketQueue::Inject(uchar *Data, int Size)
-{
- if (!buffer) return false;
- isyslog("inject was called, please report this");
-
- if (outptr>Size)
- {
- uchar *temp=(uchar *) alloca(Size+1);
- if (!temp) return false;
- memcpy(temp,Data,Size);
- outptr-=Size;
- memcpy(&buffer[outptr],temp,Size);
- pktinfo.pkthdr=-1;
- }
- else
- {
- int oldSize=Length();
- uchar *tempold=(uchar *) alloca(oldSize+1);
- if (!tempold) return false;
- uchar *temp=(uchar *) alloca(Size+1);
- if (!temp) return false;
-
- memcpy(tempold,&buffer[outptr],oldSize);
- memcpy(temp,Data,Size);
- memcpy(buffer,temp,Size);
- memcpy(buffer+Size,tempold,oldSize);
-
- inptr=Size+oldSize;
- outptr=0;
- pktinfo.pkthdr=-1;
- }
- return true;
-}
-
-bool cMarkAdPaketQueue::Put(uchar *Data, int Size)
-{
- if (!buffer) return false;
- if ((inptr) && (inptr==outptr)) inptr=outptr=0;
-
- if ((inptr+Size)>maxqueue)
- {
- if (name)
- {
- esyslog("buffer %s full",name);
- }
- else
- {
- esyslog("buffer full");
- }
- mpercent=100;
- Clear();
- return false;
- }
-
- memcpy(&buffer[inptr],Data,Size);
- inptr+=Size;
-
- int npercent=(int) ((inptr*100)/maxqueue);
- if (npercent>mpercent) mpercent=npercent;
-
- if ((npercent>90) && (name) && (npercent!=percent))
- {
- dsyslog("buffer %s usage: %3i%%",
- name,npercent);
- percent=npercent;
- }
-
- return true;
-}
-
-uchar *cMarkAdPaketQueue::Get(int *Size)
-{
- if (!buffer) return NULL;
- if (!Size) return NULL;
- if (Length()<*Size)
- {
- *Size=0;
- return NULL;
- }
- uchar *ret=&buffer[outptr];
- outptr+=*Size;
- return ret;
-}
-
-uchar *cMarkAdPaketQueue::Peek(int Size)
-{
- if (!buffer) return NULL;
- if (!Size) return NULL;
- if (Length()<Size) return NULL;
- uchar *ret=&buffer[outptr];
- return ret;
-}
-
-int cMarkAdPaketQueue::FindPktHeader(int Start, int *StreamSize,int *HeaderSize, bool LongStartCode)
-{
- if ((!StreamSize) || (!HeaderSize)) return -1;
- if (!Start) Start=outptr;
- if (Start>=inptr) return -1;
- *StreamSize=0;
- if (LongStartCode)
- {
- *HeaderSize=4; // 0x0 0x0 0x0 0x1
- }
- else
- {
- *HeaderSize=3; // 0x0 0x0 0x1
- }
- int i;
-
- if (scanner!=0xFFFFFFFF)
- {
- scanner<<=8;
- scanner|=buffer[Start++];
- }
-
- bool found=false;
- for (i=Start; i<inptr; i++)
- {
- if (LongStartCode)
- {
- if (scanner==1L)
- {
- found=true;
- break;
- }
- if ((scanner & 0xFFFFFFF0)==0x1E0L)
- {
- found=true;
- break;
- }
- }
- else
- {
- if ((scanner & 0x00FFFFFF)==1L)
- {
- found=true;
- break;
- }
- }
- scanner<<=8;
- scanner|=buffer[i];
- }
- if (!found)
- {
- if (LongStartCode)
- {
- if (scanner==1L)
- {
- found=true;
- }
- if ((scanner & 0xFFFFFFF0)==0x1E0L)
- {
- found=true;
- }
- }
- else
- {
- if ((scanner & 0x00FFFFFF)==1L)
- {
- found=true;
- }
- }
- }
-
- if (i==inptr)
- {
- if (found)
- {
- if (!Start)
- {
- scanner=0xFFFFFFFF;
- return -1;
- }
- }
- else
- {
- return -1;
- }
- }
- if (LongStartCode) i--;
- if ((buffer[i]>=0xBC) && (!Start)) // do we have a PES packet?
- {
-#define PESHDRSIZE 6
- if ((i+PESHDRSIZE)>inptr)
- {
- return -1; // we need more data (for streamsize and headersize)
- }
-
- *StreamSize=(buffer[i+1]<<8)+buffer[i+2];
- if (*StreamSize) (*StreamSize)+=PESHDRSIZE; // 6 Byte PES-Header
- if (LongStartCode)
- {
- struct PESHDROPT *peshdropt=(struct PESHDROPT *) &buffer[i+3];
- if (peshdropt->MarkerBits==0x2)
- {
- *HeaderSize=PESHDRSIZE+sizeof(struct PESHDROPT)+
- peshdropt->Length;
- }
- else
- {
- *HeaderSize=PESHDRSIZE;
- }
- }
- }
-
- return i-3;
-}
-
-int cMarkAdPaketQueue::FindAudioHeader(int Start, int *FrameSize, int *HeaderSize, bool AC3)
-{
- if ((!FrameSize) || (!HeaderSize)) return -1;
- if (!Start) Start=outptr;
- if (Start>=inptr) return -1;
- (*FrameSize)=0;
- if (AC3)
- {
- (*HeaderSize)=2;
- }
- else
- {
- (*HeaderSize)=3;
- }
- int i;
-
- if (scanner!=0xFFFFFFFF)
- {
- scanner<<=8;
- scanner|=buffer[Start++];
- }
-
- for (i=Start; i<inptr; i++)
- {
-
- if (AC3)
- {
- if ((scanner & 0x0000FFFF)==0xB77L) break;
- }
- else
- {
- if ((scanner & 0x00000FFE)==0xFFEL) break;
- }
-
- scanner<<=8;
- scanner|=buffer[i];
- }
- if (i==inptr) return -1;
- if (AC3) i-=2;
-
- if (AC3)
- {
- struct AC3HDR *ac3hdr = (struct AC3HDR *) &buffer[i];
-
- if (ac3hdr->SampleRateIndex==3) return -1; // reserved
- if (ac3hdr->FrameSizeIndex>=38) return -1; // reserved
-
- if (FrameSize)
- {
- int bitRatesAC3[3][38] = // all values are specified as kbits/s
- {
- { 64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192,
- 224, 224, 256, 256, 320, 320, 384, 384, 448, 448, 512, 512,
- 640, 640, 768, 768, 896, 896, 1024, 1024, 1152, 1152, 1280, 1280 }, // 48kHz
-
- { 69, 70, 87, 88, 104, 105, 121, 122, 139, 140, 174, 175, 208, 209,
- 243, 244, 278, 279, 348, 349, 417, 418, 487, 488, 557, 558,
- 696, 697, 835, 836, 975, 976, 1114, 1115, 1253, 1254, 1393, 1394 }, // 44.1kHz
-
- { 96, 96, 120, 120, 144, 144, 168, 168, 192, 192, 240, 240, 288,
- 288, 336, 336, 384, 384, 480, 480, 576, 576, 672, 672, 768,
- 768, 960, 960, 1152, 1152, 1344, 1344, 1536, 1536, 1728, 1728, 1920,1920 } // 32kHz
- };
-
- *FrameSize=2*bitRatesAC3[ac3hdr->SampleRateIndex][ac3hdr->FrameSizeIndex];
- }
- return i;
- }
- else
- {
- struct MP2HDR *mp2hdr = (struct MP2HDR *) &buffer[i];
- if (mp2hdr->MpegID==1) return -1; // reserved
- if (mp2hdr->Layer==0) return -1; // reserved
- if (mp2hdr->BitRateIndex==0xF) return -1; // forbidden
- if (mp2hdr->SampleRateIndex==3) return -1; //reserved
- if (mp2hdr->Emphasis==2) return -1; // reserved
-
- if (FrameSize)
- {
- int bitRates[3][3][16] = // all values are specified as kbits/s
- {
- {
- { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1 }, // M1, L1
- { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1 }, // M1, L2
- { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 } // M1, L3
- },
- {
- { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, // M2, L1
- { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, // M2, L2
- { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 } // M2, L3
- },
- {
- { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 }, // M2.5, L1
- { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, // M2.5, L2
- { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 } // M2.5, L3
- }
- };
-
- int samplingFrequencies[3][4] = // all values are specified in Hz
- {
- { 44100, 48000, 32000, -1 }, // MPEG 1
- { 22050, 24000, 16000, -1 }, // MPEG 2
- { 32000, 16000, 8000, -1 } // MPEG 2.5
- };
-
-
- int slots_per_frame[3][3] =
- {
- { 12, 144, 144 }, // MPEG 1, Layer I, II, III
- { 12, 144, 72 }, // MPEG 2, Layer I, II, III
- { 12, 144, 72 } // MPEG 2.5, Layer I, II, III
- };
-
- int mpegIndex;
- switch (mp2hdr->MpegID)
- {
- case 0:
- mpegIndex=2;
- break;
- case 2:
- mpegIndex=1;
- break;
- case 3:
- mpegIndex=0;
- break;
- default:
- mpegIndex=0; // just to get rid of compiler warnings ;)
- }
- int layerIndex = 3 - mp2hdr->Layer;
-
- // Layer I (i. e., layerIndex == 0) has a larger slot size
- int slotSize = (layerIndex == 0) ? 4 : 1; // bytes
- int sf = samplingFrequencies[mpegIndex][mp2hdr->SampleRateIndex];
-
- if (mp2hdr->BitRateIndex == 0)
- *FrameSize = 0; // "free" Bitrate -> we don't support this!
- else
- {
- int br = 1000 * bitRates[mpegIndex][layerIndex][mp2hdr->BitRateIndex]; // bits/s
- int N = slots_per_frame[mpegIndex][layerIndex] * br / sf; // slots
-
- *FrameSize = (N + mp2hdr->Padding) * slotSize; // bytes
- }
- }
- return i;
- }
-}
-
-uchar *cMarkAdPaketQueue::GetPacket(int *Size, int Type)
-{
- if (!Size) return NULL;
- *Size=0;
- if (Length()<4) return NULL;
-
- if (pktinfo.pkthdr==-1)
- {
- scanner=0xFFFFFFFF;
- switch (Type)
- {
- case MA_PACKET_AC3:
- pktinfo.pkthdr=FindAudioHeader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,true);
- break;
- case MA_PACKET_MP2:
- pktinfo.pkthdr=FindAudioHeader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,false);
- break;
- case MA_PACKET_H264:
- pktinfo.pkthdr=FindPktHeader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,true);
- break;
- default:
- pktinfo.pkthdr=FindPktHeader(0,&pktinfo.streamsize,&pktinfo.pktsyncsize,false);
- break;
- }
-
- if (pktinfo.pkthdr==-1)
- {
- return NULL;
- }
- scannerstart=pktinfo.pkthdr+pktinfo.pktsyncsize;
- }
-
- int streamsize,pktsyncsize,pkthdr=-1;
-
- if (pktinfo.streamsize)
- {
- if ((pktinfo.pkthdr+pktinfo.streamsize)>inptr)
- {
- return NULL; // need more data
- }
- else
- {
- scannerstart=pktinfo.pkthdr+pktinfo.streamsize;
- scanner=0xFFFFFFFF;
- }
- }
-
- switch (Type)
- {
- case MA_PACKET_AC3:
- pkthdr=FindAudioHeader(scannerstart,&streamsize,&pktsyncsize,true);
- break;
- case MA_PACKET_MP2:
- pkthdr=FindAudioHeader(scannerstart,&streamsize,&pktsyncsize,false);
- break;
- case MA_PACKET_H264:
- pkthdr=FindPktHeader(scannerstart,&streamsize,&pktsyncsize,true);
- break;
- default:
- pkthdr=FindPktHeader(scannerstart,&streamsize,&pktsyncsize,false);
- break;
- }
-
- if (pkthdr==-1)
- {
- scannerstart=inptr;
- return NULL;
- }
- scannerstart=pkthdr+pktsyncsize;
-
- uchar *ptr=&buffer[pktinfo.pkthdr];
-
- if (pktinfo.streamsize)
- {
- *Size=pktinfo.streamsize;
- }
- else
- {
- *Size=pkthdr-pktinfo.pkthdr;
- }
- outptr=pkthdr;
-
- int bytesleft=inptr-outptr;
- if (pktinfo.pkthdr>(4096+bytesleft))
- {
- memcpy(buffer,&buffer[pkthdr],bytesleft);
- scannerstart-=outptr;
- inptr=bytesleft;
- outptr=0;
- pkthdr=0;
- }
-
- pktinfo.pkthdr=pkthdr;
- pktinfo.streamsize=streamsize;
- pktinfo.pktsyncsize=pktsyncsize;
-
- return ptr;
-}
diff --git a/command/queue.h b/command/queue.h
deleted file mode 100644
index 4efd197..0000000
--- a/command/queue.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * queue.h: A program for the Video Disk Recorder
- *
- * See the README file for copyright information and how to reach the author.
- *
- */
-
-#ifndef __queue_h_
-#define __queue_h_
-
-#include <stdint.h>
-
-#ifndef uchar
-typedef unsigned char uchar;
-#endif
-
-typedef struct MarkAdPacket
-{
- uchar *Data;
- int Length;
- int Skipped;
- bool Offcnt;
-} MarkAdPacket;
-
-class cMarkAdPaketQueue
-{
- struct MP2HDR
- {
-unsigned Sync1:
- 8;
-unsigned Protection:
- 1;
-unsigned Layer:
- 2;
-unsigned MpegID:
- 2;
-unsigned Sync2:
- 3;
-unsigned Private:
- 1;
-unsigned Padding:
- 1;
-unsigned SampleRateIndex:
- 2;
-unsigned BitRateIndex:
- 4;
-unsigned Emphasis:
- 2;
-unsigned Original:
- 1;
-unsigned Copyright:
- 1;
-unsigned ModeExt:
- 2;
-unsigned Mode:
- 2;
- };
-
-#pragma pack(1)
- struct AC3HDR
- {
-unsigned Sync1:
- 8;
-unsigned Sync2:
- 8;
-unsigned CRC1:
- 8;
-unsigned CRC2:
- 8;
-unsigned FrameSizeIndex:
- 6;
-unsigned SampleRateIndex:
- 2;
- };
-#pragma pack()
-
-#pragma pack(1)
- struct PESHDROPT
- {
-unsigned OOC:
- 1;
-unsigned CY:
- 1;
-unsigned DAI:
- 1;
-unsigned PESP:
- 1;
-unsigned PESSC:
- 2;
-unsigned MarkerBits:
- 2;
-unsigned EXT:
- 1;
-unsigned CRC:
- 1;
-unsigned ACI:
- 1;
-unsigned TM:
- 1;
-unsigned RATE:
- 1;
-unsigned ESCR:
- 1;
-unsigned TSF:
- 2;
-unsigned Length:
- 8;
- };
-#pragma pack()
-
-private:
- char *name;
- struct pktinfo
- {
- int pkthdr;
- int pktsyncsize;
- int streamsize;
- bool ispes;
- } pktinfo;
-
- int percent;
- int mpercent; // max percentage use
-
- uchar *buffer;
- int maxqueue;
- int inptr;
- int outptr;
-
- uint32_t scanner;
- int scannerstart;
-
- int FindPktHeader(int Start, int *StreamSize,int *SyncSize, bool LongStartCode);
- int FindAudioHeader(int Start, int *FrameSize, int *SyncSize, bool AC3);
-public:
- cMarkAdPaketQueue(const char *Name, int Size=32768);
- ~cMarkAdPaketQueue();
- int Length()
- {
- return inptr-outptr;
- }
- void Clear()
- {
- inptr=outptr=0;
- pktinfo.pkthdr=-1;
- scanner=0xFFFFFFFF;
- scannerstart=-1;
- }
- bool Inject(uchar *Data, int Size);
- bool Put(uchar *Data, int Size);
- uchar *Get(int *Size);
- uchar *Peek(int Size);
-
-#define MA_PACKET_PKT 0x10 // 0x00 0x00 0x01 (PES / H262)
-#define MA_PACKET_H264 0x11 // 0x00 0x00 0x00 0x01 (H264)
-#define MA_PACKET_AC3 0x20
-#define MA_PACKET_MP2 0x30
-
- uchar *GetPacket(int *Size, int Type);
-};
-
-#endif
diff --git a/command/ts2pkt.cpp b/command/ts2pkt.cpp
deleted file mode 100644
index c3bbd15..0000000
--- a/command/ts2pkt.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * ts2pkt.cpp: A program for the Video Disk Recorder
- *
- * See the README file for copyright information and how to reach the author.
- *
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-extern "C"
-{
-#include "debug.h"
-}
-
-#include "ts2pkt.h"
-
-cMarkAdTS2Pkt::cMarkAdTS2Pkt(const char *QueueName, int QueueSize)
-{
- queue=new cMarkAdPaketQueue(QueueName,QueueSize);
- Reset();
-}
-
-cMarkAdTS2Pkt::~cMarkAdTS2Pkt()
-{
- if (queue) delete queue;
-}
-
-void cMarkAdTS2Pkt::Clear()
-{
- Reset();
-}
-
-bool cMarkAdTS2Pkt::Reset(int ErrIndex)
-{
- sync=false;
- switch (ErrIndex)
- {
- case MA_ERR_TSSIZE:
- dsyslog("inbuf not 188 bytes");
- break;
- case MA_ERR_NOSYNC:
- dsyslog("found no sync");
- break;
- case MA_ERR_SEQ:
- dsyslog("sequence error");
- break;
- case MA_ERR_AFC:
- dsyslog("wrong AFC value");
- break;
- case MA_ERR_TOBIG:
- dsyslog("buflen > 188 bytes");
- break;
- case MA_ERR_NEG:
- dsyslog("buflen negative");
- break;
- }
- counter=-1;
- if (queue) queue->Clear();
- return false;
-}
-
-bool cMarkAdTS2Pkt::InjectVideoPES(uchar *PESData, int PESSize)
-{
- if ((!PESData) || (!PESSize)) return false;
-
- struct PESHDR *peshdr=(struct PESHDR *) PESData;
-
- // first check some simple things
- if ((peshdr->Sync1!=0) && (peshdr->Sync2!=0) && (peshdr->Sync3!=1)) return false;
- if ((peshdr->StreamID & 0xF0)!=0xE0) return false;
-
- int Length=(peshdr->LenH<<8)+peshdr->LenL;
- if (Length) Length+=sizeof(PESHDR);
- if (Length!=PESSize) return false;
-
- struct PESHDROPT *peshdropt=(struct PESHDROPT *) &PESData[sizeof(struct PESHDR)];
-
- uchar *buf;
- int buflen;
-
- if (peshdropt->MarkerBits==0x2)
- {
- // we have an optional PES header
- int bpos=sizeof(struct PESHDR)+sizeof(struct PESHDROPT)+
- peshdropt->Length;
- buf=&PESData[bpos];
- buflen=PESSize-bpos;
- }
- else
- {
- int bpos=sizeof(struct PESHDR);
- buf=&PESData[bpos];
- buflen=PESSize-bpos;
- }
- queue->Inject(buf,buflen);
- return true;
-}
-
-bool cMarkAdTS2Pkt::Process(MarkAdPid Pid, uchar *TSData, int TSSize, MarkAdPacket *Pkt)
-{
- if ((!Pkt) || (!queue)) return false;
-
- bool ret=true;
-
- if (TSData)
- {
- if (TSSize!=TS_SIZE)
- {
- return Reset(MA_ERR_TSSIZE); // we need a full packet
- }
-
- // check TS packet sync
- if (TSData[0]!=0x47)
- {
- return Reset(MA_ERR_NOSYNC); // no sync
- }
-
- struct TSHDR *tshdr = (struct TSHDR *) TSData;
-
- int pid = (tshdr->PidH << 8) | tshdr->PidL;
- if (Pid.Num!=pid)
- {
- return true; // not for us, but this is ok
- }
-
- if ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter))
- {
- if (counter==(int) tshdr->Counter)
- {
- Pkt->Skipped+=TS_SIZE;
- return true; // duplicate paket -> just ignore
- }
- // sequence error
- ret=Reset(MA_ERR_SEQ);
- if (!tshdr->PayloadStart) return ret;
- }
- counter=tshdr->Counter;
-
- if (tshdr->PayloadStart)
- {
- sync=true;
- }
- if (!sync)
- {
- Pkt->Skipped+=TS_SIZE;
- return false; // not synced
- }
-
- if ((tshdr->AFC<=0) || (tshdr->AFC>3))
- {
- return Reset(MA_ERR_AFC);
- }
-
- // we just ignore the infos in the adaption field (e.g. OPCR/PCR)
- if ((tshdr->AFC!=1) && (tshdr->AFC!=3))
- {
- return true;
- }
-
- int buflen=TS_SIZE+1;
- uchar *buf=NULL;
-
- if (tshdr->AFC==1)
- {
- // payload only
- buflen=TS_SIZE-sizeof(struct TSHDR);
- buf=&TSData[sizeof(struct TSHDR)];
- }
-
- if (tshdr->AFC==3)
- {
- // adaption field + payload
- struct TSADAPT *tsadapt = (struct TSADAPT *) &TSData[4];
- int alen=tsadapt->Len+1;
- buflen=TS_SIZE-(sizeof(struct TSHDR)+alen);
- buf=&TSData[sizeof(struct TSHDR)+alen];
- }
-
- if (buflen>TS_SIZE)
- {
- // size to large
- return Reset(MA_ERR_TOBIG);
- }
- if (buflen<0)
- {
- // error in size
- return Reset(MA_ERR_NEG);
- }
- if (buflen==0)
- {
- // no data?
- return false;
- }
-
- if (tshdr->PayloadStart)
- {
- if ((buf[0]!=0) && (buf[1]!=0))
- {
- Pkt->Skipped+=TS_SIZE;
- sync=false;
- if (buflen<7) return false;
- // add a pseudo padding stream
- buf[0]=0;
- buf[1]=0;
- buf[2]=1;
- buf[3]=0xbe;
- buf[4]=buflen-6;
- buf[5]=0;
- }
- }
- queue->Put(buf,buflen);
- }
- if (!ret) return ret;
- if (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264)
- {
- Pkt->Data=queue->GetPacket(&Pkt->Length,MA_PACKET_H264);
- }
- else
- {
- Pkt->Data=queue->GetPacket(&Pkt->Length,MA_PACKET_PKT);
- }
- return ret;
-}
diff --git a/command/ts2pkt.h b/command/ts2pkt.h
deleted file mode 100644
index 367a007..0000000
--- a/command/ts2pkt.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * ts2pkt.h: A program for the Video Disk Recorder
- *
- * See the README file for copyright information and how to reach the author.
- *
- */
-
-#ifndef __ts2pkt_h_
-#define __ts2pkt_h_
-
-#ifndef TS_SIZE
-#define TS_SIZE 188
-#endif
-
-#ifndef uchar
-typedef unsigned char uchar;
-#endif
-
-#include "global.h"
-#include "queue.h"
-
-class cMarkAdTS2Pkt
-{
-private:
- struct TSHDR
- {
-unsigned Sync:
- 8;
-unsigned PidH:
- 5;
-unsigned Priority:
- 1;
-unsigned PayloadStart:
- 1;
-unsigned TError:
- 1;
-unsigned PidL:
- 8;
-unsigned Counter:
- 4;
-unsigned AFC:
- 2;
-unsigned TSC:
- 2;
- };
-
- struct TSADAPT
- {
-unsigned Len:
- 8;
-unsigned Discontinuity_indicator:
- 1;
-unsigned Random_access_indicator:
- 1;
-unsigned Elementary_stream_priority_indicator:
- 1;
-unsigned PCR_flag:
- 1;
-unsigned OPCR_flag:
- 1;
-unsigned Splicing_point_flag:
- 1;
-unsigned Transport_private_data_flag:
- 1;
-unsigned Adaption_field_extension_flag:
- 1;
-uint64_t PCR_base:
- 33;
-unsigned reserved:
- 6;
-unsigned PCR_ext:
- 9;
- };
-
- struct PESHDR
- {
- uchar Sync1;
- uchar Sync2;
- uchar Sync3;
- uchar StreamID;
- uchar LenH;
- uchar LenL;
- };
-
-#pragma pack(1)
- struct PESHDROPT
- {
-unsigned OOC:
- 1;
-unsigned CY:
- 1;
-unsigned DAI:
- 1;
-unsigned PESP:
- 1;
-unsigned PESSC:
- 2;
-unsigned MarkerBits:
- 2;
-unsigned EXT:
- 1;
-unsigned CRC:
- 1;
-unsigned ACI:
- 1;
-unsigned TM:
- 1;
-unsigned RATE:
- 1;
-unsigned ESCR:
- 1;
-unsigned TSF:
- 2;
-unsigned Length:
- 8;
- };
-#pragma pack()
-
- int counter;
- bool sync;
-
- cMarkAdPaketQueue *queue;
-
-#define MA_ERR_STARTUP 0
-#define MA_ERR_TSSIZE 1
-#define MA_ERR_NOSYNC 2
-#define MA_ERR_SEQ 3
-#define MA_ERR_AFC 4
-#define MA_ERR_TOBIG 5
-#define MA_ERR_NEG 6
- bool Reset(int ErrIndex=MA_ERR_STARTUP);
-public:
- cMarkAdTS2Pkt(const char *QueueName="TS2Pkt", int QueueSize=32768);
- ~cMarkAdTS2Pkt();
- void Clear();
- bool Process(MarkAdPid Pid,uchar *TSData, int TSSize, MarkAdPacket *Pkt);
- bool InjectVideoPES(uchar *PESData, int PESSize);
-};
-
-#endif
diff --git a/command/video.cpp b/command/video.cpp
index 77b77fa..d11d0cd 100644
--- a/command/video.cpp
+++ b/command/video.cpp
@@ -62,7 +62,7 @@ cMarkAdLogo::cMarkAdLogo(MarkAdContext *maContext)
void cMarkAdLogo::Clear()
{
memset(&area,0,sizeof(area));
- area.status=UNINITIALIZED;
+ area.status=LOGO_UNINITIALIZED;
}
int cMarkAdLogo::Load(const char *directory, char *file, int plane)
@@ -326,36 +326,36 @@ int cMarkAdLogo::Detect(int framenumber, int *logoframenumber)
mpixel+=area.mpixel[plane];
}
}
- if (extract) return NOCHANGE;
- if (!processed) return ERROR;
+ if (extract) return LOGO_NOCHANGE;
+ if (!processed) return LOGO_ERROR;
if (processed==1)
{
- if ((area.intensity>100) || (area.status!=LOGO) &&
- (area.intensity>180)) return NOCHANGE;
+ if ((area.intensity>100) || (area.status!=LOGO_VISIBLE) &&
+ (area.intensity>180)) return LOGO_NOCHANGE;
}
- int ret=NOCHANGE;
- if (area.status==UNINITIALIZED)
+ int ret=LOGO_NOCHANGE;
+ if (area.status==LOGO_UNINITIALIZED)
{
// Initialize
- if (rpixel>(mpixel*LOGO_VMARK))
+ if (rpixel>=(mpixel*LOGO_VMARK))
{
- area.status=LOGO;
+ area.status=ret=LOGO_VISIBLE;
}
else
{
- area.status=NOLOGO;
+ area.status=LOGO_INVISIBLE;
}
}
if (rpixel>=(mpixel*LOGO_VMARK))
{
- if (area.status==NOLOGO)
+ if (area.status==LOGO_INVISIBLE)
{
if (area.counter>=LOGO_VMAXCOUNT)
{
- area.status=ret=LOGO;
+ area.status=ret=LOGO_VISIBLE;
*logoframenumber=area.framenumber;
area.counter=0;
}
@@ -374,11 +374,11 @@ int cMarkAdLogo::Detect(int framenumber, int *logoframenumber)
if (rpixel<(mpixel*LOGO_IMARK))
{
- if (area.status==LOGO)
+ if (area.status==LOGO_VISIBLE)
{
if (area.counter>=LOGO_IMAXCOUNT)
{
- area.status=ret=NOLOGO;
+ area.status=ret=LOGO_INVISIBLE;
*logoframenumber=area.framenumber;
area.counter=0;
}
@@ -403,12 +403,12 @@ int cMarkAdLogo::Detect(int framenumber, int *logoframenumber)
int cMarkAdLogo::Process(int FrameNumber, int *LogoFrameNumber)
{
- if (!macontext) return ERROR;
- if (!macontext->Video.Data.Valid) return ERROR;
- if (!macontext->Video.Info.Width) return ERROR;
- if (!macontext->Video.Info.Height) return ERROR;
- if (!macontext->Config->logoDirectory[0]) return ERROR;
- if (!macontext->Info.ChannelName) return ERROR;
+ if (!macontext) return LOGO_ERROR;
+ if (!macontext->Video.Data.Valid) return LOGO_ERROR;
+ if (!macontext->Video.Info.Width) return LOGO_ERROR;
+ if (!macontext->Video.Info.Height) return LOGO_ERROR;
+ if (!macontext->Config->logoDirectory[0]) return LOGO_ERROR;
+ if (!macontext->Info.ChannelName) return LOGO_ERROR;
if (macontext->Config->logoExtraction==-1)
{
@@ -468,7 +468,7 @@ cMarkAdBlackBordersHoriz::cMarkAdBlackBordersHoriz(MarkAdContext *maContext)
void cMarkAdBlackBordersHoriz::Clear()
{
- borderstatus=UNINITIALIZED;
+ borderstatus=HBORDER_UNINITIALIZED;
borderframenumber=-1;
}
@@ -536,23 +536,23 @@ int cMarkAdBlackBordersHoriz::Process(int FrameNumber, int *BorderIFrame)
#define MINSECS 240
switch (borderstatus)
{
- case UNINITIALIZED:
+ case HBORDER_UNINITIALIZED:
if (FrameNumber>(borderframenumber+macontext->Video.Info.FramesPerSecond*MINSECS))
{
- borderstatus=BORDER;
+ borderstatus=HBORDER_VISIBLE;
}
break;
- case NOBORDER:
+ case HBORDER_INVISIBLE:
if (FrameNumber>(borderframenumber+macontext->Video.Info.FramesPerSecond*MINSECS))
{
*BorderIFrame=borderframenumber;
- borderstatus=BORDER;
+ borderstatus=HBORDER_VISIBLE;
return 1; // detected start of black border
}
break;
- case BORDER:
+ case HBORDER_VISIBLE:
borderframenumber=FrameNumber;
break;
}
@@ -562,10 +562,10 @@ int cMarkAdBlackBordersHoriz::Process(int FrameNumber, int *BorderIFrame)
{
if (borderframenumber!=-1)
{
- if (borderstatus==BORDER)
+ if (borderstatus==HBORDER_VISIBLE)
{
*BorderIFrame=borderframenumber;
- borderstatus=NOBORDER;
+ borderstatus=HBORDER_INVISIBLE;
borderframenumber=-1;
return -1; // detected stop of black border
}
@@ -577,7 +577,7 @@ int cMarkAdBlackBordersHoriz::Process(int FrameNumber, int *BorderIFrame)
else
{
borderframenumber=-1;
- borderstatus=NOBORDER;
+ borderstatus=HBORDER_INVISIBLE;
}
}
return 0;
@@ -587,8 +587,8 @@ cMarkAdOverlap::cMarkAdOverlap(MarkAdContext *maContext)
{
macontext=maContext;
- histbuf[BEFORE]=NULL;
- histbuf[AFTER]=NULL;
+ histbuf[OV_BEFORE]=NULL;
+ histbuf[OV_AFTER]=NULL;
result.CommentBefore=NULL;
result.CommentAfter=NULL;
Clear();
@@ -601,19 +601,19 @@ cMarkAdOverlap::~cMarkAdOverlap()
void cMarkAdOverlap::Clear()
{
- histcnt[BEFORE]=0;
- histcnt[AFTER]=0;
- histframes[BEFORE]=0;
- histframes[AFTER]=0;
- if (histbuf[BEFORE])
+ histcnt[OV_BEFORE]=0;
+ histcnt[OV_AFTER]=0;
+ histframes[OV_BEFORE]=0;
+ histframes[OV_AFTER]=0;
+ if (histbuf[OV_BEFORE])
{
- delete[] histbuf[BEFORE];
- histbuf[BEFORE]=NULL;
+ delete[] histbuf[OV_BEFORE];
+ histbuf[OV_BEFORE]=NULL;
}
- if (histbuf[AFTER])
+ if (histbuf[OV_AFTER])
{
- delete[] histbuf[AFTER];
- histbuf[AFTER]=NULL;
+ delete[] histbuf[OV_AFTER];
+ histbuf[OV_AFTER]=NULL;
}
if (result.CommentBefore) free(result.CommentBefore);
if (result.CommentAfter) free(result.CommentAfter);
@@ -655,12 +655,12 @@ MarkAdPos *cMarkAdOverlap::Detect()
int tmpA=0,tmpB=0;
if (result.FrameNumberBefore==-1) return NULL;
result.FrameNumberBefore=-1;
- for (int B=0; B<histcnt[BEFORE]; B++)
+ for (int B=0; B<histcnt[OV_BEFORE]; B++)
{
- for (int A=start; A<histcnt[AFTER]; A++)
+ for (int A=start; A<histcnt[OV_AFTER]; A++)
{
//printf("%6i %6i ",histbuf[BEFORE][B].framenumber,histbuf[AFTER][A].framenumber);
- bool simil=areSimilar(histbuf[BEFORE][B].histogram,histbuf[AFTER][A].histogram);
+ bool simil=areSimilar(histbuf[OV_BEFORE][B].histogram,histbuf[OV_AFTER][A].histogram);
if (simil)
{
tmpA=A;
@@ -675,8 +675,8 @@ MarkAdPos *cMarkAdOverlap::Detect()
if (simcnt>similarMaxCnt)
{
- result.FrameNumberBefore=histbuf[BEFORE][tmpB].framenumber;
- result.FrameNumberAfter=histbuf[AFTER][tmpA].framenumber;
+ result.FrameNumberBefore=histbuf[OV_BEFORE][tmpB].framenumber;
+ result.FrameNumberAfter=histbuf[OV_AFTER][tmpA].framenumber;
}
else
{
@@ -690,8 +690,8 @@ MarkAdPos *cMarkAdOverlap::Detect()
{
if (simcnt>similarMaxCnt)
{
- result.FrameNumberBefore=histbuf[BEFORE][tmpB].framenumber;
- result.FrameNumberAfter=histbuf[AFTER][tmpA].framenumber;
+ result.FrameNumberBefore=histbuf[OV_BEFORE][tmpB].framenumber;
+ result.FrameNumberAfter=histbuf[OV_AFTER][tmpA].framenumber;
}
else
{
@@ -714,13 +714,13 @@ MarkAdPos *cMarkAdOverlap::Process(int FrameNumber, int Frames, bool BeforeAd)
{
if ((lastframenumber>0) && (!similarMaxCnt))
{
- similarCutOff=60000; // lower is harder!
- similarMaxCnt=4;
+ similarCutOff=50000; // lower is harder!
+ similarMaxCnt=6;
}
if (BeforeAd)
{
- if ((histframes[BEFORE]) && (histcnt[BEFORE]>=histframes[BEFORE]))
+ if ((histframes[OV_BEFORE]) && (histcnt[OV_BEFORE]>=histframes[OV_BEFORE]))
{
if (result.FrameNumberBefore)
{
@@ -731,31 +731,31 @@ MarkAdPos *cMarkAdOverlap::Process(int FrameNumber, int Frames, bool BeforeAd)
return NULL;
}
}
- if (!histbuf[BEFORE])
+ if (!histbuf[OV_BEFORE])
{
- histframes[BEFORE]=Frames;
- histbuf[BEFORE]=new histbuffer[Frames+1];
+ histframes[OV_BEFORE]=Frames;
+ histbuf[OV_BEFORE]=new histbuffer[Frames+1];
}
- getHistogram(histbuf[BEFORE][histcnt[BEFORE]].histogram);
- histbuf[BEFORE][histcnt[BEFORE]].framenumber=FrameNumber;
- histcnt[BEFORE]++;
+ getHistogram(histbuf[OV_BEFORE][histcnt[OV_BEFORE]].histogram);
+ histbuf[OV_BEFORE][histcnt[OV_BEFORE]].framenumber=FrameNumber;
+ histcnt[OV_BEFORE]++;
}
else
{
- if (!histbuf[AFTER])
+ if (!histbuf[OV_AFTER])
{
- histframes[AFTER]=Frames;
- histbuf[AFTER]=new histbuffer[Frames+1];
+ histframes[OV_AFTER]=Frames;
+ histbuf[OV_AFTER]=new histbuffer[Frames+1];
}
- if (histcnt[AFTER]>=histframes[AFTER]-1)
+ if (histcnt[OV_AFTER]>=histframes[OV_AFTER]-1)
{
if (result.FrameNumberBefore) return NULL;
return Detect();
}
- getHistogram(histbuf[AFTER][histcnt[AFTER]].histogram);
- histbuf[AFTER][histcnt[AFTER]].framenumber=FrameNumber;
- histcnt[AFTER]++;
+ getHistogram(histbuf[OV_AFTER][histcnt[OV_AFTER]].histogram);
+ histbuf[OV_AFTER][histcnt[OV_AFTER]].framenumber=FrameNumber;
+ histcnt[OV_AFTER]++;
}
lastframenumber=FrameNumber;
return NULL;
@@ -775,7 +775,7 @@ cMarkAdVideo::cMarkAdVideo(MarkAdContext *maContext)
cMarkAdVideo::~cMarkAdVideo()
{
- ResetMarks();
+ resetmarks();
if (hborder) delete hborder;
if (logo) delete logo;
if (overlap) delete overlap;
@@ -785,11 +785,13 @@ void cMarkAdVideo::Clear()
{
aspectratio.Num=0;
aspectratio.Den=0;
+ framelast=0;
+ framebeforelast=0;
if (hborder) hborder->Clear();
if (logo) logo->Clear();
}
-void cMarkAdVideo::ResetMarks()
+void cMarkAdVideo::resetmarks()
{
for (int i=0; i<marks.maxCount; i++)
{
@@ -798,23 +800,32 @@ void cMarkAdVideo::ResetMarks()
memset(&marks,0,sizeof(marks));
}
-bool cMarkAdVideo::AddMark(int Type, int Position, const char *Comment)
+bool cMarkAdVideo::addmark(int type, int position, const char *comment)
{
- if (!Comment) return false;
+ if (!comment) return false;
if (marks.Count>marks.maxCount) return false;
- marks.Number[marks.Count].Comment=strdup(Comment);
- marks.Number[marks.Count].Position=Position;
- marks.Number[marks.Count].Type=Type;
+ marks.Number[marks.Count].Comment=strdup(comment);
+ marks.Number[marks.Count].Position=position;
+ marks.Number[marks.Count].Type=type;
marks.Count++;
return true;
}
-bool cMarkAdVideo::AspectRatioChange(MarkAdAspectRatio *a, MarkAdAspectRatio *b)
+bool cMarkAdVideo::aspectratiochange(MarkAdAspectRatio &a, MarkAdAspectRatio &b, bool &start)
{
- if ((!a) || (!b)) return false;
-
- if (a->Num==0 || a->Den==0 || b->Num==0 || b->Den==0) return false;
- if ((a->Num!=b->Num) && (a->Den!=b->Den)) return true;
+ start=false;
+ if (a.Num==0 || a.Den==0 || b.Num==0 || b.Den==0)
+ {
+ if (((a.Num==4) || (b.Num==4)) && ((a.Den==3) || (b.Den==3)))
+ {
+ start=true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ if ((a.Num!=b.Num) && (a.Den!=b.Den)) return true;
return false;
}
@@ -832,7 +843,7 @@ MarkAdMarks *cMarkAdVideo::Process(int FrameNumber, int FrameNumberNext)
{
if ((!FrameNumber) && (!FrameNumberNext)) return NULL;
- ResetMarks();
+ resetmarks();
if (!macontext->Video.Options.IgnoreLogoDetection)
{
@@ -845,7 +856,7 @@ MarkAdMarks *cMarkAdVideo::Process(int FrameNumber, int FrameNumberNext)
{
if (asprintf(&buf,"detected logo start (%i)",logoframenumber)!=-1)
{
- AddMark(MT_LOGOSTART,logoframenumber,buf);
+ addmark(MT_LOGOSTART,logoframenumber,buf);
free(buf);
}
}
@@ -853,7 +864,7 @@ MarkAdMarks *cMarkAdVideo::Process(int FrameNumber, int FrameNumberNext)
{
if (asprintf(&buf,"detected logo stop (%i)",logoframenumber)!=-1)
{
- AddMark(MT_LOGOSTOP,logoframenumber,buf);
+ addmark(MT_LOGOSTOP,logoframenumber,buf);
free(buf);
}
}
@@ -869,7 +880,7 @@ MarkAdMarks *cMarkAdVideo::Process(int FrameNumber, int FrameNumberNext)
if (asprintf(&buf,"detected start of horiz. borders (%i [%i])",
borderframenumber,FrameNumber)!=-1)
{
- AddMark(MT_BORDERSTART,borderframenumber,buf);
+ addmark(MT_BORDERSTART,borderframenumber,buf);
free(buf);
}
}
@@ -880,50 +891,58 @@ MarkAdMarks *cMarkAdVideo::Process(int FrameNumber, int FrameNumberNext)
if (asprintf(&buf,"detected stop of horiz. borders (%i [%i])",
borderframenumber,FrameNumber)!=-1)
{
- AddMark(MT_BORDERSTOP,borderframenumber,buf);
+ addmark(MT_BORDERSTOP,borderframenumber,buf);
free(buf);
}
}
if (!macontext->Video.Options.IgnoreAspectRatio)
{
- if (AspectRatioChange(&macontext->Video.Info.AspectRatio,&aspectratio))
+ bool start;
+ if (aspectratiochange(macontext->Video.Info.AspectRatio,aspectratio,start))
{
+ if ((logo->Status()==LOGO_VISIBLE) && (!start))
+ {
+ char *buf=NULL;
+ if (asprintf(&buf,"assuming logo stop (%i)",framebeforelast)!=-1)
+ {
+ addmark(MT_LOGOSTOP,framebeforelast,buf);
+ free(buf);
+ }
+ logo->SetStatusLogoInvisible();
+ }
char *buf=(char *) calloc(1,256);
if (!buf) return NULL;
- snprintf(buf,255,"aspect ratio change from %i:%i to %i:%i (",
- aspectratio.Num,aspectratio.Den,
- macontext->Video.Info.AspectRatio.Num,
- macontext->Video.Info.AspectRatio.Den);
+ if (start)
+ {
+ snprintf(buf,255,"aspect ratio %i:%i (",
+ macontext->Video.Info.AspectRatio.Num,
+ macontext->Video.Info.AspectRatio.Den);
+ }
+ else
+ {
+ snprintf(buf,255,"aspect ratio change from %i:%i to %i:%i (",
+ aspectratio.Num,aspectratio.Den,
+ macontext->Video.Info.AspectRatio.Num,
+ macontext->Video.Info.AspectRatio.Den);
+ }
- if ((macontext->Info.AspectRatio.Num) && (macontext->Info.AspectRatio.Den))
+ if ((macontext->Video.Info.AspectRatio.Num==4) &&
+ (macontext->Video.Info.AspectRatio.Den==3))
{
- if ((macontext->Video.Info.AspectRatio.Num==macontext->Info.AspectRatio.Num) &&
- (macontext->Video.Info.AspectRatio.Den==macontext->Info.AspectRatio.Den))
- {
- char nbuf[20];
- snprintf(nbuf,sizeof(nbuf),"%i)*",FrameNumberNext);
- nbuf[19]=0;
- strcat(buf,nbuf);
- AddMark(MT_ASPECTSTART,FrameNumberNext,buf);
- }
- else
- {
- char nbuf[20];
- snprintf(nbuf,sizeof(nbuf),"%i)",framelast);
- nbuf[19]=0;
- strcat(buf,nbuf);
- AddMark(MT_ASPECTSTOP,framelast,buf);
- }
+ char nbuf[20];
+ snprintf(nbuf,sizeof(nbuf),"%i)*",start ? FrameNumber : FrameNumberNext);
+ nbuf[19]=0;
+ strcat(buf,nbuf);
+ addmark(MT_ASPECTSTART,FrameNumberNext,buf);
}
else
{
char nbuf[20];
- snprintf(nbuf,sizeof(nbuf),"%i)?",FrameNumber);
+ snprintf(nbuf,sizeof(nbuf),"%i)",framelast);
nbuf[19]=0;
strcat(buf,nbuf);
-
- AddMark(MT_ASPECTCHANGE,FrameNumber,buf);
+ addmark(MT_ASPECTSTOP,framelast,buf);
}
free(buf);
}
@@ -932,5 +951,13 @@ MarkAdMarks *cMarkAdVideo::Process(int FrameNumber, int FrameNumberNext)
aspectratio.Den=macontext->Video.Info.AspectRatio.Den;
}
framelast=FrameNumberNext;
- return &marks;
+ framebeforelast=FrameNumber;
+ if (marks.Count)
+ {
+ return &marks;
+ }
+ else
+ {
+ return NULL;
+ }
}
diff --git a/command/video.h b/command/video.h
index b6db23f..16f8899 100644
--- a/command/video.h
+++ b/command/video.h
@@ -10,7 +10,7 @@
#include "global.h"
-#define LOGO_MAXHEIGHT 250
+#define LOGO_MAXHEIGHT 170
#define LOGO_MAXWIDTH 480
#define LOGO_DEFHEIGHT 100
@@ -22,11 +22,33 @@
#define LOGO_VMARK 0.5 // percantage of pixels for visible
#define LOGO_IMARK 0.15 // percentage of pixels for invisible
+enum
+{
+ LOGO_ERROR=-3,
+ LOGO_UNINITIALIZED=-2,
+ LOGO_INVISIBLE=-1,
+ LOGO_NOCHANGE=0,
+ LOGO_VISIBLE=1
+};
+
+enum
+{
+ HBORDER_ERROR=-3,
+ HBORDER_UNINITIALIZED=-2,
+ HBORDER_INVISIBLE=-1,
+ HBORDER_NOCHANGE=0,
+ HBORDER_VISIBLE=1
+};
+
+enum
+{
+ OV_BEFORE=0,
+ OV_AFTER=1
+};
+
class cMarkAdOverlap
{
private:
-#define BEFORE 0
-#define AFTER 1
MarkAdContext *macontext;
typedef int simpleHistogram[256];
@@ -67,15 +89,6 @@ private:
BOTTOM_RIGHT
};
- enum
- {
- ERROR=-3,
- UNINITIALIZED=-2,
- NOLOGO=-1,
- NOCHANGE=0,
- LOGO=1
- };
-
int LOGOHEIGHT; // max. 140
int LOGOWIDTH; // 192-288
@@ -113,27 +126,31 @@ private:
public:
cMarkAdLogo(MarkAdContext *maContext);
int Process(int FrameNumber, int *LogoFrameNumber);
+ int Status()
+ {
+ return area.status;
+ }
+ void SetStatusLogoInvisible()
+ {
+ if (area.status==LOGO_VISIBLE)
+ area.status=LOGO_INVISIBLE;
+ }
void Clear();
};
class cMarkAdBlackBordersHoriz
{
private:
- enum
- {
- ERROR=-3,
- UNINITIALIZED=-2,
- NOBORDER=-1,
- NOCHANGE=0,
- BORDER=1
- };
-
int borderstatus;
int borderframenumber;
MarkAdContext *macontext;
public:
cMarkAdBlackBordersHoriz(MarkAdContext *maContext);
int Process(int FrameNumber,int *BorderFrameNumber);
+ int Status()
+ {
+ return borderstatus;
+ }
void Clear();
};
@@ -148,11 +165,12 @@ private:
cMarkAdLogo *logo;
cMarkAdOverlap *overlap;
- void ResetMarks();
- bool AddMark(int Type, int Position, const char *Comment);
- bool AspectRatioChange(MarkAdAspectRatio *a, MarkAdAspectRatio *b);
+ void resetmarks();
+ bool addmark(int Type, int position, const char *comment);
+ bool aspectratiochange(MarkAdAspectRatio &a, MarkAdAspectRatio &b, bool &start);
int framelast;
+ int framebeforelast;
public:
cMarkAdVideo(MarkAdContext *maContext);