diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 81bad4b47cf04b57323733fe999f592d4e7d6d6c..0b36dbde239de33feadb347892428749b7cba874 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -75,7 +75,11 @@ void EncApp::xInitLibCfg() { VPS vps; +#if JVET_N0278_FIXES + vps.setMaxLayers ( m_maxLayers ); +#else vps.setMaxLayers ( 1 ); +#endif for(int i = 0; i < MAX_TLAYER; i++) { vps.setVPSIncludedLayerId ( 0, i ); @@ -696,6 +700,133 @@ void EncApp::xInitLib(bool isFieldCoding) // Public member functions // ==================================================================================================================== +#if JVET_N0278_FIXES +std::list<PelUnitBuf*> recBufList; + +void EncApp::createLib() +{ + m_bitstream.open( m_bitstreamFileName.c_str(), fstream::binary | fstream::out ); + if( !m_bitstream ) + { + EXIT( "Failed to open bitstream file " << m_bitstreamFileName.c_str() << " for writing\n" ); + } + + // initialize internal class & member variables + xInitLibCfg(); + xCreateLib( recBufList + ); + xInitLib( m_isField ); + + printChromaFormat(); +} + +void EncApp::destroyLib() +{ + m_cEncLib.printSummary( m_isField ); + + // delete used buffers in encoder class + m_cEncLib.deletePicBuffer(); + + for( auto &p : recBufList ) + { + delete p; + } + recBufList.clear(); + + xDestroyLib(); + + m_bitstream.close(); + + printRateSummary(); +} + +void EncApp::encode() +{ + // main encoder loop + int iNumEncoded = 0; + bool bEos = false; + + const InputColourSpaceConversion ipCSC = m_inputColourSpaceConvert; + const InputColourSpaceConversion snrCSC = ( !m_snrInternalColourSpace ) ? m_inputColourSpaceConvert : IPCOLOURSPACE_UNCHANGED; + + PelStorage trueOrgPic; + PelStorage orgPic; + const int sourceHeight = m_isField ? m_iSourceHeightOrg : m_iSourceHeight; + UnitArea unitArea( m_chromaFormatIDC, Area( 0, 0, m_iSourceWidth, sourceHeight ) ); + + orgPic.create( unitArea ); + trueOrgPic.create( unitArea ); +#if EXTENSION_360_VIDEO + TExt360AppEncTop ext360( *this, m_cEncLib.getGOPEncoder()->getExt360Data(), *( m_cEncLib.getGOPEncoder() ), orgPic ); +#endif + + while( !bEos ) + { + // read input YUV file +#if EXTENSION_360_VIDEO + if( ext360.isEnabled() ) + { + ext360.read( m_cVideoIOYuvInputFile, orgPic, trueOrgPic, ipCSC ); + } + else + { + m_cVideoIOYuvInputFile.read( orgPic, trueOrgPic, ipCSC, m_aiPad, m_InputChromaFormatIDC, m_bClipInputVideoToRec709Range ); + } +#else + m_cVideoIOYuvInputFile.read( orgPic, trueOrgPic, ipCSC, m_aiPad, m_InputChromaFormatIDC, m_bClipInputVideoToRec709Range ); +#endif + + // increase number of received frames + m_iFrameRcvd++; + + bEos = ( m_isField && ( m_iFrameRcvd == ( m_framesToBeEncoded >> 1 ) ) ) || ( !m_isField && ( m_iFrameRcvd == m_framesToBeEncoded ) ); + + bool flush = 0; + // if end of file (which is only detected on a read failure) flush the encoder of any queued pictures + if( m_cVideoIOYuvInputFile.isEof() ) + { + flush = true; + bEos = true; + m_iFrameRcvd--; + m_cEncLib.setFramesToBeEncoded( m_iFrameRcvd ); + } + + // call encoding function for one frame + if( m_isField ) + { + m_cEncLib.encode( bEos, flush ? 0 : &orgPic, flush ? 0 : &trueOrgPic, snrCSC, recBufList, + iNumEncoded, m_isTopFieldFirst ); +#if JVET_O0756_CALCULATE_HDRMETRICS + m_metricTime = m_cEncLib.getMetricTime(); +#endif + } + else + { + m_cEncLib.encode( bEos, flush ? 0 : &orgPic, flush ? 0 : &trueOrgPic, snrCSC, recBufList, + iNumEncoded ); +#if JVET_O0756_CALCULATE_HDRMETRICS + m_metricTime = m_cEncLib.getMetricTime(); +#endif + } + + // write bistream to file if necessary + if( iNumEncoded > 0 ) + { + xWriteOutput( iNumEncoded, recBufList + ); + } + // temporally skip frames + if( m_temporalSubsampleRatio > 1 ) + { +#if EXTENSION_360_VIDEO + m_cVideoIOYuvInputFile.skipFrames( m_temporalSubsampleRatio - 1, m_inputFileWidth, m_inputFileHeight, m_InputChromaFormatIDC ); +#else + m_cVideoIOYuvInputFile.skipFrames( m_temporalSubsampleRatio - 1, m_iSourceWidth - m_aiPad[0], m_iSourceHeight - m_aiPad[1], m_InputChromaFormatIDC ); +#endif + } + } +} +#else /** - create internal class - initialize internal variable @@ -825,6 +956,7 @@ void EncApp::encode() return; } +#endif // ==================================================================================================================== // Protected member functions diff --git a/source/App/EncoderApp/EncApp.h b/source/App/EncoderApp/EncApp.h index 9a85e2f9eeceff7933294125a9425cf5ffde7211..e13cffbbd70261999ae99594664ef7d0a8f1102e 100644 --- a/source/App/EncoderApp/EncApp.h +++ b/source/App/EncoderApp/EncApp.h @@ -92,7 +92,14 @@ public: EncApp(); virtual ~EncApp(); +#if JVET_N0278_FIXES + int getMaxLayers() const { return m_maxLayers; } + void createLib(); ///< main encoding function + void destroyLib(); ///< main encoding function void encode(); ///< main encoding function +#else + void encode(); ///< main encoding function +#endif void outputAU( const AccessUnit& au ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 386380bb28dcdb8e11d2fe3b109660915ffa4850..9ccef11ae2360f09692969e99bae36fdbf58ac09 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1372,6 +1372,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ( "FractionNumFrames", m_fractionOfFrames, 1.0, "Encode a fraction of the specified in FramesToBeEncoded frames" ) ( "SwitchPocPeriod", m_switchPocPeriod, 0, "Switch POC period for RPR" ) ( "UpscaledOutput", m_upscaledOutput, 0, "Output upscaled (2), decoded but in full resolution buffer (1) or decoded cropped (0, default) picture for RPR" ) +#if JVET_N0278_FIXES + ( "MaxLayers", m_maxLayers, 1, "Max numebr of layers" ) +#endif ; #if EXTENSION_360_VIDEO diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index c993b9ddab39ac0b284a62e5ec921f57f735165c..ce348d2f45911462dffb60c1bcef76c26ee0f253 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -605,6 +605,10 @@ protected: int m_switchPocPeriod; int m_upscaledOutput; ////< Output upscaled (2), decoded cropped but in full resolution buffer (1) or decoded cropped (0, default) picture for RPR. +#if JVET_N0278_FIXES + int m_maxLayers; +#endif + #if EXTENSION_360_VIDEO TExt360AppEncCfg m_ext360; friend class TExt360AppEncCfg; diff --git a/source/App/EncoderApp/encmain.cpp b/source/App/EncoderApp/encmain.cpp index 80b1a8326e90faa91e2f9198777d9f86b05dd73a..9976497a4e29bf6eed1ce2a6e35d73f3da47e5a9 100644 --- a/source/App/EncoderApp/encmain.cpp +++ b/source/App/EncoderApp/encmain.cpp @@ -116,6 +116,43 @@ int main(int argc, char* argv[]) #endif fprintf( stdout, "\n" ); +#if JVET_N0278_FIXES + std::vector<EncApp*> pcEncApp(1); + bool resized = false; + int i = 0; + + do + { + pcEncApp[i] = new EncApp; + // create application encoder class + pcEncApp[i]->create(); + + // parse configuration + try + { + if( !pcEncApp[i]->parseCfg( argc, argv ) ) + { + pcEncApp[i]->destroy(); + return 1; + } + } + catch( df::program_options_lite::ParseFailure &e ) + { + std::cerr << "Error parsing option \"" << e.arg << "\" with argument \"" << e.val << "\"." << std::endl; + return 1; + } + + pcEncApp[i]->createLib(); + + if( !resized ) + { + pcEncApp.resize( pcEncApp[i]->getMaxLayers() ); + resized = true; + } + + i++; + } while( i < pcEncApp.size() ); +#else EncApp* pcEncApp = new EncApp; // create application encoder class pcEncApp->create(); @@ -134,6 +171,7 @@ int main(int argc, char* argv[]) std::cerr << "Error parsing option \""<< e.arg <<"\" with argument \""<< e.val <<"\"." << std::endl; return 1; } +#endif #if PRINT_MACRO_VALUES printMacroSettings(); @@ -146,6 +184,29 @@ int main(int argc, char* argv[]) clock_t startClock = clock(); // call encoding function +#if JVET_N0278_FIXES + for( auto & encApp : pcEncApp ) + { +#ifndef _DEBUG + try + { +#endif + encApp->encode(); +#ifndef _DEBUG + } + catch( Exception &e ) + { + std::cerr << e.what() << std::endl; + return EXIT_FAILURE; + } + catch( const std::bad_alloc &e ) + { + std::cout << "Memory allocation failed: " << e.what() << std::endl; + return EXIT_FAILURE; + } +#endif + } +#else #ifndef _DEBUG try { @@ -163,6 +224,7 @@ int main(int argc, char* argv[]) std::cout << "Memory allocation failed: " << e.what() << std::endl; return EXIT_FAILURE; } +#endif #endif // ending time clock_t endClock = clock(); @@ -176,10 +238,26 @@ int main(int argc, char* argv[]) #else auto encTime = std::chrono::duration_cast<std::chrono::milliseconds>( endTime - startTime).count(); #endif + +#if JVET_N0278_FIXES + for( auto & encApp : pcEncApp ) + { + encApp->destroyLib(); + + // destroy application encoder class + encApp->destroy(); + + delete encApp; + } + + // destroy ROM + destroyROM(); +#else // destroy application encoder class pcEncApp->destroy(); delete pcEncApp; +#endif printf( "\n finished @ %s", std::ctime(&endTime2) ); diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index bdc7a63d15ebaec8cb171fb2a5f68d283da66063..0f8950086b2e88b4cea1e3e01f35d084c31dfe63 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_N0278_FIXES 1 + #define JVET_P0164_ALF_SYNTAX_SIMP 1 // JVET-p0164: simplify alf syntax with method2 #define JVET_P0042_FIX_INTER_DIR_CTX 1 // JVET-P0042: Fix overlap in context between the bi-pred flag for 8x8 CUs and the L0/L1 flag for all size CUs diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index b1188a23bc1a7eb23115a88dfe4c54fe710e944a..ef1adf7ef9121011c22da4ec17fd7000d9209113 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -201,11 +201,10 @@ void EncLib::destroy () delete[] m_CtxCache; #endif - - - +#if !JVET_N0278_FIXES // destroy ROM destroyROM(); +#endif return; } @@ -867,7 +866,9 @@ void EncLib::xInitVPS(VPS &vps) { // The SPS must have already been set up. // set the VPS profile information. +#if !JVET_N0278_FIXES vps.setMaxLayers(1); +#endif for (uint32_t i = 0; i < vps.getMaxLayers(); i++) { vps.setVPSIncludedLayerId(0, i);