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