diff --git a/src/libav.c b/src/libav.c index 3f5a4e71..1e12d66a 100644 --- a/src/libav.c +++ b/src/libav.c @@ -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; diff --git a/src/muxer/muxer_libav.c b/src/muxer/muxer_libav.c index 70b85774..d2476e62 100644 --- a/src/muxer/muxer_libav.c +++ b/src/muxer/muxer_libav.c @@ -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); diff --git a/src/muxer/tvh/mkmux.c b/src/muxer/tvh/mkmux.c index c3ade157..0c8352cb 100644 --- a/src/muxer/tvh/mkmux.c +++ b/src/muxer/tvh/mkmux.c @@ -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); diff --git a/src/plumbing/transcoding.c b/src/plumbing/transcoding.c index fc190090..874f5308 100644 --- a/src/plumbing/transcoding.c +++ b/src/plumbing/transcoding.c @@ -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); diff --git a/src/tvheadend.h b/src/tvheadend.h index 4bba2ab8..e548341b 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -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,