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