summaryrefslogtreecommitdiff
path: root/command
diff options
context:
space:
mode:
Diffstat (limited to 'command')
-rw-r--r--command/Makefile2
-rw-r--r--command/audio.cpp159
-rw-r--r--command/audio.h19
-rw-r--r--command/audio_gain_analysis.cpp423
-rw-r--r--command/audio_gain_analysis.h102
-rw-r--r--command/demux.cpp1292
-rw-r--r--command/demux.h332
-rw-r--r--command/global.h70
-rw-r--r--command/logos/ANTENA_3-A16_9-P0.pgmbin0 -> 14419 bytes
-rw-r--r--command/logos/ANTENA_3-A16_9-P1.pgmbin0 -> 3617 bytes
-rw-r--r--command/logos/ANTENA_3-A16_9-P2.pgmbin0 -> 3617 bytes
-rw-r--r--command/logos/Antena_3_HD-A16_9-P0.pgmbin50419 -> 63019 bytes
-rw-r--r--command/logos/CUATRO-A16_9-P0.pgmbin0 -> 16019 bytes
-rw-r--r--command/logos/La_1-A16_9-P0.pgmbin0 -> 14319 bytes
-rw-r--r--command/logos/La_2-A4_3-P0.pgmbin0 -> 14319 bytes
-rw-r--r--command/logos/Telecinco-A16_9-P0.pgmbin0 -> 19219 bytes
-rw-r--r--command/logos/Telecinco-A16_9-P1.pgmbin0 -> 4817 bytes
-rw-r--r--command/logos/Telecinco-A16_9-P2.pgmbin0 -> 4817 bytes
-rw-r--r--command/logos/Telecinco_HD-A16_9-P0.pgm5
-rw-r--r--command/logos/laSexta-A16_9-P0.pgmbin0 -> 12119 bytes
-rw-r--r--command/logos/laSexta_HD-A4_3-P0.pgmbin0 -> 49939 bytes
-rw-r--r--command/markad-standalone.cpp1364
-rw-r--r--command/markad-standalone.h53
-rw-r--r--command/marks.cpp24
-rw-r--r--command/marks.h1
-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.cpp312
-rw-r--r--command/video.h72
33 files changed, 2194 insertions, 3263 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..0a9c133 100644
--- a/command/audio.cpp
+++ b/command/audio.cpp
@@ -11,182 +11,73 @@
#include <stdlib.h>
#include <string.h>
-extern "C"
-{
-#include "debug.h"
-}
-
#include "audio.h"
cMarkAdAudio::cMarkAdAudio(MarkAdContext *maContext)
{
macontext=maContext;
- mark.Comment=NULL;
mark.Position=0;
mark.Type=0;
- result.CommentBefore=NULL;
- result.CommentAfter=NULL;
Clear();
}
cMarkAdAudio::~cMarkAdAudio()
{
+ resetmark();
Clear();
- ResetMark();
}
-void cMarkAdAudio::ResetMark()
-{
- if (mark.Comment) free(mark.Comment);
- mark.Comment=NULL;
- mark.Position=0;
- mark.Type=0;
-}
-
-bool cMarkAdAudio::AddMark(int Type, int Position, const char *Comment)
+void cMarkAdAudio::Clear()
{
- if (!Comment) return false;
- if (mark.Comment)
- {
- int oldlen=strlen(mark.Comment);
- mark.Comment=(char *) realloc(mark.Comment,oldlen+10+strlen(Comment));
- if (!mark.Comment)
- {
- mark.Position=0;
- return false;
- }
- strcat(mark.Comment," [");
- strcat(mark.Comment,Comment);
- strcat(mark.Comment,"]");
- }
- else
- {
- mark.Comment=strdup(Comment);
- }
- mark.Position=Position;
- mark.Type=Type;
- return true;
+ channels=0;
}
-bool cMarkAdAudio::AnalyzeGain(int FrameNumber)
+void cMarkAdAudio::resetmark()
{
- 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;
+ if (!mark.Type) return;
+ memset(&mark,0,sizeof(mark));
}
-void cMarkAdAudio::Clear()
+void cMarkAdAudio::setmark(int type, int position, int channelsbefore, int channelsafter)
{
- channels=0;
- lastframe_gain=-1;
- if (result.CommentBefore) free(result.CommentBefore);
- if (result.CommentAfter) free(result.CommentAfter);
- memset(&result,0,sizeof(result));
+ mark.ChannelsBefore=channelsbefore;
+ mark.ChannelsAfter=channelsafter;
+ mark.Position=position;
+ mark.Type=type;
}
-bool cMarkAdAudio::ChannelChange(int a, int b)
+bool cMarkAdAudio::channelchange(int a, int b)
{
if ((a==0) || (b==0)) return false;
if (a!=b) return true;
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;
- ResetMark();
+ resetmark();
- if (ChannelChange(macontext->Audio.Info.Channels,channels))
+ if (channelchange(macontext->Audio.Info.Channels,channels))
{
- char *buf=(char *) calloc(1,256);
- if (!buf) return NULL;
-
- 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);
- }
+ setmark(MT_CHANNELSTART,FrameNumberNext,channels,macontext->Audio.Info.Channels);
}
else
{
- char nbuf[20];
- snprintf(nbuf,sizeof(nbuf),"%i)?",FrameNumber);
- nbuf[19]=0;
- strcat(buf,nbuf);
- AddMark(MT_CHANNELCHANGE,FrameNumber,buf);
+ setmark(MT_CHANNELSTOP,framelast,channels,macontext->Audio.Info.Channels);
}
- 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..4c6c819 100644
--- a/command/audio.h
+++ b/command/audio.h
@@ -10,35 +10,22 @@
#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);
-
+ void resetmark();
+ void setmark(int type, int position, int channelsbefore, int channelsafter);
int channels;
- bool ChannelChange(int a, int b);
+ bool channelchange(int a, int b);
int framelast;
-
- MarkAdPos result;
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..9f634bd 100644
--- a/command/demux.cpp
+++ b/command/demux.cpp
@@ -5,282 +5,1248 @@
*
*/
+#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 cPaketQueue::Resize(int NewSize, const char *NewName)
+{
+ 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();
+ }
+ }
}
-void cMarkAdDemux::ProcessVDR(MarkAdPid Pid, uchar *Data, int Count, MarkAdPacket *Pkt)
+int cPaketQueue::findpktheader(int start, int *streamsize,int *headersize, bool longstartcode, bool pesonly=false)
{
- if (!Pkt) return;
+ 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++];
+ }
- if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) || (Pid.Type==MARKAD_PIDTYPE_AUDIO_MP2))
+ 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 (found)
+ {
+ if (!start)
+ {
+ scanner=0xFFFFFFFF;
+ return -1;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ if (longstartcode) i--;
+ if (buffer[i]>=0xBC) // do we have a PES packet?
{
- if (!pes2videoes)
+#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)
{
- if (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264)
+ struct PESHDROPT *peshdropt=(struct PESHDROPT *) &buffer[i+3];
+ if (peshdropt->MarkerBits==0x2)
{
- pes2videoes=new cMarkAdPES2ES("PES2H264ES",425984);
+ *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;
+
+ if (scanner!=0xFFFFFFFF)
+ {
+ scanner<<=8;
+ scanner|=buffer[start++];
+ }
+ else
+ {
+ scanner<<=8;
+ scanner|=buffer[start++];
+ scanner<<=8;
+ scanner|=buffer[start++];
+ }
+
+ for (i=start; i<inptr; i++)
+ {
+
+ if (ac3)
+ {
+ if ((scanner & 0x0000FFFF)==0xB77L) break;
+ }
+ else
+ {
+ if ((scanner & 0x0000FFE0)==0xFFE0L) break;
+ }
+
+ scanner<<=8;
+ scanner|=buffer[i];
+ }
+ if (i==inptr) return -1;
- MarkAdPacket pkt;
- memset(&pkt,0,sizeof(pkt));
+ i-=2;
- if (!ts2pkt)
+ if (ac3)
{
- switch (Pid.Type)
+ struct AC3HDR *ac3hdr = (struct AC3HDR *) &buffer[i];
+
+ if (ac3hdr->SampleRateIndex==3) return -1; // reserved
+ if (ac3hdr->FrameSizeIndex>=38) return -1; // reserved
+
+ if (framesize)
{
- case MARKAD_PIDTYPE_VIDEO_H264:
- ts2pkt=new cMarkAdTS2Pkt("TS2H264",819200);
- break;
+ 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
- case MARKAD_PIDTYPE_VIDEO_H262:
- ts2pkt=new cMarkAdTS2Pkt("TS2H262",262144);
- break;
+ { 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
- case MARKAD_PIDTYPE_AUDIO_AC3:
- ts2pkt=new cMarkAdTS2Pkt("TS2PES AC3",32768);
- break;
+ { 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
+ };
- case MARKAD_PIDTYPE_AUDIO_MP2:
- ts2pkt=new cMarkAdTS2Pkt("TS2PES MP2",16384);
+ *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;
}
- if (!ts2pkt) return;
- if (!ts2pkt->Process(Pid,Data,Count,&pkt))
+ int streamsize,pktsyncsize,pkthdr=-1;
+
+ if (pktinfo.streamsize)
{
- if (pes2audioes) pes2audioes->Clear();
- return;
+ if ((pktinfo.pkthdr+pktinfo.streamsize)>inptr)
+ {
+ return NULL; // need more data
+ }
+ else
+ {
+ scannerstart=pktinfo.pkthdr+pktinfo.streamsize;
+ scanner=0xFFFFFFFF;
+ }
}
- if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) || (Pid.Type==MARKAD_PIDTYPE_AUDIO_MP2))
+ switch (Type)
{
- 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);
+ 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 ((Pid.Type==MARKAD_PIDTYPE_VIDEO_H262) || (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264))
+ if (pkthdr==-1)
{
- if ((pkt.Data) && ((pkt.Data[3] & 0xF0)==0xE0) && (pkt.Data[4]!=0) && (pkt.Data[5]!=0))
+ 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
{
- ts2pkt->InjectVideoPES(pkt.Data,pkt.Length);
- pkt.Data=NULL;
- pkt.Length=0;
+ scannerstart=inptr;
+ return NULL;
}
- Pkt->Data=pkt.Data;
- Pkt->Length=pkt.Length;
- Pkt->Skipped=pkt.Skipped;
}
- 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;
+
+ return ptr;
}
-int cMarkAdDemux::GetMinNeeded(MarkAdPid Pid, uchar *Data, int Count, bool *Offcnt)
+// ----------------------------------------------------------------------------
+
+cTS2Pkt::cTS2Pkt(int Pid, const char *QueueName, int QueueSize, bool H264)
{
- if (Pid.Num>=0) return TS_SIZE;
+ queue=new cPaketQueue(QueueName,QueueSize);
+ pid=Pid;
+ h264=H264;
+ firstsync=false;
+ Clear();
+}
- uchar *qData=queue->Peek(PESHDRSIZE);
- if (!qData)
+cTS2Pkt::~cTS2Pkt()
+{
+ if (queue)
{
- int len=PESHDRSIZE-queue->Length();
- int cnt=(Count>len) ? len : Count;
- queue->Put(Data,cnt);
- return -cnt;
+ if (skipped) tsyslog("buffer skipped: %-15s %i bytes",queue->Name(),skipped);
+ delete queue;
}
+}
- int stream=qData[3];
+void cTS2Pkt::Clear()
+{
+ sync=false;
+ counter=-1;
+ skipped=0;
+ noticeFILLER=false;
+ noticeSEQUENCE=false;
+ noticeSTREAM=false;
+ if (queue) queue->Clear();
+}
- if ((qData[0]==0) && (qData[1]==0) && (qData[2]==1) && (stream>0xBC))
+bool cTS2Pkt::Process(uchar *TSData, int TSSize, AvPacket *Pkt)
+{
+ if (!Pkt) return false;
+ if (TSData)
{
- int needed=qData[4]*256+qData[5];
+ if (TSSize!=TS_SIZE) return false;
+
+ struct TSHDR *tshdr = (struct TSHDR *) TSData;
- if (((Pid.Type==MARKAD_PIDTYPE_VIDEO_H262) ||
- (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264)) && ((stream & 0xF0)!=0xE0))
+ int ppid=(tshdr->PidH << 8) | tshdr->PidL;
+ if (ppid!=pid)
{
- // ignore 6 header bytes from queue->Put above
- queue->Clear();
- if (Offcnt) *Offcnt=true;
- return -needed;
+ return false;
}
- if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_MP2) && ((stream & 0xF0)!=0xC0))
+
+ if ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter))
{
- // ignore 6 header bytes from queue->Put above
- queue->Clear();
- if (Offcnt) *Offcnt=true;
- return -needed;
+ 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;
}
- if ((Pid.Type==MARKAD_PIDTYPE_AUDIO_AC3) && (stream!=0xBD))
+ counter=tshdr->Counter;
+
+ if (tshdr->PayloadStart)
{
- // ignore 6 header bytes from queue->Put above
- queue->Clear();
- if (Offcnt) *Offcnt=true;
- return -needed;
+ 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);
+ }
+
+ Pkt->Data=queue->GetPacket(&Pkt->Length,h264 ? PACKET_H264 : PACKET_H262);
+ if (Pkt->Data)
+ {
+ Pkt->Type=h264 ? PACKET_H264 : PACKET_H262;
+ if ((h264) && ((Pkt->Data[4] & 0x1F)==0x0C))
+ {
+ 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;
}
- return needed+PESHDRSIZE;
}
else
{
- queue->Clear();
- if (Offcnt) *Offcnt=true;
- return -1; // skip one byte (maybe we get another header!)
+ Pkt->Length=0;
+ Pkt->Type=0;
}
+ return true;
}
-void cMarkAdDemux::VDRTSAddPATPMT2Offset(MarkAdPid Pid, uchar *Data, int Count, bool *Offcnt)
+// ----------------------------------------------------------------------------
+
+cPES2ES::cPES2ES(int PacketType, const char *QueueName, int QueueSize)
{
- if (Pid.Num<0) return;
- if (Count<2) return;
- if ((Data[0]==0x47) && (Data[1]==0x40) && ((Data[2]==0) || (Data[2]==0x84))) *Offcnt=false;
+ queue = new cPaketQueue(QueueName,QueueSize);
+ ptype=PacketType;
+ Clear();
}
-int cMarkAdDemux::Process(MarkAdPid Pid, uchar *Data, int Count, MarkAdPacket *Pkt)
+cPES2ES::~cPES2ES()
{
- if ((!Data) && (!Count) && (!Pkt)) return -1;
+ if (queue)
+ {
+ if (skipped) tsyslog("buffer skipped: %-15s %i bytes",queue->Name(),skipped);
+ delete queue;
+ }
+}
- uchar *in=NULL;
- int inlen=0;
- int retval=0;
+void cPES2ES::Clear()
+{
+ skipped=0;
+ if (queue) queue->Clear();
+}
- if (!pause)
+bool cPES2ES::Process(uchar *PESData, int PESSize, AvPacket *ESPkt)
+{
+ if (!ESPkt) return false;
+ if (PESData)
{
- Pkt->Data=NULL;
- Pkt->Length=0;
- Pkt->Skipped=0;
- Pkt->Offcnt=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<=0xBC) return false;
- if (!min_needed)
+ int Length=(peshdr->LenH<<8)+peshdr->LenL;
+ if (Length)
{
- if (skip)
+ Length+=sizeof(PESHDR);
+ if (Length!=PESSize)
{
- int t_skip=skip;
- skip=0;
- Pkt->Offcnt=true;
- return t_skip;
+ skipped+=Length;
+ return true;
}
+ }
+
+ if (peshdr->StreamID==0xBE)
+ {
+ queue->Clear();
+ return true;
+ }
+
+ switch (ptype)
+ {
+ 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)];
- int t_min_needed=GetMinNeeded(Pid,Data,Count,&Pkt->Offcnt);
- if (t_min_needed==0)
+ 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;
+ }
+ if ((ptype==PACKET_AC3) && (buflen>6))
+ {
+ if ((buf[4]==0x0B) && (buf[5]==0x77))
{
- return -1;
+ buf+=4;
+ buflen-=4;
}
- if (t_min_needed<0)
+ }
+ queue->Put(buf,buflen);
+ }
+ ESPkt->Data=queue->GetPacket(&ESPkt->Length,ptype);
+ if (ESPkt->Data)
+ {
+ ESPkt->Type=ptype;
+ }
+ else
+ {
+ ESPkt->Type=0;
+ ESPkt->Length=0;
+ }
+ skipped+=queue->Skipped();
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+
+cDemux::cDemux(int VPid, int DPid, int APid, bool H264, bool VDRCount)
+{
+ TS=false;
+ if ((VPid>0) || (DPid>0) || (APid>0)) TS=true;
+
+ vpid=VPid;
+ dpid=DPid;
+ apid=APid;
+ if (TS)
+ {
+ if (!vpid) vpid=-1;
+ if (!dpid) dpid=-1;
+ if (!apid) apid=-1;
+ }
+
+ 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();
+}
+
+cDemux::~cDemux()
+{
+ 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;
+
+ 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;
+}
+
+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)))
+ {
+ 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 (!TS)
+ {
+ if ((qData[0]==0) && (qData[1]==0) && (qData[2]==1) && (qData[3]>=0xBC))
+ {
+ 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))
{
- if (-t_min_needed>Count)
+ int start=queue->FindPesHeader(1);
+ if (start)
+ {
+ // broken PES in queue, skip it
+ packetsize=start;
+ skipped+=start;
+ stream_or_pid=0;
+ return 0;
+ }
+ else
{
- skip=-t_min_needed-Count;
- return Count;
+ return -1;
}
- if (t_min_needed==-1) Pkt->Skipped++;
- return -t_min_needed;
}
- min_needed=t_min_needed;
}
+ }
+ 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 (ret)
+ {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
- int needed=min_needed-queue->Length();
+bool cDemux::needmoredata()
+{
+ if (!stream_or_pid) return true;
+
+ if (!TS)
+ {
+ switch (stream_or_pid)
+ {
+ case 0xE0:
+ if (pes2videoes) return pes2videoes->NeedMoreData();
+ break;
+ case 0xC0:
+ if ((pes2audioes_mp2) && (apid)) return pes2audioes_mp2->NeedMoreData();
+ break;
+ case 0xBD:
+ if ((pes2audioes_ac3) && (dpid)) return pes2audioes_ac3->NeedMoreData();
+ break;
+ }
+ }
- if (Count>needed)
+ if (TS)
+ {
+ if ((stream_or_pid==vpid) && (ts2pkt_vpid))
{
- queue->Put(Data,needed);
- retval=needed;
+ if (pes2videoes) return pes2videoes->NeedMoreData();
+ return ts2pkt_vpid->NeedMoreData();
}
- else
+ if ((stream_or_pid==dpid) && (ts2pkt_dpid))
{
- queue->Put(Data,Count);
- retval=Count;
+ if (pes2audioes_ac3) return pes2audioes_ac3->NeedMoreData();
+ return ts2pkt_dpid->NeedMoreData();
}
- if (queue->Length()<min_needed)
+ if ((stream_or_pid==apid) && (ts2pkt_apid))
{
- return Count;
+ 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;
+}
- if (pause)
+void cDemux::NewFile()
+{
+ from_oldfile=queue->Length();
+}
+
+void cDemux::DisableDPid()
+{
+ if (pes2audioes_ac3) delete pes2audioes_ac3;
+ if (ts2pkt_dpid) delete ts2pkt_dpid;
+ pes2audioes_ac3=NULL;
+ ts2pkt_dpid=NULL;
+ if (TS)
+ {
+ dpid=-1;
+ }
+ else
+ {
+ dpid=0;
+ }
+ stream_or_pid=0;
+}
+
+int cDemux::Process(uchar *Data, int Count, AvPacket *pkt)
+{
+ if (!pkt) return -1;
+ pkt->Data=NULL;
+ pkt->Length=0;
+
+ bool add=needmoredata();
+
+ 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)
{
- if (pause_retval)
+ switch (stream_or_pid)
{
- retval=pause_retval;
- pause_retval=0;
+ 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 (apid)
+ {
+ if (!pes2audioes_mp2) pes2audioes_mp2=new cPES2ES(PACKET_MP2,"PES2MP2",16384);
+ if (!pes2audioes_mp2->Process(bpkt,bplen,pkt)) return -1;
+ }
+ else
+ {
+ stream_or_pid=0;
+ }
+ break;
+ case 0xBD:
+ if (dpid)
+ {
+ if (!pes2audioes_ac3) pes2audioes_ac3=new cPES2ES(PACKET_AC3,"PES2AC3");
+ if (!pes2audioes_ac3->Process(bpkt,bplen,pkt)) return -1;
+ }
+ else
+ {
+ stream_or_pid=0;
+ }
+ break;
+ default:
+ stream_or_pid=0;
+ break;
}
- pause=false;
}
-
- Pkt->Offcnt=true;
- VDRTSAddPATPMT2Offset(Pid, in, inlen, &Pkt->Offcnt);
- return retval;
+ if (TS)
+ {
+ 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)
+ {
+ 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;
+ }
+ 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;
+ }
+ return add ? readout : 0;
}
diff --git a/command/demux.h b/command/demux.h
index 0c91c7a..2299e6b 100644
--- a/command/demux.h
+++ b/command/demux.h
@@ -8,39 +8,323 @@
#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 DisableDPid();
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 7ac42b6..af2d3a1 100644
--- a/command/global.h
+++ b/command/global.h
@@ -22,38 +22,35 @@ typedef unsigned char uchar;
#define MA_SP_TYPE 6
#define MA_BI_TYPE 7
-#define MT_UNCERTAIN 0
-#define MT_START 1
-#define MT_STOP 2
+#define MT_START 1
+#define MT_STOP 2
-#define MT_COMMON 0x10
-#define MT_COMMONSTART 0x11
-#define MT_COMMONSTOP 0x12
+#define MT_ASSUMED 0x10
+#define MT_ASSUMEDSTART 0x11
+#define MT_ASSUMEDSTOP 0x12
-#define MT_ASSUMED 0x20
-#define MT_ASSUMEDSTART 0x21
-#define MT_ASSUMEDSTOP 0x22
+#define MT_LOGOCHANGE 0x20
+#define MT_LOGOSTART 0x21
+#define MT_LOGOSTOP 0x22
-#define MT_ASPECTCHANGE 0x30
-#define MT_ASPECTSTART 0x31
-#define MT_ASPECTSTOP 0x32
+#define MT_HBORDERCHANGE 0x30
+#define MT_HBORDERSTART 0x31
+#define MT_HBORDERSTOP 0x32
-#define MT_CHANNELCHANGE 0x40
-#define MT_CHANNELSTART 0x41
-#define MT_CHANNELSTOP 0x42
+#define MT_VBORDERCHANGE 0x40
+#define MT_VBORDERSTART 0x41
+#define MT_VBORDERSTOP 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_CHANNELCHANGE 0x60
+#define MT_CHANNELSTART 0x61
+#define MT_CHANNELSTOP 0x62
-#define MT_SILENCECHANGE 0x90
-
-#define MT_MOVED 0xE0
-#define MT_ALL 0xFF
+#define MT_MOVED 0xE0
+#define MT_ALL 0xFF
typedef struct config
{
@@ -84,15 +81,22 @@ typedef struct MarkAdPos
{
int FrameNumberBefore;
int FrameNumberAfter;
- char *CommentBefore;
- char *CommentAfter;
} MarkAdPos;
+typedef struct MarkAdAspectRatio
+{
+ int Num;
+ int Den;
+} MarkAdAspectRatio;
+
typedef struct MarkAdMark
{
char Type;
int Position;
- char *Comment;
+ int ChannelsBefore;
+ int ChannelsAfter;
+ MarkAdAspectRatio AspectRatioBefore;
+ MarkAdAspectRatio AspectRatioAfter;
} MarkAdMark;
typedef struct MarkAdMarks
@@ -102,12 +106,6 @@ typedef struct MarkAdMarks
int Count;
} MarkAdMarks;
-typedef struct MarkAdAspectRatio
-{
- int Num;
- int Den;
-} MarkAdAspectRatio;
-
#define MARKAD_PIDTYPE_VIDEO_H262 0x10
#define MARKAD_PIDTYPE_VIDEO_H264 0x11
#define MARKAD_PIDTYPE_AUDIO_AC3 0x20
@@ -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/logos/ANTENA_3-A16_9-P0.pgm b/command/logos/ANTENA_3-A16_9-P0.pgm
new file mode 100644
index 0000000..8ad9602
--- /dev/null
+++ b/command/logos/ANTENA_3-A16_9-P0.pgm
Binary files differ
diff --git a/command/logos/ANTENA_3-A16_9-P1.pgm b/command/logos/ANTENA_3-A16_9-P1.pgm
new file mode 100644
index 0000000..0c147a7
--- /dev/null
+++ b/command/logos/ANTENA_3-A16_9-P1.pgm
Binary files differ
diff --git a/command/logos/ANTENA_3-A16_9-P2.pgm b/command/logos/ANTENA_3-A16_9-P2.pgm
new file mode 100644
index 0000000..77c175b
--- /dev/null
+++ b/command/logos/ANTENA_3-A16_9-P2.pgm
Binary files differ
diff --git a/command/logos/Antena_3_HD-A16_9-P0.pgm b/command/logos/Antena_3_HD-A16_9-P0.pgm
index c742986..0d97c2c 100644
--- a/command/logos/Antena_3_HD-A16_9-P0.pgm
+++ b/command/logos/Antena_3_HD-A16_9-P0.pgm
Binary files differ
diff --git a/command/logos/CUATRO-A16_9-P0.pgm b/command/logos/CUATRO-A16_9-P0.pgm
new file mode 100644
index 0000000..6192ecf
--- /dev/null
+++ b/command/logos/CUATRO-A16_9-P0.pgm
Binary files differ
diff --git a/command/logos/La_1-A16_9-P0.pgm b/command/logos/La_1-A16_9-P0.pgm
new file mode 100644
index 0000000..9aed19c
--- /dev/null
+++ b/command/logos/La_1-A16_9-P0.pgm
Binary files differ
diff --git a/command/logos/La_2-A4_3-P0.pgm b/command/logos/La_2-A4_3-P0.pgm
new file mode 100644
index 0000000..90d5413
--- /dev/null
+++ b/command/logos/La_2-A4_3-P0.pgm
Binary files differ
diff --git a/command/logos/Telecinco-A16_9-P0.pgm b/command/logos/Telecinco-A16_9-P0.pgm
new file mode 100644
index 0000000..d33075d
--- /dev/null
+++ b/command/logos/Telecinco-A16_9-P0.pgm
Binary files differ
diff --git a/command/logos/Telecinco-A16_9-P1.pgm b/command/logos/Telecinco-A16_9-P1.pgm
new file mode 100644
index 0000000..0c1119e
--- /dev/null
+++ b/command/logos/Telecinco-A16_9-P1.pgm
Binary files differ
diff --git a/command/logos/Telecinco-A16_9-P2.pgm b/command/logos/Telecinco-A16_9-P2.pgm
new file mode 100644
index 0000000..be29a09
--- /dev/null
+++ b/command/logos/Telecinco-A16_9-P2.pgm
Binary files differ
diff --git a/command/logos/Telecinco_HD-A16_9-P0.pgm b/command/logos/Telecinco_HD-A16_9-P0.pgm
new file mode 100644
index 0000000..f0a92c9
--- /dev/null
+++ b/command/logos/Telecinco_HD-A16_9-P0.pgm
@@ -0,0 +1,5 @@
+P5
+#C3
+380 170
+255
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
diff --git a/command/logos/laSexta-A16_9-P0.pgm b/command/logos/laSexta-A16_9-P0.pgm
new file mode 100644
index 0000000..6a25f77
--- /dev/null
+++ b/command/logos/laSexta-A16_9-P0.pgm
Binary files differ
diff --git a/command/logos/laSexta_HD-A4_3-P0.pgm b/command/logos/laSexta_HD-A4_3-P0.pgm
new file mode 100644
index 0000000..67a842b
--- /dev/null
+++ b/command/logos/laSexta_HD-A4_3-P0.pgm
Binary files differ
diff --git a/command/markad-standalone.cpp b/command/markad-standalone.cpp
index cccbf0f..f99ae92 100644
--- a/command/markad-standalone.cpp
+++ b/command/markad-standalone.cpp
@@ -26,6 +26,8 @@
#include <execinfo.h>
#include <mntent.h>
#include <utime.h>
+#include <math.h>
+#include <limits.h>
#include <errno.h>
#include "markad-standalone.h"
@@ -179,625 +181,326 @@ int cOSDMessage::Send(const char *format, ...)
return 0;
}
-void cMarkAdStandalone::CalculateStopPosition(int startframe, int delta)
+void cMarkAdStandalone::CalculateCheckPositions(int startframe)
{
if (!length) return;
+ if (!startframe) return;
if (!macontext.Video.Info.FramesPerSecond) return;
- int len_in_frames=length*macontext.Video.Info.FramesPerSecond;
+ int delta=macontext.Video.Info.FramesPerSecond*MAXRANGE;
+ int len_in_frames=macontext.Video.Info.FramesPerSecond*length;
- if (startframe)
- {
- iStop=-(startframe+len_in_frames);
- chkLEFT=startframe+delta+macontext.Video.Info.FramesPerSecond;
- chkRIGHT=startframe+(len_in_frames*2/3);
- }
- else
- {
- chkLEFT=(int) (len_in_frames*2/5);
- chkRIGHT=(int) (len_in_frames*2/3);
- }
+ iStart=-startframe;
+ iStop=-(startframe+len_in_frames);
+ chkSTART=-iStart+delta;
+ chkSTOP=-iStop+(3*delta);
}
-void cMarkAdStandalone::AddStartMark()
+void cMarkAdStandalone::CheckStop()
{
- 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)
+ dsyslog("checking stop");
+ int delta=macontext.Video.Info.FramesPerSecond*MAXRANGE;
+ clMark *end=marks.GetAround(delta,iStop,MT_STOP,0x0F);
+
+ if (end)
{
- iStart=-(tStart*macontext.Video.Info.FramesPerSecond);
+ marks.DelTill(end->position,false);
+ isyslog("using mark on position %i as stop mark",end->position);
}
- CalculateStopPosition(-iStart,macontext.Video.Info.FramesPerSecond*MAXRANGE);
- if (tStart==1)
+ else
{
- tStart=iStart=0;
+ //fallback, shouldn't be reached
+ MarkAdMark mark;
+ memset(&mark,0,sizeof(mark));
+ mark.Position=iStop;
+ mark.Type=MT_ASSUMEDSTOP;
+ AddMark(&mark);
+ marks.DelTill(iStop,false);
}
+ iStop=0;
+ gotendmark=true;
}
-void cMarkAdStandalone::CheckStartStop(int frame, bool checkend)
+void cMarkAdStandalone::CheckStart()
{
- MarkAdMark mark;
- char *buf;
+ dsyslog("checking start");
+ clMark *begin=NULL;
- if ((iStartCheck>0) && (frame>=iStartCheck))
+ if ((macontext.Info.Channels) && (macontext.Audio.Info.Channels) &&
+ (macontext.Info.Channels!=macontext.Audio.Info.Channels))
{
- // check if we have a start mark which is near iStart
- 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 type=0;
- int newpos=0;
- int delta_before=MAXMARKDIFF;
- int delta_after=MAXMARKDIFF;
-
- if (before_iStart)
- {
- delta_before=abs(iStart-before_iStart->position);
- if (delta_before>MAXMARKDIFF) delta_before=MAXMARKDIFF;
- }
- if (after_iStart)
+ char as[20];
+ switch (macontext.Info.Channels)
{
- delta_after=abs(after_iStart->position-iStart);
- if (delta_after>MAXMARKDIFF) delta_after=MAXMARKDIFF;
- }
-
- if (delta_before>delta_after)
- {
- // use after_iStart
- newpos=after_iStart->position;
- type=after_iStart->type;
+ case 1:
+ strcpy(as,"mono");
+ break;
+ case 2:
+ strcpy(as,"stereo");
+ break;
+ case 6:
+ strcpy(as,"dd5.1");
+ break;
+ default:
+ strcpy(as,"??");
+ break;
}
-
- if (delta_before<delta_after)
+ char ad[20];
+ switch (macontext.Audio.Info.Channels)
{
- // use before_iStart
- newpos=before_iStart->position;
- type=before_iStart->type;
- }
-
- if (newpos)
- {
- if (type==MT_BORDERSTART)
- {
- // check if we have an MT_ASPECTCHANGE in low distance
- clMark *aspectmark=marks.GetPrev(newpos,MT_ASPECTSTART);
- if (!aspectmark) aspectmark=marks.GetNext(newpos,MT_ASPECTSTART);
- if (aspectmark)
- {
- int MAXMARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*20);
- if (abs(newpos-aspectmark->position)<=MAXMARKDIFF)
- {
- newpos=aspectmark->position;
- }
- }
- }
- isyslog("using this mark instead of assumed start mark (%i->%i)",
- newpos,iStart);
- marks.Del(iStart);
- marks.DelTill(newpos);
- CalculateStopPosition(newpos,frame-newpos);
+ case 1:
+ strcpy(ad,"mono");
+ break;
+ case 2:
+ strcpy(ad,"stereo");
+ break;
+ case 6:
+ strcpy(ad,"dd5.1");
+ break;
+ default:
+ strcpy(ad,"??");
+ break;
}
- iStart=0;
- iStartCheck=0;
+ isyslog("audio description in info (%s) wrong, we have %s",as,ad);
}
- if ((iStopCheck>0) && ((frame>=iStopCheck) || (checkend)))
+ macontext.Info.Channels=macontext.Audio.Info.Channels;
+ if (macontext.Info.Channels==6)
{
- // check if we have a stop mark which is near iStop
- clMark *before_iStop=marks.GetPrev(iStop,MT_STOP,0xF);
- clMark *after_iStop=marks.GetNext(iStop,MT_STOP,0xF);
-
- int MAXMARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*MAXRANGE);
- int newpos=0;
- int delta_before=MAXMARKDIFF;
- int delta_after=MAXMARKDIFF;
-
- if (before_iStop)
- {
- delta_before=abs(iStop-before_iStop->position);
- if (delta_before>MAXMARKDIFF) delta_before=MAXMARKDIFF;
- }
- if (after_iStop)
- {
- delta_after=abs(after_iStop->position-iStop);
- if (delta_after>MAXMARKDIFF) delta_after=MAXMARKDIFF;
- }
-
- if (delta_before>delta_after)
- {
- // use after_iStop
- newpos=after_iStop->position;
- }
-
- if (delta_before<delta_after)
- {
- // use before_iStop
- newpos=before_iStop->position;
- }
-
- if (newpos)
- {
- isyslog("using this mark instead of assumed stop mark (%i->%i)",
- newpos,iStop);
- marks.Del(iStop);
- marks.DelTill(newpos,false);
- }
- else
- {
- marks.DelTill(iStop,false);
- }
+ isyslog("DolbyDigital5.1 audio detected. logo/border/aspect detection disabled");
bDecodeVideo=false;
- gotendmark=true;
- iStop=0;
- iStopCheck=0;
- }
-
- if ((iStart<0) && (frame>-iStart))
- {
- iStart=frame;
- if (asprintf(&buf,"assumed start of broadcast (%i)",iStart)!=-1)
- {
- mark.Type=MT_ASSUMEDSTART;
- mark.Position=iStart;
- mark.Comment=buf;
- 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);
+ macontext.Video.Options.IgnoreAspectRatio=true;
+ macontext.Video.Options.IgnoreLogoDetection=true;
+ marks.Del(MT_ASPECTSTART);
+ marks.Del(MT_ASPECTSTOP);
+ // start mark must be around istart
+ begin=marks.GetAround(INT_MAX,iStart,MT_CHANNELSTART);
}
- if ((iStop<0) && (lastiframe>-iStop))
+ else
{
- iStop=frame;
- if (asprintf(&buf,"assumed stop of broadcast (%i)",iStop)!=-1)
- {
- mark.Type=MT_ASSUMEDSTOP;
- mark.Position=iStop;
- mark.Comment=buf;
- AddMark(&mark);
- free(buf);
- }
-
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*MAXRANGE);
- clMark *before_iStop=marks.GetPrev(iStart,MT_STOP,0xF);
- if (before_iStop)
+ if (macontext.Info.DPid.Num)
{
- int tmpdiff=abs(iStop-before_iStop->position);
- if (tmpdiff<MARKDIFF) MARKDIFF=tmpdiff;
+ if (macontext.Info.Channels)
+ isyslog("broadcast with %i audio channels, disabling AC3 decoding",macontext.Info.Channels);
+ macontext.Info.DPid.Num=0;
+ demux->DisableDPid();
}
- iStopCheck=iStop+MARKDIFF;
}
-}
-void cMarkAdStandalone::CheckLogoMarks(clMark *last)
-{
- clMark *mark=marks.GetFirst();
- while (mark)
+ if ((macontext.Info.AspectRatio.Num) && ((macontext.Info.AspectRatio.Num!=
+ macontext.Video.Info.AspectRatio.Num) || (macontext.Info.AspectRatio.Den!=
+ macontext.Video.Info.AspectRatio.Den)))
{
- if ((mark->type==MT_LOGOSTOP) && mark->Next() && mark->Next()->type==MT_LOGOSTART)
- {
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*55);
- if (abs(mark->Next()->position-mark->position)<=MARKDIFF)
- {
- double distance=(mark->Next()->position-mark->position)/
- macontext.Video.Info.FramesPerSecond;
- isyslog("logo distance too short (%.1fs), deleting (%i,%i)",distance,
- mark->position,mark->Next()->position);
- clMark *tmp=mark;
- mark=mark->Next()->Next();
- marks.Del(tmp->Next());
- marks.Del(tmp);
- continue;
- }
- }
- mark=mark->Next();
- if ((last) && (mark==last)) return;
+ isyslog("video aspect description in info (%i:%i) wrong",
+ macontext.Info.AspectRatio.Num,
+ macontext.Info.AspectRatio.Den);
}
-}
-void cMarkAdStandalone::CheckLastMark()
-{
- if (marks.Count()<=2) return; // just two marks -> do nothing
- clMark *last=marks.GetLast();
- if (!last) return;
+ macontext.Info.AspectRatio.Num=macontext.Video.Info.AspectRatio.Num;
+ macontext.Info.AspectRatio.Den=macontext.Video.Info.AspectRatio.Den;
- clMark *nexttolast=last->Prev();
- if (!nexttolast) return;
+ isyslog("aspectratio of %i:%i detected. %s",
+ macontext.Video.Info.AspectRatio.Num,
+ macontext.Video.Info.AspectRatio.Den,
+ ((macontext.Video.Info.AspectRatio.Num==4) &&
+ (macontext.Video.Info.AspectRatio.Den==3)) ?
+ "logo/border detection disabled" : "");
- if ((last->type & 0xF)==(nexttolast->type & 0xF))
+ if ((macontext.Video.Info.AspectRatio.Num==4) &&
+ (macontext.Video.Info.AspectRatio.Den==3))
{
- isyslog("removing double stop mark (%i)",last->position);
- marks.Del(last);
- return;
- }
-}
-
-void cMarkAdStandalone::CheckFirstMark()
-{
- if (marksAligned) return;
- clMark *first=marks.GetFirst();
- if (!first) return;
-
- // Check the second mark
- clMark *second=first->Next();
- if (!second) return;
-
- if ((marks.Count(MT_BORDERCHANGE,0xF0)>0) && (marks.Count(MT_ASPECTCHANGE,0xF0)>0))
- {
- // wait till its clear, if we use ASPECT or BORDER
- return;
- }
-
- if ((second->type & 0xF)==MT_START)
- {
- bool delsec=false;
- clMark *third=second->Next();
- if (third)
- {
- if ((third->type & 0xF)==MT_START) delsec=true;
- }
- if (delsec)
- {
- isyslog("removing double start marks (%i,%i)",first->position,second->position);
- marks.Del(second);
- }
- else
- {
- isyslog("removing double start mark (%i)",first->position);
- }
- marks.Del(first);
- marksAligned=true;
- first=marks.GetFirst();
- if (first)
- {
- CalculateStopPosition(first->position,macontext.Video.Info.FramesPerSecond*MAXRANGE);
- }
- return;
- }
-
- if ((second->type & 0xF)==MT_STOP)
- {
- marksAligned=true;
- return;
+ bDecodeVideo=false;
+ macontext.Video.Options.IgnoreLogoDetection=true;
+ marks.Del(MT_CHANNELSTART);
+ marks.Del(MT_CHANNELSTOP);
+ // start mark must be around iStart
+ begin=marks.GetAround(macontext.Video.Info.FramesPerSecond*(MAXRANGE*4),iStart,MT_ASPECTSTART);
}
- // If we have an aspectchange, check the next aspectchange mark
- // and the difference between
- if ((second->type==MT_ASPECTCHANGE) && (length))
+ if (!bDecodeVideo)
{
- clMark *next=marks.GetNext(second->position,MT_ASPECTCHANGE);
- if (next)
- {
- int maxlen=length*(13*60)/(90*60); // max 13 minutes ads on 90 minutes program
- if (maxlen>(13*60)) maxlen=(13*60); // maximum ad block = 13 minutes
- int MAXPOSDIFF=(int) (macontext.Video.Info.FramesPerSecond*maxlen);
- if ((next->position-second->position)>MAXPOSDIFF)
- {
- clMark *first=marks.GetFirst();
- if (first)
- {
- isyslog("removing unaligned start mark (%i)",first->position);
- marks.Del(first);
- marksAligned=true;
- return;
- }
- }
- }
+ macontext.Video.Data.Valid=false;
+ marks.Del(MT_LOGOSTART);
+ marks.Del(MT_LOGOSTOP);
+ marks.Del(MT_HBORDERSTART);
+ marks.Del(MT_HBORDERSTOP);
+ marks.Del(MT_VBORDERSTART);
+ marks.Del(MT_VBORDERSTOP);
}
- return;
-}
-
-void cMarkAdStandalone::CheckAspectRatio_and_AudioChannels()
-{
- if (aspectChecked) return;
- dsyslog("checking aspectratio and audio channels");
-
- if (!macontext.Info.Channels)
+ if (!begin)
{
- macontext.Info.Channels=macontext.Audio.Info.Channels;
- if (macontext.Info.Channels==2) setAudio20=true;
- if (macontext.Info.Channels==6)
- {
- isyslog("DolbyDigital5.1 audio detected. logo/border detection disabled");
- bDecodeVideo=false;
- setAudio20=false;
- setAudio51=true;
- reprocess=true;
- }
+ begin=marks.GetAround(macontext.Video.Info.FramesPerSecond*(MAXRANGE*2),iStart,MT_START,0x0F);
}
-
- bool aSet=false;
- if (!macontext.Info.AspectRatio.Num)
+ if (begin)
{
- isyslog("assuming aspectratio of %i:%i",
- macontext.Video.Info.AspectRatio.Num,macontext.Video.Info.AspectRatio.Den);
- aSet=true;
+ marks.DelTill(begin->position);
+ CalculateCheckPositions(begin->position);
+ isyslog("using mark on position %i as start mark",begin->position);
}
else
{
- if (!bIgnoreVideoInfo)
- {
- if ((macontext.Info.AspectRatio.Num!=macontext.Video.Info.AspectRatio.Num) &&
- (macontext.Info.AspectRatio.Den!=macontext.Video.Info.AspectRatio.Den))
- {
- isyslog("aspectratio in info wrong %i:%i instead of %i:%i",
- macontext.Video.Info.AspectRatio.Num,macontext.Video.Info.AspectRatio.Den,
- macontext.Info.AspectRatio.Num,macontext.Info.AspectRatio.Den);
- aSet=true;
- }
- }
- }
-
- if (aSet)
- {
- macontext.Info.AspectRatio.Num=macontext.Video.Info.AspectRatio.Num;
- macontext.Info.AspectRatio.Den=macontext.Video.Info.AspectRatio.Den;
-
- if ((macontext.Info.AspectRatio.Num==16) &&
- (macontext.Info.AspectRatio.Den==9))
- {
- macontext.Video.Options.IgnoreAspectRatio=true;
- setVideo169=true;
- setVideo43=false;
- setVideo43LB=false;
- }
-
- if ((macontext.Info.AspectRatio.Num==4) &&
- (macontext.Info.AspectRatio.Den==3))
- {
- setVideo43=true;
- setVideo169=false;
- }
- reprocess=true;
+ //fallback, shouldn't be reached
+ MarkAdMark mark;
+ memset(&mark,0,sizeof(mark));
+ mark.Position=iStart;
+ mark.Type=MT_ASSUMEDSTART;
+ AddMark(&mark);
+ marks.DelTill(iStart);
+ CalculateCheckPositions(iStart);
}
-
- aspectChecked=true;
+ iStart=0;
return;
}
void cMarkAdStandalone::AddMark(MarkAdMark *Mark)
{
- if (gotendmark) return;
if (!Mark) return;
if (!Mark->Type) return;
- if (!macontext.Video.Info.FramesPerSecond) return;
-
- bool loggedAlready=false;
+ if (gotendmark) return;
- if (Mark->Type==MT_ASPECTSTOP)
+ char *comment=NULL;
+ switch (Mark->Type)
{
- // check if last mark is an stop mark in short distance
- clMark *prev=marks.GetLast();
- if (prev)
+ case MT_ASSUMEDSTART:
+ if (asprintf(&comment,"assuming start (%i)",Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_ASSUMEDSTOP:
+ if (asprintf(&comment,"assuming stop (%i)",Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_LOGOSTART:
+ if (asprintf(&comment,"detected logo start (%i)*",Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_LOGOSTOP:
+ if (asprintf(&comment,"detected logo stop (%i)",Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_HBORDERSTART:
+ if (asprintf(&comment,"detected start of horiz. borders (%i)*",
+ Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_HBORDERSTOP:
+ if (asprintf(&comment,"detected stop of horiz. borders (%i)",
+ Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_VBORDERSTART:
+ if (asprintf(&comment,"detected start of vert. borders (%i)*",
+ Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_VBORDERSTOP:
+ if (asprintf(&comment,"detected stop of vert. borders (%i)",
+ Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_ASPECTSTART:
+ if (!Mark->AspectRatioBefore.Num)
{
- if ((prev->type & 0xF)==MT_STOP)
- {
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*15);
- if ((Mark->Position-prev->position)<MARKDIFF)
- {
- if (Mark->Comment) isyslog("%s",Mark->Comment);
- isyslog("double stop mark in short distance, deleting this mark (%i)",prev->position);
- marks.Del(prev);
- loggedAlready=true;
- }
- }
- if (prev->type==MT_ASPECTSTART)
- {
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*240);
- if ((Mark->Position-prev->position)<MARKDIFF)
- {
- if (Mark->Comment) isyslog("%s",Mark->Comment);
- double distance=(Mark->Position-prev->position)/macontext.Video.Info.FramesPerSecond;
- isyslog("aspect mark distance too short (%.1fs), deleting (%i,%i)",distance,
- prev->position,Mark->Position);
- marks.Del(prev);
- return;
- }
- }
+ if (asprintf(&comment,"aspectratio start with %i:%i (%i)*",
+ Mark->AspectRatioAfter.Num,Mark->AspectRatioAfter.Den,
+ Mark->Position)==-1) comment=NULL;
}
- }
-
- if (Mark->Type==MT_CHANNELSTART)
- {
- clMark *prev=marks.GetPrev(Mark->Position,MT_CHANNELSTOP);
- if (prev)
+ else
{
- int MARKDIFF=(int) macontext.Video.Info.FramesPerSecond;
- if ((Mark->Position-prev->position)<MARKDIFF)
- {
- if (Mark->Comment) isyslog("%s",Mark->Comment);
- double distance=(Mark->Position-prev->position)/macontext.Video.Info.FramesPerSecond;
- isyslog("channel distance too short (%.1fs), deleting (%i,%i)",distance,
- prev->position,Mark->Position);
- marks.Del(prev);
- return;
- }
+ if (asprintf(&comment,"aspectratio change from %i:%i to %i:%i (%i)*",
+ Mark->AspectRatioBefore.Num,Mark->AspectRatioBefore.Den,
+ Mark->AspectRatioAfter.Num,Mark->AspectRatioAfter.Den,
+ Mark->Position)==-1) comment=NULL;
}
+ break;
+ case MT_ASPECTSTOP:
+ if (asprintf(&comment,"aspectratio change from %i:%i to %i:%i (%i)",
+ Mark->AspectRatioBefore.Num,Mark->AspectRatioBefore.Den,
+ Mark->AspectRatioAfter.Num,Mark->AspectRatioAfter.Den,
+ Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_CHANNELSTART:
+ if (asprintf(&comment,"audio channel change from %i to %i (%i)*",
+ Mark->ChannelsBefore,Mark->ChannelsAfter,
+ Mark->Position)==-1) comment=NULL;
+ break;
+ case MT_CHANNELSTOP:
+ if (asprintf(&comment,"audio channel change from %i to %i (%i)",
+ Mark->ChannelsBefore,Mark->ChannelsAfter,
+ Mark->Position)==-1) comment=NULL;
+ break;
}
- clMark *old=marks.Get(Mark->Position);
- if ((old) && (((old->type & 0xF0)==MT_ASPECTCHANGE) || ((old->type & 0xF0)==MT_CHANNELCHANGE)))
- {
- // Aspect- / Channelchange wins over Logo/Border
- return;
- }
+ if (comment) isyslog("%s",comment);
- if (Mark->Type==MT_LOGOSTOP)
+ if ((Mark->Type & 0x0F)==MT_STOP)
{
- // check if last mark is an audiochannel stop
- clMark *prev=marks.GetLast();
- if ((prev) && (prev->type==MT_CHANNELSTOP))
+ clMark *prev=marks.GetPrev(Mark->Position,(Mark->Type & 0xF0)|MT_START);
+ if (prev)
{
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*15);
- if ((Mark->Position-prev->position)<MARKDIFF)
+ int MARKDIFF;
+ if ((Mark->Type & 0xF0)==MT_LOGOCHANGE)
{
- if (Mark->Comment) isyslog("%s",Mark->Comment);
- isyslog("audiochannel change in short distance, using this mark (%i->%i)",Mark->Position,prev->position);
- return;
+ MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*240);
+ }
+ else
+ {
+ MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*10);
}
- }
-
- prev=marks.GetPrev(Mark->Position,MT_LOGOSTART);
- if (prev)
- {
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*240);
if ((Mark->Position-prev->position)<MARKDIFF)
{
- if (Mark->Comment) isyslog("%s",Mark->Comment);
double distance=(Mark->Position-prev->position)/macontext.Video.Info.FramesPerSecond;
- isyslog("logo distance too short (%.1fs), deleting (%i,%i)",distance,
+ isyslog("mark distance too short (%.1fs), deleting %i,%i",distance,
prev->position,Mark->Position);
+ if ((prev->type & 0x0F)==MT_START) inBroadCast=false;
marks.Del(prev);
return;
}
}
}
- if (Mark->Type==MT_LOGOSTART)
+ clMark *prev=marks.GetLast();
+ if (prev)
{
- // check if last mark is an aspectratio change
- clMark *prev=marks.GetLast();
- if (prev)
+ if ((Mark->Type==MT_LOGOSTART) && (!iStart))
{
- if ((prev->type & 0xF0)==MT_ASPECTCHANGE)
+ if (prev->type==MT_LOGOSTOP)
{
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*5);
+ int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*30);
if ((Mark->Position-prev->position)<MARKDIFF)
{
- if (Mark->Comment) isyslog("%s",Mark->Comment);
- isyslog("aspectratio change in short distance, deleting this mark (%i)",
- Mark->Position);
- return;
- }
- }
-
- if (prev->type==MT_CHANNELSTART)
- {
- int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*5);
- if ((Mark->Position-prev->position)<MARKDIFF)
- {
- if (Mark->Comment) isyslog("%s",Mark->Comment);
- isyslog("audiochannel change in short distance, deleting this mark (%i)",
- Mark->Position);
+ double distance=(Mark->Position-prev->position)/macontext.Video.Info.FramesPerSecond;
+ isyslog("mark distance too short (%.1fs), deleting %i,%i",distance,
+ prev->position,Mark->Position);
+ if ((prev->type & 0x0F)==MT_START) inBroadCast=false;
+ marks.Del(prev);
return;
}
}
}
- }
- if (length>0)
- {
- if ((Mark->Type==MT_BORDERSTART) && (Mark->Position>chkLEFT) &&
- (Mark->Position<chkRIGHT) && (!macontext.Video.Options.IgnoreLogoDetection))
+ if ((prev->type & 0x0F)==(Mark->Type & 0x0F))
{
- if (Mark->Comment)
+ int MARKDIFF=(int) (macontext.Video.Info.FramesPerSecond*30);
+ int diff=abs(Mark->Position-prev->position);
+ if (diff<MARKDIFF)
{
- isyslog("%s",Mark->Comment);
- loggedAlready=true;
- }
- isyslog("border changes detected. logo detection disabled");
- macontext.Video.Options.IgnoreLogoDetection=true;
- marks.Del((uchar) MT_LOGOSTART);
- marks.Del((uchar) MT_LOGOSTOP);
- }
-
- bool deleteLogoBorder=false;
- if (((Mark->Type & 0xF0)==MT_CHANNELCHANGE) && (Mark->Position>chkLEFT) &&
- (Mark->Position<chkRIGHT) && (macontext.Info.Channels!=6))
- {
- if (!loggedAlready)
- {
- if (Mark->Comment)
- {
- isyslog("%s",Mark->Comment);
- loggedAlready=true;
- }
- }
- isyslog("audio channel changes detected. logo/border detection disabled");
- if (macontext.Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H262)
- {
- if (!macontext.Info.AspectRatio.Num)
+ if (prev->type>Mark->Type)
{
- isyslog("assuming broadcast aspectratio is 16:9");
- macontext.Info.AspectRatio.Num=16;
- macontext.Info.AspectRatio.Den=9;
- macontext.Video.Options.IgnoreAspectRatio=true;
- }
- }
- macontext.Info.Channels=6;
- setAudio51=true;
- setAudio20=false;
- reprocess=true;
- deleteLogoBorder=true;
- }
-
- if (((Mark->Type & 0xF0)==MT_ASPECTCHANGE) && (Mark->Position>chkLEFT) &&
- (Mark->Position<chkRIGHT) && (!macontext.Video.Options.IgnoreLogoDetection))
- {
- if (!loggedAlready)
- {
- if (Mark->Comment)
- {
- isyslog("%s",Mark->Comment);
- loggedAlready=true;
+ isyslog("previous mark (%i) stronger than actual mark, deleting %i",
+ prev->position, Mark->Position);
+ return;
}
- }
- isyslog("aspectratio changes detected. logo/border detection disabled");
-
- if (!macontext.Info.AspectRatio.Num)
- {
- isyslog("assuming broadcast aspectratio is 4:3");
- macontext.Info.AspectRatio.Num=4;
- macontext.Info.AspectRatio.Den=3;
- reprocess=true;
- setVideo43=true;
- }
- else
- {
- if ((macontext.Info.AspectRatio.Num==4) &&
- (macontext.Info.AspectRatio.Den==3))
+ else
{
- if (marks.Count(MT_BORDERSTART)>0)
- {
- isyslog("assuming broadcast is in letterbox format");
- setVideo43LB=true;
- setVideo43=false;
- }
+ isyslog("actual mark stronger then previous mark, deleting %i",prev->position);
+ marks.Del(prev);
}
}
- deleteLogoBorder=true;
- }
-
- if (deleteLogoBorder)
- {
- bDecodeVideo=false;
- macontext.Video.Options.IgnoreLogoDetection=true;
- macontext.Video.Data.Valid=false;
- marks.Del((uchar) MT_LOGOSTART);
- marks.Del((uchar) MT_LOGOSTOP);
- marks.Del((uchar) MT_BORDERSTART);
- marks.Del((uchar) MT_BORDERSTOP);
}
}
- if (Mark->Position>chkLEFT) CheckFirstMark();
- if (marksAligned) CheckLogoMarks(marks.GetLast());
- if ((Mark->Comment) && (!loggedAlready)) isyslog("%s",Mark->Comment);
- marks.Add(Mark->Type,Mark->Position,Mark->Comment);
+ if ((Mark->Type & 0x0F)==MT_START)
+ {
+ inBroadCast=true;
+ }
+ else
+ {
+ inBroadCast=false;
+ }
+ marks.Add(Mark->Type,Mark->Position,comment);
}
void cMarkAdStandalone::SaveFrame(int frame)
@@ -825,21 +528,7 @@ void cMarkAdStandalone::SaveFrame(int frame)
fclose(pFile);
}
-void cMarkAdStandalone::CheckBroadcastLength()
-{
- if (length) return;
- if (!macontext.Video.Info.FramesPerSecond) return;
- /* get broadcastlength from length of indexFile */
- int tframecnt=1;
- int iIndexError;
- marks.CheckIndex(directory,isTS,&tframecnt,&iIndexError);
- if (iIndexError!=0) return;
- length=tframecnt/macontext.Video.Info.FramesPerSecond;
- isyslog("got broadcast length of %im from index",length/60);
- reprocess=true;
-}
-
-bool cMarkAdStandalone::CheckIndexGrowing()
+void cMarkAdStandalone::CheckIndexGrowing()
{
// Here we check if the index is more
// advanced than our framecounter.
@@ -848,15 +537,15 @@ bool cMarkAdStandalone::CheckIndexGrowing()
#define WAITTIME 15
- if (!indexFile) return false;
- if (macontext.Config->logoExtraction!=-1) return false;
- if (sleepcnt>=2) return false; // we already slept too much
+ if (!indexFile) return;
+ if (macontext.Config->logoExtraction!=-1) return;
+ if (sleepcnt>=2) return; // we already slept too much
bool notenough=true;
do
{
struct stat statbuf;
- if (stat(indexFile,&statbuf)==-1) return false;
+ if (stat(indexFile,&statbuf)==-1) return;
int maxframes=statbuf.st_size/8;
if (maxframes<(framecnt+200))
@@ -868,7 +557,7 @@ bool cMarkAdStandalone::CheckIndexGrowing()
if (time(NULL)>(startTime+(time_t) length))
{
// "old" recording
- return false;
+ return;
}
else
{
@@ -880,13 +569,13 @@ bool cMarkAdStandalone::CheckIndexGrowing()
else
{
// "old" recording
- return false;
+ return;
}
}
marks.Save(directory,macontext.Video.Info.FramesPerSecond,isTS);
sleep(WAITTIME); // now we sleep and hopefully the index will grow
waittime+=WAITTIME;
- if (errno==EINTR) return false;
+ if (errno==EINTR) return;
sleepcnt++;
if (sleepcnt>=2)
{
@@ -907,8 +596,7 @@ bool cMarkAdStandalone::CheckIndexGrowing()
}
}
while (notenough);
- if (!sleepcnt) return true;
- else return false;
+ return;
}
void cMarkAdStandalone::ChangeMarks(clMark **Mark1, clMark **Mark2, MarkAdPos *NewPos)
@@ -920,17 +608,25 @@ void cMarkAdStandalone::ChangeMarks(clMark **Mark1, clMark **Mark2, MarkAdPos *N
if ((*Mark1)->position!=NewPos->FrameNumberBefore)
{
+ char *buf=NULL;
+ if (asprintf(&buf,"overlap before %i, moved to %i",(*Mark1)->position,
+ NewPos->FrameNumberBefore)==-1) return;
+ isyslog("%s",buf);
marks.Del(*Mark1);
- *Mark1=marks.Add(MT_MOVED,NewPos->FrameNumberBefore,NewPos->CommentBefore);
+ *Mark1=marks.Add(MT_MOVED,NewPos->FrameNumberBefore,buf);
+ free(buf);
save=true;
}
- if (NewPos->CommentBefore) isyslog("%s",NewPos->CommentBefore);
if (Mark2 && (*Mark2) && (*Mark2)->position!=NewPos->FrameNumberAfter)
{
+ char *buf=NULL;
+ if (asprintf(&buf,"overlap after %i, moved to %i",(*Mark2)->position,
+ NewPos->FrameNumberAfter)==-1) return;
+ isyslog("%s",buf);
marks.Del(*Mark2);
- *Mark2=marks.Add(MT_MOVED,NewPos->FrameNumberAfter,NewPos->CommentAfter);
- if (NewPos->CommentAfter) isyslog("%s",NewPos->CommentAfter);
+ *Mark2=marks.Add(MT_MOVED,NewPos->FrameNumberAfter,buf);
+ free(buf);
save=true;
}
if (save) marks.Save(directory,macontext.Video.Info.FramesPerSecond,isTS,true);
@@ -950,12 +646,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 +688,20 @@ 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)");
+ if (pn==mBEFORE)
+ {
+ dsyslog("processing file %05i (before mark %i)",Number,(*Mark1)->position);
+ }
+ else
+ {
+ dsyslog("processing file %05i (after mark %i)",Number,(*Mark2)->position);
+ }
}
if (lseek(f,Offset,SEEK_SET)!=Offset)
@@ -1007,32 +710,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 +752,15 @@ 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));
- //SaveFrame(lastiframe);
+ if (pn>mSTART) pos=video->ProcessOverlap(lastiframe,Frames,(pn==mBEFORE));
framecounter++;
}
- if ((pos) && (pn==3))
+ if ((pos) && (pn==mAFTER))
{
// found overlap
ChangeMarks(Mark1,Mark2,pos);
@@ -1071,54 +771,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 +817,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;
@@ -1196,24 +835,22 @@ void cMarkAdStandalone::Process2ndPass()
off_t offset;
int number,frame,iframes;
int frange=macontext.Video.Info.FramesPerSecond*120; // 40s + 80s
- int overlap=macontext.Video.Info.FramesPerSecond*10; // 10s
- if (((p1->type & 0xF0)==MT_ASPECTCHANGE) || (p1->type==0))
- {
- dsyslog("ignoring additional overlap");
- overlap=0;
- }
-
- if (marks.ReadIndex(directory,isTS,p1->position-frange,frange+overlap,&number,&offset,&frame,&iframes))
+ if (marks.ReadIndex(directory,isTS,p1->position-frange,frange,&number,&offset,&frame,&iframes))
{
if (!ProcessFile2ndPass(&p1,NULL,number,offset,frame,iframes)) break;
frange=macontext.Video.Info.FramesPerSecond*320; // 160s + 160s
- if (marks.ReadIndex(directory,isTS,p2->position-overlap,frange+overlap,&number,&offset,&frame,&iframes))
+ if (marks.ReadIndex(directory,isTS,p2->position,frange,&number,&offset,&frame,&iframes))
{
if (!ProcessFile2ndPass(&p1,&p2,number,offset,frame,iframes)) break;
}
}
+ else
+ {
+ esyslog("error reading index");
+ return;
+ }
p1=p2->Next();
if (p1)
@@ -1232,7 +869,7 @@ bool cMarkAdStandalone::ProcessFile(int Number)
if (!directory) return false;
if (!Number) return false;
- if (!CheckIndexGrowing()) CheckBroadcastLength();
+ CheckIndexGrowing();
if (abort) return false;
@@ -1256,154 +893,123 @@ 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)
+ {
+ CalculateCheckPositions(tStart*macontext.Video.Info.FramesPerSecond);
+ }
- if (!framecnt)
- {
- AddStartMark();
- }
+ if (macontext.Config->GenIndex)
+ {
+ marks.WriteIndex(directory,isTS,demux->Offset(),macontext.Video.Info.Pict_Type,Number);
+ }
+ framecnt++;
- if (macontext.Config->GenIndex)
- {
- marks.WriteIndex(directory,isTS,offset,macontext.Video.Info.Pict_Type,Number);
+ if (macontext.Video.Info.Pict_Type==MA_I_TYPE)
+ {
+ lastiframe=iframe;
+ if ((iStart<0) && (lastiframe>-iStart)) iStart=lastiframe;
+ if ((iStop<0) && (lastiframe>-iStop)) iStop=lastiframe;
+ if (iStart>0)
+ {
+ if ((inBroadCast) && (lastiframe>chkSTART)) CheckStart();
+ }
+ if (iStop>0)
+ {
+ if (lastiframe>chkSTOP) CheckStop();
+ }
+ iframe=framecnt-1;
+ dRes=true;
+ }
}
- 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 ((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))
+ {
+ isyslog("found AC3");
+ noticeVDR_AC3=true;
+ }
+ if ((framecnt-iframe)<=3)
{
- for (int i=0; i<vmarks->Count; i++)
+ 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");
- 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 ((gotendmark) && (!macontext.Config->GenIndex))
{
if (f!=-1) close(f);
return true;
}
- if (!CheckIndexGrowing()) CheckBroadcastLength();
+ CheckIndexGrowing();
if (abort)
{
if (f!=-1) close(f);
@@ -1417,23 +1023,18 @@ bool cMarkAdStandalone::ProcessFile(int Number)
bool cMarkAdStandalone::Reset(bool FirstPass)
{
bool ret=true;
- reprocess=false;
if (FirstPass) framecnt=0;
lastiframe=0;
iframe=0;
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;
- chkRIGHT=INT_MIN;
+ chkSTART=chkSTOP=INT_MAX;
if (FirstPass)
{
- marksAligned=false;
marks.DelAll();
marks.CloseIndex(directory,isTS);
}
@@ -1448,9 +1049,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;
@@ -1463,39 +1062,22 @@ void cMarkAdStandalone::ProcessFile()
if (abort) break;
if (!ProcessFile(i)) break;
if ((gotendmark) && (!macontext.Config->GenIndex)) break;
- if (reprocess)
- {
- isyslog("restarting from scratch");
- i=0;
- Reset();
- }
}
if (!abort)
{
if (lastiframe)
{
- CheckStartStop(lastiframe,true);
-
- if ((!gotendmark) && ((iStop<0) || (!tStart)))
+ if ((inBroadCast) && (!gotendmark))
{
- char *buf;
MarkAdMark tempmark;
- tempmark.Type=MT_COMMONSTOP;
+ tempmark.Type=MT_ASSUMEDSTOP;
tempmark.Position=lastiframe;
-
- if (asprintf(&buf,"stop of recording (%i)",lastiframe)!=-1)
- {
- tempmark.Comment=buf;
- AddMark(&tempmark);
- free(buf);
- }
+ AddMark(&tempmark);
}
}
-
- CheckLastMark();
- CheckLogoMarks();
}
+ skipped=demux->Skipped();
}
void cMarkAdStandalone::Process()
@@ -1581,8 +1163,7 @@ bool cMarkAdStandalone::SetFileUID(char *File)
bool cMarkAdStandalone::SaveInfo()
{
- if ((!setVideo43) && (!setVideo169) && (!setAudio20) && (!setAudio51) && (!setVideo43LB)) return true;
-
+ isyslog("writing info file");
char *src,*dst;
if (asprintf(&src,"%s/info%s",directory,isTS ? "" : ".vdr")==-1) return false;
@@ -1594,7 +1175,6 @@ bool cMarkAdStandalone::SaveInfo()
FILE *r,*w;
r=fopen(src,"r");
-
w=fopen(dst,"w+");
if ((!r) || (!w))
@@ -1608,12 +1188,6 @@ bool cMarkAdStandalone::SaveInfo()
char *lline=NULL;
size_t length=0;
- bool setVideo43LB_done=false;
- bool setVideo43_done=false;
- bool setVideo169_done=false;
- bool setAudio20_done=false;
- bool setAudio51_done=false;
-
char lang[4]="";
int component_type_add=0;
@@ -1653,47 +1227,46 @@ bool cMarkAdStandalone::SaveInfo()
case 5:
if (stream==stream_content)
{
- if ( (((type==1) || (type==5)) && (setVideo169)) ||
- (((type==3) || (type==7)) && ((setVideo43) || (setVideo43LB))))
+ if ((macontext.Info.AspectRatio.Num==4) && (macontext.Info.AspectRatio.Den==3))
{
- if (setVideo43)
- {
- if (fprintf(w,"X %i %02i %s 4:3\n",stream_content,
- component_type_43+component_type_add,lang)<=0) err=true;
- setVideo43_done=true;
- }
- if (setVideo43LB)
- {
- 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)
- {
- if (fprintf(w,"X %i %02i %s 16:9\n",stream_content,
- component_type_169+component_type_add,lang)<=0) err=true;
- setVideo169_done=true;
- }
+ if (fprintf(w,"X %i %02i %s 4:3\n",stream_content,
+ component_type_43+component_type_add,lang)<=0) err=true;
+ macontext.Info.AspectRatio.Num=0;
+ macontext.Info.AspectRatio.Den=0;
+ }
+ else if ((macontext.Info.AspectRatio.Num==16) && (macontext.Info.AspectRatio.Den==9))
+ {
+ if (fprintf(w,"X %i %02i %s 16:9\n",stream_content,
+ component_type_169+component_type_add,lang)<=0) err=true;
+ macontext.Info.AspectRatio.Num=0;
+ macontext.Info.AspectRatio.Den=0;
}
else
{
if (fprintf(w,"%s",line)<=0) err=true;
}
}
+ else
+ {
+ if (fprintf(w,"%s",line)<=0) err=true;
+ }
break;
case 2:
- if ((type==5) && ((setAudio51) || (setAudio20)))
+ if (type==5)
{
- if (setAudio51)
+ if (macontext.Info.Channels==6)
{
if (fprintf(w,"X 2 05 %s Dolby Digital 5.1\n",lang)<=0) err=true;
- setAudio51_done=true;
+ macontext.Info.Channels=0;
}
- if (setAudio20)
+ else if (macontext.Info.Channels==2)
{
if (fprintf(w,"X 2 05 %s Dolby Digital 2.0\n",lang)<=0) err=true;
- setAudio20_done=true;
+ macontext.Info.Channels=0;
+ }
+ else
+ {
+ if (fprintf(w,"%s",line)<=0) err=true;
}
}
else
@@ -1733,28 +1306,23 @@ bool cMarkAdStandalone::SaveInfo()
if (stream_content)
{
- if ((setVideo43LB) && (!setVideo43LB_done) && (!err))
- {
- if (fprintf(w,"X %i %02i %s 4:3 LetterBox\n",stream_content,
- component_type_43+component_type_add,lang)<=0) err=true;
- }
- if ((setVideo43) && (!setVideo43_done) && (!err))
+ if ((macontext.Info.AspectRatio.Num==4) && (macontext.Info.AspectRatio.Den==3) && (!err))
{
if (fprintf(w,"X %i %02i %s 4:3\n",stream_content,
component_type_43+component_type_add,lang)<=0) err=true;
}
- if ((setVideo169) && (!setVideo169_done) && (!err))
+ if ((macontext.Info.AspectRatio.Num==16) && (macontext.Info.AspectRatio.Den==9) && (!err))
{
if (fprintf(w,"X %i %02i %s 16:9\n",stream_content,
component_type_169+component_type_add,lang)<=0) err=true;
}
}
- if ((setAudio20) && (!setAudio20_done) && (!err))
+ if ((macontext.Info.Channels==2) && (!err))
{
if (fprintf(w,"X 2 05 %s Dolby Digital 2.0\n",lang)<=0) err=true;
}
- if ((setAudio51) && (!setAudio51_done) && (!err))
+ if ((macontext.Info.Channels==6) && (!err))
{
if (fprintf(w,"X 2 05 %s Dolby Digital 5.1\n",lang)<=0) err=true;
}
@@ -1800,23 +1368,36 @@ time_t cMarkAdStandalone::GetBroadcastStart(time_t start, int fd)
struct mntent *ent;
struct stat statbuf;
FILE *mounts=setmntent(_PATH_MOUNTED,"r");
+ int mlen=0;
+ int oldmlen=0;
+ bool useatime=false;
while ((ent=getmntent(mounts))!=NULL)
{
if (strstr(directory,ent->mnt_dir))
{
- if (strstr(ent->mnt_opts,"noatime"))
+ mlen=strlen(ent->mnt_dir);
+ if (mlen>oldmlen)
{
- if (stat(directory,&statbuf)!=-1)
+ if (strstr(ent->mnt_opts,"noatime"))
{
- endmntent(mounts);
- isyslog("getting broadcast start from directory atime");
- return statbuf.st_atime;
+ useatime=true;
+ }
+ else
+ {
+ useatime=false;
}
}
+ oldmlen=mlen;
}
}
endmntent(mounts);
+ if ((useatime) && (stat(directory,&statbuf)!=-1))
+ {
+ isyslog("getting broadcast start from directory atime");
+ return statbuf.st_atime;
+ }
+
// try to get from mtime
// (and hope info.vdr has not changed after the start of the recording)
if (fstat(fd,&statbuf)!=-1)
@@ -1930,7 +1511,7 @@ bool cMarkAdStandalone::LoadInfo()
int result=sscanf(line,"%*c %i %i %250c",&stream,&type,(char *) &descr);
if ((result!=0) && (result!=EOF))
{
- if (((stream==1) || (stream==5)) && (!bIgnoreVideoInfo))
+ if ((stream==1) || (stream==5))
{
if ((type!=1) && (type!=5) && (type!=9) && (type!=13))
{
@@ -1946,26 +1527,22 @@ bool cMarkAdStandalone::LoadInfo()
}
}
- if ((stream==2) && (!bIgnoreAudioInfo))
+ if (stream==2)
{
if (type==5)
{
// if we have DolbyDigital 2.0 disable AC3
if (strchr(descr,'2'))
{
- isyslog("broadcast with DolbyDigital2.0, disabling AC3 decoding");
- macontext.Info.DPid.Num=0;
+ isyslog("broadcast with DolbyDigital2.0 (from info)");
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");
- }
+ // if we have DolbyDigital 5.1 disable video decoding
+ if (strchr(descr,'5'))
+ {
+ isyslog("broadcast with DolbyDigital5.1 (from info)");
+ macontext.Info.Channels=6;
+ }
}
}
}
@@ -2011,8 +1588,6 @@ bool cMarkAdStandalone::LoadInfo()
esyslog("cannot read broadcast length from info, marks can be wrong!");
macontext.Info.AspectRatio.Num=0;
macontext.Info.AspectRatio.Den=0;
- bIgnoreAudioInfo=true;
- bIgnoreVideoInfo=true;
bDecodeVideo=macontext.Config->DecodeVideo;
macontext.Video.Options.IgnoreAspectRatio=false;
}
@@ -2131,7 +1706,11 @@ bool cMarkAdStandalone::CheckPATPMT(off_t Offset)
free(buf);
if (fd==-1) return false;
- if (lseek(fd,Offset,SEEK_SET)==(off_t)-1) return false;
+ if (lseek(fd,Offset,SEEK_SET)==(off_t)-1)
+ {
+ close(fd);
+ return false;
+ }
uchar patpmt_buf[564];
uchar *patpmt;
@@ -2324,39 +1903,27 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
directory=Directory;
abort=false;
gotendmark=false;
- reprocess=false;
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));
-
- setAudio51=false;
- setAudio20=false;
- setVideo43=false;
- setVideo43LB=false;
- setVideo169=false;
- aspectChecked=false;
+ memset(&pkt,0,sizeof(pkt));
noticeVDR_MP2=false;
noticeVDR_AC3=false;
noticeHEADER=false;
noticeFILLER=false;
- errcnt=0;
+ skipped=0;
sleepcnt=0;
waittime=iwaittime=0;
duplicate=false;
- marksAligned=false;
title[0]=0;
memset(&macontext,0,sizeof(macontext));
@@ -2365,25 +1932,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
bDecodeVideo=config->DecodeVideo;
bDecodeAudio=config->DecodeAudio;
- tStart=iStart=iStop=iStartCheck=iStopCheck=0;
-
- if ((config->ignoreInfo & IGNORE_VIDEOINFO)==IGNORE_VIDEOINFO)
- {
- bIgnoreVideoInfo=true;
- }
- else
- {
- bIgnoreVideoInfo=false;
- }
-
- if ((config->ignoreInfo & IGNORE_AUDIOINFO)==IGNORE_AUDIOINFO)
- {
- bIgnoreAudioInfo=true;
- }
- else
- {
- bIgnoreAudioInfo=false;
- }
+ tStart=iStart=iStop=0;
if ((config->ignoreInfo & IGNORE_TIMERINFO)==IGNORE_TIMERINFO)
{
@@ -2408,14 +1957,6 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
{
isyslog("video decoding disabled by user");
}
- if (bIgnoreAudioInfo)
- {
- isyslog("audio info usage disabled by user");
- }
- if (bIgnoreVideoInfo)
- {
- isyslog("video info usage disabled by user");
- }
if (bIgnoreTimerInfo)
{
isyslog("timer info usage disabled by user");
@@ -2425,8 +1966,6 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
{
// just to be sure extraction works
bDecodeVideo=true;
- bIgnoreAudioInfo=true;
- bIgnoreVideoInfo=true;
}
if (!config->NoPid)
@@ -2465,6 +2004,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())
{
@@ -2473,7 +2013,7 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
esyslog("failed loading info - logo %s%sdisabled",
(config->logoExtraction!=-1) ? "extraction" : "detection",
bIgnoreTimerInfo ? " " : " and pre-/post-timer ");
- tStart=0;
+ tStart=iStart=iStop=0;
}
}
@@ -2505,42 +2045,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)",macontext.Info.DPid.Num);
- ac3_demux = new cMarkAdDemux();
- }
- else
- {
- ac3_demux=NULL;
+ dsyslog("found AC3 (0x%04x)",macontext.Info.DPid.Num);
}
if (!abort)
@@ -2551,15 +2082,14 @@ cMarkAdStandalone::cMarkAdStandalone(const char *Directory, const MarkAdConfig *
audio = new cMarkAdAudio(&macontext);
streaminfo = new cMarkAdStreamInfo;
if (macontext.Info.ChannelName)
- dsyslog("channel %s",macontext.Info.ChannelName);
+ isyslog("channel %s",macontext.Info.ChannelName);
}
framecnt=0;
framecnt2=0;
lastiframe=0;
iframe=0;
- chkLEFT=INT_MAX;
- chkRIGHT=INT_MIN;
+ chkSTART=chkSTOP=INT_MAX;
gettimeofday(&tv1,&tz);
}
@@ -2567,9 +2097,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);
@@ -2606,9 +2136,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;
@@ -2642,10 +2170,7 @@ int usage(int svdrpport)
" decoding, 3 = disable video and audio decoding\n"
"-i --ignoreinfo=<info>\n"
" ignores hints from info(.vdr) file\n"
- " <info> 1 = ignore audio info, 2 = ignore video info,\n"
- " 4 = ignore timer info\n"
- " (options can be added together, e.g. 5 = ignore\n"
- " audio and timer info)\n"
+ " <info> 4 = ignore timer info\n"
"-l --logocachedir\n"
" directory where logos stored, default /var/lib/markad\n"
"-p --priority=<priority>\n"
@@ -2655,7 +2180,7 @@ int usage(int svdrpport)
" io priority of markad when running in background\n"
" <class> 1 = realtime, <level> from 0..7, default 4\n"
" 2 = besteffort, <level> from 0..7, default 4\n"
- " 3 = idle\n"
+ " 3 = idle (default)\n"
"-v --verbose\n"
" increments loglevel by one, can be given multiple times\n"
"-B --backupmarks\n"
@@ -2681,8 +2206,13 @@ int usage(int svdrpport)
" (default is the number of cpus)\n"
"-V --version\n"
" print version-info and exit\n"
+ " --loglevel=<level>\n"
+ " sets loglevel to the specified value\n"
+ " <level> 1=error 2=info 3=debug 4=trace\n"
" --markfile=<markfilename>\n"
" set a different markfile-name\n"
+ " --nopid\n"
+ " disables creation of markad.pid file in recdir\n"
" --online[=1|2] (default is 1)\n"
" start markad immediately when called with \"before\" as cmd\n"
" if online is 1, markad starts online for live-recordings\n"
@@ -2766,8 +2296,8 @@ int main(int argc, char *argv[])
bool bAfter=false,bEdited=false;
bool bFork=false,bNice=false,bImmediateCall=false;
int niceLevel = 19;
- int ioprio_class=2;
- int ioprio=4;
+ int ioprio_class=3;
+ int ioprio=7;
char *tok,*str;
int ntok;
int online=0;
@@ -2780,6 +2310,7 @@ int main(int argc, char *argv[])
// set defaults
config.DecodeVideo=true;
config.DecodeAudio=true;
+ config.SaveInfo=false;
config.logoExtraction=-1;
config.logoWidth=-1;
config.logoHeight=-1;
@@ -2834,7 +2365,7 @@ int main(int argc, char *argv[])
{"backupmarks", 0, 0, 'B'},
{"scenechangedetection", 0, 0, 'C'},
{"genindex",0, 0, 'G'},
- {"saveinfo",0,0,'I'},
+ {"saveinfo",0, 0, 'I'},
{"extractlogo", 1, 0, 'L'},
{"OSD",0,0,'O' },
{"log2rec",0,0,'R'},
@@ -2845,7 +2376,7 @@ int main(int argc, char *argv[])
{0, 0, 0, 0}
};
- c = getopt_long (argc, argv, "abcd:i:jl:nop:r:s:vBCGL:ORST:V",
+ c = getopt_long (argc, argv, "abcd:i:jl:nop:r:s:vBCGIL:ORST:V",
long_options, &option_index);
if (c == -1)
break;
@@ -2890,7 +2421,7 @@ int main(int argc, char *argv[])
case 'i':
// --ignoreinfo
config.ignoreInfo=atoi(optarg);
- if ((config.ignoreInfo<0) || (config.ignoreInfo>255))
+ if ((config.ignoreInfo<1) || (config.ignoreInfo>255))
{
fprintf(stderr, "markad: invalid ignoreinfo option: %s\n", optarg);
return 2;
@@ -3071,7 +2602,14 @@ int main(int argc, char *argv[])
break;
case 4: // --online
- online=atoi(optarg);
+ if (optarg)
+ {
+ online=atoi(optarg);
+ }
+ else
+ {
+ online=1;
+ }
if ((online!=1) && (online!=2))
{
fprintf(stderr, "markad: invalid online value: %s\n", optarg);
diff --git a/command/markad-standalone.h b/command/markad-standalone.h
index 78f0ea9..de91225 100644
--- a/command/markad-standalone.h
+++ b/command/markad-standalone.h
@@ -24,8 +24,7 @@
#define DELTATIME 20000 /* equals to 222ms (base is 90kHz PTS) */
-#define MAXRANGE 420 /* range to search for start/stop marks in seconds */
-
+#define MAXRANGE 120 /* range to search for start/stop marks in seconds */
class cOSDMessage
{
@@ -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;
@@ -189,7 +188,6 @@ unsigned Descriptor_Length:
bool abort;
bool gotendmark;
- bool reprocess;
int waittime;
int iwaittime;
struct timeval tv1,tv2;
@@ -202,49 +200,32 @@ unsigned Descriptor_Length:
bool bDecodeVideo;
bool bDecodeAudio;
- bool bIgnoreAudioInfo;
- bool bIgnoreVideoInfo;
bool bIgnoreTimerInfo;
- time_t startTime; // StartTime of broadcast
- int length; // Length in seconds
+ time_t startTime; // starttime of broadcast
+ int length; // length of broadcast in seconds
int tStart; // pretimer in seconds
- int iStart; // pretimer as index value
- int iStartCheck; // check position for iStart
- int iStop; // posttimer as index value
- int iStopCheck; // check position for iStop
+ int iStart; // pretimer in frames (negative if unset)
+ int iStop; // endposition in frames (negative if unset)
- int errcnt; // Skipped bytes in stream
+ void CheckStop();
+ void CheckStart();
+ void CalculateCheckPositions(int startframe);
+ int chkSTART;
+ int chkSTOP;
- bool setAudio51; // set audio to 5.1 in info
- bool setAudio20; // set audio to 2.0 in info
- bool setVideo43; // set video to 4:3 in info
- bool setVideo43LB; // set video to 4:3 letterbox in info
- bool setVideo169; // set video to 16:9 in info
-
- int chkLEFT;
- int chkRIGHT;
+ int skipped; // skipped bytes in whole file
+ bool inBroadCast; // are we in a broadcast (or ad)?
time_t GetBroadcastStart(time_t start, int fd);
- void CheckBroadcastLength();
- bool CheckIndexGrowing();
+ void CheckIndexGrowing();
char *indexFile;
int sleepcnt;
void SaveFrame(int Frame);
- bool aspectChecked;
- bool marksAligned;
-
clMarks marks;
char *IndexToHMSF(int Index);
- void CalculateStopPosition(int startframe, int delta);
- void CheckFirstMark();
- void CheckLastMark();
- void CheckStartStop(int frame, bool checkend=false);
- void CheckAspectRatio_and_AudioChannels();
- void CheckLogoMarks(clMark *last=NULL);
- void AddStartMark();
void AddMark(MarkAdMark *Mark);
bool Reset(bool FirstPass=true);
void ChangeMarks(clMark **Mark1, clMark **Mark2, MarkAdPos *NewPos);
diff --git a/command/marks.cpp b/command/marks.cpp
index 130ff42..8909e3c 100644
--- a/command/marks.cpp
+++ b/command/marks.cpp
@@ -186,6 +186,29 @@ clMark *clMarks::Get(int Position)
return mark;
}
+clMark *clMarks::GetAround(int Frames, int Position, int Type, int Mask)
+{
+ clMark *m1=GetPrev(Position,Type,Mask);
+ clMark *m2=GetNext(Position,Type,Mask);
+
+ if (!m1 && !m2) return NULL;
+ if (!m1 && m2) return m2;
+ if (m1 && !m2)
+ {
+ if (abs(Position-m1->position)>Frames) return NULL;
+ return m1;
+ }
+
+ if (abs(m1->position-Position)>abs(m2->position-Position))
+ {
+ return m2;
+ }
+ else
+ {
+ return m1;
+ }
+}
+
clMark *clMarks::GetPrev(int Position, int Type, int Mask)
{
if (!first) return NULL; // no elements yet
@@ -485,7 +508,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/marks.h b/command/marks.h
index 7c31ba9..18e6cc4 100644
--- a/command/marks.h
+++ b/command/marks.h
@@ -100,6 +100,7 @@ public:
void Del(unsigned char Type);
void Del(int Position);
clMark *Get(int Position);
+ clMark *GetAround(int Frames, int Position, int Type=0xFF, int Mask=0xFF);
clMark *GetPrev(int Position,int Type=0xFF, int Mask=0xFF);
clMark *GetNext(int Position,int Type=0xFF, int Mask=0xFF);
clMark *GetFirst()
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 cf5f649..be2cb5c 100644
--- a/command/video.cpp
+++ b/command/video.cpp
@@ -47,13 +47,13 @@ cMarkAdLogo::cMarkAdLogo(MarkAdContext *maContext)
if (maContext->Info.VPid.Type==MARKAD_PIDTYPE_VIDEO_H264)
{
- LOGOWIDTH=LOGO_DEFHDWIDTH;
LOGOHEIGHT=LOGO_DEFHDHEIGHT;
+ LOGOWIDTH=LOGO_DEFHDWIDTH;
}
else
{
- LOGOWIDTH=LOGO_DEFWIDTH;
LOGOHEIGHT=LOGO_DEFHEIGHT;
+ LOGOWIDTH=LOGO_DEFWIDTH;
}
pixfmt_info=false;
@@ -63,7 +63,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)
@@ -105,7 +105,11 @@ int cMarkAdLogo::Load(const char *directory, char *file, int plane)
return -2;
}
- if (fread(&area.mask[plane],1,width*height,pFile)!=(size_t) (width*height)) return -2;
+ if (fread(&area.mask[plane],1,width*height,pFile)!=(size_t) (width*height))
+ {
+ fclose(pFile);
+ return -2;
+ }
if (!area.mpixel[plane])
{
@@ -218,8 +222,9 @@ int cMarkAdLogo::SobelPlane(int plane)
return 0;
}
- int boundary=15;
+ int boundary=6;
int cutval=127;
+ //int cutval=60;
int width=LOGOWIDTH;
if (plane>0)
@@ -327,36 +332,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;
}
@@ -375,11 +380,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;
}
@@ -404,12 +409,16 @@ 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)
+ {
+ area.status=LOGO_UNINITIALIZED;
+ 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)
{
@@ -469,7 +478,7 @@ cMarkAdBlackBordersHoriz::cMarkAdBlackBordersHoriz(MarkAdContext *maContext)
void cMarkAdBlackBordersHoriz::Clear()
{
- borderstatus=UNINITIALIZED;
+ borderstatus=HBORDER_UNINITIALIZED;
borderframenumber=-1;
}
@@ -537,23 +546,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;
}
@@ -563,10 +572,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
}
@@ -578,7 +587,7 @@ int cMarkAdBlackBordersHoriz::Process(int FrameNumber, int *BorderIFrame)
else
{
borderframenumber=-1;
- borderstatus=NOBORDER;
+ borderstatus=HBORDER_INVISIBLE;
}
}
return 0;
@@ -588,10 +597,8 @@ cMarkAdOverlap::cMarkAdOverlap(MarkAdContext *maContext)
{
macontext=maContext;
- histbuf[BEFORE]=NULL;
- histbuf[AFTER]=NULL;
- result.CommentBefore=NULL;
- result.CommentAfter=NULL;
+ histbuf[OV_BEFORE]=NULL;
+ histbuf[OV_AFTER]=NULL;
Clear();
}
@@ -602,22 +609,20 @@ 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);
memset(&result,0,sizeof(result));
similarCutOff=0;
similarMaxCnt=0;
@@ -656,12 +661,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);
+ //printf("%6i %6i ",histbuf[OV_BEFORE][B].framenumber,histbuf[OV_AFTER][A].framenumber);
+ bool simil=areSimilar(histbuf[OV_BEFORE][B].histogram,histbuf[OV_AFTER][A].histogram);
if (simil)
{
tmpA=A;
@@ -675,15 +680,15 @@ MarkAdPos *cMarkAdOverlap::Detect()
}
else
{
- //if (simcnt) printf("%i %i %i\n",simcnt,histbuf[BEFORE][B].framenumber,histbuf[AFTER][A].framenumber);
+ //if (simcnt) printf("simcnt=%i\n",simcnt);
if (simcnt>similarMaxCnt)
{
- if ((histbuf[BEFORE][tmpB].framenumber>result.FrameNumberBefore) &&
- (histbuf[AFTER][tmpA].framenumber>result.FrameNumberAfter))
+ if ((histbuf[OV_BEFORE][tmpB].framenumber>result.FrameNumberBefore) &&
+ (histbuf[OV_AFTER][tmpA].framenumber>result.FrameNumberAfter))
{
- 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
@@ -698,23 +703,14 @@ 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
{
return NULL;
}
}
-
- if (asprintf(&result.CommentBefore,"detected overlap before (%i)",result.FrameNumberBefore)==-1)
- {
- result.CommentBefore=NULL;
- }
- if (asprintf(&result.CommentAfter,"detected overlap after (%i)",result.FrameNumberAfter)==-1)
- {
- result.CommentAfter=NULL;
- }
return &result;
}
@@ -722,13 +718,13 @@ MarkAdPos *cMarkAdOverlap::Process(int FrameNumber, int Frames, bool BeforeAd)
{
if ((lastframenumber>0) && (!similarMaxCnt))
{
- similarCutOff=60000; // lower is harder!
+ similarCutOff=50000; // lower is harder!
similarMaxCnt=4;
}
if (BeforeAd)
{
- if ((histframes[BEFORE]) && (histcnt[BEFORE]>=histframes[BEFORE]))
+ if ((histframes[OV_BEFORE]) && (histcnt[OV_BEFORE]>=histframes[OV_BEFORE]))
{
if (result.FrameNumberBefore)
{
@@ -739,31 +735,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;
@@ -783,7 +779,7 @@ cMarkAdVideo::cMarkAdVideo(MarkAdContext *maContext)
cMarkAdVideo::~cMarkAdVideo()
{
- ResetMarks();
+ resetmarks();
if (hborder) delete hborder;
if (logo) delete logo;
if (overlap) delete overlap;
@@ -793,41 +789,57 @@ 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++)
- {
- if (marks.Number[i].Comment) free(marks.Number[i].Comment);
- }
memset(&marks,0,sizeof(marks));
}
-bool cMarkAdVideo::AddMark(int Type, int Position, const char *Comment)
+bool cMarkAdVideo::addmark(int type, int position, MarkAdAspectRatio *before,
+ MarkAdAspectRatio *after)
{
- 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;
+ if (before)
+ {
+ marks.Number[marks.Count].AspectRatioBefore.Num=before->Num;
+ marks.Number[marks.Count].AspectRatioBefore.Den=before->Den;
+ }
+ if (after)
+ {
+ marks.Number[marks.Count].AspectRatioAfter.Num=after->Num;
+ marks.Number[marks.Count].AspectRatioAfter.Den=after->Den;
+ }
+ 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;
}
-MarkAdPos *cMarkAdVideo::Process2ndPass(int FrameNumber, int Frames, bool BeforeAd)
+MarkAdPos *cMarkAdVideo::ProcessOverlap(int FrameNumber, int Frames, bool BeforeAd)
{
if (!FrameNumber) return NULL;
if (!overlap) overlap=new cMarkAdOverlap(macontext);
@@ -840,7 +852,7 @@ MarkAdMarks *cMarkAdVideo::Process(int FrameNumber, int FrameNumberNext)
{
if ((!FrameNumber) && (!FrameNumberNext)) return NULL;
- ResetMarks();
+ resetmarks();
if (!macontext->Video.Options.IgnoreLogoDetection)
{
@@ -848,97 +860,69 @@ MarkAdMarks *cMarkAdVideo::Process(int FrameNumber, int FrameNumberNext)
int lret=logo->Process(FrameNumber,&logoframenumber);
if ((lret>=-1) && (lret!=0))
{
- char *buf=NULL;
if (lret>0)
{
- if (asprintf(&buf,"detected logo start (%i)",logoframenumber)!=-1)
- {
- AddMark(MT_LOGOSTART,logoframenumber,buf);
- free(buf);
- }
+ addmark(MT_LOGOSTART,logoframenumber);
}
else
{
- if (asprintf(&buf,"detected logo stop (%i)",logoframenumber)!=-1)
- {
- AddMark(MT_LOGOSTOP,logoframenumber,buf);
- free(buf);
- }
+ addmark(MT_LOGOSTOP,logoframenumber);
}
}
}
+ else
+ {
+ logo->SetStatusUninitialized();
+ }
- int borderframenumber;
- int hret=hborder->Process(FrameNumber,&borderframenumber);
+ int hborderframenumber;
+ int hret=hborder->Process(FrameNumber,&hborderframenumber);
- if ((hret>0) && (borderframenumber))
+ if ((hret>0) && (hborderframenumber))
{
- char *buf=NULL;
- if (asprintf(&buf,"detected start of horiz. borders (%i [%i])",
- borderframenumber,FrameNumber)!=-1)
- {
- AddMark(MT_BORDERSTART,borderframenumber,buf);
- free(buf);
- }
+ addmark(MT_HBORDERSTART,hborderframenumber);
}
- if ((hret<0) && (borderframenumber))
+ if ((hret<0) && (hborderframenumber))
{
- char *buf=NULL;
- if (asprintf(&buf,"detected stop of horiz. borders (%i [%i])",
- borderframenumber,FrameNumber)!=-1)
- {
- AddMark(MT_BORDERSTOP,borderframenumber,buf);
- free(buf);
- }
+ addmark(MT_HBORDERSTOP,hborderframenumber);
}
if (!macontext->Video.Options.IgnoreAspectRatio)
{
- if (AspectRatioChange(&macontext->Video.Info.AspectRatio,&aspectratio))
+ bool start;
+ if (aspectratiochange(macontext->Video.Info.AspectRatio,aspectratio,start))
{
- 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 ((logo->Status()==LOGO_VISIBLE) && (!start))
+ {
+ addmark(MT_LOGOSTOP,framebeforelast);
+ logo->SetStatusLogoInvisible();
+ }
- 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);
- }
+ addmark(MT_ASPECTSTART,start ? FrameNumber : FrameNumberNext,
+ &aspectratio,&macontext->Video.Info.AspectRatio);
}
else
{
- char nbuf[20];
- snprintf(nbuf,sizeof(nbuf),"%i)?",FrameNumber);
- nbuf[19]=0;
- strcat(buf,nbuf);
-
- AddMark(MT_ASPECTCHANGE,FrameNumber,buf);
+ addmark(MT_ASPECTSTOP,framelast,&aspectratio,
+ &macontext->Video.Info.AspectRatio);
}
- free(buf);
}
aspectratio.Num=macontext->Video.Info.AspectRatio.Num;
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 9767006..f4abbec 100644
--- a/command/video.h
+++ b/command/video.h
@@ -23,11 +23,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];
@@ -68,15 +90,6 @@ private:
BOTTOM_RIGHT
};
- enum
- {
- ERROR=-3,
- UNINITIALIZED=-2,
- NOLOGO=-1,
- NOCHANGE=0,
- LOGO=1
- };
-
int LOGOHEIGHT; // max. 140
int LOGOWIDTH; // 192-288
@@ -114,27 +127,36 @@ 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 SetStatusUninitialized()
+ {
+ if (area.status!=LOGO_UNINITIALIZED)
+ area.status=LOGO_UNINITIALIZED;
+ }
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();
};
@@ -149,16 +171,18 @@ 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, MarkAdAspectRatio *before=NULL,
+ MarkAdAspectRatio *after=NULL);
+ bool aspectratiochange(MarkAdAspectRatio &a, MarkAdAspectRatio &b, bool &start);
int framelast;
+ int framebeforelast;
public:
cMarkAdVideo(MarkAdContext *maContext);
~cMarkAdVideo();
- MarkAdPos *Process2ndPass(int FrameNumber, int Frames, bool BeforeAd);
+ MarkAdPos *ProcessOverlap(int FrameNumber, int Frames, bool BeforeAd);
MarkAdMarks *Process(int FrameNumber, int FrameNumberNext);
void Clear();
};