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 #define LOG_TAG "OMXVideoEncoderAVC"
18 #include "OMXVideoEncoderAVC.h"
19 #include "IntelMetadataBuffer.h"
20
21 static const char *AVC_MIME_TYPE = "video/h264";
22
23 struct ProfileMap {
24 OMX_VIDEO_AVCPROFILETYPE key;
25 VAProfile value;
26 const char *name;
27 };
28
29 struct LevelMap {
30 OMX_VIDEO_AVCLEVELTYPE key;
31 uint32_t value;
32 const char *name;
33 };
34
35 static ProfileMap ProfileTable[] = {
36 { OMX_VIDEO_AVCProfileBaseline, VAProfileH264Baseline, "AVC Baseline" },
37 { OMX_VIDEO_AVCProfileMain, VAProfileH264Main, "AVC Main" },
38 { OMX_VIDEO_AVCProfileHigh, VAProfileH264High, "AVC High" },
39 { (OMX_VIDEO_AVCPROFILETYPE) 0, (VAProfile) 0, "Not Supported" },
40 };
41
42 static LevelMap LevelTable[] = {
43 { OMX_VIDEO_AVCLevel4, 40, "AVC Level4" },
44 { OMX_VIDEO_AVCLevel41, 41, "AVC Level41" },
45 { OMX_VIDEO_AVCLevel42, 42, "AVC Level42" },
46 { OMX_VIDEO_AVCLevel5, 50, "AVC Level5" },
47 { OMX_VIDEO_AVCLevel51, 51, "AVC Level51" },
48 { (OMX_VIDEO_AVCLEVELTYPE) 0, 0, "Not Supported" },
49 };
50
51 #define FIND_BYKEY(table, x, y) {\
52 for(int ii = 0; ; ii++) { \
53 if (table[ii].key == x || table[ii].key == 0) { \
54 y = ii; \
55 break; \
56 } \
57 } \
58 }\
59
60 #define FIND_BYVALUE(table, x, y) {\
61 for(int ii = 0; ; ii++) { \
62 if (table[ii].value == x || table[ii].value == 0) { \
63 y = ii; \
64 break; \
65 } \
66 } \
67 } \
68
OMXVideoEncoderAVC()69 OMXVideoEncoderAVC::OMXVideoEncoderAVC() {
70 BuildHandlerList();
71 mVideoEncoder = createVideoEncoder(AVC_MIME_TYPE);
72 if (!mVideoEncoder) {
73 LOGE("OMX_ErrorInsufficientResources");
74 return;
75 }
76
77 mAVCParams = new VideoParamsAVC();
78 if (!mAVCParams) {
79 LOGE("OMX_ErrorInsufficientResources");
80 return;
81 }
82
83 //Query supported Profile/Level
84 mPLTableCount = 0;
85
86 VAProfile profiles[MAX_H264_PROFILE] = {VAProfileH264High, VAProfileH264Main, VAProfileH264Baseline};
87
88 VideoParamsProfileLevel pl;
89 for (int i=0; i < MAX_H264_PROFILE; i++) {
90 pl.profile = profiles[i];
91 pl.level = 0;
92 pl.isSupported = false;
93
94 mVideoEncoder->getParameters(&pl);
95 if (pl.isSupported) {
96 uint32_t profile_index;
97 uint32_t level_index;
98
99 FIND_BYVALUE(ProfileTable, pl.profile, profile_index);
100 if (ProfileTable[profile_index].key == (OMX_VIDEO_AVCPROFILETYPE) 0)
101 continue;
102
103 FIND_BYVALUE(LevelTable, pl.level, level_index);
104 if (LevelTable[level_index].key == (OMX_VIDEO_AVCLEVELTYPE) 0)
105 continue;
106
107 mPLTable[mPLTableCount].profile = ProfileTable[profile_index].key;
108 mPLTable[mPLTableCount].level = LevelTable[level_index].key;
109 mPLTableCount ++;
110 LOGV("Support Profile:%s, Level:%s\n", ProfileTable[profile_index].name, LevelTable[level_index].name);
111 }
112 }
113
114 mEmptyEOSBuf = OMX_FALSE;
115 }
116
~OMXVideoEncoderAVC()117 OMXVideoEncoderAVC::~OMXVideoEncoderAVC() {
118 if(mAVCParams) {
119 delete mAVCParams;
120 mAVCParams = NULL;
121 }
122 }
123
InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE * paramPortDefinitionOutput)124 OMX_ERRORTYPE OMXVideoEncoderAVC::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput) {
125 // OMX_VIDEO_PARAM_AVCTYPE
126 memset(&mParamAvc, 0, sizeof(mParamAvc));
127 SetTypeHeader(&mParamAvc, sizeof(mParamAvc));
128 mParamAvc.nPortIndex = OUTPORT_INDEX;
129
130 if (mPLTableCount > 0) {
131 mParamAvc.eProfile = (OMX_VIDEO_AVCPROFILETYPE) mPLTable[0].profile;
132 mParamAvc.eLevel = (OMX_VIDEO_AVCLEVELTYPE)mPLTable[0].level;
133 } else {
134 LOGE("No supported profile/level\n");
135 return OMX_ErrorUndefined;
136 }
137 mParamAvc.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
138 mParamAvc.nPFrames = 29;
139 mParamAvc.nBFrames = 0;
140
141 // OMX_NALSTREAMFORMATTYPE
142 memset(&mNalStreamFormat, 0, sizeof(mNalStreamFormat));
143 SetTypeHeader(&mNalStreamFormat, sizeof(mNalStreamFormat));
144 mNalStreamFormat.nPortIndex = OUTPORT_INDEX;
145 // TODO: check if this is desired Nalu Format
146 //mNalStreamFormat.eNaluFormat = OMX_NaluFormatLengthPrefixedSeparateFirstHeader;
147 // OMX_VIDEO_CONFIG_AVCINTRAPERIOD
148 memset(&mConfigAvcIntraPeriod, 0, sizeof(mConfigAvcIntraPeriod));
149 SetTypeHeader(&mConfigAvcIntraPeriod, sizeof(mConfigAvcIntraPeriod));
150 mConfigAvcIntraPeriod.nPortIndex = OUTPORT_INDEX;
151 // TODO: need to be populated from Video Encoder
152 mConfigAvcIntraPeriod.nIDRPeriod = 1;
153 mConfigAvcIntraPeriod.nPFrames = 29;
154
155 // OMX_VIDEO_CONFIG_NALSIZE
156 memset(&mConfigNalSize, 0, sizeof(mConfigNalSize));
157 SetTypeHeader(&mConfigNalSize, sizeof(mConfigNalSize));
158 mConfigNalSize.nPortIndex = OUTPORT_INDEX;
159 mConfigNalSize.nNaluBytes = 0;
160
161 // OMX_VIDEO_PARAM_INTEL_AVCVUI
162 memset(&mParamIntelAvcVui, 0, sizeof(mParamIntelAvcVui));
163 SetTypeHeader(&mParamIntelAvcVui, sizeof(mParamIntelAvcVui));
164 mParamIntelAvcVui.nPortIndex = OUTPORT_INDEX;
165 mParamIntelAvcVui.bVuiGeneration = OMX_FALSE;
166
167 // OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS
168 memset(&mConfigIntelSliceNumbers, 0, sizeof(mConfigIntelSliceNumbers));
169 SetTypeHeader(&mConfigIntelSliceNumbers, sizeof(mConfigIntelSliceNumbers));
170 mConfigIntelSliceNumbers.nPortIndex = OUTPORT_INDEX;
171 mConfigIntelSliceNumbers.nISliceNumber = 1;
172 mConfigIntelSliceNumbers.nPSliceNumber = 1;
173
174 // Override OMX_PARAM_PORTDEFINITIONTYPE
175 paramPortDefinitionOutput->nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT;
176 paramPortDefinitionOutput->nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
177 paramPortDefinitionOutput->nBufferSize = OUTPORT_BUFFER_SIZE;
178 paramPortDefinitionOutput->format.video.cMIMEType = (OMX_STRING)AVC_MIME_TYPE;
179 paramPortDefinitionOutput->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
180
181 // Override OMX_VIDEO_PARAM_PROFILELEVELTYPE
182 // TODO: check if profile/level supported is correct
183 mParamProfileLevel.eProfile = mParamAvc.eProfile;
184 mParamProfileLevel.eLevel = mParamAvc.eLevel;
185
186 // Override OMX_VIDEO_PARAM_BITRATETYPE
187 mParamBitrate.nTargetBitrate = 192000;
188
189 // Override OMX_VIDEO_CONFIG_INTEL_BITRATETYPE
190 mConfigIntelBitrate.nInitialQP = 0; // Initial QP for I frames
191
192 return OMX_ErrorNone;
193 }
194
SetVideoEncoderParam(void)195 OMX_ERRORTYPE OMXVideoEncoderAVC::SetVideoEncoderParam(void) {
196
197 Encode_Status ret = ENCODE_SUCCESS;
198 LOGV("OMXVideoEncoderAVC::SetVideoEncoderParam");
199
200 if (!mEncoderParams) {
201 LOGE("NULL pointer: mEncoderParams");
202 return OMX_ErrorBadParameter;
203 }
204
205 mVideoEncoder->getParameters(mEncoderParams);
206 uint32_t index;
207 FIND_BYKEY(ProfileTable, mParamAvc.eProfile, index);
208 if (ProfileTable[index].value != 0)
209 mEncoderParams->profile = ProfileTable[index].value;
210
211 if (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeB)
212 mEncoderParams->intraPeriod = mParamAvc.nPFrames + mParamAvc.nBFrames;
213 else
214 mEncoderParams->intraPeriod = mParamAvc.nPFrames + 1;
215
216 // 0 - all luma and chroma block edges of the slice are filtered
217 // 1 - deblocking is disabled for all block edges of the slice
218 // 2 - all luma and chroma block edges of the slice are filtered
219 // with exception of the block edges that coincide with slice boundaries
220 mEncoderParams->disableDeblocking = 0;
221
222 OMXVideoEncoderBase::SetVideoEncoderParam();
223
224 mVideoEncoder->getParameters(mAVCParams);
225 if(mParamIntelAvcVui.bVuiGeneration == OMX_TRUE) {
226 mAVCParams->VUIFlag = 1;
227 }
228 // For resolution below VGA, single core can hit the performance target and provide VQ gain
229 if (mEncoderParams->resolution.width <= 640 && mEncoderParams->resolution.height <= 480) {
230 mConfigIntelSliceNumbers.nISliceNumber = 1;
231 mConfigIntelSliceNumbers.nPSliceNumber = 1;
232 }
233 mAVCParams->sliceNum.iSliceNum = mConfigIntelSliceNumbers.nISliceNumber;
234 mAVCParams->sliceNum.pSliceNum = mConfigIntelSliceNumbers.nPSliceNumber;
235 mAVCParams->maxSliceSize = mConfigNalSize.nNaluBytes * 8;
236
237 if (mEncoderParams->intraPeriod == 0) {
238 mAVCParams->idrInterval = 0;
239 mAVCParams->ipPeriod = 1;
240 } else {
241 mAVCParams->idrInterval = mConfigAvcIntraPeriod.nIDRPeriod; //idrinterval
242 if (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeB)
243 mAVCParams->ipPeriod = mEncoderParams->intraPeriod / mParamAvc.nPFrames;
244 else
245 mAVCParams->ipPeriod = 1;
246 }
247
248 ret = mVideoEncoder ->setParameters(mAVCParams);
249 CHECK_ENCODE_STATUS("setParameters");
250
251 LOGV("VUIFlag = %d\n", mAVCParams->VUIFlag);
252 LOGV("sliceNum.iSliceNum = %d\n", mAVCParams->sliceNum.iSliceNum);
253 LOGV("sliceNum.pSliceNum = %d\n", mAVCParams->sliceNum.pSliceNum);
254 LOGV("maxSliceSize = %d\n ", mAVCParams->maxSliceSize);
255 LOGV("intraPeriod = %d\n ", mEncoderParams->intraPeriod);
256 LOGV("idrInterval = %d\n ", mAVCParams->idrInterval);
257 LOGV("ipPeriod = %d\n ", mAVCParams->ipPeriod);
258 return OMX_ErrorNone;
259 }
260
ProcessorInit(void)261 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorInit(void) {
262 mCSDOutputted = OMX_FALSE;
263 mInputPictureCount = 0;
264 mFrameEncodedCount = 0;
265 return OMXVideoEncoderBase::ProcessorInit();
266 }
267
ProcessorDeinit(void)268 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorDeinit(void) {
269 return OMXVideoEncoderBase::ProcessorDeinit();
270 }
271
ProcessorStop(void)272 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorStop(void) {
273 OMX_BUFFERHEADERTYPE *omxbuf = NULL;
274
275 while(!mBFrameList.empty()) {
276 omxbuf = * mBFrameList.begin();
277 this->ports[INPORT_INDEX]->ReturnThisBuffer(omxbuf);
278 mBFrameList.erase(mBFrameList.begin());
279 }
280
281 mEmptyEOSBuf = OMX_FALSE;
282 return OMXVideoEncoderBase::ProcessorStop();
283 }
284
ProcessorPreEmptyBuffer(OMX_BUFFERHEADERTYPE * buffer)285 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorPreEmptyBuffer(OMX_BUFFERHEADERTYPE* buffer) {
286 OMX_U32 EncodeInfo = 0;
287 OMX_U32 EncodeFrameType = 0;
288
289 uint32_t poc = 0;
290 uint32_t idrPeriod = mAVCParams->idrInterval;
291 uint32_t IntraPeriod = mEncoderParams->intraPeriod;
292 uint32_t IpPeriod = mAVCParams->ipPeriod;
293 bool BFrameEnabled = IpPeriod > 1;
294 uint32_t GOP = 0;
295
296 if (idrPeriod == 0 || IntraPeriod == 0) {
297 GOP = 0xFFFFFFFF;
298 if (IntraPeriod == 0)
299 IntraPeriod = 0xFFFFFFFF;
300 } else if (BFrameEnabled)
301 GOP = IntraPeriod*idrPeriod + 1;
302 else
303 GOP = IntraPeriod*idrPeriod;
304
305 LOGV("ProcessorPreEmptyBuffer idrPeriod=%d, IntraPeriod=%d, IpPeriod=%d, BFrameEnabled=%d\n", idrPeriod, IntraPeriod, IpPeriod, BFrameEnabled);
306
307 //decide frame type, refer Merrifield Video Encoder Driver HLD Chapter 3.17
308 poc = mInputPictureCount % GOP;
309
310 if (poc == 0 /*IDR*/) {
311 EncodeFrameType = F_IDR;
312 } else if (IntraPeriod == 1) {
313 EncodeFrameType = F_I;
314 }else if ((poc > IpPeriod) && ((poc - IpPeriod) % IntraPeriod == 0))/*I*/{
315 EncodeFrameType = F_I;
316 if (BFrameEnabled)
317 SET_CO(EncodeInfo, CACHE_POP);
318 } else if ((poc % IpPeriod == 0) /*P*/ || (buffer->nFlags & OMX_BUFFERFLAG_EOS)/*EOS,always P*/) {
319 EncodeFrameType = F_P;
320 if (BFrameEnabled)
321 SET_CO(EncodeInfo, CACHE_POP);
322 } else { /*B*/
323 EncodeFrameType = F_B;
324 SET_CO(EncodeInfo, CACHE_PUSH);
325 }
326
327 SET_FT(EncodeInfo, EncodeFrameType);
328 SET_FC(EncodeInfo, mInputPictureCount);
329
330 buffer->pPlatformPrivate = (OMX_PTR) EncodeInfo;
331
332 LOGV("ProcessorPreEmptyBuffer Frame %d, Type %s, EncodeInfo %x\n", mInputPictureCount, FrameTypeStr[EncodeFrameType], EncodeInfo);
333
334 mInputPictureCount ++;
335 return OMX_ErrorNone;
336 }
337
ProcessCacheOperation(OMX_BUFFERHEADERTYPE ** buffers)338 OMX_BOOL OMXVideoEncoderAVC::ProcessCacheOperation(OMX_BUFFERHEADERTYPE **buffers) {
339
340 OMX_BOOL Cached = OMX_FALSE;
341
342 //get frame encode info
343 Encode_Info eInfo;
344 uint32_t encodeInfo = (uint32_t) buffers[INPORT_INDEX]->pPlatformPrivate;
345 eInfo.FrameType = GET_FT(encodeInfo);
346
347 eInfo.CacheOperation = GET_CO(encodeInfo);
348 eInfo.NotStopFrame = encodeInfo & ENC_NSTOP;
349 eInfo.FrameCount = GET_FC(encodeInfo);
350
351 LOGV("ProcessCacheOperation Frame %d, type:%s, CacheOps:%s, NoSTOP=%d, EOS=%d\n",
352 eInfo.FrameCount, FrameTypeStr[eInfo.FrameType], CacheOperationStr[eInfo.CacheOperation],
353 eInfo.NotStopFrame, buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS);
354
355 OMX_BOOL emptyEOSBuf = OMX_FALSE;
356 if (buffers[INPORT_INDEX]->nFilledLen == 0 && buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS) {
357 //meet an empty EOS buffer
358 emptyEOSBuf = OMX_TRUE;
359 LOGV("ProcessCacheOperation: This frame is Empty EOS buffer\n");
360 }
361
362 if (eInfo.CacheOperation == CACHE_NONE) {
363 //nothing to do
364 } else if (eInfo.CacheOperation == CACHE_PUSH) {
365 mBFrameList.push_front(buffers[INPORT_INDEX]);
366 Cached = OMX_TRUE;
367 LOGV("ProcessCacheOperation: This B frame is cached\n");
368
369 } else if (eInfo.CacheOperation == CACHE_POP) {
370 eInfo.NotStopFrame = true; //it is also a nstop frame
371
372 OMX_BUFFERHEADERTYPE *omxbuf = NULL;
373 uint32_t i = 0;
374 uint32_t bframecount = mBFrameList.size();
375
376 LOGV("BFrameList size = %d\n", bframecount);
377
378 while(!mBFrameList.empty()) {
379 /*TODO: need to handle null data buffer with EOS
380 !NULL EOS case: B1 B2 P(EOS) -> P B1 B2(EOS)
381 NULL EOS case: B1 B2 NULL(EOS) -> B2 B1 NULL(EOS)
382 */
383
384 if (emptyEOSBuf) {
385 omxbuf = *mBFrameList.begin();
386 ports[INPORT_INDEX]->PushThisBuffer(omxbuf);
387 mBFrameList.erase(mBFrameList.begin()); //clear it from internal queue
388
389 } else {
390 omxbuf = *mBFrameList.begin();
391
392 if (buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS && i == 0 ) {
393 //this is final encode frame, mark it is new EOS and remove original EOS
394 omxbuf->nFlags |= OMX_BUFFERFLAG_EOS;
395 buffers[INPORT_INDEX]->nFlags &= ~OMX_BUFFERFLAG_EOS;
396 } else {
397 //all these frames except final B frame in miniGOP can't be stopped at any time
398 //to avoid not breaking miniGOP integrity
399 if (i > 0) {
400 uint32_t tmp = (uint32_t) omxbuf->pPlatformPrivate;
401 tmp |= ENC_NSTOP;
402 omxbuf->pPlatformPrivate = (OMX_PTR) tmp;
403 }
404 }
405 ports[INPORT_INDEX]->RetainThisBuffer(omxbuf, false); //push bufferq head
406
407 mBFrameList.erase(mBFrameList.begin()); //clear it from internal queue
408 }
409
410 i++;
411 }
412
413 if (emptyEOSBuf)
414 ports[INPORT_INDEX]->PushThisBuffer(buffers[INPORT_INDEX]); //put it at the tail
415
416 } else if (eInfo.CacheOperation == CACHE_RESET) {
417 // mBFrameList.clear();
418 }
419
420 eInfo.CacheOperation = CACHE_NONE;
421
422 /* restore all states into input OMX buffer
423 */
424 if (eInfo.NotStopFrame)
425 encodeInfo |= ENC_NSTOP;
426 else
427 encodeInfo &= ~ENC_NSTOP;
428
429 SET_CO(encodeInfo, eInfo.CacheOperation);
430 buffers[INPORT_INDEX]->pPlatformPrivate = (OMX_PTR) encodeInfo;
431
432 LOGV("ProcessCacheOperation Completed return %d\n", Cached);
433 return Cached;
434 }
435
ProcessDataRetrieve(OMX_BUFFERHEADERTYPE ** buffers,OMX_BOOL * outBufReturned)436 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessDataRetrieve(
437 OMX_BUFFERHEADERTYPE **buffers, OMX_BOOL *outBufReturned) {
438
439 OMX_NALUFORMATSTYPE NaluFormat = mNalStreamFormat.eNaluFormat;
440
441 // NaluFormat not set, setting default
442 if (NaluFormat == 0) {
443 NaluFormat = (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader;
444 mNalStreamFormat.eNaluFormat = NaluFormat;
445 }
446
447 VideoEncOutputBuffer outBuf;
448 outBuf.data = buffers[OUTPORT_INDEX]->pBuffer;
449 outBuf.bufferSize = buffers[OUTPORT_INDEX]->nAllocLen;
450 outBuf.dataSize = 0;
451 outBuf.remainingSize = 0;
452 outBuf.flag = 0;
453 outBuf.timeStamp = 0;
454 outBuf.offset = 0;
455
456 switch (NaluFormat) {
457 case OMX_NaluFormatStartCodes:
458 outBuf.format = OUTPUT_EVERYTHING;
459 break;
460
461 case OMX_NaluFormatOneNaluPerBuffer:
462 outBuf.format = OUTPUT_ONE_NAL;
463 break;
464
465 default:
466 if (NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader||
467 NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatLengthPrefixedSeparateFirstHeader){
468 if(!mCSDOutputted) {
469 LOGV("Output codec data for first frame\n");
470 outBuf.format = OUTPUT_CODEC_DATA;
471 } else {
472 if (NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader)
473 outBuf.format = OUTPUT_EVERYTHING;
474 else
475 outBuf.format = OUTPUT_NALULENGTHS_PREFIXED;
476 }
477 break;
478 } else {
479 return OMX_ErrorUndefined;
480 }
481 }
482
483 //start getOutput
484 Encode_Status ret = mVideoEncoder->getOutput(&outBuf, FUNC_NONBLOCK);
485
486 if (ret < ENCODE_SUCCESS) {
487 LOGE("libMIX getOutput Failed. ret = 0x%08x\n", ret);
488 outBuf.dataSize = 0;
489 outBuf.flag |= ENCODE_BUFFERFLAG_ENDOFFRAME;
490 if (ret == ENCODE_NO_REQUEST_DATA) {
491 if (mEmptyEOSBuf) {
492 //make sure no data encoding in HW, then emit one empty out buffer with EOS
493 outBuf.flag |= ENCODE_BUFFERFLAG_ENDOFSTREAM;
494 LOGV("no more data encoding, will signal empty EOS output buf\n");
495 } else {
496 //if not meet Empty EOS buffer, shouldn't get this error
497 LOGE("sever error, should not happend here\n");
498 //return OMX_ErrorUndefined; //not return error here to avoid omxcodec crash
499 }
500 }
501
502 } else if (ret == ENCODE_BUFFER_TOO_SMALL) {
503 LOGE("output buffer too small\n");
504 // Return code could not be ENCODE_BUFFER_TOO_SMALL, or we will have dead lock issue
505 return OMX_ErrorUndefined;
506 } else if (ret == ENCODE_DATA_NOT_READY) {
507 LOGV("Call libMIX getOutput againe due to 'data not ready'\n");
508 ret = mVideoEncoder->getOutput(&outBuf);
509 }
510
511 LOGV("libMIX getOutput data size= %d, flag=0x%08x", outBuf.dataSize, outBuf.flag);
512 OMX_U32 outfilledlen = outBuf.dataSize;
513 OMX_U32 outoffset = outBuf.offset;
514 OMX_S64 outtimestamp = outBuf.timeStamp;
515 OMX_U32 outflags = 0;
516
517 //if codecconfig
518 if (outBuf.flag & ENCODE_BUFFERFLAG_CODECCONFIG)
519 outflags |= OMX_BUFFERFLAG_CODECCONFIG;
520
521 //if syncframe
522 if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME)
523 outflags |= OMX_BUFFERFLAG_SYNCFRAME;
524
525 //if eos
526 if (outBuf.flag & ENCODE_BUFFERFLAG_ENDOFSTREAM)
527 outflags |= OMX_BUFFERFLAG_EOS;
528
529 //if full encoded data retrieved
530 if(outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) {
531 LOGV("got a complete libmix Frame\n");
532 outflags |= OMX_BUFFERFLAG_ENDOFFRAME;
533
534 if ((NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader
535 || NaluFormat == (OMX_NALUFORMATSTYPE)OMX_NaluFormatLengthPrefixedSeparateFirstHeader )
536 && !mCSDOutputted && outfilledlen > 0) {
537 mCSDOutputted = OMX_TRUE;
538
539 } else {
540 ports[INPORT_INDEX]->ReturnOneRetainedBuffer(); //return one retained frame from head
541 mFrameOutputCount ++;
542 }
543 }
544
545 if (outfilledlen == 0) {
546 if (mEmptyEOSBuf) {
547 //emit empty EOS out buf since meet empty EOS input buf
548 buffers[OUTPORT_INDEX]->nFilledLen = 0;
549 buffers[OUTPORT_INDEX]->nTimeStamp = 0;
550 buffers[OUTPORT_INDEX]->nFlags = outflags;
551 *outBufReturned = OMX_TRUE;
552 LOGV("emit one empty EOS OMX output buf = %p:%d, flag = 0x%08x, ts=%lld", buffers[OUTPORT_INDEX]->pBuffer, outfilledlen, outflags, outtimestamp);
553 } else
554 //not emit out buf since something wrong
555 *outBufReturned = OMX_FALSE;
556
557 } else {
558 buffers[OUTPORT_INDEX]->nOffset = outoffset;
559 buffers[OUTPORT_INDEX]->nFilledLen = outfilledlen;
560 buffers[OUTPORT_INDEX]->nTimeStamp = outtimestamp;
561 buffers[OUTPORT_INDEX]->nFlags = outflags;
562 if (outBuf.flag & ENCODE_BUFFERFLAG_NSTOPFRAME)
563 buffers[OUTPORT_INDEX]->pPlatformPrivate = (OMX_PTR) 0x00000001; //indicate it is nstop frame
564 *outBufReturned = OMX_TRUE;
565 LOGV("emit one OMX output buf = %p:%d, flag = 0x%08x, ts=%lld", buffers[OUTPORT_INDEX]->pBuffer, outfilledlen, outflags, outtimestamp);
566
567 }
568
569 LOGV("ProcessDataRetrieve OK, mFrameEncodedCount=%d , mFrameOutputCount=%d\n", mFrameEncodedCount, mFrameOutputCount);
570 return OMX_ErrorNone;
571 }
572
ProcessorProcess(OMX_BUFFERHEADERTYPE ** buffers,buffer_retain_t * retains,OMX_U32)573 OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorProcess(
574 OMX_BUFFERHEADERTYPE **buffers,
575 buffer_retain_t *retains,
576 OMX_U32) {
577
578 OMX_ERRORTYPE oret = OMX_ErrorNone;
579 Encode_Status ret = ENCODE_SUCCESS;
580
581 bool FrameEncoded = false;
582
583 if (buffers[INPORT_INDEX]) {
584 LOGV("input buffer has new frame\n");
585
586 //get frame encode info
587 Encode_Info eInfo;
588 uint32_t encodeInfo = (uint32_t) buffers[INPORT_INDEX]->pPlatformPrivate;
589 eInfo.FrameType = GET_FT(encodeInfo);
590 eInfo.CacheOperation = GET_CO(encodeInfo);
591 eInfo.NotStopFrame = encodeInfo & ENC_NSTOP;
592 eInfo.FrameCount = GET_FC(encodeInfo);
593
594 //handle frame cache operation
595 if (ProcessCacheOperation(buffers)) {
596 //frame is cached, nothing should be done in this case, just store status and return
597 retains[INPORT_INDEX] = BUFFER_RETAIN_CACHE;
598 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
599 return OMX_ErrorNone;
600 }
601
602 //try encode if frame is not cached
603 VideoEncRawBuffer inBuf;
604
605 inBuf.data = buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset;
606 inBuf.size = buffers[INPORT_INDEX]->nFilledLen;
607 inBuf.flag = 0;
608 inBuf.timeStamp = buffers[INPORT_INDEX]->nTimeStamp;
609
610 if (inBuf.size == 0 && buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS) {
611 //meet an empty EOS buffer, retain it directly and return from here
612 retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE;
613 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
614 mEmptyEOSBuf = OMX_TRUE;
615 return OMX_ErrorNone;
616 }
617
618 if (buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS)
619 inBuf.flag |= ENCODE_BUFFERFLAG_ENDOFSTREAM;
620 if (eInfo.NotStopFrame)
621 inBuf.flag |= ENCODE_BUFFERFLAG_NSTOPFRAME;
622 inBuf.type = (FrameType) eInfo.FrameType;
623
624 LOGV("start libmix encoding\n");
625 // encode and setConfig need to be thread safe
626 pthread_mutex_lock(&mSerializationLock);
627 ret = mVideoEncoder->encode(&inBuf, FUNC_NONBLOCK);
628 pthread_mutex_unlock(&mSerializationLock);
629 LOGV("end libmix encoding\n");
630
631 retains[INPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
632 if (ret == ENCODE_DEVICE_BUSY) {
633 //encoder is busy, put buf back and come again
634 LOGV("encoder is busy, push buffer back to get again\n");
635 retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
636 } else {
637 //if error, this buf will be returned
638 CHECK_ENCODE_STATUS("encode");
639
640 LOGV("put buffer to encoder and retain this buffer\n");
641 mFrameEncodedCount ++;
642 FrameEncoded = true;
643 retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE;
644 }
645
646 } else {
647 //no new coming frames, but maybe still have frames not outputted
648 LOGV("input buffer is null\n");
649 }
650
651 retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN; //set to default value
652 //just call getoutput if no frame encoded in this cycle to avoid retained buffer queue wrong state
653 if (!FrameEncoded) {
654 OMX_BOOL OutBufReturned = OMX_FALSE;
655 oret = ProcessDataRetrieve(buffers, &OutBufReturned);
656 if (OutBufReturned)
657 retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
658 }
659
660 LOGV("ProcessorProcess ret=%x", oret);
661 return oret;
662
663 }
664
BuildHandlerList(void)665 OMX_ERRORTYPE OMXVideoEncoderAVC::BuildHandlerList(void) {
666 OMXVideoEncoderBase::BuildHandlerList();
667 AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc);
668 AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormat, GetParamNalStreamFormat, SetParamNalStreamFormat);
669 AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSupported, GetParamNalStreamFormatSupported, SetParamNalStreamFormatSupported);
670 AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, GetParamNalStreamFormatSelect, SetParamNalStreamFormatSelect);
671 AddHandler(OMX_IndexConfigVideoAVCIntraPeriod, GetConfigVideoAVCIntraPeriod, SetConfigVideoAVCIntraPeriod);
672 AddHandler(OMX_IndexConfigVideoNalSize, GetConfigVideoNalSize, SetConfigVideoNalSize);
673 AddHandler((OMX_INDEXTYPE)OMX_IndexConfigIntelSliceNumbers, GetConfigIntelSliceNumbers, SetConfigIntelSliceNumbers);
674 AddHandler((OMX_INDEXTYPE)OMX_IndexParamIntelAVCVUI, GetParamIntelAVCVUI, SetParamIntelAVCVUI);
675 AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoBytestream, GetParamVideoBytestream, SetParamVideoBytestream);
676 AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoProfileLevelQuerySupported, GetParamVideoProfileLevelQuerySupported, SetParamVideoProfileLevelQuerySupported);
677 return OMX_ErrorNone;
678 }
679
GetParamVideoProfileLevelQuerySupported(OMX_PTR pStructure)680 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoProfileLevelQuerySupported(OMX_PTR pStructure) {
681 OMX_ERRORTYPE ret;
682 OMX_VIDEO_PARAM_PROFILELEVELTYPE *p = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pStructure;
683 CHECK_TYPE_HEADER(p);
684 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
685
686 CHECK_ENUMERATION_RANGE(p->nProfileIndex,mPLTableCount);
687
688 p->eProfile = mPLTable[p->nProfileIndex].profile;
689 p->eLevel = mPLTable[p->nProfileIndex].level;
690
691 return OMX_ErrorNone;
692 }
693
SetParamVideoProfileLevelQuerySupported(OMX_PTR)694 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoProfileLevelQuerySupported(OMX_PTR) {
695 LOGW("SetParamVideoAVCProfileLevel is not supported.");
696 return OMX_ErrorUnsupportedSetting;
697 }
698
GetParamVideoAvc(OMX_PTR pStructure)699 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoAvc(OMX_PTR pStructure) {
700 OMX_ERRORTYPE ret;
701 OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
702 CHECK_TYPE_HEADER(p);
703 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
704
705 mVideoEncoder->getParameters(mAVCParams);
706 if(mParamAvc.eProfile == OMX_VIDEO_AVCProfileHigh)
707 {
708 mAVCParams->bEntropyCodingCABAC = 1;
709 mAVCParams->bDirect8x8Inference = 1;
710 }
711 mParamAvc.bEntropyCodingCABAC = (OMX_BOOL)mAVCParams->bEntropyCodingCABAC;
712 mParamAvc.bWeightedPPrediction = (OMX_BOOL)mAVCParams->bWeightedPPrediction;
713 mParamAvc.nRefIdx10ActiveMinus1 = mAVCParams->refIdx10ActiveMinus1;
714 mParamAvc.nRefIdx11ActiveMinus1 = mAVCParams->refIdx11ActiveMinus1;
715 mParamAvc.nWeightedBipredicitonMode = mAVCParams->weightedBipredicitonMode;
716 mParamAvc.bDirect8x8Inference = (OMX_BOOL)mAVCParams->bDirect8x8Inference;
717 mParamAvc.bDirectSpatialTemporal = (OMX_BOOL)mAVCParams->bDirectSpatialTemporal;
718 mParamAvc.nCabacInitIdc = mAVCParams->cabacInitIdc;
719 mParamAvc.bFrameMBsOnly = (OMX_BOOL)mAVCParams->bFrameMBsOnly;
720 mParamAvc.bconstIpred = (OMX_BOOL)mAVCParams->bConstIpred;
721 memcpy(p, &mParamAvc, sizeof(*p));
722 return OMX_ErrorNone;
723 }
724
SetParamVideoAvc(OMX_PTR pStructure)725 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoAvc(OMX_PTR pStructure) {
726 OMX_ERRORTYPE ret;
727 OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
728 CHECK_TYPE_HEADER(p);
729 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
730 CHECK_SET_PARAM_STATE();
731
732 //Check if parameters are valid
733
734 if(p->bEnableASO == OMX_TRUE)
735 return OMX_ErrorUnsupportedSetting;
736
737 if(p->bEnableFMO == OMX_TRUE)
738 return OMX_ErrorUnsupportedSetting;
739
740 if(p->bEnableUEP == OMX_TRUE)
741 return OMX_ErrorUnsupportedSetting;
742
743 if(p->bEnableRS == OMX_TRUE)
744 return OMX_ErrorUnsupportedSetting;
745
746 if (p->eProfile == OMX_VIDEO_AVCProfileBaseline &&
747 (p->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) )
748 return OMX_ErrorBadParameter;
749
750 if (p->nAllowedPictureTypes & OMX_VIDEO_PictureTypeP && (p->nPFrames == 0))
751 return OMX_ErrorBadParameter;
752
753 if (p->nAllowedPictureTypes & OMX_VIDEO_PictureTypeB ) {
754 if (p->nBFrames == 0)
755 return OMX_ErrorBadParameter;
756
757 //IpPeriod must be integer
758 uint32_t IntraPeriod = mParamAvc.nPFrames + mParamAvc.nBFrames ;
759 if (IntraPeriod % mParamAvc.nPFrames != 0)
760 return OMX_ErrorBadParameter;
761
762 //IntraPeriod must be multipe of IpPeriod.
763 uint32_t IpPeriod = IntraPeriod /mParamAvc.nPFrames;
764 if (IntraPeriod % IpPeriod != 0)
765 return OMX_ErrorBadParameter;
766 }
767
768 // TODO: do we need to check if port is enabled?
769 // TODO: see SetPortAvcParam implementation - Can we make simple copy????
770 memcpy(&mParamAvc, p, sizeof(mParamAvc));
771 mVideoEncoder->getParameters(mAVCParams);
772 mAVCParams->bEntropyCodingCABAC = mParamAvc.bEntropyCodingCABAC;
773 mAVCParams->bDirect8x8Inference = mParamAvc.bDirect8x8Inference;
774 if(mParamAvc.eProfile == OMX_VIDEO_AVCProfileBaseline){
775 mAVCParams->bEntropyCodingCABAC = 0;
776 mAVCParams->bDirect8x8Inference = 0;
777 }
778 mVideoEncoder->setParameters(mAVCParams);
779
780
781 return OMX_ErrorNone;
782 }
783
GetParamNalStreamFormat(OMX_PTR pStructure)784 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormat(OMX_PTR pStructure) {
785 OMX_ERRORTYPE ret;
786 OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure;
787
788 CHECK_TYPE_HEADER(p);
789 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
790 // TODO: check if this is desired format
791 p->eNaluFormat = mNalStreamFormat.eNaluFormat; //OMX_NaluFormatStartCodes;
792 return OMX_ErrorNone;
793 }
794
SetParamNalStreamFormat(OMX_PTR pStructure)795 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormat(OMX_PTR pStructure) {
796 OMX_ERRORTYPE ret;
797 OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure;
798
799 CHECK_TYPE_HEADER(p);
800 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
801 LOGV("p->eNaluFormat =%d\n",p->eNaluFormat);
802 if(p->eNaluFormat != OMX_NaluFormatStartCodes &&
803 p->eNaluFormat != (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader &&
804 p->eNaluFormat != OMX_NaluFormatOneNaluPerBuffer &&
805 p->eNaluFormat != (OMX_NALUFORMATSTYPE)OMX_NaluFormatLengthPrefixedSeparateFirstHeader) {
806 LOGE("Format not support\n");
807 return OMX_ErrorUnsupportedSetting;
808 }
809 mNalStreamFormat.eNaluFormat = p->eNaluFormat;
810 return OMX_ErrorNone;
811 }
812
GetParamNalStreamFormatSupported(OMX_PTR pStructure)813 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormatSupported(OMX_PTR pStructure) {
814 OMX_ERRORTYPE ret;
815 OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure;
816
817 CHECK_TYPE_HEADER(p);
818 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
819 p->eNaluFormat = (OMX_NALUFORMATSTYPE)
820 (OMX_NaluFormatStartCodes |
821 OMX_NaluFormatStartCodesSeparateFirstHeader |
822 OMX_NaluFormatOneNaluPerBuffer|
823 OMX_NaluFormatLengthPrefixedSeparateFirstHeader);
824
825 // TODO: check if this is desired format
826 // OMX_NaluFormatFourByteInterleaveLength |
827 // OMX_NaluFormatZeroByteInterleaveLength);
828 return OMX_ErrorNone;
829 }
830
SetParamNalStreamFormatSupported(OMX_PTR)831 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormatSupported(OMX_PTR) {
832 LOGW("SetParamNalStreamFormatSupported is not supported.");
833 return OMX_ErrorUnsupportedSetting;
834 }
835
GetParamNalStreamFormatSelect(OMX_PTR)836 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormatSelect(OMX_PTR) {
837 LOGW("GetParamNalStreamFormatSelect is not supported.");
838 return OMX_ErrorUnsupportedSetting;
839 }
840
SetParamNalStreamFormatSelect(OMX_PTR pStructure)841 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormatSelect(OMX_PTR pStructure) {
842 OMX_ERRORTYPE ret;
843 OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure;
844 CHECK_TYPE_HEADER(p);
845 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
846
847 // return OMX_ErrorIncorrectStateOperation if not in Loaded state
848 CHECK_SET_PARAM_STATE();
849
850 if (p->eNaluFormat != OMX_NaluFormatStartCodes &&
851 p->eNaluFormat != (OMX_NALUFORMATSTYPE)OMX_NaluFormatStartCodesSeparateFirstHeader &&
852 p->eNaluFormat != OMX_NaluFormatOneNaluPerBuffer&&
853 p->eNaluFormat != (OMX_NALUFORMATSTYPE)OMX_NaluFormatLengthPrefixedSeparateFirstHeader) {
854 //p->eNaluFormat != OMX_NaluFormatFourByteInterleaveLength &&
855 //p->eNaluFormat != OMX_NaluFormatZeroByteInterleaveLength) {
856 // TODO: check if this is desried
857 return OMX_ErrorBadParameter;
858 }
859
860 mNalStreamFormat = *p;
861 return OMX_ErrorNone;
862 }
863
GetConfigVideoAVCIntraPeriod(OMX_PTR pStructure)864 OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigVideoAVCIntraPeriod(OMX_PTR pStructure) {
865 OMX_ERRORTYPE ret;
866 OMX_VIDEO_CONFIG_AVCINTRAPERIOD *p = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pStructure;
867
868 CHECK_TYPE_HEADER(p);
869 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
870 // TODO: populate mConfigAvcIntraPeriod from VideoEncoder
871 // return OMX_ErrorNotReady if VideoEncoder is not created.
872 memcpy(p, &mConfigAvcIntraPeriod, sizeof(*p));
873 return OMX_ErrorNone;
874 }
875
SetConfigVideoAVCIntraPeriod(OMX_PTR pStructure)876 OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigVideoAVCIntraPeriod(OMX_PTR pStructure) {
877 OMX_ERRORTYPE ret;
878 Encode_Status retStatus = ENCODE_SUCCESS;
879 OMX_VIDEO_CONFIG_AVCINTRAPERIOD *p = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pStructure;
880 CHECK_TYPE_HEADER(p);
881 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
882
883 // return OMX_ErrorNone if not in Executing state
884 // TODO: return OMX_ErrorIncorrectStateOperation?
885 CHECK_SET_CONFIG_STATE();
886
887 //check if parameters are valid
888 if ( ( (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeP) ||
889 (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) ) &&
890 p->nPFrames == 0 )
891 return OMX_ErrorBadParameter;
892
893 // TODO: apply AVC Intra Period configuration in Executing state
894 VideoConfigAVCIntraPeriod avcIntraPreriod;
895
896 if (mParamAvc.nAllowedPictureTypes & OMX_VIDEO_PictureTypeB) {
897 avcIntraPreriod.intraPeriod = p->nPFrames;
898 if (p->nPFrames % mParamAvc.nBFrames != 0)
899 return OMX_ErrorBadParameter;
900 avcIntraPreriod.ipPeriod = p->nPFrames / mParamAvc.nBFrames;
901
902 if (avcIntraPreriod.intraPeriod % avcIntraPreriod.ipPeriod != 0)
903 return OMX_ErrorBadParameter;
904
905 avcIntraPreriod.idrInterval = p->nIDRPeriod;
906 } else {
907 avcIntraPreriod.intraPeriod = p->nPFrames + 1;
908 avcIntraPreriod.ipPeriod = 1;
909 if (avcIntraPreriod.intraPeriod == 0)
910 avcIntraPreriod.idrInterval = 0;
911 else
912 avcIntraPreriod.idrInterval = p->nIDRPeriod;
913 }
914
915 retStatus = mVideoEncoder->setConfig(&avcIntraPreriod);
916 if(retStatus != ENCODE_SUCCESS) {
917 LOGW("set avc intra period config failed");
918 }
919
920 mEncoderParams->intraPeriod = avcIntraPreriod.intraPeriod;
921 mAVCParams->idrInterval = avcIntraPreriod.idrInterval;
922 mAVCParams->ipPeriod = avcIntraPreriod.ipPeriod;
923
924 mConfigAvcIntraPeriod = *p;
925 mConfigAvcIntraPeriod.nIDRPeriod = avcIntraPreriod.idrInterval;
926
927 return OMX_ErrorNone;
928 }
929
GetConfigVideoNalSize(OMX_PTR pStructure)930 OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigVideoNalSize(OMX_PTR pStructure) {
931 OMX_ERRORTYPE ret;
932 OMX_VIDEO_CONFIG_NALSIZE *p = (OMX_VIDEO_CONFIG_NALSIZE *)pStructure;
933
934 CHECK_TYPE_HEADER(p);
935 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
936 memcpy(p, &mConfigNalSize, sizeof(*p));
937 return OMX_ErrorNone;
938 }
939
SetConfigVideoNalSize(OMX_PTR pStructure)940 OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigVideoNalSize(OMX_PTR pStructure) {
941 OMX_ERRORTYPE ret;
942 Encode_Status retStatus = ENCODE_SUCCESS;
943 if (mParamBitrate.eControlRate == OMX_Video_ControlRateMax) {
944 LOGE("SetConfigVideoNalSize failed. Feature is disabled.");
945 return OMX_ErrorUnsupportedIndex;
946 }
947 OMX_VIDEO_CONFIG_NALSIZE *p = (OMX_VIDEO_CONFIG_NALSIZE *)pStructure;
948 CHECK_TYPE_HEADER(p);
949 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
950
951 // set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig)
952 mConfigNalSize = *p;
953
954 // return OMX_ErrorNone if not in Executing state
955 // TODO: return OMX_ErrorIncorrectStateOperation?
956 CHECK_SET_CONFIG_STATE();
957
958 if (mParamBitrate.eControlRate != (OMX_VIDEO_CONTROLRATETYPE)OMX_Video_Intel_ControlRateVideoConferencingMode) {
959 LOGE("SetConfigVideoNalSize failed. Feature is supported only in VCM.");
960 return OMX_ErrorUnsupportedSetting;
961 }
962 VideoConfigNALSize configNalSize;
963 configNalSize.maxSliceSize = mConfigNalSize.nNaluBytes * 8;
964 retStatus = mVideoEncoder->setConfig(&configNalSize);
965 if(retStatus != ENCODE_SUCCESS) {
966 LOGW("set NAL size config failed");
967 }
968 return OMX_ErrorNone;
969 }
970
GetConfigIntelSliceNumbers(OMX_PTR pStructure)971 OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigIntelSliceNumbers(OMX_PTR pStructure) {
972 OMX_ERRORTYPE ret;
973 OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *p = (OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *)pStructure;
974
975 CHECK_TYPE_HEADER(p);
976 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
977 memcpy(p, &mConfigIntelSliceNumbers, sizeof(*p));
978 return OMX_ErrorNone;
979 }
980
SetConfigIntelSliceNumbers(OMX_PTR pStructure)981 OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigIntelSliceNumbers(OMX_PTR pStructure) {
982 OMX_ERRORTYPE ret;
983 Encode_Status retStatus = ENCODE_SUCCESS;
984 if (mParamBitrate.eControlRate == OMX_Video_ControlRateMax) {
985 LOGE("SetConfigIntelSliceNumbers failed. Feature is disabled.");
986 return OMX_ErrorUnsupportedIndex;
987 }
988 OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *p = (OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *)pStructure;
989 CHECK_TYPE_HEADER(p);
990 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
991
992 // set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig)
993 mConfigIntelSliceNumbers = *p;
994
995 // return OMX_ErrorNone if not in Executing state
996 // TODO: return OMX_ErrorIncorrectStateOperation?
997 CHECK_SET_CONFIG_STATE();
998
999 if (mParamBitrate.eControlRate != (OMX_VIDEO_CONTROLRATETYPE)OMX_Video_Intel_ControlRateVideoConferencingMode) {
1000 LOGE("SetConfigIntelSliceNumbers failed. Feature is supported only in VCM.");
1001 return OMX_ErrorUnsupportedSetting;
1002 }
1003 VideoConfigSliceNum sliceNum;
1004 sliceNum.sliceNum.iSliceNum = mConfigIntelSliceNumbers.nISliceNumber;
1005 sliceNum.sliceNum.pSliceNum = mConfigIntelSliceNumbers.nPSliceNumber;
1006 retStatus = mVideoEncoder->setConfig(&sliceNum);
1007 if(retStatus != ENCODE_SUCCESS) {
1008 LOGW("set silce num config failed!\n");
1009 }
1010 return OMX_ErrorNone;
1011 }
1012
GetParamIntelAVCVUI(OMX_PTR pStructure)1013 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamIntelAVCVUI(OMX_PTR pStructure) {
1014
1015 OMX_ERRORTYPE ret;
1016 OMX_VIDEO_PARAM_INTEL_AVCVUI *p = (OMX_VIDEO_PARAM_INTEL_AVCVUI *)pStructure;
1017
1018 CHECK_TYPE_HEADER(p);
1019 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
1020 memcpy(p, &mParamIntelAvcVui, sizeof(*p));
1021
1022 return OMX_ErrorNone;
1023 }
1024
SetParamIntelAVCVUI(OMX_PTR pStructure)1025 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamIntelAVCVUI(OMX_PTR pStructure) {
1026
1027 OMX_ERRORTYPE ret;
1028 OMX_VIDEO_PARAM_INTEL_AVCVUI *p = (OMX_VIDEO_PARAM_INTEL_AVCVUI *)pStructure;
1029 CHECK_TYPE_HEADER(p);
1030 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
1031
1032 // set only in Loaded state (ComponentSetParam)
1033 CHECK_SET_PARAM_STATE();
1034
1035 mParamIntelAvcVui = *p;
1036 return OMX_ErrorNone;
1037 }
1038
GetParamVideoBytestream(OMX_PTR)1039 OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoBytestream(OMX_PTR) {
1040 return OMX_ErrorUnsupportedSetting;
1041 }
1042
SetParamVideoBytestream(OMX_PTR pStructure)1043 OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoBytestream(OMX_PTR pStructure) {
1044 OMX_ERRORTYPE ret;
1045 OMX_VIDEO_PARAM_BYTESTREAMTYPE *p = (OMX_VIDEO_PARAM_BYTESTREAMTYPE *)pStructure;
1046 CHECK_TYPE_HEADER(p);
1047 CHECK_PORT_INDEX(p, OUTPORT_INDEX);
1048
1049 // set only in Loaded state (ComponentSetParam)
1050 CHECK_SET_PARAM_STATE();
1051
1052 if (p->bBytestream == OMX_TRUE) {
1053 mNalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes;
1054 } else {
1055 // TODO: do we need to override the Nalu format?
1056 mNalStreamFormat.eNaluFormat = (OMX_NALUFORMATSTYPE)OMX_NaluFormatZeroByteInterleaveLength;
1057 }
1058
1059 return OMX_ErrorNone;
1060 }
1061
1062
1063 DECLARE_OMX_COMPONENT("OMX.Intel.VideoEncoder.AVC", "video_encoder.avc", OMXVideoEncoderAVC);
1064