OSDN Git Service

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