summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2008-12-13 14:43:22 +0100
committerKlaus Schmidinger <vdr@tvdr.de>2008-12-13 14:43:22 +0100
commit22feb7bf1cfc0bff0742fd23657de853b63f1890 (patch)
treeb6c7434ae85cdcd507277ea622c2b5d34f0ccc23
parent3c7d1a16aca49c647320c0ee67759007fa06a845 (diff)
downloadvdr-22feb7bf1cfc0bff0742fd23657de853b63f1890.tar.gz
vdr-22feb7bf1cfc0bff0742fd23657de853b63f1890.tar.bz2
Improved handling PES video packets with zero length when converting from TS to PES
-rw-r--r--HISTORY1
-rw-r--r--device.c16
-rw-r--r--dvbdevice.c17
-rw-r--r--remux.c37
-rw-r--r--remux.h8
5 files changed, 58 insertions, 21 deletions
diff --git a/HISTORY b/HISTORY
index f9d96f11..53381647 100644
--- a/HISTORY
+++ b/HISTORY
@@ -5840,3 +5840,4 @@ Video Disk Recorder Revision History
and Edgar Hucek).
- The cDvbTuner::IsTunedTo() function now also checks the symbol rate in case of
DVB-S and DVB-C.
+- Improved handling PES video packets with zero length when converting from TS to PES.
diff --git a/device.c b/device.c
index 06f6864c..7d42a5eb 100644
--- a/device.c
+++ b/device.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@@ -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
// a PES packet when the next TS packet that starts a payload comes in:
if (TsPayloadStart(Data)) {
- if (const uchar *p = tsToPesVideo.GetPes(Length)) {
- int w = PlayVideo(p, Length);
- if (w > 0)
- tsToPesVideo.Reset();
- else
- return w;
- }
+ int l;
+ while (const uchar *p = tsToPesVideo.GetPes(l)) {
+ int w = PlayVideo(p, l);
+ if (w < 0)
+ return w;
+ }
+ tsToPesVideo.Reset();
}
tsToPesVideo.PutTs(Data, Length);
return Length;
diff --git a/dvbdevice.c b/dvbdevice.c
index 18caabd8..e0b05a15 100644
--- a/dvbdevice.c
+++ b/dvbdevice.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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"
@@ -1266,18 +1266,25 @@ bool cDvbDevice::Flush(int TimeoutMs)
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)
{
- 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)
{
- Length = TsGetPayload(&Data);
- return PlayVideo(Data, Length);
+ return cDevice::PlayTsVideo(Data, Length);
}
int cDvbDevice::PlayTsAudio(const uchar *Data, int Length)
diff --git a/remux.c b/remux.c
index 8312a744..19385495 100644
--- a/remux.c
+++ b/remux.c
@@ -11,7 +11,7 @@
* 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.
*
- * $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"
@@ -2578,7 +2578,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
cTsToPes::cTsToPes(void)
{
data = NULL;
- size = length = 0;
+ size = length = offset = 0;
synced = false;
}
@@ -2602,12 +2602,35 @@ void cTsToPes::PutTs(const uchar *Data, int Length)
length += Length;
}
+#define MAXPESLENGTH 0xFFF0
+
const uchar *cTsToPes::GetPes(int &Length)
{
- if (PesLongEnough(length)) {
- Length = PesLength(data);
- if (Length <= length) {
- Length = length; // in case the PES packet has no explicit length, as is the case for video PES
+ if (offset < length && PesLongEnough(length)) {
+ if (!PesHasLength(data)) // this is a video PES packet with undefined length
+ offset = 6; // trigger setting PES length for initial slice
+ 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;
}
}
@@ -2616,7 +2639,7 @@ const uchar *cTsToPes::GetPes(int &Length)
void cTsToPes::Reset(void)
{
- length = 0;
+ length = offset = 0;
}
// --- Some helper functions for debugging -----------------------------------
diff --git a/remux.h b/remux.h
index fe792ebf..f471504f 100644
--- a/remux.h
+++ b/remux.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* 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
@@ -138,6 +138,11 @@ inline bool PesLongEnough(int Length)
return Length >= 6;
}
+inline bool PesHasLength(const uchar *p)
+{
+ return p[4] | p[5];
+}
+
inline int PesLength(const uchar *p)
{
return 6 + p[4] * 256 + p[5];
@@ -241,6 +246,7 @@ private:
uchar *data;
int size;
int length;
+ int offset;
bool synced;
public:
cTsToPes(void);