From 87cd3fe5e59126d8db5e05bb3b44ac7ab9557994 Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Sun, 2 Feb 2014 01:11:11 +0000 Subject: [PATCH 1/2] Create new class PlaYUVerFrame to handle video frames --- source/InputStream.cpp | 191 ++++--------------------------------- source/InputStream.h | 16 +--- source/PlaYUVerFrame.cpp | 200 +++++++++++++++++++++++++++++++++++++++ source/PlaYUVerFrame.h | 74 +++++++++++++++ 4 files changed, 299 insertions(+), 182 deletions(-) create mode 100755 source/PlaYUVerFrame.cpp create mode 100755 source/PlaYUVerFrame.h diff --git a/source/InputStream.cpp b/source/InputStream.cpp index f7bbfcc..75e0dd2 100755 --- a/source/InputStream.cpp +++ b/source/InputStream.cpp @@ -42,10 +42,6 @@ InputStream::InputStream() m_uiCurrFrameNum = 0; m_iErrorStatus = 0; m_iPixelFormat = -1; - m_pppcInputPel[0] = NULL; - m_pppcInputPel[1] = NULL; - m_pppcInputPel[2] = NULL; - m_pppcRGBPel = NULL; m_iFileFormat = INVALID; } @@ -55,16 +51,6 @@ InputStream::~InputStream() if( m_pFile ) fclose( m_pFile ); - if( m_pppcInputPel[0] ) - free_mem2Dpel( m_pppcInputPel[0] ); - if( m_pppcInputPel[1] ) - free_mem2Dpel( m_pppcInputPel[1] ); - if( m_pppcInputPel[2] ) - free_mem2Dpel( m_pppcInputPel[2] ); - - if( m_pppcRGBPel ) - free_mem3Dpel( m_pppcRGBPel ); - #ifdef USE_FFMPEG m_cLibAvContext.closeAvFormat(); #endif @@ -137,7 +123,6 @@ Bool InputStream::needFormatDialog( QString filename ) Void InputStream::init( QString filename, UInt width, UInt height, Int input_format ) { - m_uiWidth = width; m_uiHeight = height; @@ -154,58 +139,25 @@ Void InputStream::init( QString filename, UInt width, UInt height, Int input_for return; } - m_cFilename = filename; - m_pFile = fopen( m_cFilename.toLocal8Bit().data(), "rb" ); - if( m_pFile == NULL ) - { - // Error - return; - } + m_cCurrFrame = new PlaYUVerFrame( m_uiWidth, m_uiHeight, m_iPixelFormat ); UInt64 frame_bytes_input = m_uiWidth * m_uiHeight * 1.5; - UInt64 alloc_memory; - - fseek( m_pFile, 0, SEEK_END ); - m_uiTotalFrameNum = ftell( m_pFile ) / ( frame_bytes_input ); - fseek( m_pFile, 0, SEEK_SET ); if( m_iFileFormat == YUVFormat ) { - switch( m_iPixelFormat ) + m_cFilename = filename; + m_pFile = fopen( m_cFilename.toLocal8Bit().data(), "rb" ); + if( m_pFile == NULL ) { - case YUV420: - alloc_memory = get_mem2Dpel( &( m_pppcInputPel[0] ), m_uiHeight, m_uiWidth ); - if( !alloc_memory ) - { - //Error - return; - } - alloc_memory = get_mem2Dpel( &( m_pppcInputPel[1] ), m_uiHeight / 2, m_uiWidth / 2 ); - if( !alloc_memory ) - { - //Error - return; - } - alloc_memory = get_mem2Dpel( &( m_pppcInputPel[2] ), m_uiHeight / 2, m_uiWidth / 2 ); - if( !alloc_memory ) - { - //Error - return; - } - break; - case YUV400: - alloc_memory = get_mem2Dpel( &( m_pppcInputPel[0] ), m_uiHeight, m_uiWidth ); - if( !alloc_memory ) - { - //Error - return; - } - break; + // Error + return; } + fseek( m_pFile, 0, SEEK_END ); + fseek( m_pFile, 0, SEEK_SET ); + m_uiTotalFrameNum = ftell( m_pFile ) / ( frame_bytes_input ); } - get_mem3Dpel( &m_pppcRGBPel, 3, m_uiHeight, m_uiWidth ); - if( !alloc_memory ) + if( !get_mem1Dpel( &m_pInputBuffer, m_cCurrFrame->getBytesPerFrame() ) ) { //Error return; @@ -216,82 +168,6 @@ Void InputStream::init( QString filename, UInt width, UInt height, Int input_for return; } -static inline void yuvToRgb( int iY, int iU, int iV, int &iR, int &iG, int &iB ) -{ - iR = iY + 1402 * iV / 1000; - iG = iY - ( 101004 * iU + 209599 * iV ) / 293500; - iB = iY + 1772 * iU / 1000; - - if( iR < 0 ) - iR = 0; - if( iG < 0 ) - iG = 0; - if( iB < 0 ) - iB = 0; - - if( iR > 255 ) - iR = 255; - if( iG > 255 ) - iG = 255; - if( iB > 255 ) - iB = 255; -} - -Void InputStream::YUV420toRGB() -{ - Int iY, iU, iV, iR, iG, iB; - for( Int y = 0; y < m_uiHeight; y += 2 ) - { - for( Int x = 0; x < m_uiWidth; x += 2 ) - { - // Pixel (x, y). - - iY = m_pppcInputPel[0][y][x]; - iU = m_pppcInputPel[1][y >> 1][x >> 1]; - iV = m_pppcInputPel[2][y >> 1][x >> 1]; - iU -= 128; - iV -= 128; - - yuvToRgb( iY, iU, iV, iR, iG, iB ); - - m_pppcRGBPel[0][y][x] = iR; - m_pppcRGBPel[1][y][x] = iG; - m_pppcRGBPel[2][y][x] = iB; - - // Pixel (x+1, y) - - iY = m_pppcInputPel[0][y][x + 1]; - - yuvToRgb( iY, iU, iV, iR, iG, iB ); - - m_pppcRGBPel[0][y][x + 1] = iR; - m_pppcRGBPel[1][y][x + 1] = iG; - m_pppcRGBPel[2][y][x + 1] = iB; - - // Pixel (x, y+1) - - iY = m_pppcInputPel[0][y + 1][x]; - - yuvToRgb( iY, iU, iV, iR, iG, iB ); - - m_pppcRGBPel[0][y + 1][x] = iR; - m_pppcRGBPel[1][y + 1][x] = iG; - m_pppcRGBPel[2][y + 1][x] = iB; - - // Pixel (x+1, y+1) - - iY = m_pppcInputPel[0][y + 1][x + 1]; - - yuvToRgb( iY, iU, iV, iR, iG, iB ); - - m_pppcRGBPel[0][y + 1][x + 1] = iR; - m_pppcRGBPel[1][y + 1][x + 1] = iG; - m_pppcRGBPel[2][y + 1][x + 1] = iB; - - } - } -} - Void InputStream::readFrame() { UInt64 bytes_read = 0; @@ -300,48 +176,25 @@ Void InputStream::readFrame() { return; } - UInt64 frame_bytes_input = m_uiWidth * m_uiHeight * 1.5; + UInt64 frame_bytes_input = m_cCurrFrame->getBytesPerFrame(); #ifdef USE_FFMPEG if( m_cLibAvContext.getStatus() ) { m_cLibAvContext.decodeAvFormat(); - //fwrite( video_dst_data[0], 1, video_dst_bufsize, video_dst_file ); - memcpy( &( m_pppcInputPel[0][0][0] ), m_cLibAvContext.video_dst_data[0], m_uiWidth * m_uiHeight * sizeof(uint8_t) ); - memcpy( &( m_pppcInputPel[1][0][0] ), m_cLibAvContext.video_dst_data[1], m_uiWidth * m_uiHeight * sizeof(uint8_t) / 4 ); - memcpy( &( m_pppcInputPel[2][0][0] ), m_cLibAvContext.video_dst_data[2], m_uiWidth * m_uiHeight * sizeof(uint8_t) / 4 ); - YUV420toRGB(); + m_cCurrFrame->FrameFromBuffer( m_cLibAvContext.video_dst_data[0], m_iPixelFormat ); return; } #endif - switch( m_iPixelFormat ) + bytes_read = fread( m_pInputBuffer, sizeof(Pel), frame_bytes_input, m_pFile ); + if( bytes_read != frame_bytes_input ) { - case YUV420: - bytes_read = fread( &( m_pppcInputPel[0][0][0] ), sizeof(Pel), m_uiWidth * m_uiHeight, m_pFile ); - if( bytes_read != ( m_uiWidth * m_uiHeight ) ) - { - m_iErrorStatus = READING; - qDebug( ) << " Reading error !!!" << endl; - return; - } - bytes_read = fread( &( m_pppcInputPel[1][0][0] ), sizeof(Pel), m_uiWidth * m_uiHeight / 4, m_pFile ); - if( bytes_read != ( m_uiWidth * m_uiHeight / 4 ) ) - { - m_iErrorStatus = READING; - qDebug( ) << " Reading error !!!" << endl; - return; - } - bytes_read = fread( &( m_pppcInputPel[2][0][0] ), sizeof(Pel), m_uiWidth * m_uiHeight / 4, m_pFile ); - if( bytes_read != ( m_uiWidth * m_uiHeight / 4 ) ) - { - m_iErrorStatus = READING; - qDebug( ) << " Reading error !!!" << endl; - return; - } - YUV420toRGB(); - break; + m_iErrorStatus = READING; + qDebug() << " Reading error !!!" << endl; + return; } + m_cCurrFrame->FrameFromBuffer( m_pInputBuffer, m_iPixelFormat ); return; } @@ -356,10 +209,7 @@ QImage InputStream::getFrameQImage() { // Create QImage QImage img( m_uiWidth, m_uiHeight, QImage::Format_RGB888 ); - - UInt64 frame_bytes = m_uiWidth * m_uiHeight; - Pel pelR, pelG, pelB; - Pel* bufferRGB = &( m_pppcRGBPel[0][0][0] ); + Pel*** bufferRGB = m_cCurrFrame->getPelBufferRGB(); if( sizeof(Pel) == sizeof(unsigned char) ) { @@ -367,8 +217,7 @@ QImage InputStream::getFrameQImage() { for( Int x = 0; x < m_uiWidth; x++ ) { - img.setPixel( x, y, qRgb( m_pppcRGBPel[0][y][x], m_pppcRGBPel[1][y][x], m_pppcRGBPel[2][y][x] ) ); - //img.setPixel( x, y, qRgb( 0, 0, 255 ) ); + img.setPixel( x, y, qRgb( bufferRGB[0][y][x], bufferRGB[1][y][x], bufferRGB[2][y][x] ) ); } } } diff --git a/source/InputStream.h b/source/InputStream.h index 9248a77..f00fa4f 100755 --- a/source/InputStream.h +++ b/source/InputStream.h @@ -38,6 +38,7 @@ #include "TypeDef.h" #include "LibAvContextHandle.h" +#include "PlaYUVerFrame.h" namespace plaYUVer { @@ -47,7 +48,6 @@ enum InputStream_Errors NO_ERROR = 0, READING = 1, }; - class InputStream { private: @@ -64,14 +64,15 @@ private: Int m_iFileFormat; Int m_iPixelFormat; + Pel* m_pInputBuffer; + + PlaYUVerFrame *m_cCurrFrame; + UInt m_uiWidth; UInt m_uiHeight; UInt m_uiTotalFrameNum; UInt m_uiCurrFrameNum; - Pel** m_pppcInputPel[3]; - Pel*** m_pppcRGBPel; - public: InputStream(); ~InputStream(); @@ -83,11 +84,6 @@ public: static QStringList supportedPixelFormatList(); - enum InputStreamColorSpace - { - YUV420, YUV400, - }; - enum InputStreamFormats { INVALID = -1, YUVFormat = 0, // Use color space. @@ -97,8 +93,6 @@ public: Void init( QString filename, UInt width, UInt height, Int input_format ); - Void YUV420toRGB(); - Void readFrame(); Bool writeFrame( const QString& filename ); diff --git a/source/PlaYUVerFrame.cpp b/source/PlaYUVerFrame.cpp new file mode 100755 index 0000000..0532eb2 --- /dev/null +++ b/source/PlaYUVerFrame.cpp @@ -0,0 +1,200 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014 by plaYUVer developers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * \file PlaYUVerFrame.cpp + * \brief Video Frame handling + */ +#include + +#include "PlaYUVerFrame.h" +#include "LibMemAlloc.h" + +namespace plaYUVer +{ + +PlaYUVerFrame::PlaYUVerFrame( UInt width, UInt height, Int pel_format ) +{ + m_pppcInputPel[0] = NULL; + m_pppcInputPel[1] = NULL; + m_pppcInputPel[2] = NULL; + m_pppcRGBPel = NULL; + + m_uiWidth = width; + m_uiHeight = height; + m_iPixelFormat = pel_format; + + switch( m_iPixelFormat ) + { + case YUV420: + get_mem2Dpel( &( m_pppcInputPel[0] ), m_uiHeight, m_uiWidth ); + get_mem2Dpel( &( m_pppcInputPel[1] ), m_uiHeight / 2, m_uiWidth / 2 ); + get_mem2Dpel( &( m_pppcInputPel[2] ), m_uiHeight / 2, m_uiWidth / 2 ); + break; + case YUV422: + get_mem2Dpel( &( m_pppcInputPel[0] ), m_uiHeight, m_uiWidth ); + get_mem2Dpel( &( m_pppcInputPel[1] ), m_uiHeight / 2, m_uiWidth ); + get_mem2Dpel( &( m_pppcInputPel[2] ), m_uiHeight / 2, m_uiWidth ); + break; + case YUV400: + get_mem2Dpel( &( m_pppcInputPel[0] ), m_uiHeight, m_uiWidth ); + break; + case RGB: + get_mem3Dpel( &m_pppcRGBPel, 3, m_uiHeight, m_uiWidth ); + break; + } + if( m_iPixelFormat != RGB ) + get_mem3Dpel( &m_pppcRGBPel, 3, m_uiHeight, m_uiWidth ); + +} + +PlaYUVerFrame::~PlaYUVerFrame() +{ + if( m_pppcInputPel[0] ) + free_mem2Dpel( m_pppcInputPel[0] ); + if( m_pppcInputPel[1] ) + free_mem2Dpel( m_pppcInputPel[1] ); + if( m_pppcInputPel[2] ) + free_mem2Dpel( m_pppcInputPel[2] ); + + if( m_pppcRGBPel ) + free_mem3Dpel( m_pppcRGBPel ); +} + +static inline void yuvToRgb( int iY, int iU, int iV, int &iR, int &iG, int &iB ) +{ + iR = iY + 1402 * iV / 1000; + iG = iY - ( 101004 * iU + 209599 * iV ) / 293500; + iB = iY + 1772 * iU / 1000; + + if( iR < 0 ) + iR = 0; + if( iG < 0 ) + iG = 0; + if( iB < 0 ) + iB = 0; + + if( iR > 255 ) + iR = 255; + if( iG > 255 ) + iG = 255; + if( iB > 255 ) + iB = 255; +} + +Void PlaYUVerFrame::YUV420toRGB() +{ + Int iY, iU, iV, iR, iG, iB; + for( Int y = 0; y < m_uiHeight; y += 2 ) + { + for( Int x = 0; x < m_uiWidth; x += 2 ) + { + // Pixel (x, y). + + iY = m_pppcInputPel[0][y][x]; + iU = m_pppcInputPel[1][y >> 1][x >> 1]; + iV = m_pppcInputPel[2][y >> 1][x >> 1]; + iU -= 128; + iV -= 128; + + yuvToRgb( iY, iU, iV, iR, iG, iB ); + + m_pppcRGBPel[0][y][x] = iR; + m_pppcRGBPel[1][y][x] = iG; + m_pppcRGBPel[2][y][x] = iB; + + // Pixel (x+1, y) + + iY = m_pppcInputPel[0][y][x + 1]; + + yuvToRgb( iY, iU, iV, iR, iG, iB ); + + m_pppcRGBPel[0][y][x + 1] = iR; + m_pppcRGBPel[1][y][x + 1] = iG; + m_pppcRGBPel[2][y][x + 1] = iB; + + // Pixel (x, y+1) + + iY = m_pppcInputPel[0][y + 1][x]; + + yuvToRgb( iY, iU, iV, iR, iG, iB ); + + m_pppcRGBPel[0][y + 1][x] = iR; + m_pppcRGBPel[1][y + 1][x] = iG; + m_pppcRGBPel[2][y + 1][x] = iB; + + // Pixel (x+1, y+1) + + iY = m_pppcInputPel[0][y + 1][x + 1]; + + yuvToRgb( iY, iU, iV, iR, iG, iB ); + + m_pppcRGBPel[0][y + 1][x + 1] = iR; + m_pppcRGBPel[1][y + 1][x + 1] = iG; + m_pppcRGBPel[2][y + 1][x + 1] = iB; + + } + } +} + +Void PlaYUVerFrame::FrameFromBuffer( Pel *input_buffer, Int pel_format ) +{ + if( m_iPixelFormat != pel_format ) + { + return; + } + + UInt64 frame_bytes_input = m_uiWidth * m_uiHeight; + + switch( m_iPixelFormat ) + { + case YUV420: + memcpy( &m_pppcInputPel[0][0][0], input_buffer, frame_bytes_input * sizeof(Pel) ); + memcpy( &m_pppcInputPel[1][0][0], input_buffer + frame_bytes_input, frame_bytes_input / 4 * sizeof(Pel) ); + memcpy( &m_pppcInputPel[2][0][0], input_buffer + frame_bytes_input * 5 / 4, frame_bytes_input / 4 * sizeof(Pel) ); + YUV420toRGB(); + break; + case YUV422: + break; + case YUV400: + break; + case RGB: + break; + } +} + +UInt64 PlaYUVerFrame::getBytesPerFrame() +{ + switch( m_iPixelFormat ) + { + case YUV420: + return m_uiWidth * m_uiHeight * 1.5; + break; + case YUV422: + return m_uiWidth * m_uiHeight * 2; + break; + case YUV400: + return m_uiWidth * m_uiHeight; + break; + case RGB: + return m_uiWidth * m_uiHeight * 3; + break; + } +} + +} // NAMESPACE diff --git a/source/PlaYUVerFrame.h b/source/PlaYUVerFrame.h new file mode 100755 index 0000000..2e9ed47 --- /dev/null +++ b/source/PlaYUVerFrame.h @@ -0,0 +1,74 @@ +/* This file is a part of plaYUVer project + * Copyright (C) 2014 by plaYUVer developers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** + * \file PlaYUVerFrame.h + * \brief Video Frame handling + */ + +#ifndef __PLAYUVERFRAME_H__ +#define __PLAYUVERFRAME_H__ + +#include "config.h" + +#include +#include + +#include "TypeDef.h" + +namespace plaYUVer +{ + +class PlaYUVerFrame +{ +public: + PlaYUVerFrame( UInt width, UInt height, Int pel_format ); + ~PlaYUVerFrame(); + + Void FrameFromBuffer( Pel *input_buffer, Int pel_format ); + + enum InputStreamColorSpace + { + YUV420, YUV400, YUV422, RGB, + }; + + UInt64 getBytesPerFrame(); + + Pel*** getPelBufferYUV() + { + return m_pppcInputPel; + } + Pel*** getPelBufferRGB() + { + return m_pppcRGBPel; + } +private: + + Void YUV420toRGB(); + + UInt m_uiWidth; + UInt m_uiHeight; + Int m_iPixelFormat; + + Pel** m_pppcInputPel[3]; + Pel*** m_pppcRGBPel; +}; + +} // NAMESPACE + +#endif // __PLAYUVERFRAME_H__ From 72e6ca964344c5649277a169961950536ee3d2ec Mon Sep 17 00:00:00 2001 From: Joao Carreira Date: Sun, 2 Feb 2014 01:13:04 +0000 Subject: [PATCH 2/2] Pass variables as reference to LibAvContextHandle and change cursor handling when loading a new file --- source/InputStream.cpp | 2 +- source/LibAvContextHandle.cpp | 2 +- source/LibAvContextHandle.h | 2 +- source/SubWindowHandle.cpp | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/source/InputStream.cpp b/source/InputStream.cpp index 75e0dd2..07f36d4 100755 --- a/source/InputStream.cpp +++ b/source/InputStream.cpp @@ -130,7 +130,7 @@ Void InputStream::init( QString filename, UInt width, UInt height, Int input_for m_iPixelFormat = input_format; #ifdef USE_FFMPEG - Bool avStatus = m_cLibAvContext.initAvFormat( filename, width, height ); + Bool avStatus = m_cLibAvContext.initAvFormat( filename, width, height, input_format ); #endif if( m_uiWidth <= 0 || m_uiHeight <= 0 ) diff --git a/source/LibAvContextHandle.cpp b/source/LibAvContextHandle.cpp index e08404c..73e08ed 100755 --- a/source/LibAvContextHandle.cpp +++ b/source/LibAvContextHandle.cpp @@ -82,7 +82,7 @@ Void LibAvContextHandle::closeAvFormat() av_free( video_dst_data[0] ); } -Bool LibAvContextHandle::initAvFormat( QString filename, UInt width, UInt height ) +Bool LibAvContextHandle::initAvFormat( QString filename, UInt& width, UInt& height, Int& pixel_format ) { Bool bRet = true; int ret = 0; diff --git a/source/LibAvContextHandle.h b/source/LibAvContextHandle.h index 7b44c26..b2460b4 100755 --- a/source/LibAvContextHandle.h +++ b/source/LibAvContextHandle.h @@ -46,7 +46,7 @@ namespace plaYUVer class LibAvContextHandle { public: - Bool initAvFormat( QString filename, UInt width, UInt height ); + Bool initAvFormat( QString filename, UInt& width, UInt& height, Int& pixel_format ); Void closeAvFormat(); Bool decodeAvFormat(); diff --git a/source/SubWindowHandle.cpp b/source/SubWindowHandle.cpp index 19ade75..2c5393e 100644 --- a/source/SubWindowHandle.cpp +++ b/source/SubWindowHandle.cpp @@ -73,9 +73,8 @@ bool SubWindowHandle::loadFile( const QString &fileName ) { m_currStream.init( fileName, 0, 0, 0 ); } - QApplication::setOverrideCursor( Qt::WaitCursor ); - + QApplication::restoreOverrideCursor(); if( m_currStream.getStatus() == 0 ) { return false;