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.
This commit is contained in:
Stefan Seyfried
2016-01-08 17:03:04 +01:00
parent 18db6acbc2
commit 042057b565
3 changed files with 68 additions and 3 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -31,8 +31,14 @@ void Manager::addTrack(std::map<int,Track*> &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<OpenThreads::Mutex> m_lock(mutex);
for (std::map<int,Track*>::iterator it = audioTracks.begin(); it != audioTracks.end(); ++it)
for (std::map<int,Track*>::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<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)