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