1/*
2 * Copyright (C) 2011 The Android Open Source Project
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* @file   VideoEditorVideoEncoder.cpp
19* @brief  StageFright shell video encoder
20*************************************************************************
21*/
22#define LOG_NDEBUG 1
23#define LOG_TAG "VIDEOEDITOR_VIDEOENCODER"
24
25/*******************
26 *     HEADERS     *
27 *******************/
28#include "M4OSA_Debug.h"
29#include "M4SYS_AccessUnit.h"
30#include "VideoEditorVideoEncoder.h"
31#include "VideoEditorUtils.h"
32#include "MediaBufferPuller.h"
33#include <I420ColorConverter.h>
34
35#include <unistd.h>
36#include "utils/Log.h"
37#include "utils/Vector.h"
38#include <media/stagefright/foundation/ADebug.h>
39#include <media/stagefright/MediaSource.h>
40#include <media/stagefright/MediaDefs.h>
41#include <media/stagefright/MetaData.h>
42#include <media/stagefright/OMXClient.h>
43#include <media/stagefright/OMXCodec.h>
44#include <media/MediaProfiles.h>
45#include "OMX_Video.h"
46
47/********************
48 *   DEFINITIONS    *
49 ********************/
50
51// Force using hardware encoder
52#define VIDEOEDITOR_FORCECODEC kHardwareCodecsOnly
53
54#if !defined(VIDEOEDITOR_FORCECODEC)
55    #error "Cannot force DSI retrieval if codec type is not fixed"
56#endif
57
58/********************
59 *   SOURCE CLASS   *
60 ********************/
61
62namespace android {
63
64struct VideoEditorVideoEncoderSource : public MediaSource {
65    public:
66        static sp<VideoEditorVideoEncoderSource> Create(
67            const sp<MetaData> &format);
68        virtual status_t start(MetaData *params = NULL);
69        virtual status_t stop();
70        virtual sp<MetaData> getFormat();
71        virtual status_t read(MediaBuffer **buffer,
72            const ReadOptions *options = NULL);
73        virtual int32_t storeBuffer(MediaBuffer *buffer);
74        virtual int32_t getNumberOfBuffersInQueue();
75
76    protected:
77        virtual ~VideoEditorVideoEncoderSource();
78
79    private:
80        struct MediaBufferChain {
81            MediaBuffer* buffer;
82            MediaBufferChain* nextLink;
83        };
84        enum State {
85            CREATED,
86            STARTED,
87            ERROR
88        };
89        VideoEditorVideoEncoderSource(const sp<MetaData> &format);
90
91        // Don't call me
92        VideoEditorVideoEncoderSource(const VideoEditorVideoEncoderSource &);
93        VideoEditorVideoEncoderSource &operator=(
94                const VideoEditorVideoEncoderSource &);
95
96        MediaBufferChain* mFirstBufferLink;
97        MediaBufferChain* mLastBufferLink;
98        int32_t           mNbBuffer;
99        bool              mIsEOS;
100        State             mState;
101        sp<MetaData>      mEncFormat;
102        Mutex             mLock;
103        Condition         mBufferCond;
104};
105
106sp<VideoEditorVideoEncoderSource> VideoEditorVideoEncoderSource::Create(
107    const sp<MetaData> &format) {
108
109    sp<VideoEditorVideoEncoderSource> aSource =
110        new VideoEditorVideoEncoderSource(format);
111    return aSource;
112}
113
114VideoEditorVideoEncoderSource::VideoEditorVideoEncoderSource(
115    const sp<MetaData> &format):
116        mFirstBufferLink(NULL),
117        mLastBufferLink(NULL),
118        mNbBuffer(0),
119        mIsEOS(false),
120        mState(CREATED),
121        mEncFormat(format) {
122    ALOGV("VideoEditorVideoEncoderSource::VideoEditorVideoEncoderSource");
123}
124
125VideoEditorVideoEncoderSource::~VideoEditorVideoEncoderSource() {
126
127    // Safety clean up
128    if( STARTED == mState ) {
129        stop();
130    }
131}
132
133status_t VideoEditorVideoEncoderSource::start(MetaData *meta) {
134    status_t err = OK;
135
136    ALOGV("VideoEditorVideoEncoderSource::start() begin");
137
138    if( CREATED != mState ) {
139        ALOGV("VideoEditorVideoEncoderSource::start: invalid state %d", mState);
140        return UNKNOWN_ERROR;
141    }
142    mState = STARTED;
143
144    ALOGV("VideoEditorVideoEncoderSource::start() END (0x%x)", err);
145    return err;
146}
147
148status_t VideoEditorVideoEncoderSource::stop() {
149    status_t err = OK;
150
151    ALOGV("VideoEditorVideoEncoderSource::stop() begin");
152
153    if( STARTED != mState ) {
154        ALOGV("VideoEditorVideoEncoderSource::stop: invalid state %d", mState);
155        return UNKNOWN_ERROR;
156    }
157
158    // Release the buffer chain
159    int32_t i = 0;
160    MediaBufferChain* tmpLink = NULL;
161    while( mFirstBufferLink ) {
162        i++;
163        tmpLink = mFirstBufferLink;
164        mFirstBufferLink = mFirstBufferLink->nextLink;
165        delete tmpLink;
166    }
167    ALOGV("VideoEditorVideoEncoderSource::stop : %d buffer remained", i);
168    mFirstBufferLink = NULL;
169    mLastBufferLink = NULL;
170
171    mState = CREATED;
172
173    ALOGV("VideoEditorVideoEncoderSource::stop() END (0x%x)", err);
174    return err;
175}
176
177sp<MetaData> VideoEditorVideoEncoderSource::getFormat() {
178
179    ALOGV("VideoEditorVideoEncoderSource::getFormat");
180    return mEncFormat;
181}
182
183status_t VideoEditorVideoEncoderSource::read(MediaBuffer **buffer,
184        const ReadOptions *options) {
185    Mutex::Autolock autolock(mLock);
186    MediaSource::ReadOptions readOptions;
187    status_t err = OK;
188    MediaBufferChain* tmpLink = NULL;
189
190    ALOGV("VideoEditorVideoEncoderSource::read() begin");
191
192    if ( STARTED != mState ) {
193        ALOGV("VideoEditorVideoEncoderSource::read: invalid state %d", mState);
194        return UNKNOWN_ERROR;
195    }
196
197    while (mFirstBufferLink == NULL && !mIsEOS) {
198        mBufferCond.wait(mLock);
199    }
200
201    // End of stream?
202    if (mFirstBufferLink == NULL) {
203        *buffer = NULL;
204        ALOGV("VideoEditorVideoEncoderSource::read : EOS");
205        return ERROR_END_OF_STREAM;
206    }
207
208    // Get a buffer from the chain
209    *buffer = mFirstBufferLink->buffer;
210    tmpLink = mFirstBufferLink;
211    mFirstBufferLink = mFirstBufferLink->nextLink;
212
213    if ( NULL == mFirstBufferLink ) {
214        mLastBufferLink = NULL;
215    }
216    delete tmpLink;
217    mNbBuffer--;
218
219    ALOGV("VideoEditorVideoEncoderSource::read() END (0x%x)", err);
220    return err;
221}
222
223int32_t VideoEditorVideoEncoderSource::storeBuffer(MediaBuffer *buffer) {
224    Mutex::Autolock autolock(mLock);
225    status_t err = OK;
226
227    ALOGV("VideoEditorVideoEncoderSource::storeBuffer() begin");
228
229    if( NULL == buffer ) {
230        ALOGV("VideoEditorVideoEncoderSource::storeBuffer : reached EOS");
231        mIsEOS = true;
232    } else {
233        MediaBufferChain* newLink = new MediaBufferChain;
234        newLink->buffer = buffer;
235        newLink->nextLink = NULL;
236        if( NULL != mLastBufferLink ) {
237            mLastBufferLink->nextLink = newLink;
238        } else {
239            mFirstBufferLink = newLink;
240        }
241        mLastBufferLink = newLink;
242        mNbBuffer++;
243    }
244    mBufferCond.signal();
245    ALOGV("VideoEditorVideoEncoderSource::storeBuffer() end");
246    return mNbBuffer;
247}
248
249int32_t VideoEditorVideoEncoderSource::getNumberOfBuffersInQueue() {
250    Mutex::Autolock autolock(mLock);
251    return mNbBuffer;
252}
253
254/**
255 ******************************************************************************
256 * structure VideoEditorVideoEncoder_Context
257 * @brief    This structure defines the context of the StageFright video encoder
258 *           shell
259 ******************************************************************************
260*/
261typedef enum {
262    CREATED   = 0x1,
263    OPENED    = 0x2,
264    STARTED   = 0x4,
265    BUFFERING = 0x8,
266    READING   = 0x10
267} VideoEditorVideoEncoder_State;
268
269typedef struct {
270    VideoEditorVideoEncoder_State     mState;
271    M4ENCODER_Format                  mFormat;
272    M4WRITER_DataInterface*           mWriterDataInterface;
273    M4VPP_apply_fct*                  mPreProcFunction;
274    M4VPP_Context                     mPreProcContext;
275    M4SYS_AccessUnit*                 mAccessUnit;
276    M4ENCODER_Params*                 mCodecParams;
277    M4ENCODER_Header                  mHeader;
278    H264MCS_ProcessEncodedNALU_fct*   mH264NALUPostProcessFct;
279    M4OSA_Context                     mH264NALUPostProcessCtx;
280    M4OSA_UInt32                      mLastCTS;
281    sp<VideoEditorVideoEncoderSource> mEncoderSource;
282    OMXClient                         mClient;
283    sp<MediaSource>                   mEncoder;
284    OMX_COLOR_FORMATTYPE              mEncoderColorFormat;
285    MediaBufferPuller*                mPuller;
286    I420ColorConverter*               mI420ColorConverter;
287
288    uint32_t                          mNbInputFrames;
289    double                            mFirstInputCts;
290    double                            mLastInputCts;
291    uint32_t                          mNbOutputFrames;
292    int64_t                           mFirstOutputCts;
293    int64_t                           mLastOutputCts;
294
295    MediaProfiles *mVideoEditorProfile;
296    int32_t mMaxPrefetchFrames;
297} VideoEditorVideoEncoder_Context;
298
299/********************
300 *      TOOLS       *
301 ********************/
302
303M4OSA_ERR VideoEditorVideoEncoder_getDSI(M4ENCODER_Context pContext,
304        sp<MetaData> metaData) {
305    M4OSA_ERR err = M4NO_ERROR;
306    VideoEditorVideoEncoder_Context*  pEncoderContext = M4OSA_NULL;
307    status_t result = OK;
308    int32_t nbBuffer = 0;
309    int32_t stride = 0;
310    int32_t height = 0;
311    int32_t framerate = 0;
312    int32_t isCodecConfig = 0;
313    size_t size = 0;
314    uint32_t codecFlags = 0;
315    MediaBuffer* inputBuffer = NULL;
316    MediaBuffer* outputBuffer = NULL;
317    sp<VideoEditorVideoEncoderSource> encoderSource = NULL;
318    sp<MediaSource> encoder = NULL;;
319    OMXClient client;
320
321    ALOGV("VideoEditorVideoEncoder_getDSI begin");
322    // Input parameters check
323    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,       M4ERR_PARAMETER);
324    VIDEOEDITOR_CHECK(M4OSA_NULL != metaData.get(), M4ERR_PARAMETER);
325
326    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
327    VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE);
328
329    // Create the encoder source
330    encoderSource = VideoEditorVideoEncoderSource::Create(metaData);
331    VIDEOEDITOR_CHECK(NULL != encoderSource.get(), M4ERR_STATE);
332
333    // Connect to the OMX client
334    result = client.connect();
335    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
336
337    // Create the OMX codec
338    // VIDEOEDITOR_FORCECODEC MUST be defined here
339    codecFlags |= OMXCodec::VIDEOEDITOR_FORCECODEC;
340    encoder = OMXCodec::Create(client.interface(), metaData, true,
341        encoderSource, NULL, codecFlags);
342    VIDEOEDITOR_CHECK(NULL != encoder.get(), M4ERR_STATE);
343
344    /**
345     * Send fake frames and retrieve the DSI
346     */
347    // Send a fake frame to the source
348    metaData->findInt32(kKeyStride,     &stride);
349    metaData->findInt32(kKeyHeight,     &height);
350    metaData->findInt32(kKeySampleRate, &framerate);
351    size = (size_t)(stride*height*3)/2;
352    inputBuffer = new MediaBuffer(size);
353    inputBuffer->meta_data()->setInt64(kKeyTime, 0);
354    nbBuffer = encoderSource->storeBuffer(inputBuffer);
355    encoderSource->storeBuffer(NULL); // Signal EOS
356
357    // Call read once to get the DSI
358    result = encoder->start();;
359    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
360    result = encoder->read(&outputBuffer, NULL);
361    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
362    VIDEOEDITOR_CHECK(outputBuffer->meta_data()->findInt32(
363        kKeyIsCodecConfig, &isCodecConfig) && isCodecConfig, M4ERR_STATE);
364
365    VIDEOEDITOR_CHECK(M4OSA_NULL == pEncoderContext->mHeader.pBuf, M4ERR_STATE);
366    if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) {
367        // For H264, format the DSI
368        result = buildAVCCodecSpecificData(
369            (uint8_t**)(&(pEncoderContext->mHeader.pBuf)),
370            (size_t*)(&(pEncoderContext->mHeader.Size)),
371            (const uint8_t*)outputBuffer->data() + outputBuffer->range_offset(),
372            outputBuffer->range_length(), encoder->getFormat().get());
373        outputBuffer->release();
374        VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
375    } else {
376        // For MPEG4, just copy the DSI
377        pEncoderContext->mHeader.Size =
378            (M4OSA_UInt32)outputBuffer->range_length();
379        SAFE_MALLOC(pEncoderContext->mHeader.pBuf, M4OSA_Int8,
380            pEncoderContext->mHeader.Size, "Encoder header");
381        memcpy((void *)pEncoderContext->mHeader.pBuf,
382            (void *)((M4OSA_MemAddr8)(outputBuffer->data())+outputBuffer->range_offset()),
383            pEncoderContext->mHeader.Size);
384        outputBuffer->release();
385    }
386
387    result = encoder->stop();
388    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
389
390cleanUp:
391    // Destroy the graph
392    if ( encoder != NULL ) { encoder.clear(); }
393    client.disconnect();
394    if ( encoderSource != NULL ) { encoderSource.clear(); }
395    if ( M4NO_ERROR == err ) {
396        ALOGV("VideoEditorVideoEncoder_getDSI no error");
397    } else {
398        ALOGV("VideoEditorVideoEncoder_getDSI ERROR 0x%X", err);
399    }
400    ALOGV("VideoEditorVideoEncoder_getDSI end");
401    return err;
402}
403/********************
404 * ENGINE INTERFACE *
405 ********************/
406
407M4OSA_ERR VideoEditorVideoEncoder_cleanup(M4ENCODER_Context pContext) {
408    M4OSA_ERR err = M4NO_ERROR;
409    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
410
411    ALOGV("VideoEditorVideoEncoder_cleanup begin");
412    // Input parameters check
413    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
414
415    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
416    VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE);
417
418    // Release memory
419    SAFE_FREE(pEncoderContext->mHeader.pBuf);
420    SAFE_FREE(pEncoderContext);
421    pContext = M4OSA_NULL;
422
423cleanUp:
424    if ( M4NO_ERROR == err ) {
425        ALOGV("VideoEditorVideoEncoder_cleanup no error");
426    } else {
427        ALOGV("VideoEditorVideoEncoder_cleanup ERROR 0x%X", err);
428    }
429    ALOGV("VideoEditorVideoEncoder_cleanup end");
430    return err;
431}
432
433M4OSA_ERR VideoEditorVideoEncoder_init(M4ENCODER_Format format,
434        M4ENCODER_Context* pContext,
435        M4WRITER_DataInterface* pWriterDataInterface,
436        M4VPP_apply_fct* pVPPfct, M4VPP_Context pVPPctxt,
437        M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData) {
438
439    M4OSA_ERR err = M4NO_ERROR;
440    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
441    int encoderInput = OMX_COLOR_FormatYUV420Planar;
442
443    ALOGV("VideoEditorVideoEncoder_init begin: format  %d", format);
444    // Input parameters check
445    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
446    VIDEOEDITOR_CHECK(M4OSA_NULL != pWriterDataInterface, M4ERR_PARAMETER);
447    VIDEOEDITOR_CHECK(M4OSA_NULL != pVPPfct, M4ERR_PARAMETER);
448    VIDEOEDITOR_CHECK(M4OSA_NULL != pVPPctxt, M4ERR_PARAMETER);
449
450    // Context allocation & initialization
451    SAFE_MALLOC(pEncoderContext, VideoEditorVideoEncoder_Context, 1,
452        "VideoEditorVideoEncoder");
453    pEncoderContext->mState = CREATED;
454    pEncoderContext->mFormat = format;
455    pEncoderContext->mWriterDataInterface = pWriterDataInterface;
456    pEncoderContext->mPreProcFunction = pVPPfct;
457    pEncoderContext->mPreProcContext = pVPPctxt;
458    pEncoderContext->mPuller = NULL;
459
460    // Get color converter and determine encoder input format
461    pEncoderContext->mI420ColorConverter = new I420ColorConverter;
462    if (pEncoderContext->mI420ColorConverter->isLoaded()) {
463        encoderInput = pEncoderContext->mI420ColorConverter->getEncoderInputFormat();
464    }
465    if (encoderInput == OMX_COLOR_FormatYUV420Planar) {
466        delete pEncoderContext->mI420ColorConverter;
467        pEncoderContext->mI420ColorConverter = NULL;
468    }
469    pEncoderContext->mEncoderColorFormat = (OMX_COLOR_FORMATTYPE)encoderInput;
470    ALOGI("encoder input format = 0x%X\n", encoderInput);
471
472    *pContext = pEncoderContext;
473
474cleanUp:
475    if ( M4NO_ERROR == err ) {
476        ALOGV("VideoEditorVideoEncoder_init no error");
477    } else {
478        VideoEditorVideoEncoder_cleanup(pEncoderContext);
479        *pContext = M4OSA_NULL;
480        ALOGV("VideoEditorVideoEncoder_init ERROR 0x%X", err);
481    }
482    ALOGV("VideoEditorVideoEncoder_init end");
483    return err;
484}
485
486M4OSA_ERR VideoEditorVideoEncoder_init_H263(M4ENCODER_Context* pContext,
487        M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct,
488        M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData)
489        {
490
491    return VideoEditorVideoEncoder_init(M4ENCODER_kH263, pContext,
492        pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData);
493}
494
495
496M4OSA_ERR VideoEditorVideoEncoder_init_MPEG4(M4ENCODER_Context* pContext,
497        M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct,
498        M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData)
499        {
500
501    return VideoEditorVideoEncoder_init(M4ENCODER_kMPEG4, pContext,
502        pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData);
503}
504
505
506M4OSA_ERR VideoEditorVideoEncoder_init_H264(M4ENCODER_Context* pContext,
507        M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct,
508        M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData)
509        {
510
511    return VideoEditorVideoEncoder_init(M4ENCODER_kH264, pContext,
512        pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData);
513}
514
515M4OSA_ERR VideoEditorVideoEncoder_close(M4ENCODER_Context pContext) {
516    M4OSA_ERR err = M4NO_ERROR;
517    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
518
519    ALOGV("VideoEditorVideoEncoder_close begin");
520    // Input parameters check
521    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
522
523    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
524    VIDEOEDITOR_CHECK(OPENED == pEncoderContext->mState, M4ERR_STATE);
525
526    // Release memory
527    SAFE_FREE(pEncoderContext->mCodecParams);
528
529    // Destroy the graph
530    pEncoderContext->mEncoder.clear();
531    pEncoderContext->mClient.disconnect();
532    pEncoderContext->mEncoderSource.clear();
533
534    delete pEncoderContext->mPuller;
535    pEncoderContext->mPuller = NULL;
536
537    delete pEncoderContext->mI420ColorConverter;
538    pEncoderContext->mI420ColorConverter = NULL;
539
540    // Set the new state
541    pEncoderContext->mState = CREATED;
542
543cleanUp:
544    if( M4NO_ERROR == err ) {
545        ALOGV("VideoEditorVideoEncoder_close no error");
546    } else {
547        ALOGV("VideoEditorVideoEncoder_close ERROR 0x%X", err);
548    }
549    ALOGV("VideoEditorVideoEncoder_close end");
550    return err;
551}
552
553
554M4OSA_ERR VideoEditorVideoEncoder_open(M4ENCODER_Context pContext,
555        M4SYS_AccessUnit* pAU, M4OSA_Void* pParams) {
556    M4OSA_ERR err = M4NO_ERROR;
557    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
558    M4ENCODER_Params* pCodecParams = M4OSA_NULL;
559    status_t result = OK;
560    sp<MetaData> encoderMetadata = NULL;
561    const char* mime = NULL;
562    int32_t iProfile = 0;
563    int32_t iLevel = 0;
564
565    int32_t iFrameRate = 0;
566    uint32_t codecFlags = 0;
567
568    ALOGV(">>> VideoEditorVideoEncoder_open begin");
569    // Input parameters check
570    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
571    VIDEOEDITOR_CHECK(M4OSA_NULL != pAU,      M4ERR_PARAMETER);
572    VIDEOEDITOR_CHECK(M4OSA_NULL != pParams,  M4ERR_PARAMETER);
573
574    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
575    pCodecParams = (M4ENCODER_Params*)pParams;
576    VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE);
577
578    // Context initialization
579    pEncoderContext->mAccessUnit = pAU;
580    pEncoderContext->mVideoEditorProfile = MediaProfiles::getInstance();
581    pEncoderContext->mMaxPrefetchFrames =
582        pEncoderContext->mVideoEditorProfile->getVideoEditorCapParamByName(
583        "maxPrefetchYUVFrames");
584
585    // Allocate & initialize the encoding parameters
586    SAFE_MALLOC(pEncoderContext->mCodecParams, M4ENCODER_Params, 1,
587        "VideoEditorVideoEncoder");
588
589
590    pEncoderContext->mCodecParams->InputFormat = pCodecParams->InputFormat;
591    pEncoderContext->mCodecParams->InputFrameWidth =
592        pCodecParams->InputFrameWidth;
593    pEncoderContext->mCodecParams->InputFrameHeight =
594        pCodecParams->InputFrameHeight;
595    pEncoderContext->mCodecParams->FrameWidth = pCodecParams->FrameWidth;
596    pEncoderContext->mCodecParams->FrameHeight = pCodecParams->FrameHeight;
597    pEncoderContext->mCodecParams->Bitrate = pCodecParams->Bitrate;
598    pEncoderContext->mCodecParams->FrameRate = pCodecParams->FrameRate;
599    pEncoderContext->mCodecParams->Format = pCodecParams->Format;
600    pEncoderContext->mCodecParams->videoProfile = pCodecParams->videoProfile;
601    pEncoderContext->mCodecParams->videoLevel= pCodecParams->videoLevel;
602
603    // Check output format consistency and resolution
604    VIDEOEDITOR_CHECK(
605        pEncoderContext->mCodecParams->Format == pEncoderContext->mFormat,
606        M4ERR_PARAMETER);
607    VIDEOEDITOR_CHECK(0 == pEncoderContext->mCodecParams->FrameWidth  % 16,
608        M4ERR_PARAMETER);
609    VIDEOEDITOR_CHECK(0 == pEncoderContext->mCodecParams->FrameHeight % 16,
610        M4ERR_PARAMETER);
611
612    /**
613     * StageFright graph building
614     */
615
616    // Create the meta data for the encoder
617    encoderMetadata = new MetaData;
618    switch( pEncoderContext->mCodecParams->Format ) {
619        case M4ENCODER_kH263:
620            mime     = MEDIA_MIMETYPE_VIDEO_H263;
621            break;
622        case M4ENCODER_kMPEG4:
623            mime     = MEDIA_MIMETYPE_VIDEO_MPEG4;
624            break;
625        case M4ENCODER_kH264:
626            mime     = MEDIA_MIMETYPE_VIDEO_AVC;
627            break;
628        default:
629            VIDEOEDITOR_CHECK(!"VideoEncoder_open : incorrect input format",
630                M4ERR_PARAMETER);
631            break;
632    }
633    iProfile = pEncoderContext->mCodecParams->videoProfile;
634    iLevel = pEncoderContext->mCodecParams->videoLevel;
635    ALOGV("Encoder mime %s profile %d, level %d",
636        mime,iProfile, iLevel);
637    ALOGV("Encoder w %d, h %d, bitrate %d, fps %d",
638        pEncoderContext->mCodecParams->FrameWidth,
639        pEncoderContext->mCodecParams->FrameHeight,
640        pEncoderContext->mCodecParams->Bitrate,
641        pEncoderContext->mCodecParams->FrameRate);
642    CHECK(iProfile != 0x7fffffff);
643    CHECK(iLevel != 0x7fffffff);
644
645    encoderMetadata->setCString(kKeyMIMEType, mime);
646    encoderMetadata->setInt32(kKeyVideoProfile, iProfile);
647    //FIXME:
648    // Temp: Do not set the level for Mpeg4 / H.263 Enc
649    // as OMX.Nvidia.mp4.encoder and OMX.Nvidia.h263.encoder
650    // return 0x80001019
651    if (pEncoderContext->mCodecParams->Format == M4ENCODER_kH264) {
652        encoderMetadata->setInt32(kKeyVideoLevel, iLevel);
653    }
654    encoderMetadata->setInt32(kKeyWidth,
655        (int32_t)pEncoderContext->mCodecParams->FrameWidth);
656    encoderMetadata->setInt32(kKeyStride,
657        (int32_t)pEncoderContext->mCodecParams->FrameWidth);
658    encoderMetadata->setInt32(kKeyHeight,
659        (int32_t)pEncoderContext->mCodecParams->FrameHeight);
660    encoderMetadata->setInt32(kKeySliceHeight,
661        (int32_t)pEncoderContext->mCodecParams->FrameHeight);
662
663    switch( pEncoderContext->mCodecParams->FrameRate ) {
664        case M4ENCODER_k5_FPS:    iFrameRate = 5;  break;
665        case M4ENCODER_k7_5_FPS:  iFrameRate = 8;  break;
666        case M4ENCODER_k10_FPS:   iFrameRate = 10; break;
667        case M4ENCODER_k12_5_FPS: iFrameRate = 13; break;
668        case M4ENCODER_k15_FPS:   iFrameRate = 15; break;
669        case M4ENCODER_k20_FPS:   iFrameRate = 20; break;
670        case M4ENCODER_k25_FPS:   iFrameRate = 25; break;
671        case M4ENCODER_k30_FPS:   iFrameRate = 30; break;
672        case M4ENCODER_kVARIABLE_FPS:
673            iFrameRate = 30;
674            ALOGI("Frame rate set to M4ENCODER_kVARIABLE_FPS: set to 30");
675          break;
676        case M4ENCODER_kUSE_TIMESCALE:
677            iFrameRate = 30;
678            ALOGI("Frame rate set to M4ENCODER_kUSE_TIMESCALE:  set to 30");
679            break;
680
681        default:
682            VIDEOEDITOR_CHECK(!"VideoEncoder_open:incorrect framerate",
683                M4ERR_STATE);
684            break;
685    }
686    encoderMetadata->setInt32(kKeyFrameRate, iFrameRate);
687    encoderMetadata->setInt32(kKeyBitRate,
688        (int32_t)pEncoderContext->mCodecParams->Bitrate);
689    encoderMetadata->setInt32(kKeyIFramesInterval, 1);
690
691    encoderMetadata->setInt32(kKeyColorFormat,
692        pEncoderContext->mEncoderColorFormat);
693
694    if (pEncoderContext->mCodecParams->Format != M4ENCODER_kH263) {
695        // Get the encoder DSI
696        err = VideoEditorVideoEncoder_getDSI(pEncoderContext, encoderMetadata);
697        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
698    }
699
700    // Create the encoder source
701    pEncoderContext->mEncoderSource = VideoEditorVideoEncoderSource::Create(
702        encoderMetadata);
703    VIDEOEDITOR_CHECK(
704        NULL != pEncoderContext->mEncoderSource.get(), M4ERR_STATE);
705
706    // Connect to the OMX client
707    result = pEncoderContext->mClient.connect();
708    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
709
710    // Create the OMX codec
711#ifdef VIDEOEDITOR_FORCECODEC
712    codecFlags |= OMXCodec::VIDEOEDITOR_FORCECODEC;
713#endif /* VIDEOEDITOR_FORCECODEC */
714    pEncoderContext->mEncoder = OMXCodec::Create(
715        pEncoderContext->mClient.interface(), encoderMetadata, true,
716        pEncoderContext->mEncoderSource, NULL, codecFlags);
717    VIDEOEDITOR_CHECK(NULL != pEncoderContext->mEncoder.get(), M4ERR_STATE);
718    ALOGV("VideoEditorVideoEncoder_open : DONE");
719    pEncoderContext->mPuller = new MediaBufferPuller(
720        pEncoderContext->mEncoder);
721
722    // Set the new state
723    pEncoderContext->mState = OPENED;
724
725cleanUp:
726    if( M4NO_ERROR == err ) {
727        ALOGV("VideoEditorVideoEncoder_open no error");
728    } else {
729        VideoEditorVideoEncoder_close(pEncoderContext);
730        ALOGV("VideoEditorVideoEncoder_open ERROR 0x%X", err);
731    }
732    ALOGV("VideoEditorVideoEncoder_open end");
733    return err;
734}
735
736M4OSA_ERR VideoEditorVideoEncoder_processInputBuffer(
737        M4ENCODER_Context pContext, M4OSA_Double Cts,
738        M4OSA_Bool bReachedEOS) {
739    M4OSA_ERR err = M4NO_ERROR;
740    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
741    M4VIFI_ImagePlane pOutPlane[3];
742    MediaBuffer* buffer = NULL;
743    int32_t nbBuffer = 0;
744
745    ALOGV("VideoEditorVideoEncoder_processInputBuffer begin: cts  %f", Cts);
746    // Input parameters check
747    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
748
749    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
750    pOutPlane[0].pac_data = M4OSA_NULL;
751    pOutPlane[1].pac_data = M4OSA_NULL;
752    pOutPlane[2].pac_data = M4OSA_NULL;
753
754    if ( M4OSA_FALSE == bReachedEOS ) {
755        M4OSA_UInt32 sizeY = pEncoderContext->mCodecParams->FrameWidth *
756            pEncoderContext->mCodecParams->FrameHeight;
757        M4OSA_UInt32 sizeU = sizeY >> 2;
758        M4OSA_UInt32 size  = sizeY + 2*sizeU;
759        M4OSA_UInt8* pData = M4OSA_NULL;
760        buffer = new MediaBuffer((size_t)size);
761        pData = (M4OSA_UInt8*)buffer->data() + buffer->range_offset();
762
763        // Prepare the output image for pre-processing
764        pOutPlane[0].u_width   = pEncoderContext->mCodecParams->FrameWidth;
765        pOutPlane[0].u_height  = pEncoderContext->mCodecParams->FrameHeight;
766        pOutPlane[0].u_topleft = 0;
767        pOutPlane[0].u_stride  = pOutPlane[0].u_width;
768        pOutPlane[1].u_width   = pOutPlane[0].u_width/2;
769        pOutPlane[1].u_height  = pOutPlane[0].u_height/2;
770        pOutPlane[1].u_topleft = 0;
771        pOutPlane[1].u_stride  = pOutPlane[0].u_stride/2;
772        pOutPlane[2].u_width   = pOutPlane[1].u_width;
773        pOutPlane[2].u_height  = pOutPlane[1].u_height;
774        pOutPlane[2].u_topleft = 0;
775        pOutPlane[2].u_stride  = pOutPlane[1].u_stride;
776
777        pOutPlane[0].pac_data = pData;
778        pOutPlane[1].pac_data = pData + sizeY;
779        pOutPlane[2].pac_data = pData + sizeY + sizeU;
780
781        // Apply pre-processing
782        err = pEncoderContext->mPreProcFunction(
783            pEncoderContext->mPreProcContext, M4OSA_NULL, pOutPlane);
784        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
785
786        // Convert MediaBuffer to the encoder input format if necessary
787        if (pEncoderContext->mI420ColorConverter) {
788            I420ColorConverter* converter = pEncoderContext->mI420ColorConverter;
789            int actualWidth = pEncoderContext->mCodecParams->FrameWidth;
790            int actualHeight = pEncoderContext->mCodecParams->FrameHeight;
791
792            int encoderWidth, encoderHeight;
793            ARect encoderRect;
794            int encoderBufferSize;
795
796            if (converter->getEncoderInputBufferInfo(
797                actualWidth, actualHeight,
798                &encoderWidth, &encoderHeight,
799                &encoderRect, &encoderBufferSize) == 0) {
800
801                MediaBuffer* newBuffer = new MediaBuffer(encoderBufferSize);
802
803                if (converter->convertI420ToEncoderInput(
804                    pData,  // srcBits
805                    actualWidth, actualHeight,
806                    encoderWidth, encoderHeight,
807                    encoderRect,
808                    (uint8_t*)newBuffer->data() + newBuffer->range_offset()) < 0) {
809                    ALOGE("convertI420ToEncoderInput failed");
810                }
811
812                // switch to new buffer
813                buffer->release();
814                buffer = newBuffer;
815            }
816        }
817
818        // Set the metadata
819        buffer->meta_data()->setInt64(kKeyTime, (int64_t)(Cts*1000));
820    }
821
822    // Push the buffer to the source, a NULL buffer, notifies the source of EOS
823    nbBuffer = pEncoderContext->mEncoderSource->storeBuffer(buffer);
824
825cleanUp:
826    if ( M4NO_ERROR == err ) {
827        ALOGV("VideoEditorVideoEncoder_processInputBuffer error 0x%X", err);
828    } else {
829        if( NULL != buffer ) {
830            buffer->release();
831        }
832        ALOGV("VideoEditorVideoEncoder_processInputBuffer ERROR 0x%X", err);
833    }
834    ALOGV("VideoEditorVideoEncoder_processInputBuffer end");
835    return err;
836}
837
838M4OSA_ERR VideoEditorVideoEncoder_processOutputBuffer(
839        M4ENCODER_Context pContext, MediaBuffer* buffer) {
840    M4OSA_ERR err = M4NO_ERROR;
841    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
842    M4OSA_UInt32 Cts = 0;
843    int32_t i32Tmp = 0;
844    int64_t i64Tmp = 0;
845    status_t result = OK;
846
847    ALOGV("VideoEditorVideoEncoder_processOutputBuffer begin");
848    // Input parameters check
849    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
850    VIDEOEDITOR_CHECK(M4OSA_NULL != buffer,   M4ERR_PARAMETER);
851
852    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
853
854    // Process the returned AU
855    if ( 0 == buffer->range_length() ) {
856        // Encoder has no data yet, nothing unusual
857        ALOGV("VideoEditorVideoEncoder_processOutputBuffer : buffer is empty");
858        goto cleanUp;
859    }
860    VIDEOEDITOR_CHECK(0 == ((M4OSA_UInt32)buffer->data())%4, M4ERR_PARAMETER);
861    VIDEOEDITOR_CHECK(buffer->meta_data().get(), M4ERR_PARAMETER);
862    if ( buffer->meta_data()->findInt32(kKeyIsCodecConfig, &i32Tmp) && i32Tmp ){
863        {   // Display the DSI
864            ALOGV("VideoEditorVideoEncoder_processOutputBuffer DSI %d",
865                buffer->range_length());
866            uint8_t* tmp = (uint8_t*)(buffer->data());
867            for( uint32_t i=0; i<buffer->range_length(); i++ ) {
868                ALOGV("DSI [%d] %.2X", i, tmp[i]);
869            }
870        }
871    } else {
872        // Check the CTS
873        VIDEOEDITOR_CHECK(buffer->meta_data()->findInt64(kKeyTime, &i64Tmp),
874            M4ERR_STATE);
875
876        pEncoderContext->mNbOutputFrames++;
877        if ( 0 > pEncoderContext->mFirstOutputCts ) {
878            pEncoderContext->mFirstOutputCts = i64Tmp;
879        }
880        pEncoderContext->mLastOutputCts = i64Tmp;
881
882        Cts = (M4OSA_Int32)(i64Tmp/1000);
883        ALOGV("[TS_CHECK] VI/ENC WRITE frame %d @ %lld -> %d (last %d)",
884            pEncoderContext->mNbOutputFrames, i64Tmp, Cts,
885            pEncoderContext->mLastCTS);
886        if ( Cts < pEncoderContext->mLastCTS ) {
887            ALOGV("VideoEncoder_processOutputBuffer WARNING : Cts is going "
888            "backwards %d < %d", Cts, pEncoderContext->mLastCTS);
889            goto cleanUp;
890        }
891        ALOGV("VideoEditorVideoEncoder_processOutputBuffer : %d %d",
892            Cts, pEncoderContext->mLastCTS);
893
894        // Retrieve the AU container
895        err = pEncoderContext->mWriterDataInterface->pStartAU(
896            pEncoderContext->mWriterDataInterface->pWriterContext,
897            pEncoderContext->mAccessUnit->stream->streamID,
898            pEncoderContext->mAccessUnit);
899        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
900
901        // Format the AU
902        VIDEOEDITOR_CHECK(
903            buffer->range_length() <= pEncoderContext->mAccessUnit->size,
904            M4ERR_PARAMETER);
905        // Remove H264 AU start code
906        if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) {
907            if (!memcmp((const uint8_t *)buffer->data() + \
908                    buffer->range_offset(), "\x00\x00\x00\x01", 4) ) {
909                buffer->set_range(buffer->range_offset() + 4,
910                    buffer->range_length() - 4);
911            }
912        }
913
914        if ( (M4ENCODER_kH264 == pEncoderContext->mFormat) &&
915            (M4OSA_NULL != pEncoderContext->mH264NALUPostProcessFct) ) {
916        // H264 trimming case, NALU post processing is needed
917        M4OSA_Int32 outputSize = pEncoderContext->mAccessUnit->size;
918        err = pEncoderContext->mH264NALUPostProcessFct(
919            pEncoderContext->mH264NALUPostProcessCtx,
920            (M4OSA_UInt8*)buffer->data()+buffer->range_offset(),
921            buffer->range_length(),
922            (M4OSA_UInt8*)pEncoderContext->mAccessUnit->dataAddress,
923            &outputSize);
924        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
925        pEncoderContext->mAccessUnit->size = (M4OSA_UInt32)outputSize;
926        } else {
927            // The AU can just be copied
928            memcpy((void *)pEncoderContext->mAccessUnit->\
929                dataAddress, (void *)((M4OSA_MemAddr8)(buffer->data())+buffer->\
930                range_offset()), buffer->range_length());
931            pEncoderContext->mAccessUnit->size =
932                (M4OSA_UInt32)buffer->range_length();
933        }
934
935        if ( buffer->meta_data()->findInt32(kKeyIsSyncFrame,&i32Tmp) && i32Tmp){
936            pEncoderContext->mAccessUnit->attribute = AU_RAP;
937        } else {
938            pEncoderContext->mAccessUnit->attribute = AU_P_Frame;
939        }
940        pEncoderContext->mLastCTS = Cts;
941        pEncoderContext->mAccessUnit->CTS = Cts;
942        pEncoderContext->mAccessUnit->DTS = Cts;
943
944        ALOGV("VideoEditorVideoEncoder_processOutputBuffer: AU @ 0x%X 0x%X %d %d",
945            pEncoderContext->mAccessUnit->dataAddress,
946            *pEncoderContext->mAccessUnit->dataAddress,
947            pEncoderContext->mAccessUnit->size,
948            pEncoderContext->mAccessUnit->CTS);
949
950        // Write the AU
951        err = pEncoderContext->mWriterDataInterface->pProcessAU(
952            pEncoderContext->mWriterDataInterface->pWriterContext,
953            pEncoderContext->mAccessUnit->stream->streamID,
954            pEncoderContext->mAccessUnit);
955        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
956    }
957
958cleanUp:
959    if( M4NO_ERROR == err ) {
960        ALOGV("VideoEditorVideoEncoder_processOutputBuffer no error");
961    } else {
962        SAFE_FREE(pEncoderContext->mHeader.pBuf);
963        pEncoderContext->mHeader.Size = 0;
964        ALOGV("VideoEditorVideoEncoder_processOutputBuffer ERROR 0x%X", err);
965    }
966    ALOGV("VideoEditorVideoEncoder_processOutputBuffer end");
967    return err;
968}
969
970M4OSA_ERR VideoEditorVideoEncoder_encode(M4ENCODER_Context pContext,
971        M4VIFI_ImagePlane* pInPlane, M4OSA_Double Cts,
972        M4ENCODER_FrameMode FrameMode) {
973    M4OSA_ERR err = M4NO_ERROR;
974    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
975    status_t result = OK;
976    MediaBuffer* outputBuffer = NULL;
977
978    ALOGV("VideoEditorVideoEncoder_encode 0x%X %f %d", pInPlane, Cts, FrameMode);
979    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
980
981    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
982    if ( STARTED == pEncoderContext->mState ) {
983        pEncoderContext->mState = BUFFERING;
984    }
985    VIDEOEDITOR_CHECK(
986        (BUFFERING | READING) & pEncoderContext->mState, M4ERR_STATE);
987
988    pEncoderContext->mNbInputFrames++;
989    if ( 0 > pEncoderContext->mFirstInputCts ) {
990        pEncoderContext->mFirstInputCts = Cts;
991    }
992    pEncoderContext->mLastInputCts = Cts;
993
994    ALOGV("VideoEditorVideoEncoder_encode 0x%X %d %f (%d)", pInPlane, FrameMode,
995        Cts, pEncoderContext->mLastCTS);
996
997    // Push the input buffer to the encoder source
998    err = VideoEditorVideoEncoder_processInputBuffer(pEncoderContext, Cts,
999        M4OSA_FALSE);
1000    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
1001
1002    // Notify the source in case of EOS
1003    if ( M4ENCODER_kLastFrame == FrameMode ) {
1004        err = VideoEditorVideoEncoder_processInputBuffer(
1005            pEncoderContext, 0, M4OSA_TRUE);
1006        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
1007    }
1008
1009    if ( BUFFERING == pEncoderContext->mState ) {
1010        // Prefetch is complete, start reading
1011        pEncoderContext->mState = READING;
1012    }
1013    // Read
1014    while (1)  {
1015        MediaBuffer *outputBuffer =
1016                pEncoderContext->mPuller->getBufferNonBlocking();
1017
1018        if (outputBuffer == NULL) {
1019            int32_t YUVBufferNumber =
1020                    pEncoderContext->mEncoderSource->getNumberOfBuffersInQueue();
1021            /* Make sure that the configured maximum number of prefetch YUV frames is
1022             * not exceeded. This is to limit the amount of memory usage of video editor engine.
1023             * The value of maximum prefetch Yuv frames is defined in media_profiles.xml */
1024            if ((YUVBufferNumber < pEncoderContext->mMaxPrefetchFrames) ||
1025                (pEncoderContext->mPuller->hasMediaSourceReturnedError()
1026                    == true)) {
1027                break;
1028            }
1029        } else {
1030            // Provide the encoded AU to the writer
1031            err = VideoEditorVideoEncoder_processOutputBuffer(pEncoderContext,
1032                outputBuffer);
1033            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
1034
1035            pEncoderContext->mPuller->putBuffer(outputBuffer);
1036        }
1037    }
1038
1039cleanUp:
1040    if( M4NO_ERROR == err ) {
1041        ALOGV("VideoEditorVideoEncoder_encode no error");
1042    } else {
1043        ALOGV("VideoEditorVideoEncoder_encode ERROR 0x%X", err);
1044    }
1045    ALOGV("VideoEditorVideoEncoder_encode end");
1046    return err;
1047}
1048
1049M4OSA_ERR VideoEditorVideoEncoder_start(M4ENCODER_Context pContext) {
1050    M4OSA_ERR                  err             = M4NO_ERROR;
1051    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
1052    status_t                   result          = OK;
1053
1054    ALOGV("VideoEditorVideoEncoder_start begin");
1055    // Input parameters check
1056    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
1057
1058    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
1059    VIDEOEDITOR_CHECK(OPENED == pEncoderContext->mState, M4ERR_STATE);
1060
1061    pEncoderContext->mNbInputFrames  = 0;
1062    pEncoderContext->mFirstInputCts  = -1.0;
1063    pEncoderContext->mLastInputCts   = -1.0;
1064    pEncoderContext->mNbOutputFrames = 0;
1065    pEncoderContext->mFirstOutputCts = -1;
1066    pEncoderContext->mLastOutputCts  = -1;
1067
1068    result = pEncoderContext->mEncoder->start();
1069    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
1070
1071    pEncoderContext->mPuller->start();
1072
1073    // Set the new state
1074    pEncoderContext->mState = STARTED;
1075
1076cleanUp:
1077    if ( M4NO_ERROR == err ) {
1078        ALOGV("VideoEditorVideoEncoder_start no error");
1079    } else {
1080        ALOGV("VideoEditorVideoEncoder_start ERROR 0x%X", err);
1081    }
1082    ALOGV("VideoEditorVideoEncoder_start end");
1083    return err;
1084}
1085
1086M4OSA_ERR VideoEditorVideoEncoder_stop(M4ENCODER_Context pContext) {
1087    M4OSA_ERR err = M4NO_ERROR;
1088    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
1089    MediaBuffer* outputBuffer = NULL;
1090    status_t result = OK;
1091
1092    ALOGV("VideoEditorVideoEncoder_stop begin");
1093    // Input parameters check
1094    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
1095    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
1096
1097    // Send EOS again to make sure the source doesn't block.
1098    err = VideoEditorVideoEncoder_processInputBuffer(pEncoderContext, 0,
1099        M4OSA_TRUE);
1100    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
1101
1102    // Process the remaining buffers if necessary
1103    if ( (BUFFERING | READING) & pEncoderContext->mState ) {
1104        while (1)  {
1105            MediaBuffer *outputBuffer =
1106                pEncoderContext->mPuller->getBufferBlocking();
1107
1108            if (outputBuffer == NULL) break;
1109
1110            err = VideoEditorVideoEncoder_processOutputBuffer(
1111                pEncoderContext, outputBuffer);
1112            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
1113
1114            pEncoderContext->mPuller->putBuffer(outputBuffer);
1115        }
1116
1117        pEncoderContext->mState = STARTED;
1118    }
1119
1120    // Stop the graph module if necessary
1121    if ( STARTED == pEncoderContext->mState ) {
1122        pEncoderContext->mPuller->stop();
1123        pEncoderContext->mEncoder->stop();
1124        pEncoderContext->mState = OPENED;
1125    }
1126
1127    if (pEncoderContext->mNbInputFrames != pEncoderContext->mNbOutputFrames) {
1128        ALOGW("Some frames were not encoded: input(%d) != output(%d)",
1129            pEncoderContext->mNbInputFrames, pEncoderContext->mNbOutputFrames);
1130    }
1131
1132cleanUp:
1133    if ( M4NO_ERROR == err ) {
1134        ALOGV("VideoEditorVideoEncoder_stop no error");
1135    } else {
1136        ALOGV("VideoEditorVideoEncoder_stop ERROR 0x%X", err);
1137    }
1138    ALOGV("VideoEditorVideoEncoder_stop end");
1139    return err;
1140}
1141
1142M4OSA_ERR VideoEditorVideoEncoder_regulBitRate(M4ENCODER_Context pContext) {
1143    ALOGW("regulBitRate is not implemented");
1144    return M4NO_ERROR;
1145}
1146
1147M4OSA_ERR VideoEditorVideoEncoder_setOption(M4ENCODER_Context pContext,
1148        M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) {
1149    M4OSA_ERR err = M4NO_ERROR;
1150    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
1151
1152    ALOGV("VideoEditorVideoEncoder_setOption start optionID 0x%X", optionID);
1153    // Input parameters check
1154    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
1155
1156    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
1157
1158    switch( optionID ) {
1159        case M4ENCODER_kOptionID_SetH264ProcessNALUfctsPtr:
1160            pEncoderContext->mH264NALUPostProcessFct =
1161                (H264MCS_ProcessEncodedNALU_fct*)optionValue;
1162            break;
1163        case M4ENCODER_kOptionID_H264ProcessNALUContext:
1164            pEncoderContext->mH264NALUPostProcessCtx =
1165                (M4OSA_Context)optionValue;
1166            break;
1167        default:
1168            ALOGV("VideoEditorVideoEncoder_setOption: unsupported optionId 0x%X",
1169                optionID);
1170            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID);
1171            break;
1172    }
1173
1174cleanUp:
1175    if ( M4NO_ERROR == err ) {
1176        ALOGV("VideoEditorVideoEncoder_setOption no error");
1177    } else {
1178        ALOGV("VideoEditorVideoEncoder_setOption ERROR 0x%X", err);
1179    }
1180    ALOGV("VideoEditorVideoEncoder_setOption end");
1181    return err;
1182}
1183
1184M4OSA_ERR VideoEditorVideoEncoder_getOption(M4ENCODER_Context pContext,
1185        M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) {
1186    M4OSA_ERR err = M4NO_ERROR;
1187    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
1188
1189    ALOGV("VideoEditorVideoEncoder_getOption begin optinId 0x%X", optionID);
1190    // Input parameters check
1191    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
1192    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
1193
1194    switch( optionID ) {
1195        case M4ENCODER_kOptionID_EncoderHeader:
1196            VIDEOEDITOR_CHECK(
1197                    M4OSA_NULL != pEncoderContext->mHeader.pBuf, M4ERR_STATE);
1198            *(M4ENCODER_Header**)optionValue = &(pEncoderContext->mHeader);
1199            break;
1200        default:
1201            ALOGV("VideoEditorVideoEncoder_getOption: unsupported optionId 0x%X",
1202                optionID);
1203            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID);
1204            break;
1205    }
1206
1207cleanUp:
1208    if ( M4NO_ERROR == err ) {
1209        ALOGV("VideoEditorVideoEncoder_getOption no error");
1210    } else {
1211        ALOGV("VideoEditorVideoEncoder_getOption ERROR 0x%X", err);
1212    }
1213    return err;
1214}
1215
1216M4OSA_ERR VideoEditorVideoEncoder_getInterface(M4ENCODER_Format format,
1217        M4ENCODER_Format* pFormat,
1218        M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){
1219    M4OSA_ERR err = M4NO_ERROR;
1220
1221    // Input parameters check
1222    VIDEOEDITOR_CHECK(M4OSA_NULL != pFormat,           M4ERR_PARAMETER);
1223    VIDEOEDITOR_CHECK(M4OSA_NULL != pEncoderInterface, M4ERR_PARAMETER);
1224
1225    ALOGV("VideoEditorVideoEncoder_getInterface begin 0x%x 0x%x %d", pFormat,
1226        pEncoderInterface, mode);
1227
1228    SAFE_MALLOC(*pEncoderInterface, M4ENCODER_GlobalInterface, 1,
1229        "VideoEditorVideoEncoder");
1230
1231    *pFormat = format;
1232
1233    switch( format ) {
1234        case M4ENCODER_kH263:
1235            {
1236                (*pEncoderInterface)->pFctInit =
1237                    VideoEditorVideoEncoder_init_H263;
1238                break;
1239            }
1240        case M4ENCODER_kMPEG4:
1241            {
1242                (*pEncoderInterface)->pFctInit =
1243                    VideoEditorVideoEncoder_init_MPEG4;
1244                break;
1245            }
1246        case M4ENCODER_kH264:
1247            {
1248                (*pEncoderInterface)->pFctInit =
1249                    VideoEditorVideoEncoder_init_H264;
1250                break;
1251            }
1252        default:
1253            ALOGV("VideoEditorVideoEncoder_getInterface : unsupported format %d",
1254                format);
1255            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER);
1256        break;
1257    }
1258    (*pEncoderInterface)->pFctOpen         = VideoEditorVideoEncoder_open;
1259    (*pEncoderInterface)->pFctStart        = VideoEditorVideoEncoder_start;
1260    (*pEncoderInterface)->pFctStop         = VideoEditorVideoEncoder_stop;
1261    (*pEncoderInterface)->pFctPause        = M4OSA_NULL;
1262    (*pEncoderInterface)->pFctResume       = M4OSA_NULL;
1263    (*pEncoderInterface)->pFctClose        = VideoEditorVideoEncoder_close;
1264    (*pEncoderInterface)->pFctCleanup      = VideoEditorVideoEncoder_cleanup;
1265    (*pEncoderInterface)->pFctRegulBitRate =
1266        VideoEditorVideoEncoder_regulBitRate;
1267    (*pEncoderInterface)->pFctEncode       = VideoEditorVideoEncoder_encode;
1268    (*pEncoderInterface)->pFctSetOption    = VideoEditorVideoEncoder_setOption;
1269    (*pEncoderInterface)->pFctGetOption    = VideoEditorVideoEncoder_getOption;
1270
1271cleanUp:
1272    if( M4NO_ERROR == err ) {
1273        ALOGV("VideoEditorVideoEncoder_getInterface no error");
1274    } else {
1275        *pEncoderInterface = M4OSA_NULL;
1276        ALOGV("VideoEditorVideoEncoder_getInterface ERROR 0x%X", err);
1277    }
1278    return err;
1279}
1280
1281extern "C" {
1282
1283M4OSA_ERR VideoEditorVideoEncoder_getInterface_H263(M4ENCODER_Format* pFormat,
1284        M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){
1285    return VideoEditorVideoEncoder_getInterface(M4ENCODER_kH263, pFormat,
1286            pEncoderInterface, mode);
1287}
1288
1289M4OSA_ERR VideoEditorVideoEncoder_getInterface_MPEG4(M4ENCODER_Format* pFormat,
1290        M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){
1291    return VideoEditorVideoEncoder_getInterface(M4ENCODER_kMPEG4, pFormat,
1292           pEncoderInterface, mode);
1293}
1294
1295M4OSA_ERR VideoEditorVideoEncoder_getInterface_H264(M4ENCODER_Format* pFormat,
1296        M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){
1297    return VideoEditorVideoEncoder_getInterface(M4ENCODER_kH264, pFormat,
1298           pEncoderInterface, mode);
1299
1300}
1301
1302}  // extern "C"
1303
1304}  // namespace android
1305