mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-27 07:23:11 +02:00
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:
@@ -49,8 +49,9 @@ struct Track
|
|||||||
bool hidden; // not part of currently selected program
|
bool hidden; // not part of currently selected program
|
||||||
bool is_static;
|
bool is_static;
|
||||||
int ac3flags;
|
int ac3flags;
|
||||||
|
AVBitStreamFilterContext *bsfc;
|
||||||
int type, mag, page; // for teletext
|
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
|
struct Program
|
||||||
|
@@ -123,6 +123,8 @@ bool Input::Play()
|
|||||||
// Oddly, this seems to be necessary for network streaming only ...
|
// Oddly, this seems to be necessary for network streaming only ...
|
||||||
bool audioSeen = !audioTrack || !player->isHttp;
|
bool audioSeen = !audioTrack || !player->isHttp;
|
||||||
|
|
||||||
|
int reinit_audio = 0;
|
||||||
|
|
||||||
while (player->isPlaying && !player->abortRequested) {
|
while (player->isPlaying && !player->abortRequested) {
|
||||||
|
|
||||||
//IF MOVIE IS PAUSED, WAIT
|
//IF MOVIE IS PAUSED, WAIT
|
||||||
@@ -221,6 +223,53 @@ bool Input::Play()
|
|||||||
restart_audio_resampling = false;
|
restart_audio_resampling = false;
|
||||||
player->output.Write(stream, NULL, 0);
|
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) {
|
if (!player->isBackWard) {
|
||||||
int64_t pts = calcPts(stream, packet.pts);
|
int64_t pts = calcPts(stream, packet.pts);
|
||||||
if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0))
|
if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0))
|
||||||
@@ -524,6 +573,9 @@ bool Input::UpdateTracks()
|
|||||||
break;
|
break;
|
||||||
case AV_CODEC_ID_AAC:
|
case AV_CODEC_ID_AAC:
|
||||||
track.ac3flags = 5;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
track.ac3flags = 0;
|
track.ac3flags = 0;
|
||||||
|
@@ -31,9 +31,15 @@ void Manager::addTrack(std::map<int,Track*> &tracks, Track &track)
|
|||||||
Track *t = new Track;
|
Track *t = new Track;
|
||||||
*t = track;
|
*t = track;
|
||||||
tracks[track.pid] = t;
|
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;
|
*it->second = track;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Manager::addVideoTrack(Track &track)
|
void Manager::addVideoTrack(Track &track)
|
||||||
{
|
{
|
||||||
@@ -238,8 +244,14 @@ void Manager::clearTracks()
|
|||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
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;
|
delete it->second;
|
||||||
|
}
|
||||||
audioTracks.clear();
|
audioTracks.clear();
|
||||||
|
|
||||||
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
for (std::map<int, Track*>::iterator it = videoTracks.begin(); it != videoTracks.end(); ++it)
|
||||||
|
Reference in New Issue
Block a user