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

Improved handling PES video packets with zero length when converting from TS to PES

This commit is contained in:
Klaus Schmidinger 2008-12-13 14:43:22 +01:00
parent 3c7d1a16ac
commit 22feb7bf1c
5 changed files with 58 additions and 21 deletions

View File

@ -5840,3 +5840,4 @@ Video Disk Recorder Revision History
and Edgar Hucek). and Edgar Hucek).
- The cDvbTuner::IsTunedTo() function now also checks the symbol rate in case of - The cDvbTuner::IsTunedTo() function now also checks the symbol rate in case of
DVB-S and DVB-C. DVB-S and DVB-C.
- Improved handling PES video packets with zero length when converting from TS to PES.

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: device.c 2.3 2008/07/06 13:22:21 kls Exp $ * $Id: device.c 2.4 2008/12/13 14:30:28 kls Exp $
*/ */
#include "device.h" #include "device.h"
@ -1228,13 +1228,13 @@ int cDevice::PlayTsVideo(const uchar *Data, int Length)
// Video PES has no explicit length, so we can only determine the end of // Video PES has no explicit length, so we can only determine the end of
// a PES packet when the next TS packet that starts a payload comes in: // a PES packet when the next TS packet that starts a payload comes in:
if (TsPayloadStart(Data)) { if (TsPayloadStart(Data)) {
if (const uchar *p = tsToPesVideo.GetPes(Length)) { int l;
int w = PlayVideo(p, Length); while (const uchar *p = tsToPesVideo.GetPes(l)) {
if (w > 0) int w = PlayVideo(p, l);
tsToPesVideo.Reset(); if (w < 0)
else return w;
return w; }
} tsToPesVideo.Reset();
} }
tsToPesVideo.PutTs(Data, Length); tsToPesVideo.PutTs(Data, Length);
return Length; return Length;

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: dvbdevice.c 2.5 2008/12/13 12:22:36 kls Exp $ * $Id: dvbdevice.c 2.6 2008/12/13 14:38:07 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
@ -1266,18 +1266,25 @@ bool cDvbDevice::Flush(int TimeoutMs)
int cDvbDevice::PlayVideo(const uchar *Data, int Length) int cDvbDevice::PlayVideo(const uchar *Data, int Length)
{ {
return WriteAllOrNothing(fd_video, Data, Length, 1000, 10); int w;
do {
w = WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
} while (w != Length);
return w;
} }
int cDvbDevice::PlayAudio(const uchar *Data, int Length, uchar Id) int cDvbDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
{ {
return WriteAllOrNothing(fd_audio, Data, Length, 1000, 10); int w;
do {
w = WriteAllOrNothing(fd_audio, Data, Length, 1000, 10);
} while (w != Length);
return w;
} }
int cDvbDevice::PlayTsVideo(const uchar *Data, int Length) int cDvbDevice::PlayTsVideo(const uchar *Data, int Length)
{ {
Length = TsGetPayload(&Data); return cDevice::PlayTsVideo(Data, Length);
return PlayVideo(Data, Length);
} }
int cDvbDevice::PlayTsAudio(const uchar *Data, int Length) int cDvbDevice::PlayTsAudio(const uchar *Data, int Length)

37
remux.c
View File

@ -11,7 +11,7 @@
* The cRepacker family's code was originally written by Reinhard Nissl <rnissl@gmx.de>, * The cRepacker family's code was originally written by Reinhard Nissl <rnissl@gmx.de>,
* and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de. * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de.
* *
* $Id: remux.c 2.1 2008/08/15 14:49:34 kls Exp $ * $Id: remux.c 2.2 2008/12/13 14:30:15 kls Exp $
*/ */
#include "remux.h" #include "remux.h"
@ -2578,7 +2578,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
cTsToPes::cTsToPes(void) cTsToPes::cTsToPes(void)
{ {
data = NULL; data = NULL;
size = length = 0; size = length = offset = 0;
synced = false; synced = false;
} }
@ -2602,12 +2602,35 @@ void cTsToPes::PutTs(const uchar *Data, int Length)
length += Length; length += Length;
} }
#define MAXPESLENGTH 0xFFF0
const uchar *cTsToPes::GetPes(int &Length) const uchar *cTsToPes::GetPes(int &Length)
{ {
if (PesLongEnough(length)) { if (offset < length && PesLongEnough(length)) {
Length = PesLength(data); if (!PesHasLength(data)) // this is a video PES packet with undefined length
if (Length <= length) { offset = 6; // trigger setting PES length for initial slice
Length = length; // in case the PES packet has no explicit length, as is the case for video PES if (offset) {
uchar *p = data + offset - 6;
if (p != data) {
p -= 3;
memmove(p, data, 4);
}
int l = min(length - offset, MAXPESLENGTH);
offset += l;
if (p != data) {
l += 3;
p[6] = 0x80;
p[7] = 0x00;
p[8] = 0x00;
}
p[4] = l / 256;
p[5] = l & 0xFF;
Length = l + 6;
return p;
}
else {
Length = PesLength(data);
offset = Length; // to make sure we break out in case of garbage data
return data; return data;
} }
} }
@ -2616,7 +2639,7 @@ const uchar *cTsToPes::GetPes(int &Length)
void cTsToPes::Reset(void) void cTsToPes::Reset(void)
{ {
length = 0; length = offset = 0;
} }
// --- Some helper functions for debugging ----------------------------------- // --- Some helper functions for debugging -----------------------------------

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.2 2008/09/06 14:48:28 kls Exp $ * $Id: remux.h 2.3 2008/12/13 13:55:07 kls Exp $
*/ */
#ifndef __REMUX_H #ifndef __REMUX_H
@ -138,6 +138,11 @@ inline bool PesLongEnough(int Length)
return Length >= 6; return Length >= 6;
} }
inline bool PesHasLength(const uchar *p)
{
return p[4] | p[5];
}
inline int PesLength(const uchar *p) inline int PesLength(const uchar *p)
{ {
return 6 + p[4] * 256 + p[5]; return 6 + p[4] * 256 + p[5];
@ -241,6 +246,7 @@ private:
uchar *data; uchar *data;
int size; int size;
int length; int length;
int offset;
bool synced; bool synced;
public: public:
cTsToPes(void); cTsToPes(void);