From 8113bbfe40ac11df601f9e581b502ef0f9ab4c0e Mon Sep 17 00:00:00 2001 From: Jessica Hamilton Date: Tue, 29 Dec 2015 17:43:24 +1300 Subject: [PATCH] ffmpeg addon: only use swresample for planar audio. Fixes #12547. --- .../media/plugins/ffmpeg/AVCodecDecoder.cpp | 43 +++++++++++-------- src/add-ons/media/plugins/ffmpeg/Utilities.h | 16 +++++++ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp index c162b13491..69e405b577 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp @@ -408,12 +408,14 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat) if (fRawDecodedAudio->opaque == NULL) return B_NO_MEMORY; - fResampleContext = swr_alloc_set_opts(NULL, - fContext->channel_layout, fContext->request_sample_fmt, - fContext->sample_rate, - fContext->channel_layout, fContext->sample_fmt, fContext->sample_rate, - 0, NULL); - swr_init(fResampleContext); + if (AVSampleFormatIsPlanar(fContext->sample_fmt)) { + fResampleContext = swr_alloc_set_opts(NULL, + fContext->channel_layout, fContext->request_sample_fmt, + fContext->sample_rate, + fContext->channel_layout, fContext->sample_fmt, fContext->sample_rate, + 0, NULL); + swr_init(fResampleContext); + } TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, " "output frame size: %d, count: %ld, rate: %.2f\n", @@ -923,24 +925,29 @@ AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes() // "planar" audio (each channel separated instead of interleaved samples). // In that case, we use swresample to convert the data (and it is // smart enough to do just a copy, when possible) - const uint8_t* ptr[8]; - for (int i = 0; i < 8; i++) { - if (fDecodedDataBuffer->data[i] == NULL) - ptr[i] = NULL; - else - ptr[i] = fDecodedDataBuffer->data[i] + fDecodedDataBufferOffset; - } + if (AVSampleFormatIsPlanar(fContext->sample_fmt)) { + const uint8_t* ptr[8]; + for (int i = 0; i < 8; i++) { + if (fDecodedDataBuffer->data[i] == NULL) + ptr[i] = NULL; + else + ptr[i] = fDecodedDataBuffer->data[i] + fDecodedDataBufferOffset; + } - int32 result = swr_convert(fResampleContext, fRawDecodedAudio->data, - outFrames, ptr, inFrames); + int32 result = swr_convert(fResampleContext, fRawDecodedAudio->data, + outFrames, ptr, inFrames); + + if (result < 0) + debugger("resampling failed"); + } else { + memcpy(fRawDecodedAudio->data[0], fDecodedDataBuffer->data[0] + + fDecodedDataBufferOffset, frames * fOutputFrameSize); + } size_t remainingSize = inFrames * fOutputFrameSize; size_t decodedSize = outFrames * fOutputFrameSize; fDecodedDataBufferSize -= inFrames; - if (result < 0) - debugger("resampling failed"); - bool firstAudioFramesCopiedToRawDecodedAudio = fRawDecodedAudio->data[0] != fDecodedData; if (!firstAudioFramesCopiedToRawDecodedAudio) { diff --git a/src/add-ons/media/plugins/ffmpeg/Utilities.h b/src/add-ons/media/plugins/ffmpeg/Utilities.h index 209bd1eb17..3a9e0e405f 100644 --- a/src/add-ons/media/plugins/ffmpeg/Utilities.h +++ b/src/add-ons/media/plugins/ffmpeg/Utilities.h @@ -317,4 +317,20 @@ ConvertAVSampleFormatToRawAudioFormat(AVSampleFormat sampleFormatIn, } +inline bool +AVSampleFormatIsPlanar(AVSampleFormat sampleFormat) +{ + switch (sampleFormat) { + case AV_SAMPLE_FMT_FLTP: + case AV_SAMPLE_FMT_DBLP: + case AV_SAMPLE_FMT_S32P: + case AV_SAMPLE_FMT_S16P: + case AV_SAMPLE_FMT_U8P: + return true; + default: + return false; + } +} + + #endif // UTILITIES_H