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