Transfer-Mode without remux

Message ID 47A48BFC.1080606@cadsoft.de
State New
Headers

Commit Message

Klaus Schmidinger Feb. 2, 2008, 3:27 p.m. UTC
  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
  

Comments

Klaus Schmidinger Feb. 2, 2008, 3:40 p.m. UTC | #1
On 02/02/08 16:27, Klaus Schmidinger wrote:
> 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.

Nevermind, I just found it myself: it must be +5 instead of +4 in

inline int TsPayloadOffset(const uchar *Data)
{
  return (Data[3] & ADAPT_FIELD) ? Data[4] + 5 : 4;
}

Now it works - and Transfer-Mode never switched as fast as this :-)

Klaus
  
Reinhard Nissl Feb. 2, 2008, 3:59 p.m. UTC | #2
Hi,

Klaus Schmidinger schrieb:

> Now it works - and Transfer-Mode never switched as fast as this :-)

Have you never tried my syncearly patch?

Bye.
  
Klaus Schmidinger Feb. 2, 2008, 4:14 p.m. UTC | #3
On 02/02/08 16:59, Reinhard Nissl wrote:
> Hi,
> 
> Klaus Schmidinger schrieb:
> 
>> Now it works - and Transfer-Mode never switched as fast as this :-)
> 
> Have you never tried my syncearly patch?

Sorry, but I never found the time to try it.

By sending the TS payload data directly to the device, audio appears almost
instantaneously - which I believe is what the syncearly patch does, too,
right?

Plus it saves two ringbuffers (one in cTransfer and one in cRemux)
and one extra thread - sounds like some simplification to me ;-)

Of course I'll need to see how this behaves in every day live, and all
the audio track handling needs to be adjusted accordingly. But for the
moment it looks good to me.

Klaus
  
VDRU VDRU Feb. 2, 2008, 5:01 p.m. UTC | #4
On Feb 2, 2008 8:14 AM, Klaus Schmidinger <Klaus.Schmidinger@cadsoft.de> wrote:
> On 02/02/08 16:59, Reinhard Nissl wrote:
> > Have you never tried my syncearly patch?
>
> Sorry, but I never found the time to try it.
>
> By sending the TS payload data directly to the device, audio appears almost
> instantaneously - which I believe is what the syncearly patch does, too,
> right?

Maybe you should make some time to try his patches so you won't have
to spend time creating code that already exists. ;)
  
Klaus Schmidinger Feb. 2, 2008, 5:03 p.m. UTC | #5
On 02/02/08 18:01, VDR User wrote:
> On Feb 2, 2008 8:14 AM, Klaus Schmidinger <Klaus.Schmidinger@cadsoft.de> wrote:
>> On 02/02/08 16:59, Reinhard Nissl wrote:
>>> Have you never tried my syncearly patch?
>> Sorry, but I never found the time to try it.
>>
>> By sending the TS payload data directly to the device, audio appears almost
>> instantaneously - which I believe is what the syncearly patch does, too,
>> right?
> 
> Maybe you should make some time to try his patches so you won't have
> to spend time creating code that already exists. ;)

Well, I didn't write code that already existed - I eliminated
unnecessary code ;-)

Klaus
  
Friedhelm Büscher Feb. 10, 2008, 5:39 p.m. UTC | #6
Klaus Schmidinger schrieb:
> On 02/02/08 16:27, Klaus Schmidinger wrote:
>> 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).
>>
[ .. ]
> 
> Nevermind, I just found it myself: it must be +5 instead of +4 in
> 
> inline int TsPayloadOffset(const uchar *Data)
> {
>   return (Data[3] & ADAPT_FIELD) ? Data[4] + 5 : 4;
> }
> 
> Now it works - and Transfer-Mode never switched as fast as this :-)


I don't know what causes this issue, but with this patch enabled, VDR 
refuses to play radio-channel (audio) with the radio-plugin (with RDS 
enabled). When i disable the radio-plugin, audio works; when i remove 
the patch, audio works with the plugin enabled.

-> i removed this patch.

regards,
Friedhelm.
  
Klaus Schmidinger Feb. 10, 2008, 9:53 p.m. UTC | #7
On 02/10/08 18:39, Friedhelm Büscher wrote:
> Klaus Schmidinger schrieb:
>> On 02/02/08 16:27, Klaus Schmidinger wrote:
>>> 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).
>>>
> [ .. ]
>> Nevermind, I just found it myself: it must be +5 instead of +4 in
>>
>> inline int TsPayloadOffset(const uchar *Data)
>> {
>>   return (Data[3] & ADAPT_FIELD) ? Data[4] + 5 : 4;
>> }
>>
>> Now it works - and Transfer-Mode never switched as fast as this :-)
> 
> 
> I don't know what causes this issue, but with this patch enabled, VDR 
> refuses to play radio-channel (audio) with the radio-plugin (with RDS 
> enabled). When i disable the radio-plugin, audio works; when i remove 
> the patch, audio works with the plugin enabled.
> 
> -> i removed this patch.

I never suggested that anybody should actually use this patch.
It was just a first test regarding switching from PES to TS.

Klaus
  

Patch

--- ./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())