From 2d6ba03d4a2df00000bd9f3a49fba11298f0629b Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Sun, 4 Feb 2018 20:32:59 +0000 Subject: [PATCH] Improve PlaYUVerPixel and add support for RGBA format Changes ColorSpace enum Add Alpha channel support in pixel class Add RGBA pixel format to the list of supported formats --- app/FramePropertiesDock.cpp | 6 +- app/VideoSubWindow.cpp | 44 ++--- app/ViewArea.cpp | 16 +- lib/PlaYUVerFrame.cpp | 168 ++++++++---------- lib/PlaYUVerFrame.h | 7 +- lib/PlaYUVerFramePixelFormats.cpp | 285 ++++++++++++++++++------------ lib/PlaYUVerFramePixelFormats.h | 2 - lib/StreamHandlerLibav.cpp | 2 +- 8 files changed, 287 insertions(+), 243 deletions(-) diff --git a/app/FramePropertiesDock.cpp b/app/FramePropertiesDock.cpp index f4edcb4..6448be4 100644 --- a/app/FramePropertiesDock.cpp +++ b/app/FramePropertiesDock.cpp @@ -295,7 +295,7 @@ Void FramePropertiesDock::setFrame( PlaYUVerFrame* pcFrame ) if( m_iLastFrameType != colorSpace ) { m_iLastFrameType = colorSpace; - if( colorSpace == PlaYUVerPixel::COLOR_RGB || colorSpace == PlaYUVerPixel::COLOR_ARGB ) + if( colorSpace == PlaYUVerPixel::COLOR_RGB || colorSpace == PlaYUVerPixel::COLOR_RGBA ) { channelCB->clear(); channelCB->clear(); @@ -303,7 +303,7 @@ Void FramePropertiesDock::setFrame( PlaYUVerFrame* pcFrame ) channelCB->insertItem( FirstChannel, QIcon( ":/images/channel-red.png" ), "Red" ); channelCB->insertItem( SecondChannel, QIcon( ":/images/channel-green.png" ), "Green" ); channelCB->insertItem( ThirdChannel, QIcon( ":/images/channel-blue.png" ), "Blue" ); - if( colorSpace == PlaYUVerPixel::COLOR_ARGB ) + if( colorSpace == PlaYUVerPixel::COLOR_RGBA ) { channelCB->insertItem( AlphaChannel, QIcon( ":/images/channel-alpha.png" ), "Alpha" ); } @@ -513,7 +513,7 @@ Void FramePropertiesDock::slotChannelChanged( Int channel ) { if( m_pcFrame->getColorSpace() == PlaYUVerPixel::COLOR_YUV ) channel += 1; - if( channel == AlphaChannel && m_pcFrame->getColorSpace() != PlaYUVerPixel::COLOR_ARGB ) + if( channel == AlphaChannel && m_pcFrame->getColorSpace() != PlaYUVerPixel::COLOR_RGBA ) channel = ColorChannels; switch( channel ) diff --git a/app/VideoSubWindow.cpp b/app/VideoSubWindow.cpp index 4ca0e50..7900e86 100644 --- a/app/VideoSubWindow.cpp +++ b/app/VideoSubWindow.cpp @@ -977,7 +977,6 @@ Void VideoSubWindow::updatePixelValueStatusBar( const QPoint& pos ) { if( m_pcCurrFrame ) { - PlaYUVerPixel sPixelValue; Int iWidth, iHeight; Int posX = pos.x(); Int posY = pos.y(); @@ -990,28 +989,33 @@ Void VideoSubWindow::updatePixelValueStatusBar( const QPoint& pos ) { strStatus = QString( "(%1,%2) " ).arg( posX ).arg( posY ); - Int ColorSpace = m_pcCurrFrame->getColorSpace(); - if( ColorSpace == PlaYUVerPixel::COLOR_GRAY ) + Int colorSpace = m_pcCurrFrame->getColorSpace(); + PlaYUVerPixel pixelValue = m_pcCurrFrame->getPixelValue( pos.x(), pos.y() ); + switch( colorSpace ) { - sPixelValue = m_pcCurrFrame->getPixelValue( pos.x(), pos.y() ); - strStatus.append( QString( "Y: %1" ).arg( sPixelValue.Y() ) ); - } - if( ColorSpace == PlaYUVerPixel::COLOR_YUV ) - { - sPixelValue = m_pcCurrFrame->getPixelValue( pos.x(), pos.y() ); + case PlaYUVerPixel::COLOR_GRAY: + strStatus.append( QString( "Y: %1" ).arg( pixelValue.Y() ) ); + break; + case PlaYUVerPixel::COLOR_YUV: strStatus.append( QString( "Y: %1 U: %2 V: %3" ) - .arg( sPixelValue.Y() ) - .arg( sPixelValue.Cb() ) - .arg( sPixelValue.Cr() ) ); - } - - if( ( ColorSpace == PlaYUVerPixel::COLOR_RGB ) ) - { - sPixelValue = m_pcCurrFrame->getPixelValue( pos.x(), pos.y() ); + .arg( pixelValue.Y() ) + .arg( pixelValue.Cb() ) + .arg( pixelValue.Cr() ) ); + break; + case PlaYUVerPixel::COLOR_RGB: strStatus.append( QString( "R: %1 G: %2 B: %3" ) - .arg( sPixelValue.R() ) - .arg( sPixelValue.G() ) - .arg( sPixelValue.B() ) ); + .arg( pixelValue.R() ) + .arg( pixelValue.G() ) + .arg( pixelValue.B() ) ); + break; + case PlaYUVerPixel::COLOR_RGBA: + strStatus.append( QString( "R: %1 G: %2 B: %3 A: %4" ) + .arg( pixelValue.R() ) + .arg( pixelValue.G() ) + .arg( pixelValue.B() ) + .arg( pixelValue.A() ) ); + + break; } emit updateStatusBar( strStatus ); } diff --git a/app/ViewArea.cpp b/app/ViewArea.cpp index 8b8a3eb..5077d52 100644 --- a/app/ViewArea.cpp +++ b/app/ViewArea.cpp @@ -541,10 +541,18 @@ Void ViewArea::paintEvent( QPaintEvent* event ) else paInter.setPen( QColor( Qt::black ) ); - paInter.drawText( pixelRect, Qt::AlignCenter, - "R: " + QString::number( sPixelValue.R() ) + "\n" + - "G: " + QString::number( sPixelValue.G() ) + "\n" + - "B: " + QString::number( sPixelValue.B() ) ); + paInter.drawText( pixelRect, Qt::AlignCenter, "R: " + QString::number( sPixelValue.R() ) + "\nG: " + QString::number( sPixelValue.G() ) + "\nB: " + QString::number( sPixelValue.B() ) ); + } + if( ( frFormat == PlaYUVerPixel::COLOR_RGBA ) ) + { + sPixelValue = m_pcCurrFrame->getPixelValue( pixelTopLeft.x(), pixelTopLeft.y() ); + + if( ( sPixelValue.R() + sPixelValue.G() + sPixelValue.B() ) < ( m_uiPixelHalfScale * 3 ) ) + paInter.setPen( QColor( Qt::white ) ); + else + paInter.setPen( QColor( Qt::black ) ); + + paInter.drawText( pixelRect, Qt::AlignCenter, "R: " + QString::number( sPixelValue.R() ) + "\nG: " + QString::number( sPixelValue.G() ) + "\nB: " + QString::number( sPixelValue.B() ) + "\nA: " + QString::number( sPixelValue.A() ) ); } } } diff --git a/lib/PlaYUVerFrame.cpp b/lib/PlaYUVerFrame.cpp index 34a879a..30ab099 100644 --- a/lib/PlaYUVerFrame.cpp +++ b/lib/PlaYUVerFrame.cpp @@ -41,13 +41,14 @@ std::vector PlaYUVerFrame::supportedColorSpacesListNames() "YUV", "RGB", "GRAY", + "ARGB", }; } std::vector PlaYUVerFrame::supportedPixelFormatListNames() { std::vector formatsList; - for( Int i = 0; i < NUMBER_PEL_FORMATS; i++ ) + for( Int i = 0; i < numberOfFormats(); i++ ) { formatsList.push_back( g_PlaYUVerPixFmtDescriptorsMap.at( i ).name ); } @@ -57,7 +58,7 @@ std::vector PlaYUVerFrame::supportedPixelFormatListNames() std::vector PlaYUVerFrame::supportedPixelFormatListNames( Int colorSpace ) { std::vector formatsList; - for( Int i = 0; i < NUMBER_PEL_FORMATS; i++ ) + for( Int i = 0; i < numberOfFormats(); i++ ) { if( g_PlaYUVerPixFmtDescriptorsMap.at( i ).colorSpace == colorSpace ) formatsList.push_back( g_PlaYUVerPixFmtDescriptorsMap.at( i ).name ); @@ -65,9 +66,14 @@ std::vector PlaYUVerFrame::supportedPixelFormatListNames( Int colorSpace return formatsList; } +Int PlaYUVerFrame::numberOfFormats() +{ + return g_PlaYUVerPixFmtDescriptorsMap.size(); +} + Int PlaYUVerFrame::findPixelFormat( const String& name ) { - for( Int i = 0; i < NUMBER_PEL_FORMATS; i++ ) + for( Int i = 0; i < numberOfFormats(); i++ ) { if( g_PlaYUVerPixFmtDescriptorsMap.at( i ).name == name ) return i; @@ -290,7 +296,7 @@ PlaYUVerPixel PlaYUVerPixel::ConvertPixel( ColorSpace eOutputSpace ) Int outA, outB, outC; PlaYUVerPixel outPixel( COLOR_INVALID, 0, 0, 0 ); - if( ColorSpace() == eOutputSpace || eOutputSpace == COLOR_ARGB || eOutputSpace == COLOR_GRAY ) + if( ColorSpace() == eOutputSpace || eOutputSpace == COLOR_RGBA || eOutputSpace == COLOR_GRAY ) return *this; if( eOutputSpace == COLOR_RGB ) @@ -310,51 +316,6 @@ PlaYUVerPixel PlaYUVerPixel::ConvertPixel( ColorSpace eOutputSpace ) return outPixel; } -static Int getImgMemory( Pel**** array3D, Int dim1, Int dim2, Int log2ChromaHeight, Int log2ChromaWidth ) -{ - Int dim0 = 3; - Int i; - UInt64 total_mem_size = 0; - UInt64 mem_size = ( dim1 * dim2 + CHROMASHIFT( dim1, log2ChromaHeight ) * CHROMASHIFT( dim2, log2ChromaWidth ) * 2 ); - - total_mem_size += getMem2D( array3D, dim0, dim1 ); - - if( ( ( *array3D )[0][0] = (Pel*)xCallocMem( mem_size, sizeof( Pel ) ) ) == NULL ) - printf( "getImgMemory: array1D" ); - - total_mem_size += mem_size * sizeof( Pel ); - - // Luma - for( i = 1; i < dim1; i++ ) - ( *array3D )[0][i] = ( *array3D )[0][i - 1] + dim2; - - // Chroma - ( *array3D )[1][0] = ( *array3D )[0][0] + dim2 * dim1; - - dim1 = CHROMASHIFT( dim1, log2ChromaHeight ); - dim2 = CHROMASHIFT( dim2, log2ChromaWidth ); - - for( i = 1; i < dim1; i++ ) - ( *array3D )[1][i] = ( *array3D )[1][i - 1] + dim2; - - ( *array3D )[2][0] = ( *array3D )[1][0] + dim2 * dim1; - for( i = 1; i < dim1; i++ ) - ( *array3D )[2][i] = ( *array3D )[2][i - 1] + dim2; - - return total_mem_size; -} - -Void freeImgMemory( Pel*** array3D ) -{ - if( array3D ) - { - if( **array3D ) - xFreeMem( **array3D ); - - freeMem2D( array3D ); - } -} - struct PlaYUVerFramePrivate { Bool m_bInit; @@ -365,12 +326,8 @@ struct PlaYUVerFramePrivate UInt m_uiWidth; //!< Width of the frame UInt m_uiHeight; //!< Height of the frame - Int m_iPixelFormat; //!< Pixel format number (it follows the list of - //!< supported - //! pixel formats) - Int m_iNumberChannels; //!< Number of channels + Int m_iPixelFormat; //!< Pixel format number (it follows the list of supported pixel formats) UInt m_uiBitsPel; //!< Bits per pixel/channel - // Int m_iEndianness; //!< Endiannes of bytes UInt m_uiHalfPelValue; //!< Bits per pixel/channel Pel*** m_pppcInputPel; @@ -389,22 +346,22 @@ struct PlaYUVerFramePrivate UInt m_uiHistoSegments; /** - * Common constructor function of a frame - * - * @param width width of the frame - * @param height height of the frame - * @param pel_format pixel format index (always use PixelFormats enum) - * - */ + * Common constructor function of a frame + * + * @param width width of the frame + * @param height height of the frame + * @param pel_format pixel format index (always use PixelFormats enum) + * + */ Void init( UInt width, UInt height, Int pel_format, Int bitsPixel ) { m_bInit = false; + m_bHasRGBPel = false; m_pppcInputPel = NULL; m_pcARGB32 = NULL; m_uiWidth = width; m_uiHeight = height; m_iPixelFormat = pel_format; - m_iNumberChannels = 3; m_uiBitsPel = bitsPixel < 8 ? 8 : bitsPixel; m_uiHalfPelValue = 1 << ( m_uiBitsPel - 1 ); @@ -414,17 +371,39 @@ struct PlaYUVerFramePrivate } m_pcPelFormat = &( g_PlaYUVerPixFmtDescriptorsMap.at( pel_format ) ); + Int iNumberChannels = m_pcPelFormat->numberChannels; - m_bHasRGBPel = false; - if( m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_GRAY ) + std::size_t mem_size = 0; + std::size_t num_of_ptrs = 0; + for( Int ch = 0; ch < iNumberChannels; ch++ ) { - getImgMemory( &m_pppcInputPel, m_uiHeight, m_uiWidth, 1, 1 ); + Int ratioW = ch > 0 ? m_pcPelFormat->log2ChromaWidth : 0; + Int ratioH = ch > 0 ? m_pcPelFormat->log2ChromaHeight : 0; + // Add pointers mem + num_of_ptrs += CHROMASHIFT( m_uiHeight, ratioH ); + // Add pixel mem + mem_size += CHROMASHIFT( m_uiHeight, ratioH ) * CHROMASHIFT( m_uiWidth, ratioW ) * sizeof( Pel ); } - else + mem_size += num_of_ptrs * sizeof( Pel* ) + sizeof( Pel** ) * iNumberChannels; + + m_pppcInputPel = (Pel***)xMallocMem( mem_size ); + + Pel** pelPtrMem = (Pel**)( m_pppcInputPel + iNumberChannels ); + Pel* pelMem = (Pel*)( pelPtrMem + num_of_ptrs ); + for( Int ch = 0; ch < iNumberChannels; ch++ ) { - getImgMemory( &m_pppcInputPel, m_uiHeight, m_uiWidth, m_pcPelFormat->log2ChromaHeight, - m_pcPelFormat->log2ChromaWidth ); + Int ratioW = ch > 0 ? m_pcPelFormat->log2ChromaWidth : 0; + Int ratioH = ch > 0 ? m_pcPelFormat->log2ChromaHeight : 0; + m_pppcInputPel[ch] = pelPtrMem; + for( UInt h = 0; h < CHROMASHIFT( m_uiHeight, ratioH ); h++ ) + { + *pelPtrMem = pelMem; + pelPtrMem++; + pelMem += CHROMASHIFT( m_uiWidth, ratioW ); + } } + + /* Alloc ARGB memory */ getMem1D( &m_pcARGB32, m_uiHeight * m_uiWidth * 4 ); m_puiHistogram = NULL; @@ -434,7 +413,7 @@ struct PlaYUVerFramePrivate m_uiHistoSegments = 1 << m_uiBitsPel; if( m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_RGB || - m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_ARGB ) + m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_RGBA ) m_uiHistoChannels = m_pcPelFormat->numberChannels + 1; else m_uiHistoChannels = m_pcPelFormat->numberChannels; @@ -455,7 +434,7 @@ struct PlaYUVerFramePrivate m_bHasHistogram = false; if( m_pppcInputPel ) - freeImgMemory( m_pppcInputPel ); + xFreeMem( m_pppcInputPel ); if( m_pcARGB32 ) freeMem1D( m_pcARGB32 ); @@ -902,6 +881,8 @@ Void PlaYUVerFrame::frameToBuffer( Byte* output_buffer, Int iEndianness ) Void PlaYUVerFrame::fillRGBBuffer() { +#define PEL_ARGB( a, r, g, b ) ( ( a & 0xff ) << 24 ) | ( ( r & 0xff ) << 16 ) | ( ( g & 0xff ) << 8 ) | ( b & 0xff ) +#define PEL_RGB( r, g, b ) PEL_ARGB( 0xffu, r, g, b ) #define CLAMP_YUV2RGB( X ) X = X < 0 ? 0 : X > 255 ? 255 : X; #define YUV2RGB( iY, iU, iV, iR, iG, iB ) \ iR = iY + ( ( 1436 * ( iV - 128 ) ) >> 10 ); \ @@ -913,21 +894,15 @@ Void PlaYUVerFrame::fillRGBBuffer() if( d->m_bHasRGBPel ) return; - Int iR, iG, iB; Int shiftBits = d->m_uiBitsPel - 8; UInt* pARGB = (UInt*)d->m_pcARGB32; if( d->m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_GRAY ) { Pel* pY = d->m_pppcInputPel[LUMA][0]; - Int iY; for( UInt i = 0; i < d->m_uiHeight * d->m_uiWidth; i++ ) { - iY = *pY++; - iY >>= shiftBits; - iR = iY; - iG = iY; - iB = iY; - *pARGB++ = PEL_RGB( iR, iG, iB ); + *pARGB++ = PEL_RGB( *pY, *pY, *pY ); + pY++; } } else if( d->m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_RGB ) @@ -935,14 +910,17 @@ Void PlaYUVerFrame::fillRGBBuffer() Pel* pR = d->m_pppcInputPel[COLOR_R][0]; Pel* pG = d->m_pppcInputPel[COLOR_G][0]; Pel* pB = d->m_pppcInputPel[COLOR_B][0]; - for( UInt i = 0; i < d->m_uiHeight * d->m_uiWidth; i++ ) - { - iR = *pR++; - iG = *pG++; - iB = *pB++; - *pARGB++ = PEL_RGB( ( iR >> shiftBits ), ( iG >> shiftBits ), ( iB >> shiftBits ) ); - } + *pARGB++ = PEL_RGB( ( *pR++ ) >> shiftBits, ( *pG++ ) >> shiftBits, ( *pB++ ) >> shiftBits ); + } + else if( d->m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_RGBA ) + { + Pel* pR = d->m_pppcInputPel[COLOR_R][0]; + Pel* pG = d->m_pppcInputPel[COLOR_G][0]; + Pel* pB = d->m_pppcInputPel[COLOR_B][0]; + Pel* pA = d->m_pppcInputPel[COLOR_A][0]; + for( UInt i = 0; i < d->m_uiHeight * d->m_uiWidth; i++ ) + *pARGB++ = PEL_ARGB( ( *pA++ ) >> shiftBits, ( *pR++ ) >> shiftBits, ( *pG++ ) >> shiftBits, ( *pB++ ) >> shiftBits ); } else if( d->m_pcPelFormat->colorSpace == PlaYUVerPixel::COLOR_YUV ) { @@ -959,7 +937,7 @@ Void PlaYUVerFrame::fillRGBBuffer() UInt y, x; Int i, j; - for( y = 0; ym_uiHeight>> d->m_pcPelFormat->log2ChromaHeight; y++ ) + for( y = 0; y < CHROMASHIFT( d->m_uiHeight, d->m_pcPelFormat->log2ChromaHeight ); y++ ) { for( i = 0; i < 1 << d->m_pcPelFormat->log2ChromaHeight; i++ ) { @@ -967,7 +945,7 @@ Void PlaYUVerFrame::fillRGBBuffer() pU = pLineU; pV = pLineV; pARGB = pARGBLine; - for( x = 0; xm_uiWidth>> d->m_pcPelFormat->log2ChromaWidth; x++ ) + for( x = 0; x < CHROMASHIFT( d->m_uiWidth, d->m_pcPelFormat->log2ChromaWidth ); x++ ) { iU = *pU++; iU >>= shiftBits; @@ -1041,7 +1019,7 @@ Void PlaYUVerFrame::calcHistogram() { d->m_puiHistogram[*( data[j] ) + j * d->m_uiHistoSegments]++; } - if( ( colorSpace == PlaYUVerPixel::COLOR_RGB || colorSpace == PlaYUVerPixel::COLOR_ARGB ) ) + if( ( colorSpace == PlaYUVerPixel::COLOR_RGB || colorSpace == PlaYUVerPixel::COLOR_RGBA ) ) { PlaYUVerPixel currPixel( colorSpace, *( data[COLOR_R] ), *( data[COLOR_G] ), *( data[COLOR_B] ) ); luma = currPixel.ConvertPixel( PlaYUVerPixel::COLOR_YUV ).Y(); @@ -1090,7 +1068,7 @@ Int getRealHistoChannel( Int colorSpace, Int channel ) } } break; - case PlaYUVerPixel::COLOR_ARGB: + case PlaYUVerPixel::COLOR_RGBA: if( channel != COLOR_R && channel != COLOR_G && channel != COLOR_B && channel != COLOR_A && channel != LUMA ) { return -1; @@ -1309,14 +1287,14 @@ Double PlaYUVerFrame::getStdDev( Int channel, UInt start, UInt end ) /*------------ original - for ( i = start ; i <= end ; i++ ) - { - dev += ( i - mean ) * ( i - mean ) * d->m_puiHistogram[indexStart +i]; - } + for ( i = start ; i <= end ; i++ ) + { + dev += ( i - mean ) * ( i - mean ) * d->m_puiHistogram[indexStart +i]; + } - return sqrt( dev / count ); + return sqrt( dev / count ); - -----------------------*/ + -----------------------*/ for( UInt i = start; i <= end; i++ ) { diff --git a/lib/PlaYUVerFrame.h b/lib/PlaYUVerFrame.h index c604432..0829dc1 100644 --- a/lib/PlaYUVerFrame.h +++ b/lib/PlaYUVerFrame.h @@ -55,7 +55,7 @@ public: COLOR_YUV = 0, //!< YUV COLOR_RGB = 1, //!< RGB COLOR_GRAY = 2, //!< Grayscale - COLOR_ARGB = 3, //!< RGB + Alpha + COLOR_RGBA = 3, //!< RGB + Alpha COLOR_MAX = 255, //!< Accouunt for future formats }; @@ -130,7 +130,9 @@ public: RGBp, RGB24, BGR24, - NUMBER_PEL_FORMATS + RGBA, + BGRA, + PEL_FMT_MAX = 255, }; /** @@ -147,6 +149,7 @@ public: */ static std::vector supportedPixelFormatListNames(); static std::vector supportedPixelFormatListNames( Int colorSpace ); + static Int numberOfFormats(); static Int findPixelFormat( const String& name ); /** diff --git a/lib/PlaYUVerFramePixelFormats.cpp b/lib/PlaYUVerFramePixelFormats.cpp index 22495eb..f9c42d3 100644 --- a/lib/PlaYUVerFramePixelFormats.cpp +++ b/lib/PlaYUVerFramePixelFormats.cpp @@ -53,148 +53,148 @@ Void fillARGB32bufferYUV420p( Pel*** in, UChar* out, UInt width, UInt height, UInt depth ) { #ifdef USE_SSE - if( ( width % 16 ) == 0 ) - { - uint8_t *yp = in[LUMA][0]; - uint8_t *up = in[CHROMA_U][0]; - uint8_t *vp = in[CHROMA_V][0]; - uint32_t suv = width >> 1; - uint32_t *rgb = ( uint32_t* )out; + if( ( width % 16 ) == 0 ) + { + uint8_t *yp = in[LUMA][0]; + uint8_t *up = in[CHROMA_U][0]; + uint8_t *vp = in[CHROMA_V][0]; + uint32_t suv = width >> 1; + uint32_t *rgb = ( uint32_t* )out; - __m128i y0r0, y0r1, u0, v0; - __m128i y00r0, y01r0, y00r1, y01r1; - __m128i u00, u01, v00, v01; - __m128i rv00, rv01, gu00, gu01, gv00, gv01, bu00, bu01; - __m128i r00, r01, g00, g01, b00, b01; - __m128i rgb0123, rgb4567, rgb89ab, rgbcdef; - __m128i gbgb; - __m128i ysub, uvsub; - __m128i zero, facy, facrv, facgu, facgv, facbu; - __m128i *srcy128r0, *srcy128r1; - __m128i *dstrgb128r0, *dstrgb128r1; - __m64 *srcu64, *srcv64; - UInt x, y; + __m128i y0r0, y0r1, u0, v0; + __m128i y00r0, y01r0, y00r1, y01r1; + __m128i u00, u01, v00, v01; + __m128i rv00, rv01, gu00, gu01, gv00, gv01, bu00, bu01; + __m128i r00, r01, g00, g01, b00, b01; + __m128i rgb0123, rgb4567, rgb89ab, rgbcdef; + __m128i gbgb; + __m128i ysub, uvsub; + __m128i zero, facy, facrv, facgu, facgv, facbu; + __m128i *srcy128r0, *srcy128r1; + __m128i *dstrgb128r0, *dstrgb128r1; + __m64 *srcu64, *srcv64; + UInt x, y; - ysub = _mm_set1_epi32( 0x00100010 ); - uvsub = _mm_set1_epi32( 0x00800080 ); + ysub = _mm_set1_epi32( 0x00100010 ); + uvsub = _mm_set1_epi32( 0x00800080 ); - facy = _mm_set1_epi32( 0x004a004a ); - facrv = _mm_set1_epi32( 0x00660066 ); - facgu = _mm_set1_epi32( 0x00190019 ); - facgv = _mm_set1_epi32( 0x00340034 ); - facbu = _mm_set1_epi32( 0x00810081 ); + facy = _mm_set1_epi32( 0x004a004a ); + facrv = _mm_set1_epi32( 0x00660066 ); + facgu = _mm_set1_epi32( 0x00190019 ); + facgv = _mm_set1_epi32( 0x00340034 ); + facbu = _mm_set1_epi32( 0x00810081 ); - zero = _mm_set1_epi32( 0x00000000 ); + zero = _mm_set1_epi32( 0x00000000 ); - for( y = 0; y < height; y += 2 ) - { + for( y = 0; y < height; y += 2 ) + { - srcy128r0 = ( __m128i * )( yp + width * y ); - srcy128r1 = ( __m128i * )( yp + width * y + width ); - srcu64 = ( __m64 * )( up + suv * ( y / 2 ) ); - srcv64 = ( __m64 * )( vp + suv * ( y / 2 ) ); + srcy128r0 = ( __m128i * )( yp + width * y ); + srcy128r1 = ( __m128i * )( yp + width * y + width ); + srcu64 = ( __m64 * )( up + suv * ( y / 2 ) ); + srcv64 = ( __m64 * )( vp + suv * ( y / 2 ) ); - dstrgb128r0 = ( __m128i * )( rgb + width * y ); - dstrgb128r1 = ( __m128i * )( rgb + width * y + width ); + dstrgb128r0 = ( __m128i * )( rgb + width * y ); + dstrgb128r1 = ( __m128i * )( rgb + width * y + width ); - for( x = 0; x < width; x += 16 ) - { + for( x = 0; x < width; x += 16 ) + { - u0 = _mm_loadl_epi64( ( __m128i * )srcu64 ); - srcu64++; - v0 = _mm_loadl_epi64( ( __m128i * )srcv64 ); - srcv64++; + u0 = _mm_loadl_epi64( ( __m128i * )srcu64 ); + srcu64++; + v0 = _mm_loadl_epi64( ( __m128i * )srcv64 ); + srcv64++; - y0r0 = _mm_load_si128( srcy128r0++ ); - y0r1 = _mm_load_si128( srcy128r1++ ); + y0r0 = _mm_load_si128( srcy128r0++ ); + y0r1 = _mm_load_si128( srcy128r1++ ); - // constant y factors - y00r0 = _mm_mullo_epi16( _mm_sub_epi16( _mm_unpacklo_epi8( y0r0, zero ), ysub ), facy ); - y01r0 = _mm_mullo_epi16( _mm_sub_epi16( _mm_unpackhi_epi8( y0r0, zero ), ysub ), facy ); - y00r1 = _mm_mullo_epi16( _mm_sub_epi16( _mm_unpacklo_epi8( y0r1, zero ), ysub ), facy ); - y01r1 = _mm_mullo_epi16( _mm_sub_epi16( _mm_unpackhi_epi8( y0r1, zero ), ysub ), facy ); + // constant y factors + y00r0 = _mm_mullo_epi16( _mm_sub_epi16( _mm_unpacklo_epi8( y0r0, zero ), ysub ), facy ); + y01r0 = _mm_mullo_epi16( _mm_sub_epi16( _mm_unpackhi_epi8( y0r0, zero ), ysub ), facy ); + y00r1 = _mm_mullo_epi16( _mm_sub_epi16( _mm_unpacklo_epi8( y0r1, zero ), ysub ), facy ); + y01r1 = _mm_mullo_epi16( _mm_sub_epi16( _mm_unpackhi_epi8( y0r1, zero ), ysub ), facy ); - // expand u and v so they're aligned with y values - u0 = _mm_unpacklo_epi8( u0, zero ); - u00 = _mm_sub_epi16( _mm_unpacklo_epi16( u0, u0 ), uvsub ); - u01 = _mm_sub_epi16( _mm_unpackhi_epi16( u0, u0 ), uvsub ); + // expand u and v so they're aligned with y values + u0 = _mm_unpacklo_epi8( u0, zero ); + u00 = _mm_sub_epi16( _mm_unpacklo_epi16( u0, u0 ), uvsub ); + u01 = _mm_sub_epi16( _mm_unpackhi_epi16( u0, u0 ), uvsub ); - v0 = _mm_unpacklo_epi8( v0, zero ); - v00 = _mm_sub_epi16( _mm_unpacklo_epi16( v0, v0 ), uvsub ); - v01 = _mm_sub_epi16( _mm_unpackhi_epi16( v0, v0 ), uvsub ); + v0 = _mm_unpacklo_epi8( v0, zero ); + v00 = _mm_sub_epi16( _mm_unpacklo_epi16( v0, v0 ), uvsub ); + v01 = _mm_sub_epi16( _mm_unpackhi_epi16( v0, v0 ), uvsub ); - // common factors on both rows. - rv00 = _mm_mullo_epi16( facrv, v00 ); - rv01 = _mm_mullo_epi16( facrv, v01 ); - gu00 = _mm_mullo_epi16( facgu, u00 ); - gu01 = _mm_mullo_epi16( facgu, u01 ); - gv00 = _mm_mullo_epi16( facgv, v00 ); - gv01 = _mm_mullo_epi16( facgv, v01 ); - bu00 = _mm_mullo_epi16( facbu, u00 ); - bu01 = _mm_mullo_epi16( facbu, u01 ); + // common factors on both rows. + rv00 = _mm_mullo_epi16( facrv, v00 ); + rv01 = _mm_mullo_epi16( facrv, v01 ); + gu00 = _mm_mullo_epi16( facgu, u00 ); + gu01 = _mm_mullo_epi16( facgu, u01 ); + gv00 = _mm_mullo_epi16( facgv, v00 ); + gv01 = _mm_mullo_epi16( facgv, v01 ); + bu00 = _mm_mullo_epi16( facbu, u00 ); + bu01 = _mm_mullo_epi16( facbu, u01 ); - // row 0 - r00 = _mm_srai_epi16( _mm_add_epi16( y00r0, rv00 ), 6 ); - r01 = _mm_srai_epi16( _mm_add_epi16( y01r0, rv01 ), 6 ); - g00 = _mm_srai_epi16( _mm_sub_epi16( _mm_sub_epi16( y00r0, gu00 ), gv00 ), 6 ); - g01 = _mm_srai_epi16( _mm_sub_epi16( _mm_sub_epi16( y01r0, gu01 ), gv01 ), 6 ); - b00 = _mm_srai_epi16( _mm_add_epi16( y00r0, bu00 ), 6 ); - b01 = _mm_srai_epi16( _mm_add_epi16( y01r0, bu01 ), 6 ); + // row 0 + r00 = _mm_srai_epi16( _mm_add_epi16( y00r0, rv00 ), 6 ); + r01 = _mm_srai_epi16( _mm_add_epi16( y01r0, rv01 ), 6 ); + g00 = _mm_srai_epi16( _mm_sub_epi16( _mm_sub_epi16( y00r0, gu00 ), gv00 ), 6 ); + g01 = _mm_srai_epi16( _mm_sub_epi16( _mm_sub_epi16( y01r0, gu01 ), gv01 ), 6 ); + b00 = _mm_srai_epi16( _mm_add_epi16( y00r0, bu00 ), 6 ); + b01 = _mm_srai_epi16( _mm_add_epi16( y01r0, bu01 ), 6 ); - r00 = _mm_packus_epi16( r00, r01 );// rrrr.. saturated - g00 = _mm_packus_epi16( g00, g01 );// gggg.. saturated - b00 = _mm_packus_epi16( b00, b01 );// bbbb.. saturated + r00 = _mm_packus_epi16( r00, r01 );// rrrr.. saturated + g00 = _mm_packus_epi16( g00, g01 );// gggg.. saturated + b00 = _mm_packus_epi16( b00, b01 );// bbbb.. saturated - r01 = _mm_unpacklo_epi8( r00, zero );// 0r0r.. - gbgb = _mm_unpacklo_epi8( b00, g00 );// gbgb.. - rgb0123 = _mm_unpacklo_epi16( gbgb, r01 );// 0rgb0rgb.. - rgb4567 = _mm_unpackhi_epi16( gbgb, r01 );// 0rgb0rgb.. + r01 = _mm_unpacklo_epi8( r00, zero );// 0r0r.. + gbgb = _mm_unpacklo_epi8( b00, g00 );// gbgb.. + rgb0123 = _mm_unpacklo_epi16( gbgb, r01 );// 0rgb0rgb.. + rgb4567 = _mm_unpackhi_epi16( gbgb, r01 );// 0rgb0rgb.. - r01 = _mm_unpackhi_epi8( r00, zero ); - gbgb = _mm_unpackhi_epi8( b00, g00 ); - rgb89ab = _mm_unpacklo_epi16( gbgb, r01 ); - rgbcdef = _mm_unpackhi_epi16( gbgb, r01 ); + r01 = _mm_unpackhi_epi8( r00, zero ); + gbgb = _mm_unpackhi_epi8( b00, g00 ); + rgb89ab = _mm_unpacklo_epi16( gbgb, r01 ); + rgbcdef = _mm_unpackhi_epi16( gbgb, r01 ); - _mm_store_si128( dstrgb128r0++, rgb0123 ); - _mm_store_si128( dstrgb128r0++, rgb4567 ); - _mm_store_si128( dstrgb128r0++, rgb89ab ); - _mm_store_si128( dstrgb128r0++, rgbcdef ); + _mm_store_si128( dstrgb128r0++, rgb0123 ); + _mm_store_si128( dstrgb128r0++, rgb4567 ); + _mm_store_si128( dstrgb128r0++, rgb89ab ); + _mm_store_si128( dstrgb128r0++, rgbcdef ); - // row 1 - r00 = _mm_srai_epi16( _mm_add_epi16( y00r1, rv00 ), 6 ); - r01 = _mm_srai_epi16( _mm_add_epi16( y01r1, rv01 ), 6 ); - g00 = _mm_srai_epi16( _mm_sub_epi16( _mm_sub_epi16( y00r1, gu00 ), gv00 ), 6 ); - g01 = _mm_srai_epi16( _mm_sub_epi16( _mm_sub_epi16( y01r1, gu01 ), gv01 ), 6 ); - b00 = _mm_srai_epi16( _mm_add_epi16( y00r1, bu00 ), 6 ); - b01 = _mm_srai_epi16( _mm_add_epi16( y01r1, bu01 ), 6 ); + // row 1 + r00 = _mm_srai_epi16( _mm_add_epi16( y00r1, rv00 ), 6 ); + r01 = _mm_srai_epi16( _mm_add_epi16( y01r1, rv01 ), 6 ); + g00 = _mm_srai_epi16( _mm_sub_epi16( _mm_sub_epi16( y00r1, gu00 ), gv00 ), 6 ); + g01 = _mm_srai_epi16( _mm_sub_epi16( _mm_sub_epi16( y01r1, gu01 ), gv01 ), 6 ); + b00 = _mm_srai_epi16( _mm_add_epi16( y00r1, bu00 ), 6 ); + b01 = _mm_srai_epi16( _mm_add_epi16( y01r1, bu01 ), 6 ); - r00 = _mm_packus_epi16( r00, r01 );// rrrr.. saturated - g00 = _mm_packus_epi16( g00, g01 );// gggg.. saturated - b00 = _mm_packus_epi16( b00, b01 );// bbbb.. saturated + r00 = _mm_packus_epi16( r00, r01 );// rrrr.. saturated + g00 = _mm_packus_epi16( g00, g01 );// gggg.. saturated + b00 = _mm_packus_epi16( b00, b01 );// bbbb.. saturated - r01 = _mm_unpacklo_epi8( r00, zero );// 0r0r.. - gbgb = _mm_unpacklo_epi8( b00, g00 );// gbgb.. - rgb0123 = _mm_unpacklo_epi16( gbgb, r01 );// 0rgb0rgb.. - rgb4567 = _mm_unpackhi_epi16( gbgb, r01 );// 0rgb0rgb.. + r01 = _mm_unpacklo_epi8( r00, zero );// 0r0r.. + gbgb = _mm_unpacklo_epi8( b00, g00 );// gbgb.. + rgb0123 = _mm_unpacklo_epi16( gbgb, r01 );// 0rgb0rgb.. + rgb4567 = _mm_unpackhi_epi16( gbgb, r01 );// 0rgb0rgb.. - r01 = _mm_unpackhi_epi8( r00, zero ); - gbgb = _mm_unpackhi_epi8( b00, g00 ); - rgb89ab = _mm_unpacklo_epi16( gbgb, r01 ); - rgbcdef = _mm_unpackhi_epi16( gbgb, r01 ); + r01 = _mm_unpackhi_epi8( r00, zero ); + gbgb = _mm_unpackhi_epi8( b00, g00 ); + rgb89ab = _mm_unpacklo_epi16( gbgb, r01 ); + rgbcdef = _mm_unpackhi_epi16( gbgb, r01 ); - _mm_store_si128( dstrgb128r1++, rgb0123 ); - _mm_store_si128( dstrgb128r1++, rgb4567 ); - _mm_store_si128( dstrgb128r1++, rgb89ab ); - _mm_store_si128( dstrgb128r1++, rgbcdef ); + _mm_store_si128( dstrgb128r1++, rgb0123 ); + _mm_store_si128( dstrgb128r1++, rgb4567 ); + _mm_store_si128( dstrgb128r1++, rgb89ab ); + _mm_store_si128( dstrgb128r1++, rgbcdef ); - } - } - } - else + } + } + } + else #endif - { - fillARGB32bufferYUV( in, out, width, height, depth, 1, 1 ); - } + { + fillARGB32bufferYUV( in, out, width, height, depth, 1, 1 ); + } } #endif @@ -331,4 +331,57 @@ const std::map g_PlaYUVerPixFmtDescriptorsMap = { }, }, }, + { + 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 */ + }, + }, + }, + { + PlaYUVerFrame::RGBA, + { + "RGBA", + PlaYUVerPixel::COLOR_RGBA, + 4, + 1, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_RGBA ), + { + {0, 3, 1}, /* R */ + {0, 3, 2}, /* G */ + {0, 3, 3}, /* B */ + {0, 3, 4}, /* A */ + }, + }, + }, + { + PlaYUVerFrame::BGRA, + { + "BGRA", + PlaYUVerPixel::COLOR_RGBA, + 4, + 1, + 0, + 0, + ADD_FFMPEG_PEL_FMT( AV_PIX_FMT_BGRA ), + { + {0, 3, 3}, /* R */ + {0, 3, 2}, /* G */ + {0, 3, 1}, /* B */ + {0, 3, 4}, /* A */ + }, + }, + }, }; diff --git a/lib/PlaYUVerFramePixelFormats.h b/lib/PlaYUVerFramePixelFormats.h index f3c62c8..82553b7 100644 --- a/lib/PlaYUVerFramePixelFormats.h +++ b/lib/PlaYUVerFramePixelFormats.h @@ -34,8 +34,6 @@ #define CHROMARATIO( SIZE, RATIO ) ( RATIO > 1 ? ( ( SIZE + 1 ) / RATIO ) : SIZE ) -#define PEL_RGB( r, g, b ) ( 0xffu << 24 ) | ( ( r & 0xff ) << 16 ) | ( ( g & 0xff ) << 8 ) | ( b & 0xff ) - typedef struct PlaYUVerComponentDescriptor { /** diff --git a/lib/StreamHandlerLibav.cpp b/lib/StreamHandlerLibav.cpp index 8c49580..4a262d5 100644 --- a/lib/StreamHandlerLibav.cpp +++ b/lib/StreamHandlerLibav.cpp @@ -199,7 +199,7 @@ Bool StreamHandlerLibav::openHandler( String strFilename, Bool bInput ) } m_iPixelFormat = PlaYUVerFrame::NO_FMT; - for( Int i = 0; i < PlaYUVerFrame::NUMBER_PEL_FORMATS; i++ ) + for( Int i = 0; i < PlaYUVerFrame::numberOfFormats(); i++ ) { if( g_PlaYUVerPixFmtDescriptorsMap.at( i ).ffmpegPelFormat == auxPixFmt ) {