FFMPEG Plugin: Fix bug and refactor input buffer padding.

- Fixes a bug using realloc with a memory area that is declared const which
  lead to a crash in MediaPlayer playing big_buck_bunny_720p_stereo.ogg.
- The refactoring introduces a strict separation between const memory areas
  (chunk data read from GetNextChunk()) and mutable memory areas
  (fVideoChunkBuffer) by using a copy operation instead of a casted
  assignment operation.
- Updated documentation accordingly.
- Besides fixing the bug, there is no functional change intended.
This commit is contained in:
Colin Günther 2014-08-06 00:25:37 +02:00
parent 6defcb6c6d
commit 6063c02ef9
2 changed files with 35 additions and 22 deletions

View File

@ -267,6 +267,7 @@ AVCodecDecoder::SeekedTo(int64 frame, bigtime_t time)
free(fVideoChunkBuffer);
// TODO: Replace with fChunkBuffer, once audio path is
// responsible for freeing the chunk buffer, too.
fVideoChunkBuffer = NULL;
fChunkBuffer = NULL;
fChunkBufferOffset = 0;
fChunkBufferSize = 0;
@ -854,14 +855,9 @@ AVCodecDecoder::_LoadNextVideoChunkIfNeededAndUpdateStartTime()
if (getNextChunkStatus != B_OK)
return getNextChunkStatus;
fChunkBufferSize = chunkBufferSize;
free(fVideoChunkBuffer);
// Free any previously used chunk buffer first
fVideoChunkBuffer
= static_cast<uint8_t*>(const_cast<void*>(chunkBuffer));
status_t chunkBufferPaddingStatus
= _AddInputBufferPaddingToVideoChunkBuffer();
= _CopyChunkToVideoChunkBufferAndAddPadding(chunkBuffer,
chunkBufferSize);
if (chunkBufferPaddingStatus != B_OK)
return chunkBufferPaddingStatus;
@ -906,35 +902,51 @@ AVCodecDecoder::_LoadNextVideoChunkIfNeededAndUpdateStartTime()
}
/*! \brief Adds a "safety net" of additional memory to fVideoChunkBuffer as
required by FFMPEG for input buffers to video decoders.
/*! \brief Copies a chunk into fVideoChunkBuffer and adds a "safety net" of
additional memory as required by FFMPEG for input buffers to video
decoders.
This is needed so that some decoders can read safely a predefined number of
bytes at a time for performance optimization purposes.
The additonal memory has a size of FF_INPUT_BUFFER_PADDING_SIZE as defined
The additional memory has a size of FF_INPUT_BUFFER_PADDING_SIZE as defined
in avcodec.h.
Ownership of fVideoChunkBuffer memory is with the class so it needs to be
freed at the right times (on destruction, on seeking).
Also update fChunkBufferSize to reflect the size of the contained video
data (leaving out the padding).
\param chunk The chunk to copy.
\param chunkSize Size of the chunk in bytes
\returns B_OK Padding was successful. You are responsible for releasing the
allocated memory.
\returns B_NO_MEMORY Padding failed. The memory in fVideoChunkBuffer is not
freed. NULL is assigned to fVideoChunkBuffer.
allocated memory. fChunkBufferSize is set to chunkSize.
\returns B_NO_MEMORY Padding failed.
fVideoChunkBuffer is set to NULL making it safe to call free() on it.
fChunkBufferSize is set to 0 to reflect the size of fVideoChunkBuffer.
*/
status_t
AVCodecDecoder::_AddInputBufferPaddingToVideoChunkBuffer()
AVCodecDecoder::_CopyChunkToVideoChunkBufferAndAddPadding(const void* chunk,
size_t chunkSize)
{
// TODO: Rename fVideoChunkBuffer to fChunkBuffer, once the audio path is
// responsible for releasing the chunk buffer, too.
fVideoChunkBuffer
= static_cast<uint8_t*>(realloc(static_cast<void*>(fVideoChunkBuffer),
fChunkBufferSize + FF_INPUT_BUFFER_PADDING_SIZE));
if (fVideoChunkBuffer == NULL)
return B_NO_MEMORY;
memset(fVideoChunkBuffer + fChunkBufferSize, 0,
FF_INPUT_BUFFER_PADDING_SIZE);
fVideoChunkBuffer = static_cast<uint8_t*>(realloc(fVideoChunkBuffer,
chunkSize + FF_INPUT_BUFFER_PADDING_SIZE));
if (fVideoChunkBuffer == NULL) {
fChunkBufferSize = 0;
return B_NO_MEMORY;
}
memcpy(fVideoChunkBuffer, chunk, chunkSize);
memset(fVideoChunkBuffer + chunkSize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
// Establish safety net, by zero'ing the padding area.
fChunkBufferSize = chunkSize;
return B_OK;
}

View File

@ -65,7 +65,8 @@ private:
// TODO: Remove the "Video" word once
// the audio path is responsible for
// freeing the chunk buffer, too.
status_t _AddInputBufferPaddingToVideoChunkBuffer();
status_t _CopyChunkToVideoChunkBufferAndAddPadding(
const void* chunk, size_t chunkSize);
// TODO: Remove the "Video" word once
// the audio path is responsible for
// freeing the chunk buffer, too.