1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Fixed frame detection when regenerating the index

This commit is contained in:
Klaus Schmidinger 2012-11-06 11:03:06 +01:00
parent f98ae169e1
commit 3ad369d249
2 changed files with 56 additions and 48 deletions

94
remux.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: remux.c 2.68 2012/11/02 14:35:57 kls Exp $ * $Id: remux.c 2.69 2012/11/06 10:59:39 kls Exp $
*/ */
#include "remux.h" #include "remux.h"
@ -991,8 +991,6 @@ cMpeg2Parser::cMpeg2Parser(void)
int cMpeg2Parser::Parse(const uchar *Data, int Length, int Pid) int cMpeg2Parser::Parse(const uchar *Data, int Length, int Pid)
{ {
newFrame = independentFrame = false; newFrame = independentFrame = false;
if (Length < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE)
return 0; // need more data
cTsPayload tsPayload(const_cast<uchar *>(Data), Length, Pid); cTsPayload tsPayload(const_cast<uchar *>(Data), Length, Pid);
if (TsPayloadStart(Data)) { if (TsPayloadStart(Data)) {
tsPayload.SkipPesHeader(); tsPayload.SkipPesHeader();
@ -1000,23 +998,27 @@ int cMpeg2Parser::Parse(const uchar *Data, int Length, int Pid)
if (debug && seenIndependentFrame) if (debug && seenIndependentFrame)
dbgframes("/"); dbgframes("/");
} }
do { for (;;) {
scanner = (scanner << 8) | tsPayload.GetByte(); scanner = (scanner << 8) | tsPayload.GetByte();
if (scanner == 0x00000100) { // Picture Start Code if (scanner == 0x00000100) { // Picture Start Code
newFrame = true; newFrame = true;
tsPayload.GetByte(); tsPayload.GetByte();
uchar FrameType = (tsPayload.GetByte() >> 3) & 0x07; uchar FrameType = (tsPayload.GetByte() >> 3) & 0x07;
independentFrame = FrameType == 1; // I-Frame independentFrame = FrameType == 1; // I-Frame
if (debug) { if (debug) {
seenIndependentFrame |= independentFrame; seenIndependentFrame |= independentFrame;
if (seenIndependentFrame) { if (seenIndependentFrame) {
static const char FrameTypes[] = "?IPBD???"; static const char FrameTypes[] = "?IPBD???";
dbgframes("%c", FrameTypes[FrameType]); dbgframes("%c", FrameTypes[FrameType]);
} }
} }
break; break;
} }
} while (tsPayload.Available() > (MIN_TS_PACKETS_FOR_FRAME_DETECTOR - 1) * TS_SIZE); if (tsPayload.AtPayloadStart() // stop at any new payload start to have the buffer refilled if necessary
|| (tsPayload.Available() < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE // stop if the available data is below the limit...
&& (tsPayload.Available() <= 0 || tsPayload.AtTsStart()))) // ...but only if there is no more data at all, or if we are at a TS boundary
break;
}
return tsPayload.Used(); return tsPayload.Used();
} }
@ -1133,8 +1135,6 @@ int32_t cMpeg4Parser::GetGolombSe(void)
int cMpeg4Parser::Parse(const uchar *Data, int Length, int Pid) int cMpeg4Parser::Parse(const uchar *Data, int Length, int Pid)
{ {
newFrame = independentFrame = false; newFrame = independentFrame = false;
if (Length < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE)
return 0; // need more data
tsPayload.Setup(const_cast<uchar *>(Data), Length, Pid); tsPayload.Setup(const_cast<uchar *>(Data), Length, Pid);
if (TsPayloadStart(Data)) { if (TsPayloadStart(Data)) {
tsPayload.SkipPesHeader(); tsPayload.SkipPesHeader();
@ -1143,28 +1143,32 @@ int cMpeg4Parser::Parse(const uchar *Data, int Length, int Pid)
dbgframes("/"); dbgframes("/");
} }
} }
do { for (;;) {
scanner = (scanner << 8) | GetByte(true); scanner = (scanner << 8) | GetByte(true);
if ((scanner & 0xFFFFFF00) == 0x00000100) { // NAL unit start if ((scanner & 0xFFFFFF00) == 0x00000100) { // NAL unit start
uchar NalUnitType = scanner & 0x1F; uchar NalUnitType = scanner & 0x1F;
switch (NalUnitType) { switch (NalUnitType) {
case nutAccessUnitDelimiter: ParseAccessUnitDelimiter(); case nutAccessUnitDelimiter: ParseAccessUnitDelimiter();
gotAccessUnitDelimiter = true; gotAccessUnitDelimiter = true;
break; break;
case nutSequenceParameterSet: ParseSequenceParameterSet(); case nutSequenceParameterSet: ParseSequenceParameterSet();
gotSequenceParameterSet = true; gotSequenceParameterSet = true;
break; break;
case nutCodedSliceNonIdr: case nutCodedSliceNonIdr:
case nutCodedSliceIdr: if (gotAccessUnitDelimiter && gotSequenceParameterSet) { case nutCodedSliceIdr: if (gotAccessUnitDelimiter && gotSequenceParameterSet) {
ParseSliceHeader(); ParseSliceHeader();
gotAccessUnitDelimiter = false; gotAccessUnitDelimiter = false;
return tsPayload.Used(); return tsPayload.Used();
} }
break; break;
default: ; default: ;
} }
} }
} while (tsPayload.Available() > (MIN_TS_PACKETS_FOR_FRAME_DETECTOR - 1) * TS_SIZE); if (tsPayload.AtPayloadStart() // stop at any new payload start to have the buffer refilled if necessary
|| (tsPayload.Available() < MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE // stop if the available data is below the limit...
&& (tsPayload.Available() <= 0 || tsPayload.AtTsStart()))) // ...but only if there is no more data at all, or if we are at a TS boundary
break;
}
return tsPayload.Used(); return tsPayload.Used();
} }
@ -1324,8 +1328,6 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
int n = parser->Parse(Data, Length, pid); int n = parser->Parse(Data, Length, pid);
if (n > 0) { if (n > 0) {
if (parser->NewFrame()) { if (parser->NewFrame()) {
if (Processed)
return Processed; // flush everything before this new frame
newFrame = true; newFrame = true;
independentFrame = parser->IndependentFrame(); independentFrame = parser->IndependentFrame();
if (synced) { if (synced) {

10
remux.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: remux.h 2.33 2012/11/02 14:33:11 kls Exp $ * $Id: remux.h 2.34 2012/11/06 11:03:06 kls Exp $
*/ */
#ifndef __REMUX_H #ifndef __REMUX_H
@ -158,7 +158,7 @@ private:
uchar *data; uchar *data;
int length; int length;
int pid; int pid;
int index; // points to the next byte to process int index; // points to the next byte to process
public: public:
cTsPayload(void); cTsPayload(void);
cTsPayload(uchar *Data, int Length, int Pid = -1); cTsPayload(uchar *Data, int Length, int Pid = -1);
@ -171,6 +171,12 @@ public:
///< Otherwise the PID of the first TS packet defines which payload will be ///< Otherwise the PID of the first TS packet defines which payload will be
///< delivered. ///< delivered.
///< Any intermediate TS packets with different PIDs will be skipped. ///< Any intermediate TS packets with different PIDs will be skipped.
bool AtTsStart(void) { return index < length && (index % TS_SIZE) == 0; }
///< Returns true if this payload handler is currently pointing to first byte
///< of a TS packet.
bool AtPayloadStart(void) { return AtTsStart() && TsPayloadStart(data + index); }
///< Returns true if this payload handler is currently pointing to the first byte
///< of a TS packet that starts a new payload.
int Available(void) { return length - index; } int Available(void) { return length - index; }
///< Returns the number of raw bytes (including any TS headers) still available ///< Returns the number of raw bytes (including any TS headers) still available
///< in the TS payload handler. ///< in the TS payload handler.