Revert "AVCodecDecoder: use swresample to interleave audio channels."

Commit 856cc59e58 didn't really "fix"
anything; it just broke audio pretty much everywhere but YouTube,
and there videos play at 2x speed so it wasn't really worth it.

Stopgap solution for #12509.
This commit is contained in:
Augustin Cavalier
2015-12-18 20:42:29 -05:00
parent d625b5f6bb
commit 8a822b7c85
3 changed files with 40 additions and 35 deletions
@@ -5,14 +5,12 @@
* Copyright (C) 2004 Marcus Overhagen * Copyright (C) 2004 Marcus Overhagen
* Copyright (C) 2009 Stephan Amßus <[email protected]> * Copyright (C) 2009 Stephan Amßus <[email protected]>
* Copyright (C) 2014 Colin Günther <[email protected]> * Copyright (C) 2014 Colin Günther <[email protected]>
* Copyright (C) 2015 Adrien Destugues <[email protected]>
* *
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
//! libavcodec based decoder for Haiku //! libavcodec based decoder for Haiku
#include "AVCodecDecoder.h" #include "AVCodecDecoder.h"
#include <new> #include <new>
@@ -89,7 +87,6 @@ AVCodecDecoder::AVCodecDecoder()
fIsAudio(false), fIsAudio(false),
fCodec(NULL), fCodec(NULL),
fContext(avcodec_alloc_context3(NULL)), fContext(avcodec_alloc_context3(NULL)),
fResampleContext(NULL),
fDecodedData(NULL), fDecodedData(NULL),
fDecodedDataSizeInBytes(0), fDecodedDataSizeInBytes(0),
fPostProcessedDecodedPicture(avcodec_alloc_frame()), fPostProcessedDecodedPicture(avcodec_alloc_frame()),
@@ -118,6 +115,7 @@ AVCodecDecoder::AVCodecDecoder()
fAudioDecodeError(false), fAudioDecodeError(false),
fDecodedDataBuffer(avcodec_alloc_frame()), fDecodedDataBuffer(avcodec_alloc_frame()),
fDecodedDataBufferOffset(0),
fDecodedDataBufferSize(0) fDecodedDataBufferSize(0)
{ {
TRACE("AVCodecDecoder::AVCodecDecoder()\n"); TRACE("AVCodecDecoder::AVCodecDecoder()\n");
@@ -146,7 +144,6 @@ AVCodecDecoder::~AVCodecDecoder()
if (fCodecInitDone) if (fCodecInitDone)
avcodec_close(fContext); avcodec_close(fContext);
swr_free(&fResampleContext);
free(fChunkBuffer); free(fChunkBuffer);
free(fDecodedData); free(fDecodedData);
@@ -232,7 +229,8 @@ AVCodecDecoder::Setup(media_format* ioEncodedFormat, const void* infoBuffer,
} else { } else {
if (fIsAudio) { if (fIsAudio) {
fBlockAlign fBlockAlign
= ioEncodedFormat->u.encoded_audio.output.buffer_size; = ioEncodedFormat->u.encoded_audio.output
.buffer_size;
TRACE(" using buffer_size as block align: %d\n", TRACE(" using buffer_size as block align: %d\n",
fBlockAlign); fBlockAlign);
} }
@@ -272,6 +270,7 @@ AVCodecDecoder::SeekedTo(int64 frame, bigtime_t time)
free(fChunkBuffer); free(fChunkBuffer);
fChunkBuffer = NULL; fChunkBuffer = NULL;
fChunkBufferSize = 0; fChunkBufferSize = 0;
fDecodedDataBufferOffset = 0;
fDecodedDataBufferSize = 0; fDecodedDataBufferSize = 0;
fDecodedDataSizeInBytes = 0; fDecodedDataSizeInBytes = 0;
@@ -359,6 +358,7 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat)
fChunkBuffer = NULL; fChunkBuffer = NULL;
fChunkBufferSize = 0; fChunkBufferSize = 0;
fAudioDecodeError = false; fAudioDecodeError = false;
fDecodedDataBufferOffset = 0;
fDecodedDataBufferSize = 0; fDecodedDataBufferSize = 0;
_ResetTempPacket(); _ResetTempPacket();
@@ -405,13 +405,6 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat)
if (fRawDecodedAudio->opaque == NULL) if (fRawDecodedAudio->opaque == NULL)
return B_NO_MEMORY; 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);
TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, " TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, "
"output frame size: %d, count: %ld, rate: %.2f\n", "output frame size: %d, count: %ld, rate: %.2f\n",
fContext->bit_rate, fContext->sample_rate, fContext->channels, fContext->bit_rate, fContext->sample_rate, fContext->channels,
@@ -901,20 +894,24 @@ AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
assert(fRawDecodedAudio->nb_samples < fOutputFrameCount); assert(fRawDecodedAudio->nb_samples < fOutputFrameCount);
assert(fOutputFrameRate > 0); assert(fOutputFrameRate > 0);
// Some decoders do not support format conversion on themselves, or use int32 frames = min_c(fOutputFrameCount - fRawDecodedAudio->nb_samples,
// "planar" audio (each channel separated instead of interleaved samples). fDecodedDataBufferSize / fOutputFrameSize);
// In that case, we use swresample to convert the data (and it is if (frames == 0)
// smart enough to do just a copy, when possible) debugger("fDecodedDataBufferSize not multiple of frame size!");
int32 frames = swr_convert(fResampleContext, fRawDecodedAudio->data,
fOutputFrameCount - fRawDecodedAudio->nb_samples,
(const uint8_t**)fDecodedDataBuffer->data,
fDecodedDataBuffer->nb_samples);
if (frames < 0)
debugger("resampling failed");
size_t remainingSize = frames * fOutputFrameSize; size_t remainingSize = frames * fOutputFrameSize;
// libswresample handles all the buffering for us, how nice of them! #if 0
fDecodedDataBufferSize = 0; // Some decoders do not support format conversion on themselves, or use
// "planar" audio (each channel separated instead of interleaved samples).
// If this is a problem we will need to use swresample to convert the data
// here, instead of directly copying it.
swr_convert(fResampleContext, fRawDecodedAudio->data,
fDecodedDataBuffer->data + fDecodedDataBufferOffset, frames);
#else
memcpy(fRawDecodedAudio->data[0], fDecodedDataBuffer->data[0]
+ fDecodedDataBufferOffset, remainingSize);
#endif
bool firstAudioFramesCopiedToRawDecodedAudio bool firstAudioFramesCopiedToRawDecodedAudio
= fRawDecodedAudio->data[0] != fDecodedData; = fRawDecodedAudio->data[0] != fDecodedData;
@@ -931,6 +928,19 @@ AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
fRawDecodedAudio->data[0] += remainingSize; fRawDecodedAudio->data[0] += remainingSize;
fRawDecodedAudio->linesize[0] += remainingSize; fRawDecodedAudio->linesize[0] += remainingSize;
fRawDecodedAudio->nb_samples += frames; fRawDecodedAudio->nb_samples += frames;
fDecodedDataBufferOffset += remainingSize;
fDecodedDataBufferSize -= remainingSize;
// Update start times accordingly
bigtime_t framesTimeInterval = static_cast<bigtime_t>(
(1000000LL * frames) / fOutputFrameRate);
fDecodedDataBuffer->pkt_dts += framesTimeInterval;
// Start time of buffer is updated in case that it contains
// more audio frames to move.
fTempPacket.dts += framesTimeInterval;
// Start time of fTempPacket is updated in case the fTempPacket
// contains more audio frames to decode.
} }
@@ -952,7 +962,8 @@ AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
After this function returns successfully the caller can safely make the After this function returns successfully the caller can safely make the
following assumptions: following assumptions:
1. fDecodedDataBufferSize is greater than zero. 1. fDecodedDataBufferSize is greater than zero.
2. fDecodedDataBuffer contains audio frames. 2. fDecodedDataBufferOffset is set to zero.
3. fDecodedDataBuffer contains audio frames.
\returns B_OK on successfully decoding one audio frame chunk. \returns B_OK on successfully decoding one audio frame chunk.
\returns B_LAST_BUFFER_ERROR No more audio frame chunks available. From \returns B_LAST_BUFFER_ERROR No more audio frame chunks available. From
@@ -964,7 +975,7 @@ AVCodecDecoder::_DecodeNextAudioFrameChunk()
{ {
assert(fDecodedDataBufferSize == 0); assert(fDecodedDataBufferSize == 0);
while (fDecodedDataBufferSize == 0) { while(fDecodedDataBufferSize == 0) {
status_t loadingChunkStatus status_t loadingChunkStatus
= _LoadNextChunkIfNeededAndAssignStartTime(); = _LoadNextChunkIfNeededAndAssignStartTime();
if (loadingChunkStatus != B_OK) if (loadingChunkStatus != B_OK)
@@ -1011,6 +1022,7 @@ AVCodecDecoder::_DecodeNextAudioFrameChunk()
Also see "Note" below. Also see "Note" below.
2. fTempPacket was updated to exclude the data chunk that was consumed 2. fTempPacket was updated to exclude the data chunk that was consumed
by avcodec_decode_audio4(). by avcodec_decode_audio4().
3. fDecodedDataBufferOffset is set to zero.
When this function failed to decode at least one audio frame due to a When this function failed to decode at least one audio frame due to a
decoding error the caller can safely make the following assumptions: decoding error the caller can safely make the following assumptions:
@@ -1037,6 +1049,7 @@ AVCodecDecoder::_DecodeSomeAudioFramesIntoEmptyDecodedDataBuffer()
assert(fTempPacket.size > 0); assert(fTempPacket.size > 0);
avcodec_get_frame_defaults(fDecodedDataBuffer); avcodec_get_frame_defaults(fDecodedDataBuffer);
fDecodedDataBufferOffset = 0;
int gotAudioFrame = 0; int gotAudioFrame = 0;
int encodedDataSizeInBytes = avcodec_decode_audio4(fContext, int encodedDataSizeInBytes = avcodec_decode_audio4(fContext,
@@ -4,7 +4,6 @@
* Copyright (C) 2001 Axel Dörfler. * Copyright (C) 2001 Axel Dörfler.
* Copyright (C) 2004 Marcus Overhagen. * Copyright (C) 2004 Marcus Overhagen.
* Copyright (C) 2009 Stephan Aßmus <[email protected]>. * Copyright (C) 2009 Stephan Aßmus <[email protected]>.
* Copyright (C) 2015 Adrien Destugues <[email protected]>.
* *
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@@ -13,17 +12,13 @@
//! libavcodec based decoder for Haiku //! libavcodec based decoder for Haiku
#include <MediaFormats.h> #include <MediaFormats.h>
extern "C" { extern "C" {
#include "avcodec.h" #include "avcodec.h"
#include "swresample.h"
#include "swscale.h" #include "swscale.h"
} }
#include "DecoderPlugin.h" #include "DecoderPlugin.h"
#include "ReaderPlugin.h" #include "ReaderPlugin.h"
@@ -108,7 +103,6 @@ private:
// FFmpeg related members // FFmpeg related members
AVCodec* fCodec; AVCodec* fCodec;
AVCodecContext* fContext; AVCodecContext* fContext;
SwrContext* fResampleContext;
uint8_t* fDecodedData; uint8_t* fDecodedData;
size_t fDecodedDataSizeInBytes; size_t fDecodedDataSizeInBytes;
AVFrame* fPostProcessedDecodedPicture; AVFrame* fPostProcessedDecodedPicture;
@@ -118,9 +112,7 @@ private:
bool fCodecInitDone; bool fCodecInitDone;
gfx_convert_func fFormatConversionFunc; gfx_convert_func fFormatConversionFunc;
#if USE_SWS_FOR_COLOR_SPACE_CONVERSION
SwsContext* fSwsContext; SwsContext* fSwsContext;
#endif
char* fExtraData; char* fExtraData;
int fExtraDataSize; int fExtraDataSize;
@@ -137,6 +129,7 @@ private:
bool fAudioDecodeError; bool fAudioDecodeError;
AVFrame* fDecodedDataBuffer; AVFrame* fDecodedDataBuffer;
int32 fDecodedDataBufferOffset;
int32 fDecodedDataBufferSize; int32 fDecodedDataBufferSize;
AVPacket fTempPacket; AVPacket fTempPacket;
-1
View File
@@ -47,7 +47,6 @@ for architectureObject in [ MultiArchSubDirSetup ] {
UseHeaders [ FDirName $(ffmpegHeaders) libavformat ] ; UseHeaders [ FDirName $(ffmpegHeaders) libavformat ] ;
UseHeaders [ FDirName $(ffmpegHeaders) libavutil ] ; UseHeaders [ FDirName $(ffmpegHeaders) libavutil ] ;
UseHeaders [ FDirName $(ffmpegHeaders) libswscale ] ; UseHeaders [ FDirName $(ffmpegHeaders) libswscale ] ;
UseHeaders [ FDirName $(ffmpegHeaders) libswresample ] ;
Addon [ MultiArchDefaultGristFiles ffmpeg ] : Addon [ MultiArchDefaultGristFiles ffmpeg ] :
$(sources) $(sources)