Enable aac writer and use resmpling for some AAC streams thx Taapat and technik

This commit is contained in:
schpuntik
2016-10-28 23:42:58 +02:00
parent 19b576a45c
commit 73483990f8
7 changed files with 116 additions and 73 deletions

View File

@@ -49,7 +49,7 @@ class Output
int audiofd;
Writer *videoWriter, *audioWriter;
Mutex audioMutex, videoMutex;
AVStream *audioStream, *videoStream;
Track *audioTrack, *videoTrack;
Player *player;
public:
Output();
@@ -70,8 +70,8 @@ class Output
bool ClearVideo();
bool GetPts(int64_t &pts);
bool GetFrameCount(int64_t &framecount);
bool SwitchAudio(AVStream *stream);
bool SwitchVideo(AVStream *stream);
bool SwitchAudio(Track *track);
bool SwitchVideo(Track *track);
bool Write(AVStream *stream, AVPacket *packet, int64_t Pts);
};

View File

@@ -49,7 +49,7 @@ class Writer
static void Register(Writer *w, enum AVCodecID id, audio_encoding_t encoding);
static video_encoding_t GetVideoEncoding(enum AVCodecID id);
static audio_encoding_t GetAudioEncoding(enum AVCodecID id);
static Writer *GetWriter(enum AVCodecID id, enum AVMediaType codec_type);
static Writer *GetWriter(enum AVCodecID id, enum AVMediaType codec_type, int track_type);
virtual void Init(int _fd, AVStream * /*stream*/, Player *_player ) { fd = _fd; player = _player; }
virtual bool Write(AVPacket *packet, int64_t pts);

View File

@@ -215,7 +215,7 @@ bool Input::Play()
if (_videoTrack && (_videoTrack->stream == stream)) {
int64_t pts = calcPts(stream, packet.pts);
if (audioSeen && !player->output.Write(stream, &packet, pts))
logprintf("writing data to %s device failed\n", "video");
logprintf("writing data to video device failed\n");
} else if (_audioTrack && (_audioTrack->stream == stream)) {
if (restart_audio_resampling) {
restart_audio_resampling = false;
@@ -224,7 +224,7 @@ bool Input::Play()
if (!player->isBackWard) {
int64_t pts = calcPts(stream, packet.pts);
if (!player->output.Write(stream, &packet, _videoTrack ? pts : 0))
logprintf("writing data to %s device failed\n", "audio");
logprintf("writing data to audio device failed\n");
}
audioSeen = true;
} else if (_subtitleTrack && (_subtitleTrack->stream == stream)) {
@@ -493,9 +493,9 @@ again:
}
if (videoTrack)
player->output.SwitchVideo(videoTrack->stream);
player->output.SwitchVideo(videoTrack);
if (audioTrack)
player->output.SwitchAudio(audioTrack->stream);
player->output.SwitchAudio(audioTrack);
ReadSubtitles(filename);
@@ -544,6 +544,7 @@ bool Input::UpdateTracks()
}
track.pid = use_index_as_pid ? n + 1: stream->id;
track.ac3flags = 0;
switch (stream->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
@@ -553,26 +554,43 @@ bool Input::UpdateTracks()
break;
case AVMEDIA_TYPE_AUDIO:
switch(stream->codec->codec_id) {
case AV_CODEC_ID_MP2:
track.ac3flags = 9;
break;
case AV_CODEC_ID_MP3:
track.ac3flags = 4;
break;
case AV_CODEC_ID_AC3:
track.ac3flags = 1;
break;
case AV_CODEC_ID_EAC3:
track.ac3flags = 7;
break;
case AV_CODEC_ID_DTS:
track.ac3flags = 6;
break;
case AV_CODEC_ID_AAC:
track.ac3flags = 5;
break;
case AV_CODEC_ID_MP2:
track.ac3flags = 1;
break;
case AV_CODEC_ID_MP3:
track.ac3flags = 2;
break;
case AV_CODEC_ID_AC3:
track.ac3flags = 3;
break;
case AV_CODEC_ID_DTS:
track.ac3flags = 4;
break;
case AV_CODEC_ID_AAC: {
unsigned int extradata_size = stream->codec->extradata_size;
unsigned int object_type = 2;
if(extradata_size >= 2)
object_type = stream->codec->extradata[0] >> 3;
if (extradata_size <= 1 || object_type == 1 || object_type == 5) {
fprintf(stderr, "use resampling for AAC\n");
track.ac3flags = 6;
}
else
track.ac3flags = 5;
break;
}
case AV_CODEC_ID_FLAC:
track.ac3flags = 8;
break;
case AV_CODEC_ID_WMAV1:
case AV_CODEC_ID_WMAV2:
case AV_CODEC_ID_WMAVOICE:
case AV_CODEC_ID_WMAPRO:
case AV_CODEC_ID_WMALOSSLESS:
track.ac3flags = 9;
break;
default:
track.ac3flags = 0;
track.ac3flags = 0;
}
player->manager.addAudioTrack(track);
if (!audioTrack)
@@ -686,7 +704,7 @@ bool Input::GetDuration(int64_t &duration)
bool Input::SwitchAudio(Track *track)
{
audioTrack = track;
player->output.SwitchAudio(track ? track->stream : NULL);
player->output.SwitchAudio(track ? track : NULL);
// player->Seek(-5000, false);
return true;
}
@@ -706,7 +724,7 @@ bool Input::SwitchTeletext(Track *track)
bool Input::SwitchVideo(Track *track)
{
videoTrack = track;
player->output.SwitchVideo(track ? track->stream : NULL);
player->output.SwitchVideo(track ? track : NULL);
return true;
}

View File

@@ -58,7 +58,7 @@ Output::Output()
{
videofd = audiofd = -1;
videoWriter = audioWriter = NULL;
videoStream = audioStream = NULL;
videoTrack = audioTrack = NULL;
}
Output::~Output()
@@ -114,8 +114,8 @@ bool Output::Close()
audiofd = -1;
}
videoStream = NULL;
audioStream = NULL;
videoTrack = NULL;
audioTrack = NULL;
return true;
}
@@ -129,18 +129,21 @@ bool Output::Play()
AVCodecContext *avcc;
if (videoStream && videofd > -1 && (avcc = videoStream->codec)) {
videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type);
videoWriter->Init(videofd, videoStream, player);
if (videoTrack && videoTrack->stream && videofd > -1 && (avcc = videoTrack->stream->codec)) {
videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, videoTrack->ac3flags);
videoWriter->Init(videofd, videoTrack->stream, player);
if (dioctl(videofd, VIDEO_SET_ENCODING, videoWriter->GetVideoEncoding(avcc->codec_id))
|| dioctl(videofd, VIDEO_PLAY, NULL))
ret = false;
}
if (audioStream && audiofd > -1 && (avcc = audioStream->codec)) {
audioWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type);
audioWriter->Init(audiofd, audioStream, player);
if (dioctl(audiofd, AUDIO_SET_ENCODING, audioWriter->GetAudioEncoding(avcc->codec_id))
if (audioTrack && audioTrack->stream && audiofd > -1 && (avcc = audioTrack->stream->codec)) {
audioWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, audioTrack->ac3flags);
audioWriter->Init(audiofd, audioTrack->stream, player);
audio_encoding_t audioEncoding = AUDIO_ENCODING_LPCMA;
if (audioTrack->ac3flags != 6)
audioEncoding = audioWriter->GetAudioEncoding(avcc->codec_id);
if (dioctl(audiofd, AUDIO_SET_ENCODING, audioEncoding)
|| dioctl(audiofd, AUDIO_PLAY, NULL))
ret = false;
}
@@ -297,46 +300,49 @@ bool Output::GetFrameCount(int64_t &framecount)
return false;
}
bool Output::SwitchAudio(AVStream *stream)
bool Output::SwitchAudio(Track *track)
{
ScopedLock a_lock(audioMutex);
if (stream == audioStream)
if (audioTrack && track->stream == audioTrack->stream)
return true;
if (audiofd > -1) {
dioctl(audiofd, AUDIO_STOP, NULL);
ioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
}
audioStream = stream;
if (stream) {
AVCodecContext *avcc = stream->codec;
audioTrack = track;
if (track->stream) {
AVCodecContext *avcc = track->stream->codec;
if (!avcc)
return false;
audioWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type);
audioWriter->Init(audiofd, audioStream, player);
audioWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, audioTrack->ac3flags);
audioWriter->Init(audiofd, audioTrack->stream, player);
if (audiofd > -1) {
dioctl(audiofd, AUDIO_SET_ENCODING, Writer::GetAudioEncoding(avcc->codec_id));
audio_encoding_t audioEncoding = AUDIO_ENCODING_LPCMA;
if (audioTrack->ac3flags != 6)
audioEncoding = Writer::GetAudioEncoding(avcc->codec_id);
dioctl(audiofd, AUDIO_SET_ENCODING, audioEncoding);
dioctl(audiofd, AUDIO_PLAY, NULL);
}
}
return true;
}
bool Output::SwitchVideo(AVStream *stream)
bool Output::SwitchVideo(Track *track)
{
ScopedLock v_lock(videoMutex);
if (stream == videoStream)
if (videoTrack && track->stream == videoTrack->stream)
return true;
if (videofd > -1) {
dioctl(videofd, VIDEO_STOP, NULL);
ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
}
videoStream = stream;
if (stream) {
AVCodecContext *avcc = stream->codec;
videoTrack = track;
if (track->stream) {
AVCodecContext *avcc = track->stream->codec;
if (!avcc)
return false;
videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type);
videoWriter->Init(videofd, videoStream, player);
videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, videoTrack->type);
videoWriter->Init(videofd, videoTrack->stream, player);
if (videofd > -1) {
dioctl(videofd, VIDEO_SET_ENCODING, Writer::GetVideoEncoding(avcc->codec_id));
dioctl(videofd, VIDEO_PLAY, NULL);

View File

@@ -242,27 +242,36 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
restart_audio_resampling = false;
initialHeader = true;
if (swr) {
swr_free(&swr);
swr = NULL;
}
if (decoded_frame) {
av_frame_free(&decoded_frame);
decoded_frame = NULL;
}
AVCodec *codec = avcodec_find_decoder(c->codec_id);
if (!codec) {
fprintf(stderr, "%s %d: avcodec_find_decoder(%llx)\n", __func__, __LINE__, (unsigned long long) c->codec_id);
return false;
if (!codec) {
fprintf(stderr, "%s %d: avcodec_find_decoder(%llx)\n", __func__, __LINE__, (unsigned long long) c->codec_id);
return false;
}
avcodec_close(c);
if (avcodec_open2(c, codec, NULL)) {
fprintf(stderr, "%s %d: avcodec_open2 failed\n", __func__, __LINE__);
return false;
if (avcodec_open2(c, codec, NULL)) {
fprintf(stderr, "%s %d: avcodec_open2 failed\n", __func__, __LINE__);
return false;
}
}
if (!swr) {
int rates[] = { 48000, 96000, 192000, 44100, 88200, 176400, 0 };
int *rate = rates;
int in_rate = c->sample_rate;
while (*rate && ((*rate / in_rate) * in_rate != *rate) && (in_rate / *rate) * *rate != in_rate)
rate++;
out_sample_rate = *rate ? *rate : 44100;
// rates in descending order
int rates[] = {192000, 176400, 96000, 88200, 48000, 44100, 0};
int i = 0;
// find the next equal or smallest rate
while (rates[i] && in_rate < rates[i])
i++;
out_sample_rate = rates[i] ? rates[i] : 44100;
out_channels = c->channels;
if (c->channel_layout == 0) {
// FIXME -- need to guess, looks pretty much like a bug in the FFMPEG WMA decoder
@@ -304,9 +313,16 @@ bool WriterPCM::Write(AVPacket *packet, int64_t pts)
unsigned int packet_size = packet->size;
while (packet_size > 0 || (!packet_size && !packet->data)) {
av_frame_unref(decoded_frame);
int got_frame = 0;
if (!decoded_frame) {
if (!(decoded_frame = av_frame_alloc())) {
fprintf(stderr, "out of memory\n");
exit(1);
}
} else
av_frame_unref(decoded_frame);
int len = avcodec_decode_audio4(c, decoded_frame, &got_frame, packet);
if (len < 0) {
restart_audio_resampling = true;

View File

@@ -53,8 +53,8 @@ int InsertPesHeader(uint8_t *data, int size, uint8_t stream_id, int64_t pts, int
{
BitPacker_t ld2 = { data, 0, 32 };
if (size > MAX_PES_PACKET_SIZE)
size = 0; // unbounded
/* if (size > MAX_PES_PACKET_SIZE)
size = 0; // unbounded */
PutBits(&ld2, 0x0, 8);
PutBits(&ld2, 0x0, 8);

View File

@@ -66,20 +66,23 @@ bool Writer::Write(AVPacket * /* packet */, int64_t /* pts */)
static Writer writer __attribute__ ((init_priority (300)));
Writer *Writer::GetWriter(enum AVCodecID id, enum AVMediaType codec_type)
Writer *Writer::GetWriter(enum AVCodecID id, enum AVMediaType codec_type, int track_type)
{
std::map<enum AVCodecID,Writer*>::iterator it = writers.find(id);
fprintf(stderr, "GETWRITER %d %d %d", id, codec_type, track_type);
if (track_type != 6) { // hack for ACC resampling
std::map<enum AVCodecID,Writer*>::iterator it = writers.find(id);
if (it != writers.end())
return it->second;
}
switch (codec_type) {
case AVMEDIA_TYPE_AUDIO:
if (id == AV_CODEC_ID_INJECTPCM) // should not happen
break;
return GetWriter(AV_CODEC_ID_INJECTPCM, codec_type);
return GetWriter(AV_CODEC_ID_INJECTPCM, codec_type, 100);
case AVMEDIA_TYPE_VIDEO:
if (id == AV_CODEC_ID_MPEG2TS) // should not happen
break;
return GetWriter(AV_CODEC_ID_MPEG2TS, codec_type);
return GetWriter(AV_CODEC_ID_MPEG2TS, codec_type, 100);
default:
break;
}