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