FFMPEG Plugin: Fix performance regression on video path.

- For best performance the color conversion function expects a memory location
  aligned to 32 bytes. Without that alignment the color conversion function
  falls back to a slower conversion path. This fix was measured via
  DO_PROFILING and tested with various 1080p video files.
This commit is contained in:
Colin Günther
2014-08-25 14:33:41 +02:00
parent 1c5f18308c
commit fe1eb3c1c1
2 changed files with 29 additions and 11 deletions
@@ -1172,7 +1172,9 @@ AVCodecDecoder::_DecodeNextVideoFrame()
bigtime_t formatConversionStart = system_time(); bigtime_t formatConversionStart = system_time();
#endif #endif
_HandleNewVideoFrameAndUpdateSystemState(); status_t handleStatus = _HandleNewVideoFrameAndUpdateSystemState();
if (handleStatus != B_OK)
return handleStatus;
#if DO_PROFILING #if DO_PROFILING
bigtime_t doneTime = system_time(); bigtime_t doneTime = system_time();
@@ -1360,12 +1362,17 @@ AVCodecDecoder::_CopyChunkToChunkBufferAndAddPadding(const void* chunk,
\see _UpdateMediaHeaderForVideoFrame() and \see _UpdateMediaHeaderForVideoFrame() and
\see _DeinterlaceAndColorConvertVideoFrame() for when you are allowed to \see _DeinterlaceAndColorConvertVideoFrame() for when you are allowed to
call this method. call this method.
\returns B_OK when video frame was handled successfully
\returnb B_NO_MEMORY when no memory is left for correct operation.
*/ */
void status_t
AVCodecDecoder::_HandleNewVideoFrameAndUpdateSystemState() AVCodecDecoder::_HandleNewVideoFrameAndUpdateSystemState()
{ {
_UpdateMediaHeaderForVideoFrame(); _UpdateMediaHeaderForVideoFrame();
_DeinterlaceAndColorConvertVideoFrame(); status_t postProcessStatus = _DeinterlaceAndColorConvertVideoFrame();
if (postProcessStatus != B_OK)
return postProcessStatus;
ConvertAVCodecContextToVideoFrameRate(*fContext, fOutputFrameRate); ConvertAVCodecContextToVideoFrameRate(*fContext, fOutputFrameRate);
@@ -1374,6 +1381,8 @@ AVCodecDecoder::_HandleNewVideoFrameAndUpdateSystemState()
#endif #endif
fFrame++; fFrame++;
return B_OK;
} }
@@ -1393,6 +1402,8 @@ AVCodecDecoder::_HandleNewVideoFrameAndUpdateSystemState()
\returns B_LAST_BUFFER_ERROR No video frame left. \returns B_LAST_BUFFER_ERROR No video frame left.
The client of the AVCodecDecoder should stop calling it now. The client of the AVCodecDecoder should stop calling it now.
\returns B_NO_MEMORY No memory left for correct operation.
*/ */
status_t status_t
AVCodecDecoder::_FlushOneVideoFrameFromDecoderBuffer() AVCodecDecoder::_FlushOneVideoFrameFromDecoderBuffer()
@@ -1413,9 +1424,7 @@ AVCodecDecoder::_FlushOneVideoFrameFromDecoderBuffer()
return B_LAST_BUFFER_ERROR; return B_LAST_BUFFER_ERROR;
} }
_HandleNewVideoFrameAndUpdateSystemState(); return _HandleNewVideoFrameAndUpdateSystemState();
return B_OK;
} }
@@ -1487,8 +1496,11 @@ AVCodecDecoder::_UpdateMediaHeaderForVideoFrame()
When this function finishes the postprocessed video frame will be available When this function finishes the postprocessed video frame will be available
in fPostProcessedDecodedPicture and fDecodedData (fDecodedDataSizeInBytes in fPostProcessedDecodedPicture and fDecodedData (fDecodedDataSizeInBytes
will be set accordingly). will be set accordingly).
\returns B_OK video frame successfully deinterlaced and color converted.
\returns B_NO_MEMORY Not enough memory available for correct operation.
*/ */
void status_t
AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame() AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
{ {
int displayWidth = fRawDecodedPicture->width; int displayWidth = fRawDecodedPicture->width;
@@ -1534,9 +1546,13 @@ AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
fDecodedDataSizeInBytes = fHeader.size_used; fDecodedDataSizeInBytes = fHeader.size_used;
if (fDecodedData == NULL) {
const size_t kOptimalAlignmentForColorConversion = 32;
posix_memalign(reinterpret_cast<void**>(&fDecodedData),
kOptimalAlignmentForColorConversion, fDecodedDataSizeInBytes);
}
if (fDecodedData == NULL) if (fDecodedData == NULL)
fDecodedData return B_NO_MEMORY;
= static_cast<uint8_t*>(malloc(fDecodedDataSizeInBytes));
fPostProcessedDecodedPicture->data[0] = fDecodedData; fPostProcessedDecodedPicture->data[0] = fDecodedData;
fPostProcessedDecodedPicture->linesize[0] fPostProcessedDecodedPicture->linesize[0]
@@ -1586,4 +1602,6 @@ AVCodecDecoder::_DeinterlaceAndColorConvertVideoFrame()
if (fRawDecodedPicture->interlaced_frame) if (fRawDecodedPicture->interlaced_frame)
avpicture_free(&deinterlacedPicture); avpicture_free(&deinterlacedPicture);
return B_OK;
} }
@@ -75,10 +75,10 @@ private:
status_t _LoadNextChunkIfNeededAndAssignStartTime(); status_t _LoadNextChunkIfNeededAndAssignStartTime();
status_t _CopyChunkToChunkBufferAndAddPadding(const void* chunk, status_t _CopyChunkToChunkBufferAndAddPadding(const void* chunk,
size_t chunkSize); size_t chunkSize);
void _HandleNewVideoFrameAndUpdateSystemState(); status_t _HandleNewVideoFrameAndUpdateSystemState();
status_t _FlushOneVideoFrameFromDecoderBuffer(); status_t _FlushOneVideoFrameFromDecoderBuffer();
void _UpdateMediaHeaderForVideoFrame(); void _UpdateMediaHeaderForVideoFrame();
void _DeinterlaceAndColorConvertVideoFrame(); status_t _DeinterlaceAndColorConvertVideoFrame();
media_header fHeader; media_header fHeader;