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