From patchwork Sat Feb 2 15:27:56 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Klaus Schmidinger X-Patchwork-Id: 12594 Received: from raven.cadsoft.de ([217.7.101.211]) by www.linuxtv.org with esmtp (Exim 4.63) (envelope-from ) id 1JLKHe-0000i5-IH for vdr@linuxtv.org; Sat, 02 Feb 2008 16:27:58 +0100 Received: from [192.168.100.10] (hawk.cadsoft.de [192.168.100.10]) by raven.cadsoft.de (8.13.3/8.13.3) with ESMTP id m12FRucm027402; Sat, 2 Feb 2008 16:27:56 +0100 Message-ID: <47A48BFC.1080606@cadsoft.de> Date: Sat, 02 Feb 2008 16:27:56 +0100 From: Klaus Schmidinger Organization: CadSoft Computer GmbH User-Agent: Thunderbird 2.0.0.9 (X11/20070801) MIME-Version: 1.0 To: vdr@linuxtv.org X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-2.0 (raven.cadsoft.de [192.168.1.1]); Sat, 02 Feb 2008 16:27:57 +0100 (CET) Subject: [vdr] Transfer-Mode without remux X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.9 Precedence: list Reply-To: VDR Mailing List List-Id: VDR Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 Feb 2008 15:27:58 -0000 Status: O X-Status: X-Keywords: X-UID: 15393 In a crude attempt to run VDR's Transfer-Mode without using a cRemux (and thus avoiding all the extra buffering and processing) I am trying to send the payload of the TS packets directly to the device. The attached patch implements cDevice::PlayTS() and handles video and audio packets with fixed PIDs (just for testing). I do get audio and video (using a FF-DVB card as output device), but there are some distortions. From all the debug output I've made there doesn't seem to be anything wrong - even the TS continuity counters check out (except for the initial one, which is to be expected). Am I missing something obvious here? Maybe somebody on the list can find out what's wrong here - or can argue why this attempt can't work in the first place. If you try the patch, just change the hardcoded PIDs in cDevice::PlayTS() to whatever video and audio PID the channel has you're going to test with. Klaus --- ./device.c 2008/01/27 10:40:46 1.149 +++ ./device.c 2008/02/02 14:58:05 @@ -1387,6 +1387,64 @@ return Length; } +//XXX make generally available? +#define TS_LENGTH 188//XXX +#define ADAPT_FIELD 0x20 +#define CONT_CNT_MASK 0x0F +#define PAY_LOAD 0x10 +#define TS_ERROR 0x80 +inline int TsPid(const uchar *Data) +{ + return (((uint16_t)Data[1] & PID_MASK_HI) << 8) | Data[2]; +} +inline int TsPayloadOffset(const uchar *Data) +{ + return (Data[3] & ADAPT_FIELD) ? Data[4] + 4 : 4; +} +inline int TsContinuityCounter(const uchar *Data) +{ + return Data[3] & CONT_CNT_MASK; +} +//XXX + +int cDevice::PlayTS(const uchar *Data, int Length, bool VideoOnly) +{ + static int ccV = 0, ccA = 0;//XXX + if (Length == TS_LENGTH) { + int PayloadOffset = TsPayloadOffset(Data); + if (PayloadOffset < Length) { + if (Data[1] & TS_ERROR) + fprintf(stderr, "E"); + if (!(Data[3] & (ADAPT_FIELD | PAY_LOAD))) + fprintf(stderr, "D"); + if (!(Data[3] & PAY_LOAD)) { + fprintf(stderr, "0"); + return 0; + } + //XXX more checks? + int Pid = TsPid(Data); + if (Pid == 3210) { + if ((Data[3] ^ (ccV + 1)) & CONT_CNT_MASK) + fprintf(stderr, "V %d %d\n", ccV, TsContinuityCounter(Data)); + ccV = TsContinuityCounter(Data); + return PlayVideo(Data + PayloadOffset, Length - PayloadOffset); + } + if (Pid == 3211) { + if ((Data[3] ^ (ccA + 1)) & CONT_CNT_MASK) + fprintf(stderr, "A %d %d\n", ccA, TsContinuityCounter(Data)); + ccA = TsContinuityCounter(Data); + return PlayAudio(Data + PayloadOffset, Length - PayloadOffset, 0); + } + //fprintf(stderr, " P");//XXX + return 0;//XXX + } + else fprintf(stderr, " O");//XXX + } + else fprintf(stderr, " L");//XXX + return -1; +} +//XXX change description of PlayVideo()/PlayAudio()? "no longer an entire PES packet"? + int cDevice::Priority(void) const { int priority = IsPrimaryDevice() ? Setup.PrimaryLimit - 1 : DEFAULTPRIORITY; --- ./device.h 2008/01/27 10:35:18 1.87 +++ ./device.h 2008/02/02 13:10:05 @@ -554,6 +554,8 @@ ///< to a complete packet with data from the next call to PlayPes(). ///< That way any functions called from within PlayPes() will be ///< guaranteed to always receive complete PES packets. + virtual int PlayTS(const uchar *Data, int Length, bool VideoOnly = false); + ///< XXX bool Replaying(void) const; ///< Returns true if we are currently replaying. bool Transferring(void) const; --- ./player.h 2007/10/13 12:18:10 1.20 +++ ./player.h 2008/02/02 13:48:41 @@ -41,6 +41,7 @@ // Sends the given PES Data to the device and returns the number of // bytes that have actually been accepted by the device (or a // negative value in case of an error). + int PlayTS(const uchar *Data, int Length, bool VideoOnly = false) { return device ? device->PlayTS(Data, Length, VideoOnly) : -1; } public: cPlayer(ePlayMode PlayMode = pmAudioVideo); virtual ~cPlayer(); --- ./transfer.c 2007/01/05 10:45:28 1.34 +++ ./transfer.c 2008/02/02 14:16:29 @@ -32,6 +32,7 @@ void cTransfer::Activate(bool On) { + return;//XXX if (On) Start(); else { @@ -42,6 +43,9 @@ void cTransfer::Receive(uchar *Data, int Length) { + int r = PlayTS(Data, Length);//XXX + //fprintf(stderr, " %d", r);//XXX + return; if (cPlayer::IsAttached() && Running()) { int p = ringBuffer->Put(Data, Length); if (p != Length && Running())