diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 932d0e57..21b20dc4 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -910,6 +910,7 @@ Reinhard Nissl for reporting a race condition in starting a thread for implementing cDolbyRepacker for better handling of Dolby Digital PES packets for extending some buffer sizes to allow handling HDTV streams + for adding substream handling to cDolbyRepacker Richard Robson for reporting freezing replay if a timer starts while in Transfer Mode from the @@ -1112,6 +1113,7 @@ Marco Schl for some improvements to cPoller for implementing displaying mandatory subtitles in the SPU decoder for pointing out a problem with canceling the LIRC thread + for a patch that implements substream handling into cDevice::PlayPesPacket() Jürgen Schmitz for reporting a bug in displaying the current channel when switching via the SVDRP diff --git a/HISTORY b/HISTORY index 199c1508..dbcb20dc 100644 --- a/HISTORY +++ b/HISTORY @@ -3288,7 +3288,7 @@ Video Disk Recorder Revision History - Thanks to Werner Fink, Reinhard Nissl, Sascha Volkenandt and Bjørnar Nilsen for their support in testing and fine tuning this version. -2005-01-22: Version 1.3.19 +2005-01-23: Version 1.3.19 - Making sure at least the default skin is available at program start in case a plugin needs to issue an error message (thanks to Achim Tuffentshammer for @@ -3326,3 +3326,7 @@ Video Disk Recorder Revision History - Falling back to 'stereo' when switching channels in case the user had switched to 'left' or 'right' (suggested by Rolf Groppe). - Completed the Danish OSD texts (thanks to Mogens Elneff). +- Recording and Transfer Mode can now handle up to 8 Dolby Digital tracks (thanks + to Marco Schlüßler for a patch that implements substream handling into + cDevice::PlayPesPacket(), and Reinhard Nissl for adding substream handling to + cDolbyRepacker). diff --git a/device.c b/device.c index 27b82629..c1dc7aba 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 1.76 2005/01/16 16:04:56 kls Exp $ + * $Id: device.c 1.77 2005/01/23 14:10:15 kls Exp $ */ #include "device.h" @@ -660,8 +660,10 @@ void cDevice::ClrAvailableTracks(bool DescriptionsOnly) for (int i = ttNone; i < ttMaxTrackTypes; i++) *availableTracks[i].description = 0; } - else + else { memset(availableTracks, 0, sizeof(availableTracks)); + pre_1_3_19_PrivateStream = false; + } } bool cDevice::SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language, const char *Description, uint32_t Flags) @@ -837,15 +839,42 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) if (!VideoOnly && c == availableTracks[currentAudioTrack].id) w = PlayAudio(Start, d); break; - case 0xBD: // dolby - if (Setup.UseDolbyDigital) { - SetAvailableTrack(ttDolby, 0, c); - if (!VideoOnly && c == availableTracks[currentAudioTrack].id) { - w = PlayAudio(Start, d); - if (FirstLoop) - Audios.PlayAudio(Data, Length); - } + case 0xBD: { // private stream 1 + int PayloadOffset = Data[8] + 9; + uchar SubStreamId = Data[PayloadOffset]; + uchar SubStreamType = SubStreamId & 0xE0; + uchar SubStreamIndex = SubStreamId & 0x1F; + + // Compatibility mode for old VDR recordings, where 0xBD was only AC3: + //TODO apparently this doesn't work for old ORF Dolby Digital recordings + if (!pre_1_3_19_PrivateStream && (Data[6] & 4) && Data[PayloadOffset] == 0x0B && Data[PayloadOffset + 1] == 0x77) + pre_1_3_19_PrivateStream = true; + if (pre_1_3_19_PrivateStream) { + SubStreamId = c; + SubStreamType = 0x80; + SubStreamIndex = 0; } + + switch (SubStreamType) { + case 0x20: // SPU + break; + case 0x80: // AC3 & DTS + if (Setup.UseDolbyDigital) { + SetAvailableTrack(ttDolby, SubStreamIndex, SubStreamId); + if (!VideoOnly && SubStreamId == availableTracks[currentAudioTrack].id) { + w = PlayAudio(Start, d); + if (FirstLoop && !(SubStreamId & 0x80)) // no DTS + Audios.PlayAudio(Data, Length); + } + } + break; + case 0xA0: // LPCM + SetAvailableTrack(ttAudio, SubStreamIndex, SubStreamId); + if (!VideoOnly && SubStreamId == availableTracks[currentAudioTrack].id) + w = PlayAudio(Start, d); + break; + } + } break; default: ;//esyslog("ERROR: unexpected packet id %02X", c); diff --git a/device.h b/device.h index f04ba509..9ab15c9f 100644 --- a/device.h +++ b/device.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 1.52 2005/01/16 14:26:16 kls Exp $ + * $Id: device.h 1.53 2005/01/22 14:58:07 kls Exp $ */ #ifndef __DEVICE_H @@ -315,6 +315,7 @@ public: private: tTrackId availableTracks[ttMaxTrackTypes]; eTrackType currentAudioTrack; + bool pre_1_3_19_PrivateStream; protected: virtual void SetAudioTrackDevice(eTrackType Type); ///< Sets the current audio track to the given value. diff --git a/remux.c b/remux.c index 307f7ab9..06fb13bd 100644 --- a/remux.c +++ b/remux.c @@ -11,7 +11,7 @@ * The cDolbyRepacker code was originally written by Reinhard Nissl , * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de. * - * $Id: remux.c 1.26 2005/01/16 15:22:16 kls Exp $ + * $Id: remux.c 1.27 2005/01/23 12:56:39 kls Exp $ */ #include "remux.h" @@ -23,10 +23,14 @@ // --- cRepacker ------------------------------------------------------------- class cRepacker { +protected: + uint8_t subStreamId; public: + cRepacker(void) { subStreamId = 0; } virtual ~cRepacker() {} virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) = 0; virtual int BreakAt(const uchar *Data, int Count) = 0; + void SetSubStreamId(uint8_t SubStreamId) { subStreamId = SubStreamId; } }; // --- cDolbyRepacker -------------------------------------------------------- @@ -36,7 +40,7 @@ private: static int frameSizes[]; uchar fragmentData[6 + 65535]; int fragmentLen; - uchar pesHeader[6 + 3 + 255 + 4]; + uchar pesHeader[6 + 3 + 255 + 4 + 4]; int pesHeaderLen; uchar chk1; uchar chk2; @@ -211,6 +215,12 @@ int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int continue; } // adjust PES packet length and output packet + if (subStreamId) { + pesHeader[pesHeaderLen++] = subStreamId; + pesHeader[pesHeaderLen++] = 0x00; + pesHeader[pesHeaderLen++] = 0x00; + pesHeader[pesHeaderLen++] = 0x00; + } int packetLen = pesHeaderLen - 6 + ac3todo; pesHeader[4] = packetLen >> 8; pesHeader[5] = packetLen & 0xFF; @@ -343,6 +353,7 @@ private: uint8_t *buf; uint8_t cid; uint8_t audioCid; + uint8_t subStreamId; int plength; uint8_t plen[2]; uint8_t flag1; @@ -364,7 +375,7 @@ private: void write_ipack(const uint8_t *Data, int Count); void instant_repack(const uint8_t *Buf, int Count); public: - cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid = 0x00, cRepacker *Repacker = NULL); + cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid = 0x00, uint8_t SubStreamId = 0x00, cRepacker *Repacker = NULL); ~cTS2PES(); int Pid(void) { return pid; } void ts_to_pes(const uint8_t *Buf); // don't need count (=188) @@ -373,13 +384,16 @@ public: uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 }; -cTS2PES::cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid, cRepacker *Repacker) +cTS2PES::cTS2PES(int Pid, cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid, uint8_t SubStreamId, cRepacker *Repacker) { pid = Pid; resultBuffer = ResultBuffer; size = Size; audioCid = AudioCid; + subStreamId = SubStreamId; repacker = Repacker; + if (repacker) + repacker->SetSubStreamId(subStreamId); tsErrors = 0; ccErrors = 0; @@ -724,16 +738,14 @@ cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, b } if (DPids) { int n = 0; - while (*DPids && numTracks < MAXTRACKS && n < MAXDPIDS) { - ts2pes[numTracks++] = new cTS2PES(*DPids++, resultBuffer, IPACKS, 0x00, new cDolbyRepacker); //XXX substream id(n++)??? - break; //XXX until we can handle substream ids we can only handle a single Dolby track - } + while (*DPids && numTracks < MAXTRACKS && n < MAXDPIDS) + ts2pes[numTracks++] = new cTS2PES(*DPids++, resultBuffer, IPACKS, 0x00, 0x80 + n++, new cDolbyRepacker); } /* future... if (SPids) { int n = 0; while (*SPids && numTracks < MAXTRACKS && n < MAXSPIDS) - ts2pes[numTracks++] = new cTS2PES(*SPids++, resultBuffer, IPACKS); //XXX substream id(n++)??? + ts2pes[numTracks++] = new cTS2PES(*SPids++, resultBuffer, IPACKS, 0x00, 0x28 + n++); } */ } diff --git a/vdr.5 b/vdr.5 index 1bc7db4b..db33a157 100644 --- a/vdr.5 +++ b/vdr.5 @@ -8,7 +8,7 @@ .\" License as specified in the file COPYING that comes with the .\" vdr distribution. .\" -.\" $Id: vdr.5 1.33 2005/01/16 13:45:57 kls Exp $ +.\" $Id: vdr.5 1.34 2005/01/23 13:31:40 kls Exp $ .\" .TH vdr 5 "19 Dec 2004" "1.3.18" "Video Disk Recorder Files" .SH NAME @@ -561,7 +561,8 @@ a recording is split into several files. The contents of these files is \fBPacketized Elementary Stream\fR (PES) and contains ES packets with ids 0xE0...0xEF for video (only one of these may actually occur in a file), 0xC0...0xDF for audio 1...32 (up to 32 audio tracks may occur). -Dolby Digital data is stored in packets with ids 0xBD. +Dolby Digital data is stored in packets with ids 0xBD ("Private Stream 1") +and substream ids 0x80...0x87. .SS INDEX The file \fIindex.vdr\fR (if present in a recording directory) contains the (binary) index data into each of the the recording files