From 5b91c91b9052e90132f1f9b2ddc0a09bb020100f Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Sat, 3 Feb 2018 02:12:39 +0000 Subject: [PATCH] Refactor and add new support in LibAvHandler Refactor list of pixel formats Add support for custom pixel formats by converting it to YUV444p --- lib/PlaYUVerFrame.cpp | 16 +-- lib/PlaYUVerFrame.h | 2 +- lib/PlaYUVerFramePixelFormats.cpp | 186 +++++++++++++++++------------- lib/PlaYUVerFramePixelFormats.h | 4 +- lib/StreamHandlerLibav.cpp | 56 +++++++-- lib/StreamHandlerLibav.h | 6 + 6 files changed, 170 insertions(+), 100 deletions(-) diff --git a/lib/PlaYUVerFrame.cpp b/lib/PlaYUVerFrame.cpp index cee5ada..aa36688 100644 --- a/lib/PlaYUVerFrame.cpp +++ b/lib/PlaYUVerFrame.cpp @@ -51,7 +51,7 @@ std::vector PlaYUVerFrame::supportedPixelFormatListNames() std::vector formatsList; for( Int i = 0; i < NUMBER_PEL_FORMATS; i++ ) { - formatsList.push_back( g_PlaYUVerPixFmtDescriptorsList[i].name ); + formatsList.push_back( g_PlaYUVerPixFmtDescriptorsMap.at( i ).name ); } return formatsList; } @@ -61,8 +61,8 @@ std::vector PlaYUVerFrame::supportedPixelFormatListNames( Int colorSpace std::vector formatsList; for( Int i = 0; i < NUMBER_PEL_FORMATS; i++ ) { - if( g_PlaYUVerPixFmtDescriptorsList[i].colorSpace == colorSpace ) - formatsList.push_back( g_PlaYUVerPixFmtDescriptorsList[i].name ); + if( g_PlaYUVerPixFmtDescriptorsMap.at( i ).colorSpace == colorSpace ) + formatsList.push_back( g_PlaYUVerPixFmtDescriptorsMap.at( i ).name ); } return formatsList; } @@ -71,7 +71,7 @@ Int PlaYUVerFrame::findPixelFormat( const String& name ) { for( Int i = 0; i < NUMBER_PEL_FORMATS; i++ ) { - if( g_PlaYUVerPixFmtDescriptorsList[i].name == name ) + if( g_PlaYUVerPixFmtDescriptorsMap.at( i ).name == name ) return i; } return -1; @@ -180,7 +180,7 @@ struct PlaYUVerFramePrivate throw PlaYUVerFailure( "PlaYUVerFrame", "Cannot create a PlYUVerFrame of this type" ); } - m_pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsList[pel_format] ); + m_pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsMap.at( pel_format ) ); m_bHasRGBPel = false; if( m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_GRAY ) @@ -259,7 +259,7 @@ PlaYUVerFrame::PlaYUVerFrame( const PlaYUVerFrame* other ) PlaYUVerFrame::PlaYUVerFrame( const PlaYUVerFrame& other, UInt x, UInt y, UInt width, UInt height ) : d( new PlaYUVerFramePrivate ) { - const PlaYUVerPixFmtDescriptor* pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsList[other.getPelFormat()] ); + const PlaYUVerPixFmtDescriptor* pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsMap.at( other.getPelFormat() ) ); if( pcPelFormat->log2ChromaWidth ) { if( x % ( 1 << pcPelFormat->log2ChromaWidth ) ) @@ -287,7 +287,7 @@ PlaYUVerFrame::PlaYUVerFrame( const PlaYUVerFrame* other, UInt posX, UInt posY, if( !other ) return; - const PlaYUVerPixFmtDescriptor* pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsList[other->getPelFormat()] ); + const PlaYUVerPixFmtDescriptor* pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsMap.at( other->getPelFormat() ) ); if( pcPelFormat->log2ChromaWidth ) { if( posX % ( 1 << pcPelFormat->log2ChromaWidth ) ) @@ -415,7 +415,7 @@ UInt64 PlaYUVerFrame::getBytesPerFrame() UInt64 PlaYUVerFrame::getBytesPerFrame( UInt uiWidth, UInt uiHeight, Int iPixelFormat, UInt bitsPixel ) { - const PlaYUVerPixFmtDescriptor* pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsList[iPixelFormat] ); + const PlaYUVerPixFmtDescriptor* pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsMap.at( iPixelFormat ) ); UInt bytesPerPixel = ( bitsPixel - 1 ) / 8 + 1; UInt64 numberBytes = uiWidth * uiHeight; if( pcPelFormat->numberChannels > 1 ) diff --git a/lib/PlaYUVerFrame.h b/lib/PlaYUVerFrame.h index 9385116..79aae46 100644 --- a/lib/PlaYUVerFrame.h +++ b/lib/PlaYUVerFrame.h @@ -53,8 +53,8 @@ public: { NO_FMT = -1, YUV420p = 0, - YUV444p, YUV422p, + YUV444p, YUYV422, GRAY, RGBp, diff --git a/lib/PlaYUVerFramePixelFormats.cpp b/lib/PlaYUVerFramePixelFormats.cpp index 9e68b45..22495eb 100644 --- a/lib/PlaYUVerFramePixelFormats.cpp +++ b/lib/PlaYUVerFramePixelFormats.cpp @@ -198,113 +198,137 @@ Void fillARGB32bufferYUV420p( Pel*** in, UChar* out, UInt width, UInt height, UI } #endif -const PlaYUVerPixFmtDescriptor g_PlaYUVerPixFmtDescriptorsList[PlaYUVerFrame::NUMBER_PEL_FORMATS] = { +const std::map g_PlaYUVerPixFmtDescriptorsMap = { { - "YUV420p", - PlaYUVerPixel::COLOR_YUV, - 3, - 3, - 1, - 1, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV420P ), + PlaYUVerFrame::YUV420p, { - {0, 0, 1}, /* Y */ - {1, 0, 1}, /* U */ - {2, 0, 1}, /* V */ + "YUV420p", + PlaYUVerPixel::COLOR_YUV, + 3, + 3, + 1, + 1, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV420P ), + { + {0, 0, 1}, /* Y */ + {1, 0, 1}, /* U */ + {2, 0, 1}, /* V */ + }, }, }, { - "YUV422p", - PlaYUVerPixel::COLOR_YUV, - 3, - 3, - 1, - 0, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV422P ), + PlaYUVerFrame::YUV422p, { - {0, 0, 1}, /* Y */ - {1, 0, 1}, /* U */ - {2, 0, 1}, /* V */ + "YUV422p", + PlaYUVerPixel::COLOR_YUV, + 3, + 3, + 1, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV422P ), + { + {0, 0, 1}, /* Y */ + {1, 0, 1}, /* U */ + {2, 0, 1}, /* V */ + }, }, }, { - "YUV444p", - PlaYUVerPixel::COLOR_YUV, - 3, - 3, - 0, - 0, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV444P ), + PlaYUVerFrame::YUV444p, { - {0, 0, 1}, /* Y */ - {1, 0, 1}, /* U */ - {2, 0, 1}, /* V */ + "YUV444p", + PlaYUVerPixel::COLOR_YUV, + 3, + 3, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUV444P ), + { + {0, 0, 1}, /* Y */ + {1, 0, 1}, /* U */ + {2, 0, 1}, /* V */ + }, }, }, { - "YUYV422", - PlaYUVerPixel::COLOR_YUV, - 3, - 1, - 1, - 0, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUYV422 ), + PlaYUVerFrame::YUYV422, { - {0, 1, 1}, /* Y */ - {0, 3, 2}, /* U */ - {0, 3, 4}, /* V */ + "YUYV422", + PlaYUVerPixel::COLOR_YUV, + 3, + 1, + 1, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_YUYV422 ), + { + {0, 1, 1}, /* Y */ + {0, 3, 2}, /* U */ + {0, 3, 4}, /* V */ + }, }, }, { - "GRAY", - PlaYUVerPixel::COLOR_GRAY, - 1, - 1, - 0, - 0, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_GRAY8 ), - {{0, 0, 1}}, /* Y */ - }, - { - "RGBp", - PlaYUVerPixel::COLOR_RGB, - 3, - 3, - 0, - 0, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_NONE ), + PlaYUVerFrame::GRAY, { - {0, 0, 1}, /* R */ - {1, 0, 1}, /* G */ - {2, 0, 1}, /* B */ + "GRAY", + PlaYUVerPixel::COLOR_GRAY, + 1, + 1, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_GRAY8 ), + {{0, 0, 1}}, /* Y */ }, }, { - "RGB", - PlaYUVerPixel::COLOR_RGB, - 3, - 1, - 0, - 0, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_RGB24 ), + PlaYUVerFrame::RGBp, { - {0, 2, 1}, /* R */ - {0, 2, 2}, /* G */ - {0, 2, 3}, /* B */ + "RGBp", + PlaYUVerPixel::COLOR_RGB, + 3, + 3, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_NONE ), + { + {0, 0, 1}, /* R */ + {1, 0, 1}, /* G */ + {2, 0, 1}, /* B */ + }, }, }, { - "BGR", - PlaYUVerPixel::COLOR_RGB, - 3, - 1, - 0, - 0, - ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_BGR24 ), + PlaYUVerFrame::RGB24, { - {0, 2, 3}, /* B */ - {0, 2, 1}, /* R */ - {0, 2, 2}, /* G */ + "RGB", + PlaYUVerPixel::COLOR_RGB, + 3, + 1, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_RGB24 ), + { + {0, 2, 1}, /* R */ + {0, 2, 2}, /* G */ + {0, 2, 3}, /* B */ + }, + }, + }, + { + PlaYUVerFrame::BGR24, + { + "BGR", + PlaYUVerPixel::COLOR_RGB, + 3, + 1, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_BGR24 ), + { + {0, 2, 3}, /* R */ + {0, 2, 2}, /* G */ + {0, 2, 1}, /* B */ + }, }, }, }; diff --git a/lib/PlaYUVerFramePixelFormats.h b/lib/PlaYUVerFramePixelFormats.h index db6a852..2ec74a0 100644 --- a/lib/PlaYUVerFramePixelFormats.h +++ b/lib/PlaYUVerFramePixelFormats.h @@ -29,6 +29,8 @@ #include "PlaYUVerFrame.h" #include "PlaYUVerPixel.h" +#include + #define CHROMA_RESAMPLING( X ) ( ( ( X + 1 ) >> 1 ) << 1 ) #define CHROMARATIO( SIZE, RATIO ) ( RATIO > 1 ? ( ( SIZE + 1 ) / RATIO ) : SIZE ) @@ -109,6 +111,6 @@ typedef struct PlaYUVerPixFmtDescriptor #define MAX_NUMBER_PLANES 3 -extern const PlaYUVerPixFmtDescriptor g_PlaYUVerPixFmtDescriptorsList[]; +extern const std::map g_PlaYUVerPixFmtDescriptorsMap; #endif // __PLAYUVERFRAMEPIXELFORMATS_H__ diff --git a/lib/StreamHandlerLibav.cpp b/lib/StreamHandlerLibav.cpp index 76067c7..5eb2cca 100644 --- a/lib/StreamHandlerLibav.cpp +++ b/lib/StreamHandlerLibav.cpp @@ -164,8 +164,6 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) m_uiHeight = m_cStream->codec->height; #endif - m_uiFrameBufferSize = av_image_get_buffer_size( AVPixelFormat( m_ffPixFmt ), m_uiWidth, m_uiHeight, 1 ); - m_strFormatName = uppercase( strFilename.substr( strFilename.find_last_of( "." ) + 1 ) ); const char* name = avcodec_get_name( m_cCodedCtx->codec_id ); m_strCodecName = name; @@ -174,8 +172,9 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) m_uiBitsPerPixel = 8; /** - * Auxiliar conversation to re-use similar pixfmt - */ + * Auxiliar conversation to re-use similar pixfmt + */ + m_bRequiresConvertion = false; Int auxPixFmt = m_ffPixFmt; switch( m_ffPixFmt ) { @@ -202,7 +201,7 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) m_iPixelFormat = PlaYUVerFrame::NO_FMT; for( Int i = 0; i < PlaYUVerFrame::NUMBER_PEL_FORMATS; i++ ) { - if( g_PlaYUVerPixFmtDescriptorsList[i].ffmpegPelFormat == auxPixFmt ) + if( g_PlaYUVerPixFmtDescriptorsMap.at( i ).ffmpegPelFormat == auxPixFmt ) { m_iPixelFormat = i; break; @@ -210,8 +209,11 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) } if( m_iPixelFormat == PlaYUVerFrame::NO_FMT ) { - throw PlaYUVerFailure( "Cannot open file using FFmpeg libs - unsupported pixel format" ); - return false; + Int newPelFmt = PlaYUVerFrame::findPixelFormat( "YUV444p" ); + m_iPixelFormat = newPelFmt; + m_bRequiresConvertion = true; + //throw PlaYUVerFailure( "StreamHandlerLibav", "Cannot open file using FFmpeg libs - unsupported pixel format" ); + //return false; } Double fr = 30; @@ -248,6 +250,34 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) return false; } + if( m_bRequiresConvertion ) + { + AVPixelFormat newAvFmt = AVPixelFormat( g_PlaYUVerPixFmtDescriptorsMap.at( m_iPixelFormat ).ffmpegPelFormat ); + + /* create scaling context */ + m_ScalerCtx = sws_getContext( m_uiWidth, m_uiHeight, AVPixelFormat( m_ffPixFmt ), + m_uiWidth, m_uiHeight, newAvFmt, + SWS_BILINEAR, NULL, NULL, NULL ); + + m_cConvertedFrame = av_frame_alloc(); + if( !m_cConvertedFrame ) + { + closeHandler(); + return false; + } + + if( av_image_alloc( m_cConvertedFrame->data, m_cConvertedFrame->linesize, + m_uiWidth, m_uiHeight, newAvFmt, 1 ) < 0 ) + { + closeHandler(); + return false; + } + + m_ffPixFmt = newAvFmt; + } + + m_uiFrameBufferSize = av_image_get_buffer_size( AVPixelFormat( m_ffPixFmt ), m_uiWidth, m_uiHeight, 1 ); + /* initialize packet, set data to NULL, let the demuxer fill it */ av_init_packet( &m_cPacket ); m_cPacket.data = NULL; @@ -357,8 +387,16 @@ Bool StreamHandlerLibav::read( PlaYUVerFrame* pcFrame ) if( bGotFrame ) { - av_image_copy_to_buffer( m_pStreamBuffer, m_uiFrameBufferSize, m_cFrame->data, m_cFrame->linesize, - AVPixelFormat( m_ffPixFmt ), m_uiWidth, m_uiHeight, 1 ); + AVFrame* decFrame = m_cFrame; + if( m_bRequiresConvertion ) + { + sws_scale( m_ScalerCtx, (const uint8_t* const*)decFrame->data, decFrame->linesize, 0, + decFrame->height, (uint8_t* const*)m_cConvertedFrame->data, m_cConvertedFrame->linesize ); + + decFrame = m_cConvertedFrame; + } + av_image_copy_to_buffer( m_pStreamBuffer, m_uiFrameBufferSize, decFrame->data, + decFrame->linesize, AVPixelFormat( m_ffPixFmt ), m_uiWidth, m_uiHeight, 1 ); pcFrame->frameFromBuffer( m_pStreamBuffer, m_iEndianness ); m_uiCurrFrameFileIdx++; diff --git a/lib/StreamHandlerLibav.h b/lib/StreamHandlerLibav.h index edb1e93..54347a4 100644 --- a/lib/StreamHandlerLibav.h +++ b/lib/StreamHandlerLibav.h @@ -42,6 +42,7 @@ extern "C" { #include #include #include +#include } #include "PlaYUVerDefs.h" @@ -78,6 +79,8 @@ private: AVStream* m_cStream; Int m_iStreamIdx; + struct SwsContext* m_ScalerCtx; + AVCodecContext* m_cCodedCtx; Int m_ffPixFmt; @@ -89,6 +92,9 @@ private: UInt64 m_uiSecs; UInt64 m_uiMicroSec; + + Bool m_bRequiresConvertion; + AVFrame* m_cConvertedFrame; }; #endif // __STREAMHANDLERLIBAV_H__