From: Nelson Ferreira Date: Sat, 16 Jan 2016 22:14:03 +0000 (-0500) Subject: Fix crash when using ffmpeg to play mp3 and ogg X-Git-Tag: v22.1.16~3^2~1 X-Git-Url: http://cgit.sxemacs.org/?p=sxemacs;a=commitdiff_plain;h=55a8171804431552de01a8e98c585c276e32c054 Fix crash when using ffmpeg to play mp3 and ogg * src/media/media-ffmpeg.c (media_ffmpeg_analyse_audio): Refactor detection of sample size using av_get_bytes_per_sample. Error when format is not supported instead of silently go ahead and possibly crash later. * src/media/media.c (sxe_msf_DBL_up): Implement conversion to internal format from double. (sxe_msf_DBL_down): Implement from internal format to double. * src/media/media.h: Declare double encoded samples. * m4/sxe-mm.m4 (SXE_CHECK_FFMPEG_LIBS): Detect av_get_bytes_per_sample and av_get_sample_fmt_string. (SXE_MM_CHECK_FFMPEG): Enforce presenc of av_get_bytes_per_sample and av_get_sample_fmt_string. Signed-off-by: Nelson Ferreira --- diff --git a/m4/sxe-mm.m4 b/m4/sxe-mm.m4 index 92e873d..878c4da 100644 --- a/m4/sxe-mm.m4 +++ b/m4/sxe-mm.m4 @@ -388,6 +388,8 @@ AC_DEFUN([SXE_MM_CHECK_FFMPEG], [ "$ac_cv_lib_avformat_av_seek_frame" = "yes" -a \ "$ac_cv_lib_avformat_av_register_all" = "yes" -a \ "$ac_cv_lib_avformat_av_dump_format" = "yes" -a \ + "$ac_cv_lib_avformat_av_get_sample_fmt_string" = "yes" -a \ + "$ac_cv_lib_avformat_av_get_bytes_per_sample" = "yes" -a \ "$ac_cv_lib_avcodec_avcodec_find_decoder" = "yes" -a \ "$ac_cv_lib_avcodec_avcodec_open2" = "yes" -a \ "$ac_cv_lib_avutil_av_dict_get" = "yes"; then @@ -449,6 +451,8 @@ AC_DEFUN([SXE_CHECK_FFMPEG_LIBS], [dnl AC_CHECK_LIB([avformat], [av_seek_frame], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [av_register_all], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [av_dump_format], [:], [:], [${FFMPEG_LIBS}]) + AC_CHECK_LIB([avformat], [av_get_bytes_per_sample], [:], [:], [${FFMPEG_LIBS}]) + AC_CHECK_LIB([avformat], [av_get_sample_fmt_string], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [avformat_alloc_context], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [avformat_free_context], [:], [:], [${FFMPEG_LIBS}]) AC_CHECK_LIB([avformat], [avio_alloc_context], [:], [:], [${FFMPEG_LIBS}]) diff --git a/src/media/media-ffmpeg.c b/src/media/media-ffmpeg.c index 559b2e9..e9e6710 100644 --- a/src/media/media-ffmpeg.c +++ b/src/media/media-ffmpeg.c @@ -376,39 +376,47 @@ media_ffmpeg_analyse_audio(media_substream *mss, AVFormatContext *avfc, int st) mtap->samplerate = avcc->sample_rate; mtap->bitrate = media_ffmpeg_bitrate(avcc); + int sample_bytes = + av_get_bytes_per_sample(avcc->sample_fmt); + mtap->samplewidth = 8 * sample_bytes; + mtap->framesize = mtap->channels * sample_bytes; /* samplewidth and framesize */ switch (avcc->sample_fmt) { case AV_SAMPLE_FMT_U8: - mtap->samplewidth = 8; - mtap->framesize = mtap->channels * 1; + assert(sample_bytes == 1); mtap->msf = sxe_msf_U8; break; case AV_SAMPLE_FMT_S16: - mtap->samplewidth = 16; - mtap->framesize = mtap->channels * 2; + assert(sample_bytes == 2); mtap->msf = sxe_msf_S16; break; -#if defined AV_SAMPLE_FMT_S24 - case AV_SAMPLE_FMT_S24: - mtap->samplewidth = 32; - mtap->framesize = mtap->channels * 4; - mtap->msf = sxe_msf_S24; - break; -#endif /* SAMPLE_FMT_S24 */ case AV_SAMPLE_FMT_S32: - mtap->samplewidth = 32; - mtap->framesize = mtap->channels * 4; + assert(sample_bytes == 4); mtap->msf = sxe_msf_S32; break; case AV_SAMPLE_FMT_FLT: - mtap->samplewidth = 8*sizeof(float); - mtap->framesize = mtap->channels * sizeof(float); + assert(sample_bytes == sizeof(float)); mtap->msf = sxe_msf_FLT; break; + case AV_SAMPLE_FMT_DBL: + assert(sample_bytes == sizeof(double)); + mtap->msf = sxe_msf_DBL; + break; case AV_SAMPLE_FMT_NONE: - default: mtap->samplewidth = 0; break; + default: + { + char fmt_name[128]; + error(("Unsupported sample format: " + "%s (%d), %d bytes/sample"), + av_get_sample_fmt_string( + fmt_name, + sizeof(fmt_name), + avcc->sample_fmt), + avcc->sample_fmt, + sample_bytes); + } } } mtap->endianness = 0; diff --git a/src/media/media.c b/src/media/media.c index cc1707a..3d9f973 100644 --- a/src/media/media.c +++ b/src/media/media.c @@ -1300,6 +1300,47 @@ sxe_msf_FLT_down(void *d, void *s, size_t len) return; } +DEFINE_MEDIA_SAMPLE_FORMAT_SIMPLE(sxe_msf_DBL); + +static void +sxe_msf_DBL_up(void *d, void *s, size_t len) +{ + /* convert double samples to internal format (S24in32) */ + size_t i; + int32_t *dst = d; + double *src = s; + + /* len is the number of samples (== #frame * #channels) */ + MEDIA_DEBUG_FMT("upsampling DBL->internal: %u samples\n", len); + + for (i = 0; i < len; i++) { + dst[i] = (int32_t)(src[i] * SXE_MAX_S24); + } + MEDIA_DEBUG_FMT("s00:%f d00:%d s01:%f d01:%d\n", + src[0], dst[0], src[1], dst[1]); + + return; +} + +static void +sxe_msf_DBL_down(void *d, void *s, size_t len) +{ + /* convert samples from internal format (S24in32) to double */ + int i; + float *dst = d; + int32_t *src = s; + + /* len is the number of samples (== #frame * #channels) */ + MEDIA_DEBUG_FMT("downsampling internal->FLT: %u samples\n", len); + + for (i = len-1; i >= 0; i--) { + dst[i] = (double)(src[i]) / SXE_MAX_S24; + } + MEDIA_DEBUG_FMT("d00:%f d01:%f\n", dst[0], dst[1]); + + return; +} + /* `effects' */ DEFINE_MEDIA_SAMPLE_EFFECT(sxe_mse_1ch_to_2ch, _sxe_mse_1ch_to_2ch); diff --git a/src/media/media.h b/src/media/media.h index 97e3d1a..39f999f 100644 --- a/src/media/media.h +++ b/src/media/media.h @@ -414,6 +414,7 @@ struct audio_coerce_chain_s { DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_U8); DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_S16); DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_FLT); +DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_DBL); DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_S32); DECLARE_MEDIA_SAMPLE_FORMAT(sxe_msf_S24); /* format internally used */