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