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