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())
_______________________________________________ vdr mailing list vdr@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr