1 /*
2 * Copyright (c) 2009-2011 Intel Corporation. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <string.h>
18 #include "VideoEncoderLog.h"
19 #include "VideoEncoderBase.h"
20 #include "IntelMetadataBuffer.h"
21 #include <va/va_tpi.h>
22 #include <va/va_android.h>
23
VideoEncoderBase()24 VideoEncoderBase::VideoEncoderBase()
25 :mInitialized(true)
26 ,mStarted(false)
27 ,mVADisplay(NULL)
28 ,mVAContext(VA_INVALID_ID)
29 ,mVAConfig(VA_INVALID_ID)
30 ,mVAEntrypoint(VAEntrypointEncSlice)
31 ,mNewHeader(false)
32 ,mRenderMaxSliceSize(false)
33 ,mRenderQP (false)
34 ,mRenderAIR(false)
35 ,mRenderCIR(false)
36 ,mRenderFrameRate(false)
37 ,mRenderBitRate(false)
38 ,mRenderHrd(false)
39 ,mRenderMultiTemporal(false)
40 ,mForceKFrame(false)
41 ,mSeqParamBuf(0)
42 ,mPicParamBuf(0)
43 ,mSliceParamBuf(0)
44 ,mAutoRefSurfaces(NULL)
45 ,mRefSurface(VA_INVALID_SURFACE)
46 ,mRecSurface(VA_INVALID_SURFACE)
47 ,mFrameNum(0)
48 ,mCodedBufSize(0)
49 ,mAutoReference(false)
50 ,mAutoReferenceSurfaceNum(4)
51 ,mEncPackedHeaders(VA_ATTRIB_NOT_SUPPORTED)
52 ,mSliceSizeOverflow(false)
53 ,mCurOutputTask(NULL)
54 ,mOutCodedBuffer(0)
55 ,mOutCodedBufferPtr(NULL)
56 ,mCurSegment(NULL)
57 ,mOffsetInSeg(0)
58 ,mTotalSize(0)
59 ,mTotalSizeCopied(0)
60 ,mFrameSkipped(false)
61 ,mSupportedSurfaceMemType(0)
62 ,mVASurfaceMappingAction(0)
63 #ifdef INTEL_VIDEO_XPROC_SHARING
64 ,mSessionFlag(0)
65 #endif
66 {
67
68 VAStatus vaStatus = VA_STATUS_SUCCESS;
69 // here the display can be any value, use following one
70 // just for consistence purpose, so don't define it
71 unsigned int display = 0x18C34078;
72 int majorVersion = -1;
73 int minorVersion = -1;
74
75 setDefaultParams();
76
77 LOG_V("vaGetDisplay \n");
78 mVADisplay = vaGetDisplay(&display);
79 if (mVADisplay == NULL) {
80 LOG_E("vaGetDisplay failed.");
81 }
82
83 vaStatus = vaInitialize(mVADisplay, &majorVersion, &minorVersion);
84 LOG_V("vaInitialize \n");
85 if (vaStatus != VA_STATUS_SUCCESS) {
86 LOG_E( "Failed vaInitialize, vaStatus = %d\n", vaStatus);
87 mInitialized = false;
88 }
89 }
90
~VideoEncoderBase()91 VideoEncoderBase::~VideoEncoderBase() {
92
93 VAStatus vaStatus = VA_STATUS_SUCCESS;
94
95 stop();
96
97 vaStatus = vaTerminate(mVADisplay);
98 LOG_V( "vaTerminate\n");
99 if (vaStatus != VA_STATUS_SUCCESS) {
100 LOG_W( "Failed vaTerminate, vaStatus = %d\n", vaStatus);
101 } else {
102 mVADisplay = NULL;
103 }
104
105 #ifdef INTEL_VIDEO_XPROC_SHARING
106 IntelMetadataBuffer::ClearContext(mSessionFlag, false);
107 #endif
108 }
109
start()110 Encode_Status VideoEncoderBase::start() {
111
112 Encode_Status ret = ENCODE_SUCCESS;
113 VAStatus vaStatus = VA_STATUS_SUCCESS;
114
115 if (!mInitialized) {
116 LOGE("Encoder Initialize fail can not start");
117 return ENCODE_DRIVER_FAIL;
118 }
119
120 if (mStarted) {
121 LOG_V("Encoder has been started\n");
122 return ENCODE_ALREADY_INIT;
123 }
124
125 if (mComParams.rawFormat != RAW_FORMAT_NV12)
126 #ifdef IMG_GFX
127 mVASurfaceMappingAction |= MAP_ACTION_COLORCONVERT;
128 #else
129 return ENCODE_NOT_SUPPORTED;
130 #endif
131
132 if (mComParams.resolution.width > 2048 || mComParams.resolution.height > 2048){
133 LOGE("Unsupported resolution width %d, height %d\n",
134 mComParams.resolution.width, mComParams.resolution.height);
135 return ENCODE_NOT_SUPPORTED;
136 }
137 queryAutoReferenceConfig(mComParams.profile);
138
139 VAConfigAttrib vaAttrib_tmp[6],vaAttrib[VAConfigAttribTypeMax];
140 int vaAttribNumber = 0;
141 vaAttrib_tmp[0].type = VAConfigAttribRTFormat;
142 vaAttrib_tmp[1].type = VAConfigAttribRateControl;
143 vaAttrib_tmp[2].type = VAConfigAttribEncAutoReference;
144 vaAttrib_tmp[3].type = VAConfigAttribEncPackedHeaders;
145 vaAttrib_tmp[4].type = VAConfigAttribEncMaxRefFrames;
146 vaAttrib_tmp[5].type = VAConfigAttribEncRateControlExt;
147
148 vaStatus = vaGetConfigAttributes(mVADisplay, mComParams.profile,
149 VAEntrypointEncSlice, &vaAttrib_tmp[0], 6);
150 CHECK_VA_STATUS_RETURN("vaGetConfigAttributes");
151
152 if((vaAttrib_tmp[0].value & VA_RT_FORMAT_YUV420) != 0)
153 {
154 vaAttrib[vaAttribNumber].type = VAConfigAttribRTFormat;
155 vaAttrib[vaAttribNumber].value = VA_RT_FORMAT_YUV420;
156 vaAttribNumber++;
157 }
158
159 vaAttrib[vaAttribNumber].type = VAConfigAttribRateControl;
160 vaAttrib[vaAttribNumber].value = mComParams.rcMode;
161 vaAttribNumber++;
162
163 vaAttrib[vaAttribNumber].type = VAConfigAttribEncAutoReference;
164 vaAttrib[vaAttribNumber].value = mAutoReference ? 1 : VA_ATTRIB_NOT_SUPPORTED;
165 vaAttribNumber++;
166
167 if(vaAttrib_tmp[3].value != VA_ATTRIB_NOT_SUPPORTED)
168 {
169 vaAttrib[vaAttribNumber].type = VAConfigAttribEncPackedHeaders;
170 vaAttrib[vaAttribNumber].value = vaAttrib[3].value;
171 vaAttribNumber++;
172 mEncPackedHeaders = vaAttrib[3].value;
173 }
174
175 if(vaAttrib_tmp[4].value != VA_ATTRIB_NOT_SUPPORTED)
176 {
177 vaAttrib[vaAttribNumber].type = VAConfigAttribEncMaxRefFrames;
178 vaAttrib[vaAttribNumber].value = vaAttrib[4].value;
179 vaAttribNumber++;
180 mEncMaxRefFrames = vaAttrib[4].value;
181 }
182
183 if(vaAttrib_tmp[5].value != VA_ATTRIB_NOT_SUPPORTED)
184 {
185 vaAttrib[vaAttribNumber].type = VAConfigAttribEncRateControlExt;
186 vaAttrib[vaAttribNumber].value = mComParams.numberOfLayer;
187 vaAttribNumber++;
188 }
189
190 LOG_V( "======VA Configuration======\n");
191 LOG_V( "profile = %d\n", mComParams.profile);
192 LOG_V( "mVAEntrypoint = %d\n", mVAEntrypoint);
193 LOG_V( "vaAttrib[0].type = %d\n", vaAttrib[0].type);
194 LOG_V( "vaAttrib[1].type = %d\n", vaAttrib[1].type);
195 LOG_V( "vaAttrib[2].type = %d\n", vaAttrib[2].type);
196 LOG_V( "vaAttrib[0].value (Format) = %d\n", vaAttrib[0].value);
197 LOG_V( "vaAttrib[1].value (RC mode) = %d\n", vaAttrib[1].value);
198 LOG_V( "vaAttrib[2].value (AutoReference) = %d\n", vaAttrib[2].value);
199 LOG_V( "vaAttribNumber is %d\n", vaAttribNumber);
200 LOG_V( "mComParams.numberOfLayer is %d\n", mComParams.numberOfLayer);
201
202 LOG_V( "vaCreateConfig\n");
203
204 vaStatus = vaCreateConfig(
205 mVADisplay, mComParams.profile, mVAEntrypoint,
206 &vaAttrib[0], vaAttribNumber, &(mVAConfig));
207 // &vaAttrib[0], 3, &(mVAConfig)); //uncomment this after psb_video supports
208 CHECK_VA_STATUS_RETURN("vaCreateConfig");
209
210 querySupportedSurfaceMemTypes();
211
212 if (mComParams.rcMode == VA_RC_VCM) {
213 // Following three features are only enabled in VCM mode
214 mRenderMaxSliceSize = true;
215 mRenderAIR = true;
216 mRenderBitRate = true;
217 }
218
219 LOG_V( "======VA Create Surfaces for Rec/Ref frames ======\n");
220
221 uint32_t stride_aligned, height_aligned;
222 if(mAutoReference == false){
223 stride_aligned = (mComParams.resolution.width + 15) & ~15;
224 height_aligned = (mComParams.resolution.height + 15) & ~15;
225 }else{
226 // this alignment is used for AVC. For vp8 encode, driver will handle the alignment
227 if(mComParams.profile == VAProfileVP8Version0_3)
228 {
229 stride_aligned = mComParams.resolution.width;
230 height_aligned = mComParams.resolution.height;
231 mVASurfaceMappingAction |= MAP_ACTION_COPY;
232 }
233 else
234 {
235 stride_aligned = (mComParams.resolution.width + 63) & ~63; //on Merr, stride must be 64 aligned.
236 height_aligned = (mComParams.resolution.height + 31) & ~31;
237 mVASurfaceMappingAction |= MAP_ACTION_ALIGN64;
238 }
239 }
240
241 if(mAutoReference == false){
242 mRefSurface = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
243 mRecSurface = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
244
245 }else {
246 mAutoRefSurfaces = new VASurfaceID [mAutoReferenceSurfaceNum];
247 for(uint32_t i = 0; i < mAutoReferenceSurfaceNum; i ++)
248 mAutoRefSurfaces[i] = CreateNewVASurface(mVADisplay, stride_aligned, height_aligned);
249 }
250 CHECK_VA_STATUS_RETURN("vaCreateSurfaces");
251
252 //Prepare all Surfaces to be added into Context
253 uint32_t contextSurfaceCnt;
254 if(mAutoReference == false )
255 contextSurfaceCnt = 2 + mSrcSurfaceMapList.size();
256 else
257 contextSurfaceCnt = mAutoReferenceSurfaceNum + mSrcSurfaceMapList.size();
258
259 VASurfaceID *contextSurfaces = new VASurfaceID[contextSurfaceCnt];
260 int32_t index = -1;
261 android::List<VASurfaceMap *>::iterator map_node;
262
263 for(map_node = mSrcSurfaceMapList.begin(); map_node != mSrcSurfaceMapList.end(); map_node++)
264 {
265 contextSurfaces[++index] = (*map_node)->getVASurface();
266 (*map_node)->setTracked();
267 }
268
269 if(mAutoReference == false){
270 contextSurfaces[++index] = mRefSurface;
271 contextSurfaces[++index] = mRecSurface;
272 } else {
273 for (uint32_t i=0; i < mAutoReferenceSurfaceNum; i++)
274 contextSurfaces[++index] = mAutoRefSurfaces[i];
275 }
276
277 //Initialize and save the VA context ID
278 LOG_V( "vaCreateContext\n");
279 vaStatus = vaCreateContext(mVADisplay, mVAConfig,
280 #ifdef IMG_GFX
281 mComParams.resolution.width,
282 mComParams.resolution.height,
283 #else
284 stride_aligned,
285 height_aligned,
286 #endif
287 VA_PROGRESSIVE, contextSurfaces, contextSurfaceCnt,
288 &(mVAContext));
289 CHECK_VA_STATUS_RETURN("vaCreateContext");
290
291 delete [] contextSurfaces;
292
293 LOG_I("Success to create libva context width %d, height %d\n",
294 mComParams.resolution.width, mComParams.resolution.height);
295
296 uint32_t maxSize = 0;
297 ret = getMaxOutSize(&maxSize);
298 CHECK_ENCODE_STATUS_RETURN("getMaxOutSize");
299
300 // Create CodedBuffer for output
301 VABufferID VACodedBuffer;
302
303 for(uint32_t i = 0; i <mComParams.codedBufNum; i++) {
304 vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
305 VAEncCodedBufferType,
306 mCodedBufSize,
307 1, NULL,
308 &VACodedBuffer);
309 CHECK_VA_STATUS_RETURN("vaCreateBuffer::VAEncCodedBufferType");
310
311 mVACodedBufferList.push_back(VACodedBuffer);
312 }
313
314 if (ret == ENCODE_SUCCESS)
315 mStarted = true;
316
317 LOG_V( "end\n");
318 return ret;
319 }
320
encode(VideoEncRawBuffer * inBuffer,uint32_t timeout)321 Encode_Status VideoEncoderBase::encode(VideoEncRawBuffer *inBuffer, uint32_t timeout) {
322
323 Encode_Status ret = ENCODE_SUCCESS;
324 VAStatus vaStatus = VA_STATUS_SUCCESS;
325
326 if (!mStarted) {
327 LOG_E("Encoder has not initialized yet\n");
328 return ENCODE_NOT_INIT;
329 }
330
331 CHECK_NULL_RETURN_IFFAIL(inBuffer);
332
333 //======Prepare all resources encoder needed=====.
334
335 //Prepare encode vaSurface
336 VASurfaceID sid = VA_INVALID_SURFACE;
337 ret = manageSrcSurface(inBuffer, &sid);
338 CHECK_ENCODE_STATUS_RETURN("manageSrcSurface");
339
340 //Prepare CodedBuffer
341 mCodedBuffer_Lock.lock();
342 if(mVACodedBufferList.empty()){
343 if(timeout == FUNC_BLOCK)
344 mCodedBuffer_Cond.wait(mCodedBuffer_Lock);
345 else if (timeout > 0) {
346 if(NO_ERROR != mEncodeTask_Cond.waitRelative(mCodedBuffer_Lock, 1000000*timeout)){
347 mCodedBuffer_Lock.unlock();
348 LOG_E("Time out wait for Coded buffer.\n");
349 return ENCODE_DEVICE_BUSY;
350 }
351 }
352 else {//Nonblock
353 mCodedBuffer_Lock.unlock();
354 LOG_E("Coded buffer is not ready now.\n");
355 return ENCODE_DEVICE_BUSY;
356 }
357 }
358
359 if(mVACodedBufferList.empty()){
360 mCodedBuffer_Lock.unlock();
361 return ENCODE_DEVICE_BUSY;
362 }
363 VABufferID coded_buf = (VABufferID) *(mVACodedBufferList.begin());
364 mVACodedBufferList.erase(mVACodedBufferList.begin());
365 mCodedBuffer_Lock.unlock();
366
367 LOG_V("CodedBuffer ID 0x%08x\n", coded_buf);
368
369 //All resources are ready, start to assemble EncodeTask
370 EncodeTask* task = new EncodeTask();
371
372 task->completed = false;
373 task->enc_surface = sid;
374 task->coded_buffer = coded_buf;
375 task->timestamp = inBuffer->timeStamp;
376 task->priv = inBuffer->priv;
377
378 //Setup frame info, like flag ( SYNCFRAME), frame number, type etc
379 task->type = inBuffer->type;
380 task->flag = inBuffer->flag;
381 PrepareFrameInfo(task);
382
383 if(mAutoReference == false){
384 //Setup ref /rec frames
385 //TODO: B frame support, temporary use same logic
386 switch (inBuffer->type) {
387 case FTYPE_UNKNOWN:
388 case FTYPE_IDR:
389 case FTYPE_I:
390 case FTYPE_P:
391 {
392 if(!mFrameSkipped) {
393 VASurfaceID tmpSurface = mRecSurface;
394 mRecSurface = mRefSurface;
395 mRefSurface = tmpSurface;
396 }
397
398 task->ref_surface = mRefSurface;
399 task->rec_surface = mRecSurface;
400
401 break;
402 }
403 case FTYPE_B:
404 default:
405 LOG_V("Something wrong, B frame may not be supported in this mode\n");
406 ret = ENCODE_NOT_SUPPORTED;
407 goto CLEAN_UP;
408 }
409 }else {
410 task->ref_surface = VA_INVALID_SURFACE;
411 task->rec_surface = VA_INVALID_SURFACE;
412 }
413 //======Start Encoding, add task to list======
414 LOG_V("Start Encoding vaSurface=0x%08x\n", task->enc_surface);
415
416 vaStatus = vaBeginPicture(mVADisplay, mVAContext, task->enc_surface);
417 CHECK_VA_STATUS_GOTO_CLEANUP("vaBeginPicture");
418
419 ret = sendEncodeCommand(task);
420 CHECK_ENCODE_STATUS_CLEANUP("sendEncodeCommand");
421
422 vaStatus = vaEndPicture(mVADisplay, mVAContext);
423 CHECK_VA_STATUS_GOTO_CLEANUP("vaEndPicture");
424
425 LOG_V("Add Task %p into Encode Task list\n", task);
426 mEncodeTask_Lock.lock();
427 mEncodeTaskList.push_back(task);
428 mEncodeTask_Cond.signal();
429 mEncodeTask_Lock.unlock();
430
431 mFrameNum ++;
432
433 LOG_V("encode return Success\n");
434
435 return ENCODE_SUCCESS;
436
437 CLEAN_UP:
438
439 delete task;
440 mCodedBuffer_Lock.lock();
441 mVACodedBufferList.push_back(coded_buf); //push to CodedBuffer pool again since it is not used
442 mCodedBuffer_Cond.signal();
443 mCodedBuffer_Lock.unlock();
444
445 LOG_V("encode return error=%x\n", ret);
446
447 return ret;
448 }
449
450 /*
451 1. Firstly check if one task is outputting data, if yes, continue outputting, if not try to get one from list.
452 2. Due to block/non-block/block with timeout 3 modes, if task is not completed, then sync surface, if yes,
453 start output data
454 3. Use variable curoutputtask to record task which is getOutput() working on to avoid push again when get failure
455 on non-block/block with timeout modes.
456 4. if complete all output data, curoutputtask should be set NULL
457 */
getOutput(VideoEncOutputBuffer * outBuffer,uint32_t timeout)458 Encode_Status VideoEncoderBase::getOutput(VideoEncOutputBuffer *outBuffer, uint32_t timeout) {
459
460 Encode_Status ret = ENCODE_SUCCESS;
461 VAStatus vaStatus = VA_STATUS_SUCCESS;
462 bool useLocalBuffer = false;
463
464 CHECK_NULL_RETURN_IFFAIL(outBuffer);
465
466 if (mCurOutputTask == NULL) {
467 mEncodeTask_Lock.lock();
468 if(mEncodeTaskList.empty()) {
469 LOG_V("getOutput CurrentTask is NULL\n");
470 if(timeout == FUNC_BLOCK) {
471 LOG_V("waiting for task....\n");
472 mEncodeTask_Cond.wait(mEncodeTask_Lock);
473 } else if (timeout > 0) {
474 LOG_V("waiting for task in %i ms....\n", timeout);
475 if(NO_ERROR != mEncodeTask_Cond.waitRelative(mEncodeTask_Lock, 1000000*timeout)) {
476 mEncodeTask_Lock.unlock();
477 LOG_E("Time out wait for encode task.\n");
478 return ENCODE_NO_REQUEST_DATA;
479 }
480 } else {//Nonblock
481 mEncodeTask_Lock.unlock();
482 return ENCODE_NO_REQUEST_DATA;
483 }
484 }
485
486 if(mEncodeTaskList.empty()){
487 mEncodeTask_Lock.unlock();
488 return ENCODE_DATA_NOT_READY;
489 }
490 mCurOutputTask = *(mEncodeTaskList.begin());
491 mEncodeTaskList.erase(mEncodeTaskList.begin());
492 mEncodeTask_Lock.unlock();
493 }
494
495 //sync/query/wait task if not completed
496 if (mCurOutputTask->completed == false) {
497 VASurfaceStatus vaSurfaceStatus;
498
499 if (timeout == FUNC_BLOCK) {
500 //block mode, direct sync surface to output data
501
502 mOutCodedBuffer = mCurOutputTask->coded_buffer;
503
504 // Check frame skip
505 // Need encoding to be completed before calling query surface below to
506 // get the right skip frame flag for current frame
507 // It is a requirement of video driver
508 // vaSyncSurface syncs the wrong frame when rendering the same surface multiple times,
509 // so use vaMapbuffer instead
510 LOG_V ("block mode, vaMapBuffer ID = 0x%08x\n", mOutCodedBuffer);
511 if (mOutCodedBufferPtr == NULL) {
512 vaStatus = vaMapBuffer (mVADisplay, mOutCodedBuffer, (void **)&mOutCodedBufferPtr);
513 CHECK_VA_STATUS_GOTO_CLEANUP("vaMapBuffer");
514 CHECK_NULL_RETURN_IFFAIL(mOutCodedBufferPtr);
515 }
516
517 vaStatus = vaQuerySurfaceStatus(mVADisplay, mCurOutputTask->enc_surface, &vaSurfaceStatus);
518 CHECK_VA_STATUS_RETURN("vaQuerySurfaceStatus");
519 mFrameSkipped = vaSurfaceStatus & VASurfaceSkipped;
520
521 mCurOutputTask->completed = true;
522
523 } else {
524 //For both block with timeout and non-block mode, query surface, if ready, output data
525 LOG_V ("non-block mode, vaQuerySurfaceStatus ID = 0x%08x\n", mCurOutputTask->enc_surface);
526
527 vaStatus = vaQuerySurfaceStatus(mVADisplay, mCurOutputTask->enc_surface, &vaSurfaceStatus);
528 if (vaSurfaceStatus & VASurfaceReady) {
529 mOutCodedBuffer = mCurOutputTask->coded_buffer;
530 mFrameSkipped = vaSurfaceStatus & VASurfaceSkipped;
531 mCurOutputTask->completed = true;
532 //if need to call SyncSurface again ?
533
534 } else {//not encode complet yet, but keep all context and return directly
535 return ENCODE_DATA_NOT_READY;
536 }
537
538 }
539
540 }
541
542 //start to output data
543 ret = prepareForOutput(outBuffer, &useLocalBuffer);
544 CHECK_ENCODE_STATUS_CLEANUP("prepareForOutput");
545
546 //copy all flags to outBuffer
547 outBuffer->offset = 0;
548 outBuffer->flag = mCurOutputTask->flag;
549 outBuffer->type = mCurOutputTask->type;
550 outBuffer->timeStamp = mCurOutputTask->timestamp;
551 outBuffer->priv = mCurOutputTask->priv;
552
553 if (outBuffer->format == OUTPUT_EVERYTHING || outBuffer->format == OUTPUT_FRAME_DATA) {
554 ret = outputAllData(outBuffer);
555 CHECK_ENCODE_STATUS_CLEANUP("outputAllData");
556 }else {
557 ret = getExtFormatOutput(outBuffer);
558 CHECK_ENCODE_STATUS_CLEANUP("getExtFormatOutput");
559 }
560
561 LOG_V("out size for this getOutput call = %d\n", outBuffer->dataSize);
562
563 ret = cleanupForOutput();
564 CHECK_ENCODE_STATUS_CLEANUP("cleanupForOutput");
565
566 LOG_V("getOutput return Success, Frame skip is %d\n", mFrameSkipped);
567
568 return ENCODE_SUCCESS;
569
570 CLEAN_UP:
571
572 if (outBuffer->data && (useLocalBuffer == true)) {
573 delete[] outBuffer->data;
574 outBuffer->data = NULL;
575 useLocalBuffer = false;
576 }
577
578 if (mOutCodedBufferPtr != NULL) {
579 vaStatus = vaUnmapBuffer(mVADisplay, mOutCodedBuffer);
580 mOutCodedBufferPtr = NULL;
581 mCurSegment = NULL;
582 }
583
584 delete mCurOutputTask;
585 mCurOutputTask = NULL;
586 mCodedBuffer_Lock.lock();
587 mVACodedBufferList.push_back(mOutCodedBuffer);
588 mCodedBuffer_Cond.signal();
589 mCodedBuffer_Lock.unlock();
590
591 LOG_V("getOutput return error=%x\n", ret);
592 return ret;
593 }
594
flush()595 void VideoEncoderBase::flush() {
596
597 LOG_V( "Begin\n");
598
599 // reset the properities
600 mFrameNum = 0;
601
602 LOG_V( "end\n");
603 }
604
stop()605 Encode_Status VideoEncoderBase::stop() {
606
607 VAStatus vaStatus = VA_STATUS_SUCCESS;
608 Encode_Status ret = ENCODE_SUCCESS;
609
610 LOG_V( "Begin\n");
611
612 // It is possible that above pointers have been allocated
613 // before we set mStarted to true
614 if (!mStarted) {
615 LOG_V("Encoder has been stopped\n");
616 return ENCODE_SUCCESS;
617 }
618 if (mAutoRefSurfaces) {
619 delete[] mAutoRefSurfaces;
620 mAutoRefSurfaces = NULL;
621 }
622
623 mCodedBuffer_Lock.lock();
624 mVACodedBufferList.clear();
625 mCodedBuffer_Lock.unlock();
626 mCodedBuffer_Cond.broadcast();
627
628 //Delete all uncompleted tasks
629 mEncodeTask_Lock.lock();
630 while(! mEncodeTaskList.empty())
631 {
632 delete *mEncodeTaskList.begin();
633 mEncodeTaskList.erase(mEncodeTaskList.begin());
634 }
635 mEncodeTask_Lock.unlock();
636 mEncodeTask_Cond.broadcast();
637
638 //Release Src Surface Buffer Map, destroy surface manually since it is not added into context
639 LOG_V( "Rlease Src Surface Map\n");
640 while(! mSrcSurfaceMapList.empty())
641 {
642 delete (*mSrcSurfaceMapList.begin());
643 mSrcSurfaceMapList.erase(mSrcSurfaceMapList.begin());
644 }
645
646 LOG_V( "vaDestroyContext\n");
647 if (mVAContext != VA_INVALID_ID) {
648 vaStatus = vaDestroyContext(mVADisplay, mVAContext);
649 CHECK_VA_STATUS_GOTO_CLEANUP("vaDestroyContext");
650 }
651
652 LOG_V( "vaDestroyConfig\n");
653 if (mVAConfig != VA_INVALID_ID) {
654 vaStatus = vaDestroyConfig(mVADisplay, mVAConfig);
655 CHECK_VA_STATUS_GOTO_CLEANUP("vaDestroyConfig");
656 }
657
658 CLEAN_UP:
659
660 mStarted = false;
661 mSliceSizeOverflow = false;
662 mCurOutputTask= NULL;
663 mOutCodedBuffer = 0;
664 mCurSegment = NULL;
665 mOffsetInSeg =0;
666 mTotalSize = 0;
667 mTotalSizeCopied = 0;
668 mFrameSkipped = false;
669 mSupportedSurfaceMemType = 0;
670
671 LOG_V( "end\n");
672 return ret;
673 }
674
prepareForOutput(VideoEncOutputBuffer * outBuffer,bool * useLocalBuffer)675 Encode_Status VideoEncoderBase::prepareForOutput(
676 VideoEncOutputBuffer *outBuffer, bool *useLocalBuffer) {
677
678 VAStatus vaStatus = VA_STATUS_SUCCESS;
679 VACodedBufferSegment *vaCodedSeg = NULL;
680 uint32_t status = 0;
681
682 LOG_V( "begin\n");
683 // Won't check parameters here as the caller already checked them
684 // mCurSegment is NULL means it is first time to be here after finishing encoding a frame
685 if (mCurSegment == NULL) {
686 if (mOutCodedBufferPtr == NULL) {
687 vaStatus = vaMapBuffer (mVADisplay, mOutCodedBuffer, (void **)&mOutCodedBufferPtr);
688 CHECK_VA_STATUS_RETURN("vaMapBuffer");
689 CHECK_NULL_RETURN_IFFAIL(mOutCodedBufferPtr);
690 }
691
692 LOG_V("Coded Buffer ID been mapped = 0x%08x\n", mOutCodedBuffer);
693
694 mTotalSize = 0;
695 mOffsetInSeg = 0;
696 mTotalSizeCopied = 0;
697 vaCodedSeg = (VACodedBufferSegment *)mOutCodedBufferPtr;
698 mCurSegment = (VACodedBufferSegment *)mOutCodedBufferPtr;
699
700 while (1) {
701
702 mTotalSize += vaCodedSeg->size;
703 status = vaCodedSeg->status;
704 #ifndef IMG_GFX
705 uint8_t *pTemp;
706 uint32_t ii;
707 pTemp = (uint8_t*)vaCodedSeg->buf;
708 for(ii = 0; ii < 16;){
709 if (*(pTemp + ii) == 0xFF)
710 ii++;
711 else
712 break;
713 }
714 if (ii > 0) {
715 mOffsetInSeg = ii;
716 }
717 #endif
718 if (!mSliceSizeOverflow) {
719 mSliceSizeOverflow = status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK;
720 }
721
722 if (vaCodedSeg->next == NULL)
723 break;
724
725 vaCodedSeg = (VACodedBufferSegment *)vaCodedSeg->next;
726 }
727 }
728
729 // We will support two buffer allocation mode,
730 // one is application allocates the buffer and passes to encode,
731 // the other is encode allocate memory
732
733 //means app doesn't allocate the buffer, so _encode will allocate it.
734 if (outBuffer->data == NULL) {
735 *useLocalBuffer = true;
736 outBuffer->data = new uint8_t[mTotalSize - mTotalSizeCopied + 100];
737 if (outBuffer->data == NULL) {
738 LOG_E( "outBuffer->data == NULL\n");
739 return ENCODE_NO_MEMORY;
740 }
741 outBuffer->bufferSize = mTotalSize + 100;
742 outBuffer->dataSize = 0;
743 }
744
745 // Clear all flag for every call
746 outBuffer->flag = 0;
747 if (mSliceSizeOverflow) outBuffer->flag |= ENCODE_BUFFERFLAG_SLICEOVERFOLOW;
748
749 if (!mCurSegment)
750 return ENCODE_FAIL;
751
752 if (mCurSegment->size < mOffsetInSeg) {
753 LOG_E("mCurSegment->size < mOffsetInSeg\n");
754 return ENCODE_FAIL;
755 }
756
757 // Make sure we have data in current segment
758 if (mCurSegment->size == mOffsetInSeg) {
759 if (mCurSegment->next != NULL) {
760 mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
761 mOffsetInSeg = 0;
762 } else {
763 LOG_V("No more data available\n");
764 outBuffer->flag |= ENCODE_BUFFERFLAG_DATAINVALID;
765 outBuffer->dataSize = 0;
766 mCurSegment = NULL;
767 return ENCODE_NO_REQUEST_DATA;
768 }
769 }
770
771 LOG_V( "end\n");
772 return ENCODE_SUCCESS;
773 }
774
cleanupForOutput()775 Encode_Status VideoEncoderBase::cleanupForOutput() {
776
777 VAStatus vaStatus = VA_STATUS_SUCCESS;
778
779 //mCurSegment is NULL means all data has been copied out
780 if (mCurSegment == NULL && mOutCodedBufferPtr) {
781 vaStatus = vaUnmapBuffer(mVADisplay, mOutCodedBuffer);
782 CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
783 mOutCodedBufferPtr = NULL;
784 mTotalSize = 0;
785 mOffsetInSeg = 0;
786 mTotalSizeCopied = 0;
787
788 delete mCurOutputTask;
789 mCurOutputTask = NULL;
790 mCodedBuffer_Lock.lock();
791 mVACodedBufferList.push_back(mOutCodedBuffer);
792 mCodedBuffer_Cond.signal();
793 mCodedBuffer_Lock.unlock();
794
795 LOG_V("All data has been outputted, return CodedBuffer 0x%08x to pool\n", mOutCodedBuffer);
796 }
797 return ENCODE_SUCCESS;
798 }
799
queryProfileLevelConfig(VADisplay dpy,VAProfile profile)800 Encode_Status VideoEncoderBase::queryProfileLevelConfig(VADisplay dpy, VAProfile profile) {
801
802 VAStatus vaStatus = VA_STATUS_SUCCESS;
803 VAEntrypoint entryPtr[8];
804 int i, entryPtrNum;
805
806 if(profile == VAProfileH264Main) //need to be fixed
807 return ENCODE_NOT_SUPPORTED;
808
809 vaStatus = vaQueryConfigEntrypoints(dpy, profile, entryPtr, &entryPtrNum);
810 CHECK_VA_STATUS_RETURN("vaQueryConfigEntrypoints");
811
812 for(i=0; i<entryPtrNum; i++){
813 if(entryPtr[i] == VAEntrypointEncSlice)
814 return ENCODE_SUCCESS;
815 }
816
817 return ENCODE_NOT_SUPPORTED;
818 }
819
queryAutoReferenceConfig(VAProfile profile)820 Encode_Status VideoEncoderBase::queryAutoReferenceConfig(VAProfile profile) {
821
822 VAStatus vaStatus = VA_STATUS_SUCCESS;
823 VAConfigAttrib attrib_list;
824 attrib_list.type = VAConfigAttribEncAutoReference;
825 attrib_list.value = VA_ATTRIB_NOT_SUPPORTED;
826
827 vaStatus = vaGetConfigAttributes(mVADisplay, profile, VAEntrypointEncSlice, &attrib_list, 1);
828 CHECK_VA_STATUS_RETURN("vaQueryConfigAttributes");
829
830 if(attrib_list.value == VA_ATTRIB_NOT_SUPPORTED )
831 mAutoReference = false;
832 else
833 mAutoReference = true;
834
835 return ENCODE_SUCCESS;
836 }
837
querySupportedSurfaceMemTypes()838 Encode_Status VideoEncoderBase::querySupportedSurfaceMemTypes() {
839
840 VAStatus vaStatus = VA_STATUS_SUCCESS;
841
842 unsigned int num = 0;
843
844 VASurfaceAttrib* attribs = NULL;
845
846 //get attribs number
847 vaStatus = vaQuerySurfaceAttributes(mVADisplay, mVAConfig, attribs, &num);
848 CHECK_VA_STATUS_RETURN("vaGetSurfaceAttributes");
849
850 if (num == 0)
851 return ENCODE_SUCCESS;
852
853 attribs = new VASurfaceAttrib[num];
854
855 vaStatus = vaQuerySurfaceAttributes(mVADisplay, mVAConfig, attribs, &num);
856 CHECK_VA_STATUS_RETURN("vaGetSurfaceAttributes");
857
858 for(uint32_t i = 0; i < num; i ++) {
859 if (attribs[i].type == VASurfaceAttribMemoryType) {
860 mSupportedSurfaceMemType = attribs[i].value.value.i;
861 break;
862 }
863 else
864 continue;
865 }
866
867 delete attribs;
868
869 return ENCODE_SUCCESS;
870 }
871
outputAllData(VideoEncOutputBuffer * outBuffer)872 Encode_Status VideoEncoderBase::outputAllData(VideoEncOutputBuffer *outBuffer) {
873
874 // Data size been copied for every single call
875 uint32_t sizeCopiedHere = 0;
876 uint32_t sizeToBeCopied = 0;
877
878 CHECK_NULL_RETURN_IFFAIL(outBuffer->data);
879
880 while (1) {
881
882 LOG_V("mCurSegment->size = %d, mOffsetInSeg = %d\n", mCurSegment->size, mOffsetInSeg);
883 LOG_V("outBuffer->bufferSize = %d, sizeCopiedHere = %d, mTotalSizeCopied = %d\n",
884 outBuffer->bufferSize, sizeCopiedHere, mTotalSizeCopied);
885
886 if (mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere) {
887 LOG_E("mCurSegment->size < mOffsetInSeg || outBuffer->bufferSize < sizeCopiedHere\n");
888 return ENCODE_FAIL;
889 }
890
891 if ((mCurSegment->size - mOffsetInSeg) <= outBuffer->bufferSize - sizeCopiedHere) {
892 sizeToBeCopied = mCurSegment->size - mOffsetInSeg;
893 memcpy(outBuffer->data + sizeCopiedHere,
894 (uint8_t *)mCurSegment->buf + mOffsetInSeg, sizeToBeCopied);
895 sizeCopiedHere += sizeToBeCopied;
896 mTotalSizeCopied += sizeToBeCopied;
897 mOffsetInSeg = 0;
898 } else {
899 sizeToBeCopied = outBuffer->bufferSize - sizeCopiedHere;
900 memcpy(outBuffer->data + sizeCopiedHere,
901 (uint8_t *)mCurSegment->buf + mOffsetInSeg, outBuffer->bufferSize - sizeCopiedHere);
902 mTotalSizeCopied += sizeToBeCopied;
903 mOffsetInSeg += sizeToBeCopied;
904 outBuffer->dataSize = outBuffer->bufferSize;
905 outBuffer->remainingSize = mTotalSize - mTotalSizeCopied;
906 outBuffer->flag |= ENCODE_BUFFERFLAG_PARTIALFRAME;
907 return ENCODE_BUFFER_TOO_SMALL;
908 }
909
910 if (mCurSegment->next == NULL) {
911 outBuffer->dataSize = sizeCopiedHere;
912 outBuffer->remainingSize = 0;
913 outBuffer->flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
914 mCurSegment = NULL;
915 return ENCODE_SUCCESS;
916 }
917
918 mCurSegment = (VACodedBufferSegment *)mCurSegment->next;
919 mOffsetInSeg = 0;
920 }
921 }
922
setDefaultParams()923 void VideoEncoderBase::setDefaultParams() {
924
925 // Set default value for input parameters
926 mComParams.profile = VAProfileH264Baseline;
927 mComParams.level = 41;
928 mComParams.rawFormat = RAW_FORMAT_NV12;
929 mComParams.frameRate.frameRateNum = 30;
930 mComParams.frameRate.frameRateDenom = 1;
931 mComParams.resolution.width = 0;
932 mComParams.resolution.height = 0;
933 mComParams.intraPeriod = 30;
934 mComParams.rcMode = RATE_CONTROL_NONE;
935 mComParams.rcParams.initQP = 15;
936 mComParams.rcParams.minQP = 0;
937 mComParams.rcParams.maxQP = 0;
938 mComParams.rcParams.I_minQP = 0;
939 mComParams.rcParams.I_maxQP = 0;
940 mComParams.rcParams.bitRate = 640000;
941 mComParams.rcParams.targetPercentage= 0;
942 mComParams.rcParams.windowSize = 0;
943 mComParams.rcParams.disableFrameSkip = 0;
944 mComParams.rcParams.disableBitsStuffing = 1;
945 mComParams.rcParams.enableIntraFrameQPControl = 0;
946 mComParams.rcParams.temporalFrameRate = 0;
947 mComParams.rcParams.temporalID = 0;
948 mComParams.cyclicFrameInterval = 30;
949 mComParams.refreshType = VIDEO_ENC_NONIR;
950 mComParams.airParams.airMBs = 0;
951 mComParams.airParams.airThreshold = 0;
952 mComParams.airParams.airAuto = 1;
953 mComParams.disableDeblocking = 2;
954 mComParams.syncEncMode = false;
955 mComParams.codedBufNum = 2;
956 mComParams.numberOfLayer = 1;
957 mComParams.nPeriodicity = 0;
958 memset(mComParams.nLayerID,0,32*sizeof(uint32_t));
959
960 mHrdParam.bufferSize = 0;
961 mHrdParam.initBufferFullness = 0;
962
963 mStoreMetaDataInBuffers.isEnabled = false;
964 }
965
setParameters(VideoParamConfigSet * videoEncParams)966 Encode_Status VideoEncoderBase::setParameters(
967 VideoParamConfigSet *videoEncParams) {
968
969 Encode_Status ret = ENCODE_SUCCESS;
970 CHECK_NULL_RETURN_IFFAIL(videoEncParams);
971 LOG_V("Config type = %x\n", (int)videoEncParams->type);
972
973 if (mStarted) {
974 LOG_E("Encoder has been initialized, should use setConfig to change configurations\n");
975 return ENCODE_ALREADY_INIT;
976 }
977
978 switch (videoEncParams->type) {
979 case VideoParamsTypeCommon: {
980
981 VideoParamsCommon *paramsCommon =
982 reinterpret_cast <VideoParamsCommon *> (videoEncParams);
983 if (paramsCommon->size != sizeof (VideoParamsCommon)) {
984 return ENCODE_INVALID_PARAMS;
985 }
986 if(paramsCommon->codedBufNum < 2)
987 paramsCommon->codedBufNum =2;
988 mComParams = *paramsCommon;
989 break;
990 }
991
992 case VideoParamsTypeUpSteamBuffer: {
993
994 VideoParamsUpstreamBuffer *upStreamBuffer =
995 reinterpret_cast <VideoParamsUpstreamBuffer *> (videoEncParams);
996
997 if (upStreamBuffer->size != sizeof (VideoParamsUpstreamBuffer)) {
998 return ENCODE_INVALID_PARAMS;
999 }
1000
1001 ret = setUpstreamBuffer(upStreamBuffer);
1002 break;
1003 }
1004
1005 case VideoParamsTypeUsrptrBuffer: {
1006
1007 // usrptr only can be get
1008 // this case should not happen
1009 break;
1010 }
1011
1012 case VideoParamsTypeHRD: {
1013 VideoParamsHRD *hrd =
1014 reinterpret_cast <VideoParamsHRD *> (videoEncParams);
1015
1016 if (hrd->size != sizeof (VideoParamsHRD)) {
1017 return ENCODE_INVALID_PARAMS;
1018 }
1019
1020 mHrdParam.bufferSize = hrd->bufferSize;
1021 mHrdParam.initBufferFullness = hrd->initBufferFullness;
1022 mRenderHrd = true;
1023
1024 break;
1025 }
1026
1027 case VideoParamsTypeStoreMetaDataInBuffers: {
1028 VideoParamsStoreMetaDataInBuffers *metadata =
1029 reinterpret_cast <VideoParamsStoreMetaDataInBuffers *> (videoEncParams);
1030
1031 if (metadata->size != sizeof (VideoParamsStoreMetaDataInBuffers)) {
1032 return ENCODE_INVALID_PARAMS;
1033 }
1034
1035 mStoreMetaDataInBuffers.isEnabled = metadata->isEnabled;
1036
1037 break;
1038 }
1039
1040 case VideoParamsTypeTemporalLayer:{
1041 VideoParamsTemporalLayer *temporallayer =
1042 reinterpret_cast <VideoParamsTemporalLayer *> (videoEncParams);
1043
1044 if (temporallayer->size != sizeof(VideoParamsTemporalLayer)) {
1045 return ENCODE_INVALID_PARAMS;
1046 }
1047
1048 mComParams.numberOfLayer = temporallayer->numberOfLayer;
1049 mComParams.nPeriodicity = temporallayer->nPeriodicity;
1050 for(uint32_t i=0;i<temporallayer->nPeriodicity;i++)
1051 mComParams.nLayerID[i] = temporallayer->nLayerID[i];
1052 mRenderMultiTemporal = true;
1053 break;
1054 }
1055
1056 case VideoParamsTypeAVC:
1057 case VideoParamsTypeH263:
1058 case VideoParamsTypeMP4:
1059 case VideoParamsTypeVC1:
1060 case VideoParamsTypeVP8: {
1061 ret = derivedSetParams(videoEncParams);
1062 break;
1063 }
1064
1065 default: {
1066 LOG_E ("Wrong ParamType here\n");
1067 return ENCODE_INVALID_PARAMS;
1068 }
1069 }
1070 return ret;
1071 }
1072
getParameters(VideoParamConfigSet * videoEncParams)1073 Encode_Status VideoEncoderBase::getParameters(
1074 VideoParamConfigSet *videoEncParams) {
1075
1076 Encode_Status ret = ENCODE_SUCCESS;
1077 CHECK_NULL_RETURN_IFFAIL(videoEncParams);
1078 LOG_V("Config type = %d\n", (int)videoEncParams->type);
1079
1080 switch (videoEncParams->type) {
1081 case VideoParamsTypeCommon: {
1082
1083 VideoParamsCommon *paramsCommon =
1084 reinterpret_cast <VideoParamsCommon *> (videoEncParams);
1085
1086 if (paramsCommon->size != sizeof (VideoParamsCommon)) {
1087 return ENCODE_INVALID_PARAMS;
1088 }
1089 *paramsCommon = mComParams;
1090 break;
1091 }
1092
1093 case VideoParamsTypeUpSteamBuffer: {
1094
1095 // Get upstream buffer could happen
1096 // but not meaningful a lot
1097 break;
1098 }
1099
1100 case VideoParamsTypeUsrptrBuffer: {
1101 VideoParamsUsrptrBuffer *usrptrBuffer =
1102 reinterpret_cast <VideoParamsUsrptrBuffer *> (videoEncParams);
1103
1104 if (usrptrBuffer->size != sizeof (VideoParamsUsrptrBuffer)) {
1105 return ENCODE_INVALID_PARAMS;
1106 }
1107
1108 ret = getNewUsrptrFromSurface(
1109 usrptrBuffer->width, usrptrBuffer->height, usrptrBuffer->format,
1110 usrptrBuffer->expectedSize, &(usrptrBuffer->actualSize),
1111 &(usrptrBuffer->stride), &(usrptrBuffer->usrPtr));
1112
1113 break;
1114 }
1115
1116 case VideoParamsTypeHRD: {
1117 VideoParamsHRD *hrd =
1118 reinterpret_cast <VideoParamsHRD *> (videoEncParams);
1119
1120 if (hrd->size != sizeof (VideoParamsHRD)) {
1121 return ENCODE_INVALID_PARAMS;
1122 }
1123
1124 hrd->bufferSize = mHrdParam.bufferSize;
1125 hrd->initBufferFullness = mHrdParam.initBufferFullness;
1126
1127 break;
1128 }
1129
1130 case VideoParamsTypeStoreMetaDataInBuffers: {
1131 VideoParamsStoreMetaDataInBuffers *metadata =
1132 reinterpret_cast <VideoParamsStoreMetaDataInBuffers *> (videoEncParams);
1133
1134 if (metadata->size != sizeof (VideoParamsStoreMetaDataInBuffers)) {
1135 return ENCODE_INVALID_PARAMS;
1136 }
1137
1138 metadata->isEnabled = mStoreMetaDataInBuffers.isEnabled;
1139
1140 break;
1141 }
1142
1143 case VideoParamsTypeProfileLevel: {
1144 VideoParamsProfileLevel *profilelevel =
1145 reinterpret_cast <VideoParamsProfileLevel *> (videoEncParams);
1146
1147 if (profilelevel->size != sizeof (VideoParamsProfileLevel)) {
1148 return ENCODE_INVALID_PARAMS;
1149 }
1150
1151 profilelevel->level = 0;
1152 if(queryProfileLevelConfig(mVADisplay, profilelevel->profile) == ENCODE_SUCCESS){
1153 profilelevel->isSupported = true;
1154 if(profilelevel->profile == VAProfileH264High)
1155 profilelevel->level = 42;
1156 else if(profilelevel->profile == VAProfileH264Main)
1157 profilelevel->level = 42;
1158 else if(profilelevel->profile == VAProfileH264Baseline)
1159 profilelevel->level = 41;
1160 else{
1161 profilelevel->level = 0;
1162 profilelevel->isSupported = false;
1163 }
1164 }
1165 }
1166
1167 case VideoParamsTypeTemporalLayer:{
1168 VideoParamsTemporalLayer *temporallayer =
1169 reinterpret_cast <VideoParamsTemporalLayer *> (videoEncParams);
1170
1171 if(temporallayer->size != sizeof(VideoParamsTemporalLayer)) {
1172 return ENCODE_INVALID_PARAMS;
1173 }
1174
1175 temporallayer->numberOfLayer = mComParams.numberOfLayer;
1176
1177 break;
1178 }
1179
1180 case VideoParamsTypeAVC:
1181 case VideoParamsTypeH263:
1182 case VideoParamsTypeMP4:
1183 case VideoParamsTypeVC1:
1184 case VideoParamsTypeVP8: {
1185 derivedGetParams(videoEncParams);
1186 break;
1187 }
1188
1189 default: {
1190 LOG_E ("Wrong ParamType here\n");
1191 break;
1192 }
1193
1194 }
1195 return ret;
1196 }
1197
setConfig(VideoParamConfigSet * videoEncConfig)1198 Encode_Status VideoEncoderBase::setConfig(VideoParamConfigSet *videoEncConfig) {
1199
1200 Encode_Status ret = ENCODE_SUCCESS;
1201 CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
1202 LOG_V("Config type = %d\n", (int)videoEncConfig->type);
1203
1204 // workaround
1205 #if 0
1206 if (!mStarted) {
1207 LOG_E("Encoder has not initialized yet, can't call setConfig\n");
1208 return ENCODE_NOT_INIT;
1209 }
1210 #endif
1211
1212 switch (videoEncConfig->type) {
1213 case VideoConfigTypeFrameRate: {
1214 VideoConfigFrameRate *configFrameRate =
1215 reinterpret_cast <VideoConfigFrameRate *> (videoEncConfig);
1216
1217 if (configFrameRate->size != sizeof (VideoConfigFrameRate)) {
1218 return ENCODE_INVALID_PARAMS;
1219 }
1220 mComParams.frameRate = configFrameRate->frameRate;
1221 mRenderFrameRate = true;
1222 break;
1223 }
1224
1225 case VideoConfigTypeBitRate: {
1226 VideoConfigBitRate *configBitRate =
1227 reinterpret_cast <VideoConfigBitRate *> (videoEncConfig);
1228
1229 if (configBitRate->size != sizeof (VideoConfigBitRate)) {
1230 return ENCODE_INVALID_PARAMS;
1231 }
1232
1233 if(mComParams.numberOfLayer == 1)
1234 {
1235 mComParams.rcParams = configBitRate->rcParams;
1236 mRenderBitRate = true;
1237 }
1238 else
1239 {
1240 mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].nLayerID = configBitRate->rcParams.temporalID;
1241 mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].bitRate = configBitRate->rcParams.bitRate;
1242 mTemporalLayerBitrateFramerate[configBitRate->rcParams.temporalID].frameRate = configBitRate->rcParams.temporalFrameRate;
1243 }
1244 break;
1245 }
1246
1247 case VideoConfigTypeResolution: {
1248
1249 // Not Implemented
1250 break;
1251 }
1252 case VideoConfigTypeIntraRefreshType: {
1253
1254 VideoConfigIntraRefreshType *configIntraRefreshType =
1255 reinterpret_cast <VideoConfigIntraRefreshType *> (videoEncConfig);
1256
1257 if (configIntraRefreshType->size != sizeof (VideoConfigIntraRefreshType)) {
1258 return ENCODE_INVALID_PARAMS;
1259 }
1260 mComParams.refreshType = configIntraRefreshType->refreshType;
1261 break;
1262 }
1263
1264 case VideoConfigTypeCyclicFrameInterval: {
1265 VideoConfigCyclicFrameInterval *configCyclicFrameInterval =
1266 reinterpret_cast <VideoConfigCyclicFrameInterval *> (videoEncConfig);
1267 if (configCyclicFrameInterval->size != sizeof (VideoConfigCyclicFrameInterval)) {
1268 return ENCODE_INVALID_PARAMS;
1269 }
1270
1271 mComParams.cyclicFrameInterval = configCyclicFrameInterval->cyclicFrameInterval;
1272 break;
1273 }
1274
1275 case VideoConfigTypeAIR: {
1276
1277 VideoConfigAIR *configAIR = reinterpret_cast <VideoConfigAIR *> (videoEncConfig);
1278
1279 if (configAIR->size != sizeof (VideoConfigAIR)) {
1280 return ENCODE_INVALID_PARAMS;
1281 }
1282
1283 mComParams.airParams = configAIR->airParams;
1284 mRenderAIR = true;
1285 break;
1286 }
1287 case VideoConfigTypeCIR: {
1288
1289 VideoConfigCIR *configCIR = reinterpret_cast <VideoConfigCIR *> (videoEncConfig);
1290
1291 if (configCIR->size != sizeof (VideoConfigCIR)) {
1292 return ENCODE_INVALID_PARAMS;
1293 }
1294
1295 mComParams.cirParams = configCIR->cirParams;
1296 mRenderCIR = true;
1297 break;
1298 }
1299 case VideoConfigTypeAVCIntraPeriod:
1300 case VideoConfigTypeNALSize:
1301 case VideoConfigTypeIDRRequest:
1302 case VideoConfigTypeSliceNum:
1303 case VideoConfigTypeVP8:
1304 case VideoConfigTypeVP8ReferenceFrame:
1305 case VideoConfigTypeVP8MaxFrameSizeRatio:{
1306 ret = derivedSetConfig(videoEncConfig);
1307 break;
1308 }
1309 default: {
1310 LOG_E ("Wrong Config Type here\n");
1311 break;
1312 }
1313 }
1314 return ret;
1315 }
1316
getConfig(VideoParamConfigSet * videoEncConfig)1317 Encode_Status VideoEncoderBase::getConfig(VideoParamConfigSet *videoEncConfig) {
1318
1319 Encode_Status ret = ENCODE_SUCCESS;
1320 CHECK_NULL_RETURN_IFFAIL(videoEncConfig);
1321 LOG_V("Config type = %d\n", (int)videoEncConfig->type);
1322
1323 switch (videoEncConfig->type) {
1324 case VideoConfigTypeFrameRate: {
1325 VideoConfigFrameRate *configFrameRate =
1326 reinterpret_cast <VideoConfigFrameRate *> (videoEncConfig);
1327
1328 if (configFrameRate->size != sizeof (VideoConfigFrameRate)) {
1329 return ENCODE_INVALID_PARAMS;
1330 }
1331
1332 configFrameRate->frameRate = mComParams.frameRate;
1333 break;
1334 }
1335
1336 case VideoConfigTypeBitRate: {
1337 VideoConfigBitRate *configBitRate =
1338 reinterpret_cast <VideoConfigBitRate *> (videoEncConfig);
1339
1340 if (configBitRate->size != sizeof (VideoConfigBitRate)) {
1341 return ENCODE_INVALID_PARAMS;
1342 }
1343 configBitRate->rcParams = mComParams.rcParams;
1344
1345
1346 break;
1347 }
1348 case VideoConfigTypeResolution: {
1349 // Not Implemented
1350 break;
1351 }
1352 case VideoConfigTypeIntraRefreshType: {
1353
1354 VideoConfigIntraRefreshType *configIntraRefreshType =
1355 reinterpret_cast <VideoConfigIntraRefreshType *> (videoEncConfig);
1356
1357 if (configIntraRefreshType->size != sizeof (VideoConfigIntraRefreshType)) {
1358 return ENCODE_INVALID_PARAMS;
1359 }
1360 configIntraRefreshType->refreshType = mComParams.refreshType;
1361 break;
1362 }
1363
1364 case VideoConfigTypeCyclicFrameInterval: {
1365 VideoConfigCyclicFrameInterval *configCyclicFrameInterval =
1366 reinterpret_cast <VideoConfigCyclicFrameInterval *> (videoEncConfig);
1367 if (configCyclicFrameInterval->size != sizeof (VideoConfigCyclicFrameInterval)) {
1368 return ENCODE_INVALID_PARAMS;
1369 }
1370
1371 configCyclicFrameInterval->cyclicFrameInterval = mComParams.cyclicFrameInterval;
1372 break;
1373 }
1374
1375 case VideoConfigTypeAIR: {
1376
1377 VideoConfigAIR *configAIR = reinterpret_cast <VideoConfigAIR *> (videoEncConfig);
1378
1379 if (configAIR->size != sizeof (VideoConfigAIR)) {
1380 return ENCODE_INVALID_PARAMS;
1381 }
1382
1383 configAIR->airParams = mComParams.airParams;
1384 break;
1385 }
1386 case VideoConfigTypeCIR: {
1387
1388 VideoConfigCIR *configCIR = reinterpret_cast <VideoConfigCIR *> (videoEncConfig);
1389
1390 if (configCIR->size != sizeof (VideoConfigCIR)) {
1391 return ENCODE_INVALID_PARAMS;
1392 }
1393
1394 configCIR->cirParams = mComParams.cirParams;
1395 break;
1396 }
1397 case VideoConfigTypeAVCIntraPeriod:
1398 case VideoConfigTypeNALSize:
1399 case VideoConfigTypeIDRRequest:
1400 case VideoConfigTypeSliceNum:
1401 case VideoConfigTypeVP8: {
1402
1403 ret = derivedGetConfig(videoEncConfig);
1404 break;
1405 }
1406 default: {
1407 LOG_E ("Wrong ParamType here\n");
1408 break;
1409 }
1410 }
1411 return ret;
1412 }
1413
PrepareFrameInfo(EncodeTask * task)1414 void VideoEncoderBase:: PrepareFrameInfo (EncodeTask* task) {
1415 if (mNewHeader) mFrameNum = 0;
1416 LOG_V( "mFrameNum = %d ", mFrameNum);
1417
1418 updateFrameInfo(task) ;
1419 }
1420
updateFrameInfo(EncodeTask * task)1421 Encode_Status VideoEncoderBase:: updateFrameInfo (EncodeTask* task) {
1422
1423 task->type = FTYPE_P;
1424
1425 // determine the picture type
1426 if (mFrameNum == 0)
1427 task->type = FTYPE_I;
1428 if (mComParams.intraPeriod != 0 && ((mFrameNum % mComParams.intraPeriod) == 0))
1429 task->type = FTYPE_I;
1430
1431 if (task->type == FTYPE_I)
1432 task->flag |= ENCODE_BUFFERFLAG_SYNCFRAME;
1433
1434 return ENCODE_SUCCESS;
1435 }
1436
getMaxOutSize(uint32_t * maxSize)1437 Encode_Status VideoEncoderBase::getMaxOutSize (uint32_t *maxSize) {
1438
1439 uint32_t size = mComParams.resolution.width * mComParams.resolution.height;
1440
1441 if (maxSize == NULL) {
1442 LOG_E("maxSize == NULL\n");
1443 return ENCODE_NULL_PTR;
1444 }
1445
1446 LOG_V( "Begin\n");
1447
1448 if (mCodedBufSize > 0) {
1449 *maxSize = mCodedBufSize;
1450 LOG_V ("Already calculate the max encoded size, get the value directly");
1451 return ENCODE_SUCCESS;
1452 }
1453
1454 // here, VP8 is different from AVC/H263
1455 if(mComParams.profile == VAProfileVP8Version0_3) // for VP8 encode
1456 {
1457 // According to VIED suggestions, in CBR mode, coded buffer should be the size of 3 bytes per luma pixel
1458 // in CBR_HRD mode, coded buffer size should be 5 * rc_buf_sz * rc_target_bitrate;
1459 // now we just hardcode mCodedBufSize as 2M to walk round coded buffer size issue;
1460 /*
1461 if(mComParams.rcMode == VA_RC_CBR) // CBR_HRD mode
1462 mCodedBufSize = 5 * mComParams.rcParams.bitRate * 6000;
1463 else // CBR mode
1464 mCodedBufSize = 3 * mComParams.resolution.width * mComParams.resolution.height;
1465 */
1466 mCodedBufSize = (2 * 1024 * 1024 + 31) & (~31);
1467 }
1468 else // for AVC/H263/MPEG4 encode
1469 {
1470 // base on the rate control mode to calculate the defaule encoded buffer size
1471 if (mComParams.rcMode == VA_RC_NONE) {
1472 mCodedBufSize = (size * 400) / (16 * 16);
1473 // set to value according to QP
1474 } else {
1475 mCodedBufSize = mComParams.rcParams.bitRate / 4;
1476 }
1477
1478 mCodedBufSize = max (mCodedBufSize , (size * 400) / (16 * 16));
1479
1480 // in case got a very large user input bit rate value
1481 mCodedBufSize = min(mCodedBufSize, (size * 1.5 * 8));
1482 mCodedBufSize = (mCodedBufSize + 15) &(~15);
1483 }
1484
1485 *maxSize = mCodedBufSize;
1486 return ENCODE_SUCCESS;
1487 }
1488
getNewUsrptrFromSurface(uint32_t width,uint32_t height,uint32_t format,uint32_t expectedSize,uint32_t * outsize,uint32_t * stride,uint8_t ** usrptr)1489 Encode_Status VideoEncoderBase::getNewUsrptrFromSurface(
1490 uint32_t width, uint32_t height, uint32_t format,
1491 uint32_t expectedSize, uint32_t *outsize, uint32_t *stride, uint8_t **usrptr) {
1492
1493 Encode_Status ret = ENCODE_FAIL;
1494 VAStatus vaStatus = VA_STATUS_SUCCESS;
1495
1496 VASurfaceID surface = VA_INVALID_SURFACE;
1497 VAImage image;
1498 uint32_t index = 0;
1499
1500 LOG_V( "Begin\n");
1501 // If encode session has been configured, we can not request surface creation anymore
1502 if (mStarted) {
1503 LOG_E( "Already Initialized, can not request VA surface anymore\n");
1504 return ENCODE_WRONG_STATE;
1505 }
1506 if (width<=0 || height<=0 ||outsize == NULL ||stride == NULL || usrptr == NULL) {
1507 LOG_E("width<=0 || height<=0 || outsize == NULL || stride == NULL ||usrptr == NULL\n");
1508 return ENCODE_NULL_PTR;
1509 }
1510
1511 // Current only NV12 is supported in VA API
1512 // Through format we can get known the number of planes
1513 if (format != STRING_TO_FOURCC("NV12")) {
1514 LOG_W ("Format is not supported\n");
1515 return ENCODE_NOT_SUPPORTED;
1516 }
1517
1518 surface = CreateNewVASurface(mVADisplay, width, height);
1519 if (surface == VA_INVALID_SURFACE)
1520 return ENCODE_DRIVER_FAIL;
1521
1522 vaStatus = vaDeriveImage(mVADisplay, surface, &image);
1523 CHECK_VA_STATUS_RETURN("vaDeriveImage");
1524 LOG_V( "vaDeriveImage Done\n");
1525 vaStatus = vaMapBuffer(mVADisplay, image.buf, (void **) usrptr);
1526 CHECK_VA_STATUS_RETURN("vaMapBuffer");
1527
1528 // make sure the physical page been allocated
1529 for (index = 0; index < image.data_size; index = index + 4096) {
1530 unsigned char tmp = *(*usrptr + index);
1531 if (tmp == 0)
1532 *(*usrptr + index) = 0;
1533 }
1534
1535 *outsize = image.data_size;
1536 *stride = image.pitches[0];
1537
1538 LOG_V( "surface = 0x%08x\n",(uint32_t)surface);
1539 LOG_V("image->pitches[0] = %d\n", image.pitches[0]);
1540 LOG_V("image->pitches[1] = %d\n", image.pitches[1]);
1541 LOG_V("image->offsets[0] = %d\n", image.offsets[0]);
1542 LOG_V("image->offsets[1] = %d\n", image.offsets[1]);
1543 LOG_V("image->num_planes = %d\n", image.num_planes);
1544 LOG_V("image->width = %d\n", image.width);
1545 LOG_V("image->height = %d\n", image.height);
1546 LOG_V("data_size = %d\n", image.data_size);
1547 LOG_V("usrptr = 0x%p\n", *usrptr);
1548
1549 vaStatus = vaUnmapBuffer(mVADisplay, image.buf);
1550 CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
1551 vaStatus = vaDestroyImage(mVADisplay, image.image_id);
1552 CHECK_VA_STATUS_RETURN("vaDestroyImage");
1553
1554 if (*outsize < expectedSize) {
1555 LOG_E ("Allocated buffer size is small than the expected size, destroy the surface");
1556 LOG_I ("Allocated size is %d, expected size is %d\n", *outsize, expectedSize);
1557 vaStatus = vaDestroySurfaces(mVADisplay, &surface, 1);
1558 CHECK_VA_STATUS_RETURN("vaDestroySurfaces");
1559 return ENCODE_FAIL;
1560 }
1561
1562 VASurfaceMap *map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
1563 if (map == NULL) {
1564 LOG_E( "new VASurfaceMap failed\n");
1565 return ENCODE_NO_MEMORY;
1566 }
1567
1568 map->setVASurface(surface); //special case, vasuface is set, so nothing do in doMapping
1569 // map->setType(MetadataBufferTypeEncoder);
1570 map->setValue((intptr_t)*usrptr);
1571 ValueInfo vinfo;
1572 memset(&vinfo, 0, sizeof(ValueInfo));
1573 vinfo.mode = (MemMode)MEM_MODE_USRPTR;
1574 vinfo.handle = 0;
1575 vinfo.size = 0;
1576 vinfo.width = width;
1577 vinfo.height = height;
1578 vinfo.lumaStride = width;
1579 vinfo.chromStride = width;
1580 vinfo.format = VA_FOURCC_NV12;
1581 vinfo.s3dformat = 0xffffffff;
1582 map->setValueInfo(vinfo);
1583 map->doMapping();
1584
1585 mSrcSurfaceMapList.push_back(map);
1586
1587 ret = ENCODE_SUCCESS;
1588
1589 return ret;
1590 }
1591
setUpstreamBuffer(VideoParamsUpstreamBuffer * upStreamBuffer)1592 Encode_Status VideoEncoderBase::setUpstreamBuffer(VideoParamsUpstreamBuffer *upStreamBuffer) {
1593
1594 Encode_Status status = ENCODE_SUCCESS;
1595
1596 CHECK_NULL_RETURN_IFFAIL(upStreamBuffer);
1597 if (upStreamBuffer->bufCnt == 0) {
1598 LOG_E("bufCnt == 0\n");
1599 return ENCODE_FAIL;
1600 }
1601
1602 for(unsigned int i=0; i < upStreamBuffer->bufCnt; i++) {
1603 if (findSurfaceMapByValue(upStreamBuffer->bufList[i]) != NULL) //already mapped
1604 continue;
1605
1606 //wrap upstream buffer into vaSurface
1607 VASurfaceMap *map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
1608
1609 // map->setType(MetadataBufferTypeUser);
1610 map->setValue(upStreamBuffer->bufList[i]);
1611 ValueInfo vinfo;
1612 memset(&vinfo, 0, sizeof(ValueInfo));
1613 vinfo.mode = (MemMode)upStreamBuffer->bufferMode;
1614 vinfo.handle = (intptr_t)upStreamBuffer->display;
1615 vinfo.size = 0;
1616 if (upStreamBuffer->bufAttrib) {
1617 vinfo.width = upStreamBuffer->bufAttrib->realWidth;
1618 vinfo.height = upStreamBuffer->bufAttrib->realHeight;
1619 vinfo.lumaStride = upStreamBuffer->bufAttrib->lumaStride;
1620 vinfo.chromStride = upStreamBuffer->bufAttrib->chromStride;
1621 vinfo.format = upStreamBuffer->bufAttrib->format;
1622 }
1623 vinfo.s3dformat = 0xFFFFFFFF;
1624 map->setValueInfo(vinfo);
1625 status = map->doMapping();
1626
1627 if (status == ENCODE_SUCCESS)
1628 mSrcSurfaceMapList.push_back(map);
1629 else
1630 delete map;
1631 }
1632
1633 return status;
1634 }
1635
manageSrcSurface(VideoEncRawBuffer * inBuffer,VASurfaceID * sid)1636 Encode_Status VideoEncoderBase::manageSrcSurface(VideoEncRawBuffer *inBuffer, VASurfaceID *sid) {
1637
1638 Encode_Status ret = ENCODE_SUCCESS;
1639 IntelMetadataBufferType type;
1640 intptr_t value;
1641 ValueInfo vinfo;
1642 ValueInfo *pvinfo = &vinfo;
1643 intptr_t *extravalues = NULL;
1644 unsigned int extravalues_count = 0;
1645
1646 IntelMetadataBuffer imb;
1647 VASurfaceMap *map = NULL;
1648
1649 memset(&vinfo, 0, sizeof(ValueInfo));
1650 if (mStoreMetaDataInBuffers.isEnabled) {
1651 //metadatabuffer mode
1652 LOG_V("in metadata mode, data=%p, size=%d\n", inBuffer->data, inBuffer->size);
1653 if (imb.UnSerialize(inBuffer->data, inBuffer->size) != IMB_SUCCESS) {
1654 //fail to parse buffer
1655 return ENCODE_NO_REQUEST_DATA;
1656 }
1657
1658 imb.GetType(type);
1659 imb.GetValue(value);
1660 } else {
1661 //raw mode
1662 LOG_I("in raw mode, data=%p, size=%d\n", inBuffer->data, inBuffer->size);
1663 if (! inBuffer->data || inBuffer->size == 0) {
1664 return ENCODE_NULL_PTR;
1665 }
1666
1667 type = IntelMetadataBufferTypeUser;
1668 value = (intptr_t)inBuffer->data;
1669 }
1670
1671 #ifdef INTEL_VIDEO_XPROC_SHARING
1672 uint32_t sflag = mSessionFlag;
1673 imb.GetSessionFlag(mSessionFlag);
1674 if (mSessionFlag != sflag) {
1675 //new sharing session, flush buffer sharing cache
1676 IntelMetadataBuffer::ClearContext(sflag, false);
1677 //flush surfacemap cache
1678 LOG_V( "Flush Src Surface Map\n");
1679 while(! mSrcSurfaceMapList.empty())
1680 {
1681 delete (*mSrcSurfaceMapList.begin());
1682 mSrcSurfaceMapList.erase(mSrcSurfaceMapList.begin());
1683 }
1684 }
1685 #endif
1686
1687 //find if mapped
1688 map = (VASurfaceMap*) findSurfaceMapByValue(value);
1689
1690 if (map) {
1691 //has mapped, get surfaceID directly and do all necessary actions
1692 LOG_V("direct find surface %d from value %i\n", map->getVASurface(), value);
1693 *sid = map->getVASurface();
1694 map->doMapping();
1695 return ret;
1696 }
1697
1698 //if no found from list, then try to map value with parameters
1699 LOG_V("not find surface from cache with value %i, start mapping if enough information\n", value);
1700
1701 if (mStoreMetaDataInBuffers.isEnabled) {
1702
1703 //if type is IntelMetadataBufferTypeGrallocSource, use default parameters since no ValueInfo
1704 if (type == IntelMetadataBufferTypeGrallocSource) {
1705 vinfo.mode = MEM_MODE_GFXHANDLE;
1706 vinfo.handle = 0;
1707 vinfo.size = 0;
1708 vinfo.width = mComParams.resolution.width;
1709 vinfo.height = mComParams.resolution.height;
1710 vinfo.lumaStride = mComParams.resolution.width;
1711 vinfo.chromStride = mComParams.resolution.width;
1712 vinfo.format = VA_FOURCC_NV12;
1713 vinfo.s3dformat = 0xFFFFFFFF;
1714 } else {
1715 //get all info mapping needs
1716 imb.GetValueInfo(pvinfo);
1717 imb.GetExtraValues(extravalues, extravalues_count);
1718 }
1719
1720 } else {
1721
1722 //raw mode
1723 vinfo.mode = MEM_MODE_MALLOC;
1724 vinfo.handle = 0;
1725 vinfo.size = inBuffer->size;
1726 vinfo.width = mComParams.resolution.width;
1727 vinfo.height = mComParams.resolution.height;
1728 vinfo.lumaStride = mComParams.resolution.width;
1729 vinfo.chromStride = mComParams.resolution.width;
1730 vinfo.format = VA_FOURCC_NV12;
1731 vinfo.s3dformat = 0xFFFFFFFF;
1732 }
1733
1734 /* Start mapping, if pvinfo is not NULL, then have enough info to map;
1735 * if extravalues is not NULL, then need to do more times mapping
1736 */
1737 if (pvinfo){
1738 //map according info, and add to surfacemap list
1739 map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
1740 map->setValue(value);
1741 map->setValueInfo(*pvinfo);
1742 map->setAction(mVASurfaceMappingAction);
1743
1744 ret = map->doMapping();
1745 if (ret == ENCODE_SUCCESS) {
1746 LOG_V("surface mapping success, map value %i into surface %d\n", value, map->getVASurface());
1747 mSrcSurfaceMapList.push_back(map);
1748 } else {
1749 delete map;
1750 LOG_E("surface mapping failed, wrong info or meet serious error\n");
1751 return ret;
1752 }
1753
1754 *sid = map->getVASurface();
1755
1756 } else {
1757 //can't map due to no info
1758 LOG_E("surface mapping failed, missing information\n");
1759 return ENCODE_NO_REQUEST_DATA;
1760 }
1761
1762 if (extravalues) {
1763 //map more using same ValueInfo
1764 for(unsigned int i=0; i<extravalues_count; i++) {
1765 map = new VASurfaceMap(mVADisplay, mSupportedSurfaceMemType);
1766 map->setValue(extravalues[i]);
1767 map->setValueInfo(vinfo);
1768
1769 ret = map->doMapping();
1770 if (ret == ENCODE_SUCCESS) {
1771 LOG_V("surface mapping extravalue success, map value %i into surface %d\n", extravalues[i], map->getVASurface());
1772 mSrcSurfaceMapList.push_back(map);
1773 } else {
1774 delete map;
1775 map = NULL;
1776 LOG_E( "surface mapping extravalue failed, extravalue is %i\n", extravalues[i]);
1777 }
1778 }
1779 }
1780
1781 return ret;
1782 }
1783
renderDynamicBitrate(EncodeTask * task)1784 Encode_Status VideoEncoderBase::renderDynamicBitrate(EncodeTask* task) {
1785 VAStatus vaStatus = VA_STATUS_SUCCESS;
1786
1787 LOG_V( "Begin\n\n");
1788 // disable bits stuffing and skip frame apply to all rate control mode
1789
1790 VAEncMiscParameterBuffer *miscEncParamBuf;
1791 VAEncMiscParameterRateControl *bitrateControlParam;
1792 VABufferID miscParamBufferID;
1793
1794 vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
1795 VAEncMiscParameterBufferType,
1796 sizeof (VAEncMiscParameterBuffer) + sizeof (VAEncMiscParameterRateControl),
1797 1, NULL,
1798 &miscParamBufferID);
1799
1800 CHECK_VA_STATUS_RETURN("vaCreateBuffer");
1801
1802 vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
1803 CHECK_VA_STATUS_RETURN("vaMapBuffer");
1804
1805 miscEncParamBuf->type = VAEncMiscParameterTypeRateControl;
1806 bitrateControlParam = (VAEncMiscParameterRateControl *)miscEncParamBuf->data;
1807
1808 bitrateControlParam->bits_per_second = mComParams.rcParams.bitRate;
1809 bitrateControlParam->initial_qp = mComParams.rcParams.initQP;
1810 if(mComParams.rcParams.enableIntraFrameQPControl && (task->type == FTYPE_IDR || task->type == FTYPE_I)) {
1811 bitrateControlParam->min_qp = mComParams.rcParams.I_minQP;
1812 bitrateControlParam->max_qp = mComParams.rcParams.I_maxQP;
1813 mRenderBitRate = true;
1814 LOG_I("apply I min/max qp for IDR or I frame\n");
1815 } else {
1816 bitrateControlParam->min_qp = mComParams.rcParams.minQP;
1817 bitrateControlParam->max_qp = mComParams.rcParams.maxQP;
1818 mRenderBitRate = false;
1819 LOG_I("revert to original min/max qp after IDR or I frame\n");
1820 }
1821 bitrateControlParam->target_percentage = mComParams.rcParams.targetPercentage;
1822 bitrateControlParam->window_size = mComParams.rcParams.windowSize;
1823 bitrateControlParam->rc_flags.bits.disable_frame_skip = mComParams.rcParams.disableFrameSkip;
1824 bitrateControlParam->rc_flags.bits.disable_bit_stuffing = mComParams.rcParams.disableBitsStuffing;
1825 bitrateControlParam->basic_unit_size = 0;
1826
1827 LOG_I("bits_per_second = %d\n", bitrateControlParam->bits_per_second);
1828 LOG_I("initial_qp = %d\n", bitrateControlParam->initial_qp);
1829 LOG_I("min_qp = %d\n", bitrateControlParam->min_qp);
1830 LOG_I("max_qp = %d\n", bitrateControlParam->max_qp);
1831 LOG_I("target_percentage = %d\n", bitrateControlParam->target_percentage);
1832 LOG_I("window_size = %d\n", bitrateControlParam->window_size);
1833 LOG_I("disable_frame_skip = %d\n", bitrateControlParam->rc_flags.bits.disable_frame_skip);
1834 LOG_I("disable_bit_stuffing = %d\n", bitrateControlParam->rc_flags.bits.disable_bit_stuffing);
1835
1836 vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
1837 CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
1838
1839 vaStatus = vaRenderPicture(mVADisplay, mVAContext,
1840 &miscParamBufferID, 1);
1841 CHECK_VA_STATUS_RETURN("vaRenderPicture");
1842
1843 return ENCODE_SUCCESS;
1844 }
1845
1846
renderDynamicFrameRate()1847 Encode_Status VideoEncoderBase::renderDynamicFrameRate() {
1848
1849 VAStatus vaStatus = VA_STATUS_SUCCESS;
1850
1851 if (mComParams.rcMode != RATE_CONTROL_VCM) {
1852
1853 LOG_W("Not in VCM mode, but call SendDynamicFramerate\n");
1854 return ENCODE_SUCCESS;
1855 }
1856
1857 VAEncMiscParameterBuffer *miscEncParamBuf;
1858 VAEncMiscParameterFrameRate *frameRateParam;
1859 VABufferID miscParamBufferID;
1860
1861 vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
1862 VAEncMiscParameterBufferType,
1863 sizeof(miscEncParamBuf) + sizeof(VAEncMiscParameterFrameRate),
1864 1, NULL, &miscParamBufferID);
1865 CHECK_VA_STATUS_RETURN("vaCreateBuffer");
1866
1867 vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
1868 CHECK_VA_STATUS_RETURN("vaMapBuffer");
1869
1870 miscEncParamBuf->type = VAEncMiscParameterTypeFrameRate;
1871 frameRateParam = (VAEncMiscParameterFrameRate *)miscEncParamBuf->data;
1872 frameRateParam->framerate =
1873 (unsigned int) (mComParams.frameRate.frameRateNum + mComParams.frameRate.frameRateDenom/2)
1874 / mComParams.frameRate.frameRateDenom;
1875
1876 vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
1877 CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
1878
1879 vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
1880 CHECK_VA_STATUS_RETURN("vaRenderPicture");
1881
1882 LOG_I( "frame rate = %d\n", frameRateParam->framerate);
1883 return ENCODE_SUCCESS;
1884 }
1885
renderHrd()1886 Encode_Status VideoEncoderBase::renderHrd() {
1887
1888 VAStatus vaStatus = VA_STATUS_SUCCESS;
1889
1890 VAEncMiscParameterBuffer *miscEncParamBuf;
1891 VAEncMiscParameterHRD *hrdParam;
1892 VABufferID miscParamBufferID;
1893
1894 vaStatus = vaCreateBuffer(mVADisplay, mVAContext,
1895 VAEncMiscParameterBufferType,
1896 sizeof(miscEncParamBuf) + sizeof(VAEncMiscParameterHRD),
1897 1, NULL, &miscParamBufferID);
1898 CHECK_VA_STATUS_RETURN("vaCreateBuffer");
1899
1900 vaStatus = vaMapBuffer(mVADisplay, miscParamBufferID, (void **)&miscEncParamBuf);
1901 CHECK_VA_STATUS_RETURN("vaMapBuffer");
1902
1903 miscEncParamBuf->type = VAEncMiscParameterTypeHRD;
1904 hrdParam = (VAEncMiscParameterHRD *)miscEncParamBuf->data;
1905
1906 hrdParam->buffer_size = mHrdParam.bufferSize;
1907 hrdParam->initial_buffer_fullness = mHrdParam.initBufferFullness;
1908
1909 vaStatus = vaUnmapBuffer(mVADisplay, miscParamBufferID);
1910 CHECK_VA_STATUS_RETURN("vaUnmapBuffer");
1911
1912 vaStatus = vaRenderPicture(mVADisplay, mVAContext, &miscParamBufferID, 1);
1913 CHECK_VA_STATUS_RETURN("vaRenderPicture");
1914
1915 return ENCODE_SUCCESS;
1916 }
1917
findSurfaceMapByValue(intptr_t value)1918 VASurfaceMap *VideoEncoderBase::findSurfaceMapByValue(intptr_t value) {
1919 android::List<VASurfaceMap *>::iterator node;
1920
1921 for(node = mSrcSurfaceMapList.begin(); node != mSrcSurfaceMapList.end(); node++)
1922 {
1923 if ((*node)->getValue() == value)
1924 return *node;
1925 else
1926 continue;
1927 }
1928
1929 return NULL;
1930 }
1931