Mailing List archive

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

[vdr] Re: How to use 5.1 with VDR?



On 18 Jan 2003 s.huelswitt@gmx.de (Stefan Huelswitt) wrote:

> My problem with the one strange recording is related to the
> substreamtype detection (the old code doesn't had such thing). If
> I hardcode the type to 0x8 the recording is played fine. May be
> channels away from Pro7 use other encoding. I'll have to dig into
> this.

OK, I got some results on this ...

Pakets from Pro7 start with (as assumed):
00 00 01 bd 07 08 81 80 05 23 f9 ff 2a 61 0b 77 fb ae 1e 40 e1 dc 
00 00 01 bd 07 08 81 80 05 23 f9 ff 40 e1 0b 77 57 25 1e 40 e1 dc 
00 00 01 bd 07 08 81 80 05 23 f9 ff 57 61 0b 77 64 06 1e 40 e1 dc 
00 00 01 bd 07 08 81 80 05 23 f9 ff 6d e1 0b 77 ea 30 1e 40 e1 dc 

While the one other recording:

00 00 01 bd 07 fa 87 80 05 2f 7f 1b 02 33 0b 77 1a 35 1e 40 e1 dc 
00 00 01 bd 07 fa 80 00 00 99 fa 57 4f 9c d5 af 5d 
00 00 01 bd 07 fa 80 00 00 7a 93 37 89 95 4c 21 3c 
00 00 01 bd 07 fa 80 00 00 84 bb 58 d7 51 88 85 f8 
00 00 01 bd 03 2c 80 00 00 22 a4 a4 e6 91 55 50 43 
00 00 01 bd 07 fa 87 80 05 2f 7f 1b 72 b3 0b 77 f2 9d 1e 40 e1 dc 
00 00 01 bd 07 fa 80 00 00 4d 53 a6 b1 a9 a9 7c fd 
00 00 01 bd 07 fa 80 00 00 7a ee eb ac 1f 00 20 08 
00 00 01 bd 07 fa 80 00 00 29 fd b8 38 58 3e 00 00 
00 00 01 bd 03 2c 80 00 00 d5 bb b6 6b 7a 4d b6 73 

As you can see, in the second case not every PES pakets has the
begining of an AC3 paket. The AC3 pakets cross the PES paket
boundaries.
So we have to make some more effort to detect the substream type.

Here my patch (against Jan's second patch. I guess we need version
numbering here) :

--- multichannelaudio.c	2003-01-18 19:31:04.000000000 +0100
+++ /usr/local/source/VDR/vdr-1.1.x-current/multichannelaudio.c	2003-01-18 19:32:56.000000000 +0100
@@ -9,6 +9,7 @@
 //#define DEBUG(x...) fprintf(stderr, x );
 #endif
 
+//#define DEBUG_BUFF
 
 #ifndef uchar
 typedef unsigned char uchar;
@@ -84,7 +85,8 @@
 void cAudioEncapsulator::MakeFrame(const uchar *ac3data, int size, uint8_t PTSflags, const uint8_t *PTSdata)
 {
 
-#define MAXSIZE 1024
+#define MAXSIZE 1536 //1024 // don't create more pakets than necessary
+                            // 1536=6144/4
 
   int offset = 0;
   while (size > 0) {
@@ -181,6 +183,9 @@
 
   //do we enter with an empty buffer
   bool sendPTS = (bufptr - buf) < 40;
+#ifdef DEBUG_BUFF
+  printf("enter: c=%d t=%d ",bufptr-buf,end-start);
+#endif
 
   for (;;) {
 
@@ -206,11 +211,17 @@
               }
 
            bufpos = buf + length;
+#ifdef DEBUG_BUFF
+           printf("l=%d ",length);
+#endif
            }
 
         else {
 
            SendIEC60958(buf, bufpos - buf, sendPTS ? PTSflags : 0, PTSdata);
+#ifdef DEBUG_BUFF
+           printf("s=%d ",bufpos-buf);
+#endif
 
            sendPTS = false;
            bufptr = buf;
@@ -218,6 +229,9 @@
            }
         }
      }
+#ifdef DEBUG_BUFF
+   printf("rest=%d\n",bufptr-buf);
+#endif
 }
 
 
@@ -309,6 +323,8 @@
      burst[7] = (length * 8) & 0xFF;                      // Pd2
 
      memcpy(burst + 8, buf, length);
+     // is there any reason to send 6144 bytes every time, even if the
+     // normal ac3 paket size is only 1792 bytes???
      memset(burst + 8 + length, 0, 6144 - 8 - length);
      MakeFrame(burst, 6144, PTSflags, PTSdata);
      }
@@ -475,19 +491,46 @@
   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; // total length of PES unit
+        uchar *bi=&b[i];
+        int l = bi[4] * 256 + bi[5] + 6; // total length of PES unit
 
-        switch (c) {
+        switch (bi[3]) {
         case 0xBD:    //private stream 1
         case 0xBF:    //private stream 2 ???
         {
 
+           const int ptsdata = 9;            // start of PTSdata
+           int ptslen    = bi[ptsdata - 1];  // length of PTSdata
+           int headerlen = ptsdata + ptslen; // total length of PES header
+           int offset    = 0;
+
            // check substream type
-           int header = b[i + 8] + 9;
-           int offset = 0;
+           uchar subStreamType = bi[headerlen] & 0xF8;
 
-           uchar subStreamType = b[i + header] & 0xF8;
+           // The simple assumption that the start of the PES payload is also
+           // the start of an audio paket is not true for all broadcasts.
+           // Audio pakets may very well cross PES paket boundaries.
+           // To detect the correct substream type, we have to wait for a PES
+           // paket which actualy has the begining of an audio paket.
+           // The trick is based on actual stream data and may fail on other
+           // broadcasts. Currently it seems that "continuation" pakets doesn't
+           // have PTS data.
+           if(!(bi[6]&1) && !ptslen) { 
+             // If we already have a encapsulator, we continue with him,
+             // if not, we have to wait until the next full paket to identify
+             // the substreamtype
+             if(encapsulator) subStreamType=encapsulator->StreamType();
+             else subStreamType=0xFF;
+             }
+
+#ifdef DEBUG_BUFF
+           //printf("header=%d ptsdata=%d ptslen=%d type=%x\n",headerlen,ptsdata,ptslen,subStreamType);
+           int n=headerlen+8;
+           for(int j=0 ; j<n ; j+=24) {
+             for(int k=0 ; k<24 && j+k<n ; k++) printf("%02x ",bi[j+k]);
+             printf("\n");
+             }
+#endif
 
            switch (subStreamType) {
            case aDTS:
@@ -524,22 +567,17 @@
                     }
                  }
 
-              // extract if PTS info
-              uchar PTSflags = (subStreamType == 0x8) ? 2 : b[i + 7] >> 6;  // For PES we use fixed flags ??
-              const uchar *PTSdata = b + i + 9;
-              int PTSlength = b[i + 8];
-
               //skip to raw AC3 data
-              offset += PTSlength + 9;
+              offset += headerlen;
               int n = min(l - offset, length - i);
 
-              encapsulator->Decode(b + offset + i, b + offset + i + n, PTSflags, PTSdata);
-
+              encapsulator->Decode(bi + offset, bi + offset + n, bi[ptsdata-2] >> 6, bi + ptsdata);
+              }
+              // fall through
+           case 0xFF: // dummy to skip paket
               // Cancel this stream
-              memset(b + i, 0, l);
-
+              memset(bi, 0, min(l,length-i)); // check for buffer boundary
               break;
-              }
            case aLPCM: // leave this untouched
               break;
            default:


-- 
Stefan Huelswitt
huels@iname.com  | http://home.pages.de/~nathan


-- 
Info:
To unsubscribe send a mail to listar@linuxtv.org with "unsubscribe vdr" as subject.



Home | Main Index | Thread Index