| /* |
| * 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" |
| |
| #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; //<! in MB unit |
| uint32_t m_mbY : 8; //<! in MB unit |
| uint32_t m_reserved : 16; |
| }; |
| struct |
| { |
| uint32_t m_value; |
| }; |
| } DW0; |
| |
| // uint32_t 1 |
| union |
| { |
| struct |
| { |
| uint32_t m_lastMbInSliceGroup : 8; |
| uint32_t m_firstMbInSliceGroup : 8; |
| uint32_t m_lastMbInSlice : 8; |
| uint32_t m_firstMbInSlice : 8; |
| }; |
| struct |
| { |
| uint32_t m_value; |
| }; |
| } DW1; |
| |
| // uint32_t 2 |
| union |
| { |
| struct |
| { |
| uint32_t m_batchBufferEnd : 32; |
| }; |
| struct |
| { |
| uint32_t m_value; |
| }; |
| } DW2; |
| } ; |
| |
| //! |
| //! \struct SliceRecord |
| //! \brief Slice record |
| //! |
| struct SliceRecord |
| { |
| // DW 1 |
| union |
| { |
| struct |
| { |
| uint32_t m_lastMbInSliceGroup : 8; |
| uint32_t m_firstMbInSliceGroup : 8; |
| uint32_t m_lastMbInSlice : 8; |
| uint32_t m_firstMbInSlice : 8; |
| }; |
| struct |
| { |
| uint32_t m_value; |
| }; |
| } DW1; |
| |
| // DW 2 |
| union |
| { |
| struct |
| { |
| uint32_t m_batchBufferEnd : 32; |
| }; |
| struct |
| { |
| uint32_t m_value; |
| }; |
| } DW2; |
| } ; |
| |
| /* VL codes for macroblock_address_increment ISO/IEC 13818-2, B.1, Table B-1. */ |
| static const VLCode mpeg2AddrIncreamentTbl[35] = |
| { |
| { 0x00, 0 }, // forbidden m_value |
| { 0x01, 1 }, |
| { 0x03, 3 }, { 0x02, 3 }, |
| { 0x03, 4 }, { 0x02, 4 }, |
| { 0x03, 5 }, { 0x02, 5 }, |
| { 0x07, 7 }, { 0x06, 7 }, |
| { 0x0b, 8 }, { 0x0a, 8 }, { 0x09, 8 }, { 0x08, 8 }, { 0x07, 8 }, { 0x06, 8 }, |
| { 0x17, 10 }, { 0x16, 10 }, { 0x15, 10 }, { 0x14, 10 }, { 0x13, 10 }, { 0x12, 10 }, |
| { 0x23, 11 }, { 0x22, 11 }, { 0x21, 11 }, { 0x20, 11 }, { 0x1f, 11 }, { 0x1e, 11 }, { 0x1d, 11 }, { 0x1c, 11 }, { 0x1b, 11 }, { 0x1a, 11 }, { 0x19, 11 }, { 0x18, 11 }, |
| { 0x08, 11 } // macroblock_escape |
| }; |
| |
| /* VL codes for macroblock_type ISO/IEC 13818-2, B.2, Tables B-2, B-3, B-4. */ |
| static const VLCode mpeg2MbTypeTbl[3][32] = |
| { |
| /* I */ |
| { |
| { 0x00, 0 }, { 0x01, 1 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, |
| { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, |
| { 0x00, 0 }, { 0x01, 2 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, |
| { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 } |
| }, |
| /* P */ |
| { |
| { 0x00, 0 }, { 0x03, 5 }, { 0x01, 2 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, |
| { 0x01, 3 }, { 0x00, 0 }, { 0x01, 1 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, |
| { 0x00, 0 }, { 0x01, 6 }, { 0x01, 5 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, |
| { 0x00, 0 }, { 0x00, 0 }, { 0x02, 5 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 } |
| }, |
| /* B */ |
| { |
| { 0x00, 0 }, { 0x03, 5 }, { 0x00, 0 }, { 0x00, 0 }, { 0x02, 3 }, { 0x00, 0 }, { 0x03, 3 }, { 0x00, 0 }, |
| { 0x02, 4 }, { 0x00, 0 }, { 0x03, 4 }, { 0x00, 0 }, { 0x02, 2 }, { 0x00, 0 }, { 0x03, 2 }, { 0x00, 0 }, |
| { 0x00, 0 }, { 0x01, 6 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x02, 6 }, { 0x00, 0 }, |
| { 0x00, 0 }, { 0x00, 0 }, { 0x03, 6 }, { 0x00, 0 }, { 0x00, 0 }, { 0x00, 0 }, { 0x02, 5 }, { 0x00, 0 } |
| } |
| }; |
| |
| /* VL codes for motion_code+16 ISO/IEC 13818-2, B.4, Table B-10. */ |
| static const VLCode mpeg2MvVlcTbl[33] = |
| { |
| // negative motion_code |
| { 0x19, 11 }, { 0x1b, 11 }, { 0x1d, 11 }, { 0x1f, 11 }, { 0x21, 11 }, { 0x23, 11 }, |
| { 0x13, 10 }, { 0x15, 10 }, { 0x17, 10 }, |
| { 0x07, 8 }, { 0x09, 8 }, { 0x0b, 8 }, |
| { 0x07, 7 }, |
| { 0x03, 5 }, |
| { 0x03, 4 }, |
| { 0x03, 3 }, |
| // zero motion_code |
| { 0x01, 1 }, |
| // positive motion_code |
| { 0x02, 3 }, |
| { 0x02, 4 }, |
| { 0x02, 5 }, |
| { 0x06, 7 }, |
| { 0x0a, 8 }, { 0x08, 8 }, { 0x06, 8 }, |
| { 0x16, 10 }, { 0x14, 10 }, { 0x12, 10 }, |
| { 0x22, 11 }, { 0x20, 11 }, { 0x1e, 11 }, { 0x1c, 11 }, { 0x1a, 11 }, { 0x18, 11 } |
| }; |
| |
| BrcInitResetCurbe::BrcInitResetCurbe() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| MOS_ZeroMemory(&m_curbeData, m_byteSize); |
| |
| m_curbeData.DW10.m_avbrAccuracy = 30; |
| m_curbeData.DW11.m_avbrConvergence = 150; |
| m_curbeData.DW11.m_minQP = 1; |
| m_curbeData.DW12.m_maxQP = 112; |
| m_curbeData.DW12.m_noSlices = 1; |
| m_curbeData.DW13.m_instantRateThreshold0ForP = 30; |
| m_curbeData.DW13.m_instantRateThreshold1ForP = 50; |
| m_curbeData.DW13.m_instantRateThreshold2ForP = 70; |
| m_curbeData.DW13.m_instantRateThreshold3ForP = 120; |
| m_curbeData.DW14.m_instantRateThreshold0ForB = 25; |
| m_curbeData.DW14.m_instantRateThreshold1ForB = 50; |
| m_curbeData.DW14.m_instantRateThreshold2ForB = 70; |
| m_curbeData.DW14.m_instantRateThreshold3ForB = 120; |
| m_curbeData.DW15.m_instantRateThreshold0ForI = 30; |
| m_curbeData.DW15.m_instantRateThreshold1ForI = 50; |
| m_curbeData.DW15.m_instantRateThreshold2ForI = 90; |
| m_curbeData.DW15.m_instantRateThreshold3ForI = 115; |
| m_curbeData.DW16.m_deviationThreshold0ForPandB = MOS_BITFIELD_VALUE((uint32_t)-45, 8); |
| m_curbeData.DW16.m_deviationThreshold1ForPandB = MOS_BITFIELD_VALUE((uint32_t)-33, 8); |
| m_curbeData.DW16.m_deviationThreshold2ForPandB = MOS_BITFIELD_VALUE((uint32_t)-23, 8); |
| m_curbeData.DW16.m_deviationThreshold3ForPandB = MOS_BITFIELD_VALUE((uint32_t)-15, 8); |
| m_curbeData.DW17.m_deviationThreshold4ForPandB = 15; |
| m_curbeData.DW17.m_deviationThreshold5ForPandB = 23; |
| m_curbeData.DW17.m_deviationThreshold6ForPandB = 35; |
| m_curbeData.DW17.m_deviationThreshold7ForPandB = 45; |
| m_curbeData.DW18.m_deviationThreshold0ForVBR = MOS_BITFIELD_VALUE((uint32_t)-45, 8); |
| m_curbeData.DW18.m_deviationThreshold1ForVBR = MOS_BITFIELD_VALUE((uint32_t)-35, 8); |
| m_curbeData.DW18.m_deviationThreshold2ForVBR = MOS_BITFIELD_VALUE((uint32_t)-25, 8); |
| m_curbeData.DW18.m_deviationThreshold3ForVBR = MOS_BITFIELD_VALUE((uint32_t)-15, 8); |
| m_curbeData.DW19.m_deviationThreshold4ForVBR = 40; |
| m_curbeData.DW19.m_deviationThreshold5ForVBR = 50; |
| m_curbeData.DW19.m_deviationThreshold6ForVBR = 75; |
| m_curbeData.DW19.m_deviationThreshold7ForVBR = 90; |
| m_curbeData.DW20.m_deviationThreshold0ForI = MOS_BITFIELD_VALUE((uint32_t)-40, 8); |
| m_curbeData.DW20.m_deviationThreshold1ForI = MOS_BITFIELD_VALUE((uint32_t)-30, 8); |
| m_curbeData.DW20.m_deviationThreshold2ForI = MOS_BITFIELD_VALUE((uint32_t)-17, 8); |
| m_curbeData.DW20.m_deviationThreshold3ForI = MOS_BITFIELD_VALUE((uint32_t)-10, 8); |
| m_curbeData.DW21.m_deviationThreshold4ForI = 10; |
| m_curbeData.DW21.m_deviationThreshold5ForI = 20; |
| m_curbeData.DW21.m_deviationThreshold6ForI = 33; |
| m_curbeData.DW21.m_deviationThreshold7ForI = 45; |
| m_curbeData.DW25.m_value = 1; |
| } |
| |
| BrcUpdateCurbe::BrcUpdateCurbe() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| MOS_ZeroMemory(&m_curbeData, m_byteSize); |
| |
| m_curbeData.DW3.m_startGAdjFrame0 = 10; |
| m_curbeData.DW3.m_startGAdjFrame1 = 50; |
| m_curbeData.DW4.m_startGAdjFrame2 = 100; |
| m_curbeData.DW4.m_startGAdjFrame3 = 150; |
| m_curbeData.DW7.m_picHeaderDataBufferSize = 0; |
| m_curbeData.DW8.m_startGlobalAdjustMult0 = 1; |
| m_curbeData.DW8.m_startGlobalAdjustMult1 = 1; |
| m_curbeData.DW8.m_startGlobalAdjustMult2 = 3; |
| m_curbeData.DW8.m_startGlobalAdjustMult3 = 2; |
| m_curbeData.DW9.m_startGlobalAdjustMult4 = 1; |
| m_curbeData.DW9.m_startGlobalAdjustDiv0 = 40; |
| m_curbeData.DW9.m_startGlobalAdjustDiv1 = 5; |
| m_curbeData.DW9.m_startGlobalAdjustDiv2 = 5; |
| m_curbeData.DW10.m_startGlobalAdjustDiv3 = 3; |
| m_curbeData.DW10.m_startGlobalAdjustDiv4 = 1; |
| m_curbeData.DW10.m_qpThreshold0 = 7; |
| m_curbeData.DW10.m_qpThreshold1 = 18; |
| m_curbeData.DW11.m_qpThreshold2 = 25; |
| m_curbeData.DW11.m_qpThreshold3 = 37; |
| m_curbeData.DW11.m_gRateRatioThreshold0 = 40; |
| m_curbeData.DW11.m_gRateRatioThreshold1 = 75; |
| m_curbeData.DW12.m_gRateRatioThreshold2 = 97; |
| m_curbeData.DW12.m_gRateRatioThreshold3 = 103; |
| m_curbeData.DW12.m_gRateRatioThreshold4 = 125; |
| m_curbeData.DW12.m_gRateRatioThreshold5 = 160; |
| m_curbeData.DW13.m_gRateRatioThresholdQP0 = MOS_BITFIELD_VALUE((uint32_t)-3, 8); |
| m_curbeData.DW13.m_gRateRatioThresholdQP1 = MOS_BITFIELD_VALUE((uint32_t)-2, 8); |
| m_curbeData.DW13.m_gRateRatioThresholdQP2 = MOS_BITFIELD_VALUE((uint32_t)-1, 8); |
| m_curbeData.DW13.m_gRateRatioThresholdQP3 = 0; |
| m_curbeData.DW14.m_gRateRatioThresholdQP4 = 1; |
| m_curbeData.DW14.m_gRateRatioThresholdQP5 = 2; |
| m_curbeData.DW14.m_gRateRatioThresholdQP6 = 3; |
| m_curbeData.DW14.m_forceToSkip = 1; |
| m_curbeData.DW15.m_value = 0; |
| m_curbeData.DW16[0].m_value = 0x06040200; |
| m_curbeData.DW16[1].m_value = 0x0e0c0a08; |
| m_curbeData.DW16[2].m_value = 0x16141210; |
| m_curbeData.DW16[3].m_value = 0x1e1c1a18; |
| m_curbeData.DW16[4].m_value = 0x26242220; |
| m_curbeData.DW16[5].m_value = 0x2e2c2a28; |
| m_curbeData.DW16[6].m_value = 0x36343230; |
| m_curbeData.DW16[7].m_value = 0x3e3c3a38; |
| m_curbeData.DW16[8].m_value = 0x03020100; |
| m_curbeData.DW16[9].m_value = 0x07060504; |
| m_curbeData.DW16[10].m_value = 0x0e0c0a08; |
| m_curbeData.DW16[11].m_value = 0x16141210; |
| m_curbeData.DW16[12].m_value = 0x24201c18; |
| m_curbeData.DW16[13].m_value = 0x34302c28; |
| m_curbeData.DW16[14].m_value = 0x50484038; |
| m_curbeData.DW16[15].m_value = 0x70686058; |
| |
| for (uint8_t idx = 0; idx < 10 ; idx++) |
| { |
| m_curbeData.DW32[idx].m_bindingTableIndex = idx; |
| } |
| } |
| |
| const uint8_t CodechalEncodeMpeg2::m_qpAdjustmentDistThresholdMaxFrameThresholdI[] = { |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x01, 0x01, 0x02, 0x03, 0x04, |
| 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02, |
| 0xff, 0x00, 0x00, 0x00, 0x01, 0xfe, 0xfe, 0xff, 0x00, 0x00, |
| 0xfd, 0xfd, 0xff, 0xff, 0x00, 0xfc, 0xfd, 0xfe, 0xff, 0xff, |
| 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00, 0x04, 0x1e, 0x3c, 0x50, |
| 0x78, 0x8c, 0xc8, 0xff, 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x00, |
| 0x00, 0x00, 0x00, 0x00}; |
| |
| const uint8_t CodechalEncodeMpeg2::m_qpAdjustmentDistThresholdMaxFrameThresholdP[] = { |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x01, 0x01, 0x02, 0x03, 0x04, |
| 0x00, 0x01, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02, |
| 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, |
| 0xfe, 0xff, 0xff, 0xff, 0x00, 0xfc, 0xfe, 0xff, 0xff, 0x00, |
| 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0x00, 0x04, 0x1e, 0x3c, 0x50, |
| 0x78, 0x8c, 0xc8, 0xff, 0x04, 0x05, 0x06, 0x06, 0x07, 0x00, |
| 0x00, 0x00, 0x00, 0x00 }; |
| |
| const uint8_t CodechalEncodeMpeg2::m_qpAdjustmentDistThresholdMaxFrameThresholdB[] = { |
| 0x01, 0x01, 0x02, 0x03, 0x04, 0x01, 0x01, 0x01, 0x02, 0x03, |
| 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, |
| 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, |
| 0xfe, 0xff, 0xff, 0xff, 0x00, 0xfd, 0xfe, 0xff, 0xff, 0x01, |
| 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0x00, 0x02, 0x14, 0x28, 0x46, |
| 0x82, 0xa0, 0xc8, 0xff, 0x04, 0x05, 0x06, 0x06, 0x07, 0x00, |
| 0x00, 0x00, 0x00, 0x00 }; |
| |
| const uint8_t CodechalEncodeMpeg2::m_distQpAdjustmentI[] = { |
| 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x00, |
| 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0xff, 0x00, |
| 0x00, 0x00, 0x01, 0x02, 0x02, 0x04, 0x05, 0xff, 0xff, 0x00, |
| 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0xfd, 0xfe, 0xff, 0x00, |
| 0x00, 0x00, 0x01, 0x02, 0x04, 0xfe, 0xfe, 0xff, 0xff, 0x00, |
| 0x00, 0x00, 0x01, 0x03, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0x00, |
| 0x00, 0x00, 0x02, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xff, |
| 0x00, 0x01, 0xfb, 0xfc, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| |
| const uint8_t CodechalEncodeMpeg2::m_distQpAdjustmentP[] = { |
| 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0x00, |
| 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0xff, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0xff, 0xff, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0xfe, 0xff, 0xff, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x03, 0xfe, 0xfe, 0xff, 0xff, 0x00, |
| 0x00, 0x00, 0x01, 0x02, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0x00, |
| 0x00, 0x00, 0x02, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xff, 0xff, |
| 0x00, 0x01, 0xfb, 0xfc, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| |
| const uint8_t CodechalEncodeMpeg2::m_distQpAdjustmentB[] = { |
| 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x00, |
| 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x00, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0xff, 0x00, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0xfe, 0xff, 0x00, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0x02, 0xfe, 0xfe, 0xff, 0x00, 0x00, |
| 0x00, 0x00, 0x01, 0x01, 0xfd, 0xfe, 0xff, 0xff, 0x00, 0x00, |
| 0x00, 0x00, 0x01, 0xfc, 0xfd, 0xfd, 0xfe, 0xff, 0xff, 0x00, |
| 0x00, 0x00, 0xfb, 0xfc, 0xfd, 0xfe, 0xfe, 0xff, 0xff, 0xff, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
| |
| const uint8_t CodechalEncodeMpeg2::m_targetUsageToKernelMode[] = { |
| encodeNormalMode, encodeNormalMode, |
| encodeNormalMode, encodeNormalMode, |
| encodeNormalMode, encodeNormalMode, |
| encodeNormalMode, encodeNormalMode }; |
| |
| const uint32_t CodechalEncodeMpeg2::m_vmeLutXyP[] = { 0x34262410, 0x46454436 }; |
| |
| const uint32_t CodechalEncodeMpeg2::m_vmeLutXyB[] = { 0x44363410, 0x56555446 }; |
| |
| const uint32_t CodechalEncodeMpeg2::m_vmeSPathP0[] = { |
| 0x1F11F10F, 0x2E22E2FE, 0x20E220DF, 0x2EDD06FC, 0x11D33FF1, 0xEB1FF33D, 0x02F1F1F1, 0x1F201111, |
| 0xF1EFFF0C, 0xF01104F1, 0x10FF0A50, 0x000FF1C0, 0x00000000, 0x00000000, 0x00000000, 0x00000000 |
| }; |
| |
| const uint32_t CodechalEncodeMpeg2::m_vmeSPathP1[] = { |
| 0x1F11F10F, 0x2E22E2FE, 0x20E220DF, 0xF1FB06FC, 0x0000D33F, 0x00000000, 0x00000000, 0x00000000, |
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 |
| }; |
| |
| const uint32_t CodechalEncodeMpeg2::m_vmeSPathB0[] = { |
| 0x120FF10F, 0x20E20F1F, 0x201EE2FD, 0x000D02D1, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 |
| }; |
| |
| const uint32_t CodechalEncodeMpeg2::m_vmeSPathB1[] = { |
| 0x120FF10F, 0x20E20F1F, 0x0000E2FD, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, |
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 |
| }; |
| |
| MOS_STATUS CodechalEncodeMpeg2::InitMmcState() |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| #ifdef _MMC_SUPPORTED |
| m_mmcState = MOS_New(CodechalMmcEncodeMpeg2, m_hwInterface, this); |
| CODECHAL_ENCODE_CHK_NULL_RETURN(m_mmcState); |
| #endif |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| CodechalEncodeMpeg2::CodechalEncodeMpeg2( |
| CodechalHwInterface* hwInterface, |
| CodechalDebugInterface* debugInterface, |
| PCODECHAL_STANDARD_INFO standardInfo) : |
| CodechalEncoderState(hwInterface, debugInterface, standardInfo) |
| { |
| CODECHAL_ENCODE_FUNCTION_ENTER; |
| |
| CODECHAL_ENCODE_ASSERT(hwInterface); |
| m_hwInterface = hwInterface; |
| CODECHAL_ENCODE_ASSERT(m_hwInterface->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 (eStatus != MOS_STATUS_SUCCESS) |
| { |
| CODECHAL_ENCODE_ASSERTMESSAGE("Failed to allocate PAK resources."); |
| return eStatus; |
| } |
| |
| 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; |
| |
| 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; |
| |
| if (!slcDataPrev || !slcParamsPrev) |
| { |
| eStatus = MOS_STATUS_INVALID_PARAMETER; |
| CODECHAL_ENCODE_ASSERTMESSAGE("Invalid slice pointer."); |
| return eStatus; |
| } |
| |
| // 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));) |
| |
| 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<uint32_t>(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<uint32_t>(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); |
| } |
| } |
| } |