OMXVideoEncoderAVC.cpp revision 80114224b110cdd1707292e6283e970e08b513f0
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
18//#define LOG_NDEBUG 0
19#define LOG_TAG "OMXVideoEncoderAVC"
20#include <utils/Log.h>
21#include "OMXVideoEncoderAVC.h"
22
23static const char *AVC_MIME_TYPE = "video/h264";
24
25OMXVideoEncoderAVC::OMXVideoEncoderAVC() {
26    BuildHandlerList();
27    mVideoEncoder = createVideoEncoder(AVC_MIME_TYPE);
28    if (!mVideoEncoder) LOGE("OMX_ErrorInsufficientResources");
29
30    mAVCParams = new VideoParamsAVC();
31    if (!mAVCParams) LOGE("OMX_ErrorInsufficientResources");
32}
33
34OMXVideoEncoderAVC::~OMXVideoEncoderAVC() {
35    if(mAVCParams) {
36        delete mAVCParams;
37        mAVCParams = NULL;
38    }
39}
40
41OMX_ERRORTYPE OMXVideoEncoderAVC::InitOutputPortFormatSpecific(OMX_PARAM_PORTDEFINITIONTYPE *paramPortDefinitionOutput) {
42    // OMX_VIDEO_PARAM_AVCTYPE
43    memset(&mParamAvc, 0, sizeof(mParamAvc));
44    SetTypeHeader(&mParamAvc, sizeof(mParamAvc));
45    mParamAvc.nPortIndex = OUTPORT_INDEX;
46    mParamAvc.eProfile = OMX_VIDEO_AVCProfileBaseline;
47    mParamAvc.eLevel = OMX_VIDEO_AVCLevel1;
48
49    // OMX_NALSTREAMFORMATTYPE
50    memset(&mNalStreamFormat, 0, sizeof(mNalStreamFormat));
51    SetTypeHeader(&mNalStreamFormat, sizeof(mNalStreamFormat));
52    mNalStreamFormat.nPortIndex = OUTPORT_INDEX;
53    // TODO: check if this is desired Nalu Format
54    // mNalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodesSeparateFirstHeader;
55    mNalStreamFormat.eNaluFormat = OMX_NaluFormatLengthPrefixedSeparateFirstHeader;
56    // OMX_VIDEO_CONFIG_AVCINTRAPERIOD
57    memset(&mConfigAvcIntraPeriod, 0, sizeof(mConfigAvcIntraPeriod));
58    SetTypeHeader(&mConfigAvcIntraPeriod, sizeof(mConfigAvcIntraPeriod));
59    mConfigAvcIntraPeriod.nPortIndex = OUTPORT_INDEX;
60    // TODO: need to be populated from Video Encoder
61    mConfigAvcIntraPeriod.nIDRPeriod = 1;
62    mConfigAvcIntraPeriod.nPFrames = 0;
63
64    // OMX_VIDEO_CONFIG_NALSIZE
65    memset(&mConfigNalSize, 0, sizeof(mConfigNalSize));
66    SetTypeHeader(&mConfigNalSize, sizeof(mConfigNalSize));
67    mConfigNalSize.nPortIndex = OUTPORT_INDEX;
68    mConfigNalSize.nNaluBytes = 0;
69
70    // OMX_VIDEO_PARAM_INTEL_AVCVUI
71    memset(&mParamIntelAvcVui, 0, sizeof(mParamIntelAvcVui));
72    SetTypeHeader(&mParamIntelAvcVui, sizeof(mParamIntelAvcVui));
73    mParamIntelAvcVui.nPortIndex = OUTPORT_INDEX;
74    mParamIntelAvcVui.bVuiGeneration = OMX_FALSE;
75
76    // OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS
77    memset(&mConfigIntelSliceNumbers, 0, sizeof(mConfigIntelSliceNumbers));
78    SetTypeHeader(&mConfigIntelSliceNumbers, sizeof(mConfigIntelSliceNumbers));
79    mConfigIntelSliceNumbers.nPortIndex = OUTPORT_INDEX;
80    mConfigIntelSliceNumbers.nISliceNumber = 2;
81    mConfigIntelSliceNumbers.nPSliceNumber = 2;
82
83    // Override OMX_PARAM_PORTDEFINITIONTYPE
84    paramPortDefinitionOutput->nBufferCountActual = OUTPORT_ACTUAL_BUFFER_COUNT;
85    paramPortDefinitionOutput->nBufferCountMin = OUTPORT_MIN_BUFFER_COUNT;
86    paramPortDefinitionOutput->nBufferSize = OUTPORT_BUFFER_SIZE;
87    paramPortDefinitionOutput->format.video.cMIMEType = (OMX_STRING)AVC_MIME_TYPE;
88    paramPortDefinitionOutput->format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
89
90    // Override OMX_VIDEO_PARAM_PROFILELEVELTYPE
91    // TODO: check if profile/level supported is correct
92    mParamProfileLevel.eProfile = mParamAvc.eProfile;
93    mParamProfileLevel.eLevel = mParamAvc.eLevel;
94
95    // Override OMX_VIDEO_PARAM_BITRATETYPE
96    mParamBitrate.nTargetBitrate = 192000;
97
98    // Override OMX_VIDEO_CONFIG_INTEL_BITRATETYPE
99    mConfigIntelBitrate.nInitialQP = 24;  // Initial QP for I frames
100
101    return OMX_ErrorNone;
102}
103
104OMX_ERRORTYPE OMXVideoEncoderAVC::SetVideoEncoderParam(void) {
105
106    Encode_Status ret = ENCODE_SUCCESS;
107    LOGV("OMXVideoEncoderAVC::SetVideoEncoderParam");
108
109    if (!mEncoderParams) {
110        LOGE("NULL pointer: mEncoderParams");
111        return OMX_ErrorBadParameter;
112    }
113
114    mVideoEncoder->getParameters(mEncoderParams);
115    mEncoderParams->profile = (VAProfile)VAProfileH264Baseline;
116    OMXVideoEncoderBase::SetVideoEncoderParam();
117
118    mVideoEncoder->getParameters(mAVCParams);
119    if(mParamIntelAvcVui.bVuiGeneration == OMX_TRUE) {
120        mAVCParams->VUIFlag = 1;
121    }
122    mAVCParams->sliceNum.iSliceNum = mConfigIntelSliceNumbers.nISliceNumber;
123    mAVCParams->sliceNum.pSliceNum = mConfigIntelSliceNumbers.nPSliceNumber;
124    mAVCParams->idrInterval = mConfigAvcIntraPeriod.nIDRPeriod;
125    mAVCParams->maxSliceSize = mConfigNalSize.nNaluBytes * 8;
126    ret = mVideoEncoder ->setParameters(mAVCParams);
127    CHECK_ENCODE_STATUS("setParameters");
128
129    LOGV("VUIFlag = %d\n", mAVCParams->VUIFlag);
130    LOGV("sliceNum.iSliceNum = %d\n", mAVCParams->sliceNum.iSliceNum);
131    LOGV("sliceNum.pSliceNum = %d\n", mAVCParams->sliceNum.pSliceNum);
132    LOGV("idrInterval = %d\n ", mAVCParams->idrInterval);
133    LOGV("maxSliceSize = %d\n ", mAVCParams->maxSliceSize);
134    return OMX_ErrorNone;
135}
136
137OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorInit(void) {
138    mFirstFrame = OMX_TRUE;
139    return  OMXVideoEncoderBase::ProcessorInit();
140}
141
142OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorDeinit(void) {
143    return OMXVideoEncoderBase::ProcessorDeinit();
144}
145
146OMX_ERRORTYPE OMXVideoEncoderAVC::ProcessorProcess(
147    OMX_BUFFERHEADERTYPE **buffers,
148    buffer_retain_t *retains,
149    OMX_U32 numberBuffers) {
150
151    OMX_U32 outfilledlen = 0;
152    OMX_S64 outtimestamp = 0;
153    OMX_U32 outflags = 0;
154
155    OMX_ERRORTYPE oret = OMX_ErrorNone;
156    Encode_Status ret = ENCODE_SUCCESS;
157
158    VideoEncOutputBuffer outBuf;
159    VideoEncRawBuffer inBuf;
160
161    LOGV_IF(buffers[INPORT_INDEX]->nFlags & OMX_BUFFERFLAG_EOS,
162            "%s(),%d: got OMX_BUFFERFLAG_EOS\n", __func__, __LINE__);
163
164    if (!buffers[INPORT_INDEX]->nFilledLen) {
165        LOGE("%s(),%d: input buffer's nFilledLen is zero\n",  __func__, __LINE__);
166        goto out;
167    }
168
169    if (mBsState != BS_STATE_INVALID) {
170        LOGV(" Share buffer mode\n");
171        inBuf.size = mSharedBufArray[0].dataSize;
172        inBuf.data =
173            *(reinterpret_cast<uint8_t **>(buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset));
174    } else {
175        inBuf.data = buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset;
176        inBuf.size = buffers[INPORT_INDEX]->nFilledLen;
177    }
178
179    LOGV("inBuf.data=%x, size=%d",(unsigned)inBuf.data, inBuf.size);
180
181    outBuf.data = buffers[OUTPORT_INDEX]->pBuffer + buffers[OUTPORT_INDEX]->nOffset;
182    outBuf.dataSize = 0;
183    outBuf.bufferSize = buffers[OUTPORT_INDEX]->nAllocLen - buffers[OUTPORT_INDEX]->nOffset;
184
185    if(inBuf.size<=0) {
186        LOGE("The Input buf size is 0\n");
187        return OMX_ErrorBadParameter;
188    }
189
190    LOGV("in buffer = 0x%x ts = %lld",
191         buffers[INPORT_INDEX]->pBuffer + buffers[INPORT_INDEX]->nOffset,
192         buffers[INPORT_INDEX]->nTimeStamp);
193
194    if(mFrameRetrieved) {
195        // encode and setConfig need to be thread safe
196        pthread_mutex_lock(&mSerializationLock);
197        ret = mVideoEncoder->encode(&inBuf);
198        pthread_mutex_unlock(&mSerializationLock);
199        CHECK_ENCODE_STATUS("encode");
200        mFrameRetrieved = OMX_FALSE;
201
202        // This is for buffer contention, we won't release current buffer
203        // but the last input buffer
204        ports[INPORT_INDEX]->ReturnAllRetainedBuffers();
205    }
206
207    switch (mNalStreamFormat.eNaluFormat) {
208        case OMX_NaluFormatStartCodes:
209
210            outBuf.format = OUTPUT_EVERYTHING;
211            ret = mVideoEncoder->getOutput(&outBuf);
212            CHECK_ENCODE_STATUS("encode");
213
214            LOGV("output data size = %d", outBuf.dataSize);
215            outfilledlen = outBuf.dataSize;
216            outtimestamp = buffers[INPORT_INDEX]->nTimeStamp;
217
218
219            if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) {
220                outflags |= OMX_BUFFERFLAG_SYNCFRAME;
221            }
222
223            if(outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) {
224                outflags |= OMX_BUFFERFLAG_ENDOFFRAME;
225                mFrameRetrieved = OMX_TRUE;
226                retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE;
227
228            } else {
229                retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;  //get again
230
231            }
232
233            if (outfilledlen > 0) {
234                retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
235            } else {
236                retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
237            }
238
239            break;
240        case OMX_NaluFormatOneNaluPerBuffer:
241
242            outBuf.format = OUTPUT_ONE_NAL;
243            ret = mVideoEncoder->getOutput(&outBuf);
244            CHECK_ENCODE_STATUS("getOutput");
245            // Return code could not be ENCODE_BUFFER_TOO_SMALL
246            // If we don't return error, we will have dead lock issue
247            if (ret == ENCODE_BUFFER_TOO_SMALL) {
248                return OMX_ErrorUndefined;
249            }
250
251            LOGV("output codec data size = %d", outBuf.dataSize);
252
253            outfilledlen = outBuf.dataSize;
254            outtimestamp = buffers[INPORT_INDEX]->nTimeStamp;
255
256            if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) {
257                outflags |= OMX_BUFFERFLAG_SYNCFRAME;
258            }
259
260            if(outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) {
261                outflags |= OMX_BUFFERFLAG_ENDOFFRAME;
262                mFrameRetrieved = OMX_TRUE;
263                retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE;
264
265            } else {
266                retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;  //get again
267            }
268
269            if (outfilledlen > 0) {
270                retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
271            } else {
272                retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
273            }
274
275            break;
276        case OMX_NaluFormatStartCodesSeparateFirstHeader:
277
278            if(mFirstFrame) {
279                LOGV("mFirstFrame\n");
280                outBuf.format = OUTPUT_CODEC_DATA;
281                ret = mVideoEncoder->getOutput(&outBuf);
282                CHECK_ENCODE_STATUS("getOutput");
283                // Return code could not be ENCODE_BUFFER_TOO_SMALL
284                // If we don't return error, we will have dead lock issue
285                if (ret == ENCODE_BUFFER_TOO_SMALL) {
286                    return OMX_ErrorUndefined;
287                }
288
289                LOGV("output codec data size = %d", outBuf.dataSize);
290
291                outflags |= OMX_BUFFERFLAG_CODECCONFIG;
292                outflags |= OMX_BUFFERFLAG_ENDOFFRAME;
293                outflags |= OMX_BUFFERFLAG_SYNCFRAME;
294
295                // This input buffer need to be gotten again
296                retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
297                outfilledlen = outBuf.dataSize;
298                mFirstFrame = OMX_FALSE;
299            } else {
300                outBuf.format = OUTPUT_EVERYTHING;
301                mVideoEncoder->getOutput(&outBuf);
302                CHECK_ENCODE_STATUS("getOutput");
303
304                LOGV("output data size = %d", outBuf.dataSize);
305
306                outfilledlen = outBuf.dataSize;
307                outtimestamp = buffers[INPORT_INDEX]->nTimeStamp;
308
309                if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) {
310                    outflags |= OMX_BUFFERFLAG_SYNCFRAME;
311                }
312                if(outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) {
313                    LOGV("Get buffer done\n");
314                    outflags |= OMX_BUFFERFLAG_ENDOFFRAME;
315                    mFrameRetrieved = OMX_TRUE;
316                    retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE;
317
318                } else {
319                    retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;  //get again
320
321                }
322            }
323
324            if (outfilledlen > 0) {
325                retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
326            } else {
327                retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
328            }
329            break;
330	case OMX_NaluFormatLengthPrefixedSeparateFirstHeader:
331
332            if(mFirstFrame) {
333                LOGV("mFirstFrame\n");
334                outBuf.format = OUTPUT_CODEC_DATA;
335                ret = mVideoEncoder->getOutput(&outBuf);
336                CHECK_ENCODE_STATUS("getOutput");
337                // Return code could not be ENCODE_BUFFER_TOO_SMALL
338                // If we don't return error, we will have dead lock issue
339                if (ret == ENCODE_BUFFER_TOO_SMALL) {
340                    return OMX_ErrorUndefined;
341                }
342
343                LOGV("output codec data size = %d", outBuf.dataSize);
344
345                outflags |= OMX_BUFFERFLAG_CODECCONFIG;
346                outflags |= OMX_BUFFERFLAG_ENDOFFRAME;
347                outflags |= OMX_BUFFERFLAG_SYNCFRAME;
348
349                // This input buffer need to be gotten again
350                retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
351                outfilledlen = outBuf.dataSize;
352                mFirstFrame = OMX_FALSE;
353            } else {
354                outBuf.format = OUTPUT_LENGTH_PREFIXED;
355                mVideoEncoder->getOutput(&outBuf);
356                CHECK_ENCODE_STATUS("getOutput");
357
358                LOGV("output data size = %d", outBuf.dataSize);
359
360                outfilledlen = outBuf.dataSize;
361                outtimestamp = buffers[INPORT_INDEX]->nTimeStamp;
362
363                if (outBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) {
364                    outflags |= OMX_BUFFERFLAG_SYNCFRAME;
365                }
366                if(outBuf.flag & ENCODE_BUFFERFLAG_ENDOFFRAME) {
367                    LOGV("Get buffer done\n");
368                    outflags |= OMX_BUFFERFLAG_ENDOFFRAME;
369                    mFrameRetrieved = OMX_TRUE;
370                    retains[INPORT_INDEX] = BUFFER_RETAIN_ACCUMULATE;
371
372                } else {
373                    retains[INPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;  //get again
374                }
375            }
376
377            if (outfilledlen > 0) {
378                retains[OUTPORT_INDEX] = BUFFER_RETAIN_NOT_RETAIN;
379            } else {
380                retains[OUTPORT_INDEX] = BUFFER_RETAIN_GETAGAIN;
381            }
382	    break;
383    }
384
385out:
386    LOGV("output buffers = %p:%d, flag = %x", buffers[OUTPORT_INDEX]->pBuffer, outfilledlen, outflags);
387
388    if(retains[OUTPORT_INDEX] != BUFFER_RETAIN_GETAGAIN) {
389        buffers[OUTPORT_INDEX]->nFilledLen = outfilledlen;
390        buffers[OUTPORT_INDEX]->nTimeStamp = outtimestamp;
391        buffers[OUTPORT_INDEX]->nFlags = outflags;
392    }
393
394    if (retains[INPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN ||
395            retains[INPORT_INDEX] == BUFFER_RETAIN_ACCUMULATE ) {
396        mFrameInputCount ++;
397    }
398
399    if (retains[OUTPORT_INDEX] == BUFFER_RETAIN_NOT_RETAIN) mFrameOutputCount  ++;
400
401#if 0
402    if (avcEncParamIntelBitrateType.eControlRate != OMX_Video_Intel_ControlRateVideoConferencingMode) {
403        if (oret == (OMX_ERRORTYPE) OMX_ErrorIntelExtSliceSizeOverflow) {
404            oret = OMX_ErrorNone;
405        }
406    }
407#endif
408    LOGV_IF(oret == OMX_ErrorNone, "%s(),%d: exit, encode is done\n", __func__, __LINE__);
409
410    return oret;
411
412}
413
414OMX_ERRORTYPE OMXVideoEncoderAVC::BuildHandlerList(void) {
415    OMXVideoEncoderBase::BuildHandlerList();
416    AddHandler(OMX_IndexParamVideoAvc, GetParamVideoAvc, SetParamVideoAvc);
417    AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormat, GetParamNalStreamFormat, SetParamNalStreamFormat);
418    AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSupported, GetParamNalStreamFormatSupported, SetParamNalStreamFormatSupported);
419    AddHandler((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, GetParamNalStreamFormatSelect, SetParamNalStreamFormatSelect);
420    AddHandler(OMX_IndexConfigVideoAVCIntraPeriod, GetConfigVideoAVCIntraPeriod, SetConfigVideoAVCIntraPeriod);
421    AddHandler(OMX_IndexConfigVideoNalSize, GetConfigVideoNalSize, SetConfigVideoNalSize);
422    AddHandler((OMX_INDEXTYPE)OMX_IndexConfigIntelSliceNumbers, GetConfigIntelSliceNumbers, SetConfigIntelSliceNumbers);
423    AddHandler((OMX_INDEXTYPE)OMX_IndexParamIntelAVCVUI, GetParamIntelAVCVUI, SetParamIntelAVCVUI);
424    AddHandler((OMX_INDEXTYPE)OMX_IndexParamVideoBytestream, GetParamVideoBytestream, SetParamVideoBytestream);
425    return OMX_ErrorNone;
426}
427
428OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoAvc(OMX_PTR pStructure) {
429    OMX_ERRORTYPE ret;
430    OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
431    CHECK_TYPE_HEADER(p);
432    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
433
434    memcpy(p, &mParamAvc, sizeof(*p));
435    return OMX_ErrorNone;
436}
437
438OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoAvc(OMX_PTR pStructure) {
439    OMX_ERRORTYPE ret;
440    OMX_VIDEO_PARAM_AVCTYPE *p = (OMX_VIDEO_PARAM_AVCTYPE *)pStructure;
441    CHECK_TYPE_HEADER(p);
442    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
443    CHECK_SET_PARAM_STATE();
444
445    // TODO: do we need to check if port is enabled?
446    // TODO: see SetPortAvcParam implementation - Can we make simple copy????
447    memcpy(&mParamAvc, p, sizeof(mParamAvc));
448    return OMX_ErrorNone;
449}
450
451OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormat(OMX_PTR pStructure) {
452    OMX_ERRORTYPE ret;
453    OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure;
454
455    CHECK_TYPE_HEADER(p);
456    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
457    // TODO: check if this is desired format
458    p->eNaluFormat = mNalStreamFormat.eNaluFormat; //OMX_NaluFormatStartCodes;
459    return OMX_ErrorNone;
460}
461
462OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormat(OMX_PTR pStructure) {
463    OMX_ERRORTYPE ret;
464    OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure;
465
466    CHECK_TYPE_HEADER(p);
467    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
468
469    LOGV("p->eNaluFormat =%d\n",p->eNaluFormat);
470    if(p->eNaluFormat != OMX_NaluFormatStartCodes &&
471            p->eNaluFormat != OMX_NaluFormatStartCodesSeparateFirstHeader &&
472            p->eNaluFormat != OMX_NaluFormatOneNaluPerBuffer &&
473            p->eNaluFormat != OMX_NaluFormatLengthPrefixedSeparateFirstHeader) {
474        LOGE("Format not support\n");
475        return OMX_ErrorUnsupportedSetting;
476    }
477    mNalStreamFormat.eNaluFormat = p->eNaluFormat;
478    return OMX_ErrorNone;
479}
480
481OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormatSupported(OMX_PTR pStructure) {
482    OMX_ERRORTYPE ret;
483    OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure;
484
485    CHECK_TYPE_HEADER(p);
486    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
487    p->eNaluFormat = (OMX_NALUFORMATSTYPE)
488                     (OMX_NaluFormatStartCodes |
489                      OMX_NaluFormatStartCodesSeparateFirstHeader |
490                      OMX_NaluFormatOneNaluPerBuffer|
491                      OMX_NaluFormatLengthPrefixedSeparateFirstHeader);
492
493    // TODO: check if this is desired format
494    // OMX_NaluFormatFourByteInterleaveLength |
495    // OMX_NaluFormatZeroByteInterleaveLength);
496    return OMX_ErrorNone;
497}
498
499OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormatSupported(OMX_PTR pStructure) {
500    LOGW("SetParamNalStreamFormatSupported is not supported.");
501    return OMX_ErrorUnsupportedSetting;
502}
503
504OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamNalStreamFormatSelect(OMX_PTR pStructure) {
505    LOGW("GetParamNalStreamFormatSelect is not supported.");
506    return OMX_ErrorUnsupportedSetting;
507}
508
509OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamNalStreamFormatSelect(OMX_PTR pStructure) {
510    OMX_ERRORTYPE ret;
511    OMX_NALSTREAMFORMATTYPE *p = (OMX_NALSTREAMFORMATTYPE *)pStructure;
512    CHECK_TYPE_HEADER(p);
513    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
514
515    // return OMX_ErrorIncorrectStateOperation if not in Loaded state
516    CHECK_SET_PARAM_STATE();
517
518    if (p->eNaluFormat != OMX_NaluFormatStartCodes &&
519            p->eNaluFormat != OMX_NaluFormatStartCodesSeparateFirstHeader &&
520            p->eNaluFormat != OMX_NaluFormatOneNaluPerBuffer&&
521            p->eNaluFormat != OMX_NaluFormatLengthPrefixedSeparateFirstHeader) {
522        //p->eNaluFormat != OMX_NaluFormatFourByteInterleaveLength &&
523        //p->eNaluFormat != OMX_NaluFormatZeroByteInterleaveLength) {
524        // TODO: check if this is desried
525        return OMX_ErrorBadParameter;
526    }
527
528    mNalStreamFormat = *p;
529    return OMX_ErrorNone;
530}
531
532OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigVideoAVCIntraPeriod(OMX_PTR pStructure) {
533    OMX_ERRORTYPE ret;
534    OMX_VIDEO_CONFIG_AVCINTRAPERIOD *p = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pStructure;
535
536    CHECK_TYPE_HEADER(p);
537    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
538    // TODO: populate mConfigAvcIntraPeriod from VideoEncoder
539    // return OMX_ErrorNotReady if VideoEncoder is not created.
540    memcpy(p, &mConfigAvcIntraPeriod, sizeof(*p));
541    return OMX_ErrorNone;
542}
543
544OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigVideoAVCIntraPeriod(OMX_PTR pStructure) {
545    OMX_ERRORTYPE ret;
546    Encode_Status retStatus = ENCODE_SUCCESS;
547    OMX_VIDEO_CONFIG_AVCINTRAPERIOD *p = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pStructure;
548    CHECK_TYPE_HEADER(p);
549    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
550
551    // set in either Loaded state (ComponentSetParam) or Executing state (ComponentSetConfig)
552    mConfigAvcIntraPeriod = *p;
553
554    // return OMX_ErrorNone if not in Executing state
555    // TODO:  return OMX_ErrorIncorrectStateOperation?
556    CHECK_SET_CONFIG_STATE();
557
558    // TODO: apply AVC Intra Period configuration in Executing state
559    VideoConfigAVCIntraPeriod avcIntraPreriod;
560    avcIntraPreriod.idrInterval = mConfigAvcIntraPeriod.nIDRPeriod;
561    avcIntraPreriod.intraPeriod = mConfigAvcIntraPeriod.nPFrames;
562    retStatus = mVideoEncoder->setConfig(&avcIntraPreriod);
563    if(retStatus !=  ENCODE_SUCCESS) {
564        LOGW("set avc intra prerod config failed");
565    }
566    return OMX_ErrorNone;
567}
568
569OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigVideoNalSize(OMX_PTR pStructure) {
570    OMX_ERRORTYPE ret;
571    OMX_VIDEO_CONFIG_NALSIZE *p = (OMX_VIDEO_CONFIG_NALSIZE *)pStructure;
572
573    CHECK_TYPE_HEADER(p);
574    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
575    memcpy(p, &mConfigNalSize, sizeof(*p));
576    return OMX_ErrorNone;
577}
578
579OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigVideoNalSize(OMX_PTR pStructure) {
580    OMX_ERRORTYPE ret;
581    Encode_Status retStatus = ENCODE_SUCCESS;
582    if (mParamIntelBitrate.eControlRate == OMX_Video_Intel_ControlRateMax) {
583        LOGE("SetConfigVideoNalSize failed. Feature is disabled.");
584        return OMX_ErrorUnsupportedIndex;
585    }
586    OMX_VIDEO_CONFIG_NALSIZE *p = (OMX_VIDEO_CONFIG_NALSIZE *)pStructure;
587    CHECK_TYPE_HEADER(p);
588    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
589
590    // set in either Loaded  state (ComponentSetParam) or Executing state (ComponentSetConfig)
591    mConfigNalSize = *p;
592
593    // return OMX_ErrorNone if not in Executing state
594    // TODO: return OMX_ErrorIncorrectStateOperation?
595    CHECK_SET_CONFIG_STATE();
596
597    if (mParamIntelBitrate.eControlRate != OMX_Video_Intel_ControlRateVideoConferencingMode) {
598        LOGE("SetConfigVideoNalSize failed. Feature is supported only in VCM.");
599        return OMX_ErrorUnsupportedSetting;
600    }
601    VideoConfigNALSize configNalSize;
602    configNalSize.maxSliceSize = mConfigNalSize.nNaluBytes * 8;
603    retStatus = mVideoEncoder->setConfig(&configNalSize);
604    if(retStatus != ENCODE_SUCCESS) {
605        LOGW("set NAL size config failed");
606    }
607    return OMX_ErrorNone;
608}
609
610OMX_ERRORTYPE OMXVideoEncoderAVC::GetConfigIntelSliceNumbers(OMX_PTR pStructure) {
611    OMX_ERRORTYPE ret;
612    OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *p = (OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *)pStructure;
613
614    CHECK_TYPE_HEADER(p);
615    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
616    memcpy(p, &mConfigIntelSliceNumbers, sizeof(*p));
617    return OMX_ErrorNone;
618}
619
620OMX_ERRORTYPE OMXVideoEncoderAVC::SetConfigIntelSliceNumbers(OMX_PTR pStructure) {
621    OMX_ERRORTYPE ret;
622    Encode_Status retStatus = ENCODE_SUCCESS;
623    if (mParamIntelBitrate.eControlRate == OMX_Video_Intel_ControlRateMax) {
624        LOGE("SetConfigIntelSliceNumbers failed. Feature is disabled.");
625        return OMX_ErrorUnsupportedIndex;
626    }
627    OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *p = (OMX_VIDEO_CONFIG_INTEL_SLICE_NUMBERS *)pStructure;
628    CHECK_TYPE_HEADER(p);
629    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
630
631    // set in either Loaded  state (ComponentSetParam) or Executing state (ComponentSetConfig)
632    mConfigIntelSliceNumbers = *p;
633
634    // return OMX_ErrorNone if not in Executing state
635    // TODO: return OMX_ErrorIncorrectStateOperation?
636    CHECK_SET_CONFIG_STATE();
637
638    if (mParamIntelBitrate.eControlRate != OMX_Video_Intel_ControlRateVideoConferencingMode) {
639        LOGE("SetConfigIntelSliceNumbers failed. Feature is supported only in VCM.");
640        return OMX_ErrorUnsupportedSetting;
641    }
642    VideoConfigSliceNum sliceNum;
643    sliceNum.sliceNum.iSliceNum = mConfigIntelSliceNumbers.nISliceNumber;
644    sliceNum.sliceNum.pSliceNum = mConfigIntelSliceNumbers.nPSliceNumber;
645    retStatus = mVideoEncoder->setConfig(&sliceNum);
646    if(retStatus != ENCODE_SUCCESS) {
647        LOGW("set silce num config failed!\n");
648    }
649    return OMX_ErrorNone;
650}
651
652OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamIntelAVCVUI(OMX_PTR pStructure) {
653
654    OMX_ERRORTYPE ret;
655    OMX_VIDEO_PARAM_INTEL_AVCVUI *p = (OMX_VIDEO_PARAM_INTEL_AVCVUI *)pStructure;
656
657    CHECK_TYPE_HEADER(p);
658    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
659    memcpy(p, &mParamIntelAvcVui, sizeof(*p));
660
661    return OMX_ErrorNone;
662}
663
664OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamIntelAVCVUI(OMX_PTR pStructure) {
665
666    OMX_ERRORTYPE ret;
667    OMX_VIDEO_PARAM_INTEL_AVCVUI *p = (OMX_VIDEO_PARAM_INTEL_AVCVUI *)pStructure;
668    CHECK_TYPE_HEADER(p);
669    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
670
671    // set only in Loaded state (ComponentSetParam)
672    CHECK_SET_PARAM_STATE();
673
674    mParamIntelAvcVui = *p;
675    return OMX_ErrorNone;
676}
677
678OMX_ERRORTYPE OMXVideoEncoderAVC::GetParamVideoBytestream(OMX_PTR pStructure) {
679    return OMX_ErrorUnsupportedSetting;
680}
681
682OMX_ERRORTYPE OMXVideoEncoderAVC::SetParamVideoBytestream(OMX_PTR pStructure) {
683    OMX_ERRORTYPE ret;
684    OMX_VIDEO_PARAM_BYTESTREAMTYPE *p = (OMX_VIDEO_PARAM_BYTESTREAMTYPE *)pStructure;
685    CHECK_TYPE_HEADER(p);
686    CHECK_PORT_INDEX(p, OUTPORT_INDEX);
687
688    // set only in Loaded state (ComponentSetParam)
689    CHECK_SET_PARAM_STATE();
690
691    if (p->bBytestream == OMX_TRUE) {
692        mNalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes;
693    } else {
694        // TODO: do we need to override the Nalu format?
695        mNalStreamFormat.eNaluFormat = OMX_NaluFormatZeroByteInterleaveLength;
696    }
697
698    return OMX_ErrorNone;
699}
700
701
702DECLARE_OMX_COMPONENT("OMX.Intel.VideoEncoder.AVC", "video_encoder.avc", OMXVideoEncoderAVC);
703