]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
AAC fixes (ADTS header) in transcoder and libav muxer
authorJaroslav Kysela <perex@perex.cz>
Fri, 17 Oct 2014 15:25:36 +0000 (17:25 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 17 Oct 2014 15:25:59 +0000 (17:25 +0200)
src/libav.c
src/muxer/muxer_libav.c
src/muxer/tvh/mkmux.c
src/plumbing/transcoding.c
src/tvheadend.h

index 3f5a4e7116f8d9c71f5f8ad50bc4bf176498f669..1e12d66affb1d231c48dc7b1e209642fbc450069 100644 (file)
@@ -79,6 +79,7 @@ streaming_component_type2codec_id(streaming_component_type_t type)
   case SCT_EAC3:
     codec_id = AV_CODEC_ID_EAC3;
     break;
+  case SCT_MP4A:
   case SCT_AAC:
     codec_id = AV_CODEC_ID_AAC;
     break;
index 70b8577440dbb2f683e483a211e9b41aa8eefdeb..d2476e62a7e75228ced732c20059565d4aefa452 100644 (file)
@@ -114,6 +114,8 @@ lav_muxer_add_stream(lav_muxer_t *lm,
 #if 0
     c->time_base.num = 1;
     c->time_base.den = c->sample_rate;
+#else
+    c->time_base     = st->time_base;
 #endif
 
     av_dict_set(&st->metadata, "language", ssc->ssc_lang, 0);
@@ -123,10 +125,8 @@ lav_muxer_add_stream(lav_muxer_t *lm,
     c->width      = ssc->ssc_width;
     c->height     = ssc->ssc_height;
 
-#if 0
-    c->time_base.num  = 1;
+    c->time_base.num = 1;
     c->time_base.den = 25;
-#endif
 
     c->sample_aspect_ratio.num = ssc->ssc_aspect_num;
     c->sample_aspect_ratio.den = ssc->ssc_aspect_den;
@@ -396,6 +396,10 @@ lav_muxer_write_pkt(muxer_t *m, streaming_message_type_t smt, void *data)
        tvhlog(LOG_WARNING, "libav",  "Failed to filter bitstream");
        break;
       }
+    } else if (st->codec->codec_id == AV_CODEC_ID_AAC) {
+      /* remove ADTS header */
+      packet.data = pktbuf_ptr(pkt->pkt_payload) + 7;
+      packet.size = pktbuf_len(pkt->pkt_payload) - 7;
     } else {
       packet.data = pktbuf_ptr(pkt->pkt_payload);
       packet.size = pktbuf_len(pkt->pkt_payload);
index c3ade15752605b029198a21bd2b67517418d0b50..0c8352cbe543ce5d5b46f497c1b4933dc43b1822 100644 (file)
@@ -236,6 +236,7 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
   htsbuf_queue_t *q = htsbuf_queue_alloc(0), *t;
   int tracknum = 0;
   uint8_t buf4[4];
+  uint32_t bit_depth = 0;
 
   mkm->tracks = calloc(1, sizeof(mk_track_t) * ss->ss_num_components);
   mkm->ntracks = ss->ss_num_components;
@@ -302,6 +303,7 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
     case SCT_AAC:
       tracktype = 2;
       codec_id = "A_AAC";
+      bit_depth = 16;
       break;
 
     case SCT_VORBIS:
@@ -385,15 +387,13 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
       break;
     }
 
-    if(ssc->ssc_frameduration) {
-      int d = ts_rescale(ssc->ssc_frameduration, 1000000000);
-      ebml_append_uint(t, 0x23e383, d);
-    }
-    
-
     if(SCT_ISVIDEO(ssc->ssc_type)) {
       htsbuf_queue_t *vi = htsbuf_queue_alloc(0);
 
+      if(ssc->ssc_frameduration) {
+        int d = ts_rescale(ssc->ssc_frameduration, 1000000000);
+        ebml_append_uint(t, 0x23e383, d);
+      }
       ebml_append_uint(vi, 0xb0, ssc->ssc_width);
       ebml_append_uint(vi, 0xba, ssc->ssc_height);
 
@@ -416,6 +416,8 @@ mk_build_tracks(mk_mux_t *mkm, const streaming_start_t *ss)
 
       ebml_append_float(au, 0xb5, sri_to_rate(ssc->ssc_sri));
       ebml_append_uint(au, 0x9f, ssc->ssc_channels);
+      if (bit_depth)
+        ebml_append_uint(au, 0x6264, bit_depth);
 
       ebml_append_master(t, 0xe1, au);
     }
@@ -979,7 +981,6 @@ mk_write_frame_i(mk_mux_t *mkm, mk_track_t *t, th_pkt_t *pkt)
     data += 7;
   }
 
-
   ebml_append_id(mkm->cluster, 0xa3 ); // SimpleBlock
   ebml_append_size(mkm->cluster, len + 4);
   ebml_append_size(mkm->cluster, t->tracknum);
index fc190090b5f23ed44c610ba56910d35dbd7a593c..874f53081b191acc67e131a3542088a819aa808e 100644 (file)
@@ -37,6 +37,7 @@
 #include "packet.h"
 #include "transcoding.h"
 #include "libav.h"
+#include "parsers/bitstream.h"
 
 static long transcoder_nrprocessors;
 
@@ -200,6 +201,10 @@ transcoder_get_decoder(transcoder_t *t, streaming_component_type_t ty)
   enum AVCodecID codec_id;
   AVCodec *codec;
 
+  /* the MP4A and AAC packet format is same, reduce to one type */
+  if (ty == SCT_MP4A)
+    ty = SCT_AAC;
+
   codec_id = streaming_component_type2codec_id(ty);
   if (codec_id == AV_CODEC_ID_NONE) {
     tvherror("transcode", "%04X: Unsupported input codec %s",
@@ -313,6 +318,31 @@ transcoder_stream_subtitle(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *p
   avsubtitle_free(&sub);
 }
 
+static void
+create_adts_header(pktbuf_t *pb, int sri, int channels)
+{
+   bitstream_t bs;
+
+   /* 7 bytes of ADTS header */
+   init_wbits(&bs, pktbuf_ptr(pb), 56);
+
+   put_bits(&bs, 0xfff, 12); // Sync marker
+   put_bits(&bs, 0, 1);      // ID 0 = MPEG 4
+   put_bits(&bs, 0, 2);      // Layer
+   put_bits(&bs, 1, 1);      // Protection absent
+   put_bits(&bs, 2, 2);      // AOT
+   put_bits(&bs, sri, 4);
+   put_bits(&bs, 1, 1);      // Private bit
+   put_bits(&bs, channels, 3);
+   put_bits(&bs, 1, 1);      // Original
+   put_bits(&bs, 1, 1);      // Copy
+
+   put_bits(&bs, 1, 1);      // Copyright identification bit
+   put_bits(&bs, 1, 1);      // Copyright identification start
+   put_bits(&bs, pktbuf_len(pb), 13);
+   put_bits(&bs, 0, 11);     // Buffer fullness
+   put_bits(&bs, 0, 2);      // RDB in frame
+}
 
 /**
  *
@@ -690,12 +720,24 @@ transcoder_stream_audio(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
 
     } else if (got_packet_ptr && packet.pts >= 0) {
 
-      n = pkt_alloc(packet.data, packet.size, packet.pts, packet.pts);
+      int extra_size = 0;
+      
+      if (ts->ts_type == SCT_AAC) {
+        /* only if ADTS header is missing, create it */
+        if (packet.size < 2 || packet.data[0] != 0xff || (packet.data[1] & 0xf0) != 0xf0)
+          extra_size = 7;
+      }
+      
+      n = pkt_alloc(NULL, packet.size + extra_size, packet.pts, packet.pts);
+      memcpy(pktbuf_ptr(n->pkt_payload) + extra_size, packet.data, packet.size);
+
       n->pkt_componentindex = ts->ts_index;
       n->pkt_channels       = octx->channels;
       n->pkt_sri            = rate_to_sri(octx->sample_rate);
+      n->pkt_duration       = packet.duration;
 
-      n->pkt_duration = packet.duration;
+      if (extra_size && ts->ts_type == SCT_AAC)
+        create_adts_header(pkt->pkt_payload, n->pkt_sri, octx->channels);
 
       if (octx->extradata_size)
        n->pkt_header = pktbuf_alloc(octx->extradata, octx->extradata_size);
@@ -705,7 +747,6 @@ transcoder_stream_audio(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
       sm = streaming_msg_create_pkt(n);
       streaming_target_deliver2(ts->ts_target, sm);
       pkt_ref_dec(n);
-
     }
 
     av_free_packet(&packet);
index 4bba2ab8151f1f1a0403b230b0283e0a34a03004..e548341b4ad5df30de7dd5d4c69ccd550febad01 100644 (file)
@@ -222,11 +222,11 @@ typedef enum {
   SCT_TELETEXT,
   SCT_DVBSUB,
   SCT_CA,
-  SCT_AAC,
+  SCT_AAC,     /* AAC-LATM in MPEG-TS, ADTS + AAC in packet form */
   SCT_MPEGTS,
   SCT_TEXTSUB,
   SCT_EAC3,
-  SCT_MP4A,
+  SCT_MP4A,    /* ADTS + AAC in MPEG-TS and packet form */
   SCT_VP8,
   SCT_VORBIS,
   SCT_HEVC,