Transfer-Mode without remux

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Media]     [Asterisk]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Big List of Linux Books]     [Fedora Users]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux