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