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