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