FFMPEG Plugin: Refactor out moving audio frames from buffer.

- Main reason for this refactoring is to increase readability and thus make the
  audio decode path more comprehensible.

- Added documentation for the new method accordingly.

- No functional change intended.
This commit is contained in:
Colin Günther
2014-08-22 23:34:09 +02:00
parent 7dc2773cff
commit ca5c686d93
2 changed files with 90 additions and 41 deletions
@@ -684,47 +684,9 @@ AVCodecDecoder::_DecodeNextAudioFrame()
fTempPacket.size = 0;
}
if (fDecodedDataBufferSize > 0) {
// We still have decoded audio frames from the last
// invokation, which start at fDecodedDataBufferOffset
// and are of fDecodedDataBufferSize. Copy those into the buffer,
// but not more than it can hold.
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;
memcpy(fRawDecodedAudio->data[0], fDecodedDataBuffer->data[0]
+ fDecodedDataBufferOffset, remainingSize);
bool firstAudioFramesCopiedToRawDecodedAudio
= fRawDecodedAudio->data[0] != fDecodedData;
if (!firstAudioFramesCopiedToRawDecodedAudio) {
fRawDecodedAudio->format = fDecodedDataBuffer->format;
fRawDecodedAudio->pkt_dts = fDecodedDataBuffer->pkt_dts;
// TODO: also store the following fContext fields in the
// opaque field of fRawDecodedAudio:
// - fContext->channels
// - fContext->sample_rate
// Those fields a are needed to allow the client of
// BMediaDecoder::Decode() to detect an audio format change.
}
fDecodedDataBufferOffset += remainingSize;
fDecodedDataBufferSize -= remainingSize;
fRawDecodedAudio->data[0] += remainingSize;
fRawDecodedAudio->nb_samples += frames;
// Update start times
bigtime_t framesTimeInterval = static_cast<bigtime_t>(
(1000000LL * frames) / fOutputFrameRate);
fDecodedDataBuffer->pkt_dts += framesTimeInterval;
fTempPacket.dts += framesTimeInterval;
// Note: Start time of fTempPacket is updated in case the
// fTempPacket contains more audio frames to decode.
bool decodedDataBufferHasData = fDecodedDataBufferSize > 0;
if (decodedDataBufferHasData) {
_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes();
continue;
}
@@ -768,6 +730,92 @@ AVCodecDecoder::_DecodeNextAudioFrame()
}
/*! \brief Moves audio frames from fDecodedDataBuffer to fRawDecodedAudio (and
thus to fDecodedData) and updates the start times of fRawDecodedAudio,
fDecodedDataBuffer and fTempPacket accordingly.
When moving audio frames to fRawDecodedAudio this method also makes sure
that the following important fields of fRawDecodedAudio are populated and
updated with correct values:
- fRawDecodedAudio->format: Format of first audio frame
- fRawDecodedAudio->pkt_dts: Start time of first audio frame
- fRawDecodedAudio->nb_samples: Number of audio frames
- fRawDecodedAudio->opaque: TODO: Will contain the following fields
from fContext for the first audio frame:
- fContext->channels: Channel count of first audio frame
- fContext->sample_rate: Frame rate of first audio frame
This function assumes to be called only when the following assumptions
hold true:
1. There are decoded audio frames available in fDecodedDataBuffer
meaning that fDecodedDataBufferSize is greater than zero.
2. There is space left in fRawDecodedAudio to move some audio frames
in. This means that fRawDecodedAudio has lesser audio frames than
the maximum allowed (specified by fOutputFrameCount).
3. The audio frame rate is known so that we can calculate the time
range (covered by the moved audio frames) to update the start times
accordingly.
After this function returns the caller can safely make the following
assumptions:
1. The number of decoded audio frames in fDecodedDataBuffer is
decreased though it may still be greater then zero.
2. The number of frames in fRawDecodedAudio has increased and all
important fields are updated (see listing above).
3. Start times of fDecodedDataBuffer and fTempPacket were increased
with the time range covered by the moved audio frames.
Note: This function raises an exception (by calling the debugger), when
fDecodedDataBufferSize is not a multiple of fOutputFrameSize.
*/
void
AVCodecDecoder::_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes()
{
assert(fDecodedDataBufferSize > 0);
assert(fRawDecodedAudio->nb_samples < fOutputFrameCount);
assert(fOutputFrameRate > 0);
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;
memcpy(fRawDecodedAudio->data[0], fDecodedDataBuffer->data[0]
+ fDecodedDataBufferOffset, remainingSize);
bool firstAudioFramesCopiedToRawDecodedAudio
= fRawDecodedAudio->data[0] != fDecodedData;
if (!firstAudioFramesCopiedToRawDecodedAudio) {
fRawDecodedAudio->format = fDecodedDataBuffer->format;
fRawDecodedAudio->pkt_dts = fDecodedDataBuffer->pkt_dts;
// TODO: also store the following fContext fields in the
// opaque field of fRawDecodedAudio:
// - fContext->channels
// - fContext->sample_rate
// Those fields a are needed to allow the client of
// BMediaDecoder::Decode() to detect an audio format change.
}
fRawDecodedAudio->data[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.
}
/*! \brief Loads the next audio chunk into fChunkBuffer and assigns it
(including the start time) to fTempPacket accordingly only if
fTempPacket is empty.
@@ -61,6 +61,7 @@ private:
media_header* mediaHeader,
media_decode_info* info);
status_t _DecodeNextAudioFrame();
void _MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes();
status_t _LoadNextAudioChunkIfNeededAndAssignStartTime();
status_t _DecodeSomeAudioFramesIntoEmptyDecodedDataBuffer();
status_t _DecodeNextVideoFrame();