/* * Copyright (c) 2017-2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ //! //! \file codechal_encode_mpeg2.cpp //! \brief Defines base class for MPEG2 dual-pipe encoder. //! #include "codechal_encode_mpeg2.h" #include "codechal_mmc_encode_mpeg2.h" #include "codechal_kernel_hme.h" #include "codeckrnheader.h" #include "mos_os_cp_interface_specific.h" #define CODECHAL_ENCODE_MPEG2_FCODE_X(width) ((width < 200) ? 3 : (width < 500) ? 4 : (width < 1400) ? 5 : 6) #define CODECHAL_ENCODE_MPEG2_FCODE_Y(fcodeX) ((fcodeX > 5) ? 5 : fcodeX) //! //! \enum ProfileIdc //! \brief Profile idc //! enum ProfileIdc { highProfile = 0x10, spatialProfile = 0x20, snrProfile = 0x30, mainProfile = 0x40, simpleProfile = 0x50 } ; //! //! \enum LevelIdc //! \brief Level idc //! enum LevelIdc { levelHighP = 2, levelHigh = 4, levelHigh1440 = 6, levelMain = 8, levelLow = 10 } ; //! //! \enum StartCode //! \brief Start code //! enum StartCode { startCodePrefix = 0x000001, // bit string 0000 0000 0000 0000 0000 0001 startCodePicture = 0x00, // slice_start_code = 0x01..0xAF, it is the slice_vertical_position for the slice // 0xB0, 0xB1, 0xB6 - Reserved startCodeUserData = 0xB2, startCodeSequenceHeader = 0xB3, startCodeSequenceError = 0xB4, startCodeExtension = 0xB5, startCodeSequenceEnd = 0xB7, startCodeGroupStart = 0xB8 // system start codes = 0xB9..0xFF } ; //! //! \enum BingdingTableOffsetBrcInitReset //! \brief Bingding table offset brc init reset //! enum BingdingTableOffsetBrcInitReset { brcInitResetHistory = 0, brcInitResetDistortion = 1, brcInitResetNumBindingTableEntries = 2 } ; //! //! \enum BindingTableOffsetBrcUpdate //! \brief Binding table offset brc update //! enum BindingTableOffsetBrcUpdate { brcUpdateHistory = 0, brcUpdatePakStaticOutput = 1, brcUpdatePictureStateRead = 2, brcUpdatePictureStateWrite = 3, brcUpdateMbencCurbeRead = 4, brcUpdateMbencCurbeWrite = 5, brcUpdateDistortion = 6, brcUpdateConstantData = 7, brcUpdatePicHeaderInputData = 8, brcUpdateOutputData = 9, brcUpdateNumBindingTableEntries = 10 } ; //! //! \class BrcInitResetCurbe //! \brief Brc initialization reset curbe //! class BrcInitResetCurbe { public: //! //! \struct CurbeData //! \brief Curbe data //! struct CurbeData { union { struct { uint32_t m_profileLevelMaxFrame : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW0; union { struct { uint32_t m_initBufFullInBits : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW1; union { struct { uint32_t m_bufSizeInBits : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW2; union { struct { uint32_t m_averageBitRate : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW3; union { struct { uint32_t m_maxBitRate : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW4; union { struct { uint32_t m_minBitRate : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW5; union { struct { uint32_t m_frameRateM : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW6; union { struct { uint32_t m_frameRateD : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW7; union { struct { uint32_t m_brcFlag : MOS_BITFIELD_RANGE(0,15); uint32_t m_gopP : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW8; union { struct { uint32_t m_gopB : MOS_BITFIELD_RANGE(0,15); uint32_t m_frameWidthInBytes : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW9; union { struct { uint32_t m_frameHeightInBytes : MOS_BITFIELD_RANGE(0,15); uint32_t m_avbrAccuracy : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW10; union { struct { uint32_t m_avbrConvergence : MOS_BITFIELD_RANGE(0,15); uint32_t m_minQP : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW11; union { struct { uint32_t m_maxQP : MOS_BITFIELD_RANGE(0,15); uint32_t m_noSlices : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW12; union { struct { uint32_t m_instantRateThreshold0ForP : MOS_BITFIELD_RANGE(0,7); uint32_t m_instantRateThreshold1ForP : MOS_BITFIELD_RANGE(8,15); uint32_t m_instantRateThreshold2ForP : MOS_BITFIELD_RANGE(16,23); uint32_t m_instantRateThreshold3ForP : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW13; union { struct { uint32_t m_instantRateThreshold0ForB : MOS_BITFIELD_RANGE(0,7); uint32_t m_instantRateThreshold1ForB : MOS_BITFIELD_RANGE(8,15); uint32_t m_instantRateThreshold2ForB : MOS_BITFIELD_RANGE(16,23); uint32_t m_instantRateThreshold3ForB : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW14; union { struct { uint32_t m_instantRateThreshold0ForI : MOS_BITFIELD_RANGE(0,7); uint32_t m_instantRateThreshold1ForI : MOS_BITFIELD_RANGE(8,15); uint32_t m_instantRateThreshold2ForI : MOS_BITFIELD_RANGE(16,23); uint32_t m_instantRateThreshold3ForI : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW15; union { struct { uint32_t m_deviationThreshold0ForPandB : MOS_BITFIELD_RANGE(0,7); // Signed byte uint32_t m_deviationThreshold1ForPandB : MOS_BITFIELD_RANGE(8,15); // Signed byte uint32_t m_deviationThreshold2ForPandB : MOS_BITFIELD_RANGE(16,23); // Signed byte uint32_t m_deviationThreshold3ForPandB : MOS_BITFIELD_RANGE(24,31); // Signed byte }; struct { uint32_t m_value; }; } DW16; union { struct { uint32_t m_deviationThreshold4ForPandB : MOS_BITFIELD_RANGE(0,7); // Signed byte uint32_t m_deviationThreshold5ForPandB : MOS_BITFIELD_RANGE(8,15); // Signed byte uint32_t m_deviationThreshold6ForPandB : MOS_BITFIELD_RANGE(16,23); // Signed byte uint32_t m_deviationThreshold7ForPandB : MOS_BITFIELD_RANGE(24,31); // Signed byte }; struct { uint32_t m_value; }; } DW17; union { struct { uint32_t m_deviationThreshold0ForVBR : MOS_BITFIELD_RANGE(0,7); // Signed byte uint32_t m_deviationThreshold1ForVBR : MOS_BITFIELD_RANGE(8,15); // Signed byte uint32_t m_deviationThreshold2ForVBR : MOS_BITFIELD_RANGE(16,23); // Signed byte uint32_t m_deviationThreshold3ForVBR : MOS_BITFIELD_RANGE(24,31); // Signed byte }; struct { uint32_t m_value; }; } DW18; union { struct { uint32_t m_deviationThreshold4ForVBR : MOS_BITFIELD_RANGE(0,7); // Signed byte uint32_t m_deviationThreshold5ForVBR : MOS_BITFIELD_RANGE(8,15); // Signed byte uint32_t m_deviationThreshold6ForVBR : MOS_BITFIELD_RANGE(16,23); // Signed byte uint32_t m_deviationThreshold7ForVBR : MOS_BITFIELD_RANGE(24,31); // Signed byte }; struct { uint32_t m_value; }; } DW19; union { struct { uint32_t m_deviationThreshold0ForI : MOS_BITFIELD_RANGE(0,7); // Signed byte uint32_t m_deviationThreshold1ForI : MOS_BITFIELD_RANGE(8,15); // Signed byte uint32_t m_deviationThreshold2ForI : MOS_BITFIELD_RANGE(16,23); // Signed byte uint32_t m_deviationThreshold3ForI : MOS_BITFIELD_RANGE(24,31); // Signed byte }; struct { uint32_t m_value; }; } DW20; union { struct { uint32_t m_deviationThreshold4ForI : MOS_BITFIELD_RANGE(0,7); // Signed byte uint32_t m_deviationThreshold5ForI : MOS_BITFIELD_RANGE(8,15); // Signed byte uint32_t m_deviationThreshold6ForI : MOS_BITFIELD_RANGE(16,23); // Signed byte uint32_t m_deviationThreshold7ForI : MOS_BITFIELD_RANGE(24,31); // Signed byte }; struct { uint32_t m_value; }; } DW21; union { struct { uint32_t m_value; }; } DW22; union { struct { uint32_t m_value; }; } DW23; union { struct { uint32_t m_value; }; } DW24; union { struct { uint32_t m_value; }; } DW25; }m_curbeData; //! //! \brief Constructor //! BrcInitResetCurbe(); //! //! \brief Destructor //! ~BrcInitResetCurbe(){}; static const size_t m_byteSize = sizeof(CurbeData); }; //! //! \struct BrcUpdateCurbe //! \brief BRC update curbe //! class BrcUpdateCurbe { public: //! //! \struct CurbeData //! \brief Curbe data //! struct CurbeData { union { struct { uint32_t m_targetSize : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW0; union { struct { uint32_t m_frameNumber : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW1; union { struct { uint32_t m_sliceNumber : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW2; union { struct { uint32_t m_startGAdjFrame0 : MOS_BITFIELD_RANGE(0,15); uint32_t m_startGAdjFrame1 : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW3; union { struct { uint32_t m_startGAdjFrame2 : MOS_BITFIELD_RANGE(0,15); uint32_t m_startGAdjFrame3 : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW4; union { struct { uint32_t m_targetSizeFlag : MOS_BITFIELD_RANGE(0,7); uint32_t m_brcFlag : MOS_BITFIELD_RANGE(8,15); uint32_t m_maxNumPAKs : MOS_BITFIELD_RANGE(16,23); uint32_t m_currFrameType : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW5; // This offset indicates the byte position of the q_scale_type bit // in the 2nd level batch buffer containing the INSERT_OBJ command // for inserting the picture header data into the bitstream. // This offset includes the 8 bytes of the INSERT command at the // beginning of the buffer. union { struct { uint32_t m_qScaleTypeOffset : MOS_BITFIELD_RANGE(0,15); uint32_t m_vbvDelay : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW6; // This size is the size of the entire 2nd level batch buffer // containing the INSERT_OBJ command for inserting the // picture header data into the bitstream. It includes the batch buffer end // command at the end of the buffer. union { struct { uint32_t m_picHeaderDataBufferSize :MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW7; union { struct { uint32_t m_startGlobalAdjustMult0 : MOS_BITFIELD_RANGE(0,7); uint32_t m_startGlobalAdjustMult1 : MOS_BITFIELD_RANGE(8,15); uint32_t m_startGlobalAdjustMult2 : MOS_BITFIELD_RANGE(16,23); uint32_t m_startGlobalAdjustMult3 : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW8; union { struct { uint32_t m_startGlobalAdjustMult4 : MOS_BITFIELD_RANGE(0,7); uint32_t m_startGlobalAdjustDiv0 : MOS_BITFIELD_RANGE(8,15); uint32_t m_startGlobalAdjustDiv1 : MOS_BITFIELD_RANGE(16,23); uint32_t m_startGlobalAdjustDiv2 : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW9; union { struct { uint32_t m_startGlobalAdjustDiv3 : MOS_BITFIELD_RANGE(0,7); uint32_t m_startGlobalAdjustDiv4 : MOS_BITFIELD_RANGE(8,15); uint32_t m_qpThreshold0 : MOS_BITFIELD_RANGE(16,23); uint32_t m_qpThreshold1 : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW10; union { struct { uint32_t m_qpThreshold2 : MOS_BITFIELD_RANGE(0,7); uint32_t m_qpThreshold3 : MOS_BITFIELD_RANGE(8,15); uint32_t m_gRateRatioThreshold0 : MOS_BITFIELD_RANGE(16,23); uint32_t m_gRateRatioThreshold1 : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW11; union { struct { uint32_t m_gRateRatioThreshold2 : MOS_BITFIELD_RANGE(0,7); uint32_t m_gRateRatioThreshold3 : MOS_BITFIELD_RANGE(8,15); uint32_t m_gRateRatioThreshold4 : MOS_BITFIELD_RANGE(16,23); uint32_t m_gRateRatioThreshold5 : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW12; union { struct { uint32_t m_gRateRatioThresholdQP0 : MOS_BITFIELD_RANGE(0,7); uint32_t m_gRateRatioThresholdQP1 : MOS_BITFIELD_RANGE(8,15); uint32_t m_gRateRatioThresholdQP2 : MOS_BITFIELD_RANGE(16,23); uint32_t m_gRateRatioThresholdQP3 : MOS_BITFIELD_RANGE(24,31); }; struct { uint32_t m_value; }; } DW13; union { struct { uint32_t m_gRateRatioThresholdQP4 : MOS_BITFIELD_RANGE(0,7); uint32_t m_gRateRatioThresholdQP5 : MOS_BITFIELD_RANGE(8,15); uint32_t m_gRateRatioThresholdQP6 : MOS_BITFIELD_RANGE(16,23); uint32_t m_forceToSkip : MOS_BITFIELD_RANGE(24,24); uint32_t m_reserved25 : MOS_BITFIELD_RANGE(25,31); }; struct { uint32_t m_value; }; } DW14; union { struct { uint32_t m_extraHeaders : MOS_BITFIELD_RANGE(0,15); uint32_t m_intraDcPrecisionOffset : MOS_BITFIELD_RANGE(16,31); }; struct { uint32_t m_value; }; } DW15; union { struct { uint32_t m_value; }; } DW16[16]; union { struct { uint32_t m_bindingTableIndex : MOS_BITFIELD_RANGE(0,31); }; struct { uint32_t m_value; }; } DW32[10]; }m_curbeData; //! //! \brief Constructor //! BrcUpdateCurbe(); //! //! \brief Destructor //! ~BrcUpdateCurbe(){}; static const size_t m_byteSize = sizeof(CurbeData); } ; //! //! \struct VLCode //! \brief VL code //! struct VLCode{ uint32_t m_code; uint32_t m_len; }; //! //! \struct MediaObjectInlineDataMpeg2 //! \brief Media object inline data //! struct MediaObjectInlineDataMpeg2 { // DW0 union { struct { uint32_t m_mbX : 8; //GetOsInterface()); m_osInterface = m_hwInterface->GetOsInterface(); CODECHAL_ENCODE_ASSERT(m_hwInterface->GetMfxInterface()); m_mfxInterface = m_hwInterface->GetMfxInterface(); CODECHAL_ENCODE_ASSERT(m_hwInterface->GetHcpInterface()); m_hcpInterface = m_hwInterface->GetHcpInterface(); CODECHAL_ENCODE_ASSERT(m_hwInterface->GetHucInterface()); m_hucInterface = m_hwInterface->GetHucInterface(); CODECHAL_ENCODE_ASSERT(m_hwInterface->GetVdencInterface()); m_vdencInterface = m_hwInterface->GetVdencInterface(); CODECHAL_ENCODE_ASSERT(m_hwInterface->GetMiInterface()); m_miInterface = m_hwInterface->GetMiInterface(); auto renderInterface = m_hwInterface->GetRenderInterface(); CODECHAL_ENCODE_ASSERT(renderInterface); m_stateHeapInterface = renderInterface->m_stateHeapInterface; CODECHAL_ENCODE_ASSERT(m_stateHeapInterface); MOS_ZeroMemory(&m_picIdx, sizeof(m_picIdx)); MOS_ZeroMemory(&m_refList, sizeof(m_refList)); MOS_ZeroMemory(&m_4xMEMVDataBuffer, sizeof(m_4xMEMVDataBuffer)); MOS_ZeroMemory(&m_batchBufForMEDistBuffer, sizeof(m_batchBufForMEDistBuffer)); MOS_ZeroMemory(&m_mbEncBindingTable, sizeof(m_mbEncBindingTable)); MOS_ZeroMemory(&m_4xMEDistortionBuffer, sizeof(m_4xMEDistortionBuffer)); MOS_ZeroMemory(&m_brcBuffers, sizeof(m_brcBuffers)); MOS_ZeroMemory(&m_mbQpDataSurface, sizeof(m_mbQpDataSurface)); uint8_t i; for (i = 0; i < CODECHAL_ENCODE_BRC_IDX_NUM; i++) { m_brcKernelStates[i] = MHW_KERNEL_STATE(); } for (i = 0; i < mbEncKernelIdxNum; i++) { m_mbEncKernelStates[i] = MHW_KERNEL_STATE(); } m_interlacedFieldDisabled = true; // Always true since interlaced field is no longer supported. m_firstField = true; m_hwWalker = true; m_fieldScalingOutputInterleaved = true; m_hmeSupported = true; m_kuid = IDR_CODEC_AllMPEG2Enc; MOS_USER_FEATURE_VALUE_DATA userFeatureData; MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData)); MOS_UserFeature_ReadValue_ID( nullptr, __MEDIA_USER_FEATURE_VALUE_SINGLE_TASK_PHASE_ENABLE_ID, &userFeatureData, m_osInterface->pOsContext); m_singleTaskPhaseSupported = (userFeatureData.i32Data) ? true : false; m_hwInterface->GetStateHeapSettings()->dwNumSyncTags = m_numSyncTags; m_hwInterface->GetStateHeapSettings()->dwDshSize = m_initDshSize; m_useCmScalingKernel = true; } CodechalEncodeMpeg2::~CodechalEncodeMpeg2() { MOS_Delete(m_hmeKernel); } MOS_STATUS CodechalEncodeMpeg2::Initialize(CodechalSetting * codecHalSettings) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::Initialize(codecHalSettings)); CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface); CODECHAL_ENCODE_CHK_NULL_RETURN(m_hwInterface); CODECHAL_ENCODE_CHK_NULL_RETURN(m_miInterface); CODECHAL_ENCODE_CHK_NULL_RETURN(m_stateHeapInterface); m_frameNumB = 0; // Offset + Size of MB + size of MV m_mbCodeStrideInDW = 16; uint32_t fieldNumMBs = m_picWidthInMb * ((m_picHeightInMb + 1) >> 1); // 12 DW for MB + 4 DW for MV m_mbCodeSize = fieldNumMBs * 2 * 16 * sizeof(uint32_t); #if (_DEBUG || _RELEASE_INTERNAL) MOS_USER_FEATURE_VALUE_DATA userFeatureData; MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData)); MOS_UserFeature_ReadValue_ID( nullptr, __MEDIA_USER_FEATURE_VALUE_MPEG2_ENCODE_BRC_DISTORTION_BUFFER_ENABLE_ID, &userFeatureData, m_osInterface->pOsContext); m_brcDistortionBufferSupported = (userFeatureData.i32Data) ? true : false; MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData)); MOS_UserFeature_ReadValue_ID( nullptr, __MEDIA_USER_FEATURE_VALUE_MPEG2_SLICE_STATE_ENABLE_ID, &userFeatureData, m_osInterface->pOsContext); m_sliceStateEnable = (userFeatureData.i32Data) ? true : false; #endif // Initialize kernel State CODECHAL_ENCODE_CHK_STATUS_RETURN(InitKernelState()); if (m_singleTaskPhaseSupported) { m_maxBtCount = GetMaxBtCount(); } // Picture Level Commands m_hwInterface->GetMfxStateCommandsDataSize( CODECHAL_ENCODE_MODE_MPEG2, &m_pictureStatesSize, &m_picturePatchListSize, 0); // Slice Level Commands (cannot be placed in 2nd level batch) m_hwInterface->GetMfxPrimitiveCommandsDataSize( CODECHAL_ENCODE_MODE_MPEG2, &m_sliceStatesSize, &m_slicePatchListSize, 0); CODECHAL_ENCODE_CHK_STATUS_RETURN(InitMmcState()); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::AllocateBuffer( PMOS_RESOURCE buffer, uint32_t bufSize, PCCHAR name) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_CHK_NULL_RETURN(buffer); MOS_ALLOC_GFXRES_PARAMS allocParams; MOS_ZeroMemory(&allocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS)); allocParams.Type = MOS_GFXRES_BUFFER; allocParams.TileType = MOS_TILE_LINEAR; allocParams.Format = Format_Buffer; allocParams.dwBytes = bufSize; allocParams.pBufName = name; eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource( m_osInterface, &allocParams, buffer); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name); return eStatus; } CodechalResLock bufLock(m_osInterface, buffer); auto data = bufLock.Lock(CodechalResLock::writeOnly); CODECHAL_ENCODE_CHK_NULL_RETURN(data); MOS_ZeroMemory(data, bufSize); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::AllocateBuffer2D( PMOS_SURFACE surface, uint32_t surfWidth, uint32_t surfHeight, PCCHAR name) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_CHK_NULL_RETURN(surface); MOS_ZeroMemory(surface, sizeof(*surface)); surface->TileType = MOS_TILE_LINEAR; surface->bArraySpacing = true; surface->Format = Format_Buffer_2D; surface->dwWidth = MOS_ALIGN_CEIL(surfWidth, 64); surface->dwHeight = surfHeight; surface->dwPitch = surface->dwWidth; MOS_ALLOC_GFXRES_PARAMS AllocParamsForBuffer2D; MOS_ZeroMemory(&AllocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS)); AllocParamsForBuffer2D.Type = MOS_GFXRES_2D; AllocParamsForBuffer2D.TileType = surface->TileType; AllocParamsForBuffer2D.Format = surface->Format; AllocParamsForBuffer2D.dwWidth = surface->dwWidth; AllocParamsForBuffer2D.dwHeight = surface->dwHeight; AllocParamsForBuffer2D.pBufName = name; eStatus = (MOS_STATUS)m_osInterface->pfnAllocateResource( m_osInterface, &AllocParamsForBuffer2D, &surface->OsResource); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name); return eStatus; } surface->dwPitch = (uint32_t)surface->OsResource.pGmmResInfo->GetRenderPitch(); CodechalResLock bufLock(m_osInterface, &surface->OsResource); auto data = bufLock.Lock(CodechalResLock::writeOnly); CODECHAL_ENCODE_CHK_NULL_RETURN(data); MOS_ZeroMemory(data, surface->dwPitch * surface->dwHeight); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::AllocateBatchBuffer( PMHW_BATCH_BUFFER batchBuffer, uint32_t bufSize, PCCHAR name) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_CHK_NULL_RETURN(batchBuffer); MOS_ZeroMemory( batchBuffer, sizeof(MHW_BATCH_BUFFER)); batchBuffer->bSecondLevel = true; eStatus = Mhw_AllocateBb( m_osInterface, batchBuffer, nullptr, bufSize); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate %s.", name); return eStatus; } eStatus = Mhw_LockBb(m_osInterface, batchBuffer); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_ENCODE_ASSERTMESSAGE("Failed to lock %s.", name); return eStatus; } MOS_ZeroMemory(batchBuffer->pData, bufSize); eStatus = Mhw_UnlockBb( m_osInterface, batchBuffer, false); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_ENCODE_ASSERTMESSAGE("Failed to unlock %s.", name); return eStatus; } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::AllocateBrcResources() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; // BRC history buffer uint32_t bufSize = m_brcHistoryBufferSize; CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer( &m_brcBuffers.resBrcHistoryBuffer, bufSize, "BRC History Buffer")); // PAK Statistics buffer bufSize = m_brcPakStatisticsSize; CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer( &m_brcBuffers.resBrcPakStatisticBuffer[0], bufSize, "BRC PAK Statistics Buffer")); // PAK IMG_STATEs buffer bufSize = BRC_IMG_STATE_SIZE_PER_PASS * m_mfxInterface->GetBrcNumPakPasses(); for (uint8_t i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++) { CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer( &m_brcBuffers.resBrcImageStatesReadBuffer[i], bufSize, "PAK IMG State Read Buffer")); } CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer( &m_brcBuffers.resBrcImageStatesWriteBuffer, bufSize, "PAK IMG State Write Buffer")); // Picture header input and output buffers bufSize = m_brcPicHeaderSurfaceSize; CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer( &m_brcBuffers.resBrcPicHeaderInputBuffer, bufSize, "Picture Header Input Buffer")); CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer( &m_brcBuffers.resBrcPicHeaderOutputBuffer, bufSize, "Picture Header Output Buffer")); uint32_t surfWidth = m_hwInterface->m_mpeg2BrcConstantSurfaceWidth; uint32_t surfHeight = m_hwInterface->m_mpeg2BrcConstantSurfaceHeight; for (uint8_t i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++) { //BRC Constant Data Surfaces CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D( &m_brcBuffers.sBrcConstantDataBuffer[i], surfWidth, surfHeight, "BRC Constant Data Buffer")); } // BRC Distortion Surface uint32_t downscaledFieldHeightInMB4x = (m_downscaledHeightInMb4x + 1) >> 1; surfWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64); surfHeight = 2 * MOS_ALIGN_CEIL((downscaledFieldHeightInMB4x * 4), 8); CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D( &m_brcBuffers.sMeBrcDistortionBuffer, surfWidth, surfHeight, "BRC Distortion Surface Buffer")); // VME batch buffer for distortion surface for (uint8_t i = 0; i < NUM_ENCODE_BB_TYPE; i++) { uint32_t currNumMBs; if (i == MB_ENC_Frame_BB) { currNumMBs = m_downscaledWidthInMb4x * m_downscaledHeightInMb4x; } else { currNumMBs = m_downscaledWidthInMb4x * downscaledFieldHeightInMB4x; } bufSize = m_hwInterface->GetMediaObjectBufferSize( currNumMBs, sizeof(MediaObjectInlineDataMpeg2)); AllocateBatchBuffer(&m_batchBufForMEDistBuffer[i], bufSize, "ME Distortion Buffer"); } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::AllocateEncResources() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; uint32_t downscaledFieldHeightInMB4x = (m_downscaledHeightInMb4x + 1) >> 1; if (m_hmeSupported) { if (m_hmeKernel) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hmeKernel->AllocateResources()); } else { uint32_t bufWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64); // MediaBlockRW requires pitch multiple of 64 bytes when linear. uint32_t bufHeight = (m_downscaledHeightInMb4x * 2 * 4 * CODECHAL_ENCODE_ME_DATA_SIZE_MULTIPLIER); CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D( &m_4xMEMVDataBuffer, bufWidth, bufHeight, "4xME MV Data Buffer")); bufWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64); bufHeight = 2 * MOS_ALIGN_CEIL((downscaledFieldHeightInMB4x * 4 * 10), 8); CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateBuffer2D( &m_4xMEDistortionBuffer, bufWidth, bufHeight, "4xME Distortion Buffer")); } } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::AllocateResources() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncoderState::AllocateResources()); // Allocate Ref Lists CodecHalAllocateDataList( m_refList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2); if (m_encEnabled) { eStatus = AllocateEncResources(); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate ENC resources."); return eStatus; } eStatus = AllocateBrcResources(); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate BRC resources."); return eStatus; } } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::FreeBrcResources() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcHistoryBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_brcBuffers.resBrcHistoryBuffer); } if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcPakStatisticBuffer[0])) { m_osInterface->pfnFreeResource( m_osInterface, &m_brcBuffers.resBrcPakStatisticBuffer[0]); } uint32_t i; for (i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++) { if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcImageStatesReadBuffer[i])) { m_osInterface->pfnFreeResource( m_osInterface, &m_brcBuffers.resBrcImageStatesReadBuffer[i]); } } if (!Mos_ResourceIsNull(&m_brcBuffers.resBrcImageStatesWriteBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_brcBuffers.resBrcImageStatesWriteBuffer); } for (i = 0; i < CODECHAL_ENCODE_RECYCLED_BUFFER_NUM; i++) { if (!Mos_ResourceIsNull(&m_brcBuffers.sBrcConstantDataBuffer[i].OsResource)) { m_osInterface->pfnFreeResource( m_osInterface, &m_brcBuffers.sBrcConstantDataBuffer[i].OsResource); } } if (!Mos_ResourceIsNull(&m_brcBuffers.sMeBrcDistortionBuffer.OsResource)) { m_osInterface->pfnFreeResource( m_osInterface, &m_brcBuffers.sMeBrcDistortionBuffer.OsResource); } if(!Mos_ResourceIsNull(&m_brcBuffers.resBrcPicHeaderInputBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_brcBuffers.resBrcPicHeaderInputBuffer); } if(!Mos_ResourceIsNull(&m_brcBuffers.resBrcPicHeaderOutputBuffer)) { m_osInterface->pfnFreeResource( m_osInterface, &m_brcBuffers.resBrcPicHeaderOutputBuffer); } for (i = 0; i < NUM_ENCODE_BB_TYPE; i++) { if (!Mos_ResourceIsNull(&m_batchBufForMEDistBuffer[i].OsResource)) { Mhw_FreeBb(m_osInterface, &m_batchBufForMEDistBuffer[i], nullptr); } } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::FreeEncResources() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; if (m_hmeSupported) { // 4xME ME MV data buffer if (!Mos_ResourceIsNull(&m_4xMEMVDataBuffer.OsResource)) { m_osInterface->pfnFreeResource( m_osInterface, &m_4xMEMVDataBuffer.OsResource); } // 4xME distortion buffer if (!Mos_ResourceIsNull(&m_4xMEDistortionBuffer.OsResource)) { m_osInterface->pfnFreeResource( m_osInterface, &m_4xMEDistortionBuffer.OsResource); } } return eStatus; } void CodechalEncodeMpeg2::FreeResources() { CODECHAL_ENCODE_FUNCTION_ENTER; CodechalEncoderState::FreeResources(); // Release Ref Lists CodecHalFreeDataList(m_refList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2); if (m_encEnabled) { FreeBrcResources(); FreeEncResources(); } } MOS_STATUS CodechalEncodeMpeg2::CheckProfileAndLevel() { MOS_STATUS eStatus = MOS_STATUS_INVALID_PARAMETER; CODECHAL_ENCODE_FUNCTION_ENTER; switch(m_seqParams->m_profile) { case highProfile: case mainProfile: case simpleProfile: break; default: return eStatus; break; } switch(m_seqParams->m_level) { case levelHigh: case levelHigh1440: case levelMain: case levelLow: case levelHighP: break; default: return eStatus; break; } eStatus = MOS_STATUS_SUCCESS; return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SetSequenceStructs() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; m_oriFrameHeight = m_seqParams->m_frameHeight; m_oriFrameWidth = m_seqParams->m_frameWidth; if (m_seqParams->m_progressiveSequence) { m_picHeightInMb = (uint16_t)(CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_oriFrameHeight)); } else { // For interlaced frame, align to 32 pixels. m_picHeightInMb = (uint16_t)((CODECHAL_GET_WIDTH_IN_BLOCKS(m_oriFrameHeight, (CODECHAL_MACROBLOCK_WIDTH << 1))) << 1); } m_picWidthInMb = (uint16_t)(CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_oriFrameWidth)); m_frameWidth = m_picWidthInMb * CODECHAL_MACROBLOCK_WIDTH; m_frameHeight = m_picHeightInMb * CODECHAL_MACROBLOCK_HEIGHT; // HME Scaling WxH m_downscaledWidthInMb4x = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_frameWidth / SCALE_FACTOR_4x); m_downscaledHeightInMb4x = CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_frameHeight / SCALE_FACTOR_4x); m_downscaledWidth4x = m_downscaledWidthInMb4x * CODECHAL_MACROBLOCK_WIDTH; m_downscaledHeight4x = m_downscaledHeightInMb4x * CODECHAL_MACROBLOCK_HEIGHT; MotionEstimationDisableCheck(); m_targetUsage = m_seqParams->m_targetUsage & 0x7; m_kernelMode = m_targetUsageToKernelMode[m_targetUsage]; CODECHAL_ENCODE_CHK_STATUS_RETURN(CheckProfileAndLevel()); m_brcEnabled = CodecHalIsRateControlBrc(m_seqParams->m_rateControlMethod, CODECHAL_MPEG2); // Mb Qp data is only enabled for CQP if (m_brcEnabled) { m_mbQpDataEnabled = false; } m_brcReset = m_seqParams->m_resetBRC; m_avbrAccuracy = 30; m_avbrConvergence = 150; return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SetPictureStructs() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; if ((m_picParams->m_pictureCodingType < I_TYPE) || (m_picParams->m_pictureCodingType > B_TYPE)) { eStatus = MOS_STATUS_INVALID_PARAMETER; return eStatus; } if (Mos_ResourceIsNull(&m_reconSurface.OsResource) && (!m_picParams->m_useRawPicForRef || m_pakEnabled)) { eStatus = MOS_STATUS_INVALID_PARAMETER; return eStatus; } // Sync initialize if ((m_firstFrame) || (m_codecFunction == CODECHAL_FUNCTION_ENC) || (!m_brcEnabled && m_picParams->m_useRawPicForRef) || (!m_brcEnabled && (m_picParams->m_pictureCodingType == I_TYPE))) { m_waitForPak = false; } else { m_waitForPak = true; } if (m_codecFunction != CODECHAL_FUNCTION_ENC) { m_signalEnc = true; } else { m_signalEnc = false; } m_pictureCodingType = m_picParams->m_pictureCodingType; m_mbEncForcePictureCodingType = 0; // f_code checking. uint32_t fcodeX = CODECHAL_ENCODE_MPEG2_FCODE_X(m_frameWidth); uint32_t fcodeY = CODECHAL_ENCODE_MPEG2_FCODE_Y(fcodeX); if (m_pictureCodingType == I_TYPE) { if ((m_picParams->m_fcode00 > fcodeX) || (m_picParams->m_fcode01 > fcodeY) || (m_picParams->m_fcode00 == 0) || (m_picParams->m_fcode01 == 0)) { m_picParams->m_fcode00 = fcodeX; m_picParams->m_fcode01 = fcodeY; } } else if (m_pictureCodingType == P_TYPE) { if ((m_picParams->m_fcode00 > fcodeX) || (m_picParams->m_fcode01 > fcodeY) || (m_picParams->m_fcode00 == 0) || (m_picParams->m_fcode01 == 0)) { m_picParams->m_fcode00 = fcodeX; m_picParams->m_fcode01 = fcodeY; } } else // B picture { if ((m_picParams->m_fcode00 > fcodeX) || (m_picParams->m_fcode01 > fcodeY) || (m_picParams->m_fcode10 > fcodeX) || (m_picParams->m_fcode11 > fcodeY) || (m_picParams->m_fcode00 == 0) || (m_picParams->m_fcode01 == 0) || (m_picParams->m_fcode10 == 0) || (m_picParams->m_fcode11 == 0)) { m_picParams->m_fcode00 = fcodeX; m_picParams->m_fcode01 = fcodeY; m_picParams->m_fcode10 = fcodeX; m_picParams->m_fcode11 = fcodeY; } } if (m_picParams->m_fieldCodingFlag == 0) { m_frameFieldHeight = m_frameHeight; m_frameFieldHeightInMb = m_picHeightInMb; m_downscaledFrameFieldHeightInMb4x = m_downscaledHeightInMb4x; } else { m_frameFieldHeight = ((m_frameHeight + 1) >> 1); m_frameFieldHeightInMb = ((m_picHeightInMb + 1) >> 1); m_downscaledFrameFieldHeightInMb4x = ((m_downscaledHeightInMb4x + 1) >> 1); } m_statusReportFeedbackNumber = m_picParams->m_statusReportFeedbackNumber; m_lastPicInStream = m_picParams->m_lastPicInStream; m_currOriginalPic = m_picParams->m_currOriginalPic; m_currReconstructedPic = m_picParams->m_currReconstructedPic; uint8_t currRefIdx = m_picParams->m_currReconstructedPic.FrameIdx; ENCODE_CHK_COND_RETURN(currRefIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2, "currRefIdx cannot bigger than 128."); m_refList[currRefIdx]->sRefRawBuffer = m_rawSurface; m_refList[currRefIdx]->sRefReconBuffer = m_reconSurface; m_refList[currRefIdx]->resBitstreamBuffer = m_resBitstreamBuffer; if (m_pictureCodingType == I_TYPE) { m_picIdx[0].bValid = m_picIdx[1].bValid = 0; m_refList[currRefIdx]->bUsedAsRef = true; m_refList[currRefIdx]->ucNumRef = 0; } else if (m_pictureCodingType == P_TYPE) { if (m_picParams->m_refFrameList[0].PicFlags != PICTURE_INVALID) { m_picIdx[0].bValid = 1; m_picIdx[0].ucPicIdx = m_picParams->m_refFrameList[0].FrameIdx; } m_picIdx[1].bValid = 0; m_refList[currRefIdx]->bUsedAsRef = true; m_refList[currRefIdx]->RefList[0] = m_picParams->m_refFrameList[0]; m_refList[currRefIdx]->ucNumRef = 1; } else// B_TYPE { if (m_picParams->m_refFrameList[0].PicFlags != PICTURE_INVALID) { m_picIdx[0].bValid = 1; m_picIdx[0].ucPicIdx = m_picParams->m_refFrameList[0].FrameIdx; } if (m_picParams->m_refFrameList[1].PicFlags != PICTURE_INVALID) { m_picIdx[1].bValid = 1; m_picIdx[1].ucPicIdx = m_picParams->m_refFrameList[1].FrameIdx; } m_refList[currRefIdx]->bUsedAsRef = false; } m_currRefList = m_refList[currRefIdx]; if (m_codecFunction == CODECHAL_FUNCTION_ENC) { CODECHAL_ENCODE_CHK_NULL_RETURN(m_encodeParams.presMbCodeSurface); m_resMbCodeSurface = *(m_encodeParams.presMbCodeSurface); } else if (m_codecFunction == CODECHAL_FUNCTION_ENC_PAK) { // the actual MbCode/MvData surface to be allocated later m_trackedBuf->SetAllocationFlag(true); } m_hmeEnabled = m_hmeSupported && m_pictureCodingType != I_TYPE; if (m_brcEnabled) { m_numPasses = (uint8_t)(m_mfxInterface->GetBrcNumPakPasses() - 1); // 1 original plus extra to handle BRC } // if GOP structure is I-frame only, we use 3 non-ref slots for tracked buffer m_gopIsIdrFrameOnly = (m_picParams->m_gopPicSize == 1 && m_picParams->m_gopRefDist == 0); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SetSliceGroups() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; uint32_t mbCount = 0; auto bsBuffer = &m_bsBuffer; auto slcParams = m_sliceParams; auto slcData = m_slcData; PCODEC_ENCODER_SLCDATA slcDataPrevStart = nullptr; for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++) { // Slice width should equal picture width, MBs should be on same row CODECHAL_ENCODE_CHK_NULL_RETURN(slcData); CODECHAL_ENCODE_CHK_NULL_RETURN(slcParams); CODECHAL_ENCODE_ASSERT((slcParams->m_numMbsForSlice % m_picWidthInMb) == 0); CODECHAL_ENCODE_ASSERT(slcParams->m_numMbsForSlice <= m_picWidthInMb); if ((slcParams->m_quantiserScaleCode < 1) || (slcParams->m_quantiserScaleCode > 31)) { slcParams->m_quantiserScaleCode = 1; } // Determine slice groups if (slcCount == 0) { // First slice slcDataPrevStart = slcData; slcData->SliceGroup |= SLICE_GROUP_START; if (m_codecFunction == (CODECHAL_FUNCTION_ENC | CODECHAL_FUNCTION_PAK)) { slcData->SliceOffset = bsBuffer->SliceOffset; // Make slice header uint8_t aligned, all start codes are uint8_t aligned while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } for (uint32_t i = 0; i < 8; i++) { PutBit(bsBuffer, 0); } slcData->BitSize = bsBuffer->BitSize = (uint32_t)((bsBuffer->pCurrent - bsBuffer->SliceOffset - bsBuffer->pBase) * 8 + bsBuffer->BitOffset); bsBuffer->SliceOffset = (uint32_t)(bsBuffer->pCurrent - bsBuffer->pBase + (bsBuffer->BitOffset != 0)); // start at next byte } else { slcData->SliceOffset = bsBuffer->SliceOffset; slcData->BitSize = bsBuffer->BitSize; } } else { // Compare with prev slice to see if curr slice is start of new slice group PCODEC_ENCODER_SLCDATA slcDataPrev = slcData - 1; CodecEncodeMpeg2SliceParmas *slcParamsPrev = slcParams - 1; // Start of a new slice group if gap in slices or quantiser_scale_code/IntraSlice changes uint32_t mbPrevEnd = (slcParamsPrev->m_firstMbY * m_picWidthInMb) + slcParamsPrev->m_firstMbX + slcParamsPrev->m_numMbsForSlice; uint32_t mbCurrStart = (slcParams->m_firstMbY * m_picWidthInMb) + slcParams->m_firstMbX; if ((mbPrevEnd != mbCurrStart) || (slcParamsPrev->m_quantiserScaleCode != slcParams->m_quantiserScaleCode) || (slcParamsPrev->m_intraSlice != slcParams->m_intraSlice)) { slcDataPrev->SliceGroup |= SLICE_GROUP_END; slcData->SliceGroup |= SLICE_GROUP_START; slcDataPrevStart->NextSgMbXCnt = slcParams->m_firstMbX; slcDataPrevStart->NextSgMbYCnt = slcParams->m_firstMbY; slcDataPrevStart = slcData; slcData->SliceOffset = bsBuffer->SliceOffset; // Make slice header uint8_t aligned, all start codes are uint8_t aligned while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } for (uint32_t i = 0; i < 8; i++) { PutBit(bsBuffer, 0); } slcData->BitSize = bsBuffer->BitSize = (uint32_t)((bsBuffer->pCurrent - bsBuffer->SliceOffset - bsBuffer->pBase) * 8 + bsBuffer->BitOffset); bsBuffer->SliceOffset = (uint32_t)(bsBuffer->pCurrent - bsBuffer->pBase + (bsBuffer->BitOffset != 0)); // start at next byte } } if (slcCount == (m_numSlices - 1)) { // Last slice slcData->SliceGroup |= SLICE_GROUP_END; slcDataPrevStart->SliceGroup |= SLICE_GROUP_LAST; slcDataPrevStart->NextSgMbXCnt = 0; slcDataPrevStart->NextSgMbYCnt = m_frameFieldHeightInMb; } slcData->CmdOffset = mbCount * m_mbCodeStrideInDW * sizeof(uint32_t); mbCount += slcParams->m_numMbsForSlice; slcParams++; slcData++; } return eStatus; } uint32_t CodechalEncodeMpeg2::GetCurByteOffset(BSBuffer* bsBuffer) { return (uint32_t)(bsBuffer->pCurrent - bsBuffer->pBase); } MOS_STATUS CodechalEncodeMpeg2::PackDisplaySeqExtension() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto bsBuffer = &m_bsBuffer; // Make start code uint8_t aligned while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } // extension_start_code PutBits(bsBuffer, startCodePrefix, 24); PutBits(bsBuffer, startCodeExtension, 8); // extension_start_code_identifier PutBits(bsBuffer, Mpeg2sequenceDisplayExtension, 4); // video_format PutBits(bsBuffer, m_vuiParams->m_videoFormat, 3); // colour_description PutBit(bsBuffer, m_vuiParams->m_colourDescription); if (m_vuiParams->m_colourDescription) { // colour_primaries PutBits(bsBuffer, m_vuiParams->m_colourPrimaries, 8); // transfer_characteristics PutBits(bsBuffer, m_vuiParams->m_transferCharacteristics, 8); // matrix_coefficients PutBits(bsBuffer, m_vuiParams->m_matrixCoefficients, 8); } // display_horizontal_size PutBits(bsBuffer, m_vuiParams->m_displayHorizontalSize, 14); // marker_bit PutBit(bsBuffer, 1); // display_vertical_size PutBits(bsBuffer, m_vuiParams->m_displayVerticalSize, 14); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackSeqExtension() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto bsBuffer = &m_bsBuffer; // Make start code uint8_t aligned while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } // extension_start_code PutBits(bsBuffer, startCodePrefix, 24); PutBits(bsBuffer, startCodeExtension, 8); // extension_start_code_identifier PutBits(bsBuffer, Mpeg2sequenceExtension, 4); // profile_and_level_indication PutBits(bsBuffer, ((m_seqParams->m_profile & 0x70) | (m_seqParams->m_level & 0xF)), 8); // progressive_sequence PutBit(bsBuffer, m_seqParams->m_progressiveSequence); // chroma_format PutBits(bsBuffer, m_seqParams->m_chromaFormat, 2); // horizontal_size_extension PutBits(bsBuffer, ((m_seqParams->m_frameWidth >> 12) & 0x3), 2); // vertical_size_extension PutBits(bsBuffer, ((m_seqParams->m_frameHeight >> 12) & 0x3), 2); // bit_rate_extension PutBits(bsBuffer, ((MOS_ROUNDUP_DIVIDE(m_seqParams->m_bitrate * CODECHAL_ENCODE_BRC_KBPS, 400)) >> 18) & 0xFFF, 12); // marker_bit PutBit(bsBuffer, 1); // vbv_buffer_size_extension 8 uimsbf PutBits(bsBuffer, ((m_seqParams->m_vbvBufferSize >> 10) & 0xFF), 8); // low_delay PutBit(bsBuffer, m_seqParams->m_lowDelay); // frame_rate_extension_n PutBits(bsBuffer, m_seqParams->m_frameRateExtN, 2); // frame_rate_extension_d PutBits(bsBuffer, m_seqParams->m_frameRateExtD, 5); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackSeqHeader() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto bsBuffer = &m_bsBuffer; // Make start code uint8_t aligned while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } // sequence_start_code PutBits(bsBuffer, startCodePrefix, 24); PutBits(bsBuffer, startCodeSequenceHeader, 8); // horizontal_size_value CODECHAL_ENCODE_ASSERT((m_seqParams->m_frameWidth & 0xFFF) != 0); // Avoid start code emulation PutBits(bsBuffer, (m_seqParams->m_frameWidth & 0xFFF), 12); // vertical_size_value CODECHAL_ENCODE_ASSERT((m_seqParams->m_frameHeight & 0xFFF) != 0); // Avoid start code emulation PutBits(bsBuffer, (m_seqParams->m_frameHeight & 0xFFF), 12); // aspect_ratio_information CODECHAL_ENCODE_ASSERT((m_seqParams->m_aspectRatio > 0) && (m_seqParams->m_aspectRatio < 5)); PutBits(bsBuffer, m_seqParams->m_aspectRatio, 4); // frame_rate_code CODECHAL_ENCODE_ASSERT((m_seqParams->m_frameRateCode > 0) & (m_seqParams->m_frameRateCode < 15)); PutBits(bsBuffer, m_seqParams->m_frameRateCode, 4); // bit_rate_value if (m_seqParams->m_rateControlMethod == RATECONTROL_VBR) { // In Architecture prototype, the bit_rate_value of sequence header is set to m_maxBitRate not the target bit-rate for VBR case. PutBits(bsBuffer, ((MOS_ROUNDUP_DIVIDE(m_seqParams->m_maxBitRate * CODECHAL_ENCODE_BRC_KBPS, 400)) & 0x3FFFF), 18); } else { PutBits(bsBuffer, ((MOS_ROUNDUP_DIVIDE(m_seqParams->m_bitrate * CODECHAL_ENCODE_BRC_KBPS, 400)) & 0x3FFFF), 18); } // marker_bit PutBit(bsBuffer, 1); // vbv_buffer_size_value PutBits(bsBuffer, (m_seqParams->m_vbvBufferSize & 0x3FF), 10); // constrained_parameters_flag PutBit(bsBuffer, 0); // m_loadIntraQuantiserMatrix PutBit(bsBuffer, m_qMatrixParams->m_newQmatrix[0]); if (m_qMatrixParams->m_newQmatrix[0]) { // m_intraQuantiserMatrix[64] for (uint8_t i = 0; i < 64; i++) { // Already in zig-zag scan order PutBits(bsBuffer, m_qMatrixParams->m_qmatrix[0][i], 8); } } // m_loadNonIntraQuantiserMatrix PutBit(bsBuffer, m_qMatrixParams->m_newQmatrix[1]); if (m_qMatrixParams->m_newQmatrix[1]) { // m_nonIntraQuantiserMatrix[64] for (uint8_t i = 0; i < 64; i++) { // Already in zig-zag scan order PutBits(bsBuffer, m_qMatrixParams->m_qmatrix[1][i], 8); } } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackSequenceParams() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; // picture header CODECHAL_ENCODE_CHK_STATUS_RETURN(PackSeqHeader()); // picture coding extension CODECHAL_ENCODE_CHK_STATUS_RETURN(PackSeqExtension()); // optional sequence display extension (& user data) if (m_newVuiData) { CODECHAL_ENCODE_CHK_STATUS_RETURN(PackDisplaySeqExtension()); m_newVuiData = false; } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackPicCodingExtension() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto bsBuffer = &m_bsBuffer; // All start codes are uint8_t aligned while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } // extension_start_code PutBits(bsBuffer, startCodePrefix, 24); PutBits(bsBuffer, startCodeExtension, 8); // extension_start_code_identifier PutBits(bsBuffer, Mpeg2pictureCodingExtension, 4); // f_codes values 1-9 or 15; 0 or 1-14 are reserved if ((m_picParams->m_pictureCodingType == I_TYPE) && !m_picParams->m_concealmentMotionVectors) { // f_code[0][0], forward horizontal PutBits(bsBuffer, 0xF, 4); // f_code[0][1], forward vertical PutBits(bsBuffer, 0xF, 4); // f_code[1][0], backward horizontal PutBits(bsBuffer, 0xF, 4); // f_code[1][1], backward vertical PutBits(bsBuffer, 0xF, 4); } else { // f_code[0][0], forward horizontal PutBits(bsBuffer, m_picParams->m_fcode00, 4); // f_code[0][1], forward vertical PutBits(bsBuffer, m_picParams->m_fcode01, 4); if ((m_picParams->m_pictureCodingType == I_TYPE) || (m_picParams->m_pictureCodingType == P_TYPE)) { // f_code[1][0], backward horizontal PutBits(bsBuffer, 0xF, 4); // f_code[1][1], backward vertical PutBits(bsBuffer, 0xF, 4); } else { // f_code[1][0], backward horizontal PutBits(bsBuffer, m_picParams->m_fcode10, 4); // f_code[1][1], backward vertical PutBits(bsBuffer, m_picParams->m_fcode11, 4); } } // store byte offset of intra_dc_precision m_intraDcPrecisionOffset = GetCurByteOffset(bsBuffer); // intra_dc_precision PutBits(bsBuffer, m_picParams->m_intraDCprecision, 2); // picture_structure PutBits(bsBuffer, (!m_picParams->m_fieldCodingFlag) ? 3 : ((m_picParams->m_interleavedFieldBFF) ? 2 : 1), 2); bool progressiveSequence = m_seqParams->m_progressiveSequence & 0x1; bool actual_tff = (!m_picParams->m_fieldCodingFlag && !progressiveSequence) || (m_picParams->m_repeatFirstField != 0); // top_field_first PutBit(bsBuffer, (actual_tff ) ? (!m_picParams->m_interleavedFieldBFF) : 0); bool progressive = true; if (m_picParams->m_fieldCodingFlag || m_picParams->m_fieldFrameCodingFlag) { progressive = false; } // frame_pred_frame_dct if (progressive) { PutBit(bsBuffer, 1); } else if (m_picParams->m_fieldCodingFlag) { PutBit(bsBuffer, 0); } else { PutBit(bsBuffer, m_picParams->m_framePredFrameDCT); } // concealment_motion_vectors PutBit(bsBuffer, m_picParams->m_concealmentMotionVectors); // Store the byte offset of the q_scale_type m_qScaleTypeByteOffse = GetCurByteOffset(bsBuffer); // q_scale_type PutBit(bsBuffer, m_picParams->m_qscaleType); // intra_vlc_format PutBit(bsBuffer, m_picParams->m_intraVlcFormat); // alternate_scan PutBit(bsBuffer, m_picParams->m_alternateScan); // repeat_first_field PutBit(bsBuffer, (!m_picParams->m_fieldCodingFlag) ? m_picParams->m_repeatFirstField : 0); // chroma_420_type PutBit(bsBuffer, progressive); // progressive_frame PutBit(bsBuffer, progressive); // composite_display_flag PutBit(bsBuffer, m_picParams->m_compositeDisplayFlag); if (m_picParams->m_compositeDisplayFlag) { // v_axis PutBit(bsBuffer, m_picParams->m_vaxis); // field_sequence PutBits(bsBuffer, m_picParams->m_fieldSequence, 3); // sub_carrier PutBit(bsBuffer, m_picParams->m_subCarrier); // burst_amplitude PutBits(bsBuffer, m_picParams->m_burstAmplitude, 7); // sub_carrier_phase PutBits(bsBuffer, m_picParams->m_subCarrierPhase, 8); } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackPicUserData() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto userDataListHead = (CodecEncodeMpeg2UserDataList *)m_encodeParams.pMpeg2UserDataListHead; CODECHAL_ENCODE_CHK_NULL_RETURN(userDataListHead); auto bsBuffer = &m_bsBuffer; for (auto p = userDataListHead; p; p = p->m_nextItem) { auto userData = (uint8_t*)p->m_userData; while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } for(unsigned int i = 0; i < p->m_userDataSize; ++i) { PutBits(bsBuffer, (uint32_t) (userData[i]), 8); } } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackPicHeader() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto bsBuffer = &m_bsBuffer; // All start codes are uint8_t aligned while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } // picture_start_code PutBits(bsBuffer, startCodePrefix, 24); PutBits(bsBuffer, startCodePicture, 8); // temporal_reference PutBits(bsBuffer, m_picParams->m_temporalReference, 10); // picture_coding_type PutBits(bsBuffer, m_picParams->m_pictureCodingType, 3); // Store the byte offset of the q_scale_type m_vbvDelayOffset = GetCurByteOffset(bsBuffer); // vbv_delay PutBits(bsBuffer, m_picParams->m_vbvDelay, 16); if ((m_picParams->m_pictureCodingType == P_TYPE) || (m_picParams->m_pictureCodingType == B_TYPE)) { // full_pel_forward_vector, '0' PutBit(bsBuffer, 0); // forward_f_code, '111' PutBits(bsBuffer, 0x7, 3); } if (m_picParams->m_pictureCodingType == B_TYPE) { // full_pel_backward_vector, '0' PutBit(bsBuffer, 0); // backward_f_code '111' PutBits(bsBuffer, 0x7, 3); } // extra_bit_picture, '0' PutBit(bsBuffer, 0); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackGroupOfPicHeader() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto bsBuffer = &m_bsBuffer; // All start codes are uint8_t aligned while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } // group_start_code PutBits(bsBuffer, startCodePrefix, 24); PutBits(bsBuffer, startCodeGroupStart, 8); // time_code, 25 bits total // drop_flag PutBit(bsBuffer, ((m_picParams->m_timeCode >> 24) & 1)); // hour PutBits(bsBuffer, ((m_picParams->m_timeCode >> 19) & 0x1F), 5); // minute PutBits(bsBuffer, ((m_picParams->m_timeCode >> 13) & 0x3F), 6); // marker_bit PutBit(bsBuffer, 1); // sec PutBits(bsBuffer, ((m_picParams->m_timeCode >> 6) & 0x3F), 6); // frame PutBits(bsBuffer, ((m_picParams->m_timeCode) & 0x3F), 6); // closed_gop PutBit(bsBuffer, m_picParams->m_gopOptFlag & 1); // broken_link, used in editing PutBit(bsBuffer, 0); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackPictureParams() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; // optional GOP header (& user data) if (m_picParams->m_newGop) { CODECHAL_ENCODE_CHK_STATUS_RETURN(PackGroupOfPicHeader()); } // picture header CODECHAL_ENCODE_CHK_STATUS_RETURN(PackPicHeader()); // picture coding extension CODECHAL_ENCODE_CHK_STATUS_RETURN(PackPicCodingExtension()); // user data if(m_encodeParams.pMpeg2UserDataListHead) { CODECHAL_ENCODE_CHK_STATUS_RETURN(PackPicUserData()); } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackPictureHeader() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto bsBuffer = &m_bsBuffer; *(bsBuffer->pBase) = 0; // init first byte to 0 bsBuffer->pCurrent = bsBuffer->pBase; bsBuffer->SliceOffset = 0; bsBuffer->BitOffset = 0; bsBuffer->BitSize = 0; // If this is a new sequence, write the seq set if (m_newSeq) { // Pack SPS CODECHAL_ENCODE_CHK_STATUS_RETURN(PackSequenceParams()); } // Pack PPS CODECHAL_ENCODE_CHK_STATUS_RETURN(PackPictureParams()); // HW will insert next slice start code, but need to byte align for HW while (bsBuffer->BitOffset) { PutBit(bsBuffer, 0); } bsBuffer->BitSize = (uint32_t)(bsBuffer->pCurrent - bsBuffer->SliceOffset - bsBuffer->pBase) * 8 + bsBuffer->BitOffset; return eStatus; } MOS_STATUS CodechalEncodeMpeg2::InitializePicture(const EncoderParams& params) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; m_seqParams = (CodecEncodeMpeg2SequenceParams *)(params.pSeqParams); m_vuiParams = (CodecEncodeMpeg2VuiParams *)(params.pVuiParams); m_picParams = (CodecEncodeMpeg2PictureParams *)(params.pPicParams); m_sliceParams = (CodecEncodeMpeg2SliceParmas *)(params.pSliceParams); m_qMatrixParams = (CodecEncodeMpeg2QmatixParams *)(params.pIQMatrixBuffer); CODECHAL_ENCODE_CHK_NULL_RETURN(m_seqParams); CODECHAL_ENCODE_CHK_NULL_RETURN(m_vuiParams); CODECHAL_ENCODE_CHK_NULL_RETURN(m_picParams); CODECHAL_ENCODE_CHK_NULL_RETURN(m_sliceParams); CODECHAL_ENCODE_CHK_NULL_RETURN(m_qMatrixParams); // Mb Qp data m_mbQpDataEnabled = params.bMbQpDataEnabled; if (m_mbQpDataEnabled) { m_mbQpDataSurface = *(params.psMbQpDataSurface); } m_skipFrameFlag = m_picParams->m_skipFrameFlag; m_verticalLineStride = CODECHAL_VLINESTRIDE_FRAME; m_verticalLineStrideOffset = CODECHAL_VLINESTRIDEOFFSET_TOP_FIELD; m_mbcodeBottomFieldOffset = 0; m_mvBottomFieldOffset = 0; m_scaledBottomFieldOffset = 0; m_scaled16xBottomFieldOffset = 0; if (m_newSeq) { CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSequenceStructs()); } CODECHAL_ENCODE_CHK_STATUS_RETURN(SetPictureStructs()); // 4x downscaled surface needed by MbEnc IDist (for BRC) kernel or HME kernel m_scalingEnabled = (m_hmeSupported || m_brcEnabled); if (CodecHal_PictureIsField(m_currOriginalPic)) { m_verticalLineStride = CODECHAL_VLINESTRIDE_FIELD; m_frameHeight = m_frameFieldHeightInMb * 2 * 16; m_picHeightInMb = (uint16_t)(m_frameHeight / 16); if (CodecHal_PictureIsBottomField(m_currOriginalPic)) { m_verticalLineStrideOffset = CODECHAL_VLINESTRIDEOFFSET_BOT_FIELD; m_mbcodeBottomFieldOffset = m_frameFieldHeightInMb * m_picWidthInMb * 64; m_mvBottomFieldOffset = MOS_ALIGN_CEIL(m_frameFieldHeightInMb * m_picWidthInMb * (32 * 4), 0x1000); } } if (m_pictureCodingType == B_TYPE) { m_frameNumB += 1; } else { m_frameNumB = 0; } if (m_pakEnabled) { CODECHAL_ENCODE_CHK_STATUS_RETURN(PackPictureHeader()); if (m_brcEnabled) { MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams; uint32_t dwPicHeaderDataStartOffset,dwPicHeaderDataBufferSize; MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams)); pakInsertObjectParams.pBsBuffer = &m_bsBuffer; pakInsertObjectParams.pdwMpeg2PicHeaderDataStartOffset = &dwPicHeaderDataStartOffset; pakInsertObjectParams.pdwMpeg2PicHeaderTotalBufferSize = &dwPicHeaderDataBufferSize; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfcMpeg2PakInsertBrcBuffer( &m_brcBuffers.resBrcPicHeaderInputBuffer, &pakInsertObjectParams)); // The q_scale_type offset is relative to the beginning of the picture header buffer. // Since it starts off with the INSERT command, include its size in the offset for the // q_scale_type. Do the same for the vbv_delay offset. m_picHeaderDataBufferSize = dwPicHeaderDataBufferSize; m_qScaleTypeByteOffse += dwPicHeaderDataStartOffset; m_vbvDelayOffset += dwPicHeaderDataStartOffset; m_intraDcPrecisionOffset += dwPicHeaderDataStartOffset; } CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSliceGroups()); } CODECHAL_DEBUG_TOOL( m_debugInterface->m_currPic = m_picParams->m_currOriginalPic; m_debugInterface->m_bufferDumpFrameNum = m_storeData; m_debugInterface->m_frameType = m_pictureCodingType; CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpVuiParams( m_vuiParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpPicParams( m_picParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSeqParams( m_seqParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(DumpSliceParams( m_sliceParams));) if (m_currReconstructedPic.FrameIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2) { return MOS_STATUS_INVALID_PARAMETER; } CODECHAL_ENCODE_CHK_STATUS_RETURN(SetStatusReportParams( m_refList[m_currReconstructedPic.FrameIdx])); m_bitstreamUpperBound = m_encodeParams.dwBitstreamSize; return eStatus; } MOS_STATUS CodechalEncodeMpeg2::InitKernelStateBrc() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; uint32_t brcBtCount[CODECHAL_ENCODE_BRC_IDX_NUM] = { brcInitResetNumBindingTableEntries, brcUpdateNumBindingTableEntries, brcInitResetNumBindingTableEntries, 0, // IFrameDist uses MBEnc I kernel 0, // BlockCopy kernel is not needed 0 // MbBRCUpdate kernel is not needed }; uint32_t brcCurbeSize[CODECHAL_ENCODE_BRC_IDX_NUM] = { BrcInitResetCurbe::m_byteSize, BrcUpdateCurbe::m_byteSize, BrcInitResetCurbe::m_byteSize, 0, // IFrameDist uses MBEnc I kernel 0, // BlockCopy kernel is not needed 0 // MbBRCUpdate kernel is not needed }; CODECHAL_KERNEL_HEADER currKrnHeader; // CODECHAL_ENCODE_BRC_IDX_NUM - 2: BlockCopy and MbBRCUpdate kernel not needed for (uint8_t krnStateIdx = 0; krnStateIdx < CODECHAL_ENCODE_BRC_IDX_NUM - 2; krnStateIdx++) { // IFrameDist doesn't have separate kernel for MPEG2, needs to use MbEnc I kernel if (krnStateIdx == CODECHAL_ENCODE_BRC_IDX_IFRAMEDIST) { m_brcKernelStates[krnStateIdx] = m_mbEncKernelStates[mbEncKernelIdxI]; continue; } auto kernelState = &m_brcKernelStates[krnStateIdx]; uint32_t kernelSize = m_combinedKernelSize; CODECHAL_ENCODE_CHK_STATUS_RETURN(pfnGetKernelHeaderAndSize( m_kernelBinary, ENC_BRC, krnStateIdx, &currKrnHeader, &kernelSize)); kernelState->KernelParams.iBTCount = brcBtCount[krnStateIdx]; kernelState->KernelParams.iThreadCount = m_hwInterface->GetRenderInterface()->GetHwCaps()->dwMaxThreads; kernelState->KernelParams.iCurbeLength = brcCurbeSize[krnStateIdx]; kernelState->KernelParams.iBlockWidth = CODECHAL_MACROBLOCK_WIDTH; kernelState->KernelParams.iBlockHeight = CODECHAL_MACROBLOCK_HEIGHT; kernelState->KernelParams.iIdCount = 1; kernelState->dwCurbeOffset = m_stateHeapInterface->pStateHeapInterface->GetSizeofCmdInterfaceDescriptorData(); kernelState->KernelParams.pBinary = m_kernelBinary + (currKrnHeader.KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT); kernelState->KernelParams.iSize = kernelSize; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnCalculateSshAndBtSizesRequested( m_stateHeapInterface, kernelState->KernelParams.iBTCount, &kernelState->dwSshSize, &kernelState->dwBindingTableSize)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->MhwInitISH(m_stateHeapInterface, kernelState)); } return eStatus; } uint32_t CodechalEncodeMpeg2::GetMaxBtCount() { uint32_t scalingBtCount = MOS_ALIGN_CEIL( m_scaling4xKernelStates[0].KernelParams.iBTCount, m_stateHeapInterface->pStateHeapInterface->GetBtIdxAlignment()); uint32_t meBtCount = MOS_ALIGN_CEIL( m_hmeKernel ? m_hmeKernel->GetBTCount() : m_meKernelStates[0].KernelParams.iBTCount, m_stateHeapInterface->pStateHeapInterface->GetBtIdxAlignment()); uint32_t mbEncBtCount = MOS_ALIGN_CEIL( m_mbEncKernelStates[0].KernelParams.iBTCount, m_stateHeapInterface->pStateHeapInterface->GetBtIdxAlignment()); uint32_t brcBtCount = 0; for (uint32_t i = 0; i < CODECHAL_ENCODE_BRC_IDX_NUM; i++) { brcBtCount += MOS_ALIGN_CEIL( m_brcKernelStates[i].KernelParams.iBTCount, m_stateHeapInterface->pStateHeapInterface->GetBtIdxAlignment()); } return MOS_MAX(scalingBtCount + meBtCount, mbEncBtCount + brcBtCount); } MOS_STATUS CodechalEncodeMpeg2::EncodeMeKernel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; PerfTagSetting perfTag; perfTag.Value = 0; perfTag.Mode = (uint16_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK; perfTag.CallType = CODECHAL_ENCODE_PERFTAG_CALL_ME_KERNEL; perfTag.PictureCodingType = m_pictureCodingType; m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value); uint32_t krnStateIdx = (m_pictureCodingType == P_TYPE) ? CODECHAL_ENCODE_ME_IDX_P : CODECHAL_ENCODE_ME_IDX_B; if (m_pictureCodingType == B_TYPE && CodecHal_PictureIsInvalid(m_picParams->m_refFrameList[1])) { krnStateIdx = CODECHAL_ENCODE_ME_IDX_P; } auto kernelState = &m_meKernelStates[krnStateIdx]; if (m_firstTaskInPhase || !m_singleTaskPhaseSupported) { uint32_t maxBtCount = m_singleTaskPhaseSupported ? m_maxBtCount : kernelState->KernelParams.iBTCount; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnRequestSshSpaceForCmdBuf( m_stateHeapInterface, maxBtCount)); m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount); CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable()); } CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( m_stateHeapInterface, kernelState, false, 0, false, m_storeData)); MHW_INTERFACE_DESCRIPTOR_PARAMS interfaceParams; MOS_ZeroMemory(&interfaceParams, sizeof(interfaceParams)); interfaceParams.pKernelState = kernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetInterfaceDescriptor( m_stateHeapInterface, 1, &interfaceParams)); // This parameter is used to select correct mode mv cost // and search path from the predefined tables specifically // for Mpeg2 BRC encoding path m_seqParams->m_targetUsage = 8; CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbeMe()); CODECHAL_MEDIA_STATE_TYPE encFunctionType = CODECHAL_MEDIA_STATE_4X_ME; CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_DSH_TYPE, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe( encFunctionType, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_ISH_TYPE, kernelState)); ) MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer( m_osInterface, &cmdBuffer, 0)); SendKernelCmdsParams sendKernelCmdsParams; sendKernelCmdsParams.EncFunctionType = encFunctionType; sendKernelCmdsParams.pKernelState = kernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds( &cmdBuffer, &sendKernelCmdsParams)); // Add binding table CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetBindingTable( m_stateHeapInterface, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(SendMeSurfaces(&cmdBuffer)); // Dump SSH for ME kernel CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_SSH_TYPE, kernelState))); // HW walker CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams; MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams)); walkerCodecParams.WalkerMode = m_walkerMode; walkerCodecParams.dwResolutionX = m_downscaledWidthInMb4x; walkerCodecParams.dwResolutionY = m_downscaledFrameFieldHeightInMb4x; walkerCodecParams.bNoDependency = true; MHW_WALKER_PARAMS walkerParams; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalInitMediaObjectWalkerParams( m_hwInterface, &walkerParams, &walkerCodecParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetRenderInterface()->AddMediaObjectWalkerCmd( &cmdBuffer, &walkerParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSubmitBlocks( m_stateHeapInterface, kernelState)); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnUpdateGlobalCmdBufId( m_stateHeapInterface)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( &cmdBuffer, nullptr)); } CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, encFunctionType, nullptr))); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->UpdateSSEuForCmdBuffer( &cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer( m_osInterface, &cmdBuffer, m_renderContextUsesNullHw)); m_lastTaskInPhase = false; } return eStatus; } uint32_t CodechalEncodeMpeg2::CalcFrameRateValue( uint16_t frameRateCode, uint32_t factor) { uint32_t ret; switch(frameRateCode) { // Note a frame rate code of 0 is forbidden according to MPEG-2 spec case 0x1: ret = (uint32_t)((24000/1001.0)*factor); break; case 0x2: ret = 24 * factor; break; case 0x3: ret = 25*factor; break; case 0x4: ret = (uint32_t)((30000/1001.0)*factor); break; case 0x5: ret = 30 * factor; break; case 0x6: ret = 50 * factor; break; case 0x7: ret = (uint32_t)((60000/1001.0)*factor); break; case 0x8: ret = 60*factor; break; default: ret = 0xdeadbeef; } return ret; } MOS_STATUS CodechalEncodeMpeg2::SetCurbeBrcInitReset() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; BrcInitResetCurbe cmd; cmd.m_curbeData.DW1.m_initBufFullInBits = m_seqParams->m_initVBVBufferFullnessInBit; cmd.m_curbeData.DW2.m_bufSizeInBits = m_seqParams->m_vbvBufferSize * CODEC_ENCODE_MPEG2_VBV_BUFFER_SIZE_UNITS; cmd.m_curbeData.DW3.m_averageBitRate = m_seqParams->m_bitrate * CODECHAL_ENCODE_BRC_KBPS; cmd.m_curbeData.DW4.m_maxBitRate = m_seqParams->m_maxBitRate * CODECHAL_ENCODE_BRC_KBPS; if (m_picParams->m_gopPicSize == 1) { cmd.m_curbeData.DW8.m_gopP = 0; cmd.m_curbeData.DW9.m_gopB = 0; } else { cmd.m_curbeData.DW8.m_gopP = (m_picParams->m_gopRefDist) ? ((m_picParams->m_gopPicSize - 1) / m_picParams->m_gopRefDist) : 0; cmd.m_curbeData.DW9.m_gopB = (m_picParams->m_gopRefDist - 1) * cmd.m_curbeData.DW8.m_gopP; } cmd.m_curbeData.DW9.m_frameWidthInBytes = m_frameWidth; cmd.m_curbeData.DW10.m_frameHeightInBytes = m_frameHeight; cmd.m_curbeData.DW11.m_minQP = 1; cmd.m_curbeData.DW12.m_noSlices = ((m_frameHeight + 31) >> 5) << 1; // Frame Rate m_value Scaled by m_frameRateDenom uint32_t scaledFrameRateValue = CalcFrameRateValue(m_seqParams->m_frameRateCode, m_frameRateDenom); if (CodecHal_PictureIsFrame(m_picParams->m_currOriginalPic)) { cmd.m_curbeData.DW6.m_frameRateM = scaledFrameRateValue; } else // This else clause will only be taken when interlaced field support is added to MPEG-2. { cmd.m_curbeData.DW6.m_frameRateM = scaledFrameRateValue * 2; } cmd.m_curbeData.DW7.m_frameRateD = m_frameRateDenom; cmd.m_curbeData.DW8.m_brcFlag = (CodecHal_PictureIsFrame(m_picParams->m_currOriginalPic)) ? (0) : (CODECHAL_ENCODE_BRCINIT_FIELD_PIC); if (m_seqParams->m_rateControlMethod == RATECONTROL_CBR) { cmd.m_curbeData.DW4.m_maxBitRate = cmd.m_curbeData.DW3.m_averageBitRate; cmd.m_curbeData.DW8.m_brcFlag = cmd.m_curbeData.DW8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISCBR; } else if (m_seqParams->m_rateControlMethod == RATECONTROL_VBR) { cmd.m_curbeData.DW8.m_brcFlag = cmd.m_curbeData.DW8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISVBR; } else if (m_seqParams->m_rateControlMethod == RATECONTROL_AVBR) { cmd.m_curbeData.DW10.m_avbrAccuracy = m_avbrAccuracy; cmd.m_curbeData.DW11.m_avbrConvergence = m_avbrConvergence; cmd.m_curbeData.DW8.m_brcFlag = cmd.m_curbeData.DW8.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISAVBR; // For AVBR, only honor bitrate from app => InitVBV = Bitrate, Buffer size = 2*Bitrate, max bitrate = target bitrate, cmd.m_curbeData.DW1.m_initBufFullInBits = m_seqParams->m_bitrate * CODECHAL_ENCODE_BRC_KBPS; //m_seqParams->bit_rate * ENCODE_BRC_KBPS; cmd.m_curbeData.DW2.m_bufSizeInBits = 2 * m_seqParams->m_bitrate * CODECHAL_ENCODE_BRC_KBPS; //m_seqParams->bit_rate * ENCODE_BRC_KBPS; cmd.m_curbeData.DW3.m_averageBitRate = m_seqParams->m_bitrate * CODECHAL_ENCODE_BRC_KBPS; cmd.m_curbeData.DW4.m_maxBitRate = m_seqParams->m_bitrate * CODECHAL_ENCODE_BRC_KBPS; } // Profile & level max frame size uint32_t defaultFrameSize = m_frameWidth * m_frameHeight; if (m_seqParams->m_userMaxFrameSize > 0) { cmd.m_curbeData.DW0.m_profileLevelMaxFrame = MOS_MIN(m_seqParams->m_userMaxFrameSize, defaultFrameSize); } else { cmd.m_curbeData.DW0.m_profileLevelMaxFrame = defaultFrameSize; } uint32_t brcKernelIdx = (m_brcInit) ? CODECHAL_ENCODE_BRC_IDX_INIT : CODECHAL_ENCODE_BRC_IDX_RESET; PMHW_KERNEL_STATE kernelState = &m_brcKernelStates[brcKernelIdx]; if (m_brcInit) { m_brcInitCurrentTargetBufFullInBits = cmd.m_curbeData.DW1.m_initBufFullInBits; } m_brcInitResetBufSizeInBits = (double)cmd.m_curbeData.DW2.m_bufSizeInBits; m_brcInitResetInputBitsPerFrame = ((double)(cmd.m_curbeData.DW4.m_maxBitRate) * (double)(cmd.m_curbeData.DW7.m_frameRateD) /(double)(cmd.m_curbeData.DW6.m_frameRateM)); CODECHAL_ENCODE_CHK_STATUS_RETURN(kernelState->m_dshRegion.AddData( &cmd, kernelState->dwCurbeOffset, cmd.m_byteSize)); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SendBrcInitResetSurfaces( PMOS_COMMAND_BUFFER cmdBuffer) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer); uint32_t brcKernelIdx = (m_brcInit) ? CODECHAL_ENCODE_BRC_IDX_INIT : CODECHAL_ENCODE_BRC_IDX_RESET; PMHW_KERNEL_STATE kernelState = &m_brcKernelStates[brcKernelIdx]; // BRC history buffer CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams; MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIsWritable = true; surfaceCodecParams.presBuffer = &m_brcBuffers.resBrcHistoryBuffer; surfaceCodecParams.dwSize = m_brcHistoryBufferSize; surfaceCodecParams.dwBindingTableOffset = brcInitResetHistory; surfaceCodecParams.bIsWritable = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // AVC_ME BRC Distortion data buffer - output m_brcBuffers.sMeBrcDistortionBuffer.dwWidth = MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64); m_brcBuffers.sMeBrcDistortionBuffer.dwHeight = MOS_ALIGN_CEIL((m_downscaledFrameFieldHeightInMb4x * 4), 8); m_brcBuffers.sMeBrcDistortionBuffer.dwPitch = m_brcBuffers.sMeBrcDistortionBuffer.dwWidth; MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIs2DSurface = true; surfaceCodecParams.bMediaBlockRW = true; surfaceCodecParams.bIsWritable = true; surfaceCodecParams.psSurface = &m_brcBuffers.sMeBrcDistortionBuffer; surfaceCodecParams.dwOffset = m_brcBuffers.dwMeBrcDistortionBottomFieldOffset; surfaceCodecParams.dwBindingTableOffset = brcInitResetDistortion; surfaceCodecParams.bIsWritable = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::EncodeBrcInitResetKernel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; PerfTagSetting perfTag; perfTag.Value = 0; perfTag.Mode = (uint32_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK; perfTag.CallType = CODECHAL_ENCODE_PERFTAG_CALL_BRC_INIT_RESET; perfTag.PictureCodingType = m_pictureCodingType; m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value); uint32_t brcKernelIdx = (m_brcInit) ? CODECHAL_ENCODE_BRC_IDX_INIT : CODECHAL_ENCODE_BRC_IDX_RESET; PMHW_KERNEL_STATE kernelState = &m_brcKernelStates[brcKernelIdx]; if (m_firstTaskInPhase || !m_singleTaskPhaseSupported) { uint32_t maxBtCount = m_singleTaskPhaseSupported ? m_maxBtCount : kernelState->KernelParams.iBTCount; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnRequestSshSpaceForCmdBuf( m_stateHeapInterface, maxBtCount)); m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount); CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable()); } // Setup Mpeg2 Curbe CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( m_stateHeapInterface, kernelState, false, 0, false, m_storeData)); MHW_INTERFACE_DESCRIPTOR_PARAMS interfaceParams; MOS_ZeroMemory(&interfaceParams, sizeof(interfaceParams)); interfaceParams.pKernelState = kernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetInterfaceDescriptor( m_stateHeapInterface, 1, &interfaceParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbeBrcInitReset()); CODECHAL_MEDIA_STATE_TYPE encFunctionType = CODECHAL_MEDIA_STATE_BRC_INIT_RESET; CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_DSH_TYPE, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe( encFunctionType, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_ISH_TYPE, kernelState)); ) MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); SendKernelCmdsParams sendKernelCmdsParams; sendKernelCmdsParams.EncFunctionType = encFunctionType; sendKernelCmdsParams.bBrcResetRequested = m_brcReset; sendKernelCmdsParams.pKernelState = kernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams)); // Add binding table CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetBindingTable( m_stateHeapInterface, kernelState)); //Add surface states CODECHAL_ENCODE_CHK_STATUS_RETURN(SendBrcInitResetSurfaces(&cmdBuffer)); CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_SSH_TYPE, kernelState)); ) MHW_MEDIA_OBJECT_PARAMS mediaObjectParams; MOS_ZeroMemory(&mediaObjectParams, sizeof(mediaObjectParams)); MediaObjectInlineDataMpeg2 mediaObjectInlineData; MOS_ZeroMemory(&mediaObjectInlineData, sizeof(mediaObjectInlineData)); mediaObjectParams.pInlineData = &mediaObjectInlineData; mediaObjectParams.dwInlineDataSize = sizeof(mediaObjectInlineData); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetRenderInterface()->AddMediaObject( &cmdBuffer, nullptr, &mediaObjectParams)); // add end of commands here for eStatus report CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, encFunctionType)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSubmitBlocks( m_stateHeapInterface, kernelState)); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnUpdateGlobalCmdBufId( m_stateHeapInterface)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( &cmdBuffer, nullptr)); } CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, encFunctionType, nullptr))); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->UpdateSSEuForCmdBuffer( &cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer( m_osInterface, &cmdBuffer, m_renderContextUsesNullHw)); m_lastTaskInPhase = false; } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::EncodeMbEncKernel(bool mbEncIFrameDistEnabled) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; PerfTagSetting perfTag; perfTag.Value = 0; perfTag.Mode = (uint16_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK; perfTag.CallType = (mbEncIFrameDistEnabled) ? CODECHAL_ENCODE_PERFTAG_CALL_INTRA_DIST : CODECHAL_ENCODE_PERFTAG_CALL_MBENC_KERNEL; perfTag.PictureCodingType = m_pictureCodingType; m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value); CODECHAL_MEDIA_STATE_TYPE encFunctionType; if (mbEncIFrameDistEnabled) { encFunctionType = CODECHAL_MEDIA_STATE_ENC_I_FRAME_DIST; } else if (m_kernelMode == encodeNormalMode) { encFunctionType = CODECHAL_MEDIA_STATE_ENC_NORMAL; } else if (m_kernelMode == encodePerformanceMode) { encFunctionType = CODECHAL_MEDIA_STATE_ENC_PERFORMANCE; } else { encFunctionType = CODECHAL_MEDIA_STATE_ENC_QUALITY; } PMHW_KERNEL_STATE kernelState; uint8_t codingType = m_mbEncForcePictureCodingType ? m_mbEncForcePictureCodingType : (uint8_t)m_pictureCodingType; // Initialize DSH kernel region if (mbEncIFrameDistEnabled) { kernelState = &m_brcKernelStates[CODECHAL_ENCODE_BRC_IDX_IFRAMEDIST]; } else { // wPictureCodingType: I_TYPE = 1, P_TYPE = 2, B_TYPE = 3 // KernelStates are I: 0, P: 1, B: 2 // m_mbEncKernelStates: I: m_mbEncKernelStates[0], P: m_mbEncKernelStates[1], B: m_mbEncKernelStates[2] uint32_t krnStateIdx = codingType - 1; kernelState = &m_mbEncKernelStates[krnStateIdx]; } if (m_firstTaskInPhase || !m_singleTaskPhaseSupported) { uint32_t maxBtCount = m_singleTaskPhaseSupported ? m_maxBtCount : kernelState->KernelParams.iBTCount; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnRequestSshSpaceForCmdBuf( m_stateHeapInterface, maxBtCount)); m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount); CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable()); } if (m_mbEncCurbeSetInBrcUpdate) { // single task phase disabled for MPEG2 MbEnc CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( m_stateHeapInterface, kernelState, true, 0, m_singleTaskPhaseSupported, m_storeData)); } else { // Set up the DSH as normal CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( m_stateHeapInterface, kernelState, false, 0, false, m_storeData)); MHW_INTERFACE_DESCRIPTOR_PARAMS interfaceParams; MOS_ZeroMemory(&interfaceParams, sizeof(interfaceParams)); interfaceParams.pKernelState = kernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetInterfaceDescriptor( m_stateHeapInterface, 1, &interfaceParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbeMbEnc(mbEncIFrameDistEnabled, m_mbQpDataEnabled)); CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_DSH_TYPE, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe( encFunctionType, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_ISH_TYPE, kernelState)); ) } for (uint8_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC; i++) { if (m_picIdx[i].bValid) { auto Index = m_picIdx[i].ucPicIdx; m_refList[Index]->sRefBuffer = m_picParams->m_useRawPicForRef ? m_refList[Index]->sRefRawBuffer : m_refList[Index]->sRefReconBuffer; if (m_codecFunction == CODECHAL_FUNCTION_ENC_PAK) { auto pResRefMbCodeBuffer = (MOS_RESOURCE*)m_allocator->GetResource(m_standard, mbCodeBuffer, m_refList[Index]->ucMbCodeIdx); if (pResRefMbCodeBuffer) { m_refList[Index]->resRefMbCodeBuffer = *pResRefMbCodeBuffer; } } CodecHalGetResourceInfo(m_osInterface, &m_refList[Index]->sRefBuffer); } } MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); SendKernelCmdsParams sendKernelCmdsParams; sendKernelCmdsParams.EncFunctionType = encFunctionType; sendKernelCmdsParams.pKernelState = kernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams)); // Add binding table CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetBindingTable( m_stateHeapInterface, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(SendMbEncSurfaces(&cmdBuffer, mbEncIFrameDistEnabled)); if ((codingType != B_TYPE) && (!mbEncIFrameDistEnabled)) { m_prevMBCodeIdx = m_currReconstructedPic.FrameIdx; } // HW walker CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams; MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams)); walkerCodecParams.WalkerMode = m_walkerMode; walkerCodecParams.bUseScoreboard = m_useHwScoreboard; walkerCodecParams.dwResolutionX = mbEncIFrameDistEnabled ? m_downscaledWidthInMb4x : (uint32_t)m_picWidthInMb; walkerCodecParams.dwResolutionY = mbEncIFrameDistEnabled ? m_downscaledFrameFieldHeightInMb4x : (uint32_t)m_frameFieldHeightInMb; if (codingType == I_TYPE) { walkerCodecParams.bUseScoreboard = false; walkerCodecParams.bNoDependency = true; /* Enforce no dependency dispatch order for I frame */ } else if (codingType == P_TYPE) { // walkerCodecParams.wPictureCodingType can be different from m_pictureCodingType walkerCodecParams.wPictureCodingType = I_TYPE; /* Enforce 45 degree dispatch order for P frame, as by default it's 26 degree */ } else// B_TYPE { walkerCodecParams.bUseVerticalRasterScan = true; } MHW_WALKER_PARAMS walkerParams; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalInitMediaObjectWalkerParams( m_hwInterface, &walkerParams, &walkerCodecParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetRenderInterface()->AddMediaObjectWalkerCmd( &cmdBuffer, &walkerParams)); // add end of commands here for eStatus report CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, encFunctionType)); CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_SSH_TYPE, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, encFunctionType, nullptr)); ) CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSubmitBlocks( m_stateHeapInterface, kernelState)); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnUpdateGlobalCmdBufId( m_stateHeapInterface)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr)); } CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw)); m_lastTaskInPhase = false; } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SendBrcUpdateSurfaces( PMOS_COMMAND_BUFFER cmdBuffer) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer); auto kernelState = &m_brcKernelStates[CODECHAL_ENCODE_BRC_IDX_FrameBRC_UPDATE]; auto mbEncKernelState = m_brcBuffers.pMbEncKernelStateInUse; // BRC history buffer CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams; MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIsWritable = true; surfaceCodecParams.presBuffer = &m_brcBuffers.resBrcHistoryBuffer; surfaceCodecParams.dwSize = m_brcHistoryBufferSize; surfaceCodecParams.dwBindingTableOffset = brcUpdateHistory; surfaceCodecParams.bIsWritable = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // PAK Statistics buffer MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.presBuffer = &m_brcBuffers.resBrcPakStatisticBuffer[0]; surfaceCodecParams.dwSize = MOS_BYTES_TO_DWORDS(m_brcPakStatisticsSize); surfaceCodecParams.dwBindingTableOffset = brcUpdatePakStaticOutput; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // PAK IMG_STATEs buffer - read only uint32_t bufSize = MOS_BYTES_TO_DWORDS(BRC_IMG_STATE_SIZE_PER_PASS * m_mfxInterface->GetBrcNumPakPasses()); MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.presBuffer = &m_brcBuffers.resBrcImageStatesReadBuffer[m_currRecycledBufIdx]; surfaceCodecParams.dwSize = bufSize; surfaceCodecParams.dwBindingTableOffset = brcUpdatePictureStateRead; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // PAK IMG_STATEs buffer - write only MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIsWritable = true; surfaceCodecParams.presBuffer = &m_brcBuffers.resBrcImageStatesWriteBuffer; surfaceCodecParams.dwSize = bufSize; surfaceCodecParams.dwBindingTableOffset = brcUpdatePictureStateWrite; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // BRC ENC CURBE Buffer - read only MOS_RESOURCE *dsh = nullptr; CODECHAL_ENCODE_CHK_NULL_RETURN(dsh = mbEncKernelState->m_dshRegion.GetResource()); bufSize = MOS_ALIGN_CEIL( mbEncKernelState->KernelParams.iCurbeLength, m_stateHeapInterface->pStateHeapInterface->GetCurbeAlignment()); MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.presBuffer = dsh; surfaceCodecParams.dwOffset = mbEncKernelState->m_dshRegion.GetOffset() + mbEncKernelState->dwCurbeOffset; surfaceCodecParams.dwSize = MOS_BYTES_TO_DWORDS(bufSize); surfaceCodecParams.dwBindingTableOffset = brcUpdateMbencCurbeRead; // If the protection DSH isn't used, the same DSH is used for both the MbEnc CURBE read and write surfaceCodecParams.bIsWritable = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // BRC ENC CURBE Buffer - write only MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.presBuffer = dsh; surfaceCodecParams.dwOffset = mbEncKernelState->m_dshRegion.GetOffset() + mbEncKernelState->dwCurbeOffset; surfaceCodecParams.dwSize = MOS_BYTES_TO_DWORDS(bufSize); surfaceCodecParams.dwBindingTableOffset = brcUpdateMbencCurbeWrite; surfaceCodecParams.bRenderTarget = true; surfaceCodecParams.bIsWritable = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // MPEG2_ME BRC Distortion data buffer - input MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIs2DSurface = true; surfaceCodecParams.bMediaBlockRW = true; surfaceCodecParams.psSurface = &m_brcBuffers.sMeBrcDistortionBuffer; surfaceCodecParams.dwOffset = m_brcBuffers.dwMeBrcDistortionBottomFieldOffset; surfaceCodecParams.dwSize = bufSize; surfaceCodecParams.dwBindingTableOffset = brcUpdateDistortion; surfaceCodecParams.bIsWritable = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // BRC Constant Data Surface MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIs2DSurface = true; surfaceCodecParams.bMediaBlockRW = true; surfaceCodecParams.psSurface = &m_brcBuffers.sBrcConstantDataBuffer[m_currRecycledBufIdx]; surfaceCodecParams.dwBindingTableOffset = brcUpdateConstantData; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // Picture header input surface bufSize = m_picHeaderDataBufferSize; MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.presBuffer = &m_brcBuffers.resBrcPicHeaderInputBuffer; surfaceCodecParams.dwSize = bufSize; surfaceCodecParams.dwBindingTableOffset = brcUpdatePicHeaderInputData; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // Picture header output surface MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIsWritable = true; surfaceCodecParams.presBuffer = &m_brcBuffers.resBrcPicHeaderOutputBuffer; surfaceCodecParams.dwSize = bufSize; surfaceCodecParams.dwBindingTableOffset = brcUpdateOutputData; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SetCurbeBrcUpdate() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; BrcUpdateCurbe cmd; cmd.m_curbeData.DW5.m_targetSizeFlag = 0; if (m_brcInitCurrentTargetBufFullInBits > m_brcInitResetBufSizeInBits) { m_brcInitCurrentTargetBufFullInBits -= m_brcInitResetBufSizeInBits; cmd.m_curbeData.DW5.m_targetSizeFlag = 1; } cmd.m_curbeData.DW0.m_targetSize = (uint32_t)m_brcInitCurrentTargetBufFullInBits; cmd.m_curbeData.DW5.m_currFrameType = m_pictureCodingType - 1; cmd.m_curbeData.DW5.m_brcFlag = (CodecHal_PictureIsFrame(m_picParams->m_currOriginalPic)) ? (0) : (CODECHAL_ENCODE_BRCINIT_FIELD_PIC); if (m_seqParams->m_rateControlMethod == RATECONTROL_CBR) { cmd.m_curbeData.DW5.m_brcFlag = cmd.m_curbeData.DW5.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISCBR; } else if (m_seqParams->m_rateControlMethod == RATECONTROL_VBR) { cmd.m_curbeData.DW5.m_brcFlag = cmd.m_curbeData.DW5.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISVBR; } else if (m_seqParams->m_rateControlMethod == RATECONTROL_AVBR) { cmd.m_curbeData.DW5.m_brcFlag = cmd.m_curbeData.DW5.m_brcFlag | CODECHAL_ENCODE_BRCINIT_ISAVBR; } cmd.m_curbeData.DW6.m_qScaleTypeOffset = m_qScaleTypeByteOffse; cmd.m_curbeData.DW6.m_vbvDelay = m_vbvDelayOffset; cmd.m_curbeData.DW7.m_picHeaderDataBufferSize = m_picHeaderDataBufferSize; cmd.m_curbeData.DW15.m_extraHeaders = 1; cmd.m_curbeData.DW15.m_intraDcPrecisionOffset = m_intraDcPrecisionOffset; m_brcInitCurrentTargetBufFullInBits += m_brcInitResetInputBitsPerFrame; if (m_seqParams->m_rateControlMethod == RATECONTROL_AVBR) { cmd.m_curbeData.DW3.m_startGAdjFrame0 = (uint32_t)((10 * m_avbrConvergence) / (double)150); cmd.m_curbeData.DW3.m_startGAdjFrame1 = (uint32_t)((50 * m_avbrConvergence) / (double)150); cmd.m_curbeData.DW4.m_startGAdjFrame2 = (uint32_t)((100 * m_avbrConvergence) / (double)150); cmd.m_curbeData.DW4.m_startGAdjFrame3 = (uint32_t)((150 * m_avbrConvergence) / (double)150); cmd.m_curbeData.DW11.m_gRateRatioThreshold0 = (uint32_t)((100 - (m_avbrAccuracy / (double)30) * (100 - 40))); cmd.m_curbeData.DW11.m_gRateRatioThreshold1 = (uint32_t)((100 - (m_avbrAccuracy / (double)30) * (100 - 75))); cmd.m_curbeData.DW12.m_gRateRatioThreshold2 = (uint32_t)((100 - (m_avbrAccuracy / (double)30) * (100 - 97))); cmd.m_curbeData.DW12.m_gRateRatioThreshold3 = (uint32_t)((100 + (m_avbrAccuracy / (double)30) * (103 - 100))); cmd.m_curbeData.DW12.m_gRateRatioThreshold4 = (uint32_t)((100 + (m_avbrAccuracy / (double)30) * (125 - 100))); cmd.m_curbeData.DW12.m_gRateRatioThreshold5 = (uint32_t)((100 + (m_avbrAccuracy / (double)30) * (160 - 100))); } if (m_seqParams->m_forcePanicModeControl == 1) { cmd.m_curbeData.DW14.m_forceToSkip = m_seqParams->m_panicModeDisable ? 0 : 1; } else { cmd.m_curbeData.DW14.m_forceToSkip = m_panicEnable ? 1 : 0; } auto kernelState = &m_brcKernelStates[CODECHAL_ENCODE_BRC_IDX_FrameBRC_UPDATE]; CODECHAL_ENCODE_CHK_STATUS_RETURN(kernelState->m_dshRegion.AddData( &cmd, kernelState->dwCurbeOffset, cmd.m_byteSize)); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::InitBrcConstantBuffer() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto brcConstantDataBuffer = m_brcBuffers.sBrcConstantDataBuffer[m_currRecycledBufIdx]; CodechalResLock bufLock(m_osInterface, &brcConstantDataBuffer.OsResource); auto data = (uint8_t *)bufLock.Lock(CodechalResLock::writeOnly); CODECHAL_ENCODE_CHK_NULL_RETURN(data); MOS_ZeroMemory(data, brcConstantDataBuffer.dwPitch * brcConstantDataBuffer.dwHeight); uint8_t *maxFrameThresholdArray = nullptr; uint8_t *distQPAdjustmentArray = nullptr; switch(m_pictureCodingType) { case I_TYPE: maxFrameThresholdArray = (uint8_t *)m_qpAdjustmentDistThresholdMaxFrameThresholdI; distQPAdjustmentArray = (uint8_t *)m_distQpAdjustmentI; break; case P_TYPE: maxFrameThresholdArray = (uint8_t *)m_qpAdjustmentDistThresholdMaxFrameThresholdP; distQPAdjustmentArray = (uint8_t *)m_distQpAdjustmentP; break; case B_TYPE: maxFrameThresholdArray = (uint8_t *)m_qpAdjustmentDistThresholdMaxFrameThresholdB; distQPAdjustmentArray = (uint8_t *)m_distQpAdjustmentB; break; default: CODECHAL_ENCODE_ASSERTMESSAGE("Invalid picture coding type."); eStatus = MOS_STATUS_INVALID_PARAMETER; return eStatus; } // Fill surface with QP Adjustment table, Distortion threshold table, MaxFrame threshold table for I frame // The surface width happens to be the size of the array (64), but pitch can be greater. CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( data, m_frameThresholdArraySize, maxFrameThresholdArray, m_frameThresholdArraySize)); data += brcConstantDataBuffer.dwPitch; // advance next row in 2D using pitch for (uint32_t i = 0; i < m_distQpAdjustmentArraySize; i += m_brcConstantSurfaceWidth, data += brcConstantDataBuffer.dwPitch) { uint32_t copySize; // to write <=64 bytes per row if ((m_distQpAdjustmentArraySize - i) > m_brcConstantSurfaceWidth) { copySize = m_brcConstantSurfaceWidth; } else { copySize = m_distQpAdjustmentArraySize - i; } CODECHAL_ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy( data, copySize, distQPAdjustmentArray + i, copySize)); } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::EncodeBrcUpdateKernel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; PerfTagSetting perfTag; perfTag.Value = 0; perfTag.Mode = (uint16_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK; perfTag.CallType = CODECHAL_ENCODE_PERFTAG_CALL_BRC_UPDATE; perfTag.PictureCodingType = m_pictureCodingType; m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value); auto kernelState = &m_brcKernelStates[CODECHAL_ENCODE_BRC_IDX_FrameBRC_UPDATE]; if (m_firstTaskInPhase || !m_singleTaskPhaseSupported) { uint32_t maxBtCount = m_singleTaskPhaseSupported ? m_maxBtCount : kernelState->KernelParams.iBTCount; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnRequestSshSpaceForCmdBuf( m_stateHeapInterface, maxBtCount)); m_vmeStatesSize = m_hwInterface->GetKernelLoadCommandSize(maxBtCount); CODECHAL_ENCODE_CHK_STATUS_RETURN(VerifySpaceAvailable()); } // wPictureCodingType: I_TYPE = 1, P_TYPE = 2, B_TYPE = 3 // KernelStates are I: 0, P: 1, B: 2 // m_mbEncKernelStates: I: m_mbEncKernelStates[0], P: m_mbEncKernelStates[1], B: m_mbEncKernelStates[2] uint32_t krnStateIdx = m_pictureCodingType - 1; if (m_mbEncForcePictureCodingType) { krnStateIdx = m_mbEncForcePictureCodingType - 1; } auto mbEncKernelState = &m_mbEncKernelStates[krnStateIdx]; // Setup MbEnc Curbe CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( m_stateHeapInterface, mbEncKernelState, false, 0, !m_singleTaskPhaseSupported, m_storeData)); MHW_INTERFACE_DESCRIPTOR_PARAMS interfaceParams; MOS_ZeroMemory(&interfaceParams, sizeof(interfaceParams)); interfaceParams.pKernelState = mbEncKernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetInterfaceDescriptor( m_stateHeapInterface, 1, &interfaceParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbeMbEnc(0, 0)); // Brc Update CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( m_stateHeapInterface, kernelState, false, 0, false, m_storeData)); MOS_ZeroMemory(&interfaceParams, sizeof(interfaceParams)); interfaceParams.pKernelState = kernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetInterfaceDescriptor( m_stateHeapInterface, 1, &interfaceParams)); m_mbEncCurbeSetInBrcUpdate = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(SetCurbeBrcUpdate()); CODECHAL_MEDIA_STATE_TYPE encFunctionType = CODECHAL_MEDIA_STATE_BRC_UPDATE; CODECHAL_MEDIA_STATE_TYPE mbEncFunctionType; if (m_kernelMode == encodeNormalMode) { mbEncFunctionType = CODECHAL_MEDIA_STATE_ENC_NORMAL; } else if (m_kernelMode == encodePerformanceMode) { mbEncFunctionType = CODECHAL_MEDIA_STATE_ENC_PERFORMANCE; } else { mbEncFunctionType = CODECHAL_MEDIA_STATE_ENC_QUALITY; } CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_DSH_TYPE, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe( encFunctionType, kernelState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_ISH_TYPE, kernelState)); ) MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); SendKernelCmdsParams sendKernelCmdsParams; sendKernelCmdsParams.EncFunctionType = encFunctionType; sendKernelCmdsParams.pKernelState = kernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(SendGenericKernelCmds(&cmdBuffer, &sendKernelCmdsParams)); // Add binding table CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSetBindingTable( m_stateHeapInterface, kernelState)); m_brcBuffers.pMbEncKernelStateInUse = mbEncKernelState; CODECHAL_ENCODE_CHK_STATUS_RETURN(InitBrcConstantBuffer()); //Set MFX_MPEG2_PIC_STATE command MHW_VDBOX_MPEG2_PIC_STATE mpeg2PicState; MOS_ZeroMemory(&mpeg2PicState, sizeof(mpeg2PicState)); mpeg2PicState.pEncodeMpeg2PicParams = m_picParams; mpeg2PicState.pEncodeMpeg2SeqParams = m_seqParams; mpeg2PicState.wPicWidthInMb = m_picWidthInMb; mpeg2PicState.wPicHeightInMb = m_picHeightInMb; mpeg2PicState.ppRefList = &(m_refList[0]); mpeg2PicState.bBrcEnabled = true; mpeg2PicState.bTrellisQuantEnable = false; mpeg2PicState.ucKernelMode = m_kernelMode; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxMpeg2PicBrcBuffer( &m_brcBuffers.resBrcImageStatesReadBuffer[m_currRecycledBufIdx], &mpeg2PicState)); CODECHAL_ENCODE_CHK_STATUS_RETURN(SendBrcUpdateSurfaces(&cmdBuffer)); CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( encFunctionType, MHW_SSH_TYPE, kernelState)); ) MHW_MEDIA_OBJECT_PARAMS mediaObjectParams; MOS_ZeroMemory(&mediaObjectParams, sizeof(mediaObjectParams)); MediaObjectInlineData mediaObjectInlineData; MOS_ZeroMemory(&mediaObjectInlineData, sizeof(mediaObjectInlineData)); mediaObjectParams.pInlineData = &mediaObjectInlineData; mediaObjectParams.dwInlineDataSize = sizeof(mediaObjectInlineData); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetRenderInterface()->AddMediaObject( &cmdBuffer, nullptr, &mediaObjectParams)); // add end of commands here for eStatus report CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, encFunctionType)); CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, encFunctionType, nullptr)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.resBrcImageStatesReadBuffer[m_currRecycledBufIdx], CodechalDbgAttr::attrInput, "ImgStateRead", BRC_IMG_STATE_SIZE_PER_PASS * m_hwInterface->GetMfxInterface()->GetBrcNumPakPasses(), 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.sBrcConstantDataBuffer[m_currRecycledBufIdx].OsResource, CodechalDbgAttr::attrInput, "ConstData", m_brcBuffers.sBrcConstantDataBuffer[m_currRecycledBufIdx].dwPitch * m_brcBuffers.sBrcConstantDataBuffer[m_currRecycledBufIdx].dwHeight, 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); // PAK statistics buffer is only dumped for BrcUpdate kernel input CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.resBrcPakStatisticBuffer[0], CodechalDbgAttr::attrInput, "PakStats", m_brcPakStatisticsSize, 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.sMeBrcDistortionBuffer.OsResource, CodechalDbgAttr::attrInput, "BrcDist", m_brcBuffers.sMeBrcDistortionBuffer.dwPitch * m_brcBuffers.sMeBrcDistortionBuffer.dwHeight, m_brcBuffers.dwMeBrcDistortionBottomFieldOffset, CODECHAL_MEDIA_STATE_BRC_UPDATE)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.resBrcHistoryBuffer, CodechalDbgAttr::attrInput, "HistoryRead", m_brcHistoryBufferSize, 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_resMbStatsBuffer, CodechalDbgAttr::attrInput, "MBStatsSurf", m_hwInterface->m_avcMbStatBufferSize, 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.resBrcPicHeaderInputBuffer, CodechalDbgAttr::attrInput, "PicHeaderRead", CODEC_ENCODE_MPEG2_BRC_PIC_HEADER_SURFACE_SIZE, 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); ) CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnSubmitBlocks( m_stateHeapInterface, kernelState)); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_stateHeapInterface->pfnUpdateGlobalCmdBufId( m_stateHeapInterface)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( &cmdBuffer, nullptr)); } CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->UpdateSSEuForCmdBuffer( &cmdBuffer, m_singleTaskPhaseSupported, m_lastTaskInPhase)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer( m_osInterface, &cmdBuffer, m_renderContextUsesNullHw)); m_lastTaskInPhase = false; } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::ExecuteKernelFunctions() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( m_rawSurfaceToEnc, CodechalDbgAttr::attrEncodeRawInputSurface, "SrcSurf"))); m_firstTaskInPhase = true; m_lastTaskInPhase = !m_singleTaskPhaseSupported; m_lastEncPhase = false; UpdateSSDSliceCount(); // Csc, Downscaling, and/or 10-bit to 8-bit conversion // Scaling is only used to calculate distortions in case of Mpeg2 CODECHAL_ENCODE_CHK_NULL_RETURN(m_cscDsState); CodechalEncodeCscDs::KernelParams cscScalingKernelParams; MOS_ZeroMemory(&cscScalingKernelParams, sizeof(cscScalingKernelParams)); cscScalingKernelParams.bLastTaskInPhaseCSC = cscScalingKernelParams.bLastTaskInPhase4xDS = m_pictureCodingType == I_TYPE; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_cscDsState->KernelFunctions(&cscScalingKernelParams)); // P and B frames distortion calculations if (m_hmeSupported && (m_pictureCodingType != I_TYPE)) { m_firstTaskInPhase = !m_singleTaskPhaseSupported; m_lastTaskInPhase = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(EncodeMeKernel()); } MOS_SYNC_PARAMS syncParams; // Scaling and HME are not dependent on the output from PAK if (m_waitForPak && m_semaphoreObjCount && !Mos_ResourceIsNull(&m_resSyncObjectVideoContextInUse)) { // Wait on PAK syncParams = g_cInitSyncParams; syncParams.GpuContext = m_renderContext; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; syncParams.uiSemaphoreCount = m_semaphoreObjCount; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); m_semaphoreObjCount = 0; //reset } m_firstTaskInPhase = true; if (m_brcEnabled) { if (m_pictureCodingType == I_TYPE) { // The reset/init is only valid for I frames if (m_brcInit || m_brcReset) { CODECHAL_ENCODE_CHK_STATUS_RETURN(EncodeBrcInitResetKernel()); m_firstTaskInPhase = !m_singleTaskPhaseSupported; } CODECHAL_ENCODE_CHK_STATUS_RETURN(EncodeMbEncKernel(true)); m_firstTaskInPhase = !m_singleTaskPhaseSupported; } CODECHAL_ENCODE_CHK_STATUS_RETURN(EncodeBrcUpdateKernel()); m_firstTaskInPhase = !m_singleTaskPhaseSupported; } m_lastTaskInPhase = true; m_lastEncPhase = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(EncodeMbEncKernel(false)); if (!Mos_ResourceIsNull(&m_resSyncObjectRenderContextInUse)) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_renderContext; syncParams.presSyncResource = &m_resSyncObjectRenderContextInUse; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); } CODECHAL_DEBUG_TOOL( if (m_hmeEnabled && m_brcEnabled) { CODECHAL_ME_OUTPUT_PARAMS meOutputParams; MOS_ZeroMemory(&meOutputParams, sizeof(CODECHAL_ME_OUTPUT_PARAMS)); meOutputParams.psMeMvBuffer = m_hmeKernel ? m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xMvDataBuffer) : &m_4xMEMVDataBuffer; meOutputParams.psMeBrcDistortionBuffer = m_brcDistortionBufferSupported ? &m_brcBuffers.sMeBrcDistortionBuffer : nullptr; meOutputParams.psMeDistortionBuffer = m_hmeKernel ? m_hmeKernel->GetSurface(CodechalKernelHme::SurfaceId::me4xDistortionBuffer) : &m_4xMEDistortionBuffer; meOutputParams.b16xMeInUse = false; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &meOutputParams.psMeMvBuffer->OsResource, CodechalDbgAttr::attrOutput, "MvData", meOutputParams.psMeMvBuffer->dwHeight *meOutputParams.psMeMvBuffer->dwPitch, CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 32), 64) * (m_downscaledFrameFieldHeightInMb4x * 4) : 0, CODECHAL_MEDIA_STATE_4X_ME)); if (!m_vdencStreamInEnabled && meOutputParams.psMeBrcDistortionBuffer) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &meOutputParams.psMeBrcDistortionBuffer->OsResource, CodechalDbgAttr::attrOutput, "BrcDist", meOutputParams.psMeBrcDistortionBuffer->dwHeight *meOutputParams.psMeBrcDistortionBuffer->dwPitch, CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64) * MOS_ALIGN_CEIL((m_downscaledFrameFieldHeightInMb4x * 4), 8) : 0, CODECHAL_MEDIA_STATE_4X_ME)); if (meOutputParams.psMeDistortionBuffer) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &meOutputParams.psMeDistortionBuffer->OsResource, CodechalDbgAttr::attrOutput, "MeDist", meOutputParams.psMeDistortionBuffer->dwHeight *meOutputParams.psMeDistortionBuffer->dwPitch, CodecHal_PictureIsBottomField(m_currOriginalPic) ? MOS_ALIGN_CEIL((m_downscaledWidthInMb4x * 8), 64) * MOS_ALIGN_CEIL((m_downscaledFrameFieldHeightInMb4x * 4 * 10), 8) : 0, CODECHAL_MEDIA_STATE_4X_ME)); } } // dump VDEncStreamin if (m_vdencStreamInEnabled) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_resVdencStreamInBuffer[m_currRecycledBufIdx], CodechalDbgAttr::attrOutput, "MvData", m_picWidthInMb * m_picHeightInMb* CODECHAL_CACHELINE_SIZE, 0, CODECHAL_MEDIA_STATE_ME_VDENC_STREAMIN)); } } if(m_mbQpDataEnabled) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_mbQpDataSurface.OsResource, CodechalDbgAttr::attrInput, "MbQp", m_mbQpDataSurface.dwHeight*m_mbQpDataSurface.dwPitch, 0, CODECHAL_MEDIA_STATE_ENC_QUALITY)); } if (m_brcEnabled) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.resBrcImageStatesWriteBuffer, CodechalDbgAttr::attrOutput, "ImgStateWrite", BRC_IMG_STATE_SIZE_PER_PASS * m_hwInterface->GetMfxInterface()->GetBrcNumPakPasses(), 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.resBrcHistoryBuffer, CodechalDbgAttr::attrOutput, "HistoryWrite", m_brcHistoryBufferSize, 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); if (m_brcBuffers.pMbEncKernelStateInUse) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCurbe( CODECHAL_MEDIA_STATE_BRC_UPDATE, m_brcBuffers.pMbEncKernelStateInUse)); } if (m_mbencBrcBufferSize > 0) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_brcBuffers.resMbEncBrcBuffer, CodechalDbgAttr::attrOutput, "MbEncBRCWrite", m_mbencBrcBufferSize, 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); } CODECHAL_ENCODE_CHK_STATUS_RETURN( m_debugInterface->DumpBuffer( &m_brcBuffers.resBrcPicHeaderOutputBuffer, CodechalDbgAttr::attrOutput, "PicHeaderWrite", CODEC_ENCODE_MPEG2_BRC_PIC_HEADER_SURFACE_SIZE, 0, CODECHAL_MEDIA_STATE_BRC_UPDATE)); } ) // Reset after BRC Init has been processed m_brcInit = false; m_setRequestedEUSlices = false; // Reset indices for next frame if (m_brcEnabled) { m_mbEncCurbeSetInBrcUpdate = false; } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::ExecutePictureLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; PerfTagSetting perfTag; perfTag.Value = 0; perfTag.Mode = (uint16_t)m_mode & CODECHAL_ENCODE_MODE_BIT_MASK; perfTag.CallType = CODECHAL_ENCODE_PERFTAG_CALL_PAK_ENGINE; perfTag.PictureCodingType = m_pictureCodingType; m_osInterface->pfnSetPerfTag(m_osInterface, perfTag.Value); // set MFX_PIPE_MODE_SELECT values MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams; pipeModeSelectParams.Mode = m_mode; pipeModeSelectParams.bStreamOutEnabled = true; bool suppressReconPic = (!m_refList[m_currReconstructedPic.FrameIdx]->bUsedAsRef) && m_suppressReconPicSupported; pipeModeSelectParams.bPreDeblockOutEnable = !suppressReconPic; pipeModeSelectParams.bPostDeblockOutEnable = 0; // set MFX_PIPE_BUF_ADDR_STATE values MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams; pipeBufAddrParams.Mode = m_mode; pipeBufAddrParams.psPreDeblockSurface = &m_reconSurface; CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetPipeBufAddr(&pipeBufAddrParams)); pipeBufAddrParams.psPostDeblockSurface = &m_reconSurface; pipeBufAddrParams.psRawSurface = m_rawSurfaceToPak; pipeBufAddrParams.presStreamOutBuffer = &m_resStreamOutBuffer[m_currRecycledBufIdx]; pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer = &m_resDeblockingFilterRowStoreScratchBuffer; // Setting invalid entries to nullptr for (uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME; i++) { pipeBufAddrParams.presReferences[i]= nullptr; } //divide by two to account for interlace. for now only 0 and 1 will be valid. for (uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC / 2; i++) { if (m_picIdx[i].bValid) { uint8_t picIdx = m_picIdx[i].ucPicIdx; CodecHalGetResourceInfo( m_osInterface, &(m_refList[picIdx]->sRefReconBuffer)); pipeBufAddrParams.presReferences[i] = &(m_refList[picIdx]->sRefReconBuffer.OsResource); //HSW MPEG2 Interlaced VME refine, need extra references pipeBufAddrParams.presReferences[i + 2] = &(m_refList[picIdx]->sRefReconBuffer.OsResource); CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_NULL_RETURN(m_debugInterface); MOS_SURFACE refSurface; MOS_ZeroMemory(&refSurface, sizeof(refSurface)); refSurface.Format = Format_NV12; refSurface.OsResource = *(pipeBufAddrParams.presReferences[i]); CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( m_osInterface, &refSurface)); m_debugInterface->m_refIndex = (uint16_t)i; std::string refSurfName = "RefSurf[" + std::to_string(static_cast(m_debugInterface->m_refIndex)) + "]"; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( &refSurface, CodechalDbgAttr::attrReferenceSurfaces, refSurfName.c_str()));) } } // set MFX_SURFACE_STATE values MHW_VDBOX_SURFACE_PARAMS surfaceParams; MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams)); surfaceParams.Mode = m_mode; // set MFX_IND_OBJ_BASE_ADDR_STATE values // MPEG2 doesn't really use presMvObjectBuffer, different from AVC, the MV Data portion of the bitstream is loaded as part of MB control data MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams; MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams)); indObjBaseAddrParams.Mode = CODECHAL_ENCODE_MODE_MPEG2; indObjBaseAddrParams.presMvObjectBuffer = &m_resMbCodeSurface; indObjBaseAddrParams.dwMvObjectOffset = m_mvOffset + m_mvBottomFieldOffset; indObjBaseAddrParams.dwMvObjectSize = m_mbCodeSize - m_mvOffset; indObjBaseAddrParams.presPakBaseObjectBuffer = &m_resBitstreamBuffer; indObjBaseAddrParams.dwPakBaseObjectSize = m_bitstreamUpperBound; // set MFX_BSP_BUF_BASE_ADDR_STATE values MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS bspBufBaseAddrParams; MOS_ZeroMemory(&bspBufBaseAddrParams, sizeof(bspBufBaseAddrParams)); bspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resMPCRowStoreScratchBuffer; //Set MFX_MPEG2_PIC_STATE command MHW_VDBOX_MPEG2_PIC_STATE mpeg2PicState; MOS_ZeroMemory(&mpeg2PicState, sizeof(mpeg2PicState)); mpeg2PicState.pEncodeMpeg2PicParams = m_picParams; mpeg2PicState.pEncodeMpeg2SeqParams = m_seqParams; mpeg2PicState.wPicWidthInMb = m_picWidthInMb; mpeg2PicState.wPicHeightInMb = m_picHeightInMb; mpeg2PicState.ppRefList = &(m_refList[0]); mpeg2PicState.bBrcEnabled = m_brcEnabled; mpeg2PicState.bTrellisQuantEnable = false; mpeg2PicState.ucKernelMode = m_kernelMode; m_hwInterface->m_numRequestedEuSlices = (m_brcEnabled && m_sliceStateEnable && ((m_frameHeight * m_frameWidth) >= m_hwInterface->m_mpeg2SSDResolutionThreshold)) ? m_sliceShutdownRequestState : m_sliceShutdownDefaultState; MHW_VDBOX_QM_PARAMS qmParams; qmParams.Standard = CODECHAL_MPEG2; qmParams.Mode = CODECHAL_ENCODE_MODE_MPEG2; qmParams.pMpeg2IqMatrix = (CodecMpeg2IqMatrix *)m_qMatrixParams; MHW_VDBOX_QM_PARAMS fqmParams; fqmParams.Standard = CODECHAL_MPEG2; fqmParams.Mode = CODECHAL_ENCODE_MODE_MPEG2; fqmParams.pMpeg2IqMatrix = (CodecMpeg2IqMatrix *)m_qMatrixParams; MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); // Send command buffer header at the beginning (OS dependent) if (!m_singleTaskPhaseSupported || m_firstTaskInPhase) { // frame tracking tag is only added in the last command buffer header auto requestFrameTracking = m_singleTaskPhaseSupported ? m_firstTaskInPhase : m_lastTaskInPhase; CODECHAL_ENCODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking)); m_hwInterface->m_numRequestedEuSlices = CODECHAL_SLICE_SHUTDOWN_DEFAULT; } if (m_currPass) { // Insert conditional batch buffer end MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS miConditionalBatchBufferEndParams; MOS_ZeroMemory( &miConditionalBatchBufferEndParams, sizeof(MHW_MI_CONDITIONAL_BATCH_BUFFER_END_PARAMS)); miConditionalBatchBufferEndParams.presSemaphoreBuffer = &m_encodeStatusBuf.resStatusBuffer; miConditionalBatchBufferEndParams.dwOffset = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) + m_encodeStatusBuf.dwImageStatusMaskOffset + (sizeof(uint32_t) * 2); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiConditionalBatchBufferEndCmd( &cmdBuffer, &miConditionalBatchBufferEndParams)); } if (!m_currPass && m_osInterface->bTagResourceSync) { // This is a solution to solve the sync tag issue: the sync tag write for PAK is inserted at the end of 2nd pass PAK BB // which may be skipped in multi-pass PAK enabled case. The idea here is to insert the previous frame's tag at the beginning // of the BB and keep the current frame's tag at the end of the BB. There will be a delay for tag update but it should be fine // as long as Dec/VP/Enc won't depend on this PAK so soon. PMOS_RESOURCE globalGpuContextSyncTagBuffer = nullptr; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetGpuStatusBufferResource( m_osInterface, globalGpuContextSyncTagBuffer)); CODECHAL_ENCODE_CHK_NULL_RETURN(globalGpuContextSyncTagBuffer); uint32_t statusTag = m_osInterface->pfnGetGpuStatusTag(m_osInterface, m_osInterface->CurrentGpuContextOrdinal); MHW_MI_STORE_DATA_PARAMS params; params.pOsResource = globalGpuContextSyncTagBuffer; params.dwResourceOffset = m_osInterface->pfnGetGpuStatusTagOffset(m_osInterface, m_osInterface->CurrentGpuContextOrdinal); params.dwValue = (statusTag > 0)? (statusTag - 1) : 0; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiStoreDataImmCmd(&cmdBuffer, ¶ms)); } CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams)); // Ref surface surfaceParams.ucSurfaceStateId = CODECHAL_MFX_REF_SURFACE_ID; surfaceParams.psSurface = &m_reconSurface; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &surfaceParams)); // Src surface surfaceParams.ucSurfaceStateId = CODECHAL_MFX_SRC_SURFACE_ID; surfaceParams.psSurface = m_rawSurfaceToPak; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &surfaceParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(&cmdBuffer, &pipeBufAddrParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd(&cmdBuffer, &bspBufBaseAddrParams)); if (m_brcEnabled) { MHW_BATCH_BUFFER batchBuffer; MOS_ZeroMemory(&batchBuffer, sizeof(batchBuffer)); batchBuffer.OsResource = m_brcBuffers.resBrcImageStatesWriteBuffer; batchBuffer.dwOffset = m_currPass * BRC_IMG_STATE_SIZE_PER_PASS; batchBuffer.bSecondLevel = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd( &cmdBuffer, &batchBuffer)); } else { auto picStateCmdStart = cmdBuffer.pCmdPtr; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxMpeg2PicCmd(&cmdBuffer, &mpeg2PicState)); CODECHAL_DEBUG_TOOL( auto picStateCmdEnd = cmdBuffer.pCmdPtr; uint32_t picStateCmdSize = ((uint32_t)(picStateCmdEnd - picStateCmdStart))*sizeof(uint32_t); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpData( (void *)picStateCmdStart, picStateCmdSize, CodechalDbgAttr::attrPicParams, "PicState"))); } CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxQmCmd(&cmdBuffer, &qmParams)); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxFqmCmd(&cmdBuffer, &fqmParams)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SendSliceParams( PMOS_COMMAND_BUFFER cmdBuffer, PMHW_VDBOX_MPEG2_SLICE_STATE params) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer); CODECHAL_ENCODE_CHK_NULL_RETURN(params); CODECHAL_ENCODE_CHK_NULL_RETURN(params->presDataBuffer); CODECHAL_ENCODE_CHK_NULL_RETURN(params->pBsBuffer); CODECHAL_ENCODE_CHK_NULL_RETURN(params->pSlcData); if (params->pSlcData->SliceGroup & SLICE_GROUP_START) { // add Mpeg2 Slice group commands CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfcMpeg2SliceGroupCmd(cmdBuffer, params)); MHW_BATCH_BUFFER secondLevelBatchBuffer; if (params->bBrcEnabled && params->dwSliceIndex == 0) { MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER)); secondLevelBatchBuffer.OsResource = *(params->presPicHeaderBBSurf); secondLevelBatchBuffer.dwOffset = 0; secondLevelBatchBuffer.bSecondLevel = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(cmdBuffer, &secondLevelBatchBuffer)); } else { // Insert pre-slice headers MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams; MOS_ZeroMemory(&pakInsertObjectParams, sizeof(pakInsertObjectParams)); pakInsertObjectParams.bLastHeader = true; pakInsertObjectParams.pBsBuffer = params->pBsBuffer; pakInsertObjectParams.dwBitSize = params->dwLength; pakInsertObjectParams.dwOffset = params->dwOffset; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPakInsertObject(cmdBuffer, nullptr, &pakInsertObjectParams)); } // Insert Batch Buffer Start command to send Mpeg2_PAK_OBJ data for MBs in this slice MOS_ZeroMemory(&secondLevelBatchBuffer, sizeof(MHW_BATCH_BUFFER)); secondLevelBatchBuffer.OsResource = *params->presDataBuffer; secondLevelBatchBuffer.dwOffset = params->dwDataBufferOffset; secondLevelBatchBuffer.bSecondLevel = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(cmdBuffer, &secondLevelBatchBuffer)); } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::ExecuteSliceLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface->osCpInterface); auto cpInterface = m_hwInterface->GetCpInterface(); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); if (m_osInterface->osCpInterface->IsCpEnabled()) { MHW_CP_SLICE_INFO_PARAMS sliceInfoParam; sliceInfoParam.bLastPass = (m_currPass == m_numPasses) ? true : false; CODECHAL_ENCODE_CHK_STATUS_RETURN(cpInterface->SetMfxProtectionState(m_mfxInterface->IsDecodeInUse(), &cmdBuffer, nullptr, &sliceInfoParam)); CODECHAL_ENCODE_CHK_STATUS_RETURN(cpInterface->UpdateParams(false)); } MHW_VDBOX_MPEG2_SLICE_STATE sliceState; MOS_ZeroMemory(&sliceState, sizeof(sliceState)); sliceState.presDataBuffer = &m_resMbCodeSurface; sliceState.pMpeg2PicIdx = &(m_picIdx[0]); sliceState.ppMpeg2RefList = &(m_refList[0]); sliceState.pEncodeMpeg2SeqParams = m_seqParams; sliceState.pEncodeMpeg2PicParams = m_picParams; sliceState.pEncodeMpeg2SliceParams = m_sliceParams; sliceState.pBsBuffer = &m_bsBuffer; sliceState.bBrcEnabled = m_brcEnabled; if (m_seqParams->m_forcePanicModeControl == 1) { sliceState.bRCPanicEnable = !m_seqParams->m_panicModeDisable; } else { sliceState.bRCPanicEnable = m_panicEnable; } sliceState.presPicHeaderBBSurf = &m_brcBuffers.resBrcPicHeaderOutputBuffer; for (uint16_t slcCount = 0; slcCount < m_numSlices; slcCount++) { //we should not need to call pfnPackSliceHeader this it's done by hw PCODEC_ENCODER_SLCDATA slcData = m_slcData; CODECHAL_ENCODE_CHK_NULL_RETURN(slcData); sliceState.dwDataBufferOffset = m_slcData[slcCount].CmdOffset + m_mbcodeBottomFieldOffset; sliceState.dwOffset = slcData[slcCount].SliceOffset; sliceState.dwLength = slcData[slcCount].BitSize; sliceState.dwSliceIndex = slcCount; sliceState.bFirstPass = true; sliceState.bLastPass = false; sliceState.pSlcData = &slcData[slcCount]; sliceState.bFirstPass = (m_currPass == 0); sliceState.bLastPass = (m_currPass == m_numPasses); CODECHAL_ENCODE_CHK_STATUS_RETURN(SendSliceParams(&cmdBuffer, &sliceState)); } // Insert end of stream if set if (m_lastPicInStream) { MHW_VDBOX_PAK_INSERT_PARAMS pakInsertObjectParams; MOS_ZeroMemory(&pakInsertObjectParams,sizeof(pakInsertObjectParams)); pakInsertObjectParams.bLastPicInStream = true; if (m_codecFunction == CODECHAL_FUNCTION_ENC_PAK) { pakInsertObjectParams.bSetLastPicInStreamData = true; pakInsertObjectParams.dwBitSize = 32; // use dwBitSize for SrcDataEndingBitInclusion pakInsertObjectParams.dwLastPicInStreamData = (uint32_t)((1 << 16) | startCodeSequenceEnd << 24); } else { pakInsertObjectParams.bSetLastPicInStreamData = false; pakInsertObjectParams.dwBitSize = 8; // use dwBitSize for SrcDataEndingBitInclusion pakInsertObjectParams.dwLastPicInStreamData = 0; } CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPakInsertObject(&cmdBuffer, nullptr, &pakInsertObjectParams)); } CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadMfcStatus(&cmdBuffer)); // BRC PAK statistics different for each pass if (m_brcEnabled) { uint32_t frameOffset = (m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize) + m_encodeStatusBuf.dwNumPassesOffset + // Num passes offset sizeof(uint32_t) * 2; // pEncodeStatus is offset by 2 DWs in the resource EncodeReadBrcPakStatsParams readBrcPakStatsParams; readBrcPakStatsParams.pHwInterface = m_hwInterface; readBrcPakStatsParams.presBrcPakStatisticBuffer = &m_brcBuffers.resBrcPakStatisticBuffer[0]; readBrcPakStatsParams.presStatusBuffer = &m_encodeStatusBuf.resStatusBuffer; readBrcPakStatsParams.dwStatusBufNumPassesOffset = frameOffset; readBrcPakStatsParams.ucPass = m_currPass; readBrcPakStatsParams.VideoContext = m_videoContext; CODECHAL_ENCODE_CHK_STATUS_RETURN(ReadBrcPakStatistics( &cmdBuffer, &readBrcPakStatsParams)); } CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport( &cmdBuffer, CODECHAL_NUM_MEDIA_STATES)); if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( &cmdBuffer, nullptr)); } std::string Pak_pass = "PAK_PASS[" + std::to_string(static_cast(m_currPass))+"]"; CODECHAL_DEBUG_TOOL( CODECHAL_ENCODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, CODECHAL_NUM_MEDIA_STATES, Pak_pass.c_str())); //CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands( // m_debugInterface, // &cmdBuffer)); ) m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); MOS_SYNC_PARAMS syncParams; if ((m_currPass == 0) && !Mos_ResourceIsNull(&m_resSyncObjectRenderContextInUse)) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObjectRenderContextInUse; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); } if (!m_singleTaskPhaseSupported || m_lastTaskInPhase) { CODECHAL_ENCODE_CHK_STATUS_RETURN(SubmitCommandBuffer(&cmdBuffer, m_videoContextUsesNullHw)); CODECHAL_DEBUG_TOOL( if (m_mmcState) { m_mmcState->UpdateUserFeatureKey(&m_reconSurface); } ) if ((m_currPass == m_numPasses) && m_signalEnc && !Mos_ResourceIsNull(&m_resSyncObjectVideoContextInUse)) { // Check if the signal obj count exceeds max m_value if (m_semaphoreObjCount == MOS_MIN(m_semaphoreMaxCount, MOS_MAX_OBJECT_SIGNALED)) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_renderContext; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); m_semaphoreObjCount--; } // signal semaphore syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); m_semaphoreObjCount++; } } // Reset parameters for next PAK execution if (m_currPass == m_numPasses) { m_newPpsHeader = 0; m_newSeqHeader = 0; } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::PackSkippedMB(uint32_t mbIncrement) { CODECHAL_ENCODE_FUNCTION_ENTER; auto bsBuffer = &m_bsBuffer; //macroblock_escap: The macroblock_escap`e is a fixed bit-string "0000 0001 000" which is used //when the difference between macroblock_address and previous_macroblock_address is greater than 33 while(mbIncrement > 33) { PutBits(bsBuffer,0x08,11); mbIncrement -= 33; } // macroblock_address_increment: This is a variable length coded integer //which indicates the difference between macroblock_address and previous_macroblock_address PutBits(bsBuffer, mpeg2AddrIncreamentTbl[mbIncrement].m_code, mpeg2AddrIncreamentTbl[mbIncrement].m_len); // macroblock_modes() //macroblock_type: Variable length coded indicator which indicates the method of coding and //content of the macroblock according to the Tables B-2 through B-8 in spec ISO 13818-2, //for skip mb, we should choose "MC, NotCoded" for P frame which means there are no quant, backward mv, mb pattern ... //choose "Bwd,Not Coded" for B frame if(m_pictureCodingType == P_TYPE) { PutBits(bsBuffer, mpeg2MbTypeTbl[1][8].m_code, mpeg2MbTypeTbl[1][8].m_len); } else if(m_pictureCodingType == B_TYPE) { PutBits(bsBuffer, mpeg2MbTypeTbl[2][4].m_code, mpeg2MbTypeTbl[2][4].m_len); } // frame_motion_type This is a two bit code indicating the macroblock prediction, 0b10 -- frame-based // 0b01 --field based 0b11---Dual-Prime // attention: currently, mpeg2 encode only support frame encoding and field frame encoding , so Picture_Struct should be 3 if(m_picParams->m_framePredFrameDCT == 0) { PutBits(bsBuffer, 2, 2); } // motion_vectors // motion_vector ( 0, 0 ) // // set the MV to zero for skip MB. PutBits(bsBuffer, mpeg2MvVlcTbl[16 + 0].m_code, mpeg2MvVlcTbl[16 + 0].m_len); PutBits(bsBuffer, mpeg2MvVlcTbl[16 + 0].m_code, mpeg2MvVlcTbl[16 + 0].m_len); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalEncodeMpeg2::PackSkipSliceData() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; auto slcParams = m_sliceParams; auto bsBuffer = &m_bsBuffer; while (bsBuffer->BitOffset) { PutBits(bsBuffer, 0, 1); } for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++) { //slice start code PutBits(bsBuffer,0x000001,24); PutBits(bsBuffer,slcParams->m_firstMbY + 1,8); // quantiser_scale_code PutBits(bsBuffer,slcParams->m_quantiserScaleCode, 5); // intra_slice_flag PutBits(bsBuffer, 1, 1); // intra_slice PutBits(bsBuffer, slcParams->m_intraSlice, 1); // reserved_bits PutBits(bsBuffer, 0, 7); // extra_bit_slice PutBits(bsBuffer, 0, 1); PackSkippedMB(1); PackSkippedMB(slcParams->m_numMbsForSlice - 1); while (bsBuffer->BitOffset) { PutBits(bsBuffer, 0, 1); } slcParams++; } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::EncodeCopySkipFrame() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; PackSkipSliceData(); CodechalResLock bufLock(m_osInterface, &m_resBitstreamBuffer); auto data = bufLock.Lock(CodechalResLock::writeOnly);; CODECHAL_ENCODE_CHK_NULL_RETURN(data); auto bsBuffer = &m_bsBuffer; auto bsSize = (uint32_t)(bsBuffer->pCurrent - bsBuffer->pBase); //copy skipped frame MOS_SecureMemcpy(data, bsSize, bsBuffer->pBase, bsSize); //unlock bitstream buffer m_osInterface->pfnUnlockResource( m_osInterface, &m_resBitstreamBuffer ); //get cmd buffer MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); //start status report CODECHAL_ENCODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES)); //fill status report auto encodeStatus = (EncodeStatus*)(m_encodeStatusBuf.pEncodeStatus + m_encodeStatusBuf.wCurrIndex * m_encodeStatusBuf.dwReportSize); encodeStatus->dwMFCBitstreamByteCountPerFrame = bsSize; encodeStatus->dwHeaderBytesInserted = 0; // set dwHeaderBytesInserted to 0 //end status report CODECHAL_ENCODE_CHK_STATUS_RETURN(EndStatusReport(&cmdBuffer, CODECHAL_NUM_MEDIA_STATES)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw)); return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SendMbEncSurfaces( PMOS_COMMAND_BUFFER cmdBuffer, bool mbEncIFrameDistEnabled) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_ENCODE_FUNCTION_ENTER; CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer); PMHW_KERNEL_STATE kernelState; if (mbEncIFrameDistEnabled) { kernelState = &m_brcKernelStates[CODECHAL_ENCODE_BRC_IDX_IFRAMEDIST]; } else { // wPictureCodingType: I_TYPE = 1, P_TYPE = 2, B_TYPE = 3 // KernelStates are I: 0, P: 1, B: 2 // m_mbEncKernelStates: I: m_mbEncKernelStates[0], P: m_mbEncKernelStates[1], B: m_mbEncKernelStates[2] uint32_t krnStateIdx = m_pictureCodingType - 1; if (m_mbEncForcePictureCodingType) { krnStateIdx = m_mbEncForcePictureCodingType - 1; } kernelState = &m_mbEncKernelStates[krnStateIdx]; } auto presMbCodeBuffer = &m_refList[m_currReconstructedPic.FrameIdx]->resRefMbCodeBuffer; auto presPrevMbCodeBuffer = &m_refList[m_prevMBCodeIdx]->resRefMbCodeBuffer; // Caution: if PAFF supports added, need to make sure each field get correct surface pointer // PAK Obj command buffer uint32_t pakSize = (uint32_t)m_picWidthInMb * m_frameFieldHeightInMb * 16 * 4; // 12 DW for MB + 4 DW for MV CODECHAL_SURFACE_CODEC_PARAMS surfaceCodecParams; MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.presBuffer = presMbCodeBuffer; surfaceCodecParams.dwSize = pakSize; surfaceCodecParams.dwOffset = (uint32_t)m_mbcodeBottomFieldOffset; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_PAK_OBJECT_ENCODE].Value; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncPakObj; surfaceCodecParams.bRenderTarget = true; surfaceCodecParams.bIsWritable = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); // Prev PAK Obj command buffer pakSize = (uint32_t)m_picWidthInMb * m_frameFieldHeightInMb * 16 * 4; // 12 DW for MB + 4 DW for MV // verify if the current frame is not the first frame if (!Mos_ResourceIsNull(presPrevMbCodeBuffer) && !m_firstFrame) { MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.presBuffer = presPrevMbCodeBuffer; surfaceCodecParams.dwSize = pakSize; surfaceCodecParams.dwOffset = (uint32_t)m_mbcodeBottomFieldOffset; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_PAK_OBJECT_ENCODE].Value; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncPakObjPrev; surfaceCodecParams.bRenderTarget = true; surfaceCodecParams.bIsWritable = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); } auto currPicSurface = mbEncIFrameDistEnabled ? m_trackedBuf->Get4xDsSurface(CODEC_CURR_TRACKED_BUFFER) : m_rawSurfaceToEnc; // Current Picture Y MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIs2DSurface = true; surfaceCodecParams.psSurface = currPicSurface; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncCurrentY; surfaceCodecParams.dwVerticalLineStride = m_verticalLineStride; surfaceCodecParams.dwVerticalLineStrideOffset = m_verticalLineStrideOffset; #ifdef _MMC_SUPPORTED CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams)); #endif CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); bool currBottomField = CodecHal_PictureIsBottomField(m_currOriginalPic) ? 1 : 0; uint8_t vDirection = (CodecHal_PictureIsFrame(m_currOriginalPic)) ? CODECHAL_VDIRECTION_FRAME : (currBottomField) ? CODECHAL_VDIRECTION_BOT_FIELD : CODECHAL_VDIRECTION_TOP_FIELD; // Current Picture MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bUseAdvState = true; surfaceCodecParams.psSurface = currPicSurface; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncCurrentPic; surfaceCodecParams.ucVDirection = vDirection; #ifdef _MMC_SUPPORTED CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams)); #endif CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); uint8_t picIdx0 = CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2; uint8_t picIdx1 = CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2; bool refL0BottomField = false; bool refL1BottomField = false; if (m_picIdx[0].bValid) { picIdx0 = m_picIdx[0].ucPicIdx; refL0BottomField = (CodecHal_PictureIsBottomField(m_currOriginalPic)) ? 1 : 0; } if (m_picIdx[1].bValid) { picIdx1 = m_picIdx[1].ucPicIdx; refL1BottomField = (CodecHal_PictureIsBottomField(m_currOriginalPic)) ? 1 : 0; } // forward reference if (picIdx0 < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2) { if (m_verticalLineStride == CODECHAL_VLINESTRIDE_FIELD) { vDirection = (refL0BottomField ? CODECHAL_VDIRECTION_BOT_FIELD : CODECHAL_VDIRECTION_TOP_FIELD); } // Picture Y CodecHalGetResourceInfo(m_osInterface, &m_refList[picIdx0]->sRefBuffer); // Picture Y VME MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bUseAdvState = true; surfaceCodecParams.psSurface = &m_refList[picIdx0]->sRefBuffer; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncForwardPic; surfaceCodecParams.ucVDirection = vDirection; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value; #ifdef _MMC_SUPPORTED CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams)); #endif CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); } // backward reference if (picIdx1 < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2) { if (m_verticalLineStride == CODECHAL_VLINESTRIDE_FIELD) { vDirection = (refL1BottomField ? CODECHAL_VDIRECTION_BOT_FIELD : CODECHAL_VDIRECTION_TOP_FIELD); } CodecHalGetResourceInfo(m_osInterface, &m_refList[picIdx1]->sRefBuffer); // Picture Y VME MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bUseAdvState = true; surfaceCodecParams.psSurface = &m_refList[picIdx1]->sRefBuffer; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncBackwardPic; surfaceCodecParams.ucVDirection = vDirection; #ifdef _MMC_SUPPORTED CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams)); #endif CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); } // Interlace Frame if ((CodecHal_PictureIsFrame(m_picParams->m_currOriginalPic)) && (m_picParams->m_fieldCodingFlag || m_picParams->m_fieldFrameCodingFlag)) { // Current Picture Interlace MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bUseAdvState = true; surfaceCodecParams.psSurface = currPicSurface; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_CURR_ENCODE].Value; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncInterlaceFrameCurrentPic; surfaceCodecParams.ucVDirection = vDirection; #ifdef _MMC_SUPPORTED CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams)); #endif CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); if (picIdx1 < CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2) { // Picture Y VME MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bUseAdvState = true; surfaceCodecParams.psSurface = &m_refList[picIdx1]->sRefBuffer; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_REF_ENCODE].Value; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncInterlaceFrameBackwardPic; surfaceCodecParams.ucVDirection = vDirection; #ifdef _MMC_SUPPORTED CODECHAL_ENCODE_CHK_STATUS_RETURN(m_mmcState->SetSurfaceParams(&surfaceCodecParams)); #endif CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); } } // BRC distortion data buffer for I frame if (mbEncIFrameDistEnabled) { MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIs2DSurface = true; surfaceCodecParams.bMediaBlockRW = true; surfaceCodecParams.psSurface = &m_brcBuffers.sMeBrcDistortionBuffer; surfaceCodecParams.dwOffset = m_brcBuffers.dwMeBrcDistortionBottomFieldOffset; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncBrcDistortionSurface; surfaceCodecParams.bRenderTarget = true; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); } // MB-control surface for MB level QP, SkipEnable and NonSkipEnable if (m_mbQpDataEnabled) { MOS_ZeroMemory(&surfaceCodecParams, sizeof(CODECHAL_SURFACE_CODEC_PARAMS)); surfaceCodecParams.bIs2DSurface = true; surfaceCodecParams.bMediaBlockRW = true; surfaceCodecParams.psSurface = &m_mbQpDataSurface; surfaceCodecParams.dwCacheabilityControl = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_MB_QP_CODEC].Value; surfaceCodecParams.dwBindingTableOffset = m_mbEncBindingTable.m_mbEncMbControl; CODECHAL_ENCODE_CHK_STATUS_RETURN(CodecHalSetRcsSurfaceState( m_hwInterface, cmdBuffer, &surfaceCodecParams, kernelState)); } return eStatus; } MOS_STATUS CodechalEncodeMpeg2::SendPrologWithFrameTracking( PMOS_COMMAND_BUFFER cmdBuffer, bool frameTracking, MHW_MI_MMIOREGISTERS *mmioRegister) { return CodechalEncoderState::SendPrologWithFrameTracking(cmdBuffer, frameTracking, mmioRegister); } void CodechalEncodeMpeg2::UpdateSSDSliceCount() { m_setRequestedEUSlices = (m_brcEnabled && m_sliceStateEnable && (m_frameHeight * m_frameWidth) >= m_hwInterface->m_mpeg2SSDResolutionThreshold) ? true : false; m_hwInterface->m_numRequestedEuSlices = (m_setRequestedEUSlices) ? m_sliceShutdownRequestState : m_sliceShutdownDefaultState; } MOS_STATUS CodechalEncodeMpeg2::AddMediaVfeCmd( PMOS_COMMAND_BUFFER cmdBuffer, SendKernelCmdsParams *params) { CODECHAL_ENCODE_CHK_NULL_RETURN(params); MHW_VFE_PARAMS vfeParams = {}; vfeParams.pKernelState = params->pKernelState; vfeParams.eVfeSliceDisable = MHW_VFE_SLICE_ALL; vfeParams.dwMaximumNumberofThreads = m_encodeVfeMaxThreads; if (!m_useHwScoreboard) { vfeParams.Scoreboard.ScoreboardMask = 0; } else { vfeParams.Scoreboard.ScoreboardEnable = true; vfeParams.Scoreboard.ScoreboardType = m_hwScoreboardType; vfeParams.Scoreboard.ScoreboardMask = 0xFF; // Scoreboard 0 vfeParams.Scoreboard.ScoreboardDelta[0].x = 0xF; vfeParams.Scoreboard.ScoreboardDelta[0].y = 0; // Scoreboard 1 vfeParams.Scoreboard.ScoreboardDelta[1].x = 0; vfeParams.Scoreboard.ScoreboardDelta[1].y = 0xF; // Scoreboard 2 vfeParams.Scoreboard.ScoreboardDelta[2].x = 0xE; vfeParams.Scoreboard.ScoreboardDelta[2].y = 0; } CODECHAL_ENCODE_CHK_STATUS_RETURN(m_renderEngineInterface->AddMediaVfeCmd(cmdBuffer, &vfeParams)); return MOS_STATUS_SUCCESS; } #if USE_CODECHAL_DEBUG_TOOL MOS_STATUS CodechalEncodeMpeg2::DumpSeqParams( CodecEncodeMpeg2SequenceParams *seqParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSeqParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(seqParams); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss << "m_frameWidth: " << +seqParams->m_frameWidth << std::endl; oss << "m_frameHeight: " << +seqParams->m_frameHeight << std::endl; oss << "m_profile: " << +seqParams->m_profile << std::endl; oss << "m_profile: " << +seqParams->m_level << std::endl; oss << "m_chromaFormat: " << +seqParams->m_chromaFormat << std::endl; oss << "m_targetUsage: " << +seqParams->m_targetUsage << std::endl; oss << "m_aratioFrate: " << +seqParams->m_aratioFrate << std::endl; oss << "m_aspectRatio: " << +seqParams->m_aspectRatio << std::endl; oss << "m_frameRateCode: " << +seqParams->m_frameRateCode << std::endl; oss << "m_frameRateExtN: " << +seqParams->m_frameRateExtN << std::endl; oss << "m_frameRateExtD: " << +seqParams->m_frameRateExtD << std::endl; oss << "m_bitrate: " << +seqParams->m_bitrate << std::endl; oss << "m_vbvBufferSize: " << +seqParams->m_vbvBufferSize << std::endl; oss << "m_progressiveSequence: " << +seqParams->m_progressiveSequence << std::endl; oss << "m_lowDelay: " << +seqParams->m_lowDelay << std::endl; oss << "m_resetBRC: " << +seqParams->m_resetBRC << std::endl; oss << "m_noAcceleratorSPSInsertion: " << +seqParams->m_noAcceleratorSPSInsertion << std::endl; oss << "m_reserved0: " << +seqParams->m_reserved0 << std::endl; oss << "m_rateControlMethod: " << +seqParams->m_rateControlMethod << std::endl; oss << "m_reserved1: " << +seqParams->m_reserved1 << std::endl; oss << "m_maxBitRate: " << +seqParams->m_maxBitRate << std::endl; oss << "m_minBitRate: " << +seqParams->m_minBitRate << std::endl; oss << "m_userMaxFrameSize: " << +seqParams->m_userMaxFrameSize << std::endl; oss << "m_initVBVBufferFullnessInBit: " << +seqParams->m_initVBVBufferFullnessInBit << std::endl; const char *fileName = m_debugInterface->CreateFileName( "_DDIEnc", CodechalDbgBufferType::bufSeqParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalEncodeMpeg2::DumpPicParams( CodecEncodeMpeg2PictureParams *picParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(picParams); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss << "m_currOriginalPic: " << +picParams->m_currOriginalPic.FrameIdx << std::endl; oss << "m_currReconstructedPic: " << +picParams->m_currReconstructedPic.FrameIdx << std::endl; oss << "m_pictureCodingType: " << +picParams->m_pictureCodingType << std::endl; oss << "m_fieldCodingFlag: " << +picParams->m_fieldCodingFlag << std::endl; oss << "m_fieldFrameCodingFlag: " << +picParams->m_fieldFrameCodingFlag << std::endl; oss << "m_interleavedFieldBFF: " << +picParams->m_interleavedFieldBFF << std::endl; oss << "m_progressiveField: " << +picParams->m_progressiveField << std::endl; oss << "m_numSlice: " << +picParams->m_numSlice << std::endl; oss << "m_picBackwardPrediction: " << +picParams->m_picBackwardPrediction << std::endl; oss << "m_bidirectionalAveragingMode: " << +picParams->m_bidirectionalAveragingMode << std::endl; oss << "m_pic4MVallowed: " << +picParams->m_pic4MVallowed << std::endl; oss << "m_refFrameList: " << +picParams->m_refFrameList[0].FrameIdx << " " << +picParams->m_refFrameList[1].FrameIdx << std::endl; oss << "m_useRawPicForRef: " << +picParams->m_useRawPicForRef << std::endl; oss << "m_statusReportFeedbackNumber: " << +picParams->m_statusReportFeedbackNumber << std::endl; oss << "m_alternateScan: " << +picParams->m_alternateScan << std::endl; oss << "m_intraVlcFormat: " << +picParams->m_intraVlcFormat << std::endl; oss << "m_qscaleType: " << +picParams->m_qscaleType << std::endl; oss << "m_concealmentMotionVectors: " << +picParams->m_concealmentMotionVectors << std::endl; oss << "m_framePredFrameDCT: " << +picParams->m_framePredFrameDCT << std::endl; oss << "m_disableMismatchControl: " << +picParams->m_disableMismatchControl << std::endl; oss << "m_intraDCprecision: " << +picParams->m_intraDCprecision << std::endl; oss << "m_fcode00: " << +picParams->m_fcode00 << std::endl; oss << "m_fcode01: " << +picParams->m_fcode01 << std::endl; oss << "m_fcode10: " << +picParams->m_fcode10 << std::endl; oss << "m_fcode11: " << +picParams->m_fcode11 << std::endl; oss << "m_lastPicInStream: " << +picParams->m_lastPicInStream << std::endl; oss << "m_newGop: " << +picParams->m_newGop << std::endl; oss << "m_gopPicSize: " << +picParams->m_gopPicSize << std::endl; oss << "m_gopRefDist: " << +picParams->m_gopRefDist << std::endl; oss << "m_gopOptFlag: " << +picParams->m_gopOptFlag << std::endl; oss << "m_timeCode: " << +picParams->m_timeCode << std::endl; oss << "m_temporalReference: " << +picParams->m_temporalReference << std::endl; oss << "m_vbvDelay: " << +picParams->m_vbvDelay << std::endl; oss << "m_repeatFirstField: " << +picParams->m_repeatFirstField << std::endl; oss << "m_compositeDisplayFlag: " << +picParams->m_compositeDisplayFlag << std::endl; oss << "m_vaxis: " << +picParams->m_vaxis << std::endl; oss << "m_fieldSequence: " << +picParams->m_fieldSequence << std::endl; oss << "m_subCarrier: " << +picParams->m_subCarrier << std::endl; oss << "m_burstAmplitude: " << +picParams->m_burstAmplitude << std::endl; oss << "m_subCarrierPhase: " << +picParams->m_subCarrierPhase << std::endl; const char *fileName = m_debugInterface->CreateFileName( "_DDIEnc", CodechalDbgBufferType::bufPicParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalEncodeMpeg2::DumpSliceParams( CodecEncodeMpeg2SliceParmas *sliceParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(sliceParams); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss << "m_numMbsForSlice: " << +sliceParams->m_numMbsForSlice << std::endl; oss << "m_firstMbX: " << +sliceParams->m_firstMbX << std::endl; oss << "m_firstMbY: " << +sliceParams->m_firstMbY << std::endl; oss << "m_intraSlice: " << +sliceParams->m_intraSlice << std::endl; oss << "m_quantiserScaleCode: " << +sliceParams->m_quantiserScaleCode << std::endl; const char *fileName = m_debugInterface->CreateFileName( "_DDIEnc", CodechalDbgBufferType::bufSlcParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalEncodeMpeg2::DumpVuiParams( CodecEncodeMpeg2VuiParams *vuiParams) { CODECHAL_DEBUG_FUNCTION_ENTER; CODECHAL_DEBUG_CHK_NULL(vuiParams); if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrVuiParams)) { return MOS_STATUS_SUCCESS; } std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss << "m_videoFormat: " << +vuiParams->m_videoFormat << std::endl; oss << "m_colourDescription: " << +vuiParams->m_colourDescription << std::endl; oss << "m_colourPrimaries: " << +vuiParams->m_colourPrimaries << std::endl; oss << "m_transferCharacteristics: " << +vuiParams->m_transferCharacteristics << std::endl; oss << "m_matrixCoefficients: " << +vuiParams->m_matrixCoefficients << std::endl; oss << "m_displayHorizontalSize: " << +vuiParams->m_displayHorizontalSize << std::endl; oss << "m_displayVerticalSize: " << +vuiParams->m_displayVerticalSize << std::endl; const char *fileName = m_debugInterface->CreateFileName( "_DDIEnc", CodechalDbgBufferType::bufVuiParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } #endif /************************************************************************** * MB sequence in a non-MBAFF picture with WidthInMB = 5 & HeightInMB = 6 * 26 degree walking pattern * 0 1 2 3 4 * ----------------------- * 0 | 0 1 2 4 6 * 1 | 3 5 7 9 11 * 2 | 8 10 12 14 16 * 3 | 13 15 17 19 21 * 4 | 18 20 22 24 26 * 5 | 23 25 27 28 29 ***************************************************************************/ void CodechalEncodeMpeg2::MBWalker(uint16_t picWidthInMB, uint16_t picHeightInMB, uint16_t *mbmap) { uint16_t i, j; uint16_t numMBs = picWidthInMB * picHeightInMB; uint16_t curX = 0, curY = 0, wflenX, wflenY; uint16_t wfstart = 0, wflen; uint16_t walkX, walkY; wflenY = picHeightInMB - 1; for (i = 0; i < numMBs; i++) { // Get current region length wflenX = curX / 2; wflen = (wflenX < wflenY) ? wflenX : wflenY; mbmap[wfstart] = curY * picWidthInMB + curX; if (wfstart == (numMBs - 1)) break; walkX = curX - 2; walkY = curY + 1; for (j = 0; j < wflen; j++) { mbmap[wfstart + j + 1] = walkY * picWidthInMB + walkX; walkX -= 2; walkY++; } // Start new region if (curX == (picWidthInMB - 1)) { // Right picture boundary reached, adjustment required curX--; curY++; wflenY--; } else { curX++; } wfstart += (wflen + 1); } } /************************************************************************** * MB sequence in a non-MBAFF picture with WidthInMB = 5 & HeightInMB = 6 * 45 degree pattern * 0 1 2 3 4 * ----------------------- * 0 | 0 1 3 6 10 * 1 | 2 4 7 11 15 * 2 | 5 8 12 16 20 * 3 | 9 13 17 21 24 * 4 | 14 18 22 25 27 * 5 | 19 23 26 28 29 ***************************************************************************/ void CodechalEncodeMpeg2::MBWalker45Degree(uint16_t picWidthInMB, uint16_t picHeightInMB, uint16_t *mbmap) { uint16_t i, j; uint16_t numMBs = picWidthInMB * picHeightInMB; uint16_t curX = 0, curY = 0, wflenX, wflenY; uint16_t wfstart = 0, wflen; uint16_t walkX, walkY; wflenY = picHeightInMB - 1; for (i = 0; i < numMBs; i++) { // Get current region length wflenX = curX; wflen = (wflenX < wflenY) ? wflenX : wflenY; mbmap[wfstart] = curY * picWidthInMB + curX; if (wfstart == (numMBs - 1)) break; walkX = curX - 1; walkY = curY + 1; for (j = 0; j < wflen; j++) { mbmap[wfstart + j + 1] = walkY * picWidthInMB + walkX; walkX -= 1; walkY++; } // Start new region if (curX == (picWidthInMB - 1)) { // Right picture boundary reached, adjustment required curY++; wflenY--; } else { curX++; } wfstart += (wflen + 1); } } /************************************************************************** * MB sequence in a MBAFF picture with WidthInMB = 5 & HeightInMB = 6 * 26 degree walking pattern * 0 1 2 3 4 * ----------------------- * 0 | 0 2 4 8 12 * 1 | 1 3 6 10 15 * 2 | 5 9 13 18 22 * 3 | 7 11 16 20 24 * 4 | 14 19 23 26 28 * 5 | 17 21 25 27 29 ***************************************************************************/ void CodechalEncodeMpeg2::MBWalkerMBAFF(uint16_t picWidthInMB, uint16_t picHeightInMB, uint16_t *mbmap) { uint16_t i, j, k; uint16_t numMBs = picWidthInMB * picHeightInMB; uint16_t curX = 0, curY = 0, wflenX, wflenY; uint16_t wfstart = 0, wflen; uint16_t walkX, walkY; wflenY = picHeightInMB / 2 - 1; for (i = 0; i < numMBs; i++) { // Get current region length wflenX = curX / 2; wflen = (wflenX < wflenY) ? wflenX : wflenY; mbmap[wfstart] = curY * picWidthInMB + curX * 2; mbmap[wfstart + wflen + 1] = mbmap[wfstart] + 1; if ((wfstart + wflen + 1) == (numMBs - 1)) break; walkX = curX - 2; walkY = curY + 2; for (j = 0; j < wflen; j++) { k = wfstart + j + 1; mbmap[k] = walkY * picWidthInMB + walkX * 2; mbmap[k + wflen + 1] = mbmap[k] + 1; walkX -= 2; walkY += 2; } // Start new region if (curX == (picWidthInMB - 1)) { // Right picture boundary reached, adjustment required curX--; curY += 2; wflenY--; } else { curX++; } wfstart += ((wflen + 1) * 2); } } /************************************************************************** * MB sequence in a non-MBAFF picture with WidthInMB = 5 & HeightInMB = 5 * Raster scan pattern * 0 1 2 3 4 * ----------------------- * 0 | 0 1 2 3 4 * 1 | 5 6 7 8 9 * 2 | 10 11 12 13 14 * 3 | 15 16 17 18 19 * 4 | 20 21 22 23 24 ***************************************************************************/ void CodechalEncodeMpeg2::MBWalkerRasterScan(uint16_t picWidthInMB, uint16_t picHeightInMB, uint16_t *mbmap) { uint32_t i; uint32_t numMBs = picWidthInMB * picHeightInMB; for (i = 0; i < numMBs; i++) { mbmap[i] = (uint16_t)i; } } /************************************************************************** * MB sequence in a non-MBAFF picture with WidthInMB = 5 & HeightInMB = 5 * Vertical scan pattern * 0 1 2 3 4 * ----------------------- * 0 | 0 5 10 15 20 * 1 | 1 6 11 16 21 * 2 | 2 7 12 17 22 * 3 | 3 8 13 18 23 * 4 | 4 9 14 19 24 ***************************************************************************/ void CodechalEncodeMpeg2::MBWalkerVerticalScan(uint16_t picWidthInMB, uint16_t picHeightInMB, uint16_t *mbmap) { uint32_t i, j, k; for (i = 0, k = 0; i < picWidthInMB; i++) { for (j = 0; j < picHeightInMB; j++) { mbmap[k++] = (uint16_t)(i + j * picWidthInMB); } } }