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:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user