1 /*
2 * Copyright (c) 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_encode_mpeg2.cpp
24 //! \brief Defines class for DDI media mpeg2 encode.
25 //!
26
27 #include "media_libva_encoder.h"
28 #include "media_libva_util.h"
29 #include "media_ddi_encode_mpeg2.h"
30 #include "media_ddi_encode_const.h"
31 #include "media_ddi_factory.h"
32
33 extern template class MediaDdiFactoryNoArg<DdiEncodeBase>;
34 static bool isEncodeMpeg2Registered =
35 MediaDdiFactoryNoArg<DdiEncodeBase>::RegisterCodec<DdiEncodeMpeg2>(ENCODE_ID_MPEG2);
36
~DdiEncodeMpeg2()37 DdiEncodeMpeg2::~DdiEncodeMpeg2()
38 {
39 RemoveUserData();
40
41 MOS_FreeMemory(m_encodeCtx->pSeqParams);
42 m_encodeCtx->pSeqParams = nullptr;
43
44 MOS_FreeMemory(m_encodeCtx->pPicParams);
45 m_encodeCtx->pPicParams = nullptr;
46
47 if (nullptr != m_encodeCtx->ppNALUnitParams)
48 {
49 // Allocate one contiguous memory for the NALUnitParams buffers
50 // only need to free one time
51 MOS_FreeMemory(m_encodeCtx->ppNALUnitParams[0]);
52 m_encodeCtx->ppNALUnitParams[0] = nullptr;
53
54 MOS_FreeMemory(m_encodeCtx->ppNALUnitParams);
55 m_encodeCtx->ppNALUnitParams = nullptr;
56 }
57
58 MOS_FreeMemory(m_encodeCtx->pVuiParams);
59 m_encodeCtx->pVuiParams = nullptr;
60
61 MOS_FreeMemory(m_encodeCtx->pSliceParams);
62 m_encodeCtx->pSliceParams = nullptr;
63
64 MOS_FreeMemory(m_encodeCtx->pEncodeStatusReport);
65 m_encodeCtx->pEncodeStatusReport = nullptr;
66
67 MOS_FreeMemory(m_encodeCtx->pSEIFromApp);
68 m_encodeCtx->pSEIFromApp = nullptr;
69
70 MOS_FreeMemory(m_encodeCtx->pSliceHeaderData);
71 m_encodeCtx->pSliceHeaderData = nullptr;
72
73 if (m_encodeCtx->pbsBuffer)
74 {
75 MOS_FreeMemory(m_encodeCtx->pbsBuffer->pBase);
76 m_encodeCtx->pbsBuffer->pBase = nullptr;
77
78 MOS_FreeMemory(m_encodeCtx->pbsBuffer);
79 m_encodeCtx->pbsBuffer = nullptr;
80 }
81 MOS_FreeMemory(m_encodeCtx->pQmatrixParams);
82 m_encodeCtx->pQmatrixParams = nullptr;
83 }
84
ContextInitialize(CodechalSetting * codecHalSettings)85 VAStatus DdiEncodeMpeg2::ContextInitialize(
86 CodechalSetting *codecHalSettings)
87 {
88 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx.", VA_STATUS_ERROR_INVALID_CONTEXT);
89 DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "nullptr m_encodeCtx->pCpDdiInterface.", VA_STATUS_ERROR_INVALID_CONTEXT);
90 DDI_CHK_NULL(codecHalSettings, "nullptr codecHalSettings.", VA_STATUS_ERROR_INVALID_CONTEXT);
91
92 codecHalSettings->codecFunction = CODECHAL_FUNCTION_ENC_PAK;
93 codecHalSettings->width = m_encodeCtx->dwFrameWidth;
94 codecHalSettings->height = m_encodeCtx->dwFrameHeight;
95 codecHalSettings->mode = m_encodeCtx->wModeType;
96 codecHalSettings->standard = CODECHAL_MPEG2;
97
98 m_encodeCtx->pSeqParams = (void *)MOS_AllocAndZeroMemory(sizeof(CodecEncodeMpeg2SequenceParams));
99 DDI_CHK_NULL(m_encodeCtx->pSeqParams, "nullptr m_encodeCtx->pSeqParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
100
101 m_encodeCtx->pPicParams = (void *)MOS_AllocAndZeroMemory(sizeof(CodecEncodeMpeg2PictureParams));
102 DDI_CHK_NULL(m_encodeCtx->pPicParams, "nullptr m_encodeCtx->pPicParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
103
104 m_encodeCtx->pQmatrixParams = (void *)MOS_AllocAndZeroMemory(sizeof(CodecEncodeMpeg2QmatixParams));
105 DDI_CHK_NULL(m_encodeCtx->pQmatrixParams, "nullptr m_encodeCtx->pQmatrixParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
106
107 m_encodeCtx->pVuiParams = (void *)MOS_AllocAndZeroMemory(sizeof(CodecEncodeMpeg2VuiParams));
108 DDI_CHK_NULL(m_encodeCtx->pVuiParams, "nullptr m_encodeCtx->pVuiParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
109
110 // Allocate SliceParams
111 // slice params num should equal to the mbHeight //attention !!! zxf
112 m_encodeCtx->pSliceParams = (void *)MOS_AllocAndZeroMemory((m_encodeCtx->dwFrameHeight >> 4) * sizeof(CodecEncodeMpeg2SliceParmas));
113 DDI_CHK_NULL(m_encodeCtx->pSliceParams, "nullptr m_encodeCtx->pSliceParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
114
115 // Allocate Encode Status Report
116 m_encodeCtx->pEncodeStatusReport = (void *)MOS_AllocAndZeroMemory(CODECHAL_ENCODE_STATUS_NUM * sizeof(EncodeStatusReport));
117 DDI_CHK_NULL(m_encodeCtx->pEncodeStatusReport, "nullptr m_encodeCtx->pEncodeStatusReport.", VA_STATUS_ERROR_ALLOCATION_FAILED);
118
119 // Allocate SEI structure
120 m_encodeCtx->pSEIFromApp = (CodechalEncodeSeiData *)MOS_AllocAndZeroMemory(sizeof(CodechalEncodeSeiData));
121 DDI_CHK_NULL(m_encodeCtx->pSEIFromApp, "nullptr m_encodeCtx->pSEIFromApp.", VA_STATUS_ERROR_ALLOCATION_FAILED);
122
123 m_encodeCtx->pSliceHeaderData = (CODEC_ENCODER_SLCDATA *)MOS_AllocAndZeroMemory(m_encodeCtx->wPicHeightInMB *
124 sizeof(CODEC_ENCODER_SLCDATA));
125 DDI_CHK_NULL(m_encodeCtx->pSliceHeaderData, "nullptr m_encodeCtx->pSliceHeaderData.", VA_STATUS_ERROR_ALLOCATION_FAILED);
126
127 // Create the bit stream buffer to hold the packed headers from application
128 m_encodeCtx->pbsBuffer = (BSBuffer *)MOS_AllocAndZeroMemory(sizeof(BSBuffer));
129 DDI_CHK_NULL(m_encodeCtx->pbsBuffer, "nullptr m_encodeCtx->pbsBuffer.", VA_STATUS_ERROR_ALLOCATION_FAILED);
130
131 m_encodeCtx->pbsBuffer->pBase = (uint8_t *)MOS_AllocAndZeroMemory(m_encodeCtx->wPicHeightInMB * PACKED_HEADER_SIZE_PER_ROW);
132 DDI_CHK_NULL(m_encodeCtx->pbsBuffer->pBase, "nullptr m_encodeCtx->pbsBuffer->pBase.", VA_STATUS_ERROR_ALLOCATION_FAILED);
133
134 m_encodeCtx->pbsBuffer->BufferSize = m_encodeCtx->wPicHeightInMB * PACKED_HEADER_SIZE_PER_ROW;
135
136 return VA_STATUS_SUCCESS;
137 }
138
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)139 VAStatus DdiEncodeMpeg2::RenderPicture(
140 VADriverContextP ctx,
141 VAContextID context,
142 VABufferID *buffers,
143 int32_t numBuffers)
144 {
145 VAStatus vaStatus = VA_STATUS_SUCCESS;
146
147 DDI_FUNCTION_ENTER();
148
149 DDI_CHK_NULL(ctx, "nullptr context", VA_STATUS_ERROR_INVALID_CONTEXT);
150
151 DDI_MEDIA_CONTEXT *mediaCtx = DdiMedia_GetMediaContext(ctx);
152 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
153
154 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
155
156 for (int32_t i = 0; i < numBuffers; i++)
157 {
158 DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
159 DDI_CHK_NULL(buf, "Invalid buffer.", VA_STATUS_ERROR_INVALID_BUFFER);
160 if (buf->uiType == VAEncMacroblockDisableSkipMapBufferType)
161 {
162 DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resPerMBSkipMapBuffer));
163 m_encodeCtx->bMbDisableSkipMapEnabled = true;
164 continue;
165 }
166 uint32_t dataSize = buf->iSize;
167 // can use internal function instead of DdiMedia_MapBuffer here?
168 void *data = nullptr;
169 DdiMedia_MapBuffer(ctx, buffers[i], &data);
170 DDI_CHK_NULL(data, "nullptr data.", VA_STATUS_ERROR_INVALID_BUFFER);
171
172 switch (buf->uiType)
173 {
174 case VAIQMatrixBufferType:
175 case VAQMatrixBufferType:
176 DDI_CHK_STATUS(Qmatrix(data), VA_STATUS_ERROR_INVALID_BUFFER);
177 break;
178
179 case VAEncSequenceParameterBufferType:
180 DDI_CHK_STATUS(ParseSeqParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
181 m_encodeCtx->bNewSeq = true;
182 break;
183
184 case VAEncPictureParameterBufferType:
185 DDI_CHK_STATUS(ParsePicParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER);
186 DDI_CHK_STATUS(
187 AddToStatusReportQueue((void *)m_encodeCtx->resBitstreamBuffer.bo),
188 VA_STATUS_ERROR_INVALID_BUFFER);
189 break;
190
191 case VAEncSliceParameterBufferType:
192 {
193 uint32_t numSlices = buf->uiNumElements;
194 DDI_CHK_STATUS(ParseSlcParams(mediaCtx, data, numSlices), VA_STATUS_ERROR_INVALID_BUFFER);
195 }
196 break;
197
198 case VAEncPackedHeaderParameterBufferType:
199 vaStatus = ParsePackedHeaderParams(data);
200 break;
201
202 case VAEncPackedHeaderDataBufferType:
203 vaStatus = ParsePackedHeaderData(data);
204 break;
205
206 case VAEncMiscParameterBufferType:
207 DDI_CHK_STATUS(ParseMiscParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
208 break;
209
210 case VAEncQPBufferType:
211 DdiMedia_MediaBufferToMosResource(buf, &m_encodeCtx->resMBQpBuffer);
212 m_encodeCtx->bMBQpEnable = true;
213 break;
214
215 default:
216 DDI_ASSERTMESSAGE("not supported buffer type.");
217 break;
218 }
219 DdiMedia_UnmapBuffer(ctx, buffers[i]);
220 }
221
222 DDI_FUNCTION_EXIT(vaStatus);
223 return vaStatus;
224 }
225
EncodeInCodecHal(uint32_t numSlices)226 VAStatus DdiEncodeMpeg2::EncodeInCodecHal(
227 uint32_t numSlices)
228 {
229 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
230 DDI_CHK_NULL(m_encodeCtx->pMediaCtx, "nullptr m_encodeCtx->pMediaCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
231 DDI_CHK_NULL(m_encodeCtx->pCodecHal, "nullptr m_encodeCtx->pCodecHal", VA_STATUS_ERROR_INVALID_PARAMETER);
232
233 EncoderParams encodeParams;
234 MOS_ZeroMemory(&encodeParams, sizeof(EncoderParams));
235
236 if (m_encodeCtx->bVdencActive == true)
237 {
238 encodeParams.ExecCodecFunction = CODECHAL_FUNCTION_ENC_VDENC_PAK;
239 }
240 else
241 {
242 encodeParams.ExecCodecFunction = CODECHAL_FUNCTION_ENC_PAK;
243 }
244
245 DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
246
247 // Raw Surface
248 MOS_SURFACE rawSurface;
249 MOS_ZeroMemory(&rawSurface, sizeof(MOS_SURFACE));
250 rawSurface.Format = Format_NV12;
251 rawSurface.dwOffset = 0;
252 DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentRT, &(rawSurface.OsResource));
253
254 // Recon Surface
255 MOS_SURFACE reconSurface;
256 MOS_ZeroMemory(&reconSurface, sizeof(MOS_SURFACE));
257 reconSurface.Format = Format_NV12;
258 reconSurface.dwOffset = 0;
259 DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentReconTarget, &(reconSurface.OsResource));
260
261 //clear registered recon/ref surface flags
262 DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, false), "ClearRefList failed!");
263
264 // Bitstream surface
265 MOS_RESOURCE bitstreamSurface;
266 MOS_ZeroMemory(&bitstreamSurface, sizeof(MOS_RESOURCE));
267 bitstreamSurface = m_encodeCtx->resBitstreamBuffer; // in render picture
268 bitstreamSurface.Format = Format_Buffer;
269
270 encodeParams.psRawSurface = &rawSurface;
271 encodeParams.psReconSurface = &reconSurface;
272 encodeParams.presBitstreamBuffer = &bitstreamSurface;
273
274 MOS_SURFACE mbQpSurface;
275 if (m_encodeCtx->bMBQpEnable)
276 {
277 MOS_ZeroMemory(&mbQpSurface, sizeof(MOS_SURFACE));
278 mbQpSurface.Format = Format_Buffer_2D;
279 mbQpSurface.dwOffset = 0;
280 mbQpSurface.OsResource = m_encodeCtx->resMBQpBuffer;
281 encodeParams.psMbQpDataSurface = &mbQpSurface;
282 encodeParams.bMbQpDataEnabled = true;
283 }
284
285 encodeParams.bMbDisableSkipMapEnabled = m_encodeCtx->bMbDisableSkipMapEnabled;
286
287 MOS_SURFACE disableSkipMapSurface;
288 if (encodeParams.bMbDisableSkipMapEnabled)
289 {
290 MOS_ZeroMemory(&disableSkipMapSurface, sizeof(MOS_SURFACE));
291 disableSkipMapSurface.Format = Format_Buffer;
292 disableSkipMapSurface.dwOffset = 0;
293 disableSkipMapSurface.OsResource = m_encodeCtx->resPerMBSkipMapBuffer;
294 encodeParams.psMbDisableSkipMapSurface = &disableSkipMapSurface;
295 }
296
297 encodeParams.pMpeg2UserDataListHead = m_userDataListHead;
298
299 CodecEncodeMpeg2SequenceParams *mpeg2Sps = (CodecEncodeMpeg2SequenceParams *)m_encodeCtx->pSeqParams;
300 mpeg2Sps->m_targetUsage = m_encodeCtx->targetUsage;
301
302 encodeParams.pSeqParams = m_encodeCtx->pSeqParams;
303 encodeParams.pVuiParams = m_encodeCtx->pVuiParams;
304 encodeParams.pPicParams = m_encodeCtx->pPicParams;
305 encodeParams.pSliceParams = m_encodeCtx->pSliceParams;
306
307 // Sequence data
308 encodeParams.bNewSeq = m_encodeCtx->bNewSeq;
309 // VUI
310 encodeParams.bNewVuiData = m_encodeCtx->bNewVuiData;
311
312 // Slice level data
313 encodeParams.dwNumSlices = numSlices;
314
315 // IQmatrix params
316 encodeParams.bNewQmatrixData = m_encodeCtx->bNewQmatrixData;
317 encodeParams.bPicQuant = m_encodeCtx->bPicQuant;
318 encodeParams.ppNALUnitParams = m_encodeCtx->ppNALUnitParams;
319 encodeParams.pSeiData = m_encodeCtx->pSEIFromApp;
320 encodeParams.pSeiParamBuffer = m_encodeCtx->pSEIFromApp->pSEIBuffer;
321 encodeParams.dwSEIDataOffset = 0;
322
323 CODEC_AVC_IQ_MATRIX_PARAMS iqMatrixParams;
324 MOS_STATUS status = MOS_SecureMemcpy(&iqMatrixParams.ScalingList4x4,
325 6 * 16 * sizeof(uint8_t),
326 &m_scalingLists4x4,
327 6 * 16 * sizeof(uint8_t));
328 if (MOS_STATUS_SUCCESS != status)
329 {
330 DDI_ASSERTMESSAGE("DDI:Failed to copy scaling list 4x4!");
331 return VA_STATUS_ERROR_INVALID_PARAMETER;
332 }
333
334 status = MOS_SecureMemcpy(&iqMatrixParams.ScalingList8x8,
335 2 * 64 * sizeof(uint8_t),
336 &m_scalingLists8x8,
337 2 * 64 * sizeof(uint8_t));
338 if (MOS_STATUS_SUCCESS != status)
339 {
340 DDI_ASSERTMESSAGE("DDI:Failed to copy scaling list 8x8!");
341 return VA_STATUS_ERROR_INVALID_PARAMETER;
342 }
343
344 encodeParams.pIQMatrixBuffer = &iqMatrixParams;
345
346 // whether driver need to pack slice header
347 if (true == m_encodeCtx->bHavePackedSliceHdr)
348 {
349 encodeParams.bAcceleratorHeaderPackingCaps = false;
350 }
351 else
352 {
353 encodeParams.bAcceleratorHeaderPackingCaps = true;
354 }
355
356 encodeParams.pBSBuffer = m_encodeCtx->pbsBuffer;
357 encodeParams.pSlcHeaderData = (void *)m_encodeCtx->pSliceHeaderData;
358
359 status = m_encodeCtx->pCodecHal->Execute(&encodeParams);
360 if (MOS_STATUS_SUCCESS != status)
361 {
362 DDI_ASSERTMESSAGE("DDI:Failed in Codechal!");
363 return VA_STATUS_ERROR_ENCODING_ERROR;
364 }
365
366 return VA_STATUS_SUCCESS;
367 }
368
369 // parse quant matrix extension from app
Qmatrix(void * ptr)370 VAStatus DdiEncodeMpeg2::Qmatrix(void *ptr)
371 {
372 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
373 DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
374
375 VAIQMatrixBufferMPEG2 *qMatrix = (VAQMatrixBufferMPEG2 *)ptr;
376
377 CodecEncodeMpeg2QmatixParams *mpeg2QParams = (CodecEncodeMpeg2QmatixParams *)m_encodeCtx->pQmatrixParams;
378 DDI_CHK_NULL(mpeg2QParams, "nullptr mpeg2QParams", VA_STATUS_ERROR_INVALID_PARAMETER);
379
380 mpeg2QParams->m_newQmatrix[0] = qMatrix->load_intra_quantiser_matrix;
381 mpeg2QParams->m_newQmatrix[1] = qMatrix->load_non_intra_quantiser_matrix;
382 mpeg2QParams->m_newQmatrix[2] = qMatrix->load_chroma_intra_quantiser_matrix;
383 mpeg2QParams->m_newQmatrix[3] = qMatrix->load_chroma_non_intra_quantiser_matrix;
384
385 if (mpeg2QParams->m_newQmatrix[0])
386 {
387 for (uint8_t idx = 0; idx < 64; idx++)
388 {
389 mpeg2QParams->m_qmatrix[0][CODEC_AVC_Qmatrix_scan_8x8[idx]] = qMatrix->intra_quantiser_matrix[idx];
390 }
391 }
392 if (mpeg2QParams->m_newQmatrix[1])
393 {
394 for (uint8_t idx = 0; idx < 64; idx++)
395 {
396 mpeg2QParams->m_qmatrix[1][CODEC_AVC_Qmatrix_scan_8x8[idx]] = qMatrix->non_intra_quantiser_matrix[idx];
397 }
398 }
399 if (mpeg2QParams->m_newQmatrix[2])
400 {
401 for (uint8_t idx = 0; idx < 64; idx++)
402 {
403 mpeg2QParams->m_qmatrix[2][CODEC_AVC_Qmatrix_scan_8x8[idx]] = qMatrix->chroma_intra_quantiser_matrix[idx];
404 }
405 }
406 if (mpeg2QParams->m_newQmatrix[3])
407 {
408 for (uint8_t idx = 0; idx < 64; idx++)
409 {
410 mpeg2QParams->m_qmatrix[3][CODEC_AVC_Qmatrix_scan_8x8[idx]] = qMatrix->chroma_non_intra_quantiser_matrix[idx];
411 }
412 }
413
414 return VA_STATUS_SUCCESS;
415 }
416
417 // reset the parameters before each frame
ResetAtFrameLevel()418 VAStatus DdiEncodeMpeg2::ResetAtFrameLevel()
419 {
420 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
421
422 // Assume there is only one SPS parameter
423 CodecEncodeMpeg2SequenceParams *mpeg2SeqParams = (CodecEncodeMpeg2SequenceParams *)(m_encodeCtx->pSeqParams);
424 DDI_CHK_NULL(mpeg2SeqParams, "nullptr mpeg2SeqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
425 mpeg2SeqParams->m_resetBRC = false;
426
427 m_encodeCtx->dwNumSlices = 0x0;
428 m_encodeCtx->indexNALUnit = 0x0;
429
430 // reset bsbuffer every frame
431 m_encodeCtx->pbsBuffer->pCurrent = m_encodeCtx->pbsBuffer->pBase;
432 m_encodeCtx->pbsBuffer->SliceOffset = 0x0;
433 m_encodeCtx->pbsBuffer->BitOffset = 0x0;
434 m_encodeCtx->pbsBuffer->BitSize = 0x0;
435 m_encodeCtx->bNewVuiData = false;
436 m_encodeCtx->bMBQpEnable = false;
437
438 RemoveUserData();
439
440 // clear the packed header information
441 if (nullptr != m_encodeCtx->ppNALUnitParams)
442 {
443 MOS_ZeroMemory(m_encodeCtx->ppNALUnitParams[0], sizeof(CODECHAL_NAL_UNIT_PARAMS) * CODEC_ENCODE_MPEG2_MAX_NAL_TYPE);
444 }
445
446 return VA_STATUS_SUCCESS;
447 }
448
449 // parse mepg2 sequence parameters from app
ParseSeqParams(void * ptr)450 VAStatus DdiEncodeMpeg2::ParseSeqParams(void *ptr)
451 {
452 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
453 DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
454
455 VAEncSequenceParameterBufferMPEG2 *seqParams = (VAEncSequenceParameterBufferMPEG2 *)ptr;
456
457 CodecEncodeMpeg2SequenceParams *mpeg2Sps = (CodecEncodeMpeg2SequenceParams *)m_encodeCtx->pSeqParams;
458
459 CodecEncodeMpeg2PictureParams *halMpeg2PPS = (CodecEncodeMpeg2PictureParams *)m_encodeCtx->pPicParams;
460 DDI_CHK_NULL(mpeg2Sps, "nullptr mpeg2Sps", VA_STATUS_ERROR_INVALID_PARAMETER);
461 DDI_CHK_NULL(halMpeg2PPS, "nullptr halMpeg2PPS", VA_STATUS_ERROR_INVALID_PARAMETER);
462
463 MOS_ZeroMemory(mpeg2Sps, sizeof(CodecEncodeMpeg2SequenceParams));
464
465 mpeg2Sps->m_frameWidth = seqParams->picture_width;
466 mpeg2Sps->m_frameHeight = seqParams->picture_height;
467 mpeg2Sps->m_profile = seqParams->sequence_extension.bits.profile_and_level_indication & 0x70;
468 mpeg2Sps->m_level = seqParams->sequence_extension.bits.profile_and_level_indication & 0x0f;
469 mpeg2Sps->m_chromaFormat = seqParams->sequence_extension.bits.chroma_format;
470 mpeg2Sps->m_lowDelay = seqParams->sequence_extension.bits.low_delay;
471 mpeg2Sps->m_noAcceleratorSPSInsertion = false;
472 mpeg2Sps->m_progressiveSequence = seqParams->sequence_extension.bits.progressive_sequence;
473 mpeg2Sps->m_rateControlMethod = VARC2HalRC(m_encodeCtx->uiRCMethod);
474 mpeg2Sps->m_resetBRC = false; // if reset the brc each i frame
475 mpeg2Sps->m_bitrate = seqParams->bits_per_second;
476 mpeg2Sps->m_vbvBufferSize = seqParams->vbv_buffer_size;
477 //set Initial vbv buffer fullness to half of vbv buffer size in byte
478 mpeg2Sps->m_initVBVBufferFullnessInBit = seqParams->vbv_buffer_size * (CODEC_ENCODE_MPEG2_VBV_BUFFER_SIZE_UNITS >> 1);
479 mpeg2Sps->m_maxBitRate = mpeg2Sps->m_bitrate;
480 mpeg2Sps->m_minBitRate = mpeg2Sps->m_bitrate;
481
482 if ((m_encodeCtx->uiRCMethod == VA_RC_CBR) && (seqParams->vbv_buffer_size > 0))
483 {
484 //set maxframe size to half of vbv buffer size in byte, in codechal, this value will set the minimum value between this value and picture_with * picture_height
485 mpeg2Sps->m_userMaxFrameSize = seqParams->vbv_buffer_size * (CODEC_ENCODE_MPEG2_VBV_BUFFER_SIZE_UNITS >> 4);
486 }
487 else
488 {
489 mpeg2Sps->m_userMaxFrameSize = seqParams->picture_width * seqParams->picture_height * 3 / 2;
490 }
491
492 mpeg2Sps->m_aspectRatio = seqParams->aspect_ratio_information;
493 mpeg2Sps->m_frameRateExtD = seqParams->sequence_extension.bits.frame_rate_extension_d;
494 mpeg2Sps->m_frameRateExtN = seqParams->sequence_extension.bits.frame_rate_extension_n;
495 if(seqParams->frame_rate <= 0.0)
496 {
497 DDI_NORMALMESSAGE("invalidate frame rate code, set it to default 30");
498 seqParams->frame_rate = 30;
499 }
500 mpeg2Sps->m_frameRateCode = (uint32_t)CalculateFramerateCode(seqParams->frame_rate, mpeg2Sps->m_frameRateExtD, mpeg2Sps->m_frameRateExtN);
501
502 halMpeg2PPS->m_gopPicSize = seqParams->intra_period;
503 halMpeg2PPS->m_gopRefDist = seqParams->ip_period;
504 m_timeCode = seqParams->gop_header.bits.time_code;
505 m_newTimeCode = true;
506 halMpeg2PPS->m_gopOptFlag = seqParams->gop_header.bits.closed_gop;
507
508 return VA_STATUS_SUCCESS;
509 }
510
511 // parse mepg2 picture prarameters from app
ParsePicParams(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr)512 VAStatus DdiEncodeMpeg2::ParsePicParams(
513 DDI_MEDIA_CONTEXT *mediaCtx,
514 void *ptr)
515 {
516 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
517 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
518 DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
519
520 DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
521
522 VAEncPictureParameterBufferMPEG2 *picParams = (VAEncPictureParameterBufferMPEG2 *)ptr;
523
524 CodecEncodeMpeg2PictureParams *mpeg2PicParams = (CodecEncodeMpeg2PictureParams *)(m_encodeCtx->pPicParams);
525 DDI_CHK_NULL(mpeg2PicParams, "nullptr mpeg2PicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
526
527 CodecEncodeMpeg2SequenceParams *mpeg2SeqParams = (CodecEncodeMpeg2SequenceParams *)(m_encodeCtx->pSeqParams);
528 DDI_CHK_NULL(mpeg2SeqParams, "nullptr mpeg2SeqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
529
530 float frameRate = 0;
531 if ((mpeg2SeqParams->m_frameRateCode > 0) && (mpeg2SeqParams->m_frameRateCode < (sizeof(frameRateTable) / sizeof(frameRateTable[0]))))
532 {
533 //calculate real frame rate from frame_rate_code, frame_rate_extension_n and frame_rate_extension_d
534 frameRate = frameRateTable[mpeg2SeqParams->m_frameRateCode - 1].value * (mpeg2SeqParams->m_frameRateExtN + 1) / (mpeg2SeqParams->m_frameRateExtD + 1);
535 }
536 else
537 {
538 //frame_rate_code is invalid, set frame_rate to 30 defaultly.
539 frameRate = 30.0;
540 }
541
542 uint32_t frameRateRounded = (uint32_t)(frameRate * 100 + 50) / 100;
543
544 mpeg2PicParams->m_lastPicInStream = picParams->last_picture;
545 mpeg2PicParams->m_pictureCodingType = picParams->picture_type == VAEncPictureTypeIntra ? I_TYPE : (picParams->picture_type == VAEncPictureTypePredictive ? P_TYPE : B_TYPE);
546 mpeg2PicParams->m_interleavedFieldBFF = !picParams->picture_coding_extension.bits.top_field_first;
547 mpeg2PicParams->m_fieldCodingFlag = false;
548 mpeg2PicParams->m_fieldFrameCodingFlag = (!mpeg2SeqParams->m_progressiveSequence) && (!picParams->picture_coding_extension.bits.progressive_frame);
549 mpeg2PicParams->m_pic4MVallowed = 1;
550 mpeg2PicParams->m_fcode00 = picParams->f_code[0][0];
551 mpeg2PicParams->m_fcode01 = picParams->f_code[0][1];
552 mpeg2PicParams->m_fcode10 = picParams->f_code[1][0];
553 mpeg2PicParams->m_fcode11 = picParams->f_code[1][1];
554 mpeg2PicParams->m_intraDCprecision = picParams->picture_coding_extension.bits.intra_dc_precision;
555 mpeg2PicParams->m_concealmentMotionVectors = picParams->picture_coding_extension.bits.concealment_motion_vectors;
556 mpeg2PicParams->m_qscaleType = picParams->picture_coding_extension.bits.q_scale_type; //determin quantiser_scale with scale code
557
558 mpeg2PicParams->m_intraVlcFormat = picParams->picture_coding_extension.bits.intra_vlc_format;
559 mpeg2PicParams->m_alternateScan = picParams->picture_coding_extension.bits.alternate_scan;
560 mpeg2PicParams->m_framePredFrameDCT = picParams->picture_coding_extension.bits.frame_pred_frame_dct;
561
562 mpeg2PicParams->m_progressiveField = picParams->picture_coding_extension.bits.progressive_frame;
563 mpeg2PicParams->m_repeatFirstField = picParams->picture_coding_extension.bits.repeat_first_field;
564 mpeg2PicParams->m_compositeDisplayFlag = picParams->picture_coding_extension.bits.composite_display_flag;
565 mpeg2PicParams->m_temporalReference = picParams->temporal_reference;
566 mpeg2PicParams->m_vbvDelay = picParams->vbv_delay;
567
568 if (mpeg2PicParams->m_compositeDisplayFlag == 1)
569 {
570 mpeg2PicParams->m_vaxis = picParams->composite_display.bits.v_axis;
571 mpeg2PicParams->m_fieldSequence = picParams->composite_display.bits.field_sequence;
572 mpeg2PicParams->m_subCarrier = picParams->composite_display.bits.sub_carrier;
573 mpeg2PicParams->m_burstAmplitude = picParams->composite_display.bits.burst_amplitude;
574 mpeg2PicParams->m_subCarrierPhase = picParams->composite_display.bits.sub_carrier_phase;
575 }
576 if ( picParams->reconstructed_picture == VA_INVALID_SURFACE)
577 {
578 return VA_STATUS_ERROR_INVALID_PARAMETER;
579 }
580 auto recon = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParams->reconstructed_picture);
581 DDI_CHK_RET(RegisterRTSurfaces(&m_encodeCtx->RTtbl, recon),"RegisterRTSurfaces failed!");
582
583 mpeg2PicParams->m_currReconstructedPic.FrameIdx = GetRenderTargetID(rtTbl, recon);
584 mpeg2PicParams->m_currReconstructedPic.PicFlags = PICTURE_FRAME;
585
586 // be attention , that codec hal use this value to manager the reference list
587 mpeg2PicParams->m_currOriginalPic.FrameIdx = GetRenderTargetID(rtTbl, recon);
588 mpeg2PicParams->m_currOriginalPic.PicFlags = mpeg2PicParams->m_currReconstructedPic.PicFlags;
589
590 if (DDI_CODEC_INVALID_FRAME_INDEX != picParams->forward_reference_picture)
591 {
592 auto fwRef = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParams->forward_reference_picture);
593 UpdateRegisteredRTSurfaceFlag(&m_encodeCtx->RTtbl,fwRef);
594 mpeg2PicParams->m_refFrameList[0].FrameIdx = GetRenderTargetID(rtTbl, fwRef);
595 mpeg2PicParams->m_refFrameList[0].PicFlags = PICTURE_FRAME;
596 }
597 else
598 {
599 mpeg2PicParams->m_refFrameList[0].FrameIdx = (uint8_t)DDI_CODEC_INVALID_FRAME_INDEX;
600 mpeg2PicParams->m_refFrameList[0].PicFlags = PICTURE_INVALID;
601 }
602 if (DDI_CODEC_INVALID_FRAME_INDEX != picParams->backward_reference_picture)
603 {
604 auto bwRef = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParams->backward_reference_picture);
605 UpdateRegisteredRTSurfaceFlag(&m_encodeCtx->RTtbl,bwRef);
606 mpeg2PicParams->m_refFrameList[1].FrameIdx = GetRenderTargetID(rtTbl, bwRef);
607 mpeg2PicParams->m_refFrameList[1].PicFlags = PICTURE_FRAME;
608 }
609 else
610 {
611 mpeg2PicParams->m_refFrameList[1].FrameIdx = (uint8_t)DDI_CODEC_INVALID_FRAME_INDEX;
612 mpeg2PicParams->m_refFrameList[1].PicFlags = PICTURE_INVALID;
613 }
614 if (mpeg2PicParams->m_pictureCodingType == I_TYPE)
615 {
616 mpeg2PicParams->m_newGop = true;
617 }
618 else
619 {
620 mpeg2PicParams->m_newGop = false;
621 }
622 rtTbl->pCurrentReconTarget = recon;;
623
624 DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, picParams->coded_buf);
625
626 DDI_CHK_NULL(buf, "nullptr buf", VA_STATUS_ERROR_INVALID_PARAMETER);
627 RemoveFromStatusReportQueue(buf);
628 DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resBitstreamBuffer));
629 mpeg2PicParams->m_numSlice = 0;
630
631 //According to MPEG2 spec, GOP header time_code include 6 fields and the ranges of values are Hour (0~23), Minute(0~59), Marker bit(always 1), Second (0~59), Picuture (0~59), Drop_frame flag( 0 or 1).
632 //split timecode to element
633 uint32_t timeCode = m_timeCode;
634
635 uint32_t timeCodeDropframe = (timeCode >> 24) & 0x1;
636
637 uint32_t timeCodeHr = (timeCode >> 19) & 0x1f;
638
639 uint32_t timeCodeMin = (timeCode >> 13) & 0x3f;
640
641 uint32_t timeCodeMarkerBit = 0x1;
642
643 uint32_t timeCodeSec = (timeCode >> 6) & 0x3f;
644
645 uint32_t timeCodePic = (timeCode)&0x3f;
646 //update each timecode element when parsing new picparams
647 if (false == m_newTimeCode)
648 {
649 timeCodePic++;
650 if (timeCodePic >= frameRateRounded)
651 {
652 timeCodePic = 0;
653 timeCodeSec++;
654 }
655 if (timeCodeSec > maxTimeCodeSec)
656 {
657 timeCodeSec = 0;
658 timeCodeMin++;
659 }
660 if (timeCodeMin > maxTimeCodeMin)
661 {
662 timeCodeMin = 0;
663 timeCodeHr++;
664 }
665 if (timeCodeHr > maxTimeCodeHr)
666 {
667 timeCodeHr = 0;
668 }
669 }
670 else
671 {
672 m_newTimeCode = false;
673 }
674
675 //fill all updated elements back to timecode in the format used by codechal
676 mpeg2PicParams->m_timeCode = ((timeCodePic & 0x3f) |
677 ((timeCodeSec & 0x3f) << 6) |
678 ((timeCodeMarkerBit & 1) << 12) |
679 ((timeCodeMin & 0x3f) << 13) |
680 ((timeCodeHr & 0x1f) << 19) |
681 (timeCodeDropframe & 1) << 24);
682
683 m_timeCode = mpeg2PicParams->m_timeCode;
684 mpeg2PicParams->m_skipFrameFlag = 0;
685 mpeg2PicParams->m_numSkipFrames = 0;
686 mpeg2PicParams->m_sizeSkipFrames = 0;
687
688 return VA_STATUS_SUCCESS;
689 }
690
691 // parse mpeg2 slice parameters from app
ParseSlcParams(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr,uint32_t numSlices)692 VAStatus DdiEncodeMpeg2::ParseSlcParams(
693 DDI_MEDIA_CONTEXT *mediaCtx,
694 void *ptr,
695 uint32_t numSlices)
696 {
697 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
698 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
699 DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
700
701 VAEncSliceParameterBufferMPEG2 *vaEncSlcParamsMPEG2 = (VAEncSliceParameterBufferMPEG2 *)ptr;
702
703 CodecEncodeMpeg2SliceParmas *mpeg2SlcParams = (CodecEncodeMpeg2SliceParmas *)m_encodeCtx->pSliceParams;
704
705 CodecEncodeMpeg2PictureParams *mpeg2PicParams = (CodecEncodeMpeg2PictureParams *)(m_encodeCtx->pPicParams);
706 DDI_CHK_NULL(mpeg2SlcParams, "nullptr mpeg2SlcParams", VA_STATUS_ERROR_INVALID_PARAMETER);
707 DDI_CHK_NULL(mpeg2PicParams, "nullptr mpeg2PicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
708
709 // Move to a free MPEG2Slice parameter buffer
710 uint8_t numOfSlices = m_encodeCtx->dwNumSlices;
711 mpeg2SlcParams += numOfSlices;
712
713 //attention memory area protection
714 MOS_ZeroMemory(mpeg2SlcParams, sizeof(CodecEncodeMpeg2SliceParmas) * numSlices);
715
716 CodecEncodeMpeg2SequenceParams *mpeg2Sps = (CodecEncodeMpeg2SequenceParams *)m_encodeCtx->pSeqParams;
717 auto picWidthInMb = CODECHAL_GET_WIDTH_IN_MACROBLOCKS(mpeg2Sps->m_frameWidth);
718
719 for (uint32_t slcCount = 0; slcCount < numSlices; slcCount++)
720 {
721 mpeg2SlcParams->m_numMbsForSlice = vaEncSlcParamsMPEG2->num_macroblocks;
722 mpeg2SlcParams->m_firstMbX = (vaEncSlcParamsMPEG2->macroblock_address % picWidthInMb);
723 mpeg2SlcParams->m_firstMbY = vaEncSlcParamsMPEG2->macroblock_address / picWidthInMb;
724 mpeg2SlcParams->m_intraSlice = vaEncSlcParamsMPEG2->is_intra_slice;
725 mpeg2SlcParams->m_quantiserScaleCode = vaEncSlcParamsMPEG2->quantiser_scale_code;
726 mpeg2SlcParams++;
727 vaEncSlcParamsMPEG2++;
728 }
729 m_encodeCtx->dwNumSlices += numSlices;
730 mpeg2PicParams->m_numSlice = m_encodeCtx->dwNumSlices;
731
732 return VA_STATUS_SUCCESS;
733 }
734
735 // Since sequence header and picture header will be packed in codechal, we don't support packed header from application
ParsePackedHeaderParams(void * ptr)736 VAStatus DdiEncodeMpeg2::ParsePackedHeaderParams(void *ptr)
737 {
738 DDI_CHK_NULL(ptr, "invalid paked header pointer", VA_STATUS_ERROR_INVALID_PARAMETER);
739 DDI_CHK_NULL(m_encodeCtx, "invalid encode context", VA_STATUS_ERROR_INVALID_CONTEXT);
740
741 VAEncPackedHeaderParameterBuffer *packedHeaderParamBuf = (VAEncPackedHeaderParameterBuffer *)ptr;
742 if (packedHeaderParamBuf->type != VAEncPackedHeaderRawData)
743 {
744 return VA_STATUS_ERROR_INVALID_PARAMETER;
745 }
746
747 CodecEncodeMpeg2UserDataList *userDataNode = (CodecEncodeMpeg2UserDataList *)MOS_AllocAndZeroMemory(sizeof(CodecEncodeMpeg2UserDataList));
748 DDI_CHK_NULL(userDataNode, "nullptr userDataNode.", VA_STATUS_ERROR_ALLOCATION_FAILED);
749
750 if (nullptr == m_userDataListHead)
751 {
752 m_userDataListHead = userDataNode;
753 m_userDataListTail = nullptr;
754 }
755 if (m_userDataListTail)
756 {
757 CodecEncodeMpeg2UserDataList *userDataListTail = (CodecEncodeMpeg2UserDataList *)m_userDataListTail;
758 userDataListTail->m_nextItem = userDataNode;
759 }
760 m_userDataListTail = userDataNode;
761
762 uint32_t size = (packedHeaderParamBuf->bit_length + 7) >> 3;
763 userDataNode->m_userData = MOS_AllocAndZeroMemory(size);
764 if (nullptr == userDataNode->m_userData)
765 {
766 MOS_FreeMemory(userDataNode);
767 return VA_STATUS_ERROR_ALLOCATION_FAILED;
768 }
769 userDataNode->m_userDataSize = size;
770
771 return VA_STATUS_SUCCESS;
772 }
773 // Since sequence header and picture header will be packed in codechal, we don't support packed header from application
ParsePackedHeaderData(void * ptr)774 VAStatus DdiEncodeMpeg2::ParsePackedHeaderData(void *ptr)
775 {
776 DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
777 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
778
779 CodecEncodeMpeg2UserDataList *userDataListTail = (CodecEncodeMpeg2UserDataList *)m_userDataListTail;
780 if (userDataListTail && userDataListTail->m_userDataSize)
781 {
782 MOS_SecureMemcpy(
783 userDataListTail->m_userData,
784 userDataListTail->m_userDataSize,
785 ptr,
786 userDataListTail->m_userDataSize);
787 return VA_STATUS_SUCCESS;
788 }
789 return VA_STATUS_ERROR_INVALID_PARAMETER;
790 }
791
792 // it should be named DdiMpeg2Encode_ParseMiscParamVBV, because HRD is used by AVC, VBV is used by MPEG2
ParseMiscParamVBV(void * data)793 void DdiEncodeMpeg2::ParseMiscParamVBV(void *data)
794 {
795 VAEncMiscParameterHRD *vaEncMiscParamHRD = (VAEncMiscParameterHRD *)data;
796
797 CodecEncodeMpeg2SequenceParams *mpeg2SeqParams = (CodecEncodeMpeg2SequenceParams *)m_encodeCtx->pSeqParams;
798
799 mpeg2SeqParams->m_vbvBufferSize = vaEncMiscParamHRD->buffer_size / CODEC_ENCODE_MPEG2_VBV_BUFFER_SIZE_UNITS;
800 mpeg2SeqParams->m_initVBVBufferFullnessInBit = vaEncMiscParamHRD->initial_buffer_fullness;
801 //mpeg2SeqParams->m_rateControlMethod = RATECONTROL_CBR;
802 }
803
804 // Parse the frame rate paramters from app
ParseMiscParamFR(void * data)805 void DdiEncodeMpeg2::ParseMiscParamFR(void *data)
806 {
807 CodecEncodeMpeg2SequenceParams *mpeg2SeqParams = (CodecEncodeMpeg2SequenceParams *)(m_encodeCtx->pSeqParams);
808
809 VAEncMiscParameterFrameRate *vaencMiscParamFR = (VAEncMiscParameterFrameRate *)data;
810
811 float frameRate = (float)(vaencMiscParamFR->framerate & 0xffff);
812 uint32_t denominator = (vaencMiscParamFR->framerate >> 16) & 0xffff;
813 if(denominator == 0)
814 {
815 denominator = 1;
816 }
817 frameRate = frameRate / denominator;
818 if(frameRate <= 0.0)
819 {
820 DDI_NORMALMESSAGE("invalidate frame rate code, set it to default 30");
821 frameRate = 30;
822 }
823 mpeg2SeqParams->m_frameRateCode = (uint32_t)CalculateFramerateCode(frameRate,
824 mpeg2SeqParams->m_frameRateExtD,
825 mpeg2SeqParams->m_frameRateExtN);
826 }
827
828 // Parse rate control related information from app
ParseMiscParamRC(void * data)829 void DdiEncodeMpeg2::ParseMiscParamRC(void *data)
830 {
831 VAEncMiscParameterRateControl *vaEncMiscParamRC = (VAEncMiscParameterRateControl *)data;
832
833 CodecEncodeMpeg2SequenceParams *mpeg2SeqParams = (CodecEncodeMpeg2SequenceParams *)(m_encodeCtx->pSeqParams);
834
835 mpeg2SeqParams->m_bitrate = MOS_ROUNDUP_DIVIDE(vaEncMiscParamRC->bits_per_second, CODECHAL_ENCODE_BRC_KBPS);
836
837 if (VA_RC_CQP == m_encodeCtx->uiRCMethod)
838 {
839 mpeg2SeqParams->m_rateControlMethod = (RATECONTROL_CBR | RATECONTROL_VBR);
840 }
841
842 if (VA_RC_CBR == m_encodeCtx->uiRCMethod)
843 {
844 mpeg2SeqParams->m_maxBitRate = mpeg2SeqParams->m_bitrate;
845 mpeg2SeqParams->m_minBitRate = mpeg2SeqParams->m_bitrate;
846 mpeg2SeqParams->m_rateControlMethod = RATECONTROL_CBR;
847 }
848 else
849 {
850 mpeg2SeqParams->m_maxBitRate = mpeg2SeqParams->m_bitrate;
851 if (vaEncMiscParamRC->target_percentage > 50)
852 {
853 mpeg2SeqParams->m_minBitRate = mpeg2SeqParams->m_bitrate * (2 * vaEncMiscParamRC->target_percentage - 100) / 100;
854 }
855 else
856 {
857 mpeg2SeqParams->m_minBitRate = 0;
858 }
859
860 mpeg2SeqParams->m_bitrate = mpeg2SeqParams->m_bitrate * vaEncMiscParamRC->target_percentage / 100;
861 mpeg2SeqParams->m_rateControlMethod = RATECONTROL_VBR;
862
863 if ((m_encodeCtx->uiTargetBitRate != mpeg2SeqParams->m_bitrate) ||
864 (m_encodeCtx->uiMaxBitRate != mpeg2SeqParams->m_maxBitRate))
865 {
866 mpeg2SeqParams->m_resetBRC = 0x1;
867 m_encodeCtx->uiTargetBitRate = mpeg2SeqParams->m_bitrate;
868 m_encodeCtx->uiMaxBitRate = mpeg2SeqParams->m_maxBitRate;
869 }
870 }
871 }
872
873 // Parse some other parameters, now there are no Private data from APP
ParseMiscParamEncQuality(void * data)874 void DdiEncodeMpeg2::ParseMiscParamEncQuality(void *data)
875 {
876 VAEncMiscParameterEncQuality *vaEncMiscParamEncQuality = (VAEncMiscParameterEncQuality *)data;
877
878 CodecEncodeMpeg2SequenceParams *mpeg2SeqParams = (CodecEncodeMpeg2SequenceParams *)(m_encodeCtx->pSeqParams);
879
880 mpeg2SeqParams->m_forcePanicModeControl = 1;
881 mpeg2SeqParams->m_panicModeDisable = (uint8_t)vaEncMiscParamEncQuality->PanicModeDisable;
882
883 }
884
ParseMiscParamEncQualityLevel(void * data)885 void DdiEncodeMpeg2::ParseMiscParamEncQualityLevel(void *data)
886 {
887 VAEncMiscParameterBufferQualityLevel *vaMiscParamQualityLevel = (VAEncMiscParameterBufferQualityLevel*) data;
888 m_encodeCtx->targetUsage= vaMiscParamQualityLevel->quality_level;
889 // check TU, correct to default if wrong
890 if ((m_encodeCtx->targetUsage > TARGETUSAGE_BEST_SPEED) ||
891 (0 == m_encodeCtx->targetUsage))
892 {
893 m_encodeCtx->targetUsage = TARGETUSAGE_RT_SPEED;
894 DDI_ASSERTMESSAGE("Target usage from application is not correct, should be in [0,7]!\n");
895 }
896 }
897
ParseMiscParamMaxFrame(void * data)898 void DdiEncodeMpeg2::ParseMiscParamMaxFrame(void *data)
899 {
900 if (nullptr == m_encodeCtx || nullptr == data)
901 {
902 DDI_ASSERTMESSAGE("invalidate input parameters.");
903 return;
904 }
905
906 CodecEncodeMpeg2SequenceParams *mpeg2SeqParams = (CodecEncodeMpeg2SequenceParams *)(m_encodeCtx->pSeqParams);
907
908 VAEncMiscParameterBufferMaxFrameSize *maxFrameSize = (VAEncMiscParameterBufferMaxFrameSize *)data;
909
910 mpeg2SeqParams->m_userMaxFrameSize = maxFrameSize->max_frame_size;
911 }
912
ParseMiscParamTypeExtension(void * data)913 void DdiEncodeMpeg2::ParseMiscParamTypeExtension(void *data)
914 {
915 if (nullptr == m_encodeCtx || nullptr == data)
916 {
917 DDI_ASSERTMESSAGE("invalidate input parameters.");
918 return;
919 }
920
921 CodecEncodeMpeg2VuiParams *mpeg2VuiParams = (CodecEncodeMpeg2VuiParams *)(m_encodeCtx->pVuiParams);
922
923 VAEncMiscParameterExtensionDataSeqDisplayMPEG2 *displayExt = (VAEncMiscParameterExtensionDataSeqDisplayMPEG2 *)data;
924
925 if (displayExt->extension_start_code_identifier != Mpeg2sequenceDisplayExtension)
926 {
927 return;
928 }
929
930 m_encodeCtx->bNewVuiData = true;
931 mpeg2VuiParams->m_videoFormat = displayExt->video_format;
932 mpeg2VuiParams->m_colourDescription = displayExt->colour_description;
933 mpeg2VuiParams->m_colourPrimaries = displayExt->colour_primaries;
934 mpeg2VuiParams->m_transferCharacteristics = displayExt->transfer_characteristics;
935 mpeg2VuiParams->m_matrixCoefficients = displayExt->matrix_coefficients;
936 mpeg2VuiParams->m_displayHorizontalSize = displayExt->display_horizontal_size;
937 mpeg2VuiParams->m_displayVerticalSize = displayExt->display_vertical_size;
938 }
939
940 // parse VAEncMiscParameterSkipFrame to PCODEC_MPEG2_ENCODE_PIC_PARAMS
ParseMiscParamSkipFrame(void * data)941 void DdiEncodeMpeg2::ParseMiscParamSkipFrame(void *data)
942 {
943 if (nullptr == m_encodeCtx || nullptr == data)
944 {
945 DDI_ASSERTMESSAGE("invalidate input parameters.");
946 return;
947 }
948
949 // Assume only one PPS here, modify when enable multiple PPS support
950 CodecEncodeMpeg2PictureParams *mpeg2PicParams = (CodecEncodeMpeg2PictureParams *)(m_encodeCtx->pPicParams);
951
952 VAEncMiscParameterSkipFrame *vaEncMiscParamSkipFrame = (VAEncMiscParameterSkipFrame *)data;
953
954 if (nullptr == mpeg2PicParams)
955 {
956 DDI_ASSERTMESSAGE("invalidate mpeg2 picture header.");
957 return;
958 }
959 //MPEG2 only support normal skip frame
960 if (FRAME_SKIP_NORMAL < mpeg2PicParams->m_skipFrameFlag)
961 {
962 DDI_ASSERTMESSAGE("invalidate input parameters, skip_frame_flag should equal to 0 or 1.");
963 return;
964 }
965
966 // populate skipped frame params from DDI
967 mpeg2PicParams->m_skipFrameFlag = vaEncMiscParamSkipFrame->skip_frame_flag;
968 mpeg2PicParams->m_numSkipFrames = vaEncMiscParamSkipFrame->num_skip_frames;
969 mpeg2PicParams->m_sizeSkipFrames = vaEncMiscParamSkipFrame->size_skip_frames;
970 }
971
972 // Parse Misc Params
ParseMiscParams(void * ptr)973 VAStatus DdiEncodeMpeg2::ParseMiscParams(void *ptr)
974 {
975 DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
976 DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
977
978 VAEncMiscParameterBuffer *miscParamBuf = (VAEncMiscParameterBuffer *)ptr;
979 DDI_CHK_NULL(miscParamBuf->data, "nullptr miscParamBuf->data", VA_STATUS_ERROR_INVALID_PARAMETER);
980
981 switch ((int32_t)(miscParamBuf->type))
982 {
983 case VAEncMiscParameterTypeHRD:
984 {
985 ParseMiscParamVBV((void *)miscParamBuf->data);
986 break;
987 }
988 case VAEncMiscParameterTypeFrameRate:
989 {
990 ParseMiscParamFR((void *)miscParamBuf->data);
991 break;
992 }
993 case VAEncMiscParameterTypeRateControl:
994 {
995 ParseMiscParamRC((void *)miscParamBuf->data);
996 break;
997 }
998 case VAEncMiscParameterTypeEncQuality:
999 {
1000 ParseMiscParamEncQuality((void *)miscParamBuf->data);
1001 break;
1002 }
1003 case VAEncMiscParameterTypeMaxFrameSize:
1004 {
1005 ParseMiscParamMaxFrame((void *)miscParamBuf->data);
1006 break;
1007 }
1008 case VAEncMiscParameterTypeExtensionData:
1009 {
1010 ParseMiscParamTypeExtension((void *)miscParamBuf->data);
1011 break;
1012 }
1013 case VAEncMiscParameterTypeSkipFrame:
1014 {
1015 ParseMiscParamSkipFrame((void *)miscParamBuf->data);
1016 break;
1017 }
1018 case VAEncMiscParameterTypeQualityLevel:
1019 {
1020 ParseMiscParamEncQualityLevel((void *)miscParamBuf->data);
1021 break;
1022 }
1023
1024 default:
1025 {
1026 DDI_ASSERTMESSAGE("DDI: unsupported misc parameter type.");
1027 return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
1028 }
1029 }
1030
1031 return VA_STATUS_SUCCESS;
1032 }
1033
1034 // get framerate code from frame rate value;
1035 // frame_rate = frame_rate_value * (frame_rate_extension_n + 1) (frame_rate_extension_d + 1)
CalculateFramerateCode(float frameRate,uint8_t frameRateExtD,uint8_t frameRateExtN)1036 uint32_t DdiEncodeMpeg2::CalculateFramerateCode(
1037 float frameRate,
1038 uint8_t frameRateExtD,
1039 uint8_t frameRateExtN)
1040 {
1041 if (frameRate <= 0.0)
1042 {
1043 return 0;
1044 }
1045
1046 float frameRateValue = frameRate * (frameRateExtD + 1) / (frameRateExtN + 1);
1047
1048 uint32_t delta = 0xffffffff;
1049 uint32_t frameRateCode = 0;
1050 for (uint32_t i = 0; i < sizeof(frameRateTable) / sizeof(frameRateTable[0]); i++)
1051 {
1052 float tempResidual = frameRateTable[i].value - frameRateValue;
1053 tempResidual = tempResidual < 0 ? -tempResidual : tempResidual;
1054
1055 uint32_t residual = (uint32_t)(tempResidual * 1000);
1056 if (residual < delta)
1057 {
1058 delta = residual;
1059 frameRateCode = frameRateTable[i].code;
1060 }
1061 }
1062 // if the gap from spec and custom requirement is too huge, error will be report
1063 if (delta > 1000)
1064 {
1065 return 0;
1066 }
1067 else
1068 {
1069 return frameRateCode;
1070 }
1071 }
1072
RemoveUserData()1073 VAStatus DdiEncodeMpeg2::RemoveUserData()
1074 {
1075 DDI_CHK_NULL(m_encodeCtx, "invalid encode context", VA_STATUS_ERROR_INVALID_CONTEXT);
1076
1077 if (m_userDataListHead)
1078 {
1079 CodecEncodeMpeg2UserDataList *cur = nullptr;
1080 CodecEncodeMpeg2UserDataList *next = nullptr;
1081 for (cur = (CodecEncodeMpeg2UserDataList *)m_userDataListHead; cur != nullptr; cur = next)
1082 {
1083 next = cur->m_nextItem;
1084 MOS_FreeMemory(cur->m_userData);
1085 MOS_FreeMemory(cur);
1086 }
1087 m_userDataListHead = nullptr;
1088 m_userDataListTail = nullptr;
1089 }
1090 return VA_STATUS_SUCCESS;
1091 }
1092
getSliceParameterBufferSize()1093 uint32_t DdiEncodeMpeg2::getSliceParameterBufferSize()
1094 {
1095 return sizeof(VAEncSliceParameterBufferMPEG2);
1096 }
1097
getSequenceParameterBufferSize()1098 uint32_t DdiEncodeMpeg2::getSequenceParameterBufferSize()
1099 {
1100 return sizeof(VAEncSequenceParameterBufferMPEG2);
1101 }
1102
getPictureParameterBufferSize()1103 uint32_t DdiEncodeMpeg2::getPictureParameterBufferSize()
1104 {
1105 return sizeof(VAEncPictureParameterBufferMPEG2);
1106 }
1107
getQMatrixBufferSize()1108 uint32_t DdiEncodeMpeg2::getQMatrixBufferSize()
1109 {
1110 return sizeof(VAIQMatrixBufferMPEG2);
1111 }
1112