1 /*
2 * Copyright (c) 2015-2017, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file media_ddi_decode_mpeg2.cpp
24 //! \brief The class implementation of DdiDecodeMpeg2 for Mpeg2 decode
25 //!
26
27 #include "media_libva_decoder.h"
28 #include "media_libva_util.h"
29 #include "media_libva_caps.h"
30
31 #include "media_ddi_decode_mpeg2.h"
32 #include "mos_solo_generic.h"
33 #include "codechal_memdecomp.h"
34 #include "media_ddi_decode_const.h"
35 #include "media_ddi_factory.h"
36
ParseNumMbsForSlice(int32_t numSlices)37 void DdiDecodeMPEG2::ParseNumMbsForSlice(
38 int32_t numSlices)
39 {
40 CodecDecodeMpeg2PicParams *picParam = (CodecDecodeMpeg2PicParams *)(m_ddiDecodeCtx->DecodeParams.m_picParams);
41
42 CodecDecodeMpeg2SliceParams *sliceParam = (CodecDecodeMpeg2SliceParams *)(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
43
44 uint16_t widthInMB, heightInMB, numMBInSlc;
45 widthInMB = m_picWidthInMB;
46 heightInMB = m_picHeightInMB;
47
48 int32_t slcIndex;
49 CodecDecodeMpeg2SliceParams *nextSlc;
50 for (slcIndex = 0; slcIndex < numSlices; slcIndex++)
51 {
52 if (slcIndex == numSlices - 1) // last slice
53 {
54 numMBInSlc = widthInMB - sliceParam->m_sliceHorizontalPosition;
55 }
56 else
57 {
58 nextSlc = sliceParam + 1;
59 numMBInSlc = (nextSlc->m_sliceVerticalPosition * widthInMB + nextSlc->m_sliceHorizontalPosition) -
60 (sliceParam->m_sliceVerticalPosition * widthInMB + sliceParam->m_sliceHorizontalPosition);
61 }
62
63 sliceParam->m_numMbsForSlice = numMBInSlc & 0x007f;
64
65 if (sliceParam->m_numMbsForSlice < numMBInSlc)
66 {
67 sliceParam->m_numMbsForSlice = widthInMB - sliceParam->m_sliceHorizontalPosition;
68 }
69
70 sliceParam++;
71 }
72 }
73
ParseSliceParams(DDI_MEDIA_CONTEXT * mediaCtx,VASliceParameterBufferMPEG2 * slcParam,uint32_t numSlices)74 VAStatus DdiDecodeMPEG2::ParseSliceParams(
75 DDI_MEDIA_CONTEXT *mediaCtx,
76 VASliceParameterBufferMPEG2 *slcParam,
77 uint32_t numSlices)
78 {
79 CodecDecodeMpeg2PicParams *picParams = (CodecDecodeMpeg2PicParams *)(m_ddiDecodeCtx->DecodeParams.m_picParams);
80 CodecDecodeMpeg2SliceParams *codecSlcParams = (CodecDecodeMpeg2SliceParams *)(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
81 codecSlcParams += m_ddiDecodeCtx->DecodeParams.m_numSlices;
82
83 if ((slcParam == nullptr) ||
84 (codecSlcParams == nullptr) ||
85 (picParams == nullptr))
86 {
87 DDI_ASSERTMESSAGE("Invalid Parameter for Parsing Mpeg2 Slice parameter\n");
88 return VA_STATUS_ERROR_INVALID_PARAMETER;
89 }
90
91 uint32_t isField;
92 if ((picParams->m_currPic.PicFlags == PICTURE_TOP_FIELD) || (picParams->m_currPic.PicFlags == PICTURE_BOTTOM_FIELD))
93 {
94 isField = 1;
95 }
96 else
97 {
98 isField = 0;
99 }
100
101 uint32_t sliceBaseOffset = GetBsBufOffset(m_groupIndex);
102 uint32_t slcCount;
103 for (slcCount = 0; slcCount < numSlices; slcCount++)
104 {
105 codecSlcParams->m_sliceHorizontalPosition = slcParam->slice_horizontal_position;
106 codecSlcParams->m_sliceVerticalPosition = slcParam->slice_vertical_position;
107
108 codecSlcParams->m_sliceDataSize = (slcParam->slice_data_size) * 8;
109 codecSlcParams->m_sliceDataOffset = slcParam->slice_data_offset + sliceBaseOffset;
110 if (slcParam->slice_data_flag)
111 {
112 DDI_NORMALMESSAGE("The whole slice is not in the bitstream buffer for this Execute call");
113 }
114 codecSlcParams->m_macroblockOffset = slcParam->macroblock_offset;
115 codecSlcParams->m_quantiserScaleCode = slcParam->quantiser_scale_code;
116 codecSlcParams->m_reservedBits = 0;
117 slcParam++;
118 codecSlcParams++;
119 }
120
121 return VA_STATUS_SUCCESS;
122 }
123
ParseIQMatrix(DDI_MEDIA_CONTEXT * mediaCtx,VAIQMatrixBufferMPEG2 * matrix)124 VAStatus DdiDecodeMPEG2::ParseIQMatrix(
125 DDI_MEDIA_CONTEXT *mediaCtx,
126 VAIQMatrixBufferMPEG2 *matrix)
127 {
128 CodecMpeg2IqMatrix *iqMatrix = (CodecMpeg2IqMatrix *)(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
129
130 if ((iqMatrix == nullptr) || (matrix == nullptr))
131 {
132 DDI_ASSERTMESSAGE("Invalid Parameter for Parsing Mpeg2 IQ Matrix parameter\n");
133 return VA_STATUS_ERROR_INVALID_PARAMETER;
134 }
135
136 iqMatrix->m_loadIntraQuantiserMatrix = matrix->load_intra_quantiser_matrix;
137 iqMatrix->m_loadNonIntraQuantiserMatrix = matrix->load_non_intra_quantiser_matrix;
138 iqMatrix->m_loadChromaIntraQuantiserMatrix = matrix->load_chroma_intra_quantiser_matrix;
139 iqMatrix->m_loadChromaNonIntraQuantiserMatrix = matrix->load_chroma_non_intra_quantiser_matrix;
140
141 MOS_SecureMemcpy(iqMatrix->m_intraQuantiserMatrix,
142 64,
143 matrix->intra_quantiser_matrix,
144 64);
145 MOS_SecureMemcpy(iqMatrix->m_nonIntraQuantiserMatrix,
146 64,
147 matrix->non_intra_quantiser_matrix,
148 64);
149 MOS_SecureMemcpy(iqMatrix->m_chromaIntraQuantiserMatrix,
150 64,
151 matrix->chroma_intra_quantiser_matrix,
152 64);
153 MOS_SecureMemcpy(iqMatrix->m_chromaNonIntraQuantiserMatrix,
154 64,
155 matrix->chroma_non_intra_quantiser_matrix,
156 64);
157 return VA_STATUS_SUCCESS;
158 }
159
160 #define INTRA_CODED 0x1
161 #define PREDICTIVE_CODED 0x2
162 #define BIDIRECTIONAL_CODED 0x3
163
164 // S-(GMC) VOP coding used for MPEG4 part 2
165 //
166 #define S_CODED 0x4
167
ParsePicParams(DDI_MEDIA_CONTEXT * mediaCtx,VAPictureParameterBufferMPEG2 * picParam)168 VAStatus DdiDecodeMPEG2::ParsePicParams(
169 DDI_MEDIA_CONTEXT *mediaCtx,
170 VAPictureParameterBufferMPEG2 *picParam)
171 {
172 CodecDecodeMpeg2PicParams *codecPicParam = (CodecDecodeMpeg2PicParams *)(m_ddiDecodeCtx->DecodeParams.m_picParams);
173 if ((codecPicParam == nullptr) || (picParam == nullptr))
174 {
175 DDI_ASSERTMESSAGE("Invalid Parameter for Parsing Mpeg2 Picture Parameter\n");
176 return VA_STATUS_ERROR_INVALID_PARAMETER;
177 }
178
179 codecPicParam->m_currPic.FrameIdx = GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), m_ddiDecodeCtx->RTtbl.pCurrentRT);
180 switch (picParam->picture_coding_extension.bits.picture_structure)
181 {
182 case TOP_FIELD:
183 codecPicParam->m_currPic.PicFlags = PICTURE_TOP_FIELD;
184 break;
185 case BOTTOM_FIELD:
186 codecPicParam->m_currPic.PicFlags = PICTURE_BOTTOM_FIELD;
187 break;
188 case FRAME_PICTURE:
189 codecPicParam->m_currPic.PicFlags = PICTURE_FRAME;
190 break;
191 default:
192 break;
193 }
194 codecPicParam->m_topFieldFirst = picParam->picture_coding_extension.bits.top_field_first;
195 codecPicParam->m_secondField = !(picParam->picture_coding_extension.bits.is_first_field);
196 codecPicParam->m_pictureCodingType = picParam->picture_coding_type;
197
198 if (picParam->picture_coding_extension.bits.is_first_field)
199 {
200 if (codecPicParam->m_currPic.PicFlags == PICTURE_TOP_FIELD)
201 codecPicParam->m_topFieldFirst = 1;
202 if (codecPicParam->m_currPic.PicFlags == PICTURE_BOTTOM_FIELD)
203 codecPicParam->m_topFieldFirst = 0;
204 }
205 else
206 {
207 if (codecPicParam->m_currPic.PicFlags == PICTURE_TOP_FIELD)
208 codecPicParam->m_topFieldFirst = 0;
209
210 if (codecPicParam->m_currPic.PicFlags == PICTURE_BOTTOM_FIELD)
211 codecPicParam->m_topFieldFirst = 1;
212 }
213 if (picParam->picture_coding_type == INTRA_CODED)
214 {
215 codecPicParam->m_forwardRefIdx = codecPicParam->m_currPic.FrameIdx;
216 codecPicParam->m_backwardRefIdx = codecPicParam->m_currPic.FrameIdx;
217 }
218 else if (picParam->picture_coding_type == PREDICTIVE_CODED)
219 {
220 if (picParam->forward_reference_picture != VA_INVALID_SURFACE)
221 {
222 if (UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)) != VA_STATUS_SUCCESS)
223 {
224 DDI_CHK_RET(RegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)), "RegisterRTSurfaces failed!");
225 }
226
227 codecPicParam->m_forwardRefIdx = GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)); //(unsigned char)GetMPEG2SurfaceIdx(&(pRTtbl->pRT[0]), picParam->forward_reference_picture);
228 }
229 else
230 {
231 codecPicParam->m_forwardRefIdx = codecPicParam->m_currPic.FrameIdx;
232 }
233
234 if (codecPicParam->m_secondField)
235 {
236 codecPicParam->m_backwardRefIdx = codecPicParam->m_currPic.FrameIdx;
237 }
238 else
239 {
240 codecPicParam->m_backwardRefIdx = codecPicParam->m_forwardRefIdx;
241 }
242 }
243 else
244 {
245 if (picParam->forward_reference_picture != VA_INVALID_SURFACE)
246 {
247 if (UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)) != VA_STATUS_SUCCESS)
248 {
249 DDI_CHK_RET(RegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)), "RegisterRTSurfaces failed!");
250 }
251 codecPicParam->m_forwardRefIdx = GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->forward_reference_picture)); //(unsigned char)GetMPEG2SurfaceIdx(&(pRTtbl->pRT[0]), picParam->forward_reference_picture);
252 }
253 else
254 {
255 codecPicParam->m_forwardRefIdx = codecPicParam->m_currPic.FrameIdx;
256 }
257 if (picParam->backward_reference_picture != VA_INVALID_SURFACE)
258 {
259 if (UpdateRegisteredRTSurfaceFlag(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture)) != VA_STATUS_SUCCESS)
260 {
261 DDI_CHK_RET(RegisterRTSurfaces(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture)), "RegisterRTSurfaces failed!");
262 }
263 codecPicParam->m_backwardRefIdx = GetRenderTargetID(&(m_ddiDecodeCtx->RTtbl), DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->backward_reference_picture)); //(unsigned char)GetMPEG2SurfaceIdx(&(pRTtbl->pRT[0]), picParam->backward_reference_picture);
264 }
265 else
266 {
267 codecPicParam->m_backwardRefIdx = codecPicParam->m_currPic.FrameIdx;
268 }
269 }
270
271 //add protection checking to prevent ref pic index larger than DPB size
272 if (codecPicParam->m_forwardRefIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2)
273 {
274 codecPicParam->m_forwardRefIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2 - 1;
275 }
276
277 if (codecPicParam->m_backwardRefIdx >= CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2)
278 {
279 codecPicParam->m_backwardRefIdx = CODECHAL_NUM_UNCOMPRESSED_SURFACE_MPEG2 - 1;
280 }
281
282 codecPicParam->W0.m_scanOrder = picParam->picture_coding_extension.bits.alternate_scan;
283 codecPicParam->W0.m_intraVlcFormat = picParam->picture_coding_extension.bits.intra_vlc_format;
284 codecPicParam->W0.m_quantizerScaleType = picParam->picture_coding_extension.bits.q_scale_type;
285 codecPicParam->W0.m_concealmentMVFlag = picParam->picture_coding_extension.bits.concealment_motion_vectors;
286 codecPicParam->W0.m_frameDctPrediction = picParam->picture_coding_extension.bits.frame_pred_frame_dct;
287 codecPicParam->W0.m_topFieldFirst = picParam->picture_coding_extension.bits.top_field_first;
288 codecPicParam->W0.m_intraDCPrecision = picParam->picture_coding_extension.bits.intra_dc_precision;
289 codecPicParam->W1.m_value = 0;
290 codecPicParam->W1.m_fcode11 = (picParam->f_code) & 0xf;
291 codecPicParam->W1.m_fcode10 = (picParam->f_code >> 4) & 0xf;
292 codecPicParam->W1.m_fcode01 = (picParam->f_code >> 8) & 0xf;
293 codecPicParam->W1.m_fcode00 = (picParam->f_code >> 12) & 0xf;
294 codecPicParam->m_horizontalSize = picParam->horizontal_size;
295 codecPicParam->m_verticalSize = picParam->vertical_size;
296
297 if (picParam->picture_coding_type == INTRA_CODED)
298 {
299 m_picWidthInMB = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_WIDTH(picParam->horizontal_size));
300 m_picHeightInMB = (int16_t)(DDI_CODEC_NUM_MACROBLOCKS_WIDTH(picParam->vertical_size));
301 }
302
303 if ((codecPicParam->m_currPic.PicFlags == PICTURE_TOP_FIELD) || (codecPicParam->m_currPic.PicFlags == PICTURE_BOTTOM_FIELD))
304 {
305 codecPicParam->m_verticalSize = picParam->vertical_size >> 1;
306 }
307
308 codecPicParam->m_statusReportFeedbackNumber = 0;
309
310 DDI_CHK_NULL(mediaCtx, "Null mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
311 DDI_CHK_NULL(mediaCtx->m_caps, "Null m_cpas", VA_STATUS_ERROR_INVALID_CONTEXT);
312 VAStatus vaStatus = mediaCtx->m_caps->CheckDecodeResolution(
313 m_ddiDecodeCtx->wMode,
314 VAProfileMPEG2Simple,
315 codecPicParam->m_horizontalSize,
316 codecPicParam->m_verticalSize);
317 if (vaStatus != VA_STATUS_SUCCESS)
318 {
319 return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
320 }
321
322 return VA_STATUS_SUCCESS;
323 }
324
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)325 VAStatus DdiDecodeMPEG2::RenderPicture(
326 VADriverContextP ctx,
327 VAContextID context,
328 VABufferID *buffers,
329 int32_t numBuffers)
330 {
331 VAStatus va = VA_STATUS_SUCCESS;
332 PDDI_MEDIA_CONTEXT mediaCtx;
333
334 DDI_FUNCTION_ENTER();
335
336 mediaCtx = DdiMedia_GetMediaContext(ctx);
337
338 void *data = nullptr;
339 for (int32_t i = 0; i < numBuffers; i++)
340 {
341 if (!buffers || (buffers[i] == VA_INVALID_ID))
342 {
343 return VA_STATUS_ERROR_INVALID_BUFFER;
344 }
345
346 DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
347 if (nullptr == buf)
348 {
349 return VA_STATUS_ERROR_INVALID_BUFFER;
350 }
351
352 uint32_t dataSize = buf->iSize;
353 DdiMedia_MapBuffer(ctx, buffers[i], &data);
354
355 if (data == nullptr)
356 {
357 return VA_STATUS_ERROR_INVALID_BUFFER;
358 }
359
360 switch ((int32_t)buf->uiType)
361 {
362 case VASliceDataBufferType:
363 {
364 int32_t index = GetBitstreamBufIndexFromBuffer(&m_ddiDecodeCtx->BufMgr, buf);
365 if (index == DDI_CODEC_INVALID_BUFFER_INDEX)
366 {
367 return VA_STATUS_ERROR_INVALID_BUFFER;
368 }
369
370 DdiMedia_MediaBufferToMosResource(m_ddiDecodeCtx->BufMgr.pBitStreamBuffObject[index], &m_ddiDecodeCtx->BufMgr.resBitstreamBuffer);
371 m_ddiDecodeCtx->DecodeParams.m_dataSize += dataSize;
372 break;
373 }
374 case VASliceParameterBufferType:
375 {
376 if (buf->uiNumElements == 0)
377 {
378 return VA_STATUS_ERROR_INVALID_BUFFER;
379 }
380
381 VASliceParameterBufferMPEG2 *slcInfoMpeg2 =
382 (VASliceParameterBufferMPEG2 *)data;
383 uint32_t numSlices = buf->uiNumElements;
384 DDI_CHK_RET(AllocSliceParamContext(numSlices),"AllocSliceParamContext failed!");
385 DDI_CHK_RET(ParseSliceParams(mediaCtx, slcInfoMpeg2, numSlices),"ParseSliceParams failed!");
386 m_ddiDecodeCtx->DecodeParams.m_numSlices += numSlices;
387 m_groupIndex++;
388 break;
389 }
390 case VAPictureParameterBufferType:
391 {
392 VAPictureParameterBufferMPEG2 *picParam = (VAPictureParameterBufferMPEG2 *)data;
393 DDI_CHK_RET(ParsePicParams(mediaCtx, picParam),"ParsePicParams failed!");
394 break;
395 }
396 case VAIQMatrixBufferType:
397 {
398 VAIQMatrixBufferMPEG2 *imxBuf =
399 (VAIQMatrixBufferMPEG2 *)data;
400 DDI_CHK_RET(ParseIQMatrix(mediaCtx, imxBuf),"ParseIQMatrix failed!");
401 break;
402 }
403 case VADecodeStreamoutBufferType:
404 {
405 DdiMedia_MediaBufferToMosResource(buf, &m_ddiDecodeCtx->BufMgr.resExternalStreamOutBuffer);
406 m_streamOutEnabled = true;
407 break;
408 }
409 default:
410 va = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
411 break;
412 }
413 DdiMedia_UnmapBuffer(ctx, buffers[i]);
414 }
415
416 DDI_FUNCTION_EXIT(va);
417 return va;
418 }
419
SetDecodeParams()420 VAStatus DdiDecodeMPEG2::SetDecodeParams()
421 {
422 DDI_CHK_RET(DdiMediaDecode::SetDecodeParams(),"SetDecodeParams failed!");
423 ParseNumMbsForSlice((&m_ddiDecodeCtx->DecodeParams)->m_numSlices);
424 return VA_STATUS_SUCCESS;
425 }
426
AllocSliceParamContext(uint32_t numSlices)427 VAStatus DdiDecodeMPEG2::AllocSliceParamContext(
428 uint32_t numSlices)
429 {
430 uint32_t baseSize = sizeof(CodecDecodeMpeg2SliceParams);
431
432 if (m_sliceParamBufNum < (m_ddiDecodeCtx->DecodeParams.m_numSlices + numSlices))
433 {
434 // in order to avoid that the buffer is reallocated multi-times,
435 // extra 10 slices are added.
436 uint32_t extraSlices = numSlices + 10;
437
438 m_ddiDecodeCtx->DecodeParams.m_sliceParams = realloc(m_ddiDecodeCtx->DecodeParams.m_sliceParams,
439 baseSize * (m_sliceParamBufNum + extraSlices));
440
441 if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr)
442 {
443 return VA_STATUS_ERROR_ALLOCATION_FAILED;
444 }
445
446 memset((void *)((uint8_t *)m_ddiDecodeCtx->DecodeParams.m_sliceParams + baseSize * m_sliceParamBufNum), 0, baseSize * extraSlices);
447 m_sliceParamBufNum += extraSlices;
448 }
449
450 return VA_STATUS_SUCCESS;
451 }
452
DestroyContext(VADriverContextP ctx)453 void DdiDecodeMPEG2::DestroyContext(
454 VADriverContextP ctx)
455 {
456 FreeResourceBuffer();
457 // explicitly call the base function to do the further clean-up
458 DdiMediaDecode::DestroyContext(ctx);
459 }
460
GetPicParamBuf(DDI_CODEC_COM_BUFFER_MGR * bufMgr)461 uint8_t* DdiDecodeMPEG2::GetPicParamBuf(
462 DDI_CODEC_COM_BUFFER_MGR *bufMgr)
463 {
464 return (uint8_t*)(&(bufMgr->Codec_Param.Codec_Param_MPEG2.PicParamMPEG2));
465 }
466
AllocSliceControlBuffer(DDI_MEDIA_BUFFER * buf)467 VAStatus DdiDecodeMPEG2::AllocSliceControlBuffer(
468 DDI_MEDIA_BUFFER *buf)
469 {
470 DDI_CODEC_COM_BUFFER_MGR *bufMgr;
471 uint32_t availSize;
472 uint32_t newSize;
473
474 bufMgr = &(m_ddiDecodeCtx->BufMgr);
475 availSize = m_sliceCtrlBufNum - bufMgr->dwNumSliceControl;
476 if(availSize < buf->uiNumElements)
477 {
478 newSize = sizeof(VASliceParameterBufferMPEG2) * (m_sliceCtrlBufNum - availSize + buf->uiNumElements);
479 bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2 = (VASliceParameterBufferMPEG2 *)realloc(bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2, newSize);
480 if(bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2 == nullptr)
481 {
482 return VA_STATUS_ERROR_ALLOCATION_FAILED;
483 }
484 MOS_ZeroMemory(bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2 + m_sliceCtrlBufNum, sizeof(VASliceParameterBufferMPEG2) * (buf->uiNumElements - availSize));
485 m_sliceCtrlBufNum = m_sliceCtrlBufNum - availSize + buf->uiNumElements;
486 }
487 buf->pData = (uint8_t*)bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2;
488 buf->uiOffset = sizeof(VASliceParameterBufferMPEG2) * bufMgr->dwNumSliceControl;
489
490 bufMgr->dwNumSliceControl += buf->uiNumElements;
491
492 return VA_STATUS_SUCCESS;
493 }
494
ContextInit(int32_t picWidth,int32_t picHeight)495 void DdiDecodeMPEG2::ContextInit(
496 int32_t picWidth,
497 int32_t picHeight)
498 {
499 // call the function in base class to initialize it.
500 DdiMediaDecode::ContextInit(picWidth, picHeight);
501
502 m_ddiDecodeCtx->wMode = CODECHAL_DECODE_MODE_MPEG2VLD;
503 }
504
InitResourceBuffer()505 VAStatus DdiDecodeMPEG2::InitResourceBuffer()
506 {
507 VAStatus vaStatus = VA_STATUS_SUCCESS;
508 DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
509
510 bufMgr->pSliceData = nullptr;
511
512 bufMgr->ui64BitstreamOrder = 0;
513 bufMgr->dwMaxBsSize = m_width *
514 m_height * 3 / 2;
515 // minimal 10k bytes for some special case. Will refractor this later
516 if (bufMgr->dwMaxBsSize < DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE)
517 {
518 bufMgr->dwMaxBsSize = DDI_CODEC_MIN_VALUE_OF_MAX_BS_SIZE;
519 }
520
521 int32_t i;
522 // init decode bitstream buffer object
523 for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
524 {
525 bufMgr->pBitStreamBuffObject[i] = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
526 if (bufMgr->pBitStreamBuffObject[i] == nullptr)
527 {
528 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
529 goto finish;
530 }
531 bufMgr->pBitStreamBuffObject[i]->iSize = bufMgr->dwMaxBsSize;
532 bufMgr->pBitStreamBuffObject[i]->uiType = VASliceDataBufferType;
533 bufMgr->pBitStreamBuffObject[i]->format = Media_Format_Buffer;
534 bufMgr->pBitStreamBuffObject[i]->uiOffset = 0;
535 bufMgr->pBitStreamBuffObject[i]->bo = nullptr;
536 bufMgr->pBitStreamBase[i] = nullptr;
537 }
538
539 // Most Mpeg2 clips are based on row.
540 // As the pSliceData can be allocated on demand, the default size is based on wPicHeightInMB.
541 bufMgr->m_maxNumSliceData = m_picHeightInMB;
542 bufMgr->pSliceData = (DDI_CODEC_BITSTREAM_BUFFER_INFO *)MOS_AllocAndZeroMemory(sizeof(bufMgr->pSliceData[0]) *
543 bufMgr->m_maxNumSliceData);
544
545 if (bufMgr->pSliceData == nullptr)
546 {
547 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
548 goto finish;
549 }
550
551 bufMgr->dwNumSliceData = 0;
552 bufMgr->dwNumSliceControl = 0;
553
554 m_sliceCtrlBufNum = m_picHeightInMB;
555 bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2 = (VASliceParameterBufferMPEG2 *)MOS_AllocAndZeroMemory(sizeof(VASliceParameterBufferMPEG2) * m_sliceCtrlBufNum);
556 if (bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2 == nullptr)
557 {
558 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
559 goto finish;
560 }
561
562 return VA_STATUS_SUCCESS;
563
564 finish:
565 FreeResourceBuffer();
566 return vaStatus;
567 }
568
FreeResourceBuffer()569 void DdiDecodeMPEG2::FreeResourceBuffer()
570 {
571 DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_ddiDecodeCtx->BufMgr);
572
573 int32_t i;
574 for (i = 0; i < DDI_CODEC_MAX_BITSTREAM_BUFFER; i++)
575 {
576 if (bufMgr->pBitStreamBase[i])
577 {
578 DdiMediaUtil_UnlockBuffer(bufMgr->pBitStreamBuffObject[i]);
579 bufMgr->pBitStreamBase[i] = nullptr;
580 }
581 if (bufMgr->pBitStreamBuffObject[i])
582 {
583 DdiMediaUtil_FreeBuffer(bufMgr->pBitStreamBuffObject[i]);
584 MOS_FreeMemory(bufMgr->pBitStreamBuffObject[i]);
585 bufMgr->pBitStreamBuffObject[i] = nullptr;
586 }
587 }
588
589 if (bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2)
590 {
591 MOS_FreeMemory(bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2);
592 bufMgr->Codec_Param.Codec_Param_MPEG2.pVASliceParaBufMPEG2 = nullptr;
593 }
594
595 // free decode bitstream buffer object
596 MOS_FreeMemory(bufMgr->pSliceData);
597 bufMgr->pSliceData = nullptr;
598
599 return;
600 }
601
CodecHalInit(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr)602 VAStatus DdiDecodeMPEG2::CodecHalInit(
603 DDI_MEDIA_CONTEXT *mediaCtx,
604 void *ptr)
605 {
606 VAStatus vaStatus = VA_STATUS_SUCCESS;
607 MOS_CONTEXT *mosCtx = (MOS_CONTEXT *)ptr;
608
609 CODECHAL_FUNCTION codecFunction = CODECHAL_FUNCTION_DECODE;
610 m_ddiDecodeCtx->pCpDdiInterface->SetCpParams(m_ddiDecodeAttr->uiEncryptionType, m_codechalSettings);
611
612 CODECHAL_STANDARD_INFO standardInfo;
613 memset(&standardInfo, 0, sizeof(standardInfo));
614
615 standardInfo.CodecFunction = codecFunction;
616 standardInfo.Mode = (CODECHAL_MODE)m_ddiDecodeCtx->wMode;
617
618 m_codechalSettings->codecFunction = codecFunction;
619 m_codechalSettings->width = m_width;
620 m_codechalSettings->height = m_height;
621 m_codechalSettings->intelEntrypointInUse = false;
622
623 m_codechalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS;
624
625 m_codechalSettings->shortFormatInUse = m_ddiDecodeCtx->bShortFormatInUse;
626
627 m_codechalSettings->mode = CODECHAL_DECODE_MODE_MPEG2VLD;
628 m_codechalSettings->standard = CODECHAL_MPEG2;
629
630 m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = MOS_AllocAndZeroMemory(sizeof(CodecMpeg2IqMatrix));
631 if (m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer == nullptr)
632 {
633 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
634 goto CleanUpandReturn;
635 }
636 m_ddiDecodeCtx->DecodeParams.m_picParams = MOS_AllocAndZeroMemory(sizeof(CodecDecodeMpeg2PicParams));
637 if (m_ddiDecodeCtx->DecodeParams.m_picParams == nullptr)
638 {
639 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
640 goto CleanUpandReturn;
641 }
642
643 m_sliceParamBufNum = m_picHeightInMB;
644 m_ddiDecodeCtx->DecodeParams.m_sliceParams = MOS_AllocAndZeroMemory(m_sliceParamBufNum * sizeof(CodecDecodeMpeg2SliceParams));
645 if (m_ddiDecodeCtx->DecodeParams.m_sliceParams == nullptr)
646 {
647 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
648 goto CleanUpandReturn;
649 }
650
651 vaStatus = CreateCodecHal(mediaCtx,
652 ptr,
653 &standardInfo);
654
655 if (vaStatus != VA_STATUS_SUCCESS)
656 {
657 goto CleanUpandReturn;
658 }
659
660 if (InitResourceBuffer() != VA_STATUS_SUCCESS)
661 {
662 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
663 goto CleanUpandReturn;
664 }
665
666 return vaStatus;
667
668 CleanUpandReturn:
669 FreeResourceBuffer();
670
671 if (m_ddiDecodeCtx->pCodecHal)
672 {
673 m_ddiDecodeCtx->pCodecHal->Destroy();
674 MOS_Delete(m_ddiDecodeCtx->pCodecHal);
675 m_ddiDecodeCtx->pCodecHal = nullptr;
676 }
677
678 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer);
679 m_ddiDecodeCtx->DecodeParams.m_iqMatrixBuffer = nullptr;
680 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_picParams);
681 m_ddiDecodeCtx->DecodeParams.m_picParams = nullptr;
682 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_huffmanTable);
683 m_ddiDecodeCtx->DecodeParams.m_huffmanTable = nullptr;
684 MOS_FreeMemory(m_ddiDecodeCtx->DecodeParams.m_sliceParams);
685 m_ddiDecodeCtx->DecodeParams.m_sliceParams = nullptr;
686
687 return vaStatus;
688 }
689
690 extern template class MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>;
691
692 static bool mpeg2Registered =
693 MediaDdiFactory<DdiMediaDecode, DDI_DECODE_CONFIG_ATTR>::RegisterCodec<DdiDecodeMPEG2>(DECODE_ID_MPEG2);
694