From fff7e63650c1569908bf80f11a123e051e993f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludger=20Kr=C3=A4mer?= Date: Fri, 16 Aug 2013 20:30:28 +0200 Subject: [PATCH] fix compilation with ffmpeg 2.0 avcodec_decode_audio4 seems not to deliver data in AV_SAMPLE_FMT_S16 format, so we have to use libavresample for resampling --- CMakeLists.txt | 2 +- conf/FindFFMpeg.cmake | 6 ++++- src/backends/decoder.cpp | 64 ++++++++++++++++++++++++++++++++++++++++++------ src/backends/decoder.h | 8 ++++++ 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33dbb85..d3a964b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,7 +286,7 @@ IF(AUDIO_BACKEND) ENDIF(AUDIO_BACKEND) IF(ENABLE_LIBAVCODEC) - pkg_check_modules(FFMPEG libavcodec libavutil libavformat) + pkg_check_modules(FFMPEG libavcodec libavutil libavformat libavresample) IF(NOT(FFMPEG_FOUND)) INCLUDE(FindFFMpeg REQUIRED) ENDIF(NOT(FFMPEG_FOUND)) diff --git a/conf/FindFFMpeg.cmake b/conf/FindFFMpeg.cmake index 2b4dd98..8246c15 100644 --- a/conf/FindFFMpeg.cmake +++ b/conf/FindFFMpeg.cmake @@ -23,7 +23,11 @@ FIND_LIBRARY(FFMPEG_AVFORMAT_LIBRARY NAMES avformat ) -SET(FFMPEG_LIBRARY ${FFMPEG_AVCODEC_LIBRARY} ${FFMPEG_AVUTIL_LIBRARY} ${FFMPEG_AVFORMAT_LIBRARY}) +FIND_LIBRARY(FFMPEG_AVRESAMPLE_LIBRARY NAMES + avresample +) + +SET(FFMPEG_LIBRARY ${FFMPEG_AVCODEC_LIBRARY} ${FFMPEG_AVUTIL_LIBRARY} ${FFMPEG_AVFORMAT_LIBRARY} ${FFMPEG_AVRESAMPLE_LIBRARY}) MARK_AS_ADVANCED(FFMPEG_LIBRARY) # handle the QUIETLY and REQUIRED arguments and set FFMPEG_FOUND to TRUE if diff --git a/src/backends/decoder.cpp b/src/backends/decoder.cpp index 22eac2e..4b3148c 100755 --- a/src/backends/decoder.cpp +++ b/src/backends/decoder.cpp @@ -295,6 +295,8 @@ bool FFMpegVideoDecoder::decodePacket(AVPacket* pkt, uint32_t time) #else int ret=avcodec_decode_video(codecContext, frameIn, &frameOk, pkt->data, pkt->size); #endif + if (ret < 0) + return false; assert_and_throw(ret==(int)pkt->size); if(frameOk) @@ -612,10 +614,33 @@ uint32_t FFMpegAudioDecoder::decodeData(uint8_t* data, int32_t datalen, uint32_t ret=-1; else { - //This is suboptimal but equivalent to what libavcodec - //does for the compatibility version of avcodec_decode_audio3 - memcpy(curTail.samples, frameIn->extended_data[0], frameIn->linesize[0]); - maxLen=frameIn->linesize[0]; + if (frameIn->format != AV_SAMPLE_FMT_S16) + { + AVAudioResampleContext * avr = avresample_alloc_context(); + av_opt_set_int(avr, "in_channel_layout", frameIn->channel_layout, 0); + av_opt_set_int(avr, "out_channel_layout", frameIn->channel_layout, 0); + av_opt_set_int(avr, "in_sample_rate", frameIn->sample_rate, 0); + av_opt_set_int(avr, "out_sample_rate", frameIn->sample_rate, 0); + av_opt_set_int(avr, "in_sample_fmt", frameIn->format, 0); + av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + avresample_open(avr); + + uint8_t *output; + int out_linesize; + int out_samples = avresample_available(avr) + av_rescale_rnd(avresample_get_delay(avr) + frameIn->linesize[0], frameIn->sample_rate, frameIn->sample_rate, AV_ROUND_UP); + av_samples_alloc(&output, &out_linesize, frameIn->nb_samples, out_samples, AV_SAMPLE_FMT_S16, 0); + maxLen = avresample_convert(avr, &output, out_linesize, out_samples, frameIn->extended_data, frameIn->linesize[0], frameIn->nb_samples)*4; + memcpy(curTail.samples, output, maxLen); + av_freep(&output); + avresample_free(&avr); + } + else + { + //This is suboptimal but equivalent to what libavcodec + //does for the compatibility version of avcodec_decode_audio3 + memcpy(curTail.samples, frameIn->extended_data[0], frameIn->linesize[0]); + maxLen=frameIn->linesize[0]; + } } #else int32_t ret=avcodec_decode_audio3(codecContext, curTail.samples, &maxLen, &pkt); @@ -660,10 +685,33 @@ uint32_t FFMpegAudioDecoder::decodePacket(AVPacket* pkt, uint32_t time) ret=-1; else { - //This is suboptimal but equivalent to what libavcodec - //does for the compatibility version of avcodec_decode_audio3 - memcpy(curTail.samples, frameIn->extended_data[0], frameIn->linesize[0]); - maxLen=frameIn->linesize[0]; + if (frameIn->format != AV_SAMPLE_FMT_S16) + { + AVAudioResampleContext * avr = avresample_alloc_context(); + av_opt_set_int(avr, "in_channel_layout", frameIn->channel_layout, 0); + av_opt_set_int(avr, "out_channel_layout", frameIn->channel_layout, 0); + av_opt_set_int(avr, "in_sample_rate", frameIn->sample_rate, 0); + av_opt_set_int(avr, "out_sample_rate", frameIn->sample_rate, 0); + av_opt_set_int(avr, "in_sample_fmt", frameIn->format, 0); + av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); + avresample_open(avr); + + uint8_t *output; + int out_linesize; + int out_samples = avresample_available(avr) + av_rescale_rnd(avresample_get_delay(avr) + frameIn->linesize[0], frameIn->sample_rate, frameIn->sample_rate, AV_ROUND_UP); + av_samples_alloc(&output, &out_linesize, frameIn->nb_samples, out_samples, AV_SAMPLE_FMT_S16, 0); + maxLen = avresample_convert(avr, &output, out_linesize, out_samples, frameIn->extended_data, frameIn->linesize[0], frameIn->nb_samples)*4; + memcpy(curTail.samples, output, maxLen); + av_freep(&output); + avresample_free(&avr); + } + else + { + //This is suboptimal but equivalent to what libavcodec + //does for the compatibility version of avcodec_decode_audio3 + memcpy(curTail.samples, frameIn->extended_data[0], frameIn->linesize[0]); + maxLen=frameIn->linesize[0]; + } } #elif HAVE_AVCODEC_DECODE_AUDIO3 int ret=avcodec_decode_audio3(codecContext, curTail.samples, &maxLen, pkt); diff --git a/src/backends/decoder.h b/src/backends/decoder.h index 93950ad..28bd232 100644 --- a/src/backends/decoder.h +++ b/src/backends/decoder.h @@ -28,6 +28,14 @@ { #include #include +#include +#include +#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE +#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio +#endif +#ifndef CodecID +#define CodecID AVCodecID +#endif #define MAX_AUDIO_FRAME_SIZE AVCODEC_MAX_AUDIO_FRAME_SIZE } #else -- 1.8.4