From 042057b5652da3b5f6ffb1f9134c36a48588291c Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Fri, 8 Jan 2016 17:03:04 +0100 Subject: [PATCH] libeplayer3: add aac_adtstoasc bitstream filter Add the aac_adtstoasc bitstream filter for AAC streams. In the cases where it is not needed, it does not seem to hurt, and in other cases it fixes audio playback. TODO: improve the handling of the bsfc allocation / deallocation, this should go in a Track() destructor or similar. --- libeplayer3/include/manager.h | 3 +- libeplayer3/input.cpp | 52 +++++++++++++++++++++++++++++++++++ libeplayer3/manager.cpp | 16 +++++++++-- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/libeplayer3/include/manager.h b/libeplayer3/include/manager.h index 364595b..ab1168a 100644 --- a/libeplayer3/include/manager.h +++ b/libeplayer3/include/manager.h @@ -49,8 +49,9 @@ struct Track bool hidden; // not part of currently selected program bool is_static; int ac3flags; + AVBitStreamFilterContext *bsfc; int type, mag, page; // for teletext - Track() : pid(-1), stream(NULL), inactive(false), hidden(false), is_static(false), ac3flags(0) {} + Track() : pid(-1), stream(NULL), inactive(false), hidden(false), is_static(false), ac3flags(0), bsfc(NULL) {} }; struct Program diff --git a/libeplayer3/input.cpp b/libeplayer3/input.cpp index 37b4548..791eb9e 100644 --- a/libeplayer3/input.cpp +++ b/libeplayer3/input.cpp @@ -123,6 +123,8 @@ bool Input::Play() // Oddly, this seems to be necessary for network streaming only ... bool audioSeen = !audioTrack || !player->isHttp; + int reinit_audio = 0; + while (player->isPlaying && !player->abortRequested) { //IF MOVIE IS PAUSED, WAIT @@ -221,6 +223,53 @@ bool Input::Play() restart_audio_resampling = false; player->output.Write(stream, NULL, 0); } + if (_audioTrack->bsfc) { + /* this code is more or less copied from ffmpeg.c */ + AVBitStreamFilterContext *bsfc = _audioTrack->bsfc; + av_packet_split_side_data(&packet); + AVPacket new_pkt = packet; + AVCodecContext *avcc = stream->codec; + + int a = av_bitstream_filter_filter(bsfc, avcc, NULL, + &new_pkt.data, &new_pkt.size, + packet.data, packet.size, + packet.flags & AV_PKT_FLAG_KEY); + if (a == 0 && new_pkt.data != packet.data) { + if (reinit_audio < 2) + reinit_audio++; + uint8_t *t = (uint8_t *)av_malloc(new_pkt.size + FF_INPUT_BUFFER_PADDING_SIZE); + if(t) { + memcpy(t, new_pkt.data, new_pkt.size); + memset(t + new_pkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + new_pkt.data = t; + new_pkt.buf = NULL; + a = 1; + } else { + /* TODO: what happens here? */ + a = AVERROR(ENOMEM); + } + } + if (a > 0) { + packet.side_data = NULL; + packet.side_data_elems = 0; + av_free_packet(&packet); + new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size, + av_buffer_default_free, NULL, 0); + if (! new_pkt.buf) + logprintf("eplayer3:input %d no memory\n", __LINE__); + } else if (a < 0) { + logprintf("eplayer3:input: failed to open bitstream filter\n"); + } + packet = new_pkt; + } + + if (reinit_audio == 1) { /* only run once on start */ + /* we need to reprogram the AAC header in Writer::Init() + * this is a cheap hack to do that */ + logprintf("eplayer3:input: reset audio stream\n"); + player->output.SwitchAudio(NULL); + player->output.SwitchAudio(stream); + } if (!player->isBackWard) { int64_t pts = calcPts(stream, packet.pts); if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0)) @@ -524,6 +573,9 @@ bool Input::UpdateTracks() break; case AV_CODEC_ID_AAC: track.ac3flags = 5; + track.bsfc = av_bitstream_filter_init("aac_adtstoasc"); + logprintf("adding AAC STREAM %d, bsfc: %p (aac_adtstoasc)\n", + track.pid, track.bsfc); break; default: track.ac3flags = 0; diff --git a/libeplayer3/manager.cpp b/libeplayer3/manager.cpp index da39024..e6dbee7 100644 --- a/libeplayer3/manager.cpp +++ b/libeplayer3/manager.cpp @@ -31,8 +31,14 @@ void Manager::addTrack(std::map &tracks, Track &track) Track *t = new Track; *t = track; tracks[track.pid] = t; - } else + } else { + /* this should be handled by Track() itself, instead of special casing here... */ + if ((*it->second).bsfc) { + fprintf(stderr, "eplayer3:%s: closing bsf %p\n", __func__, (*it->second).bsfc); + av_bitstream_filter_close((*it->second).bsfc); + } *it->second = track; + } } void Manager::addVideoTrack(Track &track) @@ -238,8 +244,14 @@ void Manager::clearTracks() { OpenThreads::ScopedLock m_lock(mutex); - for (std::map::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it) + for (std::map::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it) { + /* see comment in addTrack() :-) */ + if (it->second->bsfc) { + fprintf(stderr, "eplayer3:%s: closing bsf %p\n", __func__, it->second->bsfc); + av_bitstream_filter_close(it->second->bsfc); + } delete it->second; + } audioTracks.clear(); for (std::map::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)