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
21static const char *AVC_MIME_TYPE = "video/h264";
22
23struct ProfileMap {
24    OMX_VIDEO_AVCPROFILETYPE key;
25    VAProfile value;
26    const char *name;
27};
28
29struct LevelMap {
30    OMX_VIDEO_AVCLEVELTYPE key;
31    uint32_t value;
32    const char *name;
33};
34
35static 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
42static 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
69OMXVideoEncoderAVC::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
117OMXVideoEncoderAVC::~OMXVideoEncoderAVC() {
118    if(mAVCParams) {
119        delete mAVCParams;
120        mAVCParams = NULL;
121    }
122}
123
124OMX_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
195OMX_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
261OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorInit(void) {
262    mCSDOutputted = OMX_FALSE;
263    mInputPictureCount = 0;
264    mFrameEncodedCount = 0;
265    return  OMXVideoEncoderBase::ProcessorInit();
266}
267
268OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorDeinit(void) {
269    return OMXVideoEncoderBase::ProcessorDeinit();
270}
271
272OMX_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
285OMX_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
338OMX_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
436OMX_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
573OMX_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
665OMX_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
680OMX_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
694OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoProfileLevelQuerySupported(OMX_PTR) {
695    LOGW("SetParamVideoAVCProfileLevel is not supported.");
696    return OMX_ErrorUnsupportedSetting;
697}
698
699OMX_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
725OMX_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
784OMX_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
795OMX_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
813OMX_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
831OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormatSupported(OMX_PTR) {
832    LOGW("SetParamNalStreamFormatSupported is not supported.");
833    return OMX_ErrorUnsupportedSetting;
834}
835
836OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormatSelect(OMX_PTR) {
837    LOGW("GetParamNalStreamFormatSelect is not supported.");
838    return OMX_ErrorUnsupportedSetting;
839}
840
841OMX_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
864OMX_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
876OMX_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
930OMX_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
940OMX_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
971OMX_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
981OMX_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
1013OMX_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
1025OMX_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
1039OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoBytestream(OMX_PTR) {
1040    return OMX_ErrorUnsupportedSetting;
1041}
1042
1043OMX_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
1063DECLARE_OMX_COMPONENT("OMX.Intel.VideoEncoder.AVC", "video_encoder.avc", OMXVideoEncoderAVC);
1064