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_base.cpp
24 //! \brief    Implements base class for DDI media encode and encode parameters parser
25 //!
26 
27 #include "media_libva_util.h"
28 #include "media_libva_common.h"
29 #include "media_ddi_encode_base.h"
30 
DdiEncodeBase()31 DdiEncodeBase::DdiEncodeBase()
32     :DdiMediaBase()
33 {
34     m_codechalSettings = CodechalSetting::CreateCodechalSetting();
35 }
36 
BeginPicture(VADriverContextP ctx,VAContextID context,VASurfaceID renderTarget)37 VAStatus DdiEncodeBase::BeginPicture(
38     VADriverContextP    ctx,
39     VAContextID         context,
40     VASurfaceID         renderTarget)
41 {
42     DDI_FUNCTION_ENTER();
43 
44     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
45 
46     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
47     DDI_CHK_NULL(mediaCtx, "Null mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
48 
49     DDI_MEDIA_SURFACE *curRT = (DDI_MEDIA_SURFACE *)DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, renderTarget);
50     DDI_CHK_NULL(curRT, "Null curRT", VA_STATUS_ERROR_INVALID_SURFACE);
51 
52     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
53     // raw input frame
54     rtTbl->pCurrentRT = curRT;
55     if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC)
56     {
57         DDI_CHK_RET(RegisterRTSurfaces(rtTbl, curRT),"RegisterRTSurfaces failed!");
58     }
59     // reset some the parameters in picture level
60     ResetAtFrameLevel();
61 
62     DDI_FUNCTION_EXIT(VA_STATUS_SUCCESS);
63     return VA_STATUS_SUCCESS;
64 }
65 
EndPicture(VADriverContextP ctx,VAContextID context)66 VAStatus DdiEncodeBase::EndPicture(
67     VADriverContextP    ctx,
68     VAContextID         context)
69 {
70     DDI_FUNCTION_ENTER();
71 
72     DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
73 
74     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
75     DDI_CHK_NULL(mediaCtx, "Null mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
76 
77     VAStatus status = EncodeInCodecHal(m_encodeCtx->dwNumSlices);
78     ClearPicParams();
79     if (VA_STATUS_SUCCESS != status)
80     {
81         DDI_ASSERTMESSAGE("DDI:DdiEncode_EncodeInCodecHal return failure.");
82         return VA_STATUS_ERROR_ENCODING_ERROR;
83     }
84 
85     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
86     rtTbl->pCurrentRT                    = nullptr;
87     m_encodeCtx->bNewSeq                 = false;
88 
89     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_encodeCtx->BufMgr);
90     bufMgr->dwNumSliceData           = 0;
91     bufMgr->dwEncodeNumSliceControl  = 0;
92 
93     DDI_FUNCTION_EXIT(VA_STATUS_SUCCESS);
94     return VA_STATUS_SUCCESS;
95 }
96 
AddToStatusReportQueue(void * codedBuf)97 VAStatus DdiEncodeBase::AddToStatusReportQueue(void *codedBuf)
98 {
99     DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "Null m_encodeCtx->pCpDdiInterface", VA_STATUS_ERROR_INVALID_CONTEXT);
100     DDI_CHK_NULL(codedBuf, "Null codedBuf", VA_STATUS_ERROR_INVALID_BUFFER);
101 
102     int32_t idx                                       = m_encodeCtx->statusReportBuf.ulHeadPosition;
103     m_encodeCtx->statusReportBuf.infos[idx].pCodedBuf = codedBuf;
104     m_encodeCtx->statusReportBuf.infos[idx].uiSize    = 0;
105     m_encodeCtx->statusReportBuf.infos[idx].uiStatus  = 0;
106     MOS_STATUS status = m_encodeCtx->pCpDdiInterface->StoreCounterToStatusReport(&m_encodeCtx->statusReportBuf.infos[idx]);
107     if (status != MOS_STATUS_SUCCESS)
108     {
109         return VA_STATUS_ERROR_INVALID_BUFFER;
110     }
111     m_encodeCtx->statusReportBuf.ulHeadPosition = (m_encodeCtx->statusReportBuf.ulHeadPosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
112 
113     return VA_STATUS_SUCCESS;
114 
115 }
116 
InitCompBuffer()117 VAStatus DdiEncodeBase::InitCompBuffer()
118 {
119     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx.", VA_STATUS_ERROR_INVALID_CONTEXT);
120     DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "Null m_encodeCtx->pCpDdiInterface.", VA_STATUS_ERROR_INVALID_CONTEXT);
121 
122     DDI_CODEC_COM_BUFFER_MGR *bufMgr = &(m_encodeCtx->BufMgr);
123     PDDI_MEDIA_CONTEXT      mediaCtx = m_encodeCtx->pMediaCtx;
124 
125     bufMgr->dwEncodeNumSliceControl = 0;
126 
127     // create status reporting structure
128     bufMgr->pCodedBufferSegment = (VACodedBufferSegment *)MOS_AllocAndZeroMemory(sizeof(VACodedBufferSegment));
129     if (bufMgr->pCodedBufferSegment == nullptr)
130     {
131         return VA_STATUS_ERROR_ALLOCATION_FAILED;
132     }
133     bufMgr->pCodedBufferSegment->next = nullptr;
134 
135     DDI_CHK_RET(m_encodeCtx->pCpDdiInterface->InitHdcp2Buffer(bufMgr), "fail to init hdcp2 buffer!");
136 
137     return VA_STATUS_SUCCESS;
138 }
139 
FreeCompBuffer()140 void DdiEncodeBase::FreeCompBuffer()
141 {
142     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx.", );
143     DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "Null m_encodeCtx->pCpDdiInterface.", );
144     DDI_CHK_NULL(m_encodeCtx->pMediaCtx, "Null m_encodeCtx->pMediaCtx.", );
145 
146     PDDI_MEDIA_CONTEXT mediaCtx = m_encodeCtx->pMediaCtx;
147     DDI_CODEC_COM_BUFFER_MGR *bufMgr   = &(m_encodeCtx->BufMgr);
148     // free  encode bitstream buffer object
149     MOS_FreeMemory(bufMgr->pSliceData);
150     bufMgr->pSliceData = nullptr;
151 
152     m_encodeCtx->pCpDdiInterface->FreeHdcp2Buffer(bufMgr);
153 
154     // free status report struct
155     MOS_FreeMemory(bufMgr->pCodedBufferSegment);
156     bufMgr->pCodedBufferSegment = nullptr;
157 }
158 
StatusReport(DDI_MEDIA_BUFFER * mediaBuf,void ** buf)159 VAStatus DdiEncodeBase::StatusReport(
160     DDI_MEDIA_BUFFER    *mediaBuf,
161     void                **buf)
162 {
163     DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "Null m_encodeCtx->pCpDdiInterface", VA_STATUS_ERROR_INVALID_CONTEXT);
164     DDI_CHK_NULL(mediaBuf, "Null mediaBuf", VA_STATUS_ERROR_INVALID_CONTEXT);
165     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
166 
167     m_encodeCtx->BufMgr.pCodedBufferSegment->status    = 0;
168 
169     //when this function is called, there must be a frame is ready, will wait until get the right information.
170     uint32_t size         = 0;
171     int32_t  index        = 0;
172     uint32_t status       = 0;
173     uint32_t timeOutCount = 0;
174     VAStatus eStatus      = VA_STATUS_SUCCESS;
175 
176     // Get encoded frame information from status buffer queue.
177     while (VA_STATUS_SUCCESS == (eStatus = GetSizeFromStatusReportBuffer(mediaBuf, &size, &status, &index)))
178     {
179         if ((index >= 0) && (size != 0))  //Get the matched encoded buffer information
180         {
181             // the first segment in the single-link list: pointer for the coded bitstream and the size
182             m_encodeCtx->BufMgr.pCodedBufferSegment->buf    = DdiMediaUtil_LockBuffer(mediaBuf, MOS_LOCKFLAG_READONLY);
183             m_encodeCtx->BufMgr.pCodedBufferSegment->size   = size;
184             m_encodeCtx->BufMgr.pCodedBufferSegment->status = status;
185             break;
186         }
187         else if ((index >= 0) && (size == 0) && (status & VA_CODED_BUF_STATUS_BAD_BITSTREAM))
188         {
189             m_encodeCtx->BufMgr.pCodedBufferSegment->buf    = DdiMediaUtil_LockBuffer(mediaBuf, MOS_LOCKFLAG_READONLY);
190             m_encodeCtx->BufMgr.pCodedBufferSegment->size   = size;
191             m_encodeCtx->BufMgr.pCodedBufferSegment->status = status;
192             break;
193         }
194 
195         mos_bo_wait_rendering(mediaBuf->bo);
196 
197         EncodeStatusReport *encodeStatusReport = (EncodeStatusReport*)m_encodeCtx->pEncodeStatusReport;
198         encodeStatusReport->bSequential = true;  //Query the encoded frame status in sequential.
199 
200         uint16_t numStatus = 1;
201         MOS_STATUS mosStatus = MOS_STATUS_SUCCESS;
202         mosStatus = m_encodeCtx->pCodecHal->GetStatusReport(encodeStatusReport, numStatus);
203         if (MOS_STATUS_NOT_ENOUGH_BUFFER == mosStatus)
204         {
205             return VA_STATUS_ERROR_NOT_ENOUGH_BUFFER;
206         } else if (MOS_STATUS_SUCCESS != mosStatus)
207         {
208             return VA_STATUS_ERROR_ENCODING_ERROR;
209         }
210 
211         if (CODECHAL_STATUS_SUCCESSFUL == encodeStatusReport[0].CodecStatus)
212         {
213             // Only AverageQP is reported at this time. Populate other bits with relevant informaiton later;
214             status = (encodeStatusReport[0].AverageQp & VA_CODED_BUF_STATUS_PICTURE_AVE_QP_MASK);
215             if(m_encodeCtx->wModeType == CODECHAL_ENCODE_MODE_AVC)
216             {
217                 CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams*) m_encodeCtx->pFeiPicParams;
218                 if ((feiPicParams != NULL) && (feiPicParams->dwMaxFrameSize != 0))
219                 {
220                     // The reported the pass number should be multi-pass PAK caused by the MaxFrameSize.
221                     // if the suggestedQpYDelta is 0, it means that MaxFrameSize doesn't trigger multi-pass PAK.
222                     // The MaxMbSize triggers multi-pass PAK, the cases should be ignored when reporting the PAK pass.
223                     if ((encodeStatusReport[0].SuggestedQpYDelta == 0) && (encodeStatusReport[0].NumberPasses != 1))
224                     {
225                         encodeStatusReport[0].NumberPasses = 1;
226                     }
227                 }
228             }
229             status = status | ((encodeStatusReport[0].NumberPasses) & 0xf)<<24;
230             // fill hdcp related buffer
231             DDI_CHK_RET(m_encodeCtx->pCpDdiInterface->StatusReportForHdcp2Buffer(&m_encodeCtx->BufMgr, encodeStatusReport), "fail to get hdcp2 status report!");
232             if (UpdateStatusReportBuffer(encodeStatusReport[0].bitstreamSize, status) != VA_STATUS_SUCCESS)
233             {
234                 m_encodeCtx->BufMgr.pCodedBufferSegment->buf  = DdiMediaUtil_LockBuffer(mediaBuf, MOS_LOCKFLAG_READONLY);
235                 m_encodeCtx->BufMgr.pCodedBufferSegment->size = 0;
236                 m_encodeCtx->BufMgr.pCodedBufferSegment->status |= VA_CODED_BUF_STATUS_BAD_BITSTREAM;
237                 m_encodeCtx->statusReportBuf.ulUpdatePosition = (m_encodeCtx->statusReportBuf.ulUpdatePosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
238                 break;
239             }
240 
241             // Report extra status for completed coded buffer
242             eStatus = ReportExtraStatus(encodeStatusReport, m_encodeCtx->BufMgr.pCodedBufferSegment);
243             if (VA_STATUS_SUCCESS != eStatus)
244             {
245                 break;
246             }
247 
248             //Add encoded frame information into status buffer queue.
249             continue;
250         }
251         else if (CODECHAL_STATUS_INCOMPLETE == encodeStatusReport[0].CodecStatus)
252         {
253             bool inlineEncodeStatusUpdate;
254             CodechalEncoderState *encoder = dynamic_cast<CodechalEncoderState *>(m_encodeCtx->pCodecHal);
255             DDI_CHK_NULL(encoder, "Null codechal encoder", VA_STATUS_ERROR_INVALID_CONTEXT);
256             inlineEncodeStatusUpdate = encoder->m_inlineEncodeStatusUpdate;
257 
258             if (inlineEncodeStatusUpdate)
259             {
260                 m_encodeCtx->BufMgr.pCodedBufferSegment->buf  = DdiMediaUtil_LockBuffer(mediaBuf, MOS_LOCKFLAG_READONLY);
261                 m_encodeCtx->BufMgr.pCodedBufferSegment->size = 0;
262                 m_encodeCtx->BufMgr.pCodedBufferSegment->status |= VA_CODED_BUF_STATUS_BAD_BITSTREAM;
263                 UpdateStatusReportBuffer(encodeStatusReport[0].bitstreamSize, m_encodeCtx->BufMgr.pCodedBufferSegment->status);
264                 DDI_ASSERTMESSAGE("Something unexpected happened in HW, return error to application");
265                 break;
266             }
267             // Wait until encode PAK complete, sometimes we application detect encoded buffer object is Idle, may Enc done, but Pak not.
268             uint32_t maxTimeOut                               = 100000;  //set max sleep times to 100000 = 1s, other wise return error.
269             if (timeOutCount < maxTimeOut)
270             {
271                 //sleep 10 us to wait encode complete, it won't impact the performance.
272                 uint32_t sleepTime                            = 10;      //sleep 10 us when encode is not complete.
273                 usleep(sleepTime);
274                 timeOutCount++;
275                 continue;
276             }
277             else
278             {
279                 //if HW didn't response in 1s, assume there is an error in encoding process, return error to App.
280                 m_encodeCtx->BufMgr.pCodedBufferSegment->buf  = DdiMediaUtil_LockBuffer(mediaBuf, MOS_LOCKFLAG_READONLY);
281                 m_encodeCtx->BufMgr.pCodedBufferSegment->size = 0;
282                 m_encodeCtx->BufMgr.pCodedBufferSegment->status |= VA_CODED_BUF_STATUS_BAD_BITSTREAM;
283                 UpdateStatusReportBuffer(encodeStatusReport[0].bitstreamSize, m_encodeCtx->BufMgr.pCodedBufferSegment->status);
284                 DDI_ASSERTMESSAGE("Something unexpected happened in HW, return error to application");
285                 break;
286             }
287         }
288         else if (CODECHAL_STATUS_ERROR == encodeStatusReport[0].CodecStatus)
289         {
290             DDI_NORMALMESSAGE("Encoding failure due to HW issue");
291             m_encodeCtx->BufMgr.pCodedBufferSegment->buf  = DdiMediaUtil_LockBuffer(mediaBuf, MOS_LOCKFLAG_READONLY);
292             m_encodeCtx->BufMgr.pCodedBufferSegment->size = 0;
293             m_encodeCtx->BufMgr.pCodedBufferSegment->status |= VA_CODED_BUF_STATUS_BAD_BITSTREAM;
294             UpdateStatusReportBuffer(encodeStatusReport[0].bitstreamSize, m_encodeCtx->BufMgr.pCodedBufferSegment->status);
295             break;
296         }
297         else
298         {
299             break;
300         }
301     }
302 
303     if (eStatus != VA_STATUS_SUCCESS)
304     {
305         return VA_STATUS_ERROR_OPERATION_FAILED;
306     }
307 
308     *buf = m_encodeCtx->BufMgr.pCodedBufferSegment;
309     return VA_STATUS_SUCCESS;
310 }
311 
EncStatusReport(DDI_MEDIA_BUFFER * mediaBuf,void ** buf)312 VAStatus DdiEncodeBase::EncStatusReport(
313     DDI_MEDIA_BUFFER    *mediaBuf,
314     void                **buf)
315 {
316     DDI_CHK_NULL(mediaBuf, "Null mediaBuf", VA_STATUS_ERROR_INVALID_CONTEXT);
317     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
318 
319     EncodeStatusReport* encodeStatusReport = (EncodeStatusReport*)m_encodeCtx->pEncodeStatusReport;
320     uint16_t numStatus    = 1;
321     uint32_t maxTimeOut   = 500000;  //set max sleep times to 500000 = 5s, other wise return error.
322     uint32_t sleepTime    = 10;  //sleep 10 us when encode is not complete.
323     uint32_t timeOutCount = 0;
324 
325     //when this function is called, there must be a frame is ready, will wait until get the right information.
326     while (1)
327     {
328         encodeStatusReport->bSequential = true;  //Query the encoded frame status in sequential.
329         m_encodeCtx->pCodecHal->GetStatusReport(encodeStatusReport, numStatus);
330 
331         if (CODECHAL_STATUS_SUCCESSFUL == encodeStatusReport[0].CodecStatus)
332         {
333             // Only AverageQP is reported at this time. Populate other bits with relevant informaiton later;
334             uint32_t status = (encodeStatusReport[0].AverageQp & VA_CODED_BUF_STATUS_PICTURE_AVE_QP_MASK);
335             status = status | ((encodeStatusReport[0].NumberPasses & 0xf)<<24);
336             if (UpdateEncStatusReportBuffer(status) != VA_STATUS_SUCCESS)
337             {
338                 return VA_STATUS_ERROR_INVALID_BUFFER;
339             }
340             break;
341         }
342         else if (CODECHAL_STATUS_INCOMPLETE == encodeStatusReport[0].CodecStatus)
343         {
344             // Wait until encode PAK complete, sometimes we application detect encoded buffer object is Idle, may Enc done, but Pak not.
345             if (timeOutCount < maxTimeOut)
346             {
347                 //sleep 10 us to wait encode complete, it won't impact the performance.
348                 usleep(sleepTime);
349                 timeOutCount++;
350                 continue;
351             }
352             else
353             {
354                 //if HW didn't response in 5s, assume there is an error in encoding process, return error to App.
355                 return VA_STATUS_ERROR_ENCODING_ERROR;
356             }
357         }
358         else
359         {
360             // App will call twice StatusReport() for 1 frame, for the second call, just return.
361             break;
362         }
363     }
364 
365     if (mediaBuf->bo)
366     {
367         *buf = DdiMediaUtil_LockBuffer(mediaBuf, MOS_LOCKFLAG_READONLY);
368     }
369     return VA_STATUS_SUCCESS;
370 }
371 
PreEncStatusReport(DDI_MEDIA_BUFFER * mediaBuf,void ** buf)372 VAStatus DdiEncodeBase::PreEncStatusReport(
373     DDI_MEDIA_BUFFER    *mediaBuf,
374     void                **buf)
375 {
376     DDI_CHK_NULL(mediaBuf, "Null mediaBuf", VA_STATUS_ERROR_INVALID_CONTEXT);
377     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
378 
379     EncodeStatusReport* encodeStatusReport = (EncodeStatusReport*)m_encodeCtx->pEncodeStatusReport;
380     uint16_t numStatus    = 1;
381     uint32_t maxTimeOut   = 500000;  //set max sleep times to 500000 = 5s, other wise return error.
382     uint32_t sleepTime    = 10;  //sleep 10 us when encode is not complete.
383     uint32_t timeOutCount = 0;
384 
385     //when this function is called, there must be a frame is ready, will wait until get the right information.
386     while (1)
387     {
388         encodeStatusReport->bSequential = true;  //Query the encoded frame status in sequential.
389         m_encodeCtx->pCodecHal->GetStatusReport(encodeStatusReport, numStatus);
390 
391         if (CODECHAL_STATUS_SUCCESSFUL == encodeStatusReport[0].CodecStatus)
392         {
393             // Only AverageQP is reported at this time. Populate other bits with relevant informaiton later;
394             uint32_t status = (encodeStatusReport[0].AverageQp & VA_CODED_BUF_STATUS_PICTURE_AVE_QP_MASK);
395             status = status | ((encodeStatusReport[0].NumberPasses & 0xf)<<24);
396             if (UpdatePreEncStatusReportBuffer(status) != VA_STATUS_SUCCESS)
397             {
398                 return VA_STATUS_ERROR_INVALID_BUFFER;
399             }
400             break;
401         }
402         else if (CODECHAL_STATUS_INCOMPLETE == encodeStatusReport[0].CodecStatus)
403         {
404             // Wait until encode PAK complete, sometimes we application detect encoded buffer object is Idle, may Enc done, but Pak not.
405             if (timeOutCount < maxTimeOut)
406             {
407                 //sleep 10 us to wait encode complete, it won't impact the performance.
408                 usleep(sleepTime);
409                 timeOutCount++;
410                 continue;
411             }
412             else
413             {
414                 //if HW didn't response in 5s, assume there is an error in encoding process, return error to App.
415                 return VA_STATUS_ERROR_ENCODING_ERROR;
416             }
417         }
418         else
419         {
420             // App will call twice PreEncStatusReport() for 1 frame, for the second call, just return.
421             break;
422         }
423     }
424 
425     if (mediaBuf->bo)
426     {
427         *buf = DdiMediaUtil_LockBuffer(mediaBuf, MOS_LOCKFLAG_READONLY);
428     }
429     return VA_STATUS_SUCCESS;
430 }
431 
RemoveFromStatusReportQueue(DDI_MEDIA_BUFFER * buf)432 VAStatus DdiEncodeBase::RemoveFromStatusReportQueue(DDI_MEDIA_BUFFER *buf)
433 {
434     VAStatus eStatus = VA_STATUS_SUCCESS;
435 
436     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
437     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
438 
439     int32_t    index  = 0;
440     uint32_t   size   = 0;
441     uint32_t   status = 0;
442 
443     eStatus = GetSizeFromStatusReportBuffer(buf, &size, &status, &index);
444     if (VA_STATUS_SUCCESS != eStatus)
445     {
446         return eStatus;
447     }
448 
449     if (index >= 0)
450     {
451         m_encodeCtx->statusReportBuf.infos[index].pCodedBuf = nullptr;
452         m_encodeCtx->statusReportBuf.infos[index].uiSize    = 0;
453     }
454     return eStatus;
455 }
456 
RemoveFromEncStatusReportQueue(DDI_MEDIA_BUFFER * buf,DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx)457 VAStatus DdiEncodeBase::RemoveFromEncStatusReportQueue(
458     DDI_MEDIA_BUFFER                  *buf,
459     DDI_ENCODE_FEI_ENC_BUFFER_TYPE    typeIdx)
460 {
461     VAStatus eStatus = VA_STATUS_SUCCESS;
462 
463     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
464     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
465 
466     if ((typeIdx < 0) || (typeIdx >= FEI_ENC_BUFFER_TYPE_MAX))
467     {
468         DDI_ASSERTMESSAGE("ENC RemoveFromEncStatusReportBuffer, gets invalid buffer type index! .");
469         return VA_STATUS_ERROR_INVALID_CONTEXT;
470     }
471 
472     int32_t  index  = 0;
473     uint32_t status = 0;
474 
475     eStatus = GetIndexFromEncStatusReportBuffer(buf, typeIdx, &status, &index);
476     if (VA_STATUS_SUCCESS != eStatus)
477     {
478         return eStatus;
479     }
480 
481     if (index >= 0)
482     {
483         m_encodeCtx->statusReportBuf.encInfos[index].pEncBuf[typeIdx] = nullptr;
484     }
485 
486     return eStatus;
487 }
488 
RemoveFromPreEncStatusReportQueue(DDI_MEDIA_BUFFER * buf,DDI_ENCODE_PRE_ENC_BUFFER_TYPE typeIdx)489 VAStatus DdiEncodeBase::RemoveFromPreEncStatusReportQueue(
490     DDI_MEDIA_BUFFER                  *buf,
491     DDI_ENCODE_PRE_ENC_BUFFER_TYPE    typeIdx)
492 {
493     VAStatus eStatus = VA_STATUS_SUCCESS;
494 
495     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
496     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
497 
498     if ((typeIdx < 0) || (typeIdx >= PRE_ENC_BUFFER_TYPE_MAX))
499     {
500         DDI_ASSERTMESSAGE("PRE ENC RemoveFromEncStatusReportBuffer, gets invalid buffer type index! .");
501         return VA_STATUS_ERROR_INVALID_CONTEXT;
502     }
503 
504     int32_t  index  = 0;
505     uint32_t status = 0;
506 
507     eStatus = GetIndexFromPreEncStatusReportBuffer(buf, typeIdx, &status, &index);
508     if (VA_STATUS_SUCCESS != eStatus)
509     {
510         return eStatus;
511     }
512 
513     bool bufferIsUpdated = m_encodeCtx->statusReportBuf.ulUpdatePosition < m_encodeCtx->statusReportBuf.ulHeadPosition ?
514                             (index < m_encodeCtx->statusReportBuf.ulUpdatePosition)
515                             : (m_encodeCtx->statusReportBuf.ulUpdatePosition == m_encodeCtx->statusReportBuf.ulHeadPosition ?
516                                 true
517                                 : ((index < m_encodeCtx->statusReportBuf.ulUpdatePosition)
518                                   &&(index > m_encodeCtx->statusReportBuf.ulHeadPosition)));
519 
520     // Remove updated status report buffer
521     if (index >= 0 && bufferIsUpdated)
522     {
523         m_encodeCtx->statusReportBuf.preencInfos[index].pPreEncBuf[typeIdx] = nullptr;
524         m_encodeCtx->statusReportBuf.preencInfos[index].uiBuffers = 0;
525     }
526 
527     return eStatus;
528 }
529 
GetSizeFromStatusReportBuffer(DDI_MEDIA_BUFFER * buf,uint32_t * size,uint32_t * status,int32_t * index)530 VAStatus DdiEncodeBase::GetSizeFromStatusReportBuffer(
531     DDI_MEDIA_BUFFER    *buf,
532     uint32_t            *size,
533     uint32_t            *status,
534     int32_t             *index)
535 {
536     VAStatus eStatus = VA_STATUS_SUCCESS;
537 
538     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
539     DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "Null m_encodeCtx->pCpDdiInterface", VA_STATUS_ERROR_INVALID_CONTEXT);
540     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
541     DDI_CHK_NULL(size, "Null size", VA_STATUS_ERROR_INVALID_CONTEXT);
542     DDI_CHK_NULL(status, "Null status", VA_STATUS_ERROR_INVALID_CONTEXT);
543     DDI_CHK_NULL(index, "Null index", VA_STATUS_ERROR_INVALID_CONTEXT);
544 
545     int32_t i = 0;
546     for (i = 0; i < DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; i++)
547     {
548         // check if the buffer has already been added to status report queue
549         if (m_encodeCtx->statusReportBuf.infos[i].pCodedBuf == (void *)buf->bo)
550         {
551             *size   = m_encodeCtx->statusReportBuf.infos[i].uiSize;
552             *status = m_encodeCtx->statusReportBuf.infos[i].uiStatus;
553 
554             break;
555         }
556     }
557 
558     if (i >= DDI_ENCODE_MAX_STATUS_REPORT_BUFFER)
559     {
560         // no matching buffer has been found
561         *size   = 0;
562         i       = DDI_CODEC_INVALID_BUFFER_INDEX;
563         eStatus = MOS_STATUS_INVALID_HANDLE;
564     }
565 
566     *index = i;
567 
568     return eStatus;
569 }
570 
GetIndexFromEncStatusReportBuffer(DDI_MEDIA_BUFFER * buf,DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx,uint32_t * status,int32_t * index)571 VAStatus DdiEncodeBase::GetIndexFromEncStatusReportBuffer(
572     DDI_MEDIA_BUFFER                  *buf,
573     DDI_ENCODE_FEI_ENC_BUFFER_TYPE    typeIdx,
574     uint32_t                          *status,
575     int32_t                           *index)
576 {
577     VAStatus eStatus = VA_STATUS_SUCCESS;
578 
579     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
580     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
581     DDI_CHK_NULL(status, "Null status", VA_STATUS_ERROR_INVALID_CONTEXT);
582     DDI_CHK_NULL(index, "Null index", VA_STATUS_ERROR_INVALID_CONTEXT);
583 
584     if ((typeIdx < 0) || (typeIdx >= FEI_ENC_BUFFER_TYPE_MAX))
585     {
586         DDI_ASSERTMESSAGE("ENC GetIndexFromEncStatusReportBuffer, gets invalid buffer type index! .");
587         return VA_STATUS_ERROR_INVALID_CONTEXT;
588     }
589 
590     int32_t i = 0;
591     for (i = 0; i < DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; i++)
592     {
593         // check if the buffer has already been added to status report queue
594         if (m_encodeCtx->statusReportBuf.encInfos[i].pEncBuf[typeIdx] == (void *)buf->bo)
595         {
596             *status = m_encodeCtx->statusReportBuf.encInfos[i].uiStatus;
597             break;
598         }
599     }
600 
601     if (i >= DDI_ENCODE_MAX_STATUS_REPORT_BUFFER)
602     {
603         // no matching buffer has been found
604         i       = DDI_CODEC_INVALID_BUFFER_INDEX;
605         eStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
606     }
607 
608     *index = i;
609 
610     return eStatus;
611 }
612 
GetIndexFromPreEncStatusReportBuffer(DDI_MEDIA_BUFFER * buf,DDI_ENCODE_PRE_ENC_BUFFER_TYPE typeIdx,uint32_t * status,int32_t * index)613 VAStatus DdiEncodeBase::GetIndexFromPreEncStatusReportBuffer(
614     DDI_MEDIA_BUFFER                  *buf,
615     DDI_ENCODE_PRE_ENC_BUFFER_TYPE    typeIdx,
616     uint32_t                          *status,
617     int32_t                           *index)
618 {
619     VAStatus eStatus = VA_STATUS_SUCCESS;
620 
621     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
622     DDI_CHK_NULL(buf, "Null buf", VA_STATUS_ERROR_INVALID_CONTEXT);
623     DDI_CHK_NULL(status, "Null status", VA_STATUS_ERROR_INVALID_CONTEXT);
624     DDI_CHK_NULL(index, "Null index", VA_STATUS_ERROR_INVALID_CONTEXT);
625 
626     if ((typeIdx < 0) || (typeIdx >= PRE_ENC_BUFFER_TYPE_MAX))
627     {
628         DDI_ASSERTMESSAGE("PRE ENC GetIndexFromPreEncStatusReportBuffer, gets invalid buffer type index! .");
629         return VA_STATUS_ERROR_INVALID_CONTEXT;
630     }
631 
632     int32_t i = 0;
633     for (i = 0; i < DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; i++)
634     {
635         // check if the buffer has already been added to status report queue
636         if (m_encodeCtx->statusReportBuf.preencInfos[i].pPreEncBuf[typeIdx] == (void *)buf->bo)
637         {
638             *status = m_encodeCtx->statusReportBuf.preencInfos[i].uiStatus;
639             break;
640         }
641     }
642 
643     if (i >= DDI_ENCODE_MAX_STATUS_REPORT_BUFFER)
644     {
645         // no matching buffer has been found
646         i       = DDI_CODEC_INVALID_BUFFER_INDEX;
647         eStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
648     }
649 
650     *index = i;
651 
652     return eStatus;
653 }
654 
CodedBufferExistInStatusReport(DDI_MEDIA_BUFFER * buf)655 bool DdiEncodeBase::CodedBufferExistInStatusReport(DDI_MEDIA_BUFFER *buf)
656 {
657     if (nullptr == m_encodeCtx || nullptr == buf)
658     {
659         return false;
660     }
661 
662     for (int32_t i = 0; i < DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; i++)
663     {
664         if (m_encodeCtx->statusReportBuf.infos[i].pCodedBuf == (void *)buf->bo)
665         {
666             return true;
667         }
668     }
669     return false;
670 }
671 
EncBufferExistInStatusReport(DDI_MEDIA_BUFFER * buf,DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx)672 bool DdiEncodeBase::EncBufferExistInStatusReport(
673     DDI_MEDIA_BUFFER                  *buf,
674     DDI_ENCODE_FEI_ENC_BUFFER_TYPE    typeIdx)
675 {
676     if (nullptr == m_encodeCtx || nullptr == buf)
677     {
678         return false;
679     }
680 
681     if ((typeIdx < 0) || (typeIdx >= FEI_ENC_BUFFER_TYPE_MAX))
682     {
683         DDI_ASSERTMESSAGE("ENC EncBufferExistInStatusReport, gets invalid buffer type index! .");
684         return false;
685     }
686 
687     for (int32_t i = 0; i < DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; i++)
688     {
689         if (m_encodeCtx->statusReportBuf.encInfos[i].pEncBuf[typeIdx] == (void *)buf->bo)
690         {
691             return true;
692         }
693     }
694     return false;
695 }
696 
PreEncBufferExistInStatusReport(DDI_MEDIA_BUFFER * buf,DDI_ENCODE_PRE_ENC_BUFFER_TYPE typeIdx)697 bool DdiEncodeBase::PreEncBufferExistInStatusReport(
698     DDI_MEDIA_BUFFER                  *buf,
699     DDI_ENCODE_PRE_ENC_BUFFER_TYPE    typeIdx)
700 {
701     if (nullptr == m_encodeCtx || nullptr == buf)
702     {
703         return false;
704     }
705 
706     if ((typeIdx < 0) || (typeIdx >= PRE_ENC_BUFFER_TYPE_MAX))
707     {
708         DDI_ASSERTMESSAGE("ENC EncBufferExistInStatusReport, gets invalid buffer type index! .");
709         return false;
710     }
711 
712     for (int32_t i = 0; i < DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; i++)
713     {
714         if (m_encodeCtx->statusReportBuf.preencInfos[i].pPreEncBuf[typeIdx] == (void *)buf->bo)
715         {
716             return true;
717         }
718     }
719     return false;
720 }
721 
VARC2HalRC(uint32_t vaRC)722 uint8_t DdiEncodeBase::VARC2HalRC(uint32_t vaRC)
723 {
724     if ((VA_RC_VBR == vaRC) || ((VA_RC_VBR | VA_RC_MB) == vaRC))
725     {
726         return (uint8_t)RATECONTROL_VBR;
727     }
728     else if (VA_RC_CQP == vaRC)
729     {
730         return (uint8_t)RATECONTROL_CQP;
731     }
732     else if (VA_RC_ICQ == vaRC)
733     {
734         return (uint8_t)RATECONTROL_ICQ;
735     }
736     else if (VA_RC_VCM == vaRC)
737     {
738         return (uint8_t)RATECONTROL_VCM;
739     }
740     else if (VA_RC_QVBR == vaRC)
741     {
742         return (uint8_t)RATECONTROL_QVBR;
743     }
744     else if (VA_RC_AVBR == vaRC)
745     {
746         return (uint8_t)RATECONTROL_AVBR;
747     }
748     else  // VA_RC_CBR or VA_RC_CBR|VA_RC_MB
749     {
750         return (uint8_t)RATECONTROL_CBR;
751     }
752 }
753 
UpdateStatusReportBuffer(uint32_t size,uint32_t status)754 VAStatus DdiEncodeBase::UpdateStatusReportBuffer(
755     uint32_t    size,
756     uint32_t    status)
757 {
758     VAStatus eStatus = VA_STATUS_SUCCESS;
759 
760     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
761 
762     int32_t i = m_encodeCtx->statusReportBuf.ulUpdatePosition;
763     if (m_encodeCtx->statusReportBuf.infos[i].pCodedBuf != nullptr &&
764         m_encodeCtx->statusReportBuf.infos[i].uiSize == 0)
765     {
766         m_encodeCtx->statusReportBuf.infos[i].uiSize   = size;
767         m_encodeCtx->statusReportBuf.infos[i].uiStatus = status;
768         m_encodeCtx->statusReportBuf.ulUpdatePosition  = (m_encodeCtx->statusReportBuf.ulUpdatePosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
769     }
770     else
771     {
772         DDI_ASSERTMESSAGE("DDI: Buffer is not enough in UpdateStatusReportBuffer! .");
773         eStatus = VA_STATUS_ERROR_OPERATION_FAILED;
774     }
775 
776     return eStatus;
777 }
778 
UpdateEncStatusReportBuffer(uint32_t status)779 VAStatus DdiEncodeBase::UpdateEncStatusReportBuffer(uint32_t status)
780 {
781     VAStatus  eStatus                         = VA_STATUS_SUCCESS;
782     bool      distortionEnable               = false;
783     bool      mbCodeMvOrCTBCmdCuRecordEnable = false;
784 
785     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
786     DDI_CHK_NULL(m_encodeCtx->pFeiPicParams, "Null m_encodeCtx->pFeiPicParams", VA_STATUS_ERROR_INVALID_CONTEXT);
787 
788     if(m_encodeCtx->wModeType == CODECHAL_ENCODE_MODE_AVC)
789     {
790         distortionEnable               = ((CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams))->DistortionEnable;
791         mbCodeMvOrCTBCmdCuRecordEnable = ((CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams))->MbCodeMvEnable;
792     }
793     else if(m_encodeCtx->wModeType == CODECHAL_ENCODE_MODE_HEVC)
794     {
795         distortionEnable               = ((CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams))->bDistortionEnable;
796         mbCodeMvOrCTBCmdCuRecordEnable = ((CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams))->bCTBCmdCuRecordEnable;
797     }
798 
799     int32_t i = m_encodeCtx->statusReportBuf.ulUpdatePosition;
800     if (((m_encodeCtx->statusReportBuf.encInfos[i].pEncBuf[0] != nullptr) && mbCodeMvOrCTBCmdCuRecordEnable) ||
801         ((m_encodeCtx->statusReportBuf.encInfos[i].pEncBuf[1] != nullptr) && mbCodeMvOrCTBCmdCuRecordEnable) ||
802         ((m_encodeCtx->statusReportBuf.encInfos[i].pEncBuf[2] != nullptr) && distortionEnable))
803     {
804         m_encodeCtx->statusReportBuf.encInfos[i].uiStatus = status;
805         m_encodeCtx->statusReportBuf.ulUpdatePosition     = (m_encodeCtx->statusReportBuf.ulUpdatePosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
806     }
807     else
808     {
809         DDI_ASSERTMESSAGE("Buffer is not enough in UpdateEncStatusReportBuffer! .");
810         eStatus = VA_STATUS_ERROR_OPERATION_FAILED;
811     }
812 
813     if ((i + 1) == DDI_ENCODE_MAX_STATUS_REPORT_BUFFER)
814     {
815         for (int32_t cnt = 0; cnt < DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; cnt++)
816         {
817             m_encodeCtx->statusReportBuf.encInfos[cnt].uiBuffers = 0;
818         }
819     }
820 
821     return eStatus;
822 }
823 
UpdatePreEncStatusReportBuffer(uint32_t status)824 VAStatus DdiEncodeBase::UpdatePreEncStatusReportBuffer(uint32_t status)
825 {
826     bool                    toUpdateStatistics;
827     VAStatus                eStatus = VA_STATUS_SUCCESS;
828     FeiPreEncParams         *preEncParams;
829 
830     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
831 
832     preEncParams = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
833     DDI_CHK_NULL(preEncParams, "Null preEncParams", VA_STATUS_ERROR_INVALID_CONTEXT);
834 
835     int32_t i = m_encodeCtx->statusReportBuf.ulUpdatePosition;
836     toUpdateStatistics = (!preEncParams->bDisableStatisticsOutput) &&
837                           ((!preEncParams->bInterlaced) ? (m_encodeCtx->statusReportBuf.preencInfos[i].pPreEncBuf[1] != nullptr)
838                                                          : ((m_encodeCtx->statusReportBuf.preencInfos[i].pPreEncBuf[1] != nullptr) &&
839                                                                (m_encodeCtx->statusReportBuf.preencInfos[i].pPreEncBuf[2] != nullptr)));
840     if (((m_encodeCtx->statusReportBuf.preencInfos[i].pPreEncBuf[0] != nullptr) && (!preEncParams->bDisableMVOutput)) || toUpdateStatistics)
841     {
842         m_encodeCtx->statusReportBuf.preencInfos[i].uiStatus = status;
843         m_encodeCtx->statusReportBuf.ulUpdatePosition        = (m_encodeCtx->statusReportBuf.ulUpdatePosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
844     }
845     else
846     {
847         DDI_ASSERTMESSAGE("Buffer is not enough in UpdatePreEncStatusReportBuffer! .");
848         eStatus = VA_STATUS_ERROR_OPERATION_FAILED;
849     }
850 
851     if ((i + 1) == DDI_ENCODE_MAX_STATUS_REPORT_BUFFER)
852     {
853         for (int32_t cnt = 0; cnt < DDI_ENCODE_MAX_STATUS_REPORT_BUFFER; cnt++)
854         {
855             m_encodeCtx->statusReportBuf.preencInfos[cnt].uiBuffers = 0;
856         }
857     }
858 
859     return eStatus;
860 }
861 
CreateBuffer(VADriverContextP ctx,VABufferType type,uint32_t size,uint32_t elementsNum,void * data,VABufferID * bufId)862 VAStatus DdiEncodeBase::CreateBuffer(
863     VADriverContextP    ctx,
864     VABufferType        type,
865     uint32_t            size,
866     uint32_t            elementsNum,
867     void                *data,
868     VABufferID          *bufId)
869 {
870     VAStatus va = VA_STATUS_SUCCESS;
871 
872     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
873 
874     // for VAEncSliceParameterBufferType buffer, VAEncQPBufferType buffer and
875     // VAEncMacroblockMapBufferType buffer, the number of elements can be greater than 1
876     if ((type != VAEncSliceParameterBufferType) &&
877         (type != VAEncQPBufferType) &&
878         (type != VAEncMacroblockMapBufferType) &&
879         (elementsNum > 1))
880     {
881         return VA_STATUS_ERROR_INVALID_PARAMETER;
882     }
883 
884     if (0 == size)
885     {
886         return VA_STATUS_ERROR_INVALID_PARAMETER;
887     }
888 
889     // for coded buffer, does not support to upload some data directly
890     if ((VAEncCodedBufferType == type) && (nullptr != data))
891     {
892         DDI_ASSERTMESSAGE("DDI:can not initialize the coded buffer!");
893         return VA_STATUS_ERROR_INVALID_PARAMETER;
894     }
895 
896     // for FEI ENC output buffers
897     if ((m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC) && (nullptr != data) &&
898         ((VAEncFEIMVBufferType == type) || (VAEncFEIMBCodeBufferType == type) || (VAEncFEIDistortionBufferType == type) ||  (VAEncFEICURecordBufferType == type)))
899     {
900         DDI_ASSERTMESSAGE("DDI:can not initialize the MVs, CURecord, MBcode and Distortion buffer for FEI ENC only!");
901         return VA_STATUS_ERROR_INVALID_PARAMETER;
902     }
903 
904     if ((m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC) && (nullptr != data) &&
905         ((VAStatsMVBufferType == type) || (VAStatsStatisticsBufferType == type) || (VAStatsStatisticsBottomFieldBufferType == type)))
906     {
907         DDI_ASSERTMESSAGE("DDI:can not initialize the MV and Statistics buffer!");
908         return VA_STATUS_ERROR_INVALID_PARAMETER;
909     }
910 
911     DDI_MEDIA_BUFFER *buf = (DDI_MEDIA_BUFFER *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_BUFFER));
912     if (buf == nullptr)
913     {
914         return VA_STATUS_ERROR_ALLOCATION_FAILED;
915     }
916 
917     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
918 
919     buf->pMediaCtx     = mediaCtx;
920     buf->uiNumElements = elementsNum;
921     buf->uiType        = type;
922     buf->uiOffset      = 0;
923 
924     uint32_t bufSize = 0;
925     uint32_t expectedSize = 0xffffffff;
926 
927     switch ((int32_t)type)
928     {
929     case VAProbabilityBufferType:
930     case VAEncCodedBufferType:
931     {
932         buf->iSize  = size;
933         buf->format = Media_Format_Buffer;
934         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
935         if (va != VA_STATUS_SUCCESS)
936         {
937             MOS_FreeMemory(buf);
938             return VA_STATUS_ERROR_ALLOCATION_FAILED;
939         }
940         break;
941     }
942     case VAEncMacroblockMapBufferType:
943     {
944         buf->uiWidth = MOS_ALIGN_CEIL(size, 64);
945         if (size != buf->uiWidth)
946         {
947             va = VA_STATUS_ERROR_INVALID_PARAMETER;
948             CleanUpBufferandReturn(buf);
949             return va;
950         }
951         bufSize            = size * elementsNum;
952         buf->uiHeight      = elementsNum;
953         buf->uiPitch       = buf->uiWidth;
954         buf->iSize         = bufSize;
955         buf->format        = Media_Format_2DBuffer;
956         buf->uiNumElements = 1;
957 
958         va = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
959         if (va != VA_STATUS_SUCCESS)
960         {
961             MOS_FreeMemory(buf);
962             return VA_STATUS_ERROR_ALLOCATION_FAILED;
963         }
964         break;
965     }
966     case VAEncMacroblockDisableSkipMapBufferType:
967     {
968         buf->uiHeight = m_encodeCtx->wPicHeightInMB;
969         buf->uiWidth  = m_encodeCtx->wPicWidthInMB;
970         buf->iSize    = m_encodeCtx->wPicHeightInMB * m_encodeCtx->wPicWidthInMB;
971         buf->format   = Media_Format_2DBuffer;
972 
973         va = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
974         if (va != VA_STATUS_SUCCESS)
975         {
976             MOS_FreeMemory(buf);
977             return VA_STATUS_ERROR_ALLOCATION_FAILED;
978         }
979         break;
980     }
981     case VAEncSliceParameterBufferType:
982     {
983         // elementsNum could be larger than 1 for this case
984         // modify to support MPEG2 later
985         // Currently the slice boundary is at MB row level
986         // Here size is assumed to be the size of the slice control parameter for one single slice
987         // and elementsNum is the number of slices
988         expectedSize = getSliceParameterBufferSize();
989 
990         if ((size < expectedSize) ||
991             (0 == elementsNum) ||
992             (elementsNum > (m_encodeCtx->dwFrameHeight / CODECHAL_MACROBLOCK_HEIGHT)))
993         {
994             va = VA_STATUS_ERROR_INVALID_PARAMETER;
995             CleanUpBufferandReturn(buf);
996             return va;
997         }
998 
999         bufSize = size * elementsNum;
1000         break;
1001     }
1002     case VAEncSequenceParameterBufferType:  // does not exist for JPEG
1003     {
1004         // elementsNum should be 1, ignore here just for robustness
1005         bufSize = size;
1006         expectedSize = getSequenceParameterBufferSize();
1007 
1008         if (bufSize < expectedSize)
1009         {
1010             va = VA_STATUS_ERROR_INVALID_PARAMETER;
1011             CleanUpBufferandReturn(buf);
1012             return va;
1013         }
1014         break;
1015     }
1016     case VAEncPictureParameterBufferType:
1017     {
1018         // elementsNum should be 1, ignore here just for robustness
1019         bufSize = size;
1020         expectedSize = getPictureParameterBufferSize();
1021 
1022         if (bufSize < expectedSize)
1023         {
1024             va = VA_STATUS_ERROR_INVALID_PARAMETER;
1025             CleanUpBufferandReturn(buf);
1026             return va;
1027         }
1028         break;
1029     }
1030     case VAIQMatrixBufferType:
1031     case VAQMatrixBufferType:
1032     {
1033         // elementsNum should be 1, ignore here just for robustness
1034         bufSize = size;
1035         expectedSize = getQMatrixBufferSize();
1036 
1037         if (bufSize < expectedSize)
1038         {
1039             va = VA_STATUS_ERROR_INVALID_PARAMETER;
1040             CleanUpBufferandReturn(buf);
1041             return va;
1042         }
1043         break;
1044     }
1045     case VAEncPackedHeaderParameterBufferType:  // doesnt exist for JPEG
1046     {
1047         // elementsNum should be 1, ignore here just for robustness
1048         bufSize = size;
1049         if (bufSize < sizeof(VAEncPackedHeaderParameterBuffer))
1050         {
1051             va = VA_STATUS_ERROR_INVALID_PARAMETER;
1052             CleanUpBufferandReturn(buf);
1053             return va;
1054         }
1055         break;
1056     }
1057     case VAEncPackedHeaderDataBufferType:  // doesnt exist for JPEG
1058     {
1059         // elementsNum should be 1, ignore here just for robustness
1060         bufSize = size;
1061         break;
1062     }
1063     case VAEncMiscParameterBufferType:  // doesnt exist for JPEG
1064     {
1065         // elementsNum should be 1, ignore here just for robustness
1066         bufSize = size;
1067 
1068         if (bufSize < sizeof(VAEncMiscParameterBuffer))
1069         {
1070             va = VA_STATUS_ERROR_INVALID_PARAMETER;
1071             CleanUpBufferandReturn(buf);
1072             return va;
1073         }
1074         break;
1075     }
1076     case VAHuffmanTableBufferType:  // only for JPEG
1077     {
1078         bufSize = size;
1079 
1080         if (bufSize < sizeof(VAHuffmanTableBufferJPEGBaseline))
1081         {
1082             va = VA_STATUS_ERROR_INVALID_PARAMETER;
1083             CleanUpBufferandReturn(buf);
1084             return va;
1085         }
1086         break;
1087     }
1088     case VAEncFEIMBControlBufferType:
1089     {
1090         bufSize       = size;
1091         buf->iSize  = size;
1092         buf->format = Media_Format_Buffer;
1093         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1094         if (va != VA_STATUS_SUCCESS)
1095         {
1096             MOS_FreeMemory(buf);
1097             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1098         }
1099         break;
1100     }
1101     case VAEncFEIMVPredictorBufferType:
1102     {
1103         bufSize       = size;
1104         buf->iSize  = size;
1105         buf->format = Media_Format_Buffer;
1106         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1107         if (va != VA_STATUS_SUCCESS)
1108         {
1109             MOS_FreeMemory(buf);
1110             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1111         }
1112         break;
1113     }
1114     case VAEncQPBufferType:
1115     {
1116         //The permb qp buffer of legacy encoder is a 2D buffer, because dynamic resolution change, we cant determine the buffer size with the resolution information in encoder context
1117         //so the size information should be from application, the width should be the size, the height is the elementsNum to define this 2D buffer,width should always 64 byte alignment.
1118         //please pay attention: 1 byte present 1 MB QP values for AVC, 4 bytes present 1 MB QP values for MPEG2, lowest byte is the real QP value, other 3 byes is other mb level contrl
1119         //which havent been exposed. the permb QP buffer of FEI is 1D buffer.
1120         if (CODECHAL_FUNCTION_ENC_PAK == m_encodeCtx->codecFunction ||
1121             CODECHAL_FUNCTION_ENC_VDENC_PAK == m_encodeCtx->codecFunction ||
1122             (((CODECHAL_FUNCTION_FEI_ENC_PAK == m_encodeCtx->codecFunction) || (CODECHAL_FUNCTION_FEI_ENC == m_encodeCtx->codecFunction)) &&
1123               (m_encodeCtx->wModeType == CODECHAL_ENCODE_MODE_HEVC)))
1124         {
1125             buf->uiWidth = MOS_ALIGN_CEIL(size, 64);
1126             if (size != buf->uiWidth)
1127             {
1128                 va = VA_STATUS_ERROR_INVALID_PARAMETER;
1129                 CleanUpBufferandReturn(buf);
1130                 return va;
1131             }
1132             bufSize            = size * elementsNum;
1133             buf->uiHeight      = elementsNum;
1134             buf->uiPitch       = buf->uiWidth;
1135             buf->iSize         = bufSize;
1136             buf->format        = Media_Format_2DBuffer;
1137             buf->uiNumElements = 1;
1138         }
1139         else
1140         {
1141             bufSize       = size;
1142             buf->iSize  = size;
1143             buf->format = Media_Format_Buffer;
1144         }
1145         va = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1146         if (va != VA_STATUS_SUCCESS)
1147         {
1148             MOS_FreeMemory(buf);
1149             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1150         }
1151         break;
1152     }
1153     case VAEncFEICTBCmdBufferType:
1154     case VAEncFEIMVBufferType:
1155     {
1156         bufSize       = size;
1157         buf->iSize  = bufSize;
1158         buf->format = Media_Format_Buffer;
1159         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1160         if (va != VA_STATUS_SUCCESS)
1161         {
1162             MOS_FreeMemory(buf);
1163             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1164         }
1165         break;
1166     }
1167     case VAEncFEICURecordBufferType:
1168     case VAEncFEIMBCodeBufferType:
1169     {
1170         bufSize       = size;
1171         buf->iSize  = bufSize;
1172         buf->format = Media_Format_Buffer;
1173         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1174         if (va != VA_STATUS_SUCCESS)
1175         {
1176             MOS_FreeMemory(buf);
1177             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1178         }
1179         break;
1180     }
1181     case VAEncFEIDistortionBufferType:
1182     {
1183         bufSize       = size;
1184         buf->iSize  = bufSize;
1185         buf->format = Media_Format_Buffer;
1186         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1187         if (va != VA_STATUS_SUCCESS)
1188         {
1189             MOS_FreeMemory(buf);
1190             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1191         }
1192         break;
1193     }
1194     case VAStatsStatisticsParameterBufferType:
1195     {
1196         // elementsNum should be 1, ignore here just for robustness
1197         bufSize = size;
1198         if (bufSize < sizeof(VAStatsStatisticsParameterH264))
1199         {
1200             va = VA_STATUS_ERROR_INVALID_PARAMETER;
1201             CleanUpBufferandReturn(buf);
1202             return va;
1203         }
1204 
1205         break;
1206     }
1207     case VAStatsMVPredictorBufferType:
1208     {
1209         bufSize       = size;
1210         buf->iSize  = size * elementsNum;
1211         buf->format = Media_Format_Buffer;
1212         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1213         if (va != VA_STATUS_SUCCESS)
1214         {
1215             MOS_FreeMemory(buf);
1216             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1217         }
1218 
1219         break;
1220     }
1221     case VAStatsMVBufferType:
1222     {
1223         bufSize       = size;
1224         buf->iSize  = size * elementsNum;
1225         buf->format = Media_Format_Buffer;
1226         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1227         if (va != VA_STATUS_SUCCESS)
1228         {
1229             MOS_FreeMemory(buf);
1230             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1231         }
1232         break;
1233     }
1234     case VAStatsStatisticsBufferType:
1235     case VAStatsStatisticsBottomFieldBufferType:
1236     {
1237         bufSize       = size;
1238         buf->iSize  = size * elementsNum;
1239         buf->format = Media_Format_Buffer;
1240         va           = DdiMediaUtil_CreateBuffer(buf, mediaCtx->pDrmBufMgr);
1241         if (va != VA_STATUS_SUCCESS)
1242         {
1243             MOS_FreeMemory(buf);
1244             return VA_STATUS_ERROR_ALLOCATION_FAILED;
1245         }
1246         break;
1247     }
1248     default:
1249     {
1250         bufSize = size * elementsNum;
1251 
1252         if (0 == bufSize)
1253         {
1254             va = VA_STATUS_ERROR_INVALID_PARAMETER;
1255             CleanUpBufferandReturn(buf);
1256             return va;
1257         }
1258 
1259         va = m_encodeCtx->pCpDdiInterface->CreateBuffer(type, buf, size, elementsNum);
1260         if (va  == VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE)
1261         {
1262             MOS_FreeMemory(buf);
1263             DDI_ASSERTMESSAGE("DDI: non supported buffer type = %d, size = %d, num = %d", type, size, elementsNum);
1264             return va;
1265         }
1266 
1267         break;
1268     }
1269     }
1270 
1271     if ((VAEncCodedBufferType != type) &&
1272         (VAEncMacroblockMapBufferType != type) &&
1273         (VAEncFEIMVBufferType != type) &&
1274         (VAEncFEIMBCodeBufferType != type) &&
1275         (VAEncFEICTBCmdBufferType != type)      &&
1276         (VAEncFEICURecordBufferType != type)    &&
1277         (VAEncFEIDistortionBufferType != type) &&
1278         (VAEncFEIMBControlBufferType != type) &&
1279         (VAEncFEIMVPredictorBufferType != type) &&
1280         (VAStatsMVBufferType != type) &&
1281         (VAStatsStatisticsBufferType != type) &&
1282         (VAStatsStatisticsBottomFieldBufferType != type) &&
1283         (VAStatsMVPredictorBufferType != type) &&
1284         (VAEncQPBufferType != type) &&
1285         (VAEncMacroblockDisableSkipMapBufferType != (int32_t)type) &&
1286         (VAProbabilityBufferType != (int32_t)type))
1287     {
1288         buf->pData = (uint8_t*)MOS_AllocAndZeroMemory(bufSize);
1289         if (nullptr == buf->pData)
1290         {
1291             va = VA_STATUS_ERROR_ALLOCATION_FAILED;
1292             CleanUpBufferandReturn(buf);
1293             return va;
1294         }
1295         buf->iSize  = bufSize;
1296         buf->format = Media_Format_CPU;
1297     }
1298 
1299     PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufferHeapElement = DdiMediaUtil_AllocPMediaBufferFromHeap(mediaCtx->pBufferHeap);
1300     if (nullptr == bufferHeapElement)
1301     {
1302         va = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1303         CleanUpBufferandReturn(buf);
1304         return va;
1305     }
1306 
1307     bufferHeapElement->pBuffer   = buf;
1308     bufferHeapElement->pCtx      = (void*)m_encodeCtx;
1309     bufferHeapElement->uiCtxType = DDI_MEDIA_CONTEXT_TYPE_ENCODER;
1310     *bufId                        = bufferHeapElement->uiVaBufferID;
1311     mediaCtx->uiNumBufs++;
1312 
1313     // return success if data is nullptr, no need to copy data
1314     if (data == nullptr || VAEncMacroblockMapBufferType == type)
1315     {
1316         return va;
1317     }
1318 
1319     DdiMediaUtil_LockBuffer(buf, MOS_LOCKFLAG_WRITEONLY | MOS_LOCKFLAG_READONLY);
1320 
1321     MOS_STATUS eStatus = MOS_SecureMemcpy((void*)(buf->pData + buf->uiOffset), bufSize, (void*)data, bufSize);
1322 
1323     DdiMediaUtil_UnlockBuffer(buf);
1324 
1325     if (eStatus != MOS_STATUS_SUCCESS)
1326     {
1327         DdiMedia_DestroyBufFromVABufferID(mediaCtx, bufferHeapElement->uiVaBufferID);
1328         va = VA_STATUS_ERROR_OPERATION_FAILED;
1329         CleanUpBufferandReturn(buf);
1330         return va;
1331     }
1332 
1333     // return success
1334     return va;
1335 }
1336 
CleanUpBufferandReturn(DDI_MEDIA_BUFFER * buf)1337 void DdiEncodeBase::CleanUpBufferandReturn(DDI_MEDIA_BUFFER *buf)
1338 {
1339     if (buf)
1340     {
1341         MOS_FreeMemory(buf->pData);
1342         MOS_FreeMemory(buf);
1343     }
1344 }
1345 
getSliceParameterBufferSize()1346 uint32_t DdiEncodeBase::getSliceParameterBufferSize()
1347 {
1348     return 0xffffffff;
1349 }
1350 
getSequenceParameterBufferSize()1351 uint32_t DdiEncodeBase::getSequenceParameterBufferSize()
1352 {
1353     return 0xffffffff;
1354 }
1355 
getPictureParameterBufferSize()1356 uint32_t DdiEncodeBase::getPictureParameterBufferSize()
1357 {
1358     return 0xffffffff;
1359 }
1360 
getQMatrixBufferSize()1361 uint32_t DdiEncodeBase::getQMatrixBufferSize()
1362 {
1363     return 0xffffffff;
1364 }
1365 
ClearPicParams()1366 void DdiEncodeBase::ClearPicParams()
1367 {
1368 }
1369