FFMPEG Plugin: Refactor scope of fTempPacket in audio path.

- There are two main reasons for this refactoring:
    1. Prepare using FFMPEGs functionality of audio frame start time assignment
       (instead of rolling it ourself) like already done for the video path
       (see _LoadNextVideoChunkIfNeededAndAssignStartTime() for reference).
    2. Get rid of fChunkBufferOffset (this is a minor reason though).

- Untangle some of the conditional checks to increase readability.

- No functional change intended.
This commit is contained in:
Colin Günther
2014-08-21 00:47:06 +02:00
parent 3bca609810
commit b82ef8bc15
2 changed files with 40 additions and 37 deletions
@@ -107,7 +107,6 @@ AVCodecDecoder::AVCodecDecoder()
fChunkBuffer(NULL), fChunkBuffer(NULL),
fVideoChunkBuffer(NULL), fVideoChunkBuffer(NULL),
fChunkBufferOffset(0),
fChunkBufferSize(0), fChunkBufferSize(0),
fAudioDecodeError(false), fAudioDecodeError(false),
@@ -269,7 +268,6 @@ AVCodecDecoder::SeekedTo(int64 frame, bigtime_t time)
// responsible for freeing the chunk buffer, too. // responsible for freeing the chunk buffer, too.
fVideoChunkBuffer = NULL; fVideoChunkBuffer = NULL;
fChunkBuffer = NULL; fChunkBuffer = NULL;
fChunkBufferOffset = 0;
fChunkBufferSize = 0; fChunkBufferSize = 0;
fDecodedDataBufferOffset = 0; fDecodedDataBufferOffset = 0;
fDecodedDataBufferSize = 0; fDecodedDataBufferSize = 0;
@@ -415,7 +413,6 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat)
result, fOutputFrameSize, fOutputFrameCount, fOutputFrameRate); result, fOutputFrameSize, fOutputFrameCount, fOutputFrameRate);
fChunkBuffer = NULL; fChunkBuffer = NULL;
fChunkBufferOffset = 0;
fChunkBufferSize = 0; fChunkBufferSize = 0;
fAudioDecodeError = false; fAudioDecodeError = false;
fDecodedDataBufferOffset = 0; fDecodedDataBufferOffset = 0;
@@ -665,7 +662,11 @@ AVCodecDecoder::_DecodeVideo(void* outBuffer, int64* outFrameCount,
status_t status_t
AVCodecDecoder::_DecodeNextAudioFrame() AVCodecDecoder::_DecodeNextAudioFrame()
{ {
fDecodedDataSizeInBytes = 0; assert(fTempPacket.size >= 0);
assert(fDecodedDataSizeInBytes == 0);
// _DecodeNextAudioFrame needs to be called on empty fDecodedData only!
// If this assert holds wrong we have a bug somewhere.
size_t maximumSizeOfDecodedData = fOutputFrameCount * fOutputFrameSize; size_t maximumSizeOfDecodedData = fOutputFrameCount * fOutputFrameSize;
if (fDecodedData == NULL) if (fDecodedData == NULL)
fDecodedData fDecodedData
@@ -680,10 +681,10 @@ AVCodecDecoder::_DecodeNextAudioFrame()
"buffer! %ld\n", fDecodedDataBufferSize); "buffer! %ld\n", fDecodedDataBufferSize);
fDecodedDataBufferSize = 0; fDecodedDataBufferSize = 0;
} }
if (fChunkBufferSize < 0) { if (fTempPacket.size < 0) {
fprintf(stderr, "Decoding read past the end of the chunk buffer! " fprintf(stderr, "Decoding read past the end of the temp packet! "
"%ld\n", fChunkBufferSize); "%d\n", fTempPacket.size);
fChunkBufferSize = 0; fTempPacket.size = 0;
} }
if (fDecodedDataBufferSize > 0) { if (fDecodedDataBufferSize > 0) {
@@ -705,7 +706,7 @@ AVCodecDecoder::_DecodeNextAudioFrame()
fStartTime += (bigtime_t)((1000000LL * frames) / fOutputFrameRate); fStartTime += (bigtime_t)((1000000LL * frames) / fOutputFrameRate);
continue; continue;
} }
if (fChunkBufferSize == 0) { if (fTempPacket.size == 0) {
// Time to read the next chunk buffer. We use a separate // Time to read the next chunk buffer. We use a separate
// media_header, since the chunk header may not belong to // media_header, since the chunk header may not belong to
// the start of the decoded audio frames we return. For // the start of the decoded audio frames we return. For
@@ -726,50 +727,53 @@ AVCodecDecoder::_DecodeNextAudioFrame()
fChunkBufferSize = 0; fChunkBufferSize = 0;
break; break;
} }
fChunkBufferOffset = 0; fTempPacket.data
= static_cast<uint8_t*>(const_cast<void*>(fChunkBuffer));
fTempPacket.size = fChunkBufferSize;
fStartTime = chunkMediaHeader.start_time; fStartTime = chunkMediaHeader.start_time;
} }
fTempPacket.data = (uint8_t*)fChunkBuffer + fChunkBufferOffset;
fTempPacket.size = fChunkBufferSize;
avcodec_get_frame_defaults(fDecodedDataBuffer); avcodec_get_frame_defaults(fDecodedDataBuffer);
int gotFrame = 0; int gotFrame = 0;
int usedBytes = avcodec_decode_audio4(fContext, int usedBytes = avcodec_decode_audio4(fContext,
fDecodedDataBuffer, &gotFrame, &fTempPacket); fDecodedDataBuffer, &gotFrame, &fTempPacket);
if (usedBytes < 0 && !fAudioDecodeError) { if (usedBytes < 0 && !fAudioDecodeError) {
// Report failure if not done already // Report failure if not done already
int32 chunkBufferOffset = fTempPacket.data
- static_cast<uint8_t*>(const_cast<void*>(fChunkBuffer));
printf("########### audio decode error, " printf("########### audio decode error, "
"fChunkBufferSize %ld, fChunkBufferOffset %ld\n", "fTempPacket.size %d, fChunkBuffer data offset %ld\n",
fChunkBufferSize, fChunkBufferOffset); fTempPacket.size, chunkBufferOffset);
fAudioDecodeError = true; fAudioDecodeError = true;
} }
if (usedBytes <= 0) { if (usedBytes <= 0) {
// Error or failure to produce decompressed output. // Error or failure to produce decompressed output.
// Skip the chunk buffer data entirely. // Skip the temp packet data entirely.
usedBytes = fChunkBufferSize; fTempPacket.size = 0;
fDecodedDataBufferSize = 0;
// Assume the audio decoded until now is broken. // Assume the audio decoded until now is broken.
memset(fDecodedData, 0, decodedData - fDecodedData); memset(fDecodedData, 0, decodedData - fDecodedData);
} else { fDecodedDataBufferOffset = 0;
// Success continue;
fAudioDecodeError = false;
if (gotFrame == 1) {
fDecodedDataBufferSize = av_samples_get_buffer_size(NULL,
fContext->channels, fDecodedDataBuffer->nb_samples,
fContext->sample_fmt, 1);
if (fDecodedDataBufferSize < 0)
fDecodedDataBufferSize = 0;
} else
fDecodedDataBufferSize = 0;
} }
//printf(" chunk size: %d, decoded: %d, used: %d\n",
//fTempPacket.size, decodedBytes, usedBytes);
fChunkBufferOffset += usedBytes; fAudioDecodeError = false;
fChunkBufferSize -= usedBytes; fDecodedDataBufferSize = 0;
fDecodedDataBufferOffset = 0; fDecodedDataBufferOffset = 0;
fTempPacket.data += usedBytes;
fTempPacket.size -= usedBytes;
bool gotNoAudioFrame = gotFrame == 0;
if (gotNoAudioFrame)
continue;
fDecodedDataBufferSize = av_samples_get_buffer_size(NULL,
fContext->channels, fDecodedDataBuffer->nb_samples,
fContext->sample_fmt, 1);
if (fDecodedDataBufferSize < 0)
fDecodedDataBufferSize = 0;
} }
fFrame += currentFrameCount; fFrame += currentFrameCount;
fDecodedDataSizeInBytes = currentFrameCount * fOutputFrameSize; fDecodedDataSizeInBytes = currentFrameCount * fOutputFrameSize;
TRACE_AUDIO(" frame count: %lld current: %lld\n", currentFrameCount, fFrame); TRACE_AUDIO(" frame count: %lld current: %lld\n", currentFrameCount, fFrame);
@@ -114,10 +114,9 @@ private:
const void* fChunkBuffer; const void* fChunkBuffer;
uint8_t* fVideoChunkBuffer; uint8_t* fVideoChunkBuffer;
// TODO: Remove and use fChunkBuffer again // TODO: Remove and use fChunkBuffer again
// (with type uint8_t*) once the audio path is // (with type uint8_t*) once the audio path
// responsible for freeing the chunk buffer, // is responsible for freeing the chunk
// too. // buffer, too.
int32 fChunkBufferOffset;
size_t fChunkBufferSize; size_t fChunkBufferSize;
bool fAudioDecodeError; bool fAudioDecodeError;