hrev50086 adds 1 changeset to branch 'master'
old head: 45569721aa73318762c19091b8020f1488afddaf
new head: da455572ed478293b2d7d9816b1ab44a44c9d33b
overview:
http://cgit.haiku-os.org/haiku/log/?qt=range&q=da455572ed47+%5E45569721aa73
----------------------------------------------------------------------------
da455572ed47: AVCodecDecoder: fix timing problems
A combination of two problems made things go wrong with the timestamp of
decoded audio.
1) The output buffer size is too small to hold the complete input.
swresample handles this by buffering the input for use the next time it
is called, however repeatedly doing this results in lots of buffering,
and our way to compute the output timestamp from the input does not take
it into account so it does weird things. Moreover, we would need to
empty the buffer by calling swr_convert with NULL input in that case.
Fix: make sure to not feed more data to swr_convert than it can output
in our buffer. This way, no buffering occurs, only the matrixing
conversion.
2) When using planar audio, the "frame size" is a bit different. Instead
of adding sample size * channel count to 1 pointer, we need to add
sample size * 1 to each channel buffer.
Fix: add the "fInputFrameSize" which takes this into account, instead of
misusing fOutputFrameSize for the input.
Fixes #12460.
[ Adrien Destugues <pulkomandy@xxxxxxxxx> ]
----------------------------------------------------------------------------
Revision: hrev50086
Commit: da455572ed478293b2d7d9816b1ab44a44c9d33b
URL: http://cgit.haiku-os.org/haiku/commit/?id=da455572ed47
Author: Adrien Destugues <pulkomandy@xxxxxxxxx>
Date: Sun Feb 14 10:45:13 2016 UTC
Ticket: https://dev.haiku-os.org/ticket/12460
----------------------------------------------------------------------------
2 files changed, 21 insertions(+), 3 deletions(-)
.../media/plugins/ffmpeg/AVCodecDecoder.cpp | 21 +++++++++++++++++---
.../media/plugins/ffmpeg/AVCodecDecoder.h | 3 +++
----------------------------------------------------------------------------
diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
index 99357f1..c000898 100644
--- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
+++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp
@@ -112,6 +112,7 @@ AVCodecDecoder::AVCodecDecoder()
fOutputFrameCount(0),
fOutputFrameRate(1.0),
fOutputFrameSize(0),
+ fInputFrameSize(0),
fChunkBuffer(NULL),
fChunkBufferSize(0),
@@ -403,6 +404,11 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format*
inOutFormat)
fOutputFrameSize = sampleSize * outputAudioFormat.channel_count;
fOutputFrameCount = outputAudioFormat.buffer_size / fOutputFrameSize;
fOutputFrameRate = outputAudioFormat.frame_rate;
+ if (av_sample_fmt_is_planar(fContext->sample_fmt))
+ fInputFrameSize = sampleSize;
+ else
+ fInputFrameSize = fOutputFrameSize;
+
fRawDecodedAudio->opaque
= av_realloc(fRawDecodedAudio->opaque,
sizeof(avformat_codec_context));
if (fRawDecodedAudio->opaque == NULL)
@@ -925,10 +931,19 @@
AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
ptr[i] = fDecodedDataBuffer->data[i] +
fDecodedDataBufferOffset;
}
- int32 result = swr_convert(fResampleContext,
fRawDecodedAudio->data,
+ // When there are more input frames than space in the output
buffer,
+ // we could feed everything to swr and it would buffer the
extra data.
+ // However, there is no easy way to flush that data without
feeding more
+ // input, and it makes our timestamp computations fail.
+ // So, we feed only as much frames as we can get out, and
handle the
+ // buffering ourselves.
+ // TODO Ideally, we should try to size our output buffer so
that it can
+ // always hold all the output (swr provides helper functions
for this)
+ inFrames = frames;
+ frames = swr_convert(fResampleContext, fRawDecodedAudio->data,
outFrames, ptr, inFrames);
- if (result < 0)
+ if (frames < 0)
debugger("resampling failed");
} else {
memcpy(fRawDecodedAudio->data[0], fDecodedDataBuffer->data[0]
@@ -937,7 +952,7 @@
AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
inFrames = frames;
}
- size_t remainingSize = inFrames * fOutputFrameSize;
+ size_t remainingSize = inFrames * fInputFrameSize;
size_t decodedSize = outFrames * fOutputFrameSize;
fDecodedDataBufferSize -= inFrames;
diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
index 48e6c46..b839d52 100644
--- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
+++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
@@ -131,6 +131,9 @@ private:
float fOutputFrameRate;
int
fOutputFrameSize;
//
sample size * channel count
+ int fInputFrameSize;
+ //
sample size * channel count
+ // or
just sample size for planar formats
uint8_t* fChunkBuffer;
size_t fChunkBufferSize;