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:
@@ -684,47 +684,9 @@ AVCodecDecoder::_DecodeNextAudioFrame()
|
|||||||
fTempPacket.size = 0;
|
fTempPacket.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fDecodedDataBufferSize > 0) {
|
bool decodedDataBufferHasData = fDecodedDataBufferSize > 0;
|
||||||
// We still have decoded audio frames from the last
|
if (decodedDataBufferHasData) {
|
||||||
// invokation, which start at fDecodedDataBufferOffset
|
_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes();
|
||||||
// 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.
|
|
||||||
continue;
|
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
|
/*! \brief Loads the next audio chunk into fChunkBuffer and assigns it
|
||||||
(including the start time) to fTempPacket accordingly only if
|
(including the start time) to fTempPacket accordingly only if
|
||||||
fTempPacket is empty.
|
fTempPacket is empty.
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ private:
|
|||||||
media_header* mediaHeader,
|
media_header* mediaHeader,
|
||||||
media_decode_info* info);
|
media_decode_info* info);
|
||||||
status_t _DecodeNextAudioFrame();
|
status_t _DecodeNextAudioFrame();
|
||||||
|
void _MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes();
|
||||||
status_t _LoadNextAudioChunkIfNeededAndAssignStartTime();
|
status_t _LoadNextAudioChunkIfNeededAndAssignStartTime();
|
||||||
status_t _DecodeSomeAudioFramesIntoEmptyDecodedDataBuffer();
|
status_t _DecodeSomeAudioFramesIntoEmptyDecodedDataBuffer();
|
||||||
status_t _DecodeNextVideoFrame();
|
status_t _DecodeNextVideoFrame();
|
||||||
|
|||||||
Reference in New Issue
Block a user