From a86d783468d57fab15f519ef32418d4a005f951f Mon Sep 17 00:00:00 2001
From: Jessica Hamilton <jessica.l.hamilton@gmail.com>
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 c162b13..69e405b 100644
a
|
b
|
AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat)
|
408 | 408 | if (fRawDecodedAudio->opaque == NULL) |
409 | 409 | return B_NO_MEMORY; |
410 | 410 | |
411 | | fResampleContext = swr_alloc_set_opts(NULL, |
412 | | fContext->channel_layout, fContext->request_sample_fmt, |
413 | | fContext->sample_rate, |
414 | | fContext->channel_layout, fContext->sample_fmt, fContext->sample_rate, |
415 | | 0, NULL); |
416 | | swr_init(fResampleContext); |
| 411 | if (AVSampleFormatIsPlanar(fContext->sample_fmt)) { |
| 412 | fResampleContext = swr_alloc_set_opts(NULL, |
| 413 | fContext->channel_layout, fContext->request_sample_fmt, |
| 414 | fContext->sample_rate, |
| 415 | fContext->channel_layout, fContext->sample_fmt, fContext->sample_rate, |
| 416 | 0, NULL); |
| 417 | swr_init(fResampleContext); |
| 418 | } |
417 | 419 | |
418 | 420 | TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, " |
419 | 421 | "output frame size: %d, count: %ld, rate: %.2f\n", |
… |
… |
AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
|
923 | 925 | // "planar" audio (each channel separated instead of interleaved samples). |
924 | 926 | // In that case, we use swresample to convert the data (and it is |
925 | 927 | // smart enough to do just a copy, when possible) |
926 | | const uint8_t* ptr[8]; |
927 | | for (int i = 0; i < 8; i++) { |
928 | | if (fDecodedDataBuffer->data[i] == NULL) |
929 | | ptr[i] = NULL; |
930 | | else |
931 | | ptr[i] = fDecodedDataBuffer->data[i] + fDecodedDataBufferOffset; |
932 | | } |
| 928 | if (AVSampleFormatIsPlanar(fContext->sample_fmt)) { |
| 929 | const uint8_t* ptr[8]; |
| 930 | for (int i = 0; i < 8; i++) { |
| 931 | if (fDecodedDataBuffer->data[i] == NULL) |
| 932 | ptr[i] = NULL; |
| 933 | else |
| 934 | ptr[i] = fDecodedDataBuffer->data[i] + fDecodedDataBufferOffset; |
| 935 | } |
933 | 936 | |
934 | | int32 result = swr_convert(fResampleContext, fRawDecodedAudio->data, |
935 | | outFrames, ptr, inFrames); |
| 937 | int32 result = swr_convert(fResampleContext, fRawDecodedAudio->data, |
| 938 | outFrames, ptr, inFrames); |
| 939 | |
| 940 | if (result < 0) |
| 941 | debugger("resampling failed"); |
| 942 | } else { |
| 943 | memcpy(fRawDecodedAudio->data[0], fDecodedDataBuffer->data[0] |
| 944 | + fDecodedDataBufferOffset, frames * fOutputFrameSize); |
| 945 | } |
936 | 946 | |
937 | 947 | size_t remainingSize = inFrames * fOutputFrameSize; |
938 | 948 | size_t decodedSize = outFrames * fOutputFrameSize; |
939 | 949 | fDecodedDataBufferSize -= inFrames; |
940 | 950 | |
941 | | if (result < 0) |
942 | | debugger("resampling failed"); |
943 | | |
944 | 951 | bool firstAudioFramesCopiedToRawDecodedAudio |
945 | 952 | = fRawDecodedAudio->data[0] != fDecodedData; |
946 | 953 | if (!firstAudioFramesCopiedToRawDecodedAudio) { |
diff --git a/src/add-ons/media/plugins/ffmpeg/Utilities.h b/src/add-ons/media/plugins/ffmpeg/Utilities.h
index 209bd1e..3a9e0e4 100644
a
|
b
|
ConvertAVSampleFormatToRawAudioFormat(AVSampleFormat sampleFormatIn,
|
317 | 317 | } |
318 | 318 | |
319 | 319 | |
| 320 | inline bool |
| 321 | AVSampleFormatIsPlanar(AVSampleFormat sampleFormat) |
| 322 | { |
| 323 | switch (sampleFormat) { |
| 324 | case AV_SAMPLE_FMT_FLTP: |
| 325 | case AV_SAMPLE_FMT_DBLP: |
| 326 | case AV_SAMPLE_FMT_S32P: |
| 327 | case AV_SAMPLE_FMT_S16P: |
| 328 | case AV_SAMPLE_FMT_U8P: |
| 329 | return true; |
| 330 | default: |
| 331 | return false; |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | |
320 | 336 | #endif // UTILITIES_H |