From c77989ee70085be02dca4dc1be362801baa15ff3 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Fri, 17 Dec 2004 14:55:49 +0100 Subject: Added support for AC3 replay over the DVB device --- transfer.c | 101 ++++++++++++++++++++++--------------------------------------- 1 file changed, 37 insertions(+), 64 deletions(-) (limited to 'transfer.c') diff --git a/transfer.c b/transfer.c index d4ccee20..056299b2 100644 --- a/transfer.c +++ b/transfer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: transfer.c 1.18 2004/10/23 13:35:08 kls Exp $ + * $Id: transfer.c 1.19 2004/11/28 11:51:00 kls Exp $ */ #include "transfer.h" @@ -20,8 +20,6 @@ cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2) { ringBuffer = new cRingBufferLinear(TRANSFERBUFSIZE, TS_SIZE * 2, true, "Transfer"); remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2); - canToggleAudioTrack = false; - audioTrack = 0xC0; active = false; } @@ -60,8 +58,41 @@ void cTransfer::Action(void) int PollTimeouts = 0; uchar *p = NULL; int Result = 0; +// XXX Apparently this isn't necessary with the new PES data handling that +// XXX was intorduced in VDR 1.3.18. If you do need this, enable the following +// XXX line and send an email to kls@cadsoft.de. If nobody requires this, it +// XXX will be removed later. kls 2004-12-27 +//#define FW_NEEDS_BUFFER_RESERVE_FOR_AC3 +#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3 + bool Cleared = false; + bool GotBufferReserve = false; +#endif active = true; while (active) { +#ifdef FW_NEEDS_BUFFER_RESERVE_FOR_AC3 +#define HasDolby true + if (HasDolby) { + if (IsAttached() && !Cleared) { + PlayPes(NULL, 0); + Cleared = true; + } + //XXX For dolby we've to fill the buffer because the firmware does + //XXX not decode dolby but use a PCM stream for transport, therefore + //XXX the firmware has not enough buffer for noiseless skipping early + //XXX PCM samples (each dolby frame requires 6144 bytes in PCM and + //XXX audio is mostly to early in comparison to video). + //XXX To resolve this, the remuxer or PlayPes() should synchronize + //XXX audio with the video frames. 2004/09/09 Werner + if (!GotBufferReserve) { + if (ringBuffer->Available() < 3 * MAXFRAMESIZE / 2) { + cCondWait::SleepMs(20); // allow the buffer to collect some reserve + continue; + } + else + GotBufferReserve = true; + } + } +#endif int Count; uchar *b = ringBuffer->Get(Count); if (b) { @@ -80,13 +111,13 @@ void cTransfer::Action(void) if (Count) ringBuffer->Del(Count); } - if (!p && (p = remux->Get(Result)) != NULL) - StripAudioPackets(p, Result, audioTrack); + if (!p) + p = remux->Get(Result); if (p) { cPoller Poller; if (DevicePoll(Poller, 100)) { PollTimeouts = 0; - int w = PlayVideo(p, Result); + int w = PlayPes(p, Result); if (w > 0) { p += w; Result -= w; @@ -112,64 +143,6 @@ void cTransfer::Action(void) active = false; } -void cTransfer::StripAudioPackets(uchar *b, int Length, uchar Except) -{ - for (int i = 0; i < Length - 6; i++) { - if (b[i] == 0x00 && b[i + 1] == 0x00 && b[i + 2] == 0x01) { - uchar c = b[i + 3]; - int l = b[i + 4] * 256 + b[i + 5] + 6; - switch (c) { - case 0xBD: // dolby - if (Except) - PlayAudio(&b[i], l); - // continue with deleting the data - otherwise it disturbs DVB replay - case 0xC0 ... 0xC1: // audio - if (c == 0xC1) - canToggleAudioTrack = true; - if (!Except || c != Except) - memset(&b[i], 0x00, min(l, Length-i)); - break; - case 0xE0 ... 0xEF: // video - break; - default: - //esyslog("ERROR: unexpected packet id %02X", c); - l = 0; - } - if (l) - i += l - 1; // the loop increments, too! - } - /*XXX - else - esyslog("ERROR: broken packet header"); - XXX*/ - } -} - -int cTransfer::NumAudioTracks(void) const -{ - return canToggleAudioTrack ? 2 : 1; -} - -const char **cTransfer::GetAudioTracks(int *CurrentTrack) const -{ - if (NumAudioTracks()) { - if (CurrentTrack) - *CurrentTrack = (audioTrack == 0xC0) ? 0 : 1; - static const char *audioTracks1[] = { "Audio 1", NULL }; - static const char *audioTracks2[] = { "Audio 1", "Audio 2", NULL }; - return NumAudioTracks() > 1 ? audioTracks2 : audioTracks1; - } - return NULL; -} - -void cTransfer::SetAudioTrack(int Index) -{ - if ((audioTrack == 0xC0) != (Index == 0)) { - audioTrack = (Index == 1) ? 0xC1 : 0xC0; - DeviceClear(); - } -} - // --- cTransferControl ------------------------------------------------------ cDevice *cTransferControl::receiverDevice = NULL; -- cgit v1.2.3