/* * Copyright (c) 2011-2020, 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_decode_vc1.cpp //! \brief Implements the decode interface extension for VC1. //! \details Implements all functions required by CodecHal for VC1 decoding. //! #include "codechal_decoder.h" #include "codechal_decode_vc1.h" #include "codechal_secure_decode_interface.h" #include "codechal_mmc_decode_vc1.h" #include "hal_oca_interface.h" #if USE_CODECHAL_DEBUG_TOOL #include #include #include "codechal_debug.h" #endif #define CODECHAL_DECODE_VC1_EOS ((uint32_t)(-1)) // picture layer bits #define CODECHAL_DECODE_VC1_BITS_INTERPFRM 1 #define CODECHAL_DECODE_VC1_BITS_FRMCNT 2 #define CODECHAL_DECODE_VC1_BITS_RANGEREDFRM 1 #define CODECHAL_DECODE_VC1_BITS_FPTYPE 3 #define CODECHAL_DECODE_VC1_BITS_BF 7 #define CODECHAL_DECODE_VC1_BITS_PQINDEX 5 #define CODECHAL_DECODE_VC1_BITS_HALFQP 1 #define CODECHAL_DECODE_VC1_BITS_PQUANTIZER 1 #define CODECHAL_DECODE_VC1_BITS_RESPIC 2 #define CODECHAL_DECODE_VC1_BITS_INTERLCF 1 #define CODECHAL_DECODE_VC1_BITS_TRANSACFRM_1 1 #define CODECHAL_DECODE_VC1_BITS_TRANSACFRM_2 1 #define CODECHAL_DECODE_VC1_BITS_TRANSACFRM2_1 1 #define CODECHAL_DECODE_VC1_BITS_TRANSACFRM2_2 1 #define CODECHAL_DECODE_VC1_BITS_TRANSDCTAB 1 #define CODECHAL_DECODE_VC1_BITS_FRSKIP 1 #define CODECHAL_DECODE_VC1_BITS_TFCNTR 8 #define CODECHAL_DECODE_VC1_BITS_FCM_1 1 #define CODECHAL_DECODE_VC1_BITS_FCM_2 1 #define CODECHAL_DECODE_VC1_BITS_TFF 1 #define CODECHAL_DECODE_VC1_BITS_RFF 1 #define CODECHAL_DECODE_VC1_BITS_REPSEQHDR 1 #define CODECHAL_DECODE_VC1_BITS_UVSAMP 1 #define CODECHAL_DECODE_VC1_BITS_POSTPROC 2 #define CODECHAL_DECODE_VC1_BITS_DQUANTFRM 1 #define CODECHAL_DECODE_VC1_BITS_DQPROFILE 2 #define CODECHAL_DECODE_VC1_BITS_DQSBEDGE 2 #define CODECHAL_DECODE_VC1_BITS_DQDBEDGE 2 #define CODECHAL_DECODE_VC1_BITS_DQBILEVEL 1 #define CODECHAL_DECODE_VC1_BITS_PQDIFF 3 #define CODECHAL_DECODE_VC1_BITS_ABSPQ 5 #define CODECHAL_DECODE_VC1_BITS_MVMODEBIT 1 #define CODECHAL_DECODE_VC1_BITS_LUMSCALE 6 #define CODECHAL_DECODE_VC1_BITS_LUMSHIFT 6 #define CODECHAL_DECODE_VC1_BITS_MVTAB 2 #define CODECHAL_DECODE_VC1_BITS_CBPTAB 2 #define CODECHAL_DECODE_VC1_BITS_TTMBF 1 #define CODECHAL_DECODE_VC1_BITS_TTFRM 2 #define CODECHAL_DECODE_VC1_BITS_ABSMQ 5 #define CODECHAL_DECODE_VC1_BITS_RPTFRM 2 #define CODECHAL_DECODE_VC1_BITS_RNDCTRL 1 #define CODECHAL_DECODE_VC1_BITS_PS_PRESENT 1 #define CODECHAL_DECODE_VC1_BITS_PS_HOFFSET 18 #define CODECHAL_DECODE_VC1_BITS_PS_VOFFSET 18 #define CODECHAL_DECODE_VC1_BITS_PS_WIDTH 14 #define CODECHAL_DECODE_VC1_BITS_PS_HEIGHT 14 #define CODECHAL_DECODE_VC1_BITS_REFDIST 2 #define CODECHAL_DECODE_VC1_BITS_REFFIELD 1 #define CODECHAL_DECODE_VC1_BITS_NUMREF 1 #define CODECHAL_DECODE_VC1_BITS_MBMODETAB 3 #define CODECHAL_DECODE_VC1_BITS_CBPTAB_INTERLACE 3 #define CODECHAL_DECODE_VC1_BITS_4MVBPTAB 2 #define CODECHAL_DECODE_VC1_BITS_2MVBPTAB 2 #define CODECHAL_DECODE_VC1_BITS_4MVSWITCH 1 #define CODECHAL_DECODE_VC1_BITS_INTCOMP 1 // bitplane #define CODECHAL_DECODE_VC1_BITS_BITPLANE_INVERT 1 #define CODECHAL_DECODE_VC1_BITS_BITPLANE_ROWSKIP 1 #define CODECHAL_DECODE_VC1_BITS_BITPLANE_COLSKIP 1 // slice layer bits #define CODECHAL_DECODE_VC1_BITS_SC_SUFFIX 8 #define CODECHAL_DECODE_VC1_BITS_SLICE_ADDR 9 #define CODECHAL_DECODE_VC1_BITS_PIC_HEADER_FLAG 1 #define CODECHAL_DECODE_VC1_BITS_SLICE_HEADER ((CODECHAL_DECODE_VC1_BITS_SC_SUFFIX) + (CODECHAL_DECODE_VC1_BITS_SLICE_ADDR) + (CODECHAL_DECODE_VC1_BITS_PIC_HEADER_FLAG)) #define CODECHAL_DECODE_VC1_MV_OFFEST_SIZE 3 MOS_STATUS CodechalDecodeVc1::GetBits(uint32_t bitsRead, uint32_t &value) { value = GetBits(bitsRead); if (CODECHAL_DECODE_VC1_EOS == value) { return MOS_STATUS_UNKNOWN; } return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVc1::GetVLC(const uint32_t* table, uint32_t &value) { value = GetVLC(table); if (CODECHAL_DECODE_VC1_EOS == value) { return MOS_STATUS_UNKNOWN; } return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVc1::SkipWords(uint32_t dwordNumber, uint32_t &value) { for (uint32_t i = 0; i < dwordNumber; i++) { value = SkipBits(16); if (CODECHAL_DECODE_VC1_EOS == value) { return MOS_STATUS_UNKNOWN; } } return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVc1::SkipBits(uint32_t bits, uint32_t &value) { if ((bits) > 0) { value = SkipBits(bits); if (CODECHAL_DECODE_VC1_EOS == value) { return MOS_STATUS_UNKNOWN; } } return MOS_STATUS_SUCCESS; } typedef union _CODECHAL_DECODE_VC1_BITSTREAM_BUFFER_VALUE { uint32_t u32Value; uint8_t u8Value[sizeof(uint32_t)]; } CODECHAL_DECODE_VC1_BITSTREAM_VALUE, *PCODECHAL_DECODE_VC1_BITSTREAM_VALUE; typedef enum _CODECHAL_DECODE_VC1_MVMODE { CODECHAL_VC1_MVMODE_1MV_HALFPEL_BILINEAR, CODECHAL_VC1_MVMODE_1MV_HALFPEL, CODECHAL_VC1_MVMODE_1MV, CODECHAL_VC1_MVMODE_MIXEDMV, CODECHAL_VC1_MVMODE_IC // Intensity Compensation } CODECHAL_DECODE_VC1_MVMODE; typedef enum _CODECHAL_DECODE_VC1_BITPLANE_CODING_MODE { CODECHAL_VC1_BITPLANE_RAW, CODECHAL_VC1_BITPLANE_NORMAL2, CODECHAL_VC1_BITPLANE_DIFF2, CODECHAL_VC1_BITPLANE_NORMAL6, CODECHAL_VC1_BITPLANE_DIFF6, CODECHAL_VC1_BITPLANE_ROWSKIP, CODECHAL_VC1_BITPLANE_COLSKIP } CODECHAL_DECODE_VC1_BITPLANE_CODING_MODE; static const uint32_t CODECHAL_DECODE_VC1_VldBitplaneModeTable[] = { 4, /* max bits */ 0, /* 1-bit codes */ 2, /* 2-bit codes */ 2, CODECHAL_VC1_BITPLANE_NORMAL2, 3, CODECHAL_VC1_BITPLANE_NORMAL6, 3, /* 3-bit codes */ 1, CODECHAL_VC1_BITPLANE_DIFF2, 2, CODECHAL_VC1_BITPLANE_ROWSKIP, 3, CODECHAL_VC1_BITPLANE_COLSKIP, 2, /* 4-bit codes */ 0, CODECHAL_VC1_BITPLANE_RAW, 1, CODECHAL_VC1_BITPLANE_DIFF6, (uint32_t)-1 }; static const uint32_t CODECHAL_DECODE_VC1_VldCode3x2Or2x3TilesTable[] = { 13, /* max bits */ 1, /* 1-bit codes */ 1, 0, 0, /* 2-bit codes */ 0, /* 3-bit codes */ 6, /* 4-bit codes */ 2, 1, 3, 2, 4, 4, 5, 8, 6, 16, 7, 32, 0, /* 5-bit codes */ 1, /* 6-bit codes */ (3 << 1) | 1, 63, 0, /* 7-bit codes */ 15, /* 8-bit codes */ 0, 3, 1, 5, 2, 6, 3, 9, 4, 10, 5, 12, 6, 17, 7, 18, 8, 20, 9, 24, 10, 33, 11, 34, 12, 36, 13, 40, 14, 48, 6, /* 9-bit codes */ (3 << 4) | 7, 31, (3 << 4) | 6, 47, (3 << 4) | 5, 55, (3 << 4) | 4, 59, (3 << 4) | 3, 61, (3 << 4) | 2, 62, 20, /* 10-bit codes */ (1 << 6) | 11, 11, (1 << 6) | 7, 7, (1 << 6) | 13, 13, (1 << 6) | 14, 14, (1 << 6) | 19, 19, (1 << 6) | 21, 21, (1 << 6) | 22, 22, (1 << 6) | 25, 25, (1 << 6) | 26, 26, (1 << 6) | 28, 28, (1 << 6) | 3, 35, (1 << 6) | 5, 37, (1 << 6) | 6, 38, (1 << 6) | 9, 41, (1 << 6) | 10, 42, (1 << 6) | 12, 44, (1 << 6) | 17, 49, (1 << 6) | 18, 50, (1 << 6) | 20, 52, (1 << 6) | 24, 56, 0, /* 11-bit codes */ 0, /* 12-bit codes */ 15, /* 13-bit codes */ (3 << 8) | 14, 15, (3 << 8) | 13, 23, (3 << 8) | 12, 27, (3 << 8) | 11, 29, (3 << 8) | 10, 30, (3 << 8) | 9, 39, (3 << 8) | 8, 43, (3 << 8) | 7, 45, (3 << 8) | 6, 46, (3 << 8) | 5, 51, (3 << 8) | 4, 53, (3 << 8) | 3, 54, (3 << 8) | 2, 57, (3 << 8) | 1, 58, (3 << 8) | 0, 60, (uint32_t)-1 }; static const uint32_t CODECHAL_DECODE_VC1_VldPictureTypeTable[] = { 4, /* max bits */ 1, /* 1-bit codes */ 0, vc1PFrame, 1, /* 2-bit codes */ 2, vc1BFrame, 1, /* 3-bit codes */ 6, vc1IFrame, 2, /* 4-bit codes */ 14, vc1BIFrame, 15, vc1SkippedFrame, (uint32_t)-1 }; static const uint32_t CODECHAL_DECODE_VC1_VldBFractionTable[] = { 7, /* max bits */ 0, /* 1-bit codes */ 0, /* 2-bit codes */ 7, /* 3-bit codes */ 0x00, 0, 0x01, 1, 0x02, 2, 0x03, 3, 0x04, 4, 0x05, 5, 0x06, 6, 0, /* 4-bit codes */ 0, /* 5-bit codes */ 0, /* 6-bit codes */ 14, /* 7-bit codes */ 0x70, 7, 0x71, 8, 0x72, 9, 0x73, 10, 0x74, 11, 0x75, 12, 0x76, 13, 0x77, 14, 0x78, 15, 0x79, 16, 0x7A, 17, 0x7B, 18, 0x7C, 19, 0x7D, 20, (uint32_t)-1 }; static const uint32_t CODECHAL_DECODE_VC1_VldRefDistTable[] = { 14, /* max bits */ 1, /* 1-bit codes */ 0, 3, 1, /* 2-bit codes */ 2, 4, 1, /* 3-bit codes */ 6, 5, 1, /* 4-bit codes */ 14, 6, 1, /* 5-bit codes */ 30, 7, 1, /* 6-bit codes */ 62, 8, 1, /* 7-bit codes */ 126, 9, 1, /* 8-bit codes */ 254, 10, 1, /* 9-bit codes */ 510, 11, 1, /* 10-bit codes */ 1022, 12, 1, /* 11-bit codes */ 2046, 13, 1, /* 12-bit codes */ 4094, 14, 1, /* 13-bit codes */ 8190, 15, 1, /* 14-bit codes */ 16382, 16, (uint32_t)-1 }; // lookup tables for MVMODE static const uint32_t CODECHAL_DECODE_VC1_LowRateMvModeTable[] = { CODECHAL_VC1_MVMODE_1MV_HALFPEL_BILINEAR, CODECHAL_VC1_MVMODE_1MV, CODECHAL_VC1_MVMODE_1MV_HALFPEL, CODECHAL_VC1_MVMODE_MIXEDMV, CODECHAL_VC1_MVMODE_IC }; static const uint32_t CODECHAL_DECODE_VC1_HighRateMvModeTable[] = { CODECHAL_VC1_MVMODE_1MV, CODECHAL_VC1_MVMODE_MIXEDMV, CODECHAL_VC1_MVMODE_1MV_HALFPEL, CODECHAL_VC1_MVMODE_1MV_HALFPEL_BILINEAR, CODECHAL_VC1_MVMODE_IC }; // lock up table for luma polarity (Interlaced picture) static const CODECHAL_DECODE_VC1_I_LUMA_BLOCKS CODECHAL_DECODE_VC1_LumaBlocks_I[16] = { { 4,{ 0 }, 0, 0, 0 },{ 3,{ 0 }, 2, 4, 6 },{ 3,{ 0 }, 0, 4, 6 },{ 2,{ 4 }, 6, 0, 2 },{ 3,{ 0 }, 0, 2, 6 },{ 2,{ 2 }, 6, 0, 4 },{ 2,{ 0 }, 6, 2, 4 },{ 3,{ 1 }, 0, 2, 4 }, { 3,{ 0 }, 0, 2, 4 },{ 2,{ 2 }, 4, 0, 6 },{ 2,{ 0 }, 4, 2, 6 },{ 3,{ 1 }, 0, 2, 6 },{ 2,{ 0 }, 2, 4, 6 },{ 3,{ 1 }, 0, 4, 6 },{ 3,{ 1 }, 2, 4, 6 },{ 4,{ 1 }, 0, 0, 0 } }; // lock up table for luma inter-coded blocks (Progressive picture) static const CODECHAL_DECODE_VC1_P_LUMA_BLOCKS CODECHAL_DECODE_VC1_LumaBlocks_P[16] = { { 4, 0, 0, 0 },{ 3, 0, 2, 4 },{ 3, 0, 2, 6 },{ 2, 0, 2, 0 },{ 3, 0, 4, 6 },{ 2, 0, 4, 0 },{ 2, 0, 6, 0 },{ 0, 0, 0, 0 }, { 3, 2, 4, 6 },{ 2, 2, 4, 0 },{ 2, 2, 6, 0 },{ 0, 0, 0, 0 },{ 2, 4, 6, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 },{ 0, 0, 0, 0 } }; static const int16_t CODECHAL_DECODE_VC1_MV_OFFEST[CODECHAL_DECODE_VC1_MV_OFFEST_SIZE][2] = { { 0, 2 },{ -2, 0 },{ 0, 0 } }; static const uint8_t CODECHAL_DECODE_VC1_RndTb[4] = { 0, 0, 0, 1 }; const CODECHAL_DECODE_VC1_OLP_STATIC_DATA g_cInit_CODECHAL_DECODE_VC1_OLP_STATIC_DATA = { // uint32_t 0 { { 0 } // Reserved }, // uint32_t 1 { { 16, // BlockWidth in Byte 16 // BlockHeight in Byte } }, // uint32_t 2 { { 0, // Profile 0, // RangeExpansionFlag 0, // UpsamplingFlag 0, // InterlaceFieldFlag 0, // RangeMapUV 0, // RangeMapUVFlag 0, // RangeMapY 0, // RangeMapYFlag 0 // ComponentFlag } }, // uint32_t 3 { { 0 } // ComponentFlag }, // uint32_t 4 { { 0 } // SourceDataBindingIndex (default: CODECHAL_DECODE_VC1_OLP_SRC_Y) }, // uint32_t 5 { { 3 } // DestDataBindingIndex (default: CODECHAL_DECODE_VC1_OLP_DST_Y) }, // uint32_t 6 { { 0 } // Reserved }, // uint32_t 7 { { 0 } // Reserved } }; //========================================================= int16_t CodechalDecodeVc1::PackMotionVectorsMedian3(int16_t mv1, int16_t mv2, int16_t mv3) { if (mv1 > mv2) { if (mv2 > mv3) return mv2; if (mv1 > mv3) return mv3; return mv1; } if (mv1 > mv3) return mv1; if (mv2 > mv3) return mv3; return mv2; } int16_t CodechalDecodeVc1::PackMotionVectorsMedian4(int16_t mv1, int16_t mv2, int16_t mv3, int16_t mv4) { int16_t max = mv1, min = mv1; if (mv2 > max) { max = mv2; } else if (mv2 < min) { min = mv2; } if (mv3 > max) { max = mv3; } else if (mv3 < min) { min = mv3; } if (mv4 > max) { max = mv4; } else if (mv4 < min) { min = mv4; } return (mv1 + mv2 + mv3 + mv4 - max - min) / 2; } void CodechalDecodeVc1::PackMotionVectorsChroma4MvP(uint16_t intraFlags, int16_t *lmv, int16_t *cmv) { int16_t mvX = 0, mvY = 0; if (CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8NumIntercodedBlocks == 4) { mvX = PackMotionVectorsMedian4(lmv[0], lmv[2], lmv[4], lmv[6]); mvY = PackMotionVectorsMedian4(lmv[1], lmv[3], lmv[5], lmv[7]); } else if (CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8NumIntercodedBlocks == 3) { mvX = PackMotionVectorsMedian3(lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex1], lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex2], lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex3]); mvY = PackMotionVectorsMedian3(lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex1 + 1], lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex2 + 1], lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex3 + 1]); } else if (CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8NumIntercodedBlocks == 2) { mvX = (lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex1] + lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex2]) / 2; mvY = (lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex1 + 1] + lmv[CODECHAL_DECODE_VC1_LumaBlocks_P[intraFlags].u8MvIndex2 + 1]) / 2; } cmv[0] = CODECHAL_DECODE_VC1_CHROMA_MV(mvX); cmv[1] = CODECHAL_DECODE_VC1_CHROMA_MV(mvY); } uint8_t CodechalDecodeVc1::PackMotionVectorsChroma4MvI( uint16_t fieldSelect, uint16_t currentField, bool fastUVMotionCompensation, int16_t *lmv, int16_t *cmv) { int16_t mvX = 0, mvY = 0; uint8_t polarity; uint16_t offset, offsetIndex; uint8_t index1, index2, index3, index4; if ((currentField == PICTURE_FRAME) || (currentField == PICTURE_INTERLACED_FRAME)) { offsetIndex = 2; } else { offsetIndex = currentField - 1; } if (offsetIndex >= CODECHAL_DECODE_VC1_MV_OFFEST_SIZE) { CODECHAL_DECODE_ASSERTMESSAGE("ERROR: offsetIndex out of bounds (%d, max %d)", offsetIndex, CODECHAL_DECODE_VC1_MV_OFFEST_SIZE); return 0; } if (CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8NumSamePolarity == 4) { polarity = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8Polarity ? 1 : 0; offset = CODECHAL_DECODE_VC1_MV_OFFEST[offsetIndex][polarity]; // Unadjust Luma lmv[1] += offset; lmv[3] += offset; lmv[5] += offset; lmv[7] += offset; mvX = PackMotionVectorsMedian4(lmv[0], lmv[2], lmv[4], lmv[6]); mvY = PackMotionVectorsMedian4(lmv[1], lmv[3], lmv[5], lmv[7]); } else if (CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8NumSamePolarity == 3) { polarity = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8Polarity ? 1 : 0; index2 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex1; index3 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex2; index4 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex3; index1 = 12 - (index2 + index3 + index4); // Sum of indices is 12 // Unadjust Luma of current polarity offset = CODECHAL_DECODE_VC1_MV_OFFEST[offsetIndex][polarity]; lmv[index2 + 1] += offset; lmv[index3 + 1] += offset; lmv[index4 + 1] += offset; if (PICTURE_TOP_FIELD != currentField && PICTURE_BOTTOM_FIELD != currentField) { CODECHAL_DECODE_ASSERTMESSAGE("Invalid Parameters."); } else { // Unadjust Luma of opposite polarity offset = CODECHAL_DECODE_VC1_MV_OFFEST[currentField - 1][1 - polarity]; } lmv[index1 + 1] += offset; mvX = PackMotionVectorsMedian3(lmv[index2], lmv[index3], lmv[index4]); mvY = PackMotionVectorsMedian3(lmv[index2 + 1], lmv[index3 + 1], lmv[index4 + 1]); } else { if (currentField == PICTURE_TOP_FIELD) { index1 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex0; index2 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex1; index3 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex2; index4 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex3; polarity = 0; } else { index1 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex2; index2 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex3; index3 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex0; index4 = CODECHAL_DECODE_VC1_LumaBlocks_I[fieldSelect].u8MvIndex1; polarity = 1; } // Unadjust Luma of current polarity offset = CODECHAL_DECODE_VC1_MV_OFFEST[offsetIndex][polarity]; lmv[index1 + 1] += offset; lmv[index2 + 1] += offset; // Unadjust Luma of opposite polarity offset = CODECHAL_DECODE_VC1_MV_OFFEST[offsetIndex][1 - polarity]; lmv[index3 + 1] += offset; lmv[index4 + 1] += offset; mvX = (lmv[index1] + lmv[index2]) / 2; mvY = (lmv[index1 + 1] + lmv[index2 + 1]) / 2; offset = 0; } cmv[0] = CODECHAL_DECODE_VC1_CHROMA_MV(mvX); cmv[1] = CODECHAL_DECODE_VC1_CHROMA_MV(mvY); if (fastUVMotionCompensation) { cmv[0] = CODECHAL_DECODE_VC1_FAST_CHROMA_MV(cmv[0]); cmv[1] = CODECHAL_DECODE_VC1_FAST_CHROMA_MV(cmv[1]); } return polarity; } void CodechalDecodeVc1::PackMotionVectors( PMHW_VDBOX_VC1_MB_STATE vc1MbState, int16_t *mv, int16_t *packedLumaMvs, int16_t *packedChromaMv) { uint16_t selectFlags; PCODEC_VC1_MB_PARAMS mb = vc1MbState->pMb; uint8_t b4Mv = mb->mb_type.motion_4mv; uint8_t mfwd = mb->mb_type.motion_forward; uint8_t mbwd = mb->mb_type.motion_backward; uint8_t mtype = mb->mb_type.motion_type; vc1MbState->bMotionSwitch = 0; PCODEC_VC1_PIC_PARAMS vc1PicParams = vc1MbState->pVc1PicParams; bool isPPicture = m_mfxInterface->IsVc1PPicture( vc1PicParams->CurrPic, vc1PicParams->picture_fields.is_first_field, vc1PicParams->picture_fields.picture_type) ? true : false; if (packedLumaMvs == nullptr) { CODECHAL_DECODE_ASSERTMESSAGE("ERROR: packedLumaMvs is nullptr"); return; } if (packedChromaMv == nullptr) { CODECHAL_DECODE_ASSERTMESSAGE("ERROR: packedChromaMv is nullptr"); return; } packedLumaMvs[0] = packedLumaMvs[2] = packedLumaMvs[4] = packedLumaMvs[6] = 0; packedLumaMvs[1] = packedLumaMvs[3] = packedLumaMvs[5] = packedLumaMvs[7] = 0; packedChromaMv[0] = CODECHAL_DECODE_VC1_CHROMA_MV(packedLumaMvs[0]); packedChromaMv[1] = CODECHAL_DECODE_VC1_CHROMA_MV(packedLumaMvs[1]); if (b4Mv) { packedLumaMvs[0] = (int16_t)mv[CodechalDecodeRstFirstForwHorz]; packedLumaMvs[1] = (int16_t)mv[CodechalDecodeRstFirstForwVert]; packedLumaMvs[2] = (int16_t)mv[CodechalDecodeRstFirstBackHorz]; packedLumaMvs[3] = (int16_t)mv[CodechalDecodeRstFirstBackVert]; packedLumaMvs[4] = (int16_t)mv[CodechalDecodeRstSecndForwHorz]; packedLumaMvs[5] = (int16_t)mv[CodechalDecodeRstSecndForwVert]; packedLumaMvs[6] = (int16_t)mv[CodechalDecodeRstSecndBackHorz]; packedLumaMvs[7] = (int16_t)mv[CodechalDecodeRstSecndBackVert]; if (vc1MbState->PicFlags == PICTURE_FRAME) { selectFlags = mb->pattern_code.block_luma_intra; PackMotionVectorsChroma4MvP(selectFlags, packedLumaMvs, packedChromaMv); } else if (vc1MbState->PicFlags != PICTURE_INTERLACED_FRAME) { selectFlags = (mb->mb_type.value & 0xF000) >> 12; vc1MbState->bFieldPolarity = PackMotionVectorsChroma4MvI( selectFlags, vc1MbState->PicFlags, vc1PicParams->fast_uvmc_flag ? true : false, packedLumaMvs, packedChromaMv); } } else { // default settings for frame pictures, relevant Motion Vectors will be reset if needed packedLumaMvs[0] = packedLumaMvs[2] = packedLumaMvs[4] = packedLumaMvs[6] = (int16_t)mv[CodechalDecodeRstFirstForwHorz]; packedLumaMvs[1] = packedLumaMvs[3] = packedLumaMvs[5] = packedLumaMvs[7] = (int16_t)mv[CodechalDecodeRstFirstForwVert]; packedChromaMv[0] = CODECHAL_DECODE_VC1_CHROMA_MV(packedLumaMvs[0]); packedChromaMv[1] = CODECHAL_DECODE_VC1_CHROMA_MV(packedLumaMvs[1]); if (vc1MbState->PicFlags == PICTURE_FRAME) { if (mbwd && mfwd) { // Progressive, direct packedLumaMvs[2] = packedLumaMvs[6] = (int16_t)mv[CodechalDecodeRstSecndForwHorz]; packedLumaMvs[3] = packedLumaMvs[7] = (int16_t)mv[CodechalDecodeRstSecndForwVert]; } } else { if (vc1MbState->PicFlags == PICTURE_INTERLACED_FRAME) { packedLumaMvs[2] = packedLumaMvs[6] = (int16_t)mv[CodechalDecodeRstFirstBackHorz]; packedLumaMvs[3] = packedLumaMvs[7] = (int16_t)mv[CodechalDecodeRstFirstBackVert]; if (mtype == CodechalDecodeMcFrame) { if (isPPicture) { packedLumaMvs[2] = packedLumaMvs[6] = packedLumaMvs[0]; packedLumaMvs[3] = packedLumaMvs[7] = packedLumaMvs[1]; } } else if (mtype == CodechalDecodeMcField) { packedLumaMvs[4] = (int16_t)mv[CodechalDecodeRstSecndForwHorz]; packedLumaMvs[5] = (int16_t)mv[CodechalDecodeRstSecndForwVert]; packedLumaMvs[6] = (int16_t)mv[CodechalDecodeRstSecndBackHorz]; packedLumaMvs[7] = (int16_t)mv[CodechalDecodeRstSecndBackVert]; } } else // Interlaced field { uint8_t fieldPolarity2, offsetIndex; uint32_t i; int16_t offset; i = 0; fieldPolarity2 = 0; offsetIndex = vc1MbState->PicFlags - 1; if (offsetIndex >= CODECHAL_DECODE_VC1_MV_OFFEST_SIZE) { CODECHAL_DECODE_ASSERTMESSAGE("ERROR: offsetIndex out of bounds (%d, max %d)", offsetIndex, CODECHAL_DECODE_VC1_MV_OFFEST_SIZE); return; } if (mfwd) { vc1MbState->bFieldPolarity = mb->mb_type.mvert_field_sel_0; fieldPolarity2 = mb->mb_type.mvert_field_sel_1; i = 1; } if (mbwd) { vc1MbState->bFieldPolarity = mb->mb_type.mvert_field_sel_1; fieldPolarity2 = mb->mb_type.mvert_field_sel_0; i = 3; packedLumaMvs[2] = packedLumaMvs[6] = (int16_t)mv[CodechalDecodeRstFirstBackHorz]; packedLumaMvs[3] = packedLumaMvs[7] = (int16_t)mv[CodechalDecodeRstFirstBackVert]; } // Unadjust luma offset = CODECHAL_DECODE_VC1_MV_OFFEST[offsetIndex][vc1MbState->bFieldPolarity]; packedLumaMvs[i] += offset; // Unadjust Luma of opposite polarity offset = CODECHAL_DECODE_VC1_MV_OFFEST[offsetIndex][fieldPolarity2]; packedLumaMvs[4 - i] += offset; if (isPPicture) { packedLumaMvs[3] = packedLumaMvs[5] = packedLumaMvs[7] = packedLumaMvs[1]; if (mb->mb_type.mvert_field_sel_0) { mb->mb_type.mvert_field_sel_0 = 1; mb->mb_type.mvert_field_sel_1 = 1; mb->mb_type.mvert_field_sel_2 = 1; mb->mb_type.mvert_field_sel_3 = 1; } } else { packedLumaMvs[5] = packedLumaMvs[1]; packedLumaMvs[7] = packedLumaMvs[3]; } // Derive unadjusted chroma packedChromaMv[0] = CODECHAL_DECODE_VC1_CHROMA_MV(packedLumaMvs[i - 1]); packedChromaMv[1] = CODECHAL_DECODE_VC1_CHROMA_MV(packedLumaMvs[i]); } } } if ((vc1MbState->PicFlags == PICTURE_INTERLACED_FRAME) && (mtype == CodechalDecodeMcField)) { uint16_t mvFieldSel = (mb->mb_type.value & 0xF000) >> 12; uint16_t concealForSel2 = 0; uint16_t concealForSel3 = 0; if (!mb->mb_type.mvert_field_sel_2) { if (!(packedLumaMvs[4] || packedLumaMvs[5])) { concealForSel2 = 1; } packedLumaMvs[5] += 4; } if (!mb->mb_type.mvert_field_sel_3) { if (!(packedLumaMvs[6] || packedLumaMvs[7])) { concealForSel3 = 1; } packedLumaMvs[7] += 4; } if (!(mfwd && mbwd) && !b4Mv) { uint16_t topPredBit, botPredBit; uint16_t topPred, botPred; if (mfwd && !mbwd) { vc1MbState->bMotionSwitch = mb->mb_type.mvert_field_sel_1; topPredBit = 0; botPredBit = (vc1MbState->bMotionSwitch) ? 3 : 2; } else { vc1MbState->bMotionSwitch = mb->mb_type.mvert_field_sel_0; topPredBit = 1; botPredBit = (vc1MbState->bMotionSwitch) ? 2 : 3; } topPred = mvFieldSel & (1 << topPredBit); botPred = mvFieldSel & (1 << botPredBit); if (isPPicture) { packedLumaMvs[0] = packedLumaMvs[2] = packedLumaMvs[topPredBit * 2]; packedLumaMvs[1] = packedLumaMvs[3] = packedLumaMvs[(topPredBit * 2) + 1]; packedLumaMvs[4] = packedLumaMvs[6] = packedLumaMvs[botPredBit * 2]; packedLumaMvs[5] = packedLumaMvs[7] = packedLumaMvs[(botPredBit * 2) + 1]; mb->mb_type.value &= 0x0FFF; if (topPred) { mb->mb_type.mvert_field_sel_0 = 1; mb->mb_type.mvert_field_sel_1 = 1; } if (botPred) { mb->mb_type.mvert_field_sel_2 = 1; mb->mb_type.mvert_field_sel_3 = 1; } } else if (vc1MbState->bMotionSwitch) // && !P_TYPE { if (concealForSel2) { packedLumaMvs[4] = packedLumaMvs[6]; packedLumaMvs[5] = packedLumaMvs[7]; } if (concealForSel3) { packedLumaMvs[6] = packedLumaMvs[4]; packedLumaMvs[7] = packedLumaMvs[5]; } mb->mb_type.value &= 0x0FFF; if (topPred) { if (topPredBit == 1) { mb->mb_type.mvert_field_sel_1 = 1; } else // topPredBit == 0 { mb->mb_type.mvert_field_sel_0 = 1; } } if (botPred) { if (botPredBit == 3) { mb->mb_type.mvert_field_sel_2 = 1; } else // botPredBit == 2 { mb->mb_type.mvert_field_sel_3 = 1; } } } } } if (vc1PicParams->fast_uvmc_flag) { packedChromaMv[0] = CODECHAL_DECODE_VC1_FAST_CHROMA_MV(packedChromaMv[0]); packedChromaMv[1] = CODECHAL_DECODE_VC1_FAST_CHROMA_MV(packedChromaMv[1]); } } MOS_STATUS CodechalDecodeVc1::InitializeUnequalFieldSurface( uint8_t refListIdx, bool nullHwInUse) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODEC_PICTURE picture = m_vc1RefList[refListIdx]->RefPic; bool isBPicture = m_mfxInterface->IsVc1BPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type) ? true : false; if (m_vc1RefList[refListIdx]->bUnequalFieldSurfaceValid) { // Reset the Surface Valid flag for second field of B picture if (m_vc1PicParams->CurrPic.FrameIdx == refListIdx && isBPicture) { m_vc1RefList[refListIdx]->bUnequalFieldSurfaceValid = false; } // Unequal field surface may be re-used return eStatus; } uint32_t currUnequalFieldIdx, prevRefListIdx; if (m_vc1PicParams->CurrPic.FrameIdx == refListIdx && isBPicture) { currUnequalFieldIdx = m_unequalFieldSurfaceForBType; } else { currUnequalFieldIdx = m_currUnequalFieldSurface; m_currUnequalFieldSurface = (m_currUnequalFieldSurface + 1) % (CODECHAL_DECODE_VC1_UNEQUAL_FIELD_WA_SURFACES - 1); prevRefListIdx = m_unequalFieldRefListIdx[currUnequalFieldIdx]; if (prevRefListIdx < CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1 && m_vc1PicParams->CurrPic.FrameIdx != prevRefListIdx) { // Invalidate unequal field index for the old reference m_vc1RefList[prevRefListIdx]->bUnequalFieldSurfaceValid = false; } } // Set up new unequal field values m_vc1RefList[refListIdx]->bUnequalFieldSurfaceValid = true; m_vc1RefList[refListIdx]->dwUnequalFieldSurfaceIdx = currUnequalFieldIdx; m_unequalFieldRefListIdx[currUnequalFieldIdx] = refListIdx; if (m_vc1PicParams->CurrPic.FrameIdx != refListIdx) { MOS_SURFACE srcSurface; MOS_ZeroMemory(&srcSurface, sizeof(MOS_SURFACE)); srcSurface.Format = Format_NV12; srcSurface.OsResource = m_vc1RefList[refListIdx]->resRefPic; CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &srcSurface)); // Format the unequal field reference CODECHAL_DECODE_CHK_STATUS_RETURN(FormatUnequalFieldPicture( srcSurface, m_unequalFieldSurface[currUnequalFieldIdx], false, nullHwInUse)); } return eStatus; } /*---------------------------------------------------------------------------- | Name : CodechalDecodeVc1::FormatUnequalFieldPicture | Purpose : Formats the destination surface, in the pack case the UV surface | is moved to be adjacent to the UV surface such that NV12 | formatting is maintained when the surface is returned to SW, | in the unpack case the UV surface is moved to be 32-pixel rows | away from the Y surface so that during decoding HW will not | overwrite the UV surface | Arguments : dwSrcSurfaceHandle - surface handle for the source surface | dwDstSurfaceHandle - surface handle for the destination surface | bPack - boolean value determining whether or not the source | surface should be packed or unpacked | Returns : MOS_STATUS - for success or failure \---------------------------------------------------------------------------*/ MOS_STATUS CodechalDecodeVc1::FormatUnequalFieldPicture( MOS_SURFACE srcSurface, MOS_SURFACE dstSurface, bool pack, bool nullHwInUse) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; uint32_t uvblockWidth = 16; uint32_t uvblockHeight = 16; uint32_t uvblockSize = uvblockWidth * uvblockHeight; uint32_t frameHeight = MOS_ALIGN_CEIL(m_height, 16); uint32_t ysize = srcSurface.dwPitch * MOS_ALIGN_CEIL(frameHeight, MOS_YTILE_H_ALIGNMENT); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); // Send command buffer header at the beginning (OS dependent) CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, false)); uint32_t frameSize = MOS_ALIGN_CEIL((srcSurface.dwPitch * (frameHeight + frameHeight / 2)), MOS_YTILE_H_ALIGNMENT); // Copy Y data first if (m_hwInterface->m_noHuC) { CodechalDataCopyParams dataCopyParams; MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); dataCopyParams.srcResource = &srcSurface.OsResource; dataCopyParams.srcSize = ysize; dataCopyParams.srcOffset = 0; dataCopyParams.dstResource = &dstSurface.OsResource; dataCopyParams.dstSize = frameSize; dataCopyParams.dstOffset = 0; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(&dataCopyParams)); } else { // Stream object params CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( &cmdBuffer, // pCmdBuffer &srcSurface.OsResource, // presSrc &dstSurface.OsResource, // presDst ysize, // u32CopyLength 0, // u32CopyInputOffset 0)); // u32CopyOutputOffset } // Copy 1 MB row of UV uint32_t srcOffset, dstOffset; for (uint32_t x = 0; x < srcSurface.dwPitch; x += uvblockWidth) { if (pack) { srcOffset = LinearToYTiledAddress( x, frameHeight + MOS_YTILE_H_ALIGNMENT, srcSurface.dwPitch); dstOffset = LinearToYTiledAddress( x, frameHeight, dstSurface.dwPitch); } else { srcOffset = LinearToYTiledAddress( x, frameHeight, srcSurface.dwPitch); dstOffset = LinearToYTiledAddress( x, frameHeight + MOS_YTILE_H_ALIGNMENT, dstSurface.dwPitch); } if (m_hwInterface->m_noHuC) { CodechalDataCopyParams dataCopyParams; MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); dataCopyParams.srcResource = &srcSurface.OsResource; dataCopyParams.srcSize = uvblockSize; dataCopyParams.srcOffset = srcOffset; dataCopyParams.dstResource = &dstSurface.OsResource; dataCopyParams.dstSize = frameSize; dataCopyParams.dstOffset = dstOffset; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(&dataCopyParams)); } else { // Stream object params CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( &cmdBuffer, // pCmdBuffer &srcSurface.OsResource, // presSrc &dstSurface.OsResource, // presDst uvblockSize, // u32CopyLength srcOffset, // u32CopyInputOffset dstOffset)); // u32CopyOutputOffset } } uint32_t uvsize = srcSurface.dwPitch * MOS_ALIGN_CEIL(((frameHeight / 2) - uvblockHeight), MOS_YTILE_H_ALIGNMENT); if (pack) { srcOffset = srcSurface.dwPitch * (frameHeight + MOS_YTILE_H_ALIGNMENT + uvblockHeight); dstOffset = dstSurface.dwPitch * (frameHeight + uvblockHeight); } else { srcOffset = srcSurface.dwPitch * (frameHeight + uvblockHeight); dstOffset = dstSurface.dwPitch * (frameHeight + MOS_YTILE_H_ALIGNMENT + uvblockHeight); } if (m_hwInterface->m_noHuC) { CodechalDataCopyParams dataCopyParams; MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); dataCopyParams.srcResource = &srcSurface.OsResource; dataCopyParams.srcSize = uvsize; dataCopyParams.srcOffset = srcOffset; dataCopyParams.dstResource = &dstSurface.OsResource; dataCopyParams.dstSize = frameSize; dataCopyParams.dstOffset = dstOffset; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(&dataCopyParams)); } else { // Stream object params CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( &cmdBuffer, // pCmdBuffer &srcSurface.OsResource, // presSrc &dstSurface.OsResource, // presDst uvsize, // u32CopyLength srcOffset, // u32CopyInputOffset dstOffset)); // u32CopyOutputOffset } if (pack) { MOS_SYNC_PARAMS syncParams; syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_destSurface.OsResource; syncParams.bReadOnly = false; syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; syncParams.bDisableLockForTranscode = m_disableLockForTranscode; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams)); // Update the resource tag (s/w tag) for On-Demand Sync m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams)); // Update the tag in GPU Sync status buffer (H/W Tag) to match the current S/W tag if (m_osInterface->bTagResourceSync) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams)); } } else { MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( &cmdBuffer, nullptr)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, nullHwInUse)); return eStatus; } MOS_STATUS CodechalDecodeVc1::ConstructBistreamBuffer() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; if (m_hwInterface->m_noHuC) { CodechalDataCopyParams dataCopyParams; MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); dataCopyParams.srcResource = &m_resDataBuffer; dataCopyParams.srcSize = m_dataSize; dataCopyParams.srcOffset = 0; dataCopyParams.dstResource = &m_resPrivateBistreamBuffer; dataCopyParams.dstSize = m_privateBistreamBufferSize; dataCopyParams.dstOffset = CODECHAL_DECODE_VC1_STUFFING_BYTES; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(&dataCopyParams)); return MOS_STATUS_SUCCESS; } m_huCCopyInUse = true; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContextForWa)); m_osInterface->pfnResetOsStates(m_osInterface); m_osInterface->pfnSetPerfTag(m_osInterface, (uint16_t)(((m_mode << 4) & 0xF0) | COPY_TYPE)); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); // Send command buffer header at the beginning (OS dependent) CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, false)); CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( &cmdBuffer, // pCmdBuffer &m_resDataBuffer, // presSrc &m_resPrivateBistreamBuffer, // presDst MOS_ALIGN_CEIL(m_dataSize, 16), // u32CopyLength 0, // u32CopyInputOffset CODECHAL_DECODE_VC1_STUFFING_BYTES)); // u32CopyOutputOffset MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( &cmdBuffer, &flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( &cmdBuffer, nullptr)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); MOS_SYNC_PARAMS syncParams; syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContextForWa; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext)); return (MOS_STATUS)eStatus; } MOS_STATUS CodechalDecodeVc1::HandleSkipFrame() { MOS_COMMAND_BUFFER cmdBuffer; MHW_MI_FLUSH_DW_PARAMS flushDwParams; MHW_GENERIC_PROLOG_PARAMS genericPrologParams; MOS_SURFACE srcSurface; uint8_t fwdRefIdx; uint32_t surfaceSize; MOS_SYNC_PARAMS syncParams; MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; fwdRefIdx = (uint8_t)m_vc1PicParams->ForwardRefIdx; MOS_ZeroMemory(&srcSurface, sizeof(MOS_SURFACE)); srcSurface.Format = Format_NV12; srcSurface.OsResource = m_vc1RefList[fwdRefIdx]->resRefPic; CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &srcSurface)); #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetSurfaceMmcMode(&m_destSurface, &srcSurface)); #endif surfaceSize = ((srcSurface.OsResource.pGmmResInfo->GetArraySize()) > 1) ? ((uint32_t)(srcSurface.OsResource.pGmmResInfo->GetQPitchPlanar(GMM_PLANE_Y) * srcSurface.OsResource.pGmmResInfo->GetRenderPitch())) : (uint32_t)(srcSurface.OsResource.pGmmResInfo->GetSizeMainSurface()); // HuC is present if (m_hwInterface->m_noHuC) { CodechalDataCopyParams dataCopyParams; MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams)); dataCopyParams.srcResource = &srcSurface.OsResource; dataCopyParams.srcSize = surfaceSize; dataCopyParams.srcOffset = srcSurface.dwOffset; dataCopyParams.dstResource = &m_destSurface.OsResource; dataCopyParams.dstSize = surfaceSize; dataCopyParams.dstOffset = m_destSurface.dwOffset; CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(&dataCopyParams)); } else { m_huCCopyInUse = true; syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContextForWa; syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContextForWa)); m_osInterface->pfnResetOsStates(m_osInterface); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); // Send command buffer header at the beginning (OS dependent) CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, false)); CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy( &cmdBuffer, // pCmdBuffer &srcSurface.OsResource, // presSrc &m_destSurface.OsResource, // presDst surfaceSize, // u32CopyLength srcSurface.dwOffset, // u32CopyInputOffset m_destSurface.dwOffset)); // u32CopyOutputOffset syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContextForWa; syncParams.presSyncResource = &m_destSurface.OsResource; syncParams.bReadOnly = false; syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; syncParams.bDisableLockForTranscode = m_disableLockForTranscode; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams)); // Update the resource tag (s/w tag) for On-Demand Sync m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag if (m_osInterface->bTagResourceSync) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource( &cmdBuffer, &syncParams)); } MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd( &cmdBuffer, &flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd( &cmdBuffer, nullptr)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext)); } return (MOS_STATUS)eStatus; } uint32_t CodechalDecodeVc1::PeekBits(uint32_t bitsRead) { uint32_t value = 0; CODECHAL_DECODE_ASSERT((bitsRead) > 0 && (bitsRead) <= 32); uint32_t *cache = m_bitstream.pu32Cache; int32_t shiftOffset = m_bitstream.iBitOffset - (bitsRead); if (shiftOffset >= 0) { value = (*cache) >> (shiftOffset); } else { shiftOffset += 32; value = (cache[0] << (32 - shiftOffset)) + (cache[1] >> shiftOffset); } return (value & ((1 << bitsRead) - 1)); } uint32_t CodechalDecodeVc1::UpdateBitstreamBuffer() { uint32_t *cache = (uint32_t *)m_bitstream.CacheBuffer; uint32_t *cacheEnd = m_bitstream.pu32CacheEnd; uint32_t *cacheDataEnd = m_bitstream.pu32CacheDataEnd; uint32_t zeroNum = m_bitstream.u32ZeroNum; uint8_t * originalBitBuffer = m_bitstream.pOriginalBitBuffer; uint8_t * originalBufferEnd = m_bitstream.pOriginalBufferEnd; if (cacheDataEnd == cacheEnd) { *cache++ = *cacheEnd; } while (cache <= cacheEnd) { uint32_t leftByte; CODECHAL_DECODE_VC1_BITSTREAM_VALUE value; if (m_bitstream.bIsEBDU) { // for EBDU, set dwLeftByte to 4 to remove emulation prevention bytes in the later while loop leftByte = 4; value.u32Value = 0; } else { leftByte = 0; value.u8Value[3] = *originalBitBuffer++; value.u8Value[2] = *originalBitBuffer++; value.u8Value[1] = *originalBitBuffer++; value.u8Value[0] = *originalBitBuffer++; } while (leftByte) { if (originalBitBuffer >= originalBufferEnd) // End of the bitstream; { *cache = value.u32Value; m_bitstream.pu32Cache = (uint32_t *)m_bitstream.CacheBuffer; m_bitstream.u32ZeroNum = zeroNum; m_bitstream.pOriginalBitBuffer = originalBitBuffer; m_bitstream.pu32CacheDataEnd = cache; m_bitstream.iBitOffsetEnd = leftByte * 8; return 0; } uint8_t data = *originalBitBuffer++; if (zeroNum < 2) { zeroNum = data ? 0 : zeroNum + 1; } else if (zeroNum == 2) { if (data == 0x03) { if (originalBitBuffer < originalBufferEnd) { data = *originalBitBuffer++; zeroNum = (data == 0); } else { CODECHAL_DECODE_ASSERTMESSAGE("VC1 Bitstream Parsing Error: Incomplete bitstream."); return(CODECHAL_DECODE_VC1_EOS); } if (data > 0x03) { CODECHAL_DECODE_ASSERTMESSAGE("VC1 Bitstream Parsing Error: Not a valid code 0x000003 %x.", data); return(CODECHAL_DECODE_VC1_EOS); } } else if (data == 0x02) { CODECHAL_DECODE_ASSERTMESSAGE("VC1 Bitstream Parsing Error: Not a valid code 0x000002."); return(CODECHAL_DECODE_VC1_EOS); } else { zeroNum = data ? 0 : (zeroNum + 1); } } else // zeroNum > 3 { if (data == 0x00) { zeroNum++; } else if (data == 0x01) { zeroNum = 0; } else { CODECHAL_DECODE_ASSERTMESSAGE("VC1 Bitstream Parsing Error: Not a start code 0x000001."); return(CODECHAL_DECODE_VC1_EOS); } } leftByte--; value.u8Value[leftByte] = data; } *cache = value.u32Value; cache++; } m_bitstream.pu32Cache = (uint32_t *)m_bitstream.CacheBuffer; m_bitstream.u32ZeroNum = zeroNum; m_bitstream.pOriginalBitBuffer = originalBitBuffer; m_bitstream.iBitOffsetEnd = 0; m_bitstream.pu32CacheDataEnd = m_bitstream.pu32CacheEnd; return 0; } uint32_t CodechalDecodeVc1::GetBits(uint32_t bitsRead) { uint32_t value = 0; CODECHAL_DECODE_ASSERT((bitsRead > 0) && (bitsRead <= 32)); uint32_t *cache = m_bitstream.pu32Cache; int32_t shiftOffset = m_bitstream.iBitOffset - (bitsRead); if (shiftOffset >= 0) { value = (*cache) >> (shiftOffset); } else { shiftOffset += 32; value = (cache[0] << (32 - shiftOffset)) + (cache[1] >> shiftOffset); m_bitstream.pu32Cache++; } value &= ((0x1 << bitsRead) - 1); m_bitstream.iBitOffset = shiftOffset; m_bitstream.u32ProcessedBitNum += bitsRead; if ((cache == m_bitstream.pu32CacheDataEnd) && (m_bitstream.iBitOffset < m_bitstream.iBitOffsetEnd)) { return CODECHAL_DECODE_VC1_EOS; } if (cache == m_bitstream.pu32CacheEnd) { if (UpdateBitstreamBuffer() == CODECHAL_DECODE_VC1_EOS) { return CODECHAL_DECODE_VC1_EOS; } } return value; } uint32_t CodechalDecodeVc1::SkipBits(uint32_t bitsRead) { CODECHAL_DECODE_ASSERT((bitsRead > 0) && (bitsRead <= 32)); uint32_t *cache = m_bitstream.pu32Cache; int32_t shiftOffset = m_bitstream.iBitOffset - (bitsRead); if (shiftOffset < 0) { shiftOffset += 32; m_bitstream.pu32Cache++; } m_bitstream.iBitOffset = shiftOffset; m_bitstream.u32ProcessedBitNum += bitsRead; if ((cache == m_bitstream.pu32CacheDataEnd) && (m_bitstream.iBitOffset < m_bitstream.iBitOffsetEnd)) { return CODECHAL_DECODE_VC1_EOS; } if (cache == m_bitstream.pu32CacheEnd) { if (UpdateBitstreamBuffer() == CODECHAL_DECODE_VC1_EOS) { return CODECHAL_DECODE_VC1_EOS; } } return 0; } uint32_t CodechalDecodeVc1::GetVLC(const uint32_t *table) { if (table == nullptr) return CODECHAL_DECODE_VC1_EOS; CODECHAL_DECODE_ASSERT(table[0] > 0); // max bits uint32_t maxCodeLength = table[0]; uint32_t tableSize = table[0]; uint32_t index = 1; uint32_t codeLength = 1; uint32_t value = PeekBits(maxCodeLength); if (CODECHAL_DECODE_VC1_EOS == value) { CODECHAL_DECODE_ASSERTMESSAGE("Bitstream exhausted."); return(value); } for (uint32_t entryIndex = 0; entryIndex < tableSize; entryIndex++) { uint32_t subtableSize = table[index++]; if (subtableSize > 0) { while (subtableSize--) { if (table[index++] == (value >> (maxCodeLength - codeLength))) { value = GetBits((uint8_t)codeLength); return(table[index]); } index++; } } codeLength++; } CODECHAL_DECODE_ASSERTMESSAGE("Code is not in VLC table."); return(CODECHAL_DECODE_VC1_EOS); } MOS_STATUS CodechalDecodeVc1::InitialiseBitstream( uint8_t* buffer, uint32_t length, bool isEBDU) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; MOS_ZeroMemory(&m_bitstream, sizeof(m_bitstream)); CODECHAL_DECODE_CHK_NULL_RETURN(&m_bitstream); CODECHAL_DECODE_CHK_NULL_RETURN(buffer); m_bitstream.pOriginalBitBuffer = buffer; m_bitstream.pOriginalBufferEnd = buffer + length; m_bitstream.u32ZeroNum = 0; m_bitstream.u32ProcessedBitNum = 0; m_bitstream.pu32Cache = (uint32_t *)m_bitstream.CacheBuffer; m_bitstream.pu32CacheEnd = (uint32_t *)(m_bitstream.CacheBuffer + CODECHAL_DECODE_VC1_BITSTRM_BUF_LEN); m_bitstream.pu32CacheDataEnd = (uint32_t *)m_bitstream.CacheBuffer; m_bitstream.iBitOffset = 32; m_bitstream.iBitOffsetEnd = 32; m_bitstream.bIsEBDU = isEBDU; if (UpdateBitstreamBuffer() == CODECHAL_DECODE_VC1_EOS) { return MOS_STATUS_UNKNOWN; } return eStatus; } MOS_STATUS CodechalDecodeVc1::BitplaneNorm2Mode() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint16_t frameFieldHeightInMb; CodecHal_GetFrameFieldHeightInMb( m_vc1PicParams->CurrPic, m_picHeightInMb, frameFieldHeightInMb); uint16_t frameFieldWidthInMb = m_picWidthInMb; uint32_t count = frameFieldWidthInMb * frameFieldHeightInMb; uint32_t value = 0; if ((frameFieldWidthInMb * frameFieldHeightInMb) & 1) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); count--; } for (uint32_t i = 0; i < count / 2; i++) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value == 0) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); } } } return eStatus; } MOS_STATUS CodechalDecodeVc1::BitplaneNorm6Mode() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint16_t frameFieldHeightInMb; CodecHal_GetFrameFieldHeightInMb( m_vc1PicParams->CurrPic, m_picHeightInMb, frameFieldHeightInMb); uint16_t frameFieldWidthInMb = m_picWidthInMb; bool is2x3Tiled = (0 != frameFieldWidthInMb % 3) && (0 == frameFieldHeightInMb % 3); uint32_t heightInTiles = 0, widthInTiles = 0; uint32_t residualX = 0, residualY = 0; uint32_t value = 0; if (is2x3Tiled) { widthInTiles = frameFieldWidthInMb / 2; heightInTiles = frameFieldHeightInMb / 3; for (uint32_t j = 0; j < heightInTiles; j++) { for (uint32_t i = 0; i < widthInTiles; i++) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetVLC(CODECHAL_DECODE_VC1_VldCode3x2Or2x3TilesTable, value)); } } residualX = frameFieldWidthInMb & 1; residualY = 0; } else // 3x2 tiles { widthInTiles = frameFieldWidthInMb / 3; heightInTiles = frameFieldHeightInMb / 2; for (uint32_t j = 0; j < heightInTiles; j++) { for (uint32_t i = 0; i < widthInTiles; i++) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetVLC(CODECHAL_DECODE_VC1_VldCode3x2Or2x3TilesTable, value)); } } residualX = frameFieldWidthInMb % 3; residualY = frameFieldHeightInMb & 1; } // ResidualY 0 or 1 or 2 for (uint32_t i = 0; i < residualX; i++) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_BITPLANE_COLSKIP, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(SkipWords(frameFieldHeightInMb >> 4, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(frameFieldHeightInMb & 0xF, value)); } } // ResidualY 0 or 1 for (uint32_t j = 0; j < residualY; j++) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_BITPLANE_ROWSKIP, value)); if (value) { uint32_t skipBits = frameFieldWidthInMb - residualX; CODECHAL_DECODE_CHK_STATUS_RETURN(SkipWords(skipBits >> 4, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(skipBits & 0xF, value)); } } return eStatus; } MOS_STATUS CodechalDecodeVc1::BitplaneRowskipMode() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint16_t frameFieldHeightInMb; CodecHal_GetFrameFieldHeightInMb( m_vc1PicParams->CurrPic, m_picHeightInMb, frameFieldHeightInMb); uint16_t frameFieldWidthInMb = m_picWidthInMb; uint32_t value = 0; for (uint32_t j = 0; j < frameFieldHeightInMb; j++) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_BITPLANE_ROWSKIP, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(SkipWords(frameFieldWidthInMb >> 4, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(frameFieldWidthInMb & 0xF, value)); } } return eStatus; } MOS_STATUS CodechalDecodeVc1::BitplaneColskipMode() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint16_t meFieldHeightInMb; CodecHal_GetFrameFieldHeightInMb( m_vc1PicParams->CurrPic, m_picHeightInMb, meFieldHeightInMb); uint16_t frameFieldWidthInMb = m_picWidthInMb; uint32_t value = 0; uint32_t colSkip = 0; for (uint32_t i = 0; i < frameFieldWidthInMb; i++) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_BITPLANE_COLSKIP, value)); colSkip = value; if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(SkipWords(meFieldHeightInMb >> 4, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(meFieldHeightInMb & 0xF, value)); } } return eStatus; } MOS_STATUS CodechalDecodeVc1::ParseVopDquant() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint32_t value = 0; uint32_t dquantFRM = 0, dqprofile = 0, dqbilevel = 0; if ((1 == m_vc1PicParams->pic_quantizer_fields.dquant) || (3 == m_vc1PicParams->pic_quantizer_fields.dquant)) { // The DQUANTFRM field is a 1 bit value that is present only // when DQUANT = 1. If DQUANTFRM = 0 then the current picture // is only quantized with PQUANT. CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_DQUANTFRM, value)); dquantFRM = value; if (dquantFRM) { // The DQPROFILE field is a 2 bits value that is present // only when DQUANT = 1 and DQUANTFRM = 1. It indicates // where we are allowed to change quantization step sizes // within the current picture. // Table 15: Macroblock Quantization Profile (DQPROFILE) Code Table // FLC Location // 00 All four Edges // 01 Double Edges // 10 Single Edges // 11 All Macroblocks CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_DQPROFILE, value)); dqprofile = value; switch (dqprofile) { case 0: // all 4 edges { break; } case 1: // double edges { // The DQSBEDGE field is a 2 bits value that is present // when DQPROFILE = Single Edge. It indicates which edge // will be quantized with ALTPQUANT. // Table 16: Single Boundary Edge Selection (DQSBEDGE) Code Table // FLC Boundary Edge // 00 Left // 01 Top // 10 Right // 11 Bottom CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_DQDBEDGE, value)); break; } case 2: // single edge { // The DQSBEDGE field is a 2 bits value that is present // when DQPROFILE = Single Edge. It indicates which edge // will be quantized with ALTPQUANT. // Table 16: Single Boundary Edge Selection (DQSBEDGE) Code Table // FLC Boundary Edge // 00 Left // 01 Top // 10 Right // 11 Bottom CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_DQDBEDGE, value)); break; } case 3: // all MBs { // The DQBILEVEL field is a 1 bit value that is present // when DQPROFILE = All Macroblock. If DQBILEVEL = 1, // then each macroblock in the picture can take one of // two possible values (PQUANT or ALTPQUANT). If // DQBILEVEL = 0, then each macroblock in the picture // can take on any quantization step size. CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_DQBILEVEL, value)); dqbilevel = value; break; } } } } else if (2 == m_vc1PicParams->pic_quantizer_fields.dquant) { dquantFRM = 1; } // PQDIFF is a 3 bit field that encodes either the PQUANT // differential or encodes an escape code. // If PQDIFF does not equal 7 then PQDIFF encodes the // differential and the ABSPQ field does not follow in // the bitstream. In this case: // ALTPQUANT = PQUANT + PQDIFF + 1 // If PQDIFF equals 7 then the ABSPQ field follows in // the bitstream and ALTPQUANT is decoded as: // ALTPQUANT = ABSPQ if (dquantFRM) { if ((m_vc1PicParams->pic_quantizer_fields.dquant == 2) || !(dqprofile == 3 && dqbilevel == 0)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_PQDIFF, value)); if (7 == value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_ABSPQ, value)); } } } return eStatus; } MOS_STATUS CodechalDecodeVc1::ParseMvRange() { uint32_t value; MOS_STATUS eStatus = MOS_STATUS_SUCCESS; // MVRANGE CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); } } return eStatus; } MOS_STATUS CodechalDecodeVc1::ParseProgressiveMvMode( const uint32_t mvModeTable[], uint32_t* mvMode) { uint32_t value; MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint32_t bitCount = 1; CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); while ((value == 0) && (bitCount < 4)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); bitCount++; } uint32_t index = (bitCount < 4) ? bitCount - 1 : bitCount + value - 1; uint32_t mvModeType = mvModeTable[index]; if (CODECHAL_VC1_MVMODE_IC == mvModeType) { bitCount = 1; CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); while ((value == 0) && (bitCount < 3)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); bitCount++; } index = (bitCount < 3) ? bitCount - 1 : bitCount + !value - 1; mvModeType = mvModeTable[index]; CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(CODECHAL_DECODE_VC1_BITS_LUMSCALE + CODECHAL_DECODE_VC1_BITS_LUMSHIFT, value)); } *mvMode = mvModeType; return eStatus; } MOS_STATUS CodechalDecodeVc1::ParseInterlaceMVMode( bool isPPicture, uint32_t* mvmode) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_CHK_NULL_RETURN(mvmode); const uint32_t *mvModeTable; if (12 < m_vc1PicParams->pic_quantizer_fields.pic_quantizer_scale) { mvModeTable = CODECHAL_DECODE_VC1_LowRateMvModeTable; } else { mvModeTable = CODECHAL_DECODE_VC1_HighRateMvModeTable; } uint32_t bitCount = 1; uint32_t value = 0; uint32_t index = 0, mvMode = 0; CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (isPPicture) { while ((value == 0) && (bitCount < 4)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); bitCount++; } index = (bitCount < 4) ? bitCount - 1 : bitCount + value - 1; mvMode = mvModeTable[index]; } else // B picture { while ((value == 0) && (bitCount < 3)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); bitCount++; } index = (bitCount < 3) ? bitCount - 1 : bitCount + !value - 1; } mvMode = mvModeTable[index]; if (CODECHAL_VC1_MVMODE_IC == value) { bitCount = 1; CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); while ((value == 0) && (bitCount < 3)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); bitCount++; } index = (bitCount < 3) ? bitCount - 1 : bitCount + !value - 1; mvMode = mvModeTable[index]; // Intensity compensation flags uint32_t skipBits = 0; CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value == 0) { skipBits += 1 + CODECHAL_DECODE_VC1_BITS_LUMSCALE + CODECHAL_DECODE_VC1_BITS_LUMSHIFT; } skipBits += CODECHAL_DECODE_VC1_BITS_LUMSCALE + CODECHAL_DECODE_VC1_BITS_LUMSHIFT; CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(skipBits, value)); } *mvmode = mvMode; return eStatus; } MOS_STATUS CodechalDecodeVc1::ParseBitplane() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint32_t value = 0; CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_BITPLANE_INVERT, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(GetVLC(CODECHAL_DECODE_VC1_VldBitplaneModeTable, value)); switch (value) // Bitplane mode { case CODECHAL_VC1_BITPLANE_NORMAL2: eStatus = BitplaneNorm2Mode(); break; case CODECHAL_VC1_BITPLANE_NORMAL6: eStatus = BitplaneNorm6Mode(); break; case CODECHAL_VC1_BITPLANE_DIFF2: eStatus = BitplaneNorm2Mode(); // Diff2 is the same as Norm2 mode break; case CODECHAL_VC1_BITPLANE_DIFF6: eStatus = BitplaneNorm6Mode(); // Diff6 is the same as Norm6 mode break; case CODECHAL_VC1_BITPLANE_ROWSKIP: eStatus = BitplaneRowskipMode(); break; case CODECHAL_VC1_BITPLANE_COLSKIP: eStatus = BitplaneColskipMode(); break; case CODECHAL_VC1_BITPLANE_RAW: // nothing to do break; default: CODECHAL_DECODE_ASSERTMESSAGE("Invalid bitplane mode %d.", value); } return eStatus; } MOS_STATUS CodechalDecodeVc1::ParsePictureLayerIAdvanced() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint32_t value = 0; if (CodecHal_PictureIsInterlacedFrame(m_vc1PicParams->CurrPic)) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); } CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); if (m_vc1PicParams->sequence_fields.overlap && (m_vc1PicParams->pic_quantizer_fields.pic_quantizer_scale <= 8)) { //conditional overlap flag CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (1 == value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (1 == value) { // CONDOVER == 2 CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); } } } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_1, value)); if (0 != value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_2, value)); } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM2_1, value)); if (0 != value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM2_2, value)); } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSDCTAB, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(ParseVopDquant()); return eStatus; } MOS_STATUS CodechalDecodeVc1::ParsePictureLayerPAdvanced() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; if (m_vc1PicParams->mv_fields.extended_mv_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseMvRange()); } const uint32_t *mvModeTable = nullptr; mvModeTable = (12 < m_vc1PicParams->pic_quantizer_fields.pic_quantizer_scale) ? CODECHAL_DECODE_VC1_LowRateMvModeTable : CODECHAL_DECODE_VC1_HighRateMvModeTable; uint32_t mvMode; CODECHAL_DECODE_CHK_STATUS_RETURN(ParseProgressiveMvMode(mvModeTable, &mvMode)); if (CODECHAL_VC1_MVMODE_MIXEDMV == mvMode) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); } CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); uint32_t value = 0; CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(CODECHAL_DECODE_VC1_BITS_MVTAB + CODECHAL_DECODE_VC1_BITS_CBPTAB, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(ParseVopDquant()); if (m_vc1PicParams->transform_fields.variable_sized_transform_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TTMBF, value)); if (1 == value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TTFRM, value)); } } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_1, value)); if (0 != value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_2, value)); } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSDCTAB, value)); return eStatus; } MOS_STATUS CodechalDecodeVc1::ParsePictureLayerBAdvanced() { uint32_t value; MOS_STATUS eStatus = MOS_STATUS_SUCCESS; if (m_vc1PicParams->mv_fields.extended_mv_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseMvRange()); } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); // B frame direct mode macroblock bit syntax element CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); // skipped macroblock bit syntax element CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(CODECHAL_DECODE_VC1_BITS_MVTAB + CODECHAL_DECODE_VC1_BITS_CBPTAB, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(ParseVopDquant()); if (m_vc1PicParams->transform_fields.variable_sized_transform_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TTMBF, value)); if (1 == value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TTFRM, value)); } } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_1, value)); if (0 != value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_2, value)); } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSDCTAB, value)); return eStatus; } MOS_STATUS CodechalDecodeVc1::ParseFieldPictureLayerPAdvanced() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint32_t value = 0; uint32_t numRef = 0; if (CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_NUMREF, value)); numRef = value; if (0 == value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_REFFIELD, value)); } } else { numRef = 0; } if (m_vc1PicParams->mv_fields.extended_mv_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseMvRange()); } if (m_vc1PicParams->mv_fields.extended_dmv_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); } } } uint32_t mvMode; if (CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseInterlaceMVMode(true, &mvMode)); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_4MVSWITCH, value)); if (value) { mvMode = CODECHAL_VC1_MVMODE_MIXEDMV; } else { mvMode = CODECHAL_VC1_MVMODE_1MV; } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_INTCOMP, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(CODECHAL_DECODE_VC1_BITS_LUMSCALE + CODECHAL_DECODE_VC1_BITS_LUMSHIFT, value)); } // skipped macroblock bitplane CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); } uint32_t skipBits = 0; if (CodecHal_PictureIsInterlacedFrame(m_vc1PicParams->CurrPic)) { skipBits += 2; // 2-bit MBMODETAB } else { skipBits += 3; // 3 bit MBMODETAB } if (0 == numRef) { skipBits += 2; // 2-bit MVTAB } else { skipBits += 3; // 3-bit MVTAB } skipBits += CODECHAL_DECODE_VC1_BITS_CBPTAB_INTERLACE; if (CodecHal_PictureIsInterlacedFrame(m_vc1PicParams->CurrPic)) { skipBits += CODECHAL_DECODE_VC1_BITS_2MVBPTAB; } if (CODECHAL_VC1_MVMODE_MIXEDMV == mvMode) { skipBits += CODECHAL_DECODE_VC1_BITS_4MVBPTAB; } CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(skipBits, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(ParseVopDquant()); if (m_vc1PicParams->transform_fields.variable_sized_transform_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TTMBF, value)); if (1 == value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TTFRM, value)); } } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_1, value)); if (0 != value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_2, value)); } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSDCTAB, value)); return eStatus; } MOS_STATUS CodechalDecodeVc1::ParseFieldPictureLayerBAdvanced() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint32_t value = 0; if (CodecHal_PictureIsInterlacedFrame(m_vc1PicParams->CurrPic)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetVLC(CODECHAL_DECODE_VC1_VldBFractionTable, value)); m_vc1PicParams->b_picture_fraction = (uint8_t)value; } if (m_vc1PicParams->mv_fields.extended_mv_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseMvRange()); } if (m_vc1PicParams->mv_fields.extended_dmv_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); } } } uint32_t mvMode; if (CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParseInterlaceMVMode(false, &mvMode)); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_INTCOMP, value)); if (value) { CODECHAL_DECODE_VERBOSEMESSAGE("INTCOMP is not false."); } mvMode = CODECHAL_VC1_MVMODE_1MV; // direct macroblock bitplane CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); // skipped macroblock bitplane CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); } if (CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { // forward macroblock CODECHAL_DECODE_CHK_STATUS_RETURN(ParseBitplane()); } uint32_t skipBits = 0; if (CodecHal_PictureIsInterlacedFrame(m_vc1PicParams->CurrPic)) { skipBits += 2; // 2-bit MBMODETAB } else { skipBits += 3; // 3 bit MBMODETAB } if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { skipBits += 2; // 2-bit MVTAB } else { skipBits += 3; // 3-bit MVTAB } skipBits += CODECHAL_DECODE_VC1_BITS_CBPTAB_INTERLACE; if (CodecHal_PictureIsInterlacedFrame(m_vc1PicParams->CurrPic)) { skipBits += CODECHAL_DECODE_VC1_BITS_2MVBPTAB; } if ((CODECHAL_VC1_MVMODE_MIXEDMV == mvMode) || CodecHal_PictureIsInterlacedFrame(m_vc1PicParams->CurrPic)) { skipBits += CODECHAL_DECODE_VC1_BITS_4MVBPTAB; } CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(skipBits, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(ParseVopDquant()); if (m_vc1PicParams->transform_fields.variable_sized_transform_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TTMBF, value)); if (1 == value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TTFRM, value)); } } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_1, value)); if (0 != value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSACFRM_2, value)); } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TRANSDCTAB, value)); return eStatus; } MOS_STATUS CodechalDecodeVc1::ParsePictureHeaderAdvanced() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; bool isIPicture = m_mfxInterface->IsVc1IPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type) ? true : false; bool isPPicture = m_mfxInterface->IsVc1PPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type) ? true : false; bool isBPicture = m_mfxInterface->IsVc1BPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type) ? true : false; bool isBIPicture = m_mfxInterface->IsVc1BIPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type) ? true : false; uint32_t value = 0; if (m_vc1PicParams->sequence_fields.interlace) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_FCM_1, value)); if (0 != value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_FCM_2, value)); } } if (CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_FPTYPE, value)); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(GetVLC(CODECHAL_DECODE_VC1_VldPictureTypeTable, value)); } if (m_vc1PicParams->sequence_fields.tfcntrflag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TFCNTR, value)); } uint32_t repeatFrameCount = 0, numPanScanWindows, skipBits; uint32_t repeatFirstField = 0; if (m_vc1PicParams->sequence_fields.pulldown) { if (!m_vc1PicParams->sequence_fields.interlace) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_RPTFRM, value)); repeatFrameCount = value; } else { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_TFF, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_RFF, value)); repeatFirstField = value; } } if (m_vc1PicParams->entrypoint_fields.panscan_flag) { // parse PANSCAN if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { if (!m_vc1PicParams->sequence_fields.pulldown) { numPanScanWindows = 1; } else { numPanScanWindows = 1 + repeatFrameCount; } } else { if (!m_vc1PicParams->sequence_fields.pulldown) { numPanScanWindows = 2; } else { numPanScanWindows = 2 + repeatFirstField; } } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_PS_PRESENT, value)); if (value) { skipBits = CODECHAL_DECODE_VC1_BITS_PS_HOFFSET + CODECHAL_DECODE_VC1_BITS_PS_VOFFSET; skipBits += CODECHAL_DECODE_VC1_BITS_PS_WIDTH + CODECHAL_DECODE_VC1_BITS_PS_HEIGHT; skipBits = skipBits * numPanScanWindows; CODECHAL_DECODE_CHK_STATUS_RETURN(SkipWords(skipBits >> 4, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(SkipBits(skipBits & 0xF, value)); } } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_RNDCTRL, value)); if (isIPicture || isBIPicture) { if (value != 0) { CODECHAL_DECODE_ASSERTMESSAGE("RNDCTRL is not 0 for I, BI pictures."); return MOS_STATUS_UNKNOWN; } } if (m_vc1PicParams->sequence_fields.interlace) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_UVSAMP, value)); } if (m_vc1PicParams->sequence_fields.finterpflag && CodecHal_PictureIsFrame(m_vc1PicParams->CurrPic)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_INTERPFRM, value)); } if (!CodecHal_PictureIsInterlacedFrame(m_vc1PicParams->CurrPic)) { if (isBPicture || (CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && isBIPicture)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetVLC(CODECHAL_DECODE_VC1_VldBFractionTable, value)); m_vc1PicParams->b_picture_fraction = (uint8_t)value; } } // REFDIST if (CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->reference_fields.reference_distance_flag && m_vc1PicParams->reference_fields.reference_picture_flag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(2, value)); if (value == 3) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetVLC(CODECHAL_DECODE_VC1_VldRefDistTable, value)); } m_vc1PicParams->reference_fields.reference_distance = value; } // Quantization Params CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_PQINDEX, value)); if (8 >= value) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_HALFQP, value)); } if (1 == m_vc1PicParams->pic_quantizer_fields.quantizer) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_PQUANTIZER, value)); } // POSTPROC if (m_vc1PicParams->post_processing) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_POSTPROC, value)); } if (!CodecHal_PictureIsFrame(m_vc1PicParams->CurrPic)) { if (isIPicture || isBIPicture) { eStatus = ParsePictureLayerIAdvanced(); } else if (isPPicture) { eStatus = ParseFieldPictureLayerPAdvanced(); } else if (isBPicture) { eStatus = ParseFieldPictureLayerBAdvanced(); } } else { if (isIPicture || isBIPicture) { eStatus = ParsePictureLayerIAdvanced(); } else if (isPPicture) { eStatus = ParsePictureLayerPAdvanced(); } else if (isBPicture) { eStatus = ParsePictureLayerBAdvanced(); } } return eStatus; } MOS_STATUS CodechalDecodeVc1::ParsePictureHeaderMainSimple() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; uint32_t value = 0; if (m_vc1PicParams->sequence_fields.finterpflag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_INTERPFRM, value)); } CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_FRMCNT, value)); if (m_vc1PicParams->sequence_fields.rangered) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_RANGEREDFRM, value)); } // picture type CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if ((0 == value) && (m_vc1PicParams->sequence_fields.max_b_frames > 0)) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(1, value)); if (0 == value) { // it's B or BI picture, get B fraction CODECHAL_DECODE_CHK_STATUS_RETURN(GetVLC(CODECHAL_DECODE_VC1_VldBFractionTable, value)); m_vc1PicParams->b_picture_fraction = (uint8_t)value; } } // we don't need to parse more since we only want B fraction value return eStatus; } MOS_STATUS CodechalDecodeVc1::GetSliceMbDataOffset() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; if (m_numSlices == 1) { return eStatus; } CodechalResLock ResourceLock(m_osInterface, &m_resDataBuffer); auto bitstream = (uint8_t*)ResourceLock.Lock(CodechalResLock::readOnly); CODECHAL_DECODE_CHK_NULL_RETURN(bitstream); // start from the second slice since HW only need MB data offset for subsequent slices uint32_t macroblockOffset = 0; for (uint32_t slcCount = 1; slcCount < m_numSlices; slcCount++) { uint8_t *slice = bitstream + m_vc1SliceParams[slcCount].slice_data_offset; // skip start code prefix slice += m_vldSliceRecord[slcCount].dwOffset; uint32_t length = m_vldSliceRecord[slcCount].dwLength; CODECHAL_DECODE_CHK_STATUS_RETURN(InitialiseBitstream(slice, length, true)); // parse slice header to get PIC_HEADER_FLAG uint32_t value = 0; CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_SC_SUFFIX, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_SLICE_ADDR, value)); CODECHAL_DECODE_CHK_STATUS_RETURN(GetBits(CODECHAL_DECODE_VC1_BITS_PIC_HEADER_FLAG, value)); // parse picture header to get MB data offset if PIC_HEADER_FLAG == true if (value) { if (macroblockOffset == 0) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParsePictureHeaderAdvanced()); macroblockOffset = m_bitstream.u32ProcessedBitNum + (CODECHAL_DECODE_VC1_SC_PREFIX_LENGTH << 3); } m_vc1SliceParams[slcCount].macroblock_offset = macroblockOffset; } } return eStatus; } MOS_STATUS CodechalDecodeVc1::ParsePictureHeader() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; bool isEBDU = m_vc1PicParams->sequence_fields.AdvancedProfileFlag; CodechalResLock ResourceLock(m_osInterface, &m_resDataBuffer); auto bitstream = (uint8_t*)ResourceLock.Lock(CodechalResLock::readOnly); CODECHAL_DECODE_CHK_NULL_RETURN(bitstream); uint32_t skippedBytes = 0; if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { // skip start code (4-byte) skippedBytes = CODECHAL_DECODE_VC1_SC_PREFIX_LENGTH + (CODECHAL_DECODE_VC1_BITS_SC_SUFFIX >> 3); } bitstream += skippedBytes; uint32_t length = m_dataSize - skippedBytes; CODECHAL_DECODE_CHK_STATUS_RETURN(InitialiseBitstream(bitstream, length, isEBDU)); if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParsePictureHeaderAdvanced()); } else { CODECHAL_DECODE_CHK_STATUS_RETURN(ParsePictureHeaderMainSimple()); } return eStatus; } MOS_STATUS CodechalDecodeVc1::AllocateResources() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; MOS_LOCK_PARAMS lockFlagsWriteOnly; MOS_ZeroMemory(&lockFlagsWriteOnly, sizeof(MOS_LOCK_PARAMS)); lockFlagsWriteOnly.WriteOnly = 1; m_numMacroblocks = m_picWidthInMb * m_picHeightInMb; m_numMacroblocksUv = m_picWidthInMb * (MOS_ALIGN_CEIL(m_picHeightInMb, 2) / 2); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource(m_osInterface, &m_resSyncObject)); CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalAllocateDataList( m_vc1RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1)); // Second level batch buffer for IT mode if (m_mode == CODECHAL_DECODE_MODE_VC1IT) { MOS_ZeroMemory(&m_itObjectBatchBuffer, sizeof(m_itObjectBatchBuffer)); // Must reserve at least 8 cachelines after MI_BATCH_BUFFER_END_CMD since HW prefetch max 8 cachelines from BB everytime uint32_t size = m_standardDecodeSizeNeeded * m_numMacroblocks + m_hwInterface->m_sizeOfCmdBatchBufferEnd + 8 * CODECHAL_CACHELINE_SIZE; CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_AllocateBb( m_osInterface, &m_itObjectBatchBuffer, nullptr, size)); m_itObjectBatchBuffer.bSecondLevel = true; } // Deblocking Filter Row Store Scratch buffer //(Num MacroBlock Width) * (Num Cachlines) * (Cachline size) CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resMfdDeblockingFilterRowStoreScratchBuffer, m_picWidthInMb * 7 * CODECHAL_CACHELINE_SIZE, "DeblockingScratchBuffer"), "Failed to allocate Deblocking Filter Row Store Scratch Buffer."); // BSD/MPC Row Store Scratch buffer // (FrameWidth in MB) * (2) * (CacheLine size per MB) CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resBsdMpcRowStoreScratchBuffer, m_picWidthInMb * CODECHAL_CACHELINE_SIZE * 2, "MpcScratchBuffer"), "Failed to allocate BSD/MPC Row Store Scratch Buffer."); // VC1 MV buffer, 1 cacheline for every MB for (uint32_t i = 0; i < CODECHAL_DECODE_VC1_DMV_MAX; i++) { CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resVc1BsdMvData[i], CODECHAL_CACHELINE_SIZE * m_numMacroblocks, "MvBuffer"), "Failed to allocate VC1 BSD MV Buffer."); } // Bitplane buffer // (Bitplane buffer pitch) * (Height in Macroblock) uint32_t size; if (m_shortFormatInUse) { if (m_width <= 2048) { size = MHW_VDBOX_VC1_BITPLANE_BUFFER_PITCH_SMALL * m_picHeightInMb; } else { size = MHW_VDBOX_VC1_BITPLANE_BUFFER_PITCH_LARGE * m_picHeightInMb; } CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resBitplaneBuffer, size, "BitplaneBuffer"), "Failed to allocate Bitplane Buffer."); } // For SP/MP short format // Private bitstream buffer // FrameWidth * FrameHeight * 1.5 + CODECHAL_DECODE_VC1_STUFFING_BYTES if (m_shortFormatInUse) { size = m_width * m_height * 3 / 2 + CODECHAL_DECODE_VC1_STUFFING_BYTES; m_privateBistreamBufferSize = size; CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateBuffer( &m_resPrivateBistreamBuffer, size, "PrivateBistreamBuffer"), "Failed to allocate BSD/MPC Row Store Scratch Buffer."); } m_unequalFieldWaInUse = (MEDIA_IS_WA(m_waTable, WaVC1UnequalFieldHeights) && (m_picHeightInMb % 2)); if (m_unequalFieldWaInUse) { // Decoded frame surface for (uint32_t i = 0; i < CODECHAL_DECODE_VC1_UNEQUAL_FIELD_WA_SURFACES; i++) { // Error Frame is 1MB x 2MB CODECHAL_DECODE_CHK_STATUS_MESSAGE_RETURN(AllocateSurface( &m_unequalFieldSurface[i], m_width, m_height + MOS_YTILE_H_ALIGNMENT, "Vc1UnequalFieldSurface"), "Failed to allocate VC1 Unequal Fields WA decoding ouput surface data buffer."); // ensure that no entries are valid m_unequalFieldRefListIdx[i] = CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1; } m_unequalFieldSurfaceForBType = CODECHAL_DECODE_VC1_UNEQUAL_FIELD_WA_SURFACES - 1; m_currUnequalFieldSurface = 0; } CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObjectWaContextInUse)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateSyncResource( m_osInterface, &m_resSyncObjectVideoContextInUse)); return (MOS_STATUS)eStatus; } CodechalDecodeVc1::~CodechalDecodeVc1() { CODECHAL_DECODE_FUNCTION_ENTER; m_osInterface->pfnDestroySyncResource(m_osInterface, &m_resSyncObject); CodecHalFreeDataList(m_vc1RefList, CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1); MOS_FreeMemory(m_vldSliceRecord); m_vldSliceRecord = nullptr; Mhw_FreeBb(m_osInterface, &m_itObjectBatchBuffer, nullptr); m_osInterface->pfnFreeResource( m_osInterface, &m_resMfdDeblockingFilterRowStoreScratchBuffer); m_osInterface->pfnFreeResource( m_osInterface, &m_resBsdMpcRowStoreScratchBuffer); for (uint32_t i = 0; i < CODECHAL_DECODE_VC1_DMV_MAX; i++) { m_osInterface->pfnFreeResource( m_osInterface, &m_resVc1BsdMvData[i]); } if (m_shortFormatInUse) { m_osInterface->pfnFreeResource( m_osInterface, &m_resBitplaneBuffer); } m_osInterface->pfnFreeResource( m_osInterface, &m_resPrivateBistreamBuffer); if (m_unequalFieldWaInUse) { for (uint32_t i = 0; i < CODECHAL_DECODE_VC1_UNEQUAL_FIELD_WA_SURFACES; i++) { // Error Frame is 1MB x 2MB m_osInterface->pfnFreeResource( m_osInterface, &m_unequalFieldSurface[i].OsResource); ; } } m_osInterface->pfnDestroySyncResource( m_osInterface, &m_resSyncObjectWaContextInUse); m_osInterface->pfnDestroySyncResource( m_osInterface, &m_resSyncObjectVideoContextInUse); } MOS_STATUS CodechalDecodeVc1::SetFrameStates() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_destSurface); CODECHAL_DECODE_CHK_NULL_RETURN(m_decodeParams.m_dataBuffer); m_dataSize = m_decodeParams.m_dataSize; m_dataOffset = m_decodeParams.m_dataOffset; m_numSlices = m_decodeParams.m_numSlices; m_numMacroblocks = m_decodeParams.m_numMacroblocks; m_vc1PicParams = (PCODEC_VC1_PIC_PARAMS)(m_decodeParams.m_picParams); m_vc1SliceParams = (PCODEC_VC1_SLICE_PARAMS)(m_decodeParams.m_sliceParams); m_vc1MbParams = (PCODEC_VC1_MB_PARAMS)(m_decodeParams.m_macroblockParams); m_destSurface = *(m_decodeParams.m_destSurface); m_resDataBuffer = *(m_decodeParams.m_dataBuffer); m_deblockDataBuffer = m_decodeParams.m_deblockData; CODECHAL_DECODE_CHK_NULL_RETURN(m_vc1PicParams); if (m_vc1PicParams->coded_width > m_destSurface.dwPitch || m_vc1PicParams->coded_height > m_destSurface.dwHeight) { return MOS_STATUS_INVALID_PARAMETER; } if (CodecHalIsDecodeModeVLD(m_mode)) { CODECHAL_DECODE_CHK_NULL_RETURN(m_vc1SliceParams); uint32_t numSliceRecord = 0; bool invalidSliceNum = false; numSliceRecord = m_numMacroblocks; if (m_numSlices > m_numMacroblocks) { numSliceRecord = m_numSlices; invalidSliceNum = true; } if (numSliceRecord > m_numVldSliceRecord || m_vldSliceRecord == nullptr) { MOS_SafeFreeMemory(m_vldSliceRecord); m_vldSliceRecord = (PCODECHAL_VC1_VLD_SLICE_RECORD)MOS_AllocAndZeroMemory(numSliceRecord * sizeof(CODECHAL_VC1_VLD_SLICE_RECORD)); CODECHAL_DECODE_CHK_NULL_RETURN(m_vldSliceRecord); m_numVldSliceRecord = numSliceRecord; } else { MOS_ZeroMemory(m_vldSliceRecord, m_numVldSliceRecord * sizeof(CODECHAL_VC1_VLD_SLICE_RECORD)); } } else if (CodecHalIsDecodeModeIT(m_mode)) { CODECHAL_DECODE_CHK_NULL_RETURN(m_vc1MbParams); // Catch the case the codec does not send a deblocking surface, but requests ILDB if (m_deblockDataBuffer == nullptr) { m_vc1PicParams->entrypoint_fields.loopfilter = 0; } } // For short format, check if it is skipped frame. if (m_shortFormatInUse) { m_numMacroblocks = m_picWidthInMb * m_picHeightInMb; if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { if ((m_vc1SliceParams->macroblock_offset == 0xFFFF) && (m_vc1SliceParams->number_macroblocks == m_numMacroblocks)) { m_vc1PicParams->picture_fields.picture_type = vc1SkippedFrame; } } else // Simple or Main Profiles { if (((m_vc1SliceParams->slice_data_size == 0) || (m_vc1SliceParams->slice_data_size == 8)) && (m_vc1SliceParams->number_macroblocks == m_numMacroblocks)) { m_vc1PicParams->picture_fields.picture_type = vc1SkippedFrame; } } } PCODEC_REF_LIST destEntry = m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]; uint16_t picType = (uint16_t)m_vc1PicParams->picture_fields.picture_type; CODEC_PICTURE currPic = m_vc1PicParams->CurrPic; if (!CodecHal_PictureIsField(currPic) || (CodecHal_PictureIsField(currPic) && m_vc1PicParams->picture_fields.is_first_field)) { MOS_ZeroMemory(destEntry, sizeof(CODEC_REF_LIST)); destEntry->RefPic = currPic; destEntry->resRefPic = m_destSurface.OsResource; } if (!m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { if (m_vc1PicParams->range_mapping_fields.range_mapping_enabled) { MOS_BIT_ON(destEntry->dwRefSurfaceFlags, CODECHAL_WMV9_RANGE_ADJUSTMENT); } else { MOS_BIT_OFF(destEntry->dwRefSurfaceFlags, CODECHAL_WMV9_RANGE_ADJUSTMENT); } } if (CodecHal_PictureIsFrame(currPic)) { MOS_BIT_ON(destEntry->dwRefSurfaceFlags, CODECHAL_VC1_PROGRESSIVE); } m_statusReportFeedbackNumber = m_vc1PicParams->StatusReportFeedbackNumber; m_deblockingEnabled = m_vc1PicParams->entrypoint_fields.loopfilter; m_width = m_vc1PicParams->coded_width; m_height = m_vc1PicParams->coded_height; m_picWidthInMb = ((uint16_t)m_width + CODECHAL_MACROBLOCK_WIDTH - 1) / CODECHAL_MACROBLOCK_WIDTH; m_picHeightInMb = ((uint16_t)m_height + CODECHAL_MACROBLOCK_HEIGHT - 1) / CODECHAL_MACROBLOCK_HEIGHT; if (CodecHal_PictureIsField(currPic) && (m_picHeightInMb % 2)) { m_vc1OddFrameHeight = true; } else { m_vc1OddFrameHeight = false; } // Overwrite the actual surface height with the coded height and width of the frame // for VC1 since it's possible for a VC1 frame to change size during playback m_destSurface.dwWidth = m_width; m_destSurface.dwHeight = m_height; bool bOLPParamsAvailable = m_vc1PicParams->range_mapping_fields.range_mapping_enabled || m_vc1PicParams->UpsamplingFlag; if (m_decodeParams.m_deblockSurface && ((m_vc1PicParams->DeblockedPicIdx != m_vc1PicParams->CurrPic.FrameIdx) || bOLPParamsAvailable) && !(CodecHal_PictureIsField(currPic) && m_vc1PicParams->picture_fields.is_first_field)) { m_olpNeeded = true; m_deblockSurface = *(m_decodeParams.m_deblockSurface); } if (m_decodeParams.m_vc1BitplaneSize == 0) { m_vc1PicParams->raw_coding.bitplane_present = 0; } if (m_vc1PicParams->raw_coding.bitplane_present) { m_resBitplaneBuffer = *(m_decodeParams.m_bitplaneBuffer); } bool pictureIsI = m_mfxInterface->IsVc1IPicture(currPic, m_vc1PicParams->picture_fields.is_first_field, picType); bool pictureIsP = m_mfxInterface->IsVc1PPicture(currPic, m_vc1PicParams->picture_fields.is_first_field, picType); bool pictureIsB = (m_mfxInterface->IsVc1BPicture(currPic, m_vc1PicParams->picture_fields.is_first_field, picType) || m_mfxInterface->IsVc1BIPicture(currPic, m_vc1PicParams->picture_fields.is_first_field, picType)); // Save anchor picture type and field structure (TFF/BFF) if (!pictureIsB) { m_prevAnchorPictureTff = (uint16_t)m_vc1PicParams->picture_fields.top_field_first; if (CodecHal_PictureIsBottomField(currPic)) { m_prevOddAnchorPictureIsP = pictureIsP; } else { m_prevEvenAnchorPictureIsP = pictureIsP; } } if (m_unequalFieldWaInUse && CodecHal_PictureIsField(currPic)) { CODECHAL_DECODE_CHK_STATUS_RETURN(InitializeUnequalFieldSurface( (uint8_t)m_vc1PicParams->CurrPic.FrameIdx, m_renderContextUsesNullHw)); CODECHAL_DECODE_CHK_STATUS_RETURN(InitializeUnequalFieldSurface( (uint8_t)m_vc1PicParams->ForwardRefIdx, m_renderContextUsesNullHw)); CODECHAL_DECODE_CHK_STATUS_RETURN(InitializeUnequalFieldSurface( (uint8_t)m_vc1PicParams->BackwardRefIdx, m_renderContextUsesNullHw)); } m_perfType = pictureIsI ? I_TYPE : (pictureIsP ? P_TYPE : B_TYPE); m_crrPic = currPic; m_secondField = (m_vc1PicParams->picture_fields.is_first_field == 1) ? false : true; CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_NULL_RETURN(m_debugInterface); m_debugInterface->m_currPic = m_crrPic; m_debugInterface->m_secondField = m_secondField; m_debugInterface->m_frameType = m_perfType; if (m_vc1PicParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpPicParams( m_vc1PicParams)); } if (m_vc1SliceParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpSliceParams( m_vc1SliceParams)); } if (m_vc1MbParams) { CODECHAL_DECODE_CHK_STATUS_RETURN(DumpMbParams( m_vc1MbParams)); } if (m_deblockDataBuffer) { //Dump decode deblocking CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpData( m_deblockDataBuffer, m_decodeParams.m_deblockDataSize, CodechalDbgAttr::attrDeblocking, "_DEC")); } if (m_decodeParams.m_vc1BitplaneSize != 0) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpBuffer( &m_resBitplaneBuffer, CodechalDbgAttr::attrVc1Bitplane, "_DEC", m_decodeParams.m_vc1BitplaneSize)); }) return eStatus; } MOS_STATUS CodechalDecodeVc1::DecodeStateLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; PCODEC_REF_LIST *vc1RefList; vc1RefList = &(m_vc1RefList[0]); uint8_t destIdx = m_vc1PicParams->CurrPic.FrameIdx; uint8_t fwdRefIdx = (uint8_t)m_vc1PicParams->ForwardRefIdx; uint8_t bwdRefIdx = (uint8_t)m_vc1PicParams->BackwardRefIdx; bool isIPicture = m_mfxInterface->IsVc1IPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type) ? true : false; bool isPPicture = m_mfxInterface->IsVc1PPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type) ? true : false; bool isBPicture = m_mfxInterface->IsVc1BPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type) ? true : false; PMOS_SURFACE destSurface; PMOS_RESOURCE fwdRefSurface, bwdRefSurface; if (m_unequalFieldWaInUse && CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { destSurface = &(m_unequalFieldSurface[vc1RefList[destIdx]->dwUnequalFieldSurfaceIdx]); fwdRefSurface = &(m_unequalFieldSurface[vc1RefList[fwdRefIdx]->dwUnequalFieldSurfaceIdx].OsResource); bwdRefSurface = &(m_unequalFieldSurface[vc1RefList[bwdRefIdx]->dwUnequalFieldSurfaceIdx].OsResource); // Overwrite the actual surface height with the coded height and width of the frame // for VC1 since it's possible for a VC1 frame to change size during playback destSurface->dwWidth = m_width; destSurface->dwHeight = m_height; } else { destSurface = &m_destSurface; fwdRefSurface = &(vc1RefList[fwdRefIdx]->resRefPic); bwdRefSurface = &(vc1RefList[bwdRefIdx]->resRefPic); } // For SP/MP short format if (m_shortFormatInUse && !m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { CODECHAL_DECODE_CHK_STATUS_RETURN(ConstructBistreamBuffer()); } MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex); HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters); MHW_VDBOX_PIPE_MODE_SELECT_PARAMS pipeModeSelectParams; pipeModeSelectParams.Mode = m_mode; pipeModeSelectParams.bStreamOutEnabled = m_streamOutEnabled; pipeModeSelectParams.bPostDeblockOutEnable = m_deblockingEnabled; pipeModeSelectParams.bPreDeblockOutEnable = !m_deblockingEnabled; pipeModeSelectParams.bShortFormatInUse = m_shortFormatInUse; pipeModeSelectParams.bVC1OddFrameHeight = m_vc1OddFrameHeight; MHW_VDBOX_SURFACE_PARAMS surfaceParams; MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams)); surfaceParams.Mode = m_mode; surfaceParams.psSurface = destSurface; MHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams; pipeBufAddrParams.Mode = m_mode; if (m_deblockingEnabled) { pipeBufAddrParams.psPostDeblockSurface = destSurface; } else { pipeBufAddrParams.psPreDeblockSurface = destSurface; } #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&pipeBufAddrParams)); #endif // when there is not a forward or backward reference, // the index is set to the destination frame index m_presReferences[CodechalDecodeFwdRefTop] = m_presReferences[CodechalDecodeFwdRefBottom] = fwdRefSurface; m_presReferences[CodechalDecodeBwdRefTop] = m_presReferences[CodechalDecodeBwdRefBottom] = bwdRefSurface; // special case for second fields if (!m_vc1PicParams->picture_fields.is_first_field && !m_mfxInterface->IsVc1IPicture( m_vc1PicParams->CurrPic, m_vc1PicParams->picture_fields.is_first_field, m_vc1PicParams->picture_fields.picture_type)) { if (m_vc1PicParams->picture_fields.top_field_first) { m_presReferences[CodechalDecodeFwdRefTop] = &destSurface->OsResource; } else { m_presReferences[CodechalDecodeFwdRefBottom] = &destSurface->OsResource; } } // set all ref pic addresses to valid addresses for error concealment purpose for (uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC; i++) { if (m_presReferences[i] == nullptr && MEDIA_IS_WA(m_waTable, WaDummyReference) && !Mos_ResourceIsNull(&m_dummyReference.OsResource)) { m_presReferences[i] = &m_dummyReference.OsResource; } } CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(pipeBufAddrParams.presReferences, sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC, m_presReferences, sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC)); pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer = &m_resMfdDeblockingFilterRowStoreScratchBuffer; if (m_streamOutEnabled) { pipeBufAddrParams.presStreamOutBuffer = &(m_streamOutBuffer[m_streamOutCurrBufIdx]); } #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->CheckReferenceList(&pipeBufAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetRefrenceSync(m_disableDecodeSyncLock, m_disableLockForTranscode)); #endif CODECHAL_DEBUG_TOOL( for (int i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC; i++) { if (pipeBufAddrParams.presReferences[i]) { MOS_SURFACE dstSurface; MOS_ZeroMemory(&dstSurface, sizeof(MOS_SURFACE)); dstSurface.Format = Format_NV12; dstSurface.OsResource = *(pipeBufAddrParams.presReferences[i]); CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo( m_osInterface, &dstSurface)); m_debugInterface->m_refIndex = (uint16_t)i; std::string refSurfName = "RefSurf[" + std::to_string(static_cast(m_debugInterface->m_refIndex)) + "]"; CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface( &dstSurface, CodechalDbgAttr::attrDecodeReferenceSurfaces, refSurfName.data())); } } ) MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS indObjBaseAddrParams; MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams)); indObjBaseAddrParams.Mode = m_mode; if (m_shortFormatInUse && !m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { indObjBaseAddrParams.dwDataSize = m_dataSize + CODECHAL_DECODE_VC1_STUFFING_BYTES; indObjBaseAddrParams.presDataBuffer = &m_resPrivateBistreamBuffer; } else { indObjBaseAddrParams.dwDataSize = m_dataSize; indObjBaseAddrParams.presDataBuffer = &m_resDataBuffer; } MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS bspBufBaseAddrParams; MOS_ZeroMemory(&bspBufBaseAddrParams, sizeof(bspBufBaseAddrParams)); bspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resBsdMpcRowStoreScratchBuffer; if (m_vc1PicParams->raw_coding.bitplane_present || m_shortFormatInUse) { bspBufBaseAddrParams.presBitplaneBuffer = &m_resBitplaneBuffer; } MHW_VDBOX_VC1_PRED_PIPE_PARAMS vc1PredPipeParams; vc1PredPipeParams.pVc1PicParams = m_vc1PicParams; vc1PredPipeParams.ppVc1RefList = vc1RefList; MHW_VDBOX_VC1_PIC_STATE vc1PicState; vc1PicState.pVc1PicParams = m_vc1PicParams; vc1PicState.Mode = m_mode; vc1PicState.ppVc1RefList = vc1RefList; vc1PicState.wPrevAnchorPictureTFF = m_prevAnchorPictureTff; vc1PicState.bPrevEvenAnchorPictureIsP = m_prevEvenAnchorPictureIsP; vc1PicState.bPrevOddAnchorPictureIsP = m_prevOddAnchorPictureIsP; if (m_shortFormatInUse) { // APP does not provide REFDIST for I/P pictures correctly if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag && CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && (isIPicture || isPPicture) && m_vc1PicParams->reference_fields.reference_distance_flag) { if (m_vc1PicParams->picture_fields.is_first_field) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParsePictureHeader()); m_referenceDistance = m_vc1PicParams->reference_fields.reference_distance; } else { m_vc1PicParams->reference_fields.reference_distance = m_referenceDistance; } } // APP does not provide BFRACTION correctly. So parse picture header to get BFRACTION if (isBPicture) { if (m_vc1PicParams->picture_fields.is_first_field) { CODECHAL_DECODE_CHK_STATUS_RETURN(ParsePictureHeader()); } } } MHW_VDBOX_VC1_DIRECTMODE_PARAMS vc1DirectmodeParams; if (m_mode == CODECHAL_DECODE_MODE_VC1VLD) { uint8_t dmvBufferIdx = (m_vc1PicParams->CurrPic.PicFlags == PICTURE_BOTTOM_FIELD) ? CODECHAL_DECODE_VC1_DMV_ODD : CODECHAL_DECODE_VC1_DMV_EVEN; vc1DirectmodeParams.presDmvReadBuffer = &m_resVc1BsdMvData[dmvBufferIdx]; vc1DirectmodeParams.presDmvWriteBuffer = &m_resVc1BsdMvData[dmvBufferIdx]; } CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, !m_olpNeeded)); if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer)); } if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->picture_fields.picture_type == vc1SkippedFrame) { // no further picture level commands needed for skipped frames m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); return eStatus; } CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &surfaceParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(&cmdBuffer, &pipeBufAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams)); if (m_mode == CODECHAL_DECODE_MODE_VC1VLD) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd(&cmdBuffer, &bspBufBaseAddrParams)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxVc1PredPipeCmd(&cmdBuffer, &vc1PredPipeParams)); if (m_intelEntrypointInUse || m_mode == CODECHAL_DECODE_MODE_VC1IT) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxVc1LongPicCmd(&cmdBuffer, &vc1PicState)); } else if (m_shortFormatInUse) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1ShortPicCmd(&cmdBuffer, &vc1PicState)); } else { CODECHAL_DECODE_ASSERTMESSAGE("Unsupported decode mode."); eStatus = MOS_STATUS_UNKNOWN; return eStatus; } if (m_mode == CODECHAL_DECODE_MODE_VC1VLD) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxVc1DirectmodeCmd(&cmdBuffer, &vc1DirectmodeParams)); } m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); return eStatus; } MOS_STATUS CodechalDecodeVc1::DecodePrimitiveLevel() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; if (m_mode == CODECHAL_DECODE_MODE_VC1IT) { CODECHAL_DECODE_CHK_STATUS_RETURN(DecodePrimitiveLevelIT()); } else if (m_mode == CODECHAL_DECODE_MODE_VC1VLD) { CODECHAL_DECODE_CHK_STATUS_RETURN(DecodePrimitiveLevelVLD()) } else { return MOS_STATUS_UNKNOWN; } return eStatus; } MOS_STATUS CodechalDecodeVc1::DecodePrimitiveLevelVLD() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; MOS_SYNC_PARAMS syncParams; // static VC1 slice parameters MHW_VDBOX_VC1_SLICE_STATE vc1SliceState; vc1SliceState.presDataBuffer = &m_resDataBuffer; uint16_t frameFieldHeightInMb; CodecHal_GetFrameFieldHeightInMb( m_vc1PicParams->CurrPic, m_picHeightInMb, frameFieldHeightInMb); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->picture_fields.picture_type == vc1SkippedFrame) { CODECHAL_DECODE_CHK_STATUS_RETURN(HandleSkipFrame()); goto submit; } else { PCODEC_VC1_SLICE_PARAMS slc = m_vc1SliceParams; bool firstValidSlice = true; int prevValidSlc = 0; for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++) { m_vldSliceRecord[slcCount].dwSliceYOffset = slc->slice_vertical_position; m_vldSliceRecord[slcCount].dwNextSliceYOffset = frameFieldHeightInMb; // init to last slice int32_t length = slc->slice_data_size >> 3; int32_t offset = slc->macroblock_offset >> 3; CodechalResLock ResourceLock(m_osInterface, &m_resDataBuffer); auto buf = (uint8_t*)ResourceLock.Lock(CodechalResLock::readOnly); if (offset > 3 && buf != nullptr && m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { int i = 0; int j = 0; buf += slc->slice_data_offset; for (i = 0, j = 0; i < offset - 1; i++, j++) { if (!buf[j] && !buf[j + 1] && buf[j + 2] == 3 && buf[j + 3] < 4) { i++, j += 2; } } if (i == offset - 1) { if (!buf[j] && !buf[j + 1] && buf[j + 2] == 3 && buf[j + 3] < 4) { buf[j + 2] = 0; j++; } j++; } offset = (8 * j + slc->macroblock_offset % 8)>>3; } // Check that the slice data does not overrun the bitstream buffer size if (((uintptr_t)(slc->slice_data_offset) + length) > m_dataSize) { length = m_dataSize - (uintptr_t)(slc->slice_data_offset); if (length < 0) { length = 0; } } // Error handling for garbage data if (((uintptr_t)(slc->slice_data_offset)) > m_dataSize) { slc++; m_vldSliceRecord[slcCount].dwSkip = true; continue; } // Check offset not larger than slice length, can have slice length of 0 if (offset > length) { slc++; m_vldSliceRecord[slcCount].dwSkip = true; continue; } // Check that the slices do not overlap, else do not send the lower slice if (!firstValidSlice && (m_vldSliceRecord[slcCount].dwSliceYOffset <= m_vldSliceRecord[prevValidSlc].dwSliceYOffset)) { slc++; m_vldSliceRecord[slcCount].dwSkip = true; continue; } if (firstValidSlice) { // Ensure that the first slice starts from 0 m_vldSliceRecord[slcCount].dwSliceYOffset = 0; slc->slice_vertical_position = 0; } else { // Set next slice start Y offset of previous slice m_vldSliceRecord[prevValidSlc].dwNextSliceYOffset = m_vldSliceRecord[slcCount].dwSliceYOffset; } if (m_shortFormatInUse) { if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { if ((slc->macroblock_offset >> 3) < CODECHAL_DECODE_VC1_SC_PREFIX_LENGTH) { slc++; m_vldSliceRecord[slcCount].dwSkip = true; continue; } // set macroblock_offset of the first slice to 0 match HW expectations. if (slcCount == 0) { slc->macroblock_offset = CODECHAL_DECODE_VC1_SC_PREFIX_LENGTH << 3; } offset = CODECHAL_DECODE_VC1_SC_PREFIX_LENGTH; } else // Simple Profile or Main Profile { { offset = CODECHAL_DECODE_VC1_STUFFING_BYTES - 1; length += CODECHAL_DECODE_VC1_STUFFING_BYTES; slc->macroblock_offset += CODECHAL_DECODE_VC1_STUFFING_BYTES << 3; slc->macroblock_offset &= (~0x7); // Clear bit offset of first MB for short format } } } m_vldSliceRecord[slcCount].dwOffset = offset; m_vldSliceRecord[slcCount].dwLength = length - offset; firstValidSlice = false; prevValidSlc = slcCount; slc++; } if (m_shortFormatInUse && m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { CODECHAL_DECODE_CHK_STATUS_RETURN(GetSliceMbDataOffset()); } // Reset slc pointer slc -= m_numSlices; //------------------------------------ // Fill BSD Object Commands //------------------------------------ for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++) { if (m_vldSliceRecord[slcCount].dwSkip) { slc++; continue; } vc1SliceState.pSlc = slc; vc1SliceState.dwOffset = m_vldSliceRecord[slcCount].dwOffset; vc1SliceState.dwLength = m_vldSliceRecord[slcCount].dwLength; vc1SliceState.dwNextVerticalPosition = m_vldSliceRecord[slcCount].dwNextSliceYOffset; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1BsdObjectCmd(&cmdBuffer, &vc1SliceState)); slc++; } // Free VLD slice record MOS_ZeroMemory(m_vldSliceRecord, (m_numSlices * sizeof(CODECHAL_VC1_VLD_SLICE_RECORD))); } // Check if destination surface needs to be synchronized if (m_unequalFieldWaInUse && CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && !m_vc1PicParams->picture_fields.is_first_field) { MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams)); } else { // Check if destination surface needs to be synchronized syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_destSurface.OsResource; syncParams.bReadOnly = false; syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; syncParams.bDisableLockForTranscode = m_disableLockForTranscode; if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic) || m_vc1PicParams->picture_fields.is_first_field) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams)); // Update the resource tag (s/w tag) for On-Demand Sync m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); } MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams)); // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag if (m_osInterface->bTagResourceSync && !(CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->picture_fields.is_first_field)) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams)); } } submit: if (m_statusQueryReportingEnabled) { CodechalDecodeStatusReport decodeStatusReport; decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber; decodeStatusReport.m_currDecodedPic = m_vc1PicParams->CurrPic; if (m_olpNeeded) { CODECHAL_DEBUG_TOOL( decodeStatusReport.m_currDeblockedPic.FrameIdx = (uint8_t)m_vc1PicParams->DeblockedPicIdx; decodeStatusReport.m_currDeblockedPic.PicFlags = PICTURE_FRAME;) decodeStatusReport.m_deblockedPicResOlp = m_deblockSurface.OsResource; } else { decodeStatusReport.m_currDeblockedPic = m_vc1PicParams->CurrPic; } decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE; decodeStatusReport.m_currDecodedPicRes = m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]->resRefPic; CODECHAL_DEBUG_TOOL( decodeStatusReport.m_secondField = (m_vc1PicParams->picture_fields.is_first_field == 1) ? false : true; decodeStatusReport.m_olpNeeded = m_olpNeeded; decodeStatusReport.m_frameType = m_perfType;) CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(decodeStatusReport, &cmdBuffer)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, CODECHAL_NUM_MEDIA_STATES, "_DEC")); //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands( // m_debugInterface, // &cmdBuffer)); ) if (m_huCCopyInUse) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContextForWa; syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); m_huCCopyInUse = false; } HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw)); CODECHAL_DEBUG_TOOL( m_mmc->UpdateUserFeatureKey(&m_destSurface);) if (m_unequalFieldWaInUse && CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && !m_vc1PicParams->picture_fields.is_first_field) { CODECHAL_DECODE_CHK_NULL_RETURN(m_vc1RefList); uint32_t destFrameIdx = m_vc1PicParams->CurrPic.FrameIdx; CODECHAL_DECODE_CHK_STATUS_RETURN(FormatUnequalFieldPicture( m_unequalFieldSurface[m_vc1RefList[destFrameIdx]->dwUnequalFieldSurfaceIdx], m_destSurface, true, m_videoContextUsesNullHw)); } if (m_olpNeeded) { CODECHAL_DECODE_CHK_STATUS_RETURN(PerformVc1Olp()); } else { if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_videoContextUsesNullHw)); } } // Needs to be re-set for Linux buffer re-use scenarios m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]->resRefPic = m_destSurface.OsResource; // Send the signal to indicate decode completion, in case On-Demand Sync is not present if (!(CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->picture_fields.is_first_field)) { MOS_SYNC_PARAMS syncParams; syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_destSurface.OsResource; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); if (m_olpNeeded) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_renderContext; syncParams.presSyncResource = &m_deblockSurface.OsResource; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); } } m_olpNeeded = false; return eStatus; } MOS_STATUS CodechalDecodeVc1::DecodePrimitiveLevelIT() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; MOS_SYNC_PARAMS syncParams; PCODEC_VC1_MB_PARAMS mb = m_vc1MbParams; MHW_VDBOX_VC1_MB_STATE vc1MbState; MOS_ZeroMemory(&vc1MbState, sizeof(vc1MbState)); // static VC1 MB parameters vc1MbState.presDataBuffer = &m_resDataBuffer; vc1MbState.pVc1PicParams = m_vc1PicParams; vc1MbState.pWaTable = m_waTable; vc1MbState.pDeblockDataBuffer = m_deblockDataBuffer; vc1MbState.dwDataSize = m_dataSize; vc1MbState.wPicWidthInMb = m_picWidthInMb; vc1MbState.wPicHeightInMb = m_picHeightInMb; vc1MbState.PicFlags = m_vc1PicParams->CurrPic.PicFlags; vc1MbState.bFieldPolarity = m_fieldPolarity; uint16_t frameFieldHeightInMb; CodecHal_GetFrameFieldHeightInMb( m_vc1PicParams->CurrPic, m_picHeightInMb, frameFieldHeightInMb); MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(&cmdBuffer, &m_itObjectBatchBuffer)); CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_LockBb(m_osInterface, &m_itObjectBatchBuffer)); PMHW_BATCH_BUFFER batchBuffer = &m_itObjectBatchBuffer; uint32_t mbAddress = 0; uint32_t mbCount; for (mbCount = 0; mbCount < m_numMacroblocks; mbCount++) { vc1MbState.pMb = mb + mbCount; // Skipped MBs before current MB uint16_t skippedMBs = (mbCount) ? (mb[mbCount].mb_address - mb[mbCount - 1].mb_address - 1) : (mb[mbCount].mb_address); while (skippedMBs--) { vc1MbState.bMbHorizOrigin = (uint8_t)(mbAddress % m_picWidthInMb); vc1MbState.bMbVertOrigin = (uint8_t)(mbAddress / m_picWidthInMb); vc1MbState.bSkipped = true; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1ItObjectCmd(batchBuffer, &vc1MbState)); mbAddress++; } // Current MB if (mbCount + 1 == m_numMacroblocks) { vc1MbState.dwLength = m_dataSize - mb[mbCount].data_offset; } else { vc1MbState.dwLength = mb[mbCount + 1].data_offset - mb[mbCount].data_offset; } vc1MbState.bMbHorizOrigin = mb[mbCount].mb_address % m_picWidthInMb; vc1MbState.bMbVertOrigin = mb[mbCount].mb_address / m_picWidthInMb; vc1MbState.dwOffset = (vc1MbState.dwLength) ? mb[mbCount].data_offset : 0; vc1MbState.bSkipped = false; if (m_vc1PicParams->entrypoint_fields.loopfilter) { eStatus = MOS_SecureMemcpy(vc1MbState.DeblockData, CODEC_NUM_BLOCK_PER_MB, m_deblockDataBuffer + CODEC_NUM_BLOCK_PER_MB * mb[mbCount].mb_address, CODEC_NUM_BLOCK_PER_MB); if (eStatus != MOS_STATUS_SUCCESS) { CODECHAL_DECODE_ASSERTMESSAGE("Failed to copy memory."); m_olpNeeded = false; return eStatus; } } if (!mb[mbCount].mb_type.intra_mb) { if (mb[mbCount].mb_type.motion_forward || mb[mbCount].mb_type.motion_backward) { PackMotionVectors( &vc1MbState, (int16_t *)mb[mbCount].motion_vector, (int16_t *)vc1MbState.PackedLumaMvs, (int16_t *)&vc1MbState.PackedChromaMv); } else { mb[mbCount].mb_type.motion_forward = 1; MOS_ZeroMemory(vc1MbState.PackedLumaMvs, sizeof(vc1MbState.PackedLumaMvs)); // MV's of zero vc1MbState.bMotionSwitch = 0; } } CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1ItObjectCmd(batchBuffer, &vc1MbState)); mbAddress = mb[mbCount].mb_address; } m_fieldPolarity = vc1MbState.bFieldPolarity; // skipped MBs at the end uint16_t skippedMBs = m_picWidthInMb * frameFieldHeightInMb - mb[mbCount - 1].mb_address - 1; while (skippedMBs--) { vc1MbState.bSkipped = true; CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1ItObjectCmd(batchBuffer, &vc1MbState)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(nullptr, &m_itObjectBatchBuffer)); CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->Dump2ndLvlBatch( batchBuffer, CODECHAL_NUM_MEDIA_STATES, "_DEC")); ) CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_UnlockBb(m_osInterface, &m_itObjectBatchBuffer, true)); // Check if destination surface needs to be synchronized if (m_unequalFieldWaInUse && CodecHal_PictureIsField(m_vc1PicParams->CurrPic)) { if (!m_vc1PicParams->picture_fields.is_first_field) { MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams)); } } else { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_destSurface.OsResource; syncParams.bReadOnly = false; syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; syncParams.bDisableLockForTranscode = m_disableLockForTranscode; if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic) || m_vc1PicParams->picture_fields.is_first_field) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams)); // Update the resource tag (s/w tag) for On-Demand Sync m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); } MHW_MI_FLUSH_DW_PARAMS flushDwParams; MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams)); // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag if (m_osInterface->bTagResourceSync && !(CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->picture_fields.is_first_field)) { CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams)); } } if (m_statusQueryReportingEnabled) { CodechalDecodeStatusReport decodeStatusReport; decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber; decodeStatusReport.m_currDecodedPic = m_vc1PicParams->CurrPic; if (m_olpNeeded) { CODECHAL_DEBUG_TOOL( decodeStatusReport.m_currDeblockedPic.FrameIdx = (uint8_t)m_vc1PicParams->DeblockedPicIdx; decodeStatusReport.m_currDeblockedPic.PicFlags = PICTURE_FRAME;) decodeStatusReport.m_deblockedPicResOlp = m_deblockSurface.OsResource; } else { decodeStatusReport.m_currDeblockedPic = m_vc1PicParams->CurrPic; } decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE; decodeStatusReport.m_currDecodedPicRes = m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]->resRefPic; CODECHAL_DEBUG_TOOL( decodeStatusReport.m_secondField = (m_vc1PicParams->picture_fields.is_first_field == 1) ? false : true; decodeStatusReport.m_olpNeeded = m_olpNeeded; decodeStatusReport.m_frameType = m_perfType;) CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(decodeStatusReport, &cmdBuffer)); } CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, CODECHAL_NUM_MEDIA_STATES, "_DEC")); //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands( // m_debugInterface, // &cmdBuffer)); ) if (m_huCCopyInUse) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContextForWa; syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObjectWaContextInUse; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); m_huCCopyInUse = false; } HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw)); CODECHAL_DEBUG_TOOL( m_mmc->UpdateUserFeatureKey(&m_destSurface);) if (m_unequalFieldWaInUse && CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && !m_vc1PicParams->picture_fields.is_first_field) { CODECHAL_DECODE_CHK_NULL_RETURN(m_vc1RefList); uint32_t destFrameIdx = m_vc1PicParams->CurrPic.FrameIdx; CODECHAL_DECODE_CHK_STATUS_RETURN(FormatUnequalFieldPicture( m_unequalFieldSurface[m_vc1RefList[destFrameIdx]->dwUnequalFieldSurfaceIdx], m_destSurface, true, m_videoContextUsesNullHw)); } if (m_olpNeeded) { CODECHAL_DECODE_CHK_STATUS_RETURN(PerformVc1Olp()); } else { if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_videoContextUsesNullHw)); } } // Needs to be re-set for Linux buffer re-use scenarios m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]->resRefPic = m_destSurface.OsResource; // Send the signal to indicate decode completion, in case On-Demand Sync is not present if (!(CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->picture_fields.is_first_field)) { MOS_SYNC_PARAMS syncParams; syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_destSurface.OsResource; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); if (m_olpNeeded) { syncParams = g_cInitSyncParams; syncParams.GpuContext = m_renderContext; syncParams.presSyncResource = &m_deblockSurface.OsResource; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams)); } } m_olpNeeded = false; return eStatus; } MOS_STATUS CodechalDecodeVc1::AddVc1OlpCmd( PCODECHAL_DECODE_VC1_OLP_PARAMS vc1OlpParams) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; MhwRenderInterface *renderEngineInterface = m_hwInterface->GetRenderInterface(); PMHW_KERNEL_STATE kernelState = &m_olpKernelState; // Launch media walker to handle Y component CODECHAL_WALKER_CODEC_PARAMS walkerCodecParams; MOS_ZeroMemory(&walkerCodecParams, sizeof(walkerCodecParams)); walkerCodecParams.WalkerMode = MHW_WALKER_MODE_SINGLE; walkerCodecParams.dwResolutionX = m_picWidthInMb; walkerCodecParams.dwResolutionY = m_picHeightInMb; walkerCodecParams.bNoDependency = true; // force raster scan mode MHW_WALKER_PARAMS walkerParams; CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalInitMediaObjectWalkerParams( m_hwInterface, &walkerParams, &walkerCodecParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaObjectWalkerCmd( vc1OlpParams->pCmdBuffer, &walkerParams)); vc1OlpParams->pPipeControlParams->dwFlushMode = MHW_FLUSH_READ_CACHE; CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl( vc1OlpParams->pCmdBuffer, nullptr, vc1OlpParams->pPipeControlParams)); vc1OlpParams->pPipeControlParams->dwFlushMode = MHW_FLUSH_WRITE_CACHE; CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl( vc1OlpParams->pCmdBuffer, nullptr, vc1OlpParams->pPipeControlParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddStateBaseAddrCmd( vc1OlpParams->pCmdBuffer, vc1OlpParams->pStateBaseAddrParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaVfeCmd( vc1OlpParams->pCmdBuffer, vc1OlpParams->pVfeParams)); kernelState->dwCurbeOffset += kernelState->KernelParams.iCurbeLength; CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaCurbeLoadCmd( vc1OlpParams->pCmdBuffer, vc1OlpParams->pCurbeLoadParams)); kernelState->dwCurbeOffset -= kernelState->KernelParams.iCurbeLength; CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaIDLoadCmd( vc1OlpParams->pCmdBuffer, vc1OlpParams->pIdLoadParams)); // For UV component, block size changed in CURBE static data and keep FrameWidth/HeightInMb unchanged here CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaObjectWalkerCmd( vc1OlpParams->pCmdBuffer, &walkerParams)); return eStatus; } MOS_STATUS CodechalDecodeVc1::PerformVc1Olp() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; MhwRenderInterface *renderEngineInterface = m_hwInterface->GetRenderInterface(); PMHW_KERNEL_STATE kernelState = &m_olpKernelState; PMHW_STATE_HEAP_INTERFACE stateHeapInterface = renderEngineInterface->m_stateHeapInterface; CODECHAL_DECODE_CHK_NULL_RETURN(stateHeapInterface); MOS_SYNC_PARAMS syncParams; syncParams = g_cInitSyncParams; syncParams.GpuContext = m_videoContext; syncParams.presSyncResource = &m_resSyncObject; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams)); syncParams = g_cInitSyncParams; syncParams.GpuContext = m_renderContext; syncParams.presSyncResource = &m_resSyncObject; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams)); // Initialize DSH kernel region m_osInterface->pfnSetGpuContext(m_osInterface, m_renderContext); m_osInterface->pfnResetOsStates(m_osInterface); m_osInterface->pfnSetPerfTag( m_osInterface, (uint16_t)(((m_mode << 4) & 0xF0) | OLP_TYPE)); m_osInterface->pfnResetPerfBufferID(m_osInterface); CodecHalGetResourceInfo(m_osInterface, &m_deblockSurface); // DstSurface #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->DisableSurfaceMmcState(&m_deblockSurface)); #endif CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnRequestSshSpaceForCmdBuf( stateHeapInterface, kernelState->KernelParams.iBTCount)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace( stateHeapInterface, kernelState, false, m_olpDshSize, false, m_decodeStatusBuf.m_swStoreData)); MHW_INTERFACE_DESCRIPTOR_PARAMS idParams; MOS_ZeroMemory(&idParams, sizeof(idParams)); idParams.pKernelState = kernelState; CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSetInterfaceDescriptor( stateHeapInterface, 1, &idParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(SetCurbeOlp()); // Send HW commands (including SSH) MOS_COMMAND_BUFFER cmdBuffer; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0)); MHW_PIPE_CONTROL_PARAMS pipeControlParams; MOS_ZeroMemory(&pipeControlParams, sizeof(pipeControlParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetDefaultSSEuSetting(CODECHAL_MEDIA_STATE_OLP, false, false, false)); CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking( &cmdBuffer, true)); if (renderEngineInterface->GetL3CacheConfig()->bL3CachingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->SetL3Cache(&cmdBuffer)); } CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->EnablePreemption(&cmdBuffer)); CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddPipelineSelectCmd(&cmdBuffer, false)); CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSetBindingTable( stateHeapInterface, kernelState)); // common function for codec needed when we make change for AVC MHW_RCS_SURFACE_PARAMS surfaceParamsSrc; MOS_ZeroMemory(&surfaceParamsSrc, sizeof(surfaceParamsSrc)); surfaceParamsSrc.dwNumPlanes = 2; // Y, UV surfaceParamsSrc.psSurface = &m_destSurface; surfaceParamsSrc.psSurface->dwDepth = 1; // depth needs to be 0 for codec 2D surface // Y Plane surfaceParamsSrc.dwBindingTableOffset[MHW_Y_PLANE] = CODECHAL_DECODE_VC1_OLP_SRC_Y; surfaceParamsSrc.ForceSurfaceFormat[MHW_Y_PLANE] = MHW_GFX3DSTATE_SURFACEFORMAT_R8_UNORM; // UV Plane surfaceParamsSrc.dwBindingTableOffset[MHW_U_PLANE] = CODECHAL_DECODE_VC1_OLP_SRC_UV; surfaceParamsSrc.ForceSurfaceFormat[MHW_U_PLANE] = MHW_GFX3DSTATE_SURFACEFORMAT_R16_UINT; surfaceParamsSrc.dwBaseAddrOffset[MHW_U_PLANE] = m_destSurface.dwPitch * MOS_ALIGN_FLOOR(m_destSurface.UPlaneOffset.iYOffset, MOS_YTILE_H_ALIGNMENT); surfaceParamsSrc.dwHeightToUse[MHW_U_PLANE] = surfaceParamsSrc.psSurface->dwHeight / 2; surfaceParamsSrc.dwYOffset[MHW_U_PLANE] = (m_destSurface.UPlaneOffset.iYOffset % MOS_YTILE_H_ALIGNMENT); #ifdef _MMC_SUPPORTED CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->GetSurfaceMmcState(surfaceParamsSrc.psSurface)); #endif MHW_RCS_SURFACE_PARAMS surfaceParamsDst; MOS_ZeroMemory(&surfaceParamsDst, sizeof(surfaceParamsDst)); surfaceParamsDst = surfaceParamsSrc; surfaceParamsDst.bIsWritable = true; surfaceParamsDst.psSurface = &m_deblockSurface; surfaceParamsDst.psSurface->dwDepth = 1; // depth needs to be 0 for codec 2D surface surfaceParamsDst.dwBindingTableOffset[MHW_Y_PLANE] = CODECHAL_DECODE_VC1_OLP_DST_Y; surfaceParamsDst.dwBindingTableOffset[MHW_U_PLANE] = CODECHAL_DECODE_VC1_OLP_DST_UV; CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSetSurfaceState( stateHeapInterface, kernelState, &cmdBuffer, 1, &surfaceParamsSrc)); CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSetSurfaceState( stateHeapInterface, kernelState, &cmdBuffer, 1, &surfaceParamsDst)); MHW_STATE_BASE_ADDR_PARAMS stateBaseAddrParams; MOS_ZeroMemory(&stateBaseAddrParams, sizeof(stateBaseAddrParams)); MOS_RESOURCE *dsh = nullptr, *ish = nullptr; CODECHAL_DECODE_CHK_NULL_RETURN(dsh = kernelState->m_dshRegion.GetResource()); CODECHAL_DECODE_CHK_NULL_RETURN(ish = kernelState->m_ishRegion.GetResource()); stateBaseAddrParams.presDynamicState = dsh; stateBaseAddrParams.dwDynamicStateSize = kernelState->m_dshRegion.GetHeapSize(); stateBaseAddrParams.presInstructionBuffer = ish; stateBaseAddrParams.dwInstructionBufferSize = kernelState->m_ishRegion.GetHeapSize(); CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddStateBaseAddrCmd(&cmdBuffer, &stateBaseAddrParams)); MHW_VFE_PARAMS vfeParams = {}; vfeParams.pKernelState = kernelState; CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaVfeCmd(&cmdBuffer, &vfeParams)); MHW_CURBE_LOAD_PARAMS curbeLoadParams; MOS_ZeroMemory(&curbeLoadParams, sizeof(curbeLoadParams)); curbeLoadParams.pKernelState = kernelState; CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaCurbeLoadCmd(&cmdBuffer, &curbeLoadParams)); MHW_ID_LOAD_PARAMS idLoadParams; MOS_ZeroMemory(&idLoadParams, sizeof(idLoadParams)); idLoadParams.pKernelState = kernelState; idLoadParams.dwNumKernelsLoaded = 1; CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaIDLoadCmd(&cmdBuffer, &idLoadParams)); CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( CODECHAL_MEDIA_STATE_OLP, MHW_DSH_TYPE, kernelState)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( CODECHAL_MEDIA_STATE_OLP, MHW_SSH_TYPE, kernelState)); ) CODECHAL_DECODE_VC1_OLP_PARAMS vc1OlpParams; vc1OlpParams.pCmdBuffer = &cmdBuffer; vc1OlpParams.pPipeControlParams = &pipeControlParams; vc1OlpParams.pStateBaseAddrParams = &stateBaseAddrParams; vc1OlpParams.pVfeParams = &vfeParams; vc1OlpParams.pCurbeLoadParams = &curbeLoadParams; vc1OlpParams.pIdLoadParams = &idLoadParams; CODECHAL_DECODE_CHK_STATUS_RETURN(AddVc1OlpCmd(&vc1OlpParams)); // Check if destination surface needs to be synchronized, before command buffer submission syncParams = g_cInitSyncParams; syncParams.GpuContext = m_renderContext; syncParams.presSyncResource = &m_deblockSurface.OsResource; syncParams.bReadOnly = false; syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock; syncParams.bDisableLockForTranscode = m_disableLockForTranscode; CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams)); // Update the resource tag (s/w tag) for On-Demand Sync m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams); // Update GPU Sync tag for on demand synchronization if (m_osInterface->bTagResourceSync) { pipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE; CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl(&cmdBuffer, nullptr, &pipeControlParams)); CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams)); } CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSubmitBlocks( stateHeapInterface, kernelState)); CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnUpdateGlobalCmdBufId( stateHeapInterface)); // Add PipeControl to invalidate ISP and MediaState to avoid PageFault issue // This code is temporal and it will be moved to batch buffer end in short if (GFX_IS_GEN_9_OR_LATER(m_hwInterface->GetPlatform())) { MHW_PIPE_CONTROL_PARAMS pipeControlParams; MOS_ZeroMemory(&pipeControlParams, sizeof(pipeControlParams)); pipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE; pipeControlParams.bGenericMediaStateClear = true; pipeControlParams.bIndirectStatePointersDisable = true; pipeControlParams.bDisableCSStall = false; CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl(&cmdBuffer, nullptr, &pipeControlParams)); if (MEDIA_IS_WA(m_hwInterface->GetWaTable(), WaSendDummyVFEafterPipelineSelect)) { MHW_VFE_PARAMS vfeStateParams = {}; vfeStateParams.dwNumberofURBEntries = 1; CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaVfeCmd(&cmdBuffer, &vfeStateParams)); } } CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr)); // To clear the SSEU values in the hw interface struct, so next kernel can be programmed correctly CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, false, true)); m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0); CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer( &cmdBuffer, CODECHAL_MEDIA_STATE_OLP, "_DEC")); ) CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw)); if (m_statusQueryReportingEnabled) { CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_renderContextUsesNullHw)); } m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext); return eStatus; } MOS_STATUS CodechalDecodeVc1::UpdateVc1KernelState() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; PMHW_STATE_HEAP_INTERFACE stateHeapInterface = m_hwInterface->GetRenderInterface()->m_stateHeapInterface; PCODECHAL_DECODE_VC1_KERNEL_HEADER_CM decodeKernel; PMHW_KERNEL_STATE kernelState = &m_olpKernelState; decodeKernel = (PCODECHAL_DECODE_VC1_KERNEL_HEADER_CM)kernelState->KernelParams.pBinary; CODECHAL_DECODE_CHK_NULL_RETURN(decodeKernel); kernelState->dwKernelBinaryOffset = decodeKernel->OLP.KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT; m_olpDshSize = stateHeapInterface->pStateHeapInterface->GetSizeofCmdInterfaceDescriptorData() + (MOS_ALIGN_CEIL(m_olpCurbeStaticDataLength, stateHeapInterface->pStateHeapInterface->GetCurbeAlignment()) * 2); return eStatus; } MOS_STATUS CodechalDecodeVc1::InitKernelStateVc1Olp() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; MhwRenderInterface *renderEngineInterface = m_hwInterface->GetRenderInterface(); PMHW_STATE_HEAP_INTERFACE stateHeapInterface = renderEngineInterface->m_stateHeapInterface; CODECHAL_DECODE_CHK_NULL_RETURN(stateHeapInterface); PMHW_KERNEL_STATE kernelState = &m_olpKernelState; kernelState->KernelParams.pBinary = m_olpKernelBase; kernelState->KernelParams.iSize = m_olpKernelSize; kernelState->KernelParams.iBTCount = CODECHAL_DECODE_VC1_OLP_NUM_SURFACES; kernelState->KernelParams.iThreadCount = renderEngineInterface->GetHwCaps()->dwMaxThreads; kernelState->KernelParams.iCurbeLength = m_olpCurbeStaticDataLength; kernelState->KernelParams.iBlockWidth = CODECHAL_MACROBLOCK_WIDTH; kernelState->KernelParams.iBlockHeight = CODECHAL_MACROBLOCK_HEIGHT; kernelState->KernelParams.iIdCount = 1; kernelState->dwCurbeOffset = stateHeapInterface->pStateHeapInterface->GetSizeofCmdInterfaceDescriptorData(); CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnCalculateSshAndBtSizesRequested( stateHeapInterface, kernelState->KernelParams.iBTCount, &kernelState->dwSshSize, &kernelState->dwBindingTableSize)); CODECHAL_DECODE_CHK_STATUS_RETURN(UpdateVc1KernelState()); CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->MhwInitISH( stateHeapInterface, &m_olpKernelState)); return eStatus; } MOS_STATUS CodechalDecodeVc1::SetCurbeOlp() { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(m_hwInterface->GetRenderInterface()); CODECHAL_DECODE_CHK_NULL_RETURN(m_hwInterface->GetRenderInterface()->m_stateHeapInterface); PMHW_STATE_HEAP_INTERFACE stateHeapInterface = m_hwInterface->GetRenderInterface()->m_stateHeapInterface; // Configure Curbe data for Y component CODECHAL_DECODE_VC1_OLP_STATIC_DATA cmd = g_cInit_CODECHAL_DECODE_VC1_OLP_STATIC_DATA; cmd.DW2.InterlaceFieldFlag = CodecHal_PictureIsField(m_vc1PicParams->CurrPic); cmd.DW2.PictureUpsamplingFlag = m_vc1PicParams->UpsamplingFlag; cmd.DW2.RangeExpansionFlag = (m_vc1PicParams->range_mapping_fields.range_mapping_enabled != 0); cmd.DW2.Profile = m_vc1PicParams->sequence_fields.AdvancedProfileFlag; cmd.DW2.ComponentFlag = 0; if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { cmd.DW2.RangeMapUV = m_vc1PicParams->range_mapping_fields.chroma; cmd.DW2.RangeMapUVFlag = m_vc1PicParams->range_mapping_fields.chroma_flag; cmd.DW2.RangeMapY = m_vc1PicParams->range_mapping_fields.luma; cmd.DW2.RangeMapYFlag = m_vc1PicParams->range_mapping_fields.luma_flag; } CODECHAL_DECODE_CHK_STATUS_RETURN(m_olpKernelState.m_dshRegion.AddData( &cmd, m_olpKernelState.dwCurbeOffset, sizeof(cmd))); // Configure Curbe data for UV component cmd = g_cInit_CODECHAL_DECODE_VC1_OLP_STATIC_DATA; cmd.DW2.InterlaceFieldFlag = CodecHal_PictureIsField(m_vc1PicParams->CurrPic); cmd.DW2.PictureUpsamplingFlag = m_vc1PicParams->UpsamplingFlag; cmd.DW2.RangeExpansionFlag = (m_vc1PicParams->range_mapping_fields.range_mapping_enabled != 0); cmd.DW2.Profile = m_vc1PicParams->sequence_fields.AdvancedProfileFlag; cmd.DW2.ComponentFlag = 1; if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag) { cmd.DW2.RangeMapUV = m_vc1PicParams->range_mapping_fields.chroma; cmd.DW2.RangeMapUVFlag = m_vc1PicParams->range_mapping_fields.chroma_flag; cmd.DW2.RangeMapY = m_vc1PicParams->range_mapping_fields.luma; cmd.DW2.RangeMapYFlag = m_vc1PicParams->range_mapping_fields.luma_flag; } cmd.DW4.SourceDataBindingIndex = CODECHAL_DECODE_VC1_OLP_SRC_UV; cmd.DW5.DestDataBindingIndex = CODECHAL_DECODE_VC1_OLP_DST_UV; CODECHAL_DECODE_CHK_STATUS_RETURN(m_olpKernelState.m_dshRegion.AddData( &cmd, m_olpKernelState.dwCurbeOffset + MOS_ALIGN_CEIL(m_olpCurbeStaticDataLength, stateHeapInterface->pStateHeapInterface->GetCurbeAlignment()), sizeof(cmd))); return eStatus; } MOS_STATUS CodechalDecodeVc1::InitMmcState() { #ifdef _MMC_SUPPORTED m_mmc = MOS_New(CodechalMmcDecodeVc1, m_hwInterface, this); CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc); #endif return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVc1::AllocateStandard( CodechalSetting *settings) { MOS_STATUS eStatus = MOS_STATUS_SUCCESS; CODECHAL_DECODE_FUNCTION_ENTER; CODECHAL_DECODE_CHK_NULL_RETURN(settings); CODECHAL_DECODE_CHK_STATUS_RETURN(InitMmcState()); bool isComputeContextEnabled = false; MOS_GPUCTX_CREATOPTIONS createOption; #if (_DEBUG || _RELEASE_INTERNAL) MOS_USER_FEATURE_VALUE_DATA userFeatureData; MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData)); MOS_UserFeature_ReadValue_ID( nullptr, __MEDIA_USER_FEATURE_VALUE_DECODE_ENABLE_COMPUTE_CONTEXT_ID, &userFeatureData, m_osInterface->pOsContext); isComputeContextEnabled = (userFeatureData.u32Data) ? true : false; #endif if (!MEDIA_IS_SKU(m_skuTable, FtrCCSNode)) { isComputeContextEnabled = false; } if (isComputeContextEnabled) { // Create Render Context for field scaling CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext( m_osInterface, MOS_GPU_CONTEXT_COMPUTE, MOS_GPU_NODE_COMPUTE, &createOption)); m_renderContext = MOS_GPU_CONTEXT_COMPUTE; } else { // Create Render Context for field scaling CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext( m_osInterface, MOS_GPU_CONTEXT_RENDER, MOS_GPU_NODE_3D, &createOption)); m_renderContext = MOS_GPU_CONTEXT_RENDER; } m_intelEntrypointInUse = settings->intelEntrypointInUse; m_width = settings->width; m_height = settings->height; m_picWidthInMb = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_width); m_picHeightInMb = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_height); m_shortFormatInUse = settings->shortFormatInUse; m_huCCopyInUse = false; CODECHAL_DECODE_CHK_STATUS_RETURN(InitKernelStateVc1Olp()); CODECHAL_DEBUG_TOOL( CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion( CODECHAL_MEDIA_STATE_OLP, MHW_ISH_TYPE, &m_olpKernelState));) // Picture Level Commands m_hwInterface->GetMfxStateCommandsDataSize( m_mode, &m_commandBufferSizeNeeded, &m_commandPatchListSizeNeeded, m_shortFormatInUse); // Primitive Level Commands m_hwInterface->GetMfxPrimitiveCommandsDataSize( m_mode, &m_standardDecodeSizeNeeded, &m_standardDecodePatchListSizeNeeded, m_shortFormatInUse); CODECHAL_DECODE_CHK_STATUS_RETURN(AllocateResources()); return eStatus; } CodechalDecodeVc1::CodechalDecodeVc1( CodechalHwInterface *hwInterface, CodechalDebugInterface* debugInterface, PCODECHAL_STANDARD_INFO standardInfo) : CodechalDecode(hwInterface, debugInterface, standardInfo), m_huCCopyInUse(0) { CODECHAL_DECODE_FUNCTION_ENTER; MOS_ZeroMemory(&m_resMfdDeblockingFilterRowStoreScratchBuffer, sizeof(m_resMfdDeblockingFilterRowStoreScratchBuffer)); MOS_ZeroMemory(&m_resBsdMpcRowStoreScratchBuffer, sizeof(m_resBsdMpcRowStoreScratchBuffer)); MOS_ZeroMemory(m_resVc1BsdMvData, sizeof(m_resVc1BsdMvData)); MOS_ZeroMemory(&m_resSyncObject, sizeof(m_resSyncObject)); MOS_ZeroMemory(&m_resPrivateBistreamBuffer, sizeof(m_resPrivateBistreamBuffer)); MOS_ZeroMemory(&m_bitstream, sizeof(m_bitstream)); MOS_ZeroMemory(&m_itObjectBatchBuffer, sizeof(m_itObjectBatchBuffer)); MOS_ZeroMemory(m_unequalFieldSurface, sizeof(m_unequalFieldSurface)); MOS_ZeroMemory(m_unequalFieldRefListIdx, sizeof(m_unequalFieldRefListIdx)); MOS_ZeroMemory(&m_destSurface, sizeof(m_destSurface)); MOS_ZeroMemory(&m_deblockSurface, sizeof(m_deblockSurface)); MOS_ZeroMemory(&m_resDataBuffer, sizeof(m_resDataBuffer)); MOS_ZeroMemory(&m_resBitplaneBuffer, sizeof(m_resBitplaneBuffer)); MOS_ZeroMemory(&m_resSyncObjectWaContextInUse, sizeof(m_resSyncObjectWaContextInUse)); MOS_ZeroMemory(&m_resSyncObjectVideoContextInUse, sizeof(m_resSyncObjectVideoContextInUse)); MOS_ZeroMemory(m_presReferences, (sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC)); MOS_ZeroMemory(m_vc1RefList, (sizeof(PCODEC_REF_LIST) * CODECHAL_NUM_UNCOMPRESSED_SURFACE_VC1)); #if (_DEBUG || _RELEASE_INTERNAL) m_reportFrameCrc = true; #endif m_hwInterface = hwInterface; } #if USE_CODECHAL_DEBUG_TOOL MOS_STATUS CodechalDecodeVc1::DumpPicParams( PCODEC_VC1_PIC_PARAMS vc1PicParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrPicParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(vc1PicParams); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss.setf(std::ios::hex, std::ios::basefield); oss<< "CurrPic FrameIdx: "<< +vc1PicParams->CurrPic.FrameIdx<CurrPic.PicFlags<DeblockedPicIdx<ForwardRefIdx<BackwardRefIdx<sequence_fields.value<sequence_fields.pulldown<sequence_fields.interlace<sequence_fields.tfcntrflag<sequence_fields.finterpflag<sequence_fields.psf<sequence_fields.multires<sequence_fields.overlap<sequence_fields.syncmarker<sequence_fields.rangered<sequence_fields.max_b_frames<sequence_fields.AdvancedProfileFlag<coded_width<coded_height<entrypoint_fields.broken_link<entrypoint_fields.closed_entry<entrypoint_fields.panscan_flag<entrypoint_fields.loopfilter<conditional_overlap_flag<fast_uvmc_flag<range_mapping_fields.range_mapping_enabled<range_mapping_fields.luma_flag<range_mapping_fields.luma<range_mapping_fields.chroma_flag<range_mapping_fields.chroma<UpsamplingFlag<ScaleFactor<b_picture_fraction<cbp_table<mb_mode_table<range_reduction_frame<rounding_control<post_processing<picture_resolution_index<luma_scale<luma_shift<picture_fields.value<picture_fields.picture_type<picture_fields.frame_coding_mode<picture_fields.top_field_first<picture_fields.is_first_field<picture_fields.intensity_compensation<raw_coding.value<raw_coding.bitplane_present<raw_coding.mv_type_mb<raw_coding.direct_mb<raw_coding.skip_mb<raw_coding.field_tx<raw_coding.forward_mb<raw_coding.ac_pred<raw_coding.overflags<reference_fields.value<reference_fields.reference_distance_flag<reference_fields.reference_distance<reference_fields.BwdReferenceDistance<reference_fields.num_reference_pictures<reference_fields.reference_field_pic_indicator<mv_fields.value<mv_fields.MvMode<mv_fields.UnifiedMvMode<mv_fields.mv_table<mv_fields.two_mv_block_pattern_table<mv_fields.four_mv_switch<mv_fields.four_mv_block_pattern_table<mv_fields.extended_mv_flag<mv_fields.extended_mv_range<mv_fields.extended_dmv_flag<mv_fields.extended_dmv_range<pic_quantizer_fields.value<pic_quantizer_fields.dquant<pic_quantizer_fields.quantizer<pic_quantizer_fields.half_qp<pic_quantizer_fields.AltPQuantEdgeMask<pic_quantizer_fields.AltPQuantConfig<pic_quantizer_fields.pic_quantizer_scale<pic_quantizer_fields.pic_quantizer_type<pic_quantizer_fields.alt_pic_quantizer<transform_fields.value<transform_fields.variable_sized_transform_flag<transform_fields.mb_level_transform_type_flag<transform_fields.frame_level_transform_type<transform_fields.transform_ac_codingset_idx1<transform_fields.transform_ac_codingset_idx2<transform_fields.intra_transform_dc_table<StatusReportFeedbackNumber<CreateFileName( "_DEC", CodechalDbgBufferType::bufPicParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVc1::DumpSliceParams( PCODEC_VC1_SLICE_PARAMS sliceControl) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrSlcParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(sliceControl); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss.setf(std::ios::hex, std::ios::basefield); oss<< "slice_data_size: "<< +sliceControl->slice_data_size<slice_data_offset<macroblock_offset<slice_vertical_position<CreateFileName( "_DEC", CodechalDbgBufferType::bufSlcParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } MOS_STATUS CodechalDecodeVc1::DumpMbParams( PCODEC_VC1_MB_PARAMS mbParams) { CODECHAL_DEBUG_FUNCTION_ENTER; if (!m_debugInterface->DumpIsEnabled(CodechalDbgAttr::attrMbParams)) { return MOS_STATUS_SUCCESS; } CODECHAL_DEBUG_CHK_NULL(mbParams); std::ostringstream oss; oss.setf(std::ios::showbase | std::ios::uppercase); oss.setf(std::ios::hex, std::ios::basefield); oss<< "mb_address: "<< +mbParams->mb_address<mb_skips_following<data_offset<data_length<num_coef[i]<mb_type.value<mb_type.intra_mb<mb_type.motion_forward<mb_type.motion_backward<mb_type.motion_4mv<mb_type.h261_loopfilter<mb_type.field_residual<mb_type.mb_scan_method<mb_type.motion_type<mb_type.host_resid_diff<mb_type.reserved<mb_type.mvert_field_sel_0<mb_type.mvert_field_sel_1<mb_type.mvert_field_sel_2<mb_type.mvert_field_sel_3<pattern_code.value<pattern_code.block_coded_pattern<pattern_code.block_luma_intra<pattern_code.block_chroma_intra<motion_vector[i].value<motion_vector[i].mv_x<motion_vector[i].mv_y<CreateFileName( "_DEC", CodechalDbgBufferType::bufMbParams, CodechalDbgExtType::txt); std::ofstream ofs(fileName, std::ios::out); ofs << oss.str(); ofs.close(); return MOS_STATUS_SUCCESS; } #endif