blob: 998875ca68d0372887a4d43c8b7eb1f2e1f94607 [file] [log] [blame]
/*
* 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 <sstream>
#include <fstream>
#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
}
};
//==<Functions>=======================================================
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;
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 MVs 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;
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, widthInTiles;
uint32_t residualX, residualY;
uint32_t value;
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;
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;
uint32_t colSkip;
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;
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;
uint32_t index, mvMode;
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;
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;
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;
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;
uint32_t numRef;
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;
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;
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;
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;
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));
m_vldSliceRecord =
(PCODECHAL_VC1_VLD_SLICE_RECORD)MOS_AllocAndZeroMemory(m_picHeightInMb * sizeof(CODECHAL_VC1_VLD_SLICE_RECORD));
// 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);
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);
}
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) ? true : false;
bool pictureIsP = m_mfxInterface->IsVc1PPicture(currPic, m_vc1PicParams->picture_fields.is_first_field, picType) ? true : false;
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))
? true
: false;
// 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<uint32_t>(m_debugInterface->m_refIndex));
CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
&dstSurface,
CodechalDbgAttr::attrReferenceSurfaces,
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);
buf += slc->slice_data_offset;
if (offset > 3 && buf != nullptr &&
m_vc1PicParams->sequence_fields.AdvancedProfileFlag)
{
int i = 0;
int j = 0;
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;
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));
}
#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<<std::endl;
oss<< "CurrPic PicFlags: "<< +vc1PicParams->CurrPic.PicFlags<<std::endl;
oss<< "DeblockedPicIdx: "<< +vc1PicParams->DeblockedPicIdx<<std::endl;
oss<< "ForwardRefIdx: "<< +vc1PicParams->ForwardRefIdx<<std::endl;
oss<< "BackwardRefIdx: "<< +vc1PicParams->BackwardRefIdx<<std::endl;
//Dump sequence_fields
oss<< "sequence_fields value: "<< +vc1PicParams->sequence_fields.value<<std::endl;
oss<< "pulldown: "<< +vc1PicParams->sequence_fields.pulldown<<std::endl;
oss<< "interlace: "<< +vc1PicParams->sequence_fields.interlace<<std::endl;
oss<< "tfcntrflag: "<< +vc1PicParams->sequence_fields.tfcntrflag<<std::endl;
oss<< "finterpflag: "<< +vc1PicParams->sequence_fields.finterpflag<<std::endl;
oss<< "psf: "<< +vc1PicParams->sequence_fields.psf<<std::endl;
oss<< "multires: "<< +vc1PicParams->sequence_fields.multires<<std::endl;
oss<< "overlap: "<< +vc1PicParams->sequence_fields.overlap<<std::endl;
oss<< "syncmarker: "<< +vc1PicParams->sequence_fields.syncmarker<<std::endl;
oss<< "rangered: "<< +vc1PicParams->sequence_fields.rangered<<std::endl;
oss<< "max_b_frames: "<< +vc1PicParams->sequence_fields.max_b_frames<<std::endl;
oss<< "AdvancedProfileFlag: "<< +vc1PicParams->sequence_fields.AdvancedProfileFlag<<std::endl;
oss<< "coded_width: "<< +vc1PicParams->coded_width<<std::endl;
oss<< "coded_height: "<< +vc1PicParams->coded_height<<std::endl;
//Dump entrypoint_fields
oss<< "broken_link: "<< +vc1PicParams->entrypoint_fields.broken_link<<std::endl;
oss<< "closed_entry: "<< +vc1PicParams->entrypoint_fields.closed_entry<<std::endl;
oss<< "panscan_flag: "<< +vc1PicParams->entrypoint_fields.panscan_flag<<std::endl;
oss<< "loopfilter: "<< +vc1PicParams->entrypoint_fields.loopfilter<<std::endl;
oss<< "conditional_overlap_flag: "<< +vc1PicParams->conditional_overlap_flag<<std::endl;
oss<< "fast_uvmc_flag: "<< +vc1PicParams->fast_uvmc_flag<<std::endl;
//Dump range_mapping_fields
oss<< "range_mapping_fields range_mapping_enabled: "<< +vc1PicParams->range_mapping_fields.range_mapping_enabled<<std::endl;
oss<< "luma_flag: "<< +vc1PicParams->range_mapping_fields.luma_flag<<std::endl;
oss<< "luma: "<< +vc1PicParams->range_mapping_fields.luma<<std::endl;
oss<< "chroma_flag: "<< +vc1PicParams->range_mapping_fields.chroma_flag<<std::endl;
oss<< "chroma: "<< +vc1PicParams->range_mapping_fields.chroma<<std::endl;
oss<< "UpsamplingFlag: "<< +vc1PicParams->UpsamplingFlag<<std::endl;
oss<< "ScaleFactor: "<< +vc1PicParams->ScaleFactor<<std::endl;
oss<< "b_picture_fraction: "<< +vc1PicParams->b_picture_fraction<<std::endl;
oss<< "cbp_table: "<< +vc1PicParams->cbp_table<<std::endl;
oss<< "mb_mode_table: "<< +vc1PicParams->mb_mode_table<<std::endl;
oss<< "range_reduction_frame: "<< +vc1PicParams->range_reduction_frame<<std::endl;
oss<< "rounding_control: "<< +vc1PicParams->rounding_control<<std::endl;
oss<< "post_processing: "<< +vc1PicParams->post_processing<<std::endl;
oss<< "picture_resolution_index: "<< +vc1PicParams->picture_resolution_index<<std::endl;
oss<< "luma_scale: "<< +vc1PicParams->luma_scale<<std::endl;
oss<< "luma_shift: "<< +vc1PicParams->luma_shift<<std::endl;
//Dump picture_fields
oss<< "picture_fields value: "<< +vc1PicParams->picture_fields.value<<std::endl;
oss<< "picture_type: "<< +vc1PicParams->picture_fields.picture_type<<std::endl;
oss<< "frame_coding_mode: "<< +vc1PicParams->picture_fields.frame_coding_mode<<std::endl;
oss<< "top_field_first: "<< +vc1PicParams->picture_fields.top_field_first<<std::endl;
oss<< "is_first_field: "<< +vc1PicParams->picture_fields.is_first_field<<std::endl;
oss<< "intensity_compensation: "<< +vc1PicParams->picture_fields.intensity_compensation<<std::endl;
//Dump raw_coding
oss<< "raw_coding value: "<< +vc1PicParams->raw_coding.value<<std::endl;
oss<< "bitplane_present: "<< +vc1PicParams->raw_coding.bitplane_present<<std::endl;
oss<< "mv_type_mb: "<< +vc1PicParams->raw_coding.mv_type_mb<<std::endl;
oss<< "direct_mb: "<< +vc1PicParams->raw_coding.direct_mb<<std::endl;
oss<< "skip_mb: "<< +vc1PicParams->raw_coding.skip_mb<<std::endl;
oss<< "field_tx: "<< +vc1PicParams->raw_coding.field_tx<<std::endl;
oss<< "forward_mb: "<< +vc1PicParams->raw_coding.forward_mb<<std::endl;
oss<< "ac_pred: "<< +vc1PicParams->raw_coding.ac_pred<<std::endl;
oss<< "overflags: "<< +vc1PicParams->raw_coding.overflags<<std::endl;
//Dump reference_fields
oss<< "reference_fields value: "<< +vc1PicParams->reference_fields.value<<std::endl;
oss<< "reference_distance_flag: "<< +vc1PicParams->reference_fields.reference_distance_flag<<std::endl;
oss<< "reference_distance: "<< +vc1PicParams->reference_fields.reference_distance<<std::endl;
oss<< "BwdReferenceDistance: "<< +vc1PicParams->reference_fields.BwdReferenceDistance<<std::endl;
oss<< "num_reference_pictures: "<< +vc1PicParams->reference_fields.num_reference_pictures<<std::endl;
oss<< "reference_field_pic_indicator: "<< +vc1PicParams->reference_fields.reference_field_pic_indicator<<std::endl;
//Dump mv_fields
oss<< "mv_fields value: "<< +vc1PicParams->mv_fields.value<<std::endl;
oss<< "MvMode: "<< +vc1PicParams->mv_fields.MvMode<<std::endl;
oss<< "UnifiedMvMode: "<< +vc1PicParams->mv_fields.UnifiedMvMode<<std::endl;
oss<< "mv_table: "<< +vc1PicParams->mv_fields.mv_table<<std::endl;
oss<< "two_mv_block_pattern_table: "<< +vc1PicParams->mv_fields.two_mv_block_pattern_table<<std::endl;
oss<< "four_mv_switch: "<< +vc1PicParams->mv_fields.four_mv_switch<<std::endl;
oss<< "four_mv_block_pattern_table: "<< +vc1PicParams->mv_fields.four_mv_block_pattern_table<<std::endl;
oss<< "extended_mv_flag: "<< +vc1PicParams->mv_fields.extended_mv_flag<<std::endl;
oss<< "extended_mv_range: "<< +vc1PicParams->mv_fields.extended_mv_range<<std::endl;
oss<< "extended_dmv_flag: "<< +vc1PicParams->mv_fields.extended_dmv_flag<<std::endl;
oss<< "extended_dmv_range: "<< +vc1PicParams->mv_fields.extended_dmv_range<<std::endl;
//Dump pic_quantizer_fields
oss<< "pic_quantizer_fields value: "<< +vc1PicParams->pic_quantizer_fields.value<<std::endl;
oss<< "dquant: "<< +vc1PicParams->pic_quantizer_fields.dquant<<std::endl;
oss<< "quantizer: "<< +vc1PicParams->pic_quantizer_fields.quantizer<<std::endl;
oss<< "half_qp: "<< +vc1PicParams->pic_quantizer_fields.half_qp<<std::endl;
oss<< "AltPQuantEdgeMask: "<< +vc1PicParams->pic_quantizer_fields.AltPQuantEdgeMask<<std::endl;
oss<< "AltPQuantConfig: "<< +vc1PicParams->pic_quantizer_fields.AltPQuantConfig<<std::endl;
oss<< "pic_quantizer_scale: "<< +vc1PicParams->pic_quantizer_fields.pic_quantizer_scale<<std::endl;
oss<< "pic_quantizer_type: "<< +vc1PicParams->pic_quantizer_fields.pic_quantizer_type<<std::endl;
oss<< "alt_pic_quantizer: "<< +vc1PicParams->pic_quantizer_fields.alt_pic_quantizer<<std::endl;
//Dump transform_fields
oss<< "transform_fields value: "<< +vc1PicParams->transform_fields.value<<std::endl;
oss<< "variable_sized_transform_flag: "<< +vc1PicParams->transform_fields.variable_sized_transform_flag<<std::endl;
oss<< "mb_level_transform_type_flag: "<< +vc1PicParams->transform_fields.mb_level_transform_type_flag<<std::endl;
oss<< "frame_level_transform_type: "<< +vc1PicParams->transform_fields.frame_level_transform_type<<std::endl;
oss<< "transform_ac_codingset_idx1: "<< +vc1PicParams->transform_fields.transform_ac_codingset_idx1<<std::endl;
oss<< "transform_ac_codingset_idx2: "<< +vc1PicParams->transform_fields.transform_ac_codingset_idx2<<std::endl;
oss<< "intra_transform_dc_table: "<< +vc1PicParams->transform_fields.intra_transform_dc_table<<std::endl;
oss<< "StatusReportFeedbackNumber : "<< +vc1PicParams->StatusReportFeedbackNumber<<std::endl;
const char* fileName = m_debugInterface->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<<std::endl;
oss<< "slice_data_offset: "<< +sliceControl->slice_data_offset<<std::endl;
oss<< "macroblock_offset: "<< +sliceControl->macroblock_offset<<std::endl;
oss<< "slice_vertical_position: "<< +sliceControl->slice_vertical_position<<std::endl;
const char* fileName = m_debugInterface->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<<std::endl;
oss<< "mb_skips_following: "<< +mbParams->mb_skips_following<<std::endl;
oss<< "data_offset: "<< +mbParams->data_offset<<std::endl;
oss<< "data_length: "<< +mbParams->data_length<<std::endl;
//Dump num_coef[CODEC_NUM_BLOCK_PER_MB]
for(uint16_t i=0;i<CODEC_NUM_BLOCK_PER_MB;++i)
{
oss<< "num_coef["<<+i<<"]: "<< +mbParams->num_coef[i]<<std::endl;
}
//Dump union mb_type
oss<< "mb_type.value: "<< +mbParams->mb_type.value<<std::endl;
oss<< "mb_type.intra_mb: "<< +mbParams->mb_type.intra_mb<<std::endl;
oss<< "mb_type.motion_forward: "<< +mbParams->mb_type.motion_forward<<std::endl;
oss<< "mb_type.motion_backward: "<< +mbParams->mb_type.motion_backward<<std::endl;
oss<< "mb_type.motion_4mv: "<< +mbParams->mb_type.motion_4mv<<std::endl;
oss<< "mb_type.h261_loopfilter: "<<+mbParams->mb_type.h261_loopfilter<<std::endl;
oss<< "mb_type.field_residual: "<< +mbParams->mb_type.field_residual<<std::endl;
oss<< "mb_type.mb_scan_method: "<< +mbParams->mb_type.mb_scan_method<<std::endl;
oss<< "mb_type.motion_type: "<< +mbParams->mb_type.motion_type<<std::endl;
oss<< "mb_type.host_resid_diff: "<< +mbParams->mb_type.host_resid_diff<<std::endl;
oss<< "mb_type.reserved: "<< +mbParams->mb_type.reserved<<std::endl;
oss<< "mb_type.mvert_field_sel_0: "<< +mbParams->mb_type.mvert_field_sel_0<<std::endl;
oss<< "mb_type.mvert_field_sel_1: "<< +mbParams->mb_type.mvert_field_sel_1<<std::endl;
oss<< "mb_type.mvert_field_sel_2: "<< +mbParams->mb_type.mvert_field_sel_2<<std::endl;
oss<< "mb_type.mvert_field_sel_3: "<< +mbParams->mb_type.mvert_field_sel_3<<std::endl;
//Dump union pattern_code
oss<< "pattern_code.value: "<< +mbParams->pattern_code.value<<std::endl;
oss<< "pattern_code.block_coded_pattern: "<< +mbParams->pattern_code.block_coded_pattern<<std::endl;
oss<< "pattern_code.block_luma_intra: "<< +mbParams->pattern_code.block_luma_intra<<std::endl;
oss<< "pattern_code.block_chroma_intra: "<< +mbParams->pattern_code.block_chroma_intra<<std::endl;
//Dump union motion_vector[4]
for(uint8_t i=0;i<4;++i)
{
oss<< "motion_vector["<<+i<<"].value: "<< +mbParams->motion_vector[i].value<<std::endl;
oss<< "motion_vector["<<+i<<"].mv_x: "<< +mbParams->motion_vector[i].mv_x<<std::endl;
oss<< "motion_vector["<<+i<<"].mv_y: "<< +mbParams->motion_vector[i].mv_y<<std::endl;
}
const char* fileName = m_debugInterface->CreateFileName(
"_DEC",
CodechalDbgBufferType::bufMbParams,
CodechalDbgExtType::txt);
std::ofstream ofs(fileName, std::ios::out);
ofs << oss.str();
ofs.close();
return MOS_STATUS_SUCCESS;
}
#endif