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) 2009 Stephan Amßus <[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.
*/
//! libavcodec based decoder for Haiku
#include "AVCodecDecoder.h"
#include <new>
@@ -89,7 +87,6 @@ AVCodecDecoder::AVCodecDecoder()
fIsAudio(false),
fCodec(NULL),
fContext(avcodec_alloc_context3(NULL)),
fResampleContext(NULL),
fDecodedData(NULL),
fDecodedDataSizeInBytes(0),
fPostProcessedDecodedPicture(avcodec_alloc_frame()),
@@ -118,6 +115,7 @@ AVCodecDecoder::AVCodecDecoder()
fAudioDecodeError(false),
fDecodedDataBuffer(avcodec_alloc_frame()),
fDecodedDataBufferOffset(0),
fDecodedDataBufferSize(0)
{
TRACE("AVCodecDecoder::AVCodecDecoder()\n");
@@ -146,7 +144,6 @@ AVCodecDecoder::~AVCodecDecoder()
if (fCodecInitDone)
avcodec_close(fContext);
swr_free(&fResampleContext);
free(fChunkBuffer);
free(fDecodedData);
@@ -232,7 +229,8 @@ AVCodecDecoder::Setup(media_format* ioEncodedFormat, const void* infoBuffer,
} else {
if (fIsAudio) {
fBlockAlign
= ioEncodedFormat->u.encoded_audio.output.buffer_size;
= ioEncodedFormat->u.encoded_audio.output
.buffer_size;
TRACE(" using buffer_size as block align: %d\n",
fBlockAlign);
}
@@ -272,6 +270,7 @@ AVCodecDecoder::SeekedTo(int64 frame, bigtime_t time)
free(fChunkBuffer);
fChunkBuffer = NULL;
fChunkBufferSize = 0;
fDecodedDataBufferOffset = 0;
fDecodedDataBufferSize = 0;
fDecodedDataSizeInBytes = 0;
@@ -359,6 +358,7 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat)
fChunkBuffer = NULL;
fChunkBufferSize = 0;
fAudioDecodeError = false;
fDecodedDataBufferOffset = 0;
fDecodedDataBufferSize = 0;
_ResetTempPacket();
@@ -405,13 +405,6 @@ 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);
TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, "
"output frame size: %d, count: %ld, rate: %.2f\n",
fContext->bit_rate, fContext->sample_rate, fContext->channels,
@@ -901,20 +894,24 @@ AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
assert(fRawDecodedAudio->nb_samples < fOutputFrameCount);
assert(fOutputFrameRate > 0);
// Some decoders do not support format conversion on themselves, or use
// "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)
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");
int32 frames = min_c(fOutputFrameCount - fRawDecodedAudio->nb_samples,
fDecodedDataBufferSize / fOutputFrameSize);
if (frames == 0)
debugger("fDecodedDataBufferSize not multiple of frame size!");
size_t remainingSize = frames * fOutputFrameSize;
// libswresample handles all the buffering for us, how nice of them!
fDecodedDataBufferSize = 0;
#if 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
= fRawDecodedAudio->data[0] != fDecodedData;
@@ -931,6 +928,19 @@ AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
fRawDecodedAudio->data[0] += remainingSize;
fRawDecodedAudio->linesize[0] += remainingSize;
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
following assumptions:
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_LAST_BUFFER_ERROR No more audio frame chunks available. From
@@ -964,7 +975,7 @@ AVCodecDecoder::_DecodeNextAudioFrameChunk()
{
assert(fDecodedDataBufferSize == 0);
while (fDecodedDataBufferSize == 0) {
while(fDecodedDataBufferSize == 0) {
status_t loadingChunkStatus
= _LoadNextChunkIfNeededAndAssignStartTime();
if (loadingChunkStatus != B_OK)
@@ -1011,6 +1022,7 @@ AVCodecDecoder::_DecodeNextAudioFrameChunk()
Also see "Note" below.
2. fTempPacket was updated to exclude the data chunk that was consumed
by avcodec_decode_audio4().
3. fDecodedDataBufferOffset is set to zero.
When this function failed to decode at least one audio frame due to a
decoding error the caller can safely make the following assumptions:
@@ -1037,6 +1049,7 @@ AVCodecDecoder::_DecodeSomeAudioFramesIntoEmptyDecodedDataBuffer()
assert(fTempPacket.size > 0);
avcodec_get_frame_defaults(fDecodedDataBuffer);
fDecodedDataBufferOffset = 0;
int gotAudioFrame = 0;
int encodedDataSizeInBytes = avcodec_decode_audio4(fContext,
@@ -4,7 +4,6 @@
* Copyright (C) 2001 Axel Dörfler.
* Copyright (C) 2004 Marcus Overhagen.
* 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.
*/
@@ -13,17 +12,13 @@
//! libavcodec based decoder for Haiku
#include <MediaFormats.h>
extern "C" {
#include "avcodec.h"
#include "swresample.h"
#include "swscale.h"
}
#include "DecoderPlugin.h"
#include "ReaderPlugin.h"
@@ -108,7 +103,6 @@ private:
// FFmpeg related members
AVCodec* fCodec;
AVCodecContext* fContext;
SwrContext* fResampleContext;
uint8_t* fDecodedData;
size_t fDecodedDataSizeInBytes;
AVFrame* fPostProcessedDecodedPicture;
@@ -118,9 +112,7 @@ private:
bool fCodecInitDone;
gfx_convert_func fFormatConversionFunc;
#if USE_SWS_FOR_COLOR_SPACE_CONVERSION
SwsContext* fSwsContext;
#endif
char* fExtraData;
int fExtraDataSize;
@@ -137,6 +129,7 @@ private:
bool fAudioDecodeError;
AVFrame* fDecodedDataBuffer;
int32 fDecodedDataBufferOffset;
int32 fDecodedDataBufferSize;
AVPacket fTempPacket;
-1
View File
@@ -47,7 +47,6 @@ for architectureObject in [ MultiArchSubDirSetup ] {
UseHeaders [ FDirName $(ffmpegHeaders) libavformat ] ;
UseHeaders [ FDirName $(ffmpegHeaders) libavutil ] ;
UseHeaders [ FDirName $(ffmpegHeaders) libswscale ] ;
UseHeaders [ FDirName $(ffmpegHeaders) libswresample ] ;
Addon [ MultiArchDefaultGristFiles ffmpeg ] :
$(sources)