]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
parser: add frame parser for all mpeg audio layers (123)
authorJaroslav Kysela <perex@perex.cz>
Tue, 20 Oct 2015 08:42:03 +0000 (10:42 +0200)
committerJaroslav Kysela <perex@perex.cz>
Tue, 20 Oct 2015 08:42:03 +0000 (10:42 +0200)
src/muxer/muxer_mkv.c
src/parsers/parsers.c

index 5d11f15c35c63a6df31c3b597af6d3437b7ff7fd..906b00b1bba06061f37fd34ccc15dcd629a8c4de 100644 (file)
@@ -287,7 +287,7 @@ mk_build_tracks(mk_muxer_t *mk, streaming_start_t *ss)
 
     case SCT_MPEG2AUDIO:
       tracktype = 2;
-      codec_id = "A_MPEG/L2";
+      codec_id = "A_MPEG/L3";
       break;
 
     case SCT_AC3:
index 5a4330bb5aa0c7e84c7b81d34cd89608ad59ccac..aa5c60498b32a771a8d6b0e9651f84a15f0d0b4d 100644 (file)
@@ -99,7 +99,7 @@ static void parse_teletext(service_t *t, elementary_stream_t *st,
 static int parse_mpa(service_t *t, elementary_stream_t *st, size_t len,
                      uint32_t next_startcode, int sc_offset);
 
-static int parse_mpa2(service_t *t, elementary_stream_t *st);
+static int parse_mpa123(service_t *t, elementary_stream_t *st);
 
 static int parse_ac3(service_t *t, elementary_stream_t *st, size_t len,
                      uint32_t next_startcode, int sc_offset);
@@ -444,6 +444,8 @@ depacketize(service_t *t, elementary_stream_t *st, size_t len,
 
   st->es_buf_a.sb_err = st->es_buf.sb_err;
 
+  tvhtrace("parser", "depacketize add %zd", len);
+  tvhlog_hexdump("parser", buf, len);
   sbuf_append(&st->es_buf_a, buf, len);
   return PARSER_APPEND;
 }
@@ -543,64 +545,93 @@ static void parse_mp4a_data(service_t *t, elementary_stream_t *st,
   }
 }
 
-const static int mpa_br[16] = {
-    0,  32,  48,  56,
-   64,  80,  96, 112, 
-  128, 160, 192, 224,
-  256, 320, 384, 0
+const static int mpa_br[2][3][16] = {
+{
+  {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0},
+  {0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384, 0},
+  {0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 0},
+},
+{
+  {0, 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, 0},
+  {0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0},
+  {0,  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0},
+}
 };
 
 const static int mpa_sr[4]  = {44100, 48000, 32000, 0};
 const static int mpa_sri[4] = {4,     3,     5,     0};
 
-static int
-mpa_valid_frame(const uint8_t *buf)
+static inline int
+mpa_valid_frame(uint32_t h)
 {
-  return buf[0] == 0xff && (buf[1] & 0xfe) == 0xfc;
+  if ((h & 0xffe00000) != 0xffe00000) return 0; /* start bits */
+  if ((h & (3<<17)) == 0) return 0;             /* unknown MPEG audio layer */
+  if ((h & (15<<12)) == (15<<12)) return 0;     /* invalid bitrate */
+  if ((h & (3<<10)) == (3<<10)) return 0;             /* invalid frequency */
+  return 1;
 }
 
-
 /**
  *
  */
 static int
-parse_mpa2(service_t *t, elementary_stream_t *st)
+parse_mpa123(service_t *t, elementary_stream_t *st)
 {
-  int i, len;
+  int i, len, layer, lsf, mpeg25, br, sr, pad, fsize, channels, duration;
+  int64_t dts;
+  uint32_t h;
   const uint8_t *buf;
 
  again:
   buf = st->es_buf_a.sb_data;
   len = st->es_buf_a.sb_ptr;
 
-  for(i = 0; i < len - 4; i++) {
-    if(mpa_valid_frame(buf + i)) {
-      int br = mpa_br[ buf[i+2] >> 4     ];
-      int sr = mpa_sr[(buf[i+2] >> 2) & 3];
-      int pad =       (buf[i+2] >> 1) & 1;
+  for (i = 0; i < len - 4; i++) {
+    if (!mpa_valid_frame(h = RB32(buf + i))) continue;
 
-      if(br && sr) {
-        int fsize = 144000 * br / sr + pad;
-        int duration = 90000 * 1152 / sr;
-        int64_t dts = st->es_curdts;
-        int channels = (buf[i + 3] & 0xc0) == 0xc0 ? 1 : 2;
-        if(dts == PTS_UNSET)
-          dts = st->es_nextdts;
+    layer = 4 - ((h >> 17) & 3);
+    lsf = mpeg25 = 1;
+    pad = (h >> 9) & 1;
+    if (h & (1<<20)) {
+      lsf = ((h >> 19) & 1) ^ 1;
+      mpeg25 = 0;
+    }
+    sr = mpa_sr[(h >> 10) & 3] >> (lsf + mpeg25);
+    br = (h >> 12) & 0xf;
 
-        if(dts != PTS_UNSET &&
-           len >= i + fsize + 4 &&
-           mpa_valid_frame(buf + i + fsize)) {
+    if (br == 0 || sr == 0) continue;
 
-          makeapkt(t, st, buf + i, fsize, dts, duration,
-                   channels, mpa_sri[(buf[i+2] >> 2) & 3],
-                   st->es_buf_a.sb_err);
-          st->es_buf_a.sb_err = 0;
-          sbuf_cut(&st->es_buf_a, i + fsize);
-          goto again;
-        }
-      }
+    br = mpa_br[lsf][layer - 1][br];
+    if (br == 0) continue;
+
+    switch (layer) {
+    case 1:  fsize = (((br * 12000) / sr) + pad) * 4; break;
+    case 2:  fsize = ((br * 144000) / sr) + pad; break;
+    case 3:  fsize = ((br * 144000) / (sr << lsf)) + pad; break;
+    default: fsize = 0;
+    }
+
+    duration = 90000 * 1152 / sr;
+    channels = ((h >> 6) & 3) == 3 ? 1 : 2;
+    dts = st->es_curdts;
+    if (dts == PTS_UNSET) {
+      dts = st->es_nextdts;
+      if(dts == PTS_UNSET) continue;
+    }
+
+    if(len < i + fsize + 4) continue;
+
+    h = RB32(buf + i + fsize);
+    if(mpa_valid_frame(h)) {
+      makeapkt(t, st, buf + i, fsize, dts, duration,
+               channels, mpa_sri[(buf[i+2] >> 2) & 3],
+               st->es_buf_a.sb_err);
+      st->es_buf_a.sb_err = 0;
+      sbuf_cut(&st->es_buf_a, i + fsize);
+      goto again;
     }
   }
+
   return PARSER_RESET;
 }
 
@@ -615,7 +646,7 @@ parse_mpa(service_t *t, elementary_stream_t *st, size_t ilen,
   
   if((r = depacketize(t, st, ilen, next_startcode, sc_offset)) != PARSER_APPEND)
     return r;
-  return parse_mpa2(t, st);
+  return parse_mpa123(t, st);
 }