From 73483990f86081bc08ee6a28b9dcafbf4cf8f4c4 Mon Sep 17 00:00:00 2001 From: schpuntik Date: Fri, 28 Oct 2016 23:42:58 +0200 Subject: [PATCH] Enable aac writer and use resmpling for some AAC streams thx Taapat and technik --- libeplayer3/include/output.h | 6 ++-- libeplayer3/include/writer.h | 2 +- libeplayer3/input.cpp | 68 ++++++++++++++++++++++------------- libeplayer3/output.cpp | 56 ++++++++++++++++------------- libeplayer3/writer/pcm.cpp | 42 +++++++++++++++------- libeplayer3/writer/pes.cpp | 4 +-- libeplayer3/writer/writer.cpp | 11 +++--- 7 files changed, 116 insertions(+), 73 deletions(-) diff --git a/libeplayer3/include/output.h b/libeplayer3/include/output.h index 4b024fa..2fec93e 100644 --- a/libeplayer3/include/output.h +++ b/libeplayer3/include/output.h @@ -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); }; diff --git a/libeplayer3/include/writer.h b/libeplayer3/include/writer.h index 4d6ee2e..359223b 100644 --- a/libeplayer3/include/writer.h +++ b/libeplayer3/include/writer.h @@ -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); diff --git a/libeplayer3/input.cpp b/libeplayer3/input.cpp index 9f79f39..19af03e 100644 --- a/libeplayer3/input.cpp +++ b/libeplayer3/input.cpp @@ -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; } diff --git a/libeplayer3/output.cpp b/libeplayer3/output.cpp index 63e55c5..5b8cb65 100644 --- a/libeplayer3/output.cpp +++ b/libeplayer3/output.cpp @@ -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); diff --git a/libeplayer3/writer/pcm.cpp b/libeplayer3/writer/pcm.cpp index cb84f27..7fe2579 100644 --- a/libeplayer3/writer/pcm.cpp +++ b/libeplayer3/writer/pcm.cpp @@ -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; diff --git a/libeplayer3/writer/pes.cpp b/libeplayer3/writer/pes.cpp index 0a1265b..c8b9bc2 100644 --- a/libeplayer3/writer/pes.cpp +++ b/libeplayer3/writer/pes.cpp @@ -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); diff --git a/libeplayer3/writer/writer.cpp b/libeplayer3/writer/writer.cpp index 67bc0d9..3a0b9f0 100644 --- a/libeplayer3/writer/writer.cpp +++ b/libeplayer3/writer/writer.cpp @@ -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::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::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; }