To Enable Video Editor Encoder Buffer Sharing

BZ: 49310

The patch links the Intel encoder buffer sharing static library
in video editor. The implementation is placed in video HAL layer.

Original patches:
R3: 38063 BZ: 25225
    54576 BZ: 43092
    49988 BZ: 34584 35665

Change-Id: I8a1fb9208eeda66c470a29785cdb0a1acd289b5f
Signed-off-by: wfeng6 <wei.feng@intel.com>
Reviewed-on: http://android.intel.com:8080/59446
Reviewed-by: Ding, Haitao <haitao.ding@intel.com>
Tested-by: Ding, Haitao <haitao.ding@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
diff --git a/Android.mk b/Android.mk
index 369ab19..825caaa 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,4 +15,5 @@
 include $(VENDORS_INTEL_MRST_LIBMIX_ROOT)/frameworks/asf_extractor/Android.mk
 include $(VENDORS_INTEL_MRST_LIBMIX_ROOT)/frameworks/vavideodecoder/Android.mk
 include $(VENDORS_INTEL_MRST_LIBMIX_ROOT)/frameworks/libI420colorconvert/Android.mk
+include $(VENDORS_INTEL_MRST_LIBMIX_ROOT)/frameworks/videoedit/Android.mk
 endif
diff --git a/frameworks/videoedit/Android.mk b/frameworks/videoedit/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/frameworks/videoedit/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/frameworks/videoedit/stagefrightshells/Android.mk b/frameworks/videoedit/stagefrightshells/Android.mk
new file mode 100644
index 0000000..2e7c5ef
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/Android.mk
@@ -0,0 +1,75 @@
+#
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+    MediaBufferPuller.cpp \
+    VideoEditorVideoDecoder.cpp \
+    VideoEditorAudioDecoder.cpp \
+    VideoEditorMp3Reader.cpp \
+    VideoEditor3gpReader.cpp \
+    VideoEditorBuffer.c \
+    VideoEditorVideoEncoder.cpp \
+    VideoEditorAudioEncoder.cpp \
+    IntelVideoEditorUtils.cpp \
+    IntelVideoEditorEncoderSource.cpp \
+    IntelVideoEditorAVCEncoder.cpp \
+    IntelVideoEditorH263Encoder.cpp
+
+LOCAL_C_INCLUDES += \
+    $(TOP)/frameworks/av/media/libmediaplayerservice \
+    $(TOP)/frameworks/av/media/libstagefright \
+    $(TOP)/frameworks/av/media/libstagefright/include \
+    $(TOP)/frameworks/av/media/libstagefright/rtsp \
+    $(call include-path-for, corecg graphics) \
+    $(TOP)/frameworks/av/libvideoeditor/lvpp \
+    $(TOP)/frameworks/av/libvideoeditor/osal/inc \
+    $(TOP)/frameworks/av/libvideoeditor/vss/inc \
+    $(TOP)/frameworks/av/libvideoeditor/vss/common/inc \
+    $(TOP)/frameworks/av/libvideoeditor/vss/mcs/inc \
+    $(TOP)/frameworks/av/libvideoeditor/vss/stagefrightshells/inc \
+    $(TOP)/frameworks/native/include/media/editor \
+    $(TOP)/frameworks/native/include/media/openmax \
+    $(TARGET_OUT_HEADERS)/libsharedbuffer \
+    $(TARGET_OUT_HEADERS)/libmix_videoencoder \
+    $(TARGET_OUT_HEADERS)/libva
+
+LOCAL_SHARED_LIBRARIES :=     \
+    libcutils                 \
+    libutils                  \
+    libmedia                  \
+    libbinder                 \
+    libstagefright            \
+    libstagefright_foundation \
+    libstagefright_omx        \
+    libgui                    \
+    libvideoeditor_osal       \
+    libvideoeditorplayer      \
+    libsharedbuffer
+
+LOCAL_CFLAGS += \
+
+LOCAL_STATIC_LIBRARIES := \
+    libstagefright_color_conversion
+
+
+LOCAL_MODULE:= libvideoeditor_stagefrightshells_intel
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/frameworks/videoedit/stagefrightshells/IntelVideoEditorAVCEncoder.cpp b/frameworks/videoedit/stagefrightshells/IntelVideoEditorAVCEncoder.cpp
new file mode 100644
index 0000000..9681bba
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/IntelVideoEditorAVCEncoder.cpp
@@ -0,0 +1,468 @@
+/*
+ * INTEL CONFIDENTIAL
+ * Copyright 2010-2011 Intel Corporation All Rights Reserved.
+
+ * The source code, information and material ("Material") contained herein is owned
+ * by Intel Corporation or its suppliers or licensors, and title to such Material
+ * remains with Intel Corporation or its suppliers or licensors. The Material contains
+ * proprietary information of Intel or its suppliers and licensors. The Material is
+ * protected by worldwide copyright laws and treaty provisions. No part of the Material
+ * may be used, copied, reproduced, modified, published, uploaded, posted, transmitted,
+ * distributed or disclosed in any way without Intel's prior express written permission.
+ * No license under any patent, copyright or other intellectual property rights in the
+ * Material is granted to or conferred upon you, either expressly, by implication, inducement,
+ * estoppel or otherwise. Any license under such intellectual property rights must be express
+ * and approved by Intel in writing.
+
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any
+ * other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way.
+ */
+
+#define LOG_NDEBUG 1
+#define LOG_TAG "IntelVideoEditorAVCEncoder"
+#include <utils/Log.h>
+#include "OMX_Video.h"
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include "IntelVideoEditorAVCEncoder.h"
+#include <media/stagefright/foundation/ADebug.h>
+
+#define INIT_BUF_FULLNESS_RATIO 0.6
+#define MIN_INTRA_PERIOD        30
+#define SHORT_INTRA_PERIOD (mVideoFrameRate)
+#define MEDIUM_INTRA_PERIOD (2*mVideoFrameRate)
+#define LONG_INTRA_PERIOD (4*mVideoFrameRate)
+#define LOW_QUALITY_BITRATE         2000000
+#define MEDIUM_QUALITY_BITRATE      5000000
+#define BITRATE_1M                  1000000
+#define BITRATE_2M                  2000000
+#define BITRATE_4M                  4000000
+#define BITRATE_5M                  5000000
+
+namespace android {
+
+IntelVideoEditorAVCEncoder::IntelVideoEditorAVCEncoder(
+        const sp<MediaSource>& source,
+        const sp<MetaData>& meta)
+    : mSource(source),
+      mMeta(meta),
+      mUseSyncMode(0),
+      mStarted(false),
+      mFirstFrame(true),
+      mFrameCount(0),
+      mVAEncoder(NULL),
+      mOutBufGroup(NULL),
+      mLastInputBuffer(NULL) {
+
+    LOGV("Construct IntelVideoEditorAVCEncoder");
+}
+
+IntelVideoEditorAVCEncoder::~IntelVideoEditorAVCEncoder() {
+    LOGV("Destruct IntelVideoEditorAVCEncoder");
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t IntelVideoEditorAVCEncoder::initCheck(const sp<MetaData>& meta) {
+    LOGV("initCheck");
+
+    Encode_Status   encStatus;
+
+    sp<MetaData> sourceFormat = mSource->getFormat();
+
+    CHECK(sourceFormat->findInt32(kKeyWidth, &mVideoWidth));
+    CHECK(sourceFormat->findInt32(kKeyHeight, &mVideoHeight));
+    CHECK(sourceFormat->findInt32(kKeyFrameRate, &mVideoFrameRate));
+    CHECK(sourceFormat->findInt32(kKeyColorFormat, &mVideoColorFormat));
+
+    CHECK(sourceFormat->findInt32(kKeyBitRate, &mVideoBitRate));
+
+    // Tune the output bitrates to improve the quality
+    if (mVideoBitRate < BITRATE_1M) {
+        mVideoBitRate = BITRATE_1M;
+        if (mVideoHeight > 720) {
+            mVideoBitRate = BITRATE_4M;
+        }
+        else if (mVideoHeight > 480)
+        {
+            mVideoBitRate = BITRATE_2M;
+        }
+    }
+    else if (mVideoBitRate < BITRATE_4M) {
+        if (mVideoHeight > 720) {
+            mVideoBitRate = BITRATE_5M;
+        }
+        else if (mVideoHeight > 480) {
+            mVideoBitRate = BITRATE_4M;
+        }
+    }
+
+    LOGI("mVideoWidth = %d, mVideoHeight = %d, mVideoFrameRate = %d, mVideoColorFormat = %d, mVideoBitRate = %d",
+        mVideoWidth, mVideoHeight, mVideoFrameRate, mVideoColorFormat, mVideoBitRate);
+
+    if (mVideoColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
+        LOGE("Color format %d is not supported", mVideoColorFormat);
+        return BAD_VALUE;
+    }
+
+    mFrameSize = mVideoHeight* mVideoWidth* 1.5;
+
+    /*
+     * SET PARAMS FOR THE ENCODER BASED ON THE METADATA
+     * */
+    encStatus = mVAEncoder->getParameters(&mEncParamsCommon);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("got encoder params");
+
+    mEncParamsCommon.resolution.width = mVideoWidth;
+    mEncParamsCommon.resolution.height= mVideoHeight;
+    mEncParamsCommon.frameRate.frameRateNum = mVideoFrameRate;
+    mEncParamsCommon.frameRate.frameRateDenom = 1;
+    mEncParamsCommon.rcMode = RATE_CONTROL_VBR;
+    mEncParamsCommon.rcParams.bitRate = mVideoBitRate;
+    mEncParamsCommon.rawFormat =  RAW_FORMAT_NV12;
+
+    mEncParamsCommon.rcParams.minQP  = 0;
+    mEncParamsCommon.rcParams.initQP = 0;
+
+    if (mVideoBitRate < LOW_QUALITY_BITRATE) {
+        mEncParamsCommon.intraPeriod = LONG_INTRA_PERIOD;
+    }
+    else if (mVideoBitRate < MEDIUM_QUALITY_BITRATE) {
+        mEncParamsCommon.intraPeriod = MEDIUM_INTRA_PERIOD;
+    }
+    else {
+        mEncParamsCommon.intraPeriod = SHORT_INTRA_PERIOD;
+    }
+    if (mEncParamsCommon.intraPeriod < MIN_INTRA_PERIOD) {
+        mEncParamsCommon.intraPeriod = MIN_INTRA_PERIOD;
+    }
+
+    mEncParamsCommon.syncEncMode = mUseSyncMode;
+    mFrameCount = 0;
+
+    // All luma and chroma block edges of the slice are filtered
+    mEncParamsCommon.disableDeblocking = 0;
+
+    encStatus = mVAEncoder->setParameters(&mEncParamsCommon);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("new encoder params set");
+
+    encStatus = mVAEncoder->getParameters(&mEncParamsH264);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("got H264 encoder params ");
+
+    mEncParamsH264.idrInterval = 1;
+    mEncParamsH264.sliceNum.iSliceNum = 2;
+    mEncParamsH264.sliceNum.pSliceNum = 2;
+
+    // If the bitrate is low, we set the slice number to 1 in one frame to avoid visible boundary
+    if (mVideoBitRate < LOW_QUALITY_BITRATE) {
+        mEncParamsH264.sliceNum.iSliceNum = 1;
+        mEncParamsH264.sliceNum.pSliceNum = 1;
+    }
+    mEncParamsH264.VUIFlag = 0;
+
+    encStatus = mVAEncoder->setParameters(&mEncParamsH264);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("new  H264 encoder params set");
+
+    VideoParamsHRD hrdParam;
+    encStatus = mVAEncoder->getParameters(&hrdParam);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("got encoder hrd params ");
+
+    hrdParam.bufferSize = mVideoBitRate;
+    hrdParam.initBufferFullness = hrdParam.bufferSize * INIT_BUF_FULLNESS_RATIO;
+
+    encStatus = mVAEncoder->setParameters(&hrdParam);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("new  encoder hard params set");
+
+    mOutBufGroup = new MediaBufferGroup();
+    CHECK(mOutBufGroup != NULL);
+
+    return OK;
+}
+
+status_t IntelVideoEditorAVCEncoder::start(MetaData *params) {
+    LOGV("start");
+    status_t ret = OK;
+
+    if (mStarted) {
+        LOGW("Call start() when encoder already started");
+        return OK;
+    }
+
+    mSource->start(params);
+
+    mVAEncoder = createVideoEncoder(MEDIA_MIMETYPE_VIDEO_AVC);
+
+    if (mVAEncoder == NULL) {
+        LOGE("Fail to create video encoder");
+        return NO_MEMORY;
+    }
+    mInitCheck = initCheck(mMeta);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    uint32_t maxSize;
+    mVAEncoder->getMaxOutSize(&maxSize);
+
+    LOGV("allocating output buffers of size %d",maxSize);
+    for (int i = 0; i < OUTPUT_BUFFERS; i++ ) {
+        mOutBufGroup->add_buffer(new MediaBuffer(maxSize));
+    }
+
+    if (OK != getSharedBuffers()) {
+        LOGE("Failed to get the shared buffers from encoder ");
+        return UNKNOWN_ERROR;
+    }
+
+    Encode_Status err;
+    err = mVAEncoder->start();
+    if (err!= ENCODE_SUCCESS) {
+        LOGE("Failed to initialize the encoder: %d", err);
+        return UNKNOWN_ERROR;
+    }
+
+    if (OK != setSharedBuffers()) {
+        LOGE("Failed to setup the shared buffers");
+        return UNKNOWN_ERROR;
+    }
+
+    mStarted = true;
+    LOGV("start- DONE");
+    return OK;
+}
+
+int IntelVideoEditorAVCEncoder::SBShutdownFunc(void* arg)
+{
+    LOGV("IntelVideoEditorAVCEncoder::SBShutdownFunc begin()");
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+    int error = r->sourceExitSharingMode();
+    LOGV("sourceExitSharingMode returns %d",error);
+    return 0;
+}
+
+status_t IntelVideoEditorAVCEncoder::stop() {
+    LOGV("stop");
+    if (!mStarted) {
+        LOGW("Call stop() when encoder has not started");
+        return OK;
+    }
+
+    if (mOutBufGroup) {
+        delete mOutBufGroup;
+        mOutBufGroup = NULL;
+    }
+    if (mLastInputBuffer!=NULL) {
+        mLastInputBuffer->release();
+    }
+    mLastInputBuffer = NULL;
+
+    /* call mSource->stop in a new thread, so the source
+        can do its end of shared buffer shutdown */
+
+    androidCreateThread(SBShutdownFunc,this);
+    LOGV("Successfull create thread!");
+
+    /* do encoder's buffer sharing shutdown */
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+    int err = r->encoderExitSharingMode();
+    LOGV("encoderExitSharingMode returned %d\n", err);
+
+    mSource->stop();
+
+    err = r->encoderRequestToDisableSharingMode();
+    LOGV("encoderRequestToDisableSharingMode returned %d\n", err);
+
+    /* libsharedbuffer wants the source to call this after the encoder calls
+     * encoderRequestToDisableSharingMode. Instead of doing complicated
+     * synchronization, let's just call this ourselves on the source's
+     * behalf. */
+    err = r->sourceRequestToDisableSharingMode();
+    LOGV("sourceRequestToDisableSharingMode returned %d\n", err);
+
+    releaseVideoEncoder(mVAEncoder);
+    mVAEncoder = NULL;
+
+    mStarted = false;
+    LOGV("stop - DONE");
+
+    return OK;
+}
+
+sp<MetaData> IntelVideoEditorAVCEncoder::getFormat() {
+
+    sp<MetaData> format = new MetaData;
+    format->setInt32(kKeyWidth, mVideoWidth);
+    format->setInt32(kKeyHeight, mVideoHeight);
+    format->setInt32(kKeyBitRate, mVideoBitRate);
+    format->setInt32(kKeySampleRate, mVideoFrameRate);
+    format->setInt32(kKeyColorFormat, mVideoColorFormat);
+    format->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+    format->setCString(kKeyDecoderComponent, "IntelVideoEditorAVCEncoder");
+    return format;
+}
+
+status_t IntelVideoEditorAVCEncoder::read(MediaBuffer **out, const ReadOptions *options) {
+
+    status_t err;
+    Encode_Status encRet;
+    MediaBuffer *tmpIn;
+    int64_t timestamp = 0;
+    CHECK(!options);
+    mReadOptions = options;
+    *out = NULL;
+
+    LOGV("IntelVideoEditorAVCEncoder::read start");
+
+    do {
+        err = mSource->read(&tmpIn, NULL);
+        if (err == INFO_FORMAT_CHANGED) {
+            stop();
+            start(NULL);
+        }
+    } while (err == INFO_FORMAT_CHANGED);
+
+    if (err == ERROR_END_OF_STREAM) {
+        return err;
+    }
+    else if (err != OK) {
+        LOGE("Failed to read input video frame: %d", err);
+        return err;
+    }
+
+
+    VideoEncRawBuffer vaInBuf;
+
+    vaInBuf.data = (uint8_t *)tmpIn->data();
+    vaInBuf.size = tmpIn->size();
+
+    tmpIn->meta_data()->findInt64(kKeyTime, (int64_t *)&(vaInBuf.timeStamp));
+    LOGV("Encoding: buffer %p, size = %d, ts= %llu",vaInBuf.data, vaInBuf.size, vaInBuf.timeStamp);
+
+    encRet = mVAEncoder->encode(&vaInBuf);
+    if (encRet != ENCODE_SUCCESS) {
+        LOGE("Failed to encode input video frame: %d", encRet);
+        tmpIn->release();
+        return UNKNOWN_ERROR;
+    }
+
+    if (mLastInputBuffer != NULL) {
+        mLastInputBuffer->release();
+        mLastInputBuffer = NULL;
+    }
+    mLastInputBuffer = tmpIn;
+
+    LOGV("Encoding Done, getting output buffer 	");
+    MediaBuffer *outputBuffer;
+
+    CHECK(mOutBufGroup->acquire_buffer(&outputBuffer) == OK);
+    LOGV("Waiting for outputbuffer");
+    VideoEncOutputBuffer vaOutBuf;
+    vaOutBuf.bufferSize = outputBuffer->size();
+    vaOutBuf.dataSize = 0;
+    vaOutBuf.data = (uint8_t *) outputBuffer->data();
+    vaOutBuf.format = OUTPUT_EVERYTHING;
+
+    if (mFirstFrame) {
+        LOGV("mFirstFrame\n");
+        encRet = mVAEncoder->getOutput(&vaOutBuf);
+        if (encRet != ENCODE_SUCCESS) {
+            LOGE("Failed to retrieve encoded video frame: %d", encRet);
+            outputBuffer->release();
+            return UNKNOWN_ERROR;
+        }
+        outputBuffer->meta_data()->setInt32(kKeyIsCodecConfig,true);
+        outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame,true);
+        mFirstFrame = false;
+    } else {
+        vaOutBuf.format = OUTPUT_EVERYTHING;
+        encRet = mVAEncoder->getOutput(&vaOutBuf);
+        if (encRet != ENCODE_SUCCESS) {
+            LOGE("Failed to retrieve encoded video frame: %d", encRet);
+            outputBuffer->release();
+            return UNKNOWN_ERROR;
+        }
+        if (vaOutBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) {
+            outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame,true);
+        }
+    }
+    timestamp = vaInBuf.timeStamp;
+
+    LOGV("Got it! data= %p, ts=%llu size =%d", vaOutBuf.data, timestamp, vaOutBuf.dataSize);
+
+    outputBuffer->set_range(0, vaOutBuf.dataSize);
+    outputBuffer->meta_data()->setInt64(kKeyTime,timestamp);
+    *out = outputBuffer;
+
+    LOGV("IntelVideoEditorAVCEncoder::read end");
+    return OK;
+}
+
+status_t IntelVideoEditorAVCEncoder::getSharedBuffers() {
+
+    LOGV("getSharedBuffers begin");
+    Encode_Status encRet;
+    status_t ret = OK;
+
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+
+    if (r->encoderRequestToEnableSharingMode() == BS_SUCCESS) {
+        LOGV("Shared buffer mode available\n");
+    }
+    else {
+        LOGE("Request to enable sharing failed \n");
+        return UNKNOWN_ERROR;
+    }
+
+    for(int i = 0; i < INPUT_SHARED_BUFFERS; i++) {
+        VideoParamsUsrptrBuffer paramsUsrptrBuffer;
+        paramsUsrptrBuffer.type = VideoParamsTypeUsrptrBuffer;
+        paramsUsrptrBuffer.size =  sizeof(VideoParamsUsrptrBuffer);
+        paramsUsrptrBuffer.expectedSize = mFrameSize;
+        paramsUsrptrBuffer.format = STRING_TO_FOURCC("NV12");
+        paramsUsrptrBuffer.width = mVideoWidth;
+        paramsUsrptrBuffer.height = mVideoHeight;
+        LOGV("Share buffer request=");
+        encRet = mVAEncoder->getParameters(&paramsUsrptrBuffer);
+        if (encRet != ENCODE_SUCCESS  ) {
+            LOGE("could not allocate input surface from the encoder %d", encRet);
+            ret = NO_MEMORY;
+            break;
+        }
+        mSharedBufs[i].allocatedSize = paramsUsrptrBuffer.actualSize;
+        mSharedBufs[i].height = mVideoHeight;
+        mSharedBufs[i].width = mVideoWidth;
+        mSharedBufs[i].pointer = paramsUsrptrBuffer.usrPtr;
+        mSharedBufs[i].stride = paramsUsrptrBuffer.stride;
+    }
+    LOGV("getSharedBuffers end");
+    return ret;
+}
+
+status_t IntelVideoEditorAVCEncoder::setSharedBuffers() {
+    LOGV("setSharedBuffers");
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+
+    if (r->encoderSetSharedBuffer(mSharedBufs,INPUT_SHARED_BUFFERS) != BS_SUCCESS) {
+        LOGE("encoderSetSharedBuffer failed \n");
+        return UNKNOWN_ERROR;
+    }
+
+    if (r->encoderEnterSharingMode() != BS_SUCCESS) {
+        LOGE("sourceEnterSharingMode failed\n");
+        return UNKNOWN_ERROR;
+    }
+    return OK;
+}
+
+}
diff --git a/frameworks/videoedit/stagefrightshells/IntelVideoEditorAVCEncoder.h b/frameworks/videoedit/stagefrightshells/IntelVideoEditorAVCEncoder.h
new file mode 100644
index 0000000..29fd1c7
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/IntelVideoEditorAVCEncoder.h
@@ -0,0 +1,85 @@
+/*
+ * INTEL CONFIDENTIAL
+ * Copyright 2010-2011 Intel Corporation All Rights Reserved.
+
+ * The source code, information and material ("Material") contained herein is owned
+ * by Intel Corporation or its suppliers or licensors, and title to such Material
+ * remains with Intel Corporation or its suppliers or licensors. The Material contains
+ * proprietary information of Intel or its suppliers and licensors. The Material is
+ * protected by worldwide copyright laws and treaty provisions. No part of the Material
+ * may be used, copied, reproduced, modified, published, uploaded, posted, transmitted,
+ * distributed or disclosed in any way without Intel's prior express written permission.
+ * No license under any patent, copyright or other intellectual property rights in the
+ * Material is granted to or conferred upon you, either expressly, by implication, inducement,
+ * estoppel or otherwise. Any license under such intellectual property rights must be express
+ * and approved by Intel in writing.
+
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any
+ * other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way.
+ */
+
+#ifndef INTELVIDEOEDITORAVCENCODER_H
+#define INTELVIDEOEDITORAVCENCODER_H
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+#include "va/va.h"
+#include "VideoEncoderHost.h"
+#include <IntelBufferSharing.h>
+
+namespace android {
+struct IntelVideoEditorAVCEncoder :  public MediaSource {
+    IntelVideoEditorAVCEncoder(const sp<MediaSource> &source,
+            const sp<MetaData>& meta);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options);
+
+
+protected:
+    virtual ~IntelVideoEditorAVCEncoder();
+
+private:
+    sp<MediaSource> mSource;
+    sp<MetaData>    mMeta;
+
+    int32_t  mVideoWidth;
+    int32_t  mVideoHeight;
+    int32_t  mFrameSize;
+    int32_t  mVideoFrameRate;
+    int32_t  mVideoBitRate;
+    int32_t  mVideoColorFormat;
+    int32_t  mUseSyncMode;
+    status_t mInitCheck;
+    bool     mStarted;
+    bool     mFirstFrame;
+    int32_t  mFrameCount;
+    static const int OUTPUT_BUFFERS = 6;
+    static const int INPUT_SHARED_BUFFERS = 8;
+    IVideoEncoder         *mVAEncoder;
+    VideoParamsCommon     mEncParamsCommon;
+    VideoParamsAVC        mEncParamsH264;
+    SharedBufferType      mSharedBufs[INPUT_SHARED_BUFFERS];
+    const ReadOptions     *mReadOptions;
+    MediaBufferGroup      *mOutBufGroup;   /* group of output buffers*/
+    MediaBuffer           *mLastInputBuffer;
+
+private:
+    status_t initCheck(const sp<MetaData>& meta);
+    int32_t calcBitrate(int width, int height);
+    status_t getSharedBuffers();
+    status_t setSharedBuffers();
+    static int SBShutdownFunc(void* arg);
+
+    IntelVideoEditorAVCEncoder(const IntelVideoEditorAVCEncoder &);
+    IntelVideoEditorAVCEncoder &operator=(const IntelVideoEditorAVCEncoder &);
+};
+};
+#endif
+
diff --git a/frameworks/videoedit/stagefrightshells/IntelVideoEditorEncoderSource.cpp b/frameworks/videoedit/stagefrightshells/IntelVideoEditorEncoderSource.cpp
new file mode 100644
index 0000000..e2c16ed
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/IntelVideoEditorEncoderSource.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * INTEL CONFIDENTIAL
+ * Copyright 2010-2011 Intel Corporation All Rights Reserved.
+
+ * The source code, information and material ("Material") contained herein is owned
+ * by Intel Corporation or its suppliers or licensors, and title to such Material
+ * remains with Intel Corporation or its suppliers or licensors. The Material contains
+ * proprietary information of Intel or its suppliers and licensors. The Material is
+ * protected by worldwide copyright laws and treaty provisions. No part of the Material
+ * may be used, copied, reproduced, modified, published, uploaded, posted, transmitted,
+ * distributed or disclosed in any way without Intel's prior express written permission.
+ * No license under any patent, copyright or other intellectual property rights in the
+ * Material is granted to or conferred upon you, either expressly, by implication, inducement,
+ * estoppel or otherwise. Any license under such intellectual property rights must be express
+ * and approved by Intel in writing.
+
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any
+ * other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IntelVideoEditorEncoderSource"
+#include "utils/Log.h"
+
+#include "IntelVideoEditorEncoderSource.h"
+#include "utils/Vector.h"
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <IntelBufferSharing.h>
+
+namespace android {
+sp<IntelVideoEditorEncoderSource> IntelVideoEditorEncoderSource::Create(
+    const sp<MetaData> &format) {
+
+    sp<IntelVideoEditorEncoderSource> aSource =
+        new IntelVideoEditorEncoderSource(format);
+    return aSource;
+}
+
+IntelVideoEditorEncoderSource::IntelVideoEditorEncoderSource(
+    const sp<MetaData> &format):
+        mGroup(NULL),
+        mUseSharedBuffers(false),
+        mFirstBufferLink(NULL),
+        mLastBufferLink(NULL),
+        mNbBuffer(0),
+        mIsEOS(false),
+        mState(CREATED),
+        mEncFormat(format) {
+    LOGV("IntelVideoEditorEncoderSource::IntelVideoEditorEncoderSource");
+}
+
+IntelVideoEditorEncoderSource::~IntelVideoEditorEncoderSource() {
+
+    // Safety clean up
+    if( STARTED == mState ) {
+        stop();
+    }
+}
+
+status_t IntelVideoEditorEncoderSource::start(MetaData *meta) {
+    Mutex::Autolock autolock(mLock);
+    status_t err = OK;
+
+    LOGV("IntelVideoEditorEncoderSource::start() begin");
+
+    if( CREATED != mState ) {
+        LOGV("IntelVideoEditorEncoderSource::start: invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+    mState = STARTED;
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+    if (r->sourceRequestToEnableSharingMode() == BS_SUCCESS) {
+        LOGI("Shared buffer mode available\n");
+        mUseSharedBuffers = true;
+        mGroup = NULL;
+    }
+    else
+    {
+        LOGE("Shared buffer mode not available\n");
+        return UNKNOWN_ERROR;
+    }
+    LOGV("IntelVideoEditorEncoderSource::start() END (0x%x)", err);
+    return err;
+}
+
+status_t IntelVideoEditorEncoderSource::getSharedBuffers()
+{
+    Mutex::Autolock autolock(mLock);
+
+    LOGV("IntelVideoEditorEncoderSource::getSharedBuffers begin");
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+    SharedBufferType *bufs = NULL;
+    int buf_cnt = 0;
+
+    if (r->sourceEnterSharingMode() != BS_SUCCESS) {
+        LOGE("sourceEnterSharingMode failed\n");
+        return UNKNOWN_ERROR;
+    }
+
+    if (r->sourceGetSharedBuffer(NULL, &buf_cnt) != BS_SUCCESS) {
+        LOGE("sourceGetSharedBuffer failed, unable to get buffer count\n");
+        return UNKNOWN_ERROR;
+    }
+
+    bufs = new SharedBufferType[buf_cnt];
+    if (r->sourceGetSharedBuffer(bufs, &buf_cnt) != BS_SUCCESS) {
+        LOGE("sourceGetSharedBuffer failed, unable to retrieve buffers\n");
+        delete [] bufs;
+        return UNKNOWN_ERROR;
+    }
+
+    mGroup = new MediaBufferGroup();
+
+    for (int n = 0; n < buf_cnt; n++)
+    {
+        mGroup->add_buffer(new MediaBuffer(bufs[n].pointer, bufs[n].allocatedSize));
+    }
+
+    delete [] bufs;
+
+    LOGV("IntelVideoEditorAVCEncoderSource::getSharedBuffers end");
+    return OK;
+}
+
+
+status_t IntelVideoEditorEncoderSource::stop() {
+
+    LOGV("IntelVideoEditorAVCEncoderSource::stop() begin");
+    status_t err = OK;
+
+    if( STARTED != mState ) {
+        LOGV("IntelVideoEditorAVCEncoderSource::stop: invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+
+    if (mUseSharedBuffers) {
+        if (mGroup) {
+            delete mGroup;
+            mGroup = NULL;
+        }
+        mUseSharedBuffers = false;
+    }
+
+    int32_t i = 0;
+    MediaBufferChain* tmpLink = NULL;
+    while( mFirstBufferLink ) {
+        i++;
+        tmpLink = mFirstBufferLink;
+        mFirstBufferLink = mFirstBufferLink->nextLink;
+        delete tmpLink;
+    }
+    LOGV("IntelVideoEditorEncoderSource::stop : %d buffer remained", i);
+    mFirstBufferLink = NULL;
+    mLastBufferLink = NULL;
+    mState = CREATED;
+
+    LOGV("IntelVideoEditorEncoderSource::stop() END (0x%x)", err);
+    return err;
+}
+
+sp<MetaData> IntelVideoEditorEncoderSource::getFormat() {
+
+    LOGV("IntelVideoEditorEncoderSource::getFormat");
+    return mEncFormat;
+}
+
+status_t IntelVideoEditorEncoderSource::read(MediaBuffer **buffer,
+        const ReadOptions *options) {
+    Mutex::Autolock autolock(mLock);
+
+    LOGV("IntelVideoEditorEncoderSource::read() begin");
+
+    MediaSource::ReadOptions readOptions;
+    status_t err = OK;
+    MediaBufferChain* tmpLink = NULL;
+
+    if ( STARTED != mState ) {
+        LOGV("IntelVideoEditorEncoderSource::read: invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+
+    while (mFirstBufferLink == NULL && !mIsEOS) {
+        LOGV("Wait for buffer in IntelVideoEditorEncoderSource::read()");
+        mBufferCond.wait(mLock);
+    }
+
+    LOGV("Get the buffer in IntelVideoEditorEncoderSource::read()!");
+
+    // End of stream?
+    if (mFirstBufferLink == NULL) {
+        *buffer = NULL;
+        LOGV("IntelVideoEditorEncoderSource::read : EOS");
+        return ERROR_END_OF_STREAM;
+    }
+
+    // Get a buffer from the chain
+    *buffer = mFirstBufferLink->buffer;
+    tmpLink = mFirstBufferLink;
+    mFirstBufferLink = mFirstBufferLink->nextLink;
+
+    if ( NULL == mFirstBufferLink) {
+        mLastBufferLink = NULL;
+    }
+    delete tmpLink;
+    mNbBuffer--;
+
+    LOGV("IntelVideoEditorEncoderSource::read() END (0x%x)", err);
+    return err;
+}
+
+int32_t IntelVideoEditorEncoderSource::storeBuffer(MediaBuffer *buffer) {
+    Mutex::Autolock autolock(mLock);
+
+    LOGV("IntelVideoEditorEncoderSource::storeBuffer() begin");
+
+    status_t err = OK;
+
+    if( NULL == buffer ) {
+        LOGV("IntelVideoEditorEncoderSource::storeBuffer : reached EOS");
+        mIsEOS = true;
+    } else {
+        MediaBufferChain* newLink = new MediaBufferChain;
+        newLink->buffer = buffer;
+        newLink->nextLink = NULL;
+        if( NULL != mLastBufferLink ) {
+            mLastBufferLink->nextLink = newLink;
+        } else {
+            mFirstBufferLink = newLink;
+        }
+        mLastBufferLink = newLink;
+        mNbBuffer++;
+    }
+    mBufferCond.signal();
+    LOGV("IntelVideoEditorEncoderSource::storeBuffer() end");
+    return mNbBuffer;
+}
+
+int32_t IntelVideoEditorEncoderSource::requestBuffer(MediaBuffer **buffer) {
+    status_t err = OK;
+    LOGV("IntelVideoEditorEncoderSource::requestBuffer() begin");
+    if (!mGroup && mUseSharedBuffers) {
+        err = getSharedBuffers();
+        if (err != OK) {
+            LOGE("shared buffer setup failed\n");
+            return err;
+        }
+    }
+
+    err = mGroup->acquire_buffer(buffer);
+    LOGV("requestBuffer buffer addr = 0x%p",(uint8_t *)(*buffer)->data());
+    if (err != OK) {
+        LOGE("Fail to get shared buffers");
+        return UNKNOWN_ERROR;
+    }
+    LOGV("IntelVideoEditorEncoderSource::requestBuffer() end");
+    return err;
+}
+}
diff --git a/frameworks/videoedit/stagefrightshells/IntelVideoEditorEncoderSource.h b/frameworks/videoedit/stagefrightshells/IntelVideoEditorEncoderSource.h
new file mode 100644
index 0000000..2f76051
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/IntelVideoEditorEncoderSource.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * INTEL CONFIDENTIAL
+ * Copyright 2010-2011 Intel Corporation All Rights Reserved.
+
+ * The source code, information and material ("Material") contained herein is owned
+ * by Intel Corporation or its suppliers or licensors, and title to such Material
+ * remains with Intel Corporation or its suppliers or licensors. The Material contains
+ * proprietary information of Intel or its suppliers and licensors. The Material is
+ * protected by worldwide copyright laws and treaty provisions. No part of the Material
+ * may be used, copied, reproduced, modified, published, uploaded, posted, transmitted,
+ * distributed or disclosed in any way without Intel's prior express written permission.
+ * No license under any patent, copyright or other intellectual property rights in the
+ * Material is granted to or conferred upon you, either expressly, by implication, inducement,
+ * estoppel or otherwise. Any license under such intellectual property rights must be express
+ * and approved by Intel in writing.
+
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any
+ * other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way.
+ */
+
+#ifndef INTELVIDEOEDITORENCODERSOURCE_H
+#define INTELVIDEOEDITORENCODERSOURCE_H
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaBufferGroup.h>
+
+namespace android {
+struct IntelVideoEditorEncoderSource : public MediaSource {
+    public:
+        static sp<IntelVideoEditorEncoderSource> Create(
+            const sp<MetaData> &format);
+        virtual status_t start(MetaData *params = NULL);
+        virtual status_t stop();
+        virtual sp<MetaData> getFormat();
+        virtual status_t read(MediaBuffer **buffer,
+            const ReadOptions *options = NULL);
+        virtual int32_t storeBuffer(MediaBuffer *buffer);
+        virtual int32_t requestBuffer(MediaBuffer **buffer);
+
+    protected:
+        virtual ~IntelVideoEditorEncoderSource();
+
+    private:
+        status_t getSharedBuffers();
+        MediaBufferGroup* mGroup;
+        bool mUseSharedBuffers;
+
+        struct MediaBufferChain {
+            MediaBuffer* buffer;
+            MediaBufferChain* nextLink;
+        };
+        enum State {
+            CREATED,
+            STARTED,
+            ERROR
+        };
+        IntelVideoEditorEncoderSource(const sp<MetaData> &format);
+
+        // Don't call me
+        IntelVideoEditorEncoderSource(const IntelVideoEditorEncoderSource &);
+        IntelVideoEditorEncoderSource &operator=(
+                const IntelVideoEditorEncoderSource &);
+
+        MediaBufferChain* mFirstBufferLink;
+        MediaBufferChain* mLastBufferLink;
+        int32_t           mNbBuffer;
+        bool              mIsEOS;
+        State             mState;
+        sp<MetaData>      mEncFormat;
+        Mutex             mLock;
+        Condition         mBufferCond;
+};
+}
+#endif
diff --git a/frameworks/videoedit/stagefrightshells/IntelVideoEditorH263Encoder.cpp b/frameworks/videoedit/stagefrightshells/IntelVideoEditorH263Encoder.cpp
new file mode 100644
index 0000000..02f91f3
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/IntelVideoEditorH263Encoder.cpp
@@ -0,0 +1,400 @@
+/*
+ * INTEL CONFIDENTIAL
+ * Copyright 2010-2011 Intel Corporation All Rights Reserved.
+
+ * The source code, information and material ("Material") contained herein is owned
+ * by Intel Corporation or its suppliers or licensors, and title to such Material
+ * remains with Intel Corporation or its suppliers or licensors. The Material contains
+ * proprietary information of Intel or its suppliers and licensors. The Material is
+ * protected by worldwide copyright laws and treaty provisions. No part of the Material
+ * may be used, copied, reproduced, modified, published, uploaded, posted, transmitted,
+ * distributed or disclosed in any way without Intel's prior express written permission.
+ * No license under any patent, copyright or other intellectual property rights in the
+ * Material is granted to or conferred upon you, either expressly, by implication, inducement,
+ * estoppel or otherwise. Any license under such intellectual property rights must be express
+ * and approved by Intel in writing.
+
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any
+ * other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way.
+ */
+
+#define LOG_NDEBUG 1
+#define LOG_TAG "IntelVideoEditorH263Encoder"
+#include <utils/Log.h>
+#include "OMX_Video.h"
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include "IntelVideoEditorH263Encoder.h"
+#define INIT_BUF_FULLNESS_RATIO 0.8125
+#define INITIAL_INTRA_PERIOD (mVideoFrameRate * 2 / 3)
+#define NORMAL_INTRA_PERIOD (mVideoFrameRate * 3)
+
+namespace android {
+
+IntelVideoEditorH263Encoder::IntelVideoEditorH263Encoder(
+        const sp<MediaSource>& source,
+        const sp<MetaData>& meta)
+    : mSource(source),
+      mMeta(meta),
+      mUseSyncMode(0),
+      mStarted(false),
+      mFirstFrame(true),
+      mFrameCount(0),
+      mVAEncoder(NULL),
+      mOutBufGroup(NULL),
+      mLastInputBuffer(NULL) {
+
+    LOGV("Construct IntelVideoEditorH263Encoder");
+}
+
+IntelVideoEditorH263Encoder::~IntelVideoEditorH263Encoder() {
+    LOGV("Destruct IntelVideoEditorH263Encoder");
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t IntelVideoEditorH263Encoder::initCheck(const sp<MetaData>& meta) {
+    LOGV("initCheck");
+
+    Encode_Status   encStatus;
+
+    sp<MetaData> sourceFormat = mSource->getFormat();
+
+    CHECK(sourceFormat->findInt32(kKeyWidth, &mVideoWidth));
+    CHECK(sourceFormat->findInt32(kKeyHeight, &mVideoHeight));
+    CHECK(sourceFormat->findInt32(kKeyFrameRate, &mVideoFrameRate));
+    CHECK(sourceFormat->findInt32(kKeyColorFormat, &mVideoColorFormat));
+
+    CHECK(sourceFormat->findInt32(kKeyBitRate, &mVideoBitRate));
+    LOGV("mVideoWidth = %d, mVideoHeight = %d, mVideoFrameRate = %d, mVideoColorFormat = %d, mVideoBitRate = %d",
+        mVideoWidth, mVideoHeight, mVideoFrameRate, mVideoColorFormat, mVideoBitRate);
+    if (mVideoColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
+        LOGE("Color format %d is not supported", mVideoColorFormat);
+        return BAD_VALUE;
+    }
+    mFrameSize = mVideoHeight* mVideoWidth* 1.5;
+    /*
+     * SET PARAMS FOR THE ENCODER BASED ON THE METADATA
+     * */
+
+    encStatus = mVAEncoder->getParameters(&mEncParamsCommon);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("got encoder params");
+
+    mEncParamsCommon.resolution.width = mVideoWidth;
+    mEncParamsCommon.resolution.height= mVideoHeight;
+    mEncParamsCommon.frameRate.frameRateNum = mVideoFrameRate;
+    mEncParamsCommon.frameRate.frameRateDenom = 1;
+    mEncParamsCommon.rcMode = RATE_CONTROL_VBR;
+    mEncParamsCommon.rcParams.bitRate = mVideoBitRate;
+    mEncParamsCommon.rawFormat =  RAW_FORMAT_NV12;
+
+    // Set intra period to be a small value so that more IDR will be generated
+    // at the beginning of encoding. After a certain period of time, change intra period
+    // to be a bigger value, NORMAL_INTRA_PERIOD, in the rest of encoding.
+    // This is to workaround that it may take long to show video after clone / extended
+    // mode switching. During mode swithing, the current Widi stack sends RTSP command to
+    // set adaptor jitter buffer size. Widi adaptor may miss the first IDR during adaptor
+    // jitter buffer size setting. If the first IDR is missed, Widi adaptor must wait for
+    // the next IDR to arrive so that decoding can be started. If intra period is long,
+    // it will take long to show video.
+    mEncParamsCommon.intraPeriod = INITIAL_INTRA_PERIOD;
+
+    mEncParamsCommon.rcParams.minQP  = 1;
+    mEncParamsCommon.rcParams.initQP = 24;
+
+    mEncParamsCommon.syncEncMode = mUseSyncMode;
+    mFrameCount = 0;
+
+    encStatus = mVAEncoder->setParameters(&mEncParamsCommon);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("new encoder params set");
+
+    VideoParamsHRD hrdParam;
+    encStatus = mVAEncoder->getParameters(&hrdParam);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("got encoder hrd params ");
+
+    hrdParam.bufferSize = mVideoBitRate;
+    hrdParam.initBufferFullness = hrdParam.bufferSize * INIT_BUF_FULLNESS_RATIO;
+
+    encStatus = mVAEncoder->setParameters(&hrdParam);
+    CHECK(encStatus == ENCODE_SUCCESS);
+    LOGV("new  encoder hard params set");
+
+    mOutBufGroup = new MediaBufferGroup();
+    CHECK(mOutBufGroup != NULL);
+
+    return OK;
+}
+
+status_t IntelVideoEditorH263Encoder::start(MetaData *params) {
+    LOGV("start");
+    status_t ret = OK;
+
+    if (mStarted) {
+        LOGW("Call start() when encoder already started");
+        return OK;
+    }
+
+    mSource->start(params);
+
+    mVAEncoder = createVideoEncoder("video/h263");
+
+    if (mVAEncoder == NULL) {
+        LOGE("Fail to create video encoder");
+        return NO_MEMORY;
+    }
+    mInitCheck = initCheck(mMeta);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    uint32_t maxSize;
+    mVAEncoder->getMaxOutSize(&maxSize);
+
+    LOGV("allocating output buffers of size %d",maxSize);
+    for (int i = 0; i < OUTPUT_BUFFERS; i++ ) {
+        mOutBufGroup->add_buffer(new MediaBuffer(maxSize));
+    }
+
+    if (OK != getSharedBuffers()) {
+        LOGE("Failed to get the shared buffers from encoder ");
+        return UNKNOWN_ERROR;
+    }
+
+    Encode_Status err;
+    err = mVAEncoder->start();
+    if (err!= ENCODE_SUCCESS) {
+        LOGE("Failed to initialize the encoder: %d", err);
+        return UNKNOWN_ERROR;
+    }
+
+    if (OK != setSharedBuffers()) {
+        LOGE("Failed to setup the shared buffers");
+        return UNKNOWN_ERROR;
+    }
+
+    mStarted = true;
+    LOGV("start- DONE");
+    return OK;
+}
+
+int IntelVideoEditorH263Encoder::SBShutdownFunc(void* arg)
+{
+    LOGV("IntelVideoEditorAVCEncoder::SBShutdownFunc begin()");
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+    int error = r->sourceExitSharingMode();
+    LOGV("sourceExitSharingMode returns %d",error);
+    return 0;
+}
+
+status_t IntelVideoEditorH263Encoder::stop() {
+    LOGV("stop");
+    if (!mStarted) {
+        LOGW("Call stop() when encoder has not started");
+        return OK;
+    }
+
+    if (mOutBufGroup) {
+        delete mOutBufGroup;
+        mOutBufGroup = NULL;
+    }
+    if (mLastInputBuffer!=NULL) {
+        mLastInputBuffer->release();
+    }
+    mLastInputBuffer = NULL;
+
+    /* call mSource->stop in a new thread, so the source
+        can do its end of shared buffer shutdown */
+
+    androidCreateThread(SBShutdownFunc,this);
+    LOGV("Successfull create thread!");
+
+    /* do encoder's buffer sharing shutdown */
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+    int err = r->encoderExitSharingMode();
+    LOGV("encoderExitSharingMode returned %d\n", err);
+
+    mSource->stop();
+
+    err = r->encoderRequestToDisableSharingMode();
+    LOGV("encoderRequestToDisableSharingMode returned %d\n", err);
+
+    /* libsharedbuffer wants the source to call this after the encoder calls
+     * encoderRequestToDisableSharingMode. Instead of doing complicated
+     * synchronization, let's just call this ourselves on the source's
+     * behalf. */
+    err = r->sourceRequestToDisableSharingMode();
+    LOGV("sourceRequestToDisableSharingMode returned %d\n", err);
+
+    releaseVideoEncoder(mVAEncoder);
+    mVAEncoder = NULL;
+
+    mStarted = false;
+    LOGV("stop - DONE");
+
+    return OK;
+}
+
+sp<MetaData> IntelVideoEditorH263Encoder::getFormat() {
+    LOGV("getFormat");
+
+    sp<MetaData> format = new MetaData;
+    format->setInt32(kKeyWidth, mVideoWidth);
+    format->setInt32(kKeyHeight, mVideoHeight);
+    format->setInt32(kKeyBitRate, mVideoBitRate);
+    format->setInt32(kKeySampleRate, mVideoFrameRate);
+    format->setInt32(kKeyColorFormat, mVideoColorFormat);
+    format->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+    format->setCString(kKeyDecoderComponent, "IntelVideoEditorH263Encoder");
+    return format;
+}
+
+status_t IntelVideoEditorH263Encoder::read(MediaBuffer **out, const ReadOptions *options) {
+
+    status_t err;
+    Encode_Status encRet;
+    MediaBuffer *tmpIn;
+    int64_t timestamp = 0;
+    CHECK(!options);
+    mReadOptions = options;
+    *out = NULL;
+
+    LOGV("IntelVideoEditorAVCEncoder::read start");
+
+    do {
+        err = mSource->read(&tmpIn, NULL);
+        if (err == INFO_FORMAT_CHANGED) {
+            stop();
+            start(NULL);
+        }
+    } while (err == INFO_FORMAT_CHANGED);
+
+    if (err == ERROR_END_OF_STREAM) {
+        return err;
+    }
+    else if (err != OK) {
+        LOGE("Failed to read input video frame: %d", err);
+        return err;
+    }
+
+    VideoEncRawBuffer vaInBuf;
+
+    vaInBuf.data = (uint8_t *)tmpIn->data();
+    vaInBuf.size = tmpIn->size();
+
+    tmpIn->meta_data()->findInt64(kKeyTime, (int64_t *)&(vaInBuf.timeStamp));
+    LOGV("Encoding: buffer %p, size = %d, ts= %llu",vaInBuf.data, vaInBuf.size, vaInBuf.timeStamp);
+
+    encRet = mVAEncoder->encode(&vaInBuf);
+    if (encRet != ENCODE_SUCCESS) {
+        LOGE("Failed to encode input video frame: %d", encRet);
+        tmpIn->release();
+        return UNKNOWN_ERROR;
+    }
+
+    if (mLastInputBuffer != NULL) {
+        mLastInputBuffer->release();
+        mLastInputBuffer = NULL;
+    }
+    mLastInputBuffer = tmpIn;
+
+    LOGV("Encoding Done, getting output buffer 	");
+    MediaBuffer *outputBuffer;
+
+    CHECK(mOutBufGroup->acquire_buffer(&outputBuffer) == OK);
+    LOGV("Waiting for outputbuffer");
+    VideoEncOutputBuffer vaOutBuf;
+    vaOutBuf.bufferSize = outputBuffer->size();
+    vaOutBuf.dataSize = 0;
+    vaOutBuf.data = (uint8_t *) outputBuffer->data();
+    vaOutBuf.format = OUTPUT_EVERYTHING;
+
+    vaOutBuf.format = OUTPUT_EVERYTHING;
+    encRet = mVAEncoder->getOutput(&vaOutBuf);
+    if (encRet != ENCODE_SUCCESS) {
+        LOGE("Failed to retrieve encoded video frame: %d", encRet);
+        outputBuffer->release();
+        return UNKNOWN_ERROR;
+    }
+    if (vaOutBuf.flag & ENCODE_BUFFERFLAG_SYNCFRAME) {
+        outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame,true);
+    }
+
+    timestamp = vaInBuf.timeStamp;
+
+    LOGV("Got it! data= %p, ts=%llu size =%d", vaOutBuf.data, timestamp, vaOutBuf.dataSize);
+
+    outputBuffer->set_range(0, vaOutBuf.dataSize);
+    outputBuffer->meta_data()->setInt64(kKeyTime,timestamp);
+    *out = outputBuffer;
+    LOGV("IntelVideoEditorAVCEncoder::read end");
+    return OK;
+}
+
+status_t IntelVideoEditorH263Encoder::getSharedBuffers() {
+
+    LOGV("getSharedBuffers begin");
+    Encode_Status encRet;
+    status_t ret = OK;
+
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+
+    if (r->encoderRequestToEnableSharingMode() == BS_SUCCESS) {
+        LOGI("Shared buffer mode available\n");
+    }
+    else {
+        LOGE("Request to enable sharing failed \n");
+        return UNKNOWN_ERROR;
+    }
+
+    for(int i = 0; i < INPUT_SHARED_BUFFERS; i++) {
+        VideoParamsUsrptrBuffer paramsUsrptrBuffer;
+        paramsUsrptrBuffer.type = VideoParamsTypeUsrptrBuffer;
+        paramsUsrptrBuffer.size =  sizeof(VideoParamsUsrptrBuffer);
+        paramsUsrptrBuffer.expectedSize = mFrameSize;
+        paramsUsrptrBuffer.format = STRING_TO_FOURCC("NV12");
+        paramsUsrptrBuffer.width = mVideoWidth;
+        paramsUsrptrBuffer.height = mVideoHeight;
+        LOGV("Share buffer request=");
+        encRet = mVAEncoder->getParameters(&paramsUsrptrBuffer);
+        if (encRet != ENCODE_SUCCESS  ) {
+            LOGE("could not allocate input surface from the encoder %d", encRet);
+            ret = NO_MEMORY;
+            break;
+        }
+        mSharedBufs[i].allocatedSize = paramsUsrptrBuffer.actualSize;
+        mSharedBufs[i].height = mVideoHeight;
+        mSharedBufs[i].width = mVideoWidth;
+        mSharedBufs[i].pointer = paramsUsrptrBuffer.usrPtr;
+        mSharedBufs[i].stride = paramsUsrptrBuffer.stride;
+    }
+    LOGV("getSharedBuffers end");
+    return ret;
+}
+
+status_t IntelVideoEditorH263Encoder::setSharedBuffers() {
+
+    LOGV("setSharedBuffers");
+    sp<BufferShareRegistry> r = BufferShareRegistry::getInstance();
+
+    if (r->encoderSetSharedBuffer(mSharedBufs,INPUT_SHARED_BUFFERS) != BS_SUCCESS) {
+        LOGE("encoderSetSharedBuffer failed \n");
+        return UNKNOWN_ERROR;
+    }
+
+    if (r->encoderEnterSharingMode() != BS_SUCCESS) {
+        LOGE("sourceEnterSharingMode failed\n");
+        return UNKNOWN_ERROR;
+    }
+    return OK;
+}
+
+}
diff --git a/frameworks/videoedit/stagefrightshells/IntelVideoEditorH263Encoder.h b/frameworks/videoedit/stagefrightshells/IntelVideoEditorH263Encoder.h
new file mode 100644
index 0000000..0c4bee6
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/IntelVideoEditorH263Encoder.h
@@ -0,0 +1,84 @@
+/*
+ * INTEL CONFIDENTIAL
+ * Copyright 2010-2011 Intel Corporation All Rights Reserved.
+
+ * The source code, information and material ("Material") contained herein is owned
+ * by Intel Corporation or its suppliers or licensors, and title to such Material
+ * remains with Intel Corporation or its suppliers or licensors. The Material contains
+ * proprietary information of Intel or its suppliers and licensors. The Material is
+ * protected by worldwide copyright laws and treaty provisions. No part of the Material
+ * may be used, copied, reproduced, modified, published, uploaded, posted, transmitted,
+ * distributed or disclosed in any way without Intel's prior express written permission.
+ * No license under any patent, copyright or other intellectual property rights in the
+ * Material is granted to or conferred upon you, either expressly, by implication, inducement,
+ * estoppel or otherwise. Any license under such intellectual property rights must be express
+ * and approved by Intel in writing.
+
+ * Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any
+ * other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way.
+ */
+
+#ifndef INTELVIDEOEDITORH263ENCODER_H
+#define INTELVIDEOEDITORH263ENCODER_H
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+#include "va/va.h"
+#include "VideoEncoderHost.h"
+#include <IntelBufferSharing.h>
+
+namespace android {
+struct IntelVideoEditorH263Encoder :  public MediaSource {
+    IntelVideoEditorH263Encoder(const sp<MediaSource> &source,
+            const sp<MetaData>& meta);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options);
+
+
+protected:
+    virtual ~IntelVideoEditorH263Encoder();
+
+private:
+    sp<MediaSource> mSource;
+    sp<MetaData>    mMeta;
+
+    int32_t  mVideoWidth;
+    int32_t  mVideoHeight;
+    int32_t  mFrameSize;
+    int32_t  mVideoFrameRate;
+    int32_t  mVideoBitRate;
+    int32_t  mVideoColorFormat;
+    int32_t  mUseSyncMode;
+    status_t mInitCheck;
+    bool     mStarted;
+    bool     mFirstFrame;
+    int32_t  mFrameCount;
+    static const int OUTPUT_BUFFERS = 6;
+    static const int INPUT_SHARED_BUFFERS = 8;
+    IVideoEncoder         *mVAEncoder;
+    VideoParamsCommon     mEncParamsCommon;
+    SharedBufferType      mSharedBufs[INPUT_SHARED_BUFFERS];
+    const ReadOptions     *mReadOptions;
+    MediaBufferGroup      *mOutBufGroup;   /* group of output buffers*/
+    MediaBuffer           *mLastInputBuffer;
+
+private:
+    status_t initCheck(const sp<MetaData>& meta);
+    int32_t calcBitrate(int width, int height);
+    status_t getSharedBuffers();
+    status_t setSharedBuffers();
+    static int SBShutdownFunc(void* arg);
+
+    IntelVideoEditorH263Encoder(const IntelVideoEditorH263Encoder &);
+    IntelVideoEditorH263Encoder &operator=(const IntelVideoEditorH263Encoder &);
+};
+};
+#endif
+
diff --git a/frameworks/videoedit/stagefrightshells/IntelVideoEditorUtils.cpp b/frameworks/videoedit/stagefrightshells/IntelVideoEditorUtils.cpp
new file mode 100644
index 0000000..299d82a
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/IntelVideoEditorUtils.cpp
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+*************************************************************************
+* @file   VideoEditorUtils.cpp
+* @brief  StageFright shell Utilities
+*************************************************************************
+*/
+#define LOG_NDEBUG 1
+#define LOG_TAG "SF_utils"
+#include "utils/Log.h"
+
+#include "IntelVideoEditorUtils.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXCodec.h>
+
+/* Android includes*/
+#include <utils/Log.h>
+#include <memory.h>
+
+/*---------------------*/
+/*  DEBUG LEVEL SETUP  */
+/*---------------------*/
+#define LOG1 ALOGE    /*ERRORS Logging*/
+#define LOG2 ALOGI    /*WARNING Logging*/
+#define LOG3 //ALOGV  /*COMMENTS Logging*/
+
+namespace android {
+
+void displayMetaData(const sp<MetaData> meta) {
+
+    const char* charData;
+    int32_t int32Data;
+    int64_t int64Data;
+    uint32_t type;
+    const void* data;
+    void* ptr;
+    size_t size;
+
+    if (meta->findCString(kKeyMIMEType, &charData)) {
+        LOG1("displayMetaData kKeyMIMEType %s", charData);
+    }
+    if (meta->findInt32(kKeyWidth, &int32Data)) {
+        LOG1("displayMetaData kKeyWidth %d", int32Data);
+    }
+    if (meta->findInt32(kKeyHeight, &int32Data)) {
+        LOG1("displayMetaData kKeyHeight %d", int32Data);
+    }
+    if (meta->findInt32(kKeyIFramesInterval, &int32Data)) {
+        LOG1("displayMetaData kKeyIFramesInterval %d", int32Data);
+    }
+    if (meta->findInt32(kKeyStride, &int32Data)) {
+        LOG1("displayMetaData kKeyStride %d", int32Data);
+    }
+    if (meta->findInt32(kKeySliceHeight, &int32Data)) {
+        LOG1("displayMetaData kKeySliceHeight %d", int32Data);
+    }
+    if (meta->findInt32(kKeyChannelCount, &int32Data)) {
+        LOG1("displayMetaData kKeyChannelCount %d", int32Data);
+    }
+    if (meta->findInt32(kKeySampleRate, &int32Data)) {
+        LOG1("displayMetaData kKeySampleRate %d", int32Data);
+    }
+    if (meta->findInt32(kKeyBitRate, &int32Data)) {
+        LOG1("displayMetaData kKeyBitRate %d", int32Data);
+    }
+    if (meta->findData(kKeyESDS, &type, &data, &size)) {
+        LOG1("displayMetaData kKeyESDS type=%d size=%d", type, size);
+    }
+    if (meta->findData(kKeyAVCC, &type, &data, &size)) {
+        LOG1("displayMetaData kKeyAVCC data=0x%X type=%d size=%d",
+            *((unsigned int*)data), type, size);
+    }
+    if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
+        LOG1("displayMetaData kKeyVorbisInfo type=%d size=%d", type, size);
+    }
+    if (meta->findData(kKeyVorbisBooks, &type, &data, &size)) {
+        LOG1("displayMetaData kKeyVorbisBooks type=%d size=%d", type, size);
+    }
+    if (meta->findInt32(kKeyWantsNALFragments, &int32Data)) {
+        LOG1("displayMetaData kKeyWantsNALFragments %d", int32Data);
+    }
+    if (meta->findInt32(kKeyIsSyncFrame, &int32Data)) {
+        LOG1("displayMetaData kKeyIsSyncFrame %d", int32Data);
+    }
+    if (meta->findInt32(kKeyIsCodecConfig, &int32Data)) {
+        LOG1("displayMetaData kKeyIsCodecConfig %d", int32Data);
+    }
+    if (meta->findInt64(kKeyTime, &int64Data)) {
+        LOG1("displayMetaData kKeyTime %lld", int64Data);
+    }
+    if (meta->findInt32(kKeyDuration, &int32Data)) {
+        LOG1("displayMetaData kKeyDuration %d", int32Data);
+    }
+    if (meta->findInt32(kKeyColorFormat, &int32Data)) {
+        LOG1("displayMetaData kKeyColorFormat %d", int32Data);
+    }
+    if (meta->findPointer(kKeyPlatformPrivate, &ptr)) {
+        LOG1("displayMetaData kKeyPlatformPrivate pointer=0x%x", (int32_t) ptr);
+    }
+    if (meta->findCString(kKeyDecoderComponent, &charData)) {
+        LOG1("displayMetaData kKeyDecoderComponent %s", charData);
+    }
+    if (meta->findInt32(kKeyBufferID, &int32Data)) {
+        LOG1("displayMetaData kKeyBufferID %d", int32Data);
+    }
+    if (meta->findInt32(kKeyMaxInputSize, &int32Data)) {
+        LOG1("displayMetaData kKeyMaxInputSize %d", int32Data);
+    }
+    if (meta->findInt64(kKeyThumbnailTime, &int64Data)) {
+        LOG1("displayMetaData kKeyThumbnailTime %lld", int64Data);
+    }
+    if (meta->findCString(kKeyAlbum, &charData)) {
+        LOG1("displayMetaData kKeyAlbum %s", charData);
+    }
+    if (meta->findCString(kKeyArtist, &charData)) {
+        LOG1("displayMetaData kKeyArtist %s", charData);
+    }
+    if (meta->findCString(kKeyAlbumArtist, &charData)) {
+        LOG1("displayMetaData kKeyAlbumArtist %s", charData);
+    }
+    if (meta->findCString(kKeyComposer, &charData)) {
+        LOG1("displayMetaData kKeyComposer %s", charData);
+    }
+    if (meta->findCString(kKeyGenre, &charData)) {
+        LOG1("displayMetaData kKeyGenre %s", charData);
+    }
+    if (meta->findCString(kKeyTitle, &charData)) {
+        LOG1("displayMetaData kKeyTitle %s", charData);
+    }
+    if (meta->findCString(kKeyYear, &charData)) {
+        LOG1("displayMetaData kKeyYear %s", charData);
+    }
+    if (meta->findData(kKeyAlbumArt, &type, &data, &size)) {
+        LOG1("displayMetaData kKeyAlbumArt type=%d size=%d", type, size);
+    }
+    if (meta->findCString(kKeyAlbumArtMIME, &charData)) {
+        LOG1("displayMetaData kKeyAlbumArtMIME %s", charData);
+    }
+    if (meta->findCString(kKeyAuthor, &charData)) {
+        LOG1("displayMetaData kKeyAuthor %s", charData);
+    }
+    if (meta->findCString(kKeyCDTrackNumber, &charData)) {
+        LOG1("displayMetaData kKeyCDTrackNumber %s", charData);
+    }
+    if (meta->findCString(kKeyDiscNumber, &charData)) {
+        LOG1("displayMetaData kKeyDiscNumber %s", charData);
+    }
+    if (meta->findCString(kKeyDate, &charData)) {
+        LOG1("displayMetaData kKeyDate %s", charData);
+    }
+    if (meta->findCString(kKeyWriter, &charData)) {
+        LOG1("displayMetaData kKeyWriter %s", charData);
+    }
+    if (meta->findInt32(kKeyTimeScale, &int32Data)) {
+        LOG1("displayMetaData kKeyTimeScale %d", int32Data);
+    }
+    if (meta->findInt32(kKeyVideoProfile, &int32Data)) {
+        LOG1("displayMetaData kKeyVideoProfile %d", int32Data);
+    }
+    if (meta->findInt32(kKeyVideoLevel, &int32Data)) {
+        LOG1("displayMetaData kKeyVideoLevel %d", int32Data);
+    }
+    if (meta->findInt32(kKey64BitFileOffset, &int32Data)) {
+        LOG1("displayMetaData kKey64BitFileOffset %d", int32Data);
+    }
+    if (meta->findInt32(kKeyFileType, &int32Data)) {
+        LOG1("displayMetaData kKeyFileType %d", int32Data);
+    }
+    if (meta->findInt64(kKeyTrackTimeStatus, &int64Data)) {
+        LOG1("displayMetaData kKeyTrackTimeStatus %lld", int64Data);
+    }
+    if (meta->findInt32(kKeyNotRealTime, &int32Data)) {
+        LOG1("displayMetaData kKeyNotRealTime %d", int32Data);
+    }
+}
+
+/**
+ * This code was extracted from StageFright MPEG4 writer
+ * Is is used to parse and format the AVC codec specific info received
+ * from StageFright encoders
+ */
+static const uint8_t kNalUnitTypeSeqParamSet = 0x07;
+static const uint8_t kNalUnitTypePicParamSet = 0x08;
+struct AVCParamSet {
+    AVCParamSet(uint16_t length, const uint8_t *data)
+        : mLength(length), mData(data) {}
+
+    uint16_t mLength;
+    const uint8_t *mData;
+};
+struct AVCCodecSpecificContext {
+    List<AVCParamSet> mSeqParamSets;
+    List<AVCParamSet> mPicParamSets;
+    uint8_t mProfileIdc;
+    uint8_t mProfileCompatible;
+    uint8_t mLevelIdc;
+};
+
+const uint8_t *parseParamSet(AVCCodecSpecificContext* pC,
+        const uint8_t *data, size_t length, int type, size_t *paramSetLen) {
+    CHECK(type == kNalUnitTypeSeqParamSet ||
+          type == kNalUnitTypePicParamSet);
+
+    size_t bytesLeft = length;
+    while (bytesLeft > 4  &&
+            memcmp("\x00\x00\x00\x01", &data[length - bytesLeft], 4)) {
+        --bytesLeft;
+    }
+    if (bytesLeft <= 4) {
+        bytesLeft = 0; // Last parameter set
+    }
+    const uint8_t *nextStartCode = &data[length - bytesLeft];
+    *paramSetLen = nextStartCode - data;
+    if (*paramSetLen == 0) {
+        ALOGE("Param set is malformed, since its length is 0");
+        return NULL;
+    }
+
+    AVCParamSet paramSet(*paramSetLen, data);
+    if (type == kNalUnitTypeSeqParamSet) {
+        if (*paramSetLen < 4) {
+            ALOGE("Seq parameter set malformed");
+            return NULL;
+        }
+        if (pC->mSeqParamSets.empty()) {
+            pC->mProfileIdc = data[1];
+            pC->mProfileCompatible = data[2];
+            pC->mLevelIdc = data[3];
+        } else {
+            if (pC->mProfileIdc != data[1] ||
+                pC->mProfileCompatible != data[2] ||
+                pC->mLevelIdc != data[3]) {
+                ALOGV("Inconsistent profile/level found in seq parameter sets");
+                return NULL;
+            }
+        }
+        pC->mSeqParamSets.push_back(paramSet);
+    } else {
+        pC->mPicParamSets.push_back(paramSet);
+    }
+    return nextStartCode;
+}
+
+status_t buildAVCCodecSpecificData(uint8_t **pOutputData, size_t *pOutputSize,
+        const uint8_t *data, size_t size, MetaData *param)
+{
+    //ALOGV("buildAVCCodecSpecificData");
+
+    if ( (pOutputData == NULL) || (pOutputSize == NULL) ) {
+        ALOGE("output is invalid");
+        return ERROR_MALFORMED;
+    }
+
+    if (*pOutputData != NULL) {
+        ALOGE("Already have codec specific data");
+        return ERROR_MALFORMED;
+    }
+
+    if (size < 4) {
+        ALOGE("Codec specific data length too short: %d", size);
+        return ERROR_MALFORMED;
+    }
+
+    // Data is in the form of AVCCodecSpecificData
+    if (memcmp("\x00\x00\x00\x01", data, 4)) {
+        // 2 bytes for each of the parameter set length field
+        // plus the 7 bytes for the header
+        if (size < 4 + 7) {
+            ALOGE("Codec specific data length too short: %d", size);
+            return ERROR_MALFORMED;
+        }
+
+        *pOutputSize = size;
+        *pOutputData = (uint8_t*)malloc(size);
+        memcpy(*pOutputData, data, size);
+        return OK;
+    }
+
+    AVCCodecSpecificContext ctx;
+    uint8_t *outputData = NULL;
+    size_t outputSize = 0;
+
+    // Check if the data is valid
+    uint8_t type = kNalUnitTypeSeqParamSet;
+    bool gotSps = false;
+    bool gotPps = false;
+    const uint8_t *tmp = data;
+    const uint8_t *nextStartCode = data;
+    size_t bytesLeft = size;
+    size_t paramSetLen = 0;
+    outputSize = 0;
+    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
+        type = (*(tmp + 4)) & 0x1F;
+        if (type == kNalUnitTypeSeqParamSet) {
+            if (gotPps) {
+                ALOGE("SPS must come before PPS");
+                return ERROR_MALFORMED;
+            }
+            if (!gotSps) {
+                gotSps = true;
+            }
+            nextStartCode = parseParamSet(&ctx, tmp + 4, bytesLeft - 4, type,
+                &paramSetLen);
+        } else if (type == kNalUnitTypePicParamSet) {
+            if (!gotSps) {
+                ALOGE("SPS must come before PPS");
+                return ERROR_MALFORMED;
+            }
+            if (!gotPps) {
+                gotPps = true;
+            }
+            nextStartCode = parseParamSet(&ctx, tmp + 4, bytesLeft - 4, type,
+                &paramSetLen);
+        } else {
+            ALOGE("Only SPS and PPS Nal units are expected");
+            return ERROR_MALFORMED;
+        }
+
+        if (nextStartCode == NULL) {
+            return ERROR_MALFORMED;
+        }
+
+        // Move on to find the next parameter set
+        bytesLeft -= nextStartCode - tmp;
+        tmp = nextStartCode;
+        outputSize += (2 + paramSetLen);
+
+        if (gotSps && gotPps) {
+            break;
+        }
+    }
+
+    {
+        // Check on the number of seq parameter sets
+        size_t nSeqParamSets = ctx.mSeqParamSets.size();
+        if (nSeqParamSets == 0) {
+            ALOGE("Cound not find sequence parameter set");
+            return ERROR_MALFORMED;
+        }
+
+        if (nSeqParamSets > 0x1F) {
+            ALOGE("Too many seq parameter sets (%d) found", nSeqParamSets);
+            return ERROR_MALFORMED;
+        }
+    }
+
+    {
+        // Check on the number of pic parameter sets
+        size_t nPicParamSets = ctx.mPicParamSets.size();
+        if (nPicParamSets == 0) {
+            ALOGE("Cound not find picture parameter set");
+            return ERROR_MALFORMED;
+        }
+        if (nPicParamSets > 0xFF) {
+            ALOGE("Too many pic parameter sets (%d) found", nPicParamSets);
+            return ERROR_MALFORMED;
+        }
+    }
+
+    // ISO 14496-15: AVC file format
+    outputSize += 7;  // 7 more bytes in the header
+    outputData = (uint8_t *)malloc(outputSize);
+    uint8_t *header = outputData;
+    header[0] = 1;                     // version
+    header[1] = ctx.mProfileIdc;           // profile indication
+    header[2] = ctx.mProfileCompatible;    // profile compatibility
+    header[3] = ctx.mLevelIdc;
+
+    // 6-bit '111111' followed by 2-bit to lengthSizeMinuusOne
+    int32_t use2ByteNalLength = 0;
+    if (param &&
+        param->findInt32(kKey2ByteNalLength, &use2ByteNalLength) &&
+        use2ByteNalLength) {
+        header[4] = 0xfc | 1;  // length size == 2 bytes
+    } else {
+        header[4] = 0xfc | 3;  // length size == 4 bytes
+    }
+
+    // 3-bit '111' followed by 5-bit numSequenceParameterSets
+    int nSequenceParamSets = ctx.mSeqParamSets.size();
+    header[5] = 0xe0 | nSequenceParamSets;
+    header += 6;
+    for (List<AVCParamSet>::iterator it = ctx.mSeqParamSets.begin();
+         it != ctx.mSeqParamSets.end(); ++it) {
+        // 16-bit sequence parameter set length
+        uint16_t seqParamSetLength = it->mLength;
+        header[0] = seqParamSetLength >> 8;
+        header[1] = seqParamSetLength & 0xff;
+        //ALOGE("### SPS %d %d %d", seqParamSetLength, header[0], header[1]);
+
+        // SPS NAL unit (sequence parameter length bytes)
+        memcpy(&header[2], it->mData, seqParamSetLength);
+        header += (2 + seqParamSetLength);
+    }
+
+    // 8-bit nPictureParameterSets
+    int nPictureParamSets = ctx.mPicParamSets.size();
+    header[0] = nPictureParamSets;
+    header += 1;
+    for (List<AVCParamSet>::iterator it = ctx.mPicParamSets.begin();
+         it != ctx.mPicParamSets.end(); ++it) {
+        // 16-bit picture parameter set length
+        uint16_t picParamSetLength = it->mLength;
+        header[0] = picParamSetLength >> 8;
+        header[1] = picParamSetLength & 0xff;
+//ALOGE("### PPS %d %d %d", picParamSetLength, header[0], header[1]);
+
+        // PPS Nal unit (picture parameter set length bytes)
+        memcpy(&header[2], it->mData, picParamSetLength);
+        header += (2 + picParamSetLength);
+    }
+
+    *pOutputSize = outputSize;
+    *pOutputData = outputData;
+    return OK;
+}
+
+status_t removeAVCCodecSpecificData(uint8_t **pOutputData, size_t *pOutputSize,
+        const uint8_t *data, size_t size, MetaData *param)
+{
+    LOGV("removeAVCCodecSpecificData begin");
+    LOGV("Inputdataaddr = %p,Inputsize = %d", data,size);
+    if ( (pOutputData == NULL) || (pOutputSize == NULL) ) {
+        LOGE("output is invalid");
+        return ERROR_MALFORMED;
+    }
+
+    if (size < 4) {
+        LOGE("Codec specific data length too short: %d", size);
+        return ERROR_MALFORMED;
+    }
+
+    AVCCodecSpecificContext ctx;
+    uint8_t *outputData = NULL;
+    size_t outputSize = 0;
+
+    // Check if the data is valid
+    uint8_t type = kNalUnitTypeSeqParamSet;
+    bool gotSps = false;
+    bool gotPps = false;
+    const uint8_t *tmp = data;
+    const uint8_t *nextStartCode = data;
+    size_t bytesLeft = size;
+    size_t paramSetLen = 0;
+    outputSize = 0;
+
+    while (bytesLeft > 4 && !memcmp("\x00\x00\x00\x01", tmp, 4)) {
+        type = (*(tmp + 4)) & 0x1F;
+        if (type == kNalUnitTypeSeqParamSet) {
+            if (gotPps) {
+                LOGE("SPS must come before PPS");
+                return ERROR_MALFORMED;
+            }
+            if (!gotSps) {
+                gotSps = true;
+            }
+            nextStartCode = parseParamSet(&ctx, tmp + 4, bytesLeft - 4, type,
+                &paramSetLen);
+        } else if (type == kNalUnitTypePicParamSet) {
+            if (!gotSps) {
+                LOGE("SPS must come before PPS");
+                return ERROR_MALFORMED;
+            }
+            if (!gotPps) {
+                gotPps = true;
+            }
+            nextStartCode = parseParamSet(&ctx, tmp + 4, bytesLeft - 4, type,
+                &paramSetLen);
+        } else {
+            LOGE("Only SPS and PPS Nal units are expected");
+            return ERROR_MALFORMED;
+        }
+        if (nextStartCode == NULL) {
+            return ERROR_MALFORMED;
+        }
+        bytesLeft -= nextStartCode - tmp;
+        tmp = nextStartCode;
+        outputSize += (4 + paramSetLen);
+        LOGV("DSI size is %d!",outputSize);
+        if(gotSps && gotPps)
+        {
+            break;
+        }
+    }
+    *pOutputData = (uint8_t *)(data + outputSize);
+    *pOutputSize = outputSize;
+    LOGV("Outputdataaddr = %p,Outputsize = %d", *pOutputData, *pOutputSize);
+    LOGV("removeAVCCodecSpecificData end");
+    return OK;
+}
+}// namespace android
diff --git a/frameworks/videoedit/stagefrightshells/IntelVideoEditorUtils.h b/frameworks/videoedit/stagefrightshells/IntelVideoEditorUtils.h
new file mode 100644
index 0000000..81acf17
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/IntelVideoEditorUtils.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+*************************************************************************
+* @file   VideoEditorUtils.cpp
+* @brief  StageFright shell Utilities
+*************************************************************************
+*/
+#ifndef ANDROID_UTILS_H_
+#define ANDROID_UTILS_H_
+
+/*******************
+ *     HEADERS     *
+ *******************/
+
+#include "M4OSA_Debug.h"
+
+#include "utils/Log.h"
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+/**
+ *************************************************************************
+ * VIDEOEDITOR_CHECK(test, errCode)
+ * @note This macro displays an error message and goes to function cleanUp label
+ *       if the test fails.
+ *************************************************************************
+ */
+#define VIDEOEDITOR_CHECK(test, errCode) \
+{ \
+    if( !(test) ) { \
+        ALOGV("!!! %s (L%d) check failed : " #test ", yields error 0x%.8x", \
+            __FILE__, __LINE__, errCode); \
+        err = (errCode); \
+        goto cleanUp; \
+    } \
+}
+
+/**
+ *************************************************************************
+ * SAFE_FREE(p)
+ * @note This macro calls free and makes sure the pointer is set to NULL.
+ *************************************************************************
+ */
+#define SAFE_FREE(p) \
+{ \
+    if(M4OSA_NULL != (p)) { \
+        free((p)) ; \
+        (p) = M4OSA_NULL ; \
+    } \
+}
+
+/**
+ *************************************************************************
+ * SAFE_MALLOC(p, type, count, comment)
+ * @note This macro allocates a buffer, checks for success and fills the buffer
+ *       with 0.
+ *************************************************************************
+ */
+#define SAFE_MALLOC(p, type, count, comment) \
+{ \
+    (p) = (type*)M4OSA_32bitAlignedMalloc(sizeof(type)*(count), 0xFF,(M4OSA_Char*)comment);\
+    VIDEOEDITOR_CHECK(M4OSA_NULL != (p), M4ERR_ALLOC); \
+    memset((void *)(p), 0,sizeof(type)*(count)); \
+}
+
+
+    /********************
+     *    UTILITIES     *
+     ********************/
+
+
+namespace android {
+
+/*--------------------------*/
+/* DISPLAY METADATA CONTENT */
+/*--------------------------*/
+void displayMetaData(const sp<MetaData> meta);
+
+// Build the AVC codec spcific info from the StageFright encoders output
+status_t buildAVCCodecSpecificData(uint8_t **outputData, size_t *outputSize,
+        const uint8_t *data, size_t size, MetaData *param);
+
+// Remove the AVC codec specific info from the StageFright encoders output
+status_t removeAVCCodecSpecificData(uint8_t **outputData, size_t *outputSize,
+        const uint8_t *data, size_t size, MetaData *param);
+}//namespace android
+
+
+#endif //ANDROID_UTILS_H_
diff --git a/frameworks/videoedit/stagefrightshells/MediaBufferPuller.cpp b/frameworks/videoedit/stagefrightshells/MediaBufferPuller.cpp
new file mode 100644
index 0000000..acc8268
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/MediaBufferPuller.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaBufferPuller"
+#include <utils/Log.h>
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include "MediaBufferPuller.h"
+
+namespace android {
+
+
+MediaBufferPuller::MediaBufferPuller(const sp<MediaSource>& source)
+    : mSource(source),
+      mAskToStart(false),
+      mAskToStop(false),
+      mAcquireStopped(false),
+      mReleaseStopped(false),
+      mSourceError(OK) {
+
+    androidCreateThread(acquireThreadStart, this);
+    androidCreateThread(releaseThreadStart, this);
+}
+
+MediaBufferPuller::~MediaBufferPuller() {
+    stop();
+}
+
+bool MediaBufferPuller::hasMediaSourceReturnedError() const {
+    Mutex::Autolock autolock(mLock);
+    return ((mSourceError != OK) ? true : false);
+}
+void MediaBufferPuller::start() {
+    Mutex::Autolock autolock(mLock);
+    mAskToStart = true;
+    mAcquireCond.signal();
+    mReleaseCond.signal();
+}
+
+void MediaBufferPuller::stop() {
+    Mutex::Autolock autolock(mLock);
+    mAskToStop = true;
+    mAcquireCond.signal();
+    mReleaseCond.signal();
+    while (!mAcquireStopped || !mReleaseStopped) {
+        mUserCond.wait(mLock);
+    }
+
+    // Release remaining buffers
+    for (size_t i = 0; i < mBuffers.size(); i++) {
+        mBuffers.itemAt(i)->release();
+    }
+
+    for (size_t i = 0; i < mReleaseBuffers.size(); i++) {
+        mReleaseBuffers.itemAt(i)->release();
+    }
+
+    mBuffers.clear();
+    mReleaseBuffers.clear();
+}
+
+MediaBuffer* MediaBufferPuller::getBufferNonBlocking() {
+    Mutex::Autolock autolock(mLock);
+    if (mBuffers.empty()) {
+        return NULL;
+    } else {
+        MediaBuffer* b = mBuffers.itemAt(0);
+        mBuffers.removeAt(0);
+        return b;
+    }
+}
+
+MediaBuffer* MediaBufferPuller::getBufferBlocking() {
+    Mutex::Autolock autolock(mLock);
+    while (mBuffers.empty() && !mAcquireStopped) {
+        mUserCond.wait(mLock);
+    }
+
+    if (mBuffers.empty()) {
+        return NULL;
+    } else {
+        MediaBuffer* b = mBuffers.itemAt(0);
+        mBuffers.removeAt(0);
+        return b;
+    }
+}
+
+void MediaBufferPuller::putBuffer(MediaBuffer* buffer) {
+    Mutex::Autolock autolock(mLock);
+    mReleaseBuffers.push(buffer);
+    mReleaseCond.signal();
+}
+
+int MediaBufferPuller::acquireThreadStart(void* arg) {
+    MediaBufferPuller* self = (MediaBufferPuller*)arg;
+    self->acquireThreadFunc();
+    return 0;
+}
+
+int MediaBufferPuller::releaseThreadStart(void* arg) {
+    MediaBufferPuller* self = (MediaBufferPuller*)arg;
+    self->releaseThreadFunc();
+    return 0;
+}
+
+void MediaBufferPuller::acquireThreadFunc() {
+    mLock.lock();
+
+    // Wait for the start signal
+    while (!mAskToStart && !mAskToStop) {
+        mAcquireCond.wait(mLock);
+    }
+
+    // Loop until we are asked to stop, or there is nothing more to read
+    while (!mAskToStop) {
+        MediaBuffer* pBuffer;
+        mLock.unlock();
+        status_t result = mSource->read(&pBuffer, NULL);
+        mLock.lock();
+        mSourceError = result;
+        if (result != OK) {
+            break;
+        }
+        mBuffers.push(pBuffer);
+        mUserCond.signal();
+    }
+
+    mAcquireStopped = true;
+    mUserCond.signal();
+    mLock.unlock();
+}
+
+void MediaBufferPuller::releaseThreadFunc() {
+    mLock.lock();
+
+    // Wait for the start signal
+    while (!mAskToStart && !mAskToStop) {
+        mReleaseCond.wait(mLock);
+    }
+
+    // Loop until we are asked to stop
+    while (1) {
+        if (mReleaseBuffers.empty()) {
+            if (mAskToStop) {
+                break;
+            } else {
+                mReleaseCond.wait(mLock);
+                continue;
+            }
+        }
+        MediaBuffer* pBuffer = mReleaseBuffers.itemAt(0);
+        mReleaseBuffers.removeAt(0);
+        mLock.unlock();
+        pBuffer->release();
+        mLock.lock();
+    }
+
+    mReleaseStopped = true;
+    mUserCond.signal();
+    mLock.unlock();
+}
+
+};  // namespace android
diff --git a/frameworks/videoedit/stagefrightshells/MediaBufferPuller.h b/frameworks/videoedit/stagefrightshells/MediaBufferPuller.h
new file mode 100644
index 0000000..ed72a53
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/MediaBufferPuller.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MEDIA_BUFFER_PULLER_H
+#define _MEDIA_BUFFER_PULLER_H
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+
+namespace android {
+
+struct MediaSource;
+struct MediaBuffer;
+
+/*
+ * An object of this class can pull a list of media buffers
+ * from a MediaSource repeatedly. The user can then get the
+ * buffers from that list.
+ */
+struct MediaBufferPuller {
+public:
+    MediaBufferPuller(const sp<MediaSource>& source);
+    ~MediaBufferPuller();
+
+    // Start to build up the list of the buffers.
+    void start();
+
+    // Release the list of the available buffers, and stop
+    // pulling buffers from the MediaSource.
+    void stop();
+
+    // Get a buffer from the list. If there is no buffer available
+    // at the time this method is called, NULL is returned.
+    MediaBuffer* getBufferBlocking();
+
+    // Get a buffer from the list. If there is no buffer available
+    // at the time this method is called, it blocks waiting for
+    // a buffer to become available or until stop() is called.
+    MediaBuffer* getBufferNonBlocking();
+
+    // Add a buffer to the end of the list available media buffers
+    void putBuffer(MediaBuffer* buffer);
+
+    // Check whether the source returned an error or not.
+    bool hasMediaSourceReturnedError() const;
+
+private:
+    static int acquireThreadStart(void* arg);
+    void acquireThreadFunc();
+
+    static int releaseThreadStart(void* arg);
+    void releaseThreadFunc();
+
+    sp<MediaSource> mSource;
+    Vector<MediaBuffer*> mBuffers;
+    Vector<MediaBuffer*> mReleaseBuffers;
+
+    mutable Mutex mLock;
+    Condition mUserCond;     // for the user of this class
+    Condition mAcquireCond;  // for the acquire thread
+    Condition mReleaseCond;  // for the release thread
+
+    bool mAskToStart;      // Asks the threads to start
+    bool mAskToStop;       // Asks the threads to stop
+    bool mAcquireStopped;  // The acquire thread has stopped
+    bool mReleaseStopped;  // The release thread has stopped
+    status_t mSourceError; // Error returned by MediaSource read
+
+    // Don't call me!
+    MediaBufferPuller(const MediaBufferPuller&);
+    MediaBufferPuller& operator=(const MediaBufferPuller&);
+};
+
+}  // namespace android
+
+#endif  // _MEDIA_BUFFER_PULLER_H
diff --git a/frameworks/videoedit/stagefrightshells/VideoEditor3gpReader.cpp b/frameworks/videoedit/stagefrightshells/VideoEditor3gpReader.cpp
new file mode 100644
index 0000000..5026073
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/VideoEditor3gpReader.cpp
@@ -0,0 +1,2030 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+*************************************************************************
+* @file   VideoEditor3gpReader.cpp
+* @brief  StageFright shell 3GP Reader
+*************************************************************************
+*/
+
+#define LOG_NDEBUG 1
+#define LOG_TAG "VIDEOEDITOR_3GPREADER"
+
+/**
+ * HEADERS
+ *
+ */
+#define VIDEOEDITOR_BITSTREAM_PARSER
+
+#include "M4OSA_Debug.h"
+#include "VideoEditor3gpReader.h"
+#include "M4SYS_AccessUnit.h"
+#include "VideoEditorUtils.h"
+#include "M4READER_3gpCom.h"
+#include "M4_Common.h"
+#include "M4OSA_FileWriter.h"
+
+#ifdef VIDEOEDITOR_BITSTREAM_PARSER
+#include "M4OSA_CoreID.h"
+#include "M4OSA_Error.h"
+#include "M4OSA_Memory.h"
+#include "M4_Utils.h"
+#endif
+
+#include "ESDS.h"
+#include "utils/Log.h"
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+/**
+ * SOURCE CLASS
+ */
+namespace android {
+/**
+ * ENGINE INTERFACE
+ */
+
+/**
+ ************************************************************************
+ * @brief   Array of AMR NB/WB bitrates
+ * @note    Array to match the mode and the bit rate
+ ************************************************************************
+*/
+const M4OSA_UInt32 VideoEditor3gpReader_AmrBitRate [2 /* 8kHz / 16kHz     */]
+                                                   [9 /* the bitrate mode */] =
+{
+    {4750, 5150, 5900,  6700,  7400,  7950,  10200, 12200, 0},
+    {6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850}
+};
+
+/**
+ *******************************************************************************
+ * structure VideoEditor3gpReader_Context
+ * @brief:This structure defines the context of the StageFright 3GP shell Reader
+ *******************************************************************************
+*/
+typedef struct {
+    sp<DataSource>              mDataSource;
+    sp<MediaExtractor>          mExtractor;
+    sp<MediaSource>             mAudioSource;
+    sp<MediaSource>             mVideoSource;
+    M4_StreamHandler*           mAudioStreamHandler;
+    M4_StreamHandler*           mVideoStreamHandler;
+    M4SYS_AccessUnit            mAudioAu;
+    M4SYS_AccessUnit            mVideoAu;
+    M4OSA_Time                  mMaxDuration;
+    int64_t                     mFileSize;
+    M4_StreamType               mStreamType;
+    M4OSA_UInt32                mStreamId;
+    int32_t                     mTracks;
+    int32_t                     mCurrTrack;
+    M4OSA_Bool                  mAudioSeeking;
+    M4OSA_Time                  mAudioSeekTime;
+    M4OSA_Bool                  mVideoSeeking;
+    M4OSA_Time                  mVideoSeekTime;
+
+} VideoEditor3gpReader_Context;
+
+#ifdef VIDEOEDITOR_BITSTREAM_PARSER
+/**
+ ************************************************************************
+ * structure    VideoEditor3gpReader_BitStreamParserContext
+ * @brief       Internal BitStreamParser context
+ ************************************************************************
+*/
+typedef struct {
+    M4OSA_UInt32*   mPbitStream;   /**< bitstream pointer (32bits aligned) */
+    M4OSA_Int32     mSize;         /**< bitstream size in bytes */
+    M4OSA_Int32     mIndex;        /**< byte index */
+    M4OSA_Int32     mBitIndex;     /**< bit index */
+    M4OSA_Int32     mStructSize;   /**< size of structure */
+} VideoEditor3gpReader_BitStreamParserContext;
+
+/**
+ *******************************************************************************
+ * @brief   Allocates the context and initializes internal data.
+ * @param   pContext    (OUT)  Pointer to the BitStreamParser context to create.
+ * @param   bitStream   A pointer to the bitstream
+ * @param   size        The size of the bitstream in bytes
+ *******************************************************************************
+*/
+static void VideoEditor3gpReader_BitStreamParserInit(void** pContext,
+        void* pBitStream, M4OSA_Int32 size) {
+    VideoEditor3gpReader_BitStreamParserContext* pStreamContext;
+
+    *pContext=M4OSA_NULL;
+    pStreamContext = (VideoEditor3gpReader_BitStreamParserContext*)M4OSA_32bitAlignedMalloc(
+        sizeof(VideoEditor3gpReader_BitStreamParserContext), M4READER_3GP,
+            (M4OSA_Char*)"3GP BitStreamParser Context");
+    if (M4OSA_NULL == pStreamContext) {
+        return;
+    }
+    pStreamContext->mPbitStream=(M4OSA_UInt32*)pBitStream;
+    pStreamContext->mSize=size;
+    pStreamContext->mIndex=0;
+    pStreamContext->mBitIndex=0;
+    pStreamContext->mStructSize =
+        sizeof(VideoEditor3gpReader_BitStreamParserContext);
+
+    *pContext=pStreamContext;
+}
+/**
+ **********************************************************************
+ * @brief   Clean up context
+ * @param   pContext    (IN/OUT)  BitStreamParser context.
+ **********************************************************************
+*/
+static void VideoEditor3gpReader_BitStreamParserCleanUp(void* pContext) {
+    free((M4OSA_Int32*)pContext);
+}
+/**
+ *****************************************************************************
+ * @brief   Read the next <length> bits in the bitstream.
+ * @note    The function does not update the bitstream pointer.
+ * @param   pContext    (IN/OUT) BitStreamParser context.
+ * @param   length      (IN) The number of bits to extract from the bitstream
+ * @return  the read bits
+ *****************************************************************************
+*/
+static M4OSA_UInt32 VideoEditor3gpReader_BitStreamParserShowBits(void* pContext,
+        M4OSA_Int32 length) {
+    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
+        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
+
+    M4OSA_UInt32 u_mask;
+    M4OSA_UInt32 retval;
+    M4OSA_Int32 i_ovf;
+
+    M4OSA_DEBUG_IF1((M4OSA_NULL==pStreamContext), 0,
+        "VideoEditor3gpReader_BitStreamParserShowBits:invalid context pointer");
+
+    retval=(M4OSA_UInt32)GET_MEMORY32(pStreamContext->\
+        mPbitStream[ pStreamContext->mIndex ]);
+    i_ovf = pStreamContext->mBitIndex + length - 32;
+    u_mask = (length >= 32) ? 0xffffffff: (1 << length) - 1;
+
+    /* do we have enough bits availble in the current word(32bits)*/
+    if (i_ovf <= 0) {
+        retval=(retval >> (- i_ovf)) & u_mask;
+    } else {
+        M4OSA_UInt32 u_nextword = (M4OSA_UInt32)GET_MEMORY32(
+            pStreamContext->mPbitStream[ pStreamContext->mIndex + 1 ]);
+        M4OSA_UInt32 u_msb_mask, u_msb_value, u_lsb_mask, u_lsb_value;
+
+        u_msb_mask = ((1 << (32 - pStreamContext->mBitIndex)) - 1) << i_ovf;
+        u_msb_value = retval << i_ovf;
+        u_lsb_mask = (1 << i_ovf) - 1;
+        u_lsb_value = u_nextword >> (32 - i_ovf);
+        retval= (u_msb_value & u_msb_mask ) | (u_lsb_value & u_lsb_mask);
+    }
+    /* return the bits...*/
+    return retval;
+}
+/**
+ ************************************************************************
+ * @brief   Increment the bitstream pointer of <length> bits.
+ * @param   pContext    (IN/OUT) BitStreamParser context.
+ * @param   length      (IN) The number of bit to shift the bitstream
+ ************************************************************************
+*/
+static void VideoEditor3gpReader_BitStreamParserFlushBits(void* pContext,
+        M4OSA_Int32 length) {
+    VideoEditor3gpReader_BitStreamParserContext* pStreamContext=(
+        VideoEditor3gpReader_BitStreamParserContext*)pContext;
+    M4OSA_Int32 val;
+
+    if (M4OSA_NULL == pStreamContext) {
+        return;
+    }
+    val=pStreamContext->mBitIndex + length;
+    /* update the bits...*/
+    pStreamContext->mBitIndex += length;
+
+    if (val - 32 >= 0) {
+        /* update the bits...*/
+        pStreamContext->mBitIndex -= 32;
+        /* update the words*/
+        pStreamContext->mIndex++;
+    }
+}
+
+static M4OSA_UInt32 VideoEditor3gpReader_BitStreamParserGetBits(
+        void* pContext,M4OSA_Int32 bitPos, M4OSA_Int32 bitLength) {
+    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
+        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
+
+    M4OSA_Int32 bitLocation, bitIndex;
+    M4OSA_UInt32 retval=0;
+
+    M4OSA_DEBUG_IF1((M4OSA_NULL==pStreamContext), 0,
+        "VideoEditor3gpReader_BitStreamParserGetBits: invalid context pointer");
+
+    /* computes the word location*/
+    bitLocation=bitPos/32;
+    bitIndex=(bitPos) % 32;
+
+    if (bitLocation < pStreamContext->mSize) {
+        M4OSA_UInt32 u_mask;
+        M4OSA_Int32 i_ovf = bitIndex + bitLength - 32;
+        retval=(M4OSA_UInt32)GET_MEMORY32(
+            pStreamContext->mPbitStream[ bitLocation ]);
+
+        u_mask = (bitLength >= 32) ? 0xffffffff: (1 << bitLength) - 1;
+
+        if (i_ovf <= 0) {
+            retval=(retval >> (- i_ovf)) & u_mask;
+        } else {
+            M4OSA_UInt32 u_nextword = (M4OSA_UInt32)GET_MEMORY32(
+                pStreamContext->mPbitStream[ bitLocation + 1 ]);
+            M4OSA_UInt32 u_msb_mask, u_msb_value, u_lsb_mask, u_lsb_value;
+
+            u_msb_mask = ((1 << (32 - bitIndex)) - 1) << i_ovf;
+            u_msb_value = retval << i_ovf;
+            u_lsb_mask = (1 << i_ovf) - 1;
+            u_lsb_value = u_nextword >> (32 - i_ovf);
+            retval= (u_msb_value & u_msb_mask ) | (u_lsb_value & u_lsb_mask);
+        }
+    }
+    return retval;
+}
+
+static void VideoEditor3gpReader_BitStreamParserRestart(void* pContext) {
+    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
+        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
+
+    if (M4OSA_NULL == pStreamContext) {
+        return;
+    }
+    /* resets the bitstream pointers*/
+    pStreamContext->mIndex=0;
+    pStreamContext->mBitIndex=0;
+}
+/**
+ *******************************************************************************
+ * @brief  Get a pointer to the current byte pointed by the bitstream pointer.
+ * @note   It should be used carefully as the pointer is in the bitstream itself
+ *         and no copy is made.
+ * @param  pContext    (IN/OUT)  BitStreamParser context.
+ * @return Pointer to the current location in the bitstream
+ *******************************************************************************
+*/
+static M4OSA_UInt8*  VideoEditor3gpReader_GetCurrentbitStreamPointer(
+        void* pContext) {
+    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
+        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
+    M4OSA_DEBUG_IF1((M4OSA_NULL==pStreamContext), 0, "invalid context pointer");
+
+    return (M4OSA_UInt8*)((M4OSA_UInt8*)pStreamContext->mPbitStream + \
+        pStreamContext->mIndex * sizeof(M4OSA_UInt32) + \
+        pStreamContext->mBitIndex/8) ;
+}
+
+static M4OSA_Int32 VideoEditor3gpReader_BitStreamParserGetSize(void* pContext) {
+    VideoEditor3gpReader_BitStreamParserContext* pStreamContext =
+        (VideoEditor3gpReader_BitStreamParserContext*)pContext;
+    M4OSA_DEBUG_IF1((M4OSA_NULL==pStreamContext), 0, "invalid context pointer");
+
+    return pStreamContext->mSize;
+}
+
+
+static void VideoEditor3gpReader_MPEG4BitStreamParserInit(void** pContext,
+        void* pBitStream, M4OSA_Int32 size) {
+    VideoEditor3gpReader_BitStreamParserInit(pContext, pBitStream, size);
+}
+static M4OSA_Int32 VideoEditor3gpReader_GetMpegLengthFromInteger(void* pContext,
+        M4OSA_UInt32 val) {
+    M4OSA_UInt32 length=0;
+    M4OSA_UInt32 numBytes=0;
+    M4OSA_UInt32 b=0;
+
+    M4OSA_DEBUG_IF1((M4OSA_NULL==pContext), 0, "invalid context pointer");
+
+    /* the length is encoded as a sequence of bytes. The highest bit is used
+    to indicate that the length continues on the next byte.
+
+    The length can be: 0x80 0x80 0x80 0x22
+    of just            0x22 (highest bit not set)
+
+    */
+
+    do {
+        b=(val & ((0xff)<< (8 * numBytes)))>> (8 * numBytes);
+        length=(length << 7) | (b & 0x7f);
+        numBytes++;
+    } while ((b & 0x80) && numBytes < 4);
+
+    return length;
+}
+
+/**
+ *******************************************************************************
+ * @brief  Decode an MPEG4 Systems descriptor size from an encoded SDL size data
+ * @note   The value is read from the current bitstream location.
+ * @param  pContext    (IN/OUT)  BitStreamParser context.
+ * @return Size in a human readable form
+ *******************************************************************************
+*/
+static M4OSA_Int32 VideoEditor3gpReader_GetMpegLengthFromStream(void* pContext){
+    M4OSA_UInt32 length=0;
+    M4OSA_UInt32 numBytes=0;
+    M4OSA_UInt32 b=0;
+
+    M4OSA_DEBUG_IF1((M4OSA_NULL==pContext), 0, "invalid context pointer");
+
+    /* the length is encoded as a sequence of bytes. The highest bit is used
+    to indicate that the length continues on the next byte.
+
+    The length can be: 0x80 0x80 0x80 0x22
+    of just            0x22 (highest bit not set)
+    */
+
+    do {
+        b=VideoEditor3gpReader_BitStreamParserShowBits(pContext, 8);
+        VideoEditor3gpReader_BitStreamParserFlushBits(pContext, 8);
+        length=(length << 7) | (b & 0x7f);
+        numBytes++;
+    } while ((b & 0x80) && numBytes < 4);
+
+    return length;
+}
+#endif /* VIDEOEDITOR_BITSTREAM_PARSER */
+/**
+************************************************************************
+* @brief    create an instance of the 3gp reader
+ * @note    allocates the context
+ *
+ * @param   pContext:       (OUT)   pointer on a reader context
+ *
+ * @return  M4NO_ERROR              there is no error
+ * @return  M4ERR_ALLOC             a memory allocation has failed
+ * @return  M4ERR_PARAMETER         at least one parameter is not valid
+************************************************************************
+*/
+
+M4OSA_ERR VideoEditor3gpReader_create(M4OSA_Context *pContext) {
+    VideoEditor3gpReader_Context* pC = NULL;
+    M4OSA_ERR err = M4NO_ERROR;
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext , M4ERR_PARAMETER);
+
+    ALOGV("VideoEditor3gpReader_create begin");
+
+    /* Context allocation & initialization */
+    SAFE_MALLOC(pC, VideoEditor3gpReader_Context, 1, "VideoEditor3gpReader");
+
+    memset(pC, sizeof(VideoEditor3gpReader_Context), 0);
+
+    pC->mAudioStreamHandler  = M4OSA_NULL;
+    pC->mAudioAu.dataAddress = M4OSA_NULL;
+    pC->mVideoStreamHandler  = M4OSA_NULL;
+    pC->mVideoAu.dataAddress = M4OSA_NULL;
+
+    pC->mAudioSeeking = M4OSA_FALSE;
+    pC->mAudioSeekTime = 0;
+
+    pC->mVideoSeeking = M4OSA_FALSE;
+    pC->mVideoSeekTime = 0;
+
+    pC->mMaxDuration = 0;
+
+    *pContext=pC;
+
+cleanUp:
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditor3gpReader_create no error");
+    } else {
+        ALOGV("VideoEditor3gpReader_create ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditor3gpReader_create end ");
+    return err;
+}
+
+/**
+**************************************************************************
+* @brief    destroy the instance of the 3gp reader
+* @note after this call the context is invalid
+* @param    context:        (IN)    Context of the reader
+* @return   M4NO_ERROR              there is no error
+* @return   M4ERR_PARAMETER         pContext parameter is not properly set
+**************************************************************************
+*/
+
+M4OSA_ERR VideoEditor3gpReader_destroy(M4OSA_Context pContext) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditor3gpReader_Context* pC = M4OSA_NULL;
+
+    ALOGV("VideoEditor3gpReader_destroy begin");
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    pC = (VideoEditor3gpReader_Context*)pContext;
+
+    SAFE_FREE(pC->mAudioAu.dataAddress);
+    pC->mAudioAu.dataAddress = M4OSA_NULL;
+    SAFE_FREE(pC->mVideoAu.dataAddress);
+    pC->mVideoAu.dataAddress = M4OSA_NULL;
+    SAFE_FREE(pC);
+    pContext = M4OSA_NULL;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditor3gpReader_destroy no error");
+    }
+    else
+    {
+        ALOGV("VideoEditor3gpReader_destroy ERROR 0x%X", err);
+    }
+
+    ALOGV("VideoEditor3gpReader_destroy end ");
+    return err;
+}
+
+/**
+************************************************************************
+* @brief    open the reader and initializes its created instance
+* @note     this function open the media file
+* @param    context:            (IN)    Context of the reader
+* @param    pFileDescriptor:    (IN)    Pointer to proprietary data identifying
+*                                       the media to open
+* @return   M4NO_ERROR                  there is no error
+* @return   M4ERR_PARAMETER             the context is NULL
+* @return   M4ERR_UNSUPPORTED_MEDIA_TYPE
+*                                       the media is DRM protected
+************************************************************************
+*/
+
+M4OSA_ERR VideoEditor3gpReader_open(M4OSA_Context pContext,
+        M4OSA_Void* pFileDescriptor) {
+    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)pContext;
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditor3gpReader_open start ");
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pC),  M4ERR_PARAMETER,
+        "VideoEditor3gpReader_open: invalid context pointer");
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_open: invalid pointer pFileDescriptor");
+
+    ALOGV("VideoEditor3gpReader_open Datasource start %s",
+        (char*)pFileDescriptor);
+    //pC->mDataSource = DataSource::CreateFromURI((char*)pFileDescriptor);
+    pC->mDataSource = new FileSource ((char*)pFileDescriptor);
+
+    if (pC->mDataSource == NULL) {
+        ALOGV("VideoEditor3gpReader_open Datasource error");
+        return M4ERR_PARAMETER;
+    }
+
+    pC->mExtractor = MediaExtractor::Create(pC->mDataSource,
+        MEDIA_MIMETYPE_CONTAINER_MPEG4);
+
+    if (pC->mExtractor == NULL) {
+        ALOGV("VideoEditor3gpReader_open extractor error");
+        return M4ERR_PARAMETER;
+    }
+
+    int32_t isDRMProtected = 0;
+    sp<MetaData> meta = pC->mExtractor->getMetaData();
+    meta->findInt32(kKeyIsDRM, &isDRMProtected);
+    if (isDRMProtected) {
+        ALOGV("VideoEditorMp3Reader_open error - DRM Protected");
+        return M4ERR_UNSUPPORTED_MEDIA_TYPE;
+    }
+
+    ALOGV("VideoEditor3gpReader_open end ");
+    return err;
+}
+
+/**
+************************************************************************
+* @brief    close the reader
+* @note     close the 3GP file
+* @param    context:        (IN)    Context of the reader
+* @return   M4NO_ERROR              there is no error
+* @return   M4ERR_PARAMETER         the context is NULL
+* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
+************************************************************************
+*/
+M4OSA_ERR VideoEditor3gpReader_close(M4OSA_Context context) {
+    VideoEditor3gpReader_Context *pC = (VideoEditor3gpReader_Context*)context;
+    M4READER_AudioSbrUserdata *pAudioSbrUserData;
+    M4_AccessUnit *pAU;
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditor3gpReader_close begin");
+
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_close: invalid context pointer");
+
+    if (pC->mAudioStreamHandler) {
+        ALOGV("VideoEditor3gpReader_close Audio");
+
+        if (M4OSA_NULL != pC->mAudioStreamHandler->m_pDecoderSpecificInfo) {
+            free(pC->mAudioStreamHandler->\
+                m_pDecoderSpecificInfo);
+            pC->mAudioStreamHandler->m_decoderSpecificInfoSize = 0;
+            pC->mAudioStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
+        }
+
+        if ((M4DA_StreamTypeAudioAac == pC->mAudioStreamHandler->m_streamType)
+            && (M4OSA_NULL != pC->mAudioStreamHandler->m_pUserData)) {
+            pAudioSbrUserData = (M4READER_AudioSbrUserdata*)(\
+                pC->mAudioStreamHandler->m_pUserData);
+
+            pAU = (M4_AccessUnit*)pAudioSbrUserData->m_pFirstAU;
+            if (M4OSA_NULL != pAU) {
+                free(pAU);
+            }
+
+            if (M4OSA_NULL != pAudioSbrUserData->m_pAacDecoderUserConfig) {
+                free(pAudioSbrUserData->\
+                    m_pAacDecoderUserConfig);
+            }
+            free(pAudioSbrUserData);
+            pC->mAudioStreamHandler->m_pUserData = M4OSA_NULL;
+        }
+
+        if (pC->mAudioStreamHandler->m_pESDSInfo != M4OSA_NULL) {
+            free(pC->mAudioStreamHandler->m_pESDSInfo);
+            pC->mAudioStreamHandler->m_pESDSInfo = M4OSA_NULL;
+            pC->mAudioStreamHandler->m_ESDSInfoSize = 0;
+        }
+        /* Finally destroy the stream handler */
+        free(pC->mAudioStreamHandler);
+        pC->mAudioStreamHandler = M4OSA_NULL;
+
+        pC->mAudioSource->stop();
+        pC->mAudioSource.clear();
+    }
+    if (pC->mVideoStreamHandler) {
+        ALOGV("VideoEditor3gpReader_close Video ");
+
+        if(M4OSA_NULL != pC->mVideoStreamHandler->m_pDecoderSpecificInfo) {
+            free(pC->mVideoStreamHandler->\
+                m_pDecoderSpecificInfo);
+            pC->mVideoStreamHandler->m_decoderSpecificInfoSize = 0;
+            pC->mVideoStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
+        }
+
+        if(M4OSA_NULL != pC->mVideoStreamHandler->m_pH264DecoderSpecificInfo) {
+            free(pC->mVideoStreamHandler->\
+                m_pH264DecoderSpecificInfo);
+            pC->mVideoStreamHandler->m_H264decoderSpecificInfoSize = 0;
+            pC->mVideoStreamHandler->m_pH264DecoderSpecificInfo = M4OSA_NULL;
+        }
+
+        if(pC->mVideoStreamHandler->m_pESDSInfo != M4OSA_NULL) {
+            free(pC->mVideoStreamHandler->m_pESDSInfo);
+            pC->mVideoStreamHandler->m_pESDSInfo = M4OSA_NULL;
+            pC->mVideoStreamHandler->m_ESDSInfoSize = 0;
+        }
+
+        /* Finally destroy the stream handler */
+        free(pC->mVideoStreamHandler);
+        pC->mVideoStreamHandler = M4OSA_NULL;
+
+        pC->mVideoSource->stop();
+        pC->mVideoSource.clear();
+    }
+    pC->mExtractor.clear();
+    pC->mDataSource.clear();
+
+    ALOGV("VideoEditor3gpReader_close end");
+    return err;
+}
+
+/**
+************************************************************************
+* @brief    get an option from the 3gp reader
+* @note     it allows the caller to retrieve a property value:
+*
+* @param    context:        (IN)    Context of the reader
+* @param    optionId:       (IN)    indicates the option to get
+* @param    pValue:         (OUT)   pointer to structure or value (allocated
+*                                   by user) where option is stored
+*
+* @return   M4NO_ERROR              there is no error
+* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
+* @return   M4ERR_PARAMETER         at least one parameter is not properly set
+* @return   M4ERR_BAD_OPTION_ID     when the option ID is not a valid one
+* @return   M4ERR_VIDEO_NOT_H263    No video stream H263 in file.
+* @return   M4ERR_NO_VIDEO_STREAM_RETRIEVED_YET
+*           Function 3gpReader_getNextStreamHandler must be called before
+************************************************************************
+*/
+M4OSA_ERR VideoEditor3gpReader_getOption(M4OSA_Context context,
+        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
+    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditor3gpReader_getOption begin %d", optionId);
+
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
+        "invalid context pointer");
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_getOption: invalid pointer on value");
+
+    switch (optionId) {
+    case M4READER_kOptionID_Duration:
+        {
+            ALOGV("VideoEditor3gpReader_getOption duration %d",pC->mMaxDuration);
+            *(M4OSA_Time*)pValue = pC->mMaxDuration;
+        }
+        break;
+    case M4READER_kOptionID_Version:
+        /* not used */
+        ALOGV("VideoEditor3gpReader_getOption: M4READER_kOptionID_Version");
+        break;
+
+    case M4READER_kOptionID_Copyright:
+        /* not used */
+        ALOGV(">>>>>>>   M4READER_kOptionID_Copyright");
+        break;
+
+    case M4READER_kOptionID_CreationTime:
+        /* not used */
+        ALOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_CreationTime");
+    break;
+
+    case M4READER_kOptionID_Bitrate:
+        {
+            M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue;
+
+            if (pC->mMaxDuration != 0) {
+                M4OSA_UInt32 ui32Tmp = (M4OSA_UInt32)pC->mMaxDuration;
+                *pBitrate = (M4OSA_UInt32)(pC->mFileSize * 8000.0 / pC->mMaxDuration);
+            }
+            ALOGV("VideoEditor3gpReader_getOption bitrate %ld", *pBitrate);
+        }
+    break;
+    case M4READER_3GP_kOptionID_H263Properties:
+        {
+            if(M4OSA_NULL == pC->mVideoStreamHandler) {
+                ALOGV("VideoEditor3gpReader_getOption no videoStream retrieved");
+
+                err = M4ERR_NO_VIDEO_STREAM_RETRIEVED_YET;
+                break;
+            }
+            if((M4DA_StreamTypeVideoH263 != pC->mVideoStreamHandler->\
+                m_streamType) || (pC->mVideoStreamHandler->\
+                m_decoderSpecificInfoSize < 7)) {
+                ALOGV("VideoEditor3gpReader_getOption DSI Size %d",
+                    pC->mVideoStreamHandler->m_decoderSpecificInfoSize);
+
+                err = M4ERR_VIDEO_NOT_H263;
+                break;
+            }
+
+            /* MAGICAL in the decoder confi H263: the 7th byte is the profile
+             * number, 6th byte is the level number */
+            ((M4READER_3GP_H263Properties *)pValue)->uiProfile =
+                pC->mVideoStreamHandler->m_pDecoderSpecificInfo[6];
+            ((M4READER_3GP_H263Properties *)pValue)->uiLevel =
+                pC->mVideoStreamHandler->m_pDecoderSpecificInfo[5];
+            ALOGV("VideoEditor3gpReader_getOption M4READER_3GP_kOptionID_\
+            H263Properties end");
+        }
+        break;
+    case M4READER_3GP_kOptionID_PurpleLabsDrm:
+        ALOGV("VideoEditor3gpReaderOption M4READER_3GP_kOptionID_PurpleLabsDrm");
+        /* not used */
+        break;
+
+    case M4READER_kOptionID_GetNumberOfAudioAu:
+        /* not used */
+        ALOGV("VideoEditor3gpReadeOption M4READER_kOptionID_GetNumberOfAudioAu");
+    break;
+
+    case M4READER_kOptionID_GetNumberOfVideoAu:
+        /* not used */
+        ALOGV("VideoEditor3gpReader_getOption :GetNumberOfVideoAu");
+    break;
+
+    case M4READER_kOptionID_GetMetadata:
+        /* not used */
+        ALOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_GetMetadata");
+    break;
+
+    case M4READER_kOptionID_3gpFtypBox:
+        /* used only for SEMC */
+        ALOGV("VideoEditor3gpReader_getOption M4READER_kOptionID_3gpFtypBox");
+        err = M4ERR_BAD_OPTION_ID; //check this
+        break;
+
+#ifdef OPTIONID_GET_NEXT_VIDEO_CTS
+    case M4READER_3GP_kOptionID_getNextVideoCTS:
+        /* not used */
+        ALOGV("VideoEditor3gpReader_getOption: getNextVideoCTS");
+        break;
+#endif
+    default:
+        {
+            err = M4ERR_BAD_OPTION_ID;
+            ALOGV("VideoEditor3gpReader_getOption M4ERR_BAD_OPTION_ID");
+        }
+        break;
+    }
+    ALOGV("VideoEditor3gpReader_getOption end: optionID: x%x", optionId);
+    return err;
+}
+/**
+************************************************************************
+* @brief    set an option on the 3gp reader
+* @note No option can be set yet.
+* @param    context:        (IN)    Context of the reader
+* @param    optionId:       (IN)    indicates the option to set
+* @param    pValue:         (IN)    pointer to structure or value (allocated
+*                                   by user) where option is stored
+* @return   M4NO_ERROR              there is no error
+* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
+* @return   M4ERR_PARAMETER         at least one parameter is not properly set
+* @return   M4ERR_BAD_OPTION_ID     when the option ID is not a valid one
+************************************************************************
+*/
+M4OSA_ERR VideoEditor3gpReader_setOption(M4OSA_Context context,
+        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
+    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+
+    /* Check function parameters */
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pC), M4ERR_PARAMETER,
+        "invalid context pointer");
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
+        "invalid value pointer");
+
+    ALOGV("VideoEditor3gpReader_setOption begin %d",optionId);
+
+    switch(optionId) {
+        case M4READER_kOptionID_SetOsaFileReaderFctsPtr:
+        break;
+
+        case M4READER_3GP_kOptionID_AudioOnly:
+        break;
+
+        case M4READER_3GP_kOptionID_VideoOnly:
+        break;
+
+        case M4READER_3GP_kOptionID_FastOpenMode:
+        break;
+
+        case M4READER_kOptionID_MaxMetadataSize:
+        break;
+
+        default:
+        {
+            ALOGV("VideoEditor3gpReader_setOption: returns M4ERR_BAD_OPTION_ID");
+            err = M4ERR_BAD_OPTION_ID;
+        }
+        break;
+    }
+    ALOGV("VideoEditor3gpReader_setOption end ");
+    return err;
+}
+/**
+ ************************************************************************
+ * @brief   fill the access unit structure with initialization values
+ * @param   context:        (IN)     Context of the reader
+ * @param   pStreamHandler: (IN)     pointer to the stream handler to which
+ *                                   the access unit will be associated
+ * @param   pAccessUnit:    (IN/OUT) pointer to the access unit (allocated
+ *                                   by the caller) to initialize
+ * @return  M4NO_ERROR               there is no error
+ * @return  M4ERR_PARAMETER          at least one parameter is not properly set
+ ************************************************************************
+*/
+M4OSA_ERR VideoEditor3gpReader_fillAuStruct(M4OSA_Context context,
+        M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
+    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
+    M4OSA_ERR err= M4NO_ERROR;
+
+    M4OSA_DEBUG_IF1((pC == 0),             M4ERR_PARAMETER,
+        "VideoEditor3gpReader_fillAuStruct: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_fillAuStruc invalid pointer to M4_StreamHandler");
+    M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
+        "VideoEditor3gpReader_fillAuStruct: invalid pointer to M4_AccessUnit");
+
+    ALOGV("VideoEditor3gpReader_fillAuStruct begin");
+
+    /* Initialize pAccessUnit structure */
+    pAccessUnit->m_size         = 0;
+    pAccessUnit->m_CTS          = 0;
+    pAccessUnit->m_DTS          = 0;
+    pAccessUnit->m_attribute    = 0;
+    pAccessUnit->m_dataAddress  = M4OSA_NULL;
+    pAccessUnit->m_maxsize      = pStreamHandler->m_maxAUSize;
+    pAccessUnit->m_streamID     = pStreamHandler->m_streamId;
+    pAccessUnit->m_structSize   = sizeof(M4_AccessUnit);
+
+    ALOGV("VideoEditor3gpReader_fillAuStruct end");
+    return M4NO_ERROR;
+}
+
+/**
+********************************************************************************
+* @brief    jump into the stream at the specified time
+* @note
+* @param    context:        (IN)   Context of the reader
+* @param    pStreamHandler  (IN)   the stream handler of the stream to make jump
+* @param    pTime           (I/O)IN  the time to jump to (in ms)
+*                                OUT the time to which the stream really jumped
+* @return   M4NO_ERROR             there is no error
+* @return   M4ERR_PARAMETER        at least one parameter is not properly set
+********************************************************************************
+*/
+M4OSA_ERR VideoEditor3gpReader_jump(M4OSA_Context context,
+        M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime) {
+    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+    M4SYS_AccessUnit* pAu;
+    M4OSA_Time time64;
+
+    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_jump: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_jump: invalid pointer to M4_StreamHandler");
+    M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_jump: invalid time pointer");
+
+    ALOGV("VideoEditor3gpReader_jump begin");
+
+    if (*pTime == (pStreamHandler->m_duration)) {
+        *pTime -= 1;
+    }
+    time64 = (M4OSA_Time)*pTime;
+
+    ALOGV("VideoEditor3gpReader_jump time us %ld ", time64);
+
+    if ((pC->mAudioStreamHandler != M4OSA_NULL) &&
+            (pStreamHandler->m_streamId == pC->mAudioStreamHandler->m_streamId))
+            {
+        pAu = &pC->mAudioAu;
+        pAu->CTS = time64;
+        pAu->DTS = time64;
+
+        time64 = time64 * 1000; /* Convert the time into micro sec */
+        pC->mAudioSeeking = M4OSA_TRUE;
+        pC->mAudioSeekTime = time64;
+        ALOGV("VideoEditor3gpReader_jump AUDIO time us %ld ", time64);
+    } else if ((pC->mVideoStreamHandler != M4OSA_NULL) &&
+            (pStreamHandler->m_streamId == pC->mVideoStreamHandler->m_streamId))
+            {
+        pAu = &pC->mVideoAu;
+        pAu->CTS = time64;
+        pAu->DTS = time64;
+
+        time64 = time64 * 1000; /* Convert the time into micro sec */
+        pC->mVideoSeeking = M4OSA_TRUE;
+        pC->mVideoSeekTime = time64;
+        ALOGV("VideoEditor3gpReader_jump VIDEO time us %ld ", time64);
+    } else {
+        ALOGV("VideoEditor3gpReader_jump passed StreamHandler is not known\n");
+        return M4ERR_PARAMETER;
+    }
+    time64 = time64 / 1000; /* Convert the time into milli sec */
+    ALOGV("VideoEditor3gpReader_jump time ms before seekset %ld ", time64);
+
+    *pTime = (M4OSA_Int32)time64;
+
+    ALOGV("VideoEditor3gpReader_jump end");
+    err = M4NO_ERROR;
+    return err;
+}
+/**
+********************************************************************************
+* @brief    reset the stream, that is seek it to beginning and make it ready
+* @note
+* @param    context:        (IN)    Context of the reader
+* @param    pStreamHandler  (IN)    The stream handler of the stream to reset
+* @return   M4NO_ERROR              there is no error
+* @return   M4ERR_PARAMETER         at least one parameter is not properly set
+********************************************************************************
+*/
+M4OSA_ERR VideoEditor3gpReader_reset(M4OSA_Context context,
+        M4_StreamHandler *pStreamHandler) {
+    VideoEditor3gpReader_Context* pC = (VideoEditor3gpReader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+    M4SYS_StreamID streamIdArray[2];
+    M4SYS_AccessUnit* pAu;
+    M4OSA_Time time64 = 0;
+
+    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_reset: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_reset: invalid pointer to M4_StreamHandler");
+
+    ALOGV("VideoEditor3gpReader_reset begin");
+
+    if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
+        pAu = &pC->mAudioAu;
+    } else if (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler) {
+        pAu = &pC->mVideoAu;
+    } else {
+        ALOGV("VideoEditor3gpReader_reset passed StreamHandler is not known\n");
+        return M4ERR_PARAMETER;
+    }
+
+    pAu->CTS = time64;
+    pAu->DTS = time64;
+
+    ALOGV("VideoEditor3gpReader_reset end");
+    return err;
+}
+
+/**
+********************************************************************************
+* @brief  Gets an access unit (AU) from the stream handler source.
+* @note   An AU is the smallest possible amount of data to be decoded by decoder
+*
+* @param    context:        (IN) Context of the reader
+* @param    pStreamHandler  (IN) The stream handler of the stream to make jump
+* @param    pAccessUnit     (IO) Pointer to access unit to fill with read data
+* @return   M4NO_ERROR           there is no error
+* @return   M4ERR_PARAMETER      at least one parameter is not properly set
+* @returns  M4ERR_ALLOC          memory allocation failed
+* @returns  M4WAR_NO_MORE_AU     there are no more access unit in the stream
+********************************************************************************
+*/
+M4OSA_ERR VideoEditor3gpReader_getNextAu(M4OSA_Context context,
+        M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
+    VideoEditor3gpReader_Context* pC=(VideoEditor3gpReader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+    M4SYS_AccessUnit* pAu;
+    int64_t tempTime64 = 0;
+    MediaBuffer *mMediaBuffer = NULL;
+    MediaSource::ReadOptions options;
+    M4OSA_Bool flag = M4OSA_FALSE;
+    status_t error;
+    int32_t i32Tmp = 0;
+
+    M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_getNextAu: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_getNextAu: invalid pointer to M4_StreamHandler");
+    M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
+        "VideoEditor3gpReader_getNextAu: invalid pointer to M4_AccessUnit");
+
+    ALOGV("VideoEditor3gpReader_getNextAu begin");
+
+    if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
+        ALOGV("VideoEditor3gpReader_getNextAu audio stream");
+        pAu = &pC->mAudioAu;
+        if (pC->mAudioSeeking == M4OSA_TRUE) {
+            ALOGV("VideoEditor3gpReader_getNextAu audio seek time: %ld",
+                pC->mAudioSeekTime);
+            options.setSeekTo(pC->mAudioSeekTime);
+            pC->mAudioSource->read(&mMediaBuffer, &options);
+
+            mMediaBuffer->meta_data()->findInt64(kKeyTime,
+                (int64_t*)&tempTime64);
+            options.clearSeekTo();
+            pC->mAudioSeeking = M4OSA_FALSE;
+            flag = M4OSA_TRUE;
+        } else {
+            ALOGV("VideoEditor3gpReader_getNextAu audio no seek:");
+            pC->mAudioSource->read(&mMediaBuffer, &options);
+            if (mMediaBuffer != NULL) {
+                mMediaBuffer->meta_data()->findInt64(kKeyTime,
+                    (int64_t*)&tempTime64);
+            }
+        }
+    } else if (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler) {
+        ALOGV("VideoEditor3gpReader_getNextAu video steram ");
+        pAu = &pC->mVideoAu;
+        if(pC->mVideoSeeking == M4OSA_TRUE) {
+            flag = M4OSA_TRUE;
+            ALOGV("VideoEditor3gpReader_getNextAu seek: %ld",pC->mVideoSeekTime);
+            options.setSeekTo(pC->mVideoSeekTime,
+                MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+            do
+            {
+                if (mMediaBuffer != NULL) {
+                    ALOGV("VideoEditor3gpReader_getNextAu free the MediaBuffer");
+                    mMediaBuffer->release();
+                }
+                error = pC->mVideoSource->read(&mMediaBuffer, &options);
+                ALOGV("VE3gpReader_getNextAu MediaBuffer %x , error %d",
+                    mMediaBuffer, error);
+                if (mMediaBuffer != NULL)
+                {
+                    if (mMediaBuffer->meta_data()->findInt32(kKeyIsSyncFrame,
+                        &i32Tmp) && i32Tmp) {
+                            ALOGV("SYNC FRAME FOUND--%d", i32Tmp);
+                        pAu->attribute = AU_RAP;
+                    }
+                    else {
+                        pAu->attribute = AU_P_Frame;
+                    }
+                    mMediaBuffer->meta_data()->findInt64(kKeyTime,
+                        (int64_t*)&tempTime64);
+                } else {
+                    break;
+                }
+                options.clearSeekTo();
+            } while(tempTime64 < pC->mVideoSeekTime);
+
+            ALOGV("VE3gpReader_getNextAu: video  time with seek  = %lld:",
+                tempTime64);
+            pC->mVideoSeeking = M4OSA_FALSE;
+        } else {
+            ALOGV("VideoEditor3gpReader_getNextAu video no seek:");
+            pC->mVideoSource->read(&mMediaBuffer, &options);
+
+            if(mMediaBuffer != NULL) {
+                if (mMediaBuffer->meta_data()->findInt32(kKeyIsSyncFrame,
+                    &i32Tmp) && i32Tmp) {
+                    ALOGV("SYNC FRAME FOUND--%d", i32Tmp);
+                    pAu->attribute = AU_RAP;
+                }
+                else {
+                    pAu->attribute = AU_P_Frame;
+                }
+                mMediaBuffer->meta_data()->findInt64(kKeyTime,
+                    (int64_t*)&tempTime64);
+                ALOGV("VE3gpReader_getNextAu: video no seek time = %lld:",
+                    tempTime64);
+            }else {
+                ALOGV("VE3gpReader_getNextAu:video no seek time buffer is NULL");
+            }
+        }
+    } else {
+        ALOGV("VideoEditor3gpReader_getNextAu M4ERR_PARAMETER");
+        return M4ERR_PARAMETER;
+    }
+
+    if (mMediaBuffer != NULL) {
+        if( (pAu->dataAddress == NULL) ||  (pAu->size < \
+            mMediaBuffer->range_length())) {
+            if(pAu->dataAddress != NULL) {
+                free((M4OSA_Int32*)pAu->dataAddress);
+                pAu->dataAddress = NULL;
+            }
+            ALOGV("Buffer lenght = %d ,%d",(mMediaBuffer->range_length() +\
+                3) & ~0x3,(mMediaBuffer->range_length()));
+
+            pAu->dataAddress = (M4OSA_Int32*)M4OSA_32bitAlignedMalloc(
+                (mMediaBuffer->range_length() + 3) & ~0x3,M4READER_3GP,
+                    (M4OSA_Char*)"pAccessUnit->m_dataAddress" );
+            if(pAu->dataAddress == NULL) {
+                ALOGV("VideoEditor3gpReader_getNextAu malloc failed");
+                return M4ERR_ALLOC;
+            }
+        }
+        pAu->size = mMediaBuffer->range_length();
+
+        memcpy((void *)pAu->dataAddress,
+            (void *)((const char *)mMediaBuffer->data() + mMediaBuffer->range_offset()),
+            mMediaBuffer->range_length());
+
+        if( (pStreamHandler == (M4_StreamHandler*)pC->mVideoStreamHandler)  &&
+            (pStreamHandler->m_streamType == M4DA_StreamTypeVideoMpeg4Avc) ) {
+            M4OSA_UInt32 size = mMediaBuffer->range_length();
+            M4OSA_UInt8 *lbuffer;
+
+            lbuffer = (M4OSA_UInt8 *) pAu->dataAddress;
+            ALOGV("pAccessUnit->m_dataAddress size = %x",size);
+
+            lbuffer[0] = (size >> 24) & 0xFF;
+            lbuffer[1] = (size >> 16) & 0xFF;
+            lbuffer[2] = (size >> 8) & 0xFF;
+            lbuffer[3] = (size) & 0xFF;
+        }
+
+        pAu->CTS = tempTime64;
+
+        pAu->CTS = pAu->CTS / 1000; //converting the microsec to millisec
+        ALOGV("VideoEditor3gpReader_getNextAu CTS = %ld",pAu->CTS);
+
+        pAu->DTS  = pAu->CTS;
+        if (pStreamHandler == (M4_StreamHandler*)pC->mAudioStreamHandler) {
+            pAu->attribute = M4SYS_kFragAttrOk;
+        }
+        mMediaBuffer->release();
+
+        pAccessUnit->m_dataAddress = (M4OSA_Int8*) pAu->dataAddress;
+        pAccessUnit->m_size = pAu->size;
+        pAccessUnit->m_maxsize = pAu->size;
+        pAccessUnit->m_CTS = pAu->CTS;
+        pAccessUnit->m_DTS = pAu->DTS;
+        pAccessUnit->m_attribute = pAu->attribute;
+
+    } else {
+        ALOGV("VideoEditor3gpReader_getNextAu: M4WAR_NO_MORE_AU (EOS) reached");
+        pAccessUnit->m_size = 0;
+        err = M4WAR_NO_MORE_AU;
+    }
+    options.clearSeekTo();
+
+    pAu->nbFrag = 0;
+    mMediaBuffer = NULL;
+    ALOGV("VideoEditor3gpReader_getNextAu end ");
+
+    return err;
+}
+/**
+ *******************************************************************************
+ * @brief   Split the AVC DSI in its different components and write it in
+ *          ONE memory buffer
+ * @note
+ * @param   pStreamHandler:         (IN/OUT) The MPEG4-AVC stream
+ * @param   pDecoderConfigLocal:    (IN) The DSI buffer
+ * @param   decoderConfigSizeLocal: (IN) The DSI buffer size
+ * @return  M4NO_ERROR              there is no error
+ * @return  ERR_FILE_SYNTAX_ERROR   pDecoderConfigLocal is NULL
+ *******************************************************************************
+*/
+static M4OSA_ERR VideoEditor3gpReader_AnalyseAvcDsi(
+        M4_StreamHandler *pStreamHandler, M4OSA_Int32* pDecoderConfigLocal,
+        M4OSA_Int32 decoderConfigSizeLocal) {
+    struct _avcSpecificInfo *pAvcSpecInfo = M4OSA_NULL;
+    M4OSA_UInt32 uiSpecInfoSize;
+    M4OSA_Context pBitParserContext = M4OSA_NULL;
+    M4OSA_MemAddr8 pPos;
+
+    /**
+     * First parsing to get the total allocation size (we must not do
+     * multiple malloc, but only one instead) */
+    {
+        M4OSA_Int32 val;
+        M4OSA_UInt32 i,j;
+        M4OSA_UInt8 nalUnitLength;
+        M4OSA_UInt8  numOfSequenceParameterSets;
+        M4OSA_UInt32 uiTotalSizeOfSPS = 0;
+        M4OSA_UInt8  numOfPictureParameterSets;
+        M4OSA_UInt32 uiTotalSizeOfPPS = 0;
+        M4OSA_UInt32 uiSize;
+        struct _avcSpecificInfo avcSpIf;
+
+        avcSpIf.m_nalUnitLength = 0;
+
+        if (M4OSA_NULL == pDecoderConfigLocal) {
+            return M4ERR_READER3GP_DECODER_CONFIG_ERROR;
+        }
+
+        VideoEditor3gpReader_MPEG4BitStreamParserInit(&pBitParserContext,
+            pDecoderConfigLocal, decoderConfigSizeLocal);
+
+        if (M4OSA_NULL == pBitParserContext) {
+            return M4ERR_ALLOC;
+        }
+
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+                                       /* 8 bits -- configuration version */
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+                                       /* 8 bits -- avc profile indication*/
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+                                       /* 8 bits -- profile compatibility */
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+                                       /* 8 bits -- avc level indication*/
+        val=VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext, 8);
+                       /* 6 bits reserved 111111b 2 bits length Size minus one*/
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+                                       /* m_nalUnitLength */
+
+        nalUnitLength = (M4OSA_UInt8)((val & 0x03) + 1);/*0b11111100*/
+        if (nalUnitLength > 4) {
+            pStreamHandler->m_decoderSpecificInfoSize = 0;
+            pStreamHandler->m_pDecoderSpecificInfo = M4OSA_NULL;
+            VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
+        } else {
+            /**
+             * SPS table */
+            val=VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext,
+            8);/* 3 bits-reserved 111b-5 bits number of sequence parameter set*/
+            numOfSequenceParameterSets = val & 0x1F;
+            /*1F instead of E0*/ /*0b11100000*/ /*Number of seq parameter sets*/
+            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+            for (i=0; i < numOfSequenceParameterSets; i++) {
+                /**
+                 * Get the size of this element */
+                uiSize =
+                    (M4OSA_UInt32)VideoEditor3gpReader_BitStreamParserShowBits(
+                    pBitParserContext, 16);
+                uiTotalSizeOfSPS += uiSize;
+                VideoEditor3gpReader_BitStreamParserFlushBits(
+                    pBitParserContext, 16);
+                /**
+                 *Read the element(dont keep it, we only want size right now) */
+                for (j=0; j<uiSize; j++) {
+                    VideoEditor3gpReader_BitStreamParserFlushBits(
+                        pBitParserContext, 8);
+                }
+            }
+
+            /**
+             * SPS table */
+            numOfPictureParameterSets=(M4OSA_UInt8)\
+                VideoEditor3gpReader_BitStreamParserShowBits(pBitParserContext,
+                    8);
+            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+            for (i=0; i < numOfPictureParameterSets; i++) {
+                /**
+                 * Get the size of this element */
+                uiSize = (M4OSA_UInt32)
+                    VideoEditor3gpReader_BitStreamParserShowBits(
+                    pBitParserContext, 16);
+                uiTotalSizeOfPPS += uiSize;
+                VideoEditor3gpReader_BitStreamParserFlushBits(
+                    pBitParserContext, 16);
+                /**
+                 *Read the element(dont keep it,we only want size right now)*/
+                for (j=0; j<uiSize; j++) {
+                    VideoEditor3gpReader_BitStreamParserFlushBits(
+                        pBitParserContext, 8);
+                }
+            }
+
+            /**
+             * Compute the size of the full buffer */
+            uiSpecInfoSize = sizeof(struct _avcSpecificInfo) +
+                     numOfSequenceParameterSets * sizeof(struct _parameterSet)
+                     + /**< size of the table of SPS elements */
+                     numOfPictureParameterSets  * sizeof(struct _parameterSet)
+                     + /**< size of the table of PPS elements */
+                     uiTotalSizeOfSPS +
+                     uiTotalSizeOfPPS;
+            /**
+             * Allocate the buffer */
+            pAvcSpecInfo =(struct _avcSpecificInfo*)M4OSA_32bitAlignedMalloc(uiSpecInfoSize,
+                M4READER_3GP, (M4OSA_Char*)"MPEG-4 AVC DecoderSpecific");
+            if (M4OSA_NULL == pAvcSpecInfo) {
+                VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
+                return M4ERR_ALLOC;
+            }
+
+            /**
+             * Set the pointers to the correct part of the buffer */
+            pAvcSpecInfo->m_nalUnitLength = nalUnitLength;
+            pAvcSpecInfo->m_numOfSequenceParameterSets =
+                numOfSequenceParameterSets;
+            pAvcSpecInfo->m_numOfPictureParameterSets  =
+                numOfPictureParameterSets;
+
+            /* We place the SPS param sets table after m_pPictureParameterSet */
+            pAvcSpecInfo->m_pSequenceParameterSet= (struct _parameterSet*)(
+                (M4OSA_MemAddr8)(&pAvcSpecInfo->m_pPictureParameterSet) +
+                sizeof(pAvcSpecInfo->m_pPictureParameterSet));
+            /*We place the PPS param sets table after the SPS param sets table*/
+            pAvcSpecInfo->m_pPictureParameterSet = (struct _parameterSet*)(
+                (M4OSA_MemAddr8)(pAvcSpecInfo->m_pSequenceParameterSet) +
+                (numOfSequenceParameterSets * sizeof(struct _parameterSet)));
+            /**< The data will be placed after the PPS param sets table */
+            pPos = (M4OSA_MemAddr8)pAvcSpecInfo->m_pPictureParameterSet +
+                (numOfPictureParameterSets * sizeof(struct _parameterSet));
+
+            /**
+             * reset the bit parser */
+            VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
+        }
+    }
+
+    /**
+     * Second parsing to copy the data */
+    if (M4OSA_NULL != pAvcSpecInfo) {
+        M4OSA_Int32 i,j;
+
+        VideoEditor3gpReader_MPEG4BitStreamParserInit(&pBitParserContext,
+            pDecoderConfigLocal, decoderConfigSizeLocal);
+
+        if (M4OSA_NULL == pBitParserContext) {
+            free(pAvcSpecInfo);
+            return M4ERR_ALLOC;
+        }
+
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+            /* 8 bits -- configuration version */
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+            /* 8 bits -- avc profile indication*/
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+            /* 8 bits -- profile compatibility */
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+            /* 8 bits -- avc level indication*/
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+            /* m_nalUnitLength */
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+        /* 3 bits -- reserved 111b -- 5 bits number of sequence parameter set*/
+
+        for (i=0; i < pAvcSpecInfo->m_numOfSequenceParameterSets; i++) {
+            pAvcSpecInfo->m_pSequenceParameterSet[i].m_length =
+                (M4OSA_UInt16)VideoEditor3gpReader_BitStreamParserShowBits(
+                pBitParserContext, 16);
+            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext,16);
+
+            pAvcSpecInfo->m_pSequenceParameterSet[i].m_pParameterSetUnit =
+                (M4OSA_UInt8*)pPos;  /**< current position in the buffer */
+            pPos += pAvcSpecInfo->m_pSequenceParameterSet[i].m_length;
+                /**< increment the position in the buffer */
+            for (j=0; j<pAvcSpecInfo->m_pSequenceParameterSet[i].m_length;j++){
+                pAvcSpecInfo->m_pSequenceParameterSet[i].m_pParameterSetUnit[j]=
+                    (M4OSA_UInt8)VideoEditor3gpReader_BitStreamParserShowBits(
+                    pBitParserContext, 8);
+                VideoEditor3gpReader_BitStreamParserFlushBits(
+                    pBitParserContext, 8);
+            }
+        }
+
+        VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext, 8);
+            /* number of pîcture parameter set*/
+
+        for (i=0; i < pAvcSpecInfo->m_numOfPictureParameterSets; i++) {
+            pAvcSpecInfo->m_pPictureParameterSet[i].m_length =
+                (M4OSA_UInt16)VideoEditor3gpReader_BitStreamParserShowBits(
+                pBitParserContext, 16);
+            VideoEditor3gpReader_BitStreamParserFlushBits(pBitParserContext,16);
+
+            pAvcSpecInfo->m_pPictureParameterSet[i].m_pParameterSetUnit =
+                (M4OSA_UInt8*)pPos;   /**< current position in the buffer */
+            pPos += pAvcSpecInfo->m_pPictureParameterSet[i].m_length;
+                /**< increment the position in the buffer */
+            for (j=0; j<pAvcSpecInfo->m_pPictureParameterSet[i].m_length; j++) {
+                pAvcSpecInfo->m_pPictureParameterSet[i].m_pParameterSetUnit[j] =
+                    (M4OSA_UInt8)VideoEditor3gpReader_BitStreamParserShowBits(
+                    pBitParserContext, 8);
+                VideoEditor3gpReader_BitStreamParserFlushBits(
+                    pBitParserContext, 8);
+            }
+        }
+        VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
+        pStreamHandler->m_decoderSpecificInfoSize = uiSpecInfoSize;
+        pStreamHandler->m_pDecoderSpecificInfo = (M4OSA_UInt8*)pAvcSpecInfo;
+    }
+    pStreamHandler->m_H264decoderSpecificInfoSize  =  decoderConfigSizeLocal;
+    pStreamHandler->m_pH264DecoderSpecificInfo  = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
+        decoderConfigSizeLocal, M4READER_3GP,
+        (M4OSA_Char*)"MPEG-4 AVC DecoderSpecific");
+    if (M4OSA_NULL == pStreamHandler->m_pH264DecoderSpecificInfo) {
+        goto cleanup;
+    }
+
+    memcpy((void * ) pStreamHandler->m_pH264DecoderSpecificInfo,
+        (void * )pDecoderConfigLocal,
+        pStreamHandler->m_H264decoderSpecificInfoSize);
+    return M4NO_ERROR;
+cleanup:
+    VideoEditor3gpReader_BitStreamParserCleanUp(pBitParserContext);
+    return M4ERR_READER3GP_DECODER_CONFIG_ERROR;
+}
+/**
+********************************************************************************
+* @brief    Get the next stream found in the 3gp file
+* @note
+* @param    context:     (IN)    Context of the reader
+* @param    pMediaFamily: OUT)   pointer to a user allocated
+*                                M4READER_MediaFamily that will be filled
+*                                with the media family of the found stream
+* @param    pStreamHandler:(OUT) pointer to StreamHandler that will be allocated
+*                                and filled with the found stream description
+* @return   M4NO_ERROR              there is no error
+* @return   M4ERR_BAD_CONTEXT       provided context is not a valid one
+* @return   M4ERR_PARAMETER         at least one parameter is not properly set
+* @return   M4WAR_NO_MORE_STREAM    no more available stream in the media
+********************************************************************************
+*/
+M4OSA_ERR VideoEditor3gpReader_getNextStreamHandler(M4OSA_Context context,
+        M4READER_MediaFamily *pMediaFamily,
+        M4_StreamHandler **pStreamHandler) {
+    VideoEditor3gpReader_Context* pC=(VideoEditor3gpReader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+    M4SYS_StreamID streamIdArray[2];
+    M4SYS_StreamDescription streamDesc;
+    M4_AudioStreamHandler* pAudioStreamHandler;
+    M4_VideoStreamHandler* pVideoStreamHandler;
+    M4OSA_Int8 *DecoderSpecificInfo = M4OSA_NULL;
+    M4OSA_Int32 decoderSpecificInfoSize =0, maxAUSize = 0;
+
+    M4_StreamType streamType = M4DA_StreamTypeUnknown;
+    M4OSA_UInt8 temp, i, trackCount;
+    M4OSA_Bool haveAudio = M4OSA_FALSE;
+    M4OSA_Bool haveVideo = M4OSA_FALSE;
+    sp<MetaData> meta  = NULL;
+    int64_t Duration = 0;
+    M4OSA_UInt8* DecoderSpecific = M4OSA_NULL ;
+    uint32_t type;
+    const void *data;
+    size_t size;
+    const void *codec_specific_data;
+    size_t codec_specific_data_size;
+    M4OSA_Int32  ptempTime;
+    M4OSA_Int32  avgFPS=0;
+
+    ALOGV("VideoEditor3gpReader_getNextStreamHandler begin");
+
+    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_getNextStreamHandler: invalid context");
+    M4OSA_DEBUG_IF1((pMediaFamily   == 0), M4ERR_PARAMETER,
+        "getNextStreamHandler: invalid pointer to MediaFamily");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "getNextStreamHandler: invalid pointer to StreamHandler");
+
+    trackCount = pC->mExtractor->countTracks();
+    temp = pC->mCurrTrack;
+
+    if(temp >= trackCount) {
+        ALOGV("VideoEditor3gpReader_getNextStreamHandler error = %d",
+            M4WAR_NO_MORE_STREAM);
+        return (M4WAR_NO_MORE_STREAM);
+    } else {
+        const char *mime;
+        meta = pC->mExtractor->getTrackMetaData(temp);
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
+            pC->mVideoSource = pC->mExtractor->getTrack(temp);
+            pC->mVideoSource->start();
+
+            *pMediaFamily = M4READER_kMediaFamilyVideo;
+            haveVideo = true;
+            ALOGV("VideoEditor3gpReader_getNextStreamHandler getTrack called");
+            if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+                streamType = M4DA_StreamTypeVideoMpeg4Avc;
+            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_H263)) {
+                streamType = M4DA_StreamTypeVideoH263;
+            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
+                streamType = M4DA_StreamTypeVideoMpeg4;
+            } else {
+                ALOGV("VideoEditor3gpReaderGetNextStreamHandler streamTypeNONE");
+            }
+            ALOGV("VideoEditor3gpReader_getNextStreamHandler: stream type: %d ",
+                streamType);
+
+            if(streamType != M4DA_StreamTypeUnknown) {
+                pC->mStreamType = streamType;
+                pC->mStreamId = pC->mCurrTrack;
+
+                pVideoStreamHandler = (M4_VideoStreamHandler*)M4OSA_32bitAlignedMalloc
+                    (sizeof(M4_VideoStreamHandler), M4READER_3GP,
+                    (M4OSA_Char*)"M4_VideoStreamHandler");
+                if (M4OSA_NULL == pVideoStreamHandler) {
+                    return M4ERR_ALLOC;
+                }
+                pVideoStreamHandler->m_structSize=sizeof(M4_VideoStreamHandler);
+
+                meta->findInt32(kKeyWidth,
+                    (int32_t*)&(pVideoStreamHandler->m_videoWidth));
+                meta->findInt32(kKeyHeight,
+                    (int32_t*)&(pVideoStreamHandler->m_videoHeight));
+
+                (*pStreamHandler)  = (M4_StreamHandler*)(pVideoStreamHandler);
+                meta->findInt64(kKeyDuration,
+                    (int64_t*)&(Duration));
+                ((*pStreamHandler)->m_duration) =
+                    (int32_t)((Duration)/1000); // conversion to mS
+                pC->mMaxDuration = ((*pStreamHandler)->m_duration);
+                ALOGV("VideoEditor3gpReader_getNextStreamHandler m_duration %d",
+                    (*pStreamHandler)->m_duration);
+
+                off64_t fileSize = 0;
+                pC->mDataSource->getSize(&fileSize);
+                pC->mFileSize  = fileSize;
+
+                ALOGV("VideoEditor3gpReader_getNextStreamHandler m_fileSize %d",
+                    pC->mFileSize);
+
+                meta->findInt32(kKeyMaxInputSize, (int32_t*)&(maxAUSize));
+                if(maxAUSize == 0) {
+                    maxAUSize = 70000;
+                }
+                (*pStreamHandler)->m_maxAUSize = maxAUSize;
+                ALOGV("<<<<<<<<<<   video: mMaxAUSize from MP4 extractor: %d",
+                    (*pStreamHandler)->m_maxAUSize);
+
+                ((M4_StreamHandler*)pVideoStreamHandler)->m_averageBitRate =
+                        (pC->mFileSize * 8000)/pC->mMaxDuration;
+                ALOGV("VideoEditor3gpReader_getNextStreamHandler m_averageBitrate %d",
+                    ((M4_StreamHandler*)pVideoStreamHandler)->m_averageBitRate);
+
+
+                meta->findInt32(kKeyFrameRate,
+                    (int32_t*)&(avgFPS));
+                ALOGV("<<<<<<<<<<   video: Average FPS from MP4 extractor: %d",
+                    avgFPS);
+
+                pVideoStreamHandler->m_averageFrameRate =(M4OSA_Float) avgFPS;
+                ALOGV("<<<<<<<<<<   video: Average FPS from MP4 extractor in FLOAT: %f",
+                    pVideoStreamHandler->m_averageFrameRate);
+
+                // Get the video rotation degree
+                int32_t rotationDegree;
+                if(!meta->findInt32(kKeyRotation, &rotationDegree)) {
+                    rotationDegree = 0;
+                }
+                pVideoStreamHandler->videoRotationDegrees = rotationDegree;
+
+                pC->mVideoStreamHandler =
+                    (M4_StreamHandler*)(pVideoStreamHandler);
+
+                /* Get the DSI info */
+                if(M4DA_StreamTypeVideoH263 == streamType) {
+                    if (meta->findData(kKeyD263, &type, &data, &size)) {
+                        (*pStreamHandler)->m_decoderSpecificInfoSize = size;
+                        if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
+                            DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
+                                (*pStreamHandler)->m_decoderSpecificInfoSize,
+                                M4READER_3GP,(M4OSA_Char*)"H263 DSI");
+                            if (M4OSA_NULL == DecoderSpecific) {
+                                return M4ERR_ALLOC;
+                            }
+                            memcpy((void *)DecoderSpecific,
+                                (void *)data, size);
+                            (*pStreamHandler)->m_pDecoderSpecificInfo =
+                                DecoderSpecific;
+                        }
+                        else {
+                            (*pStreamHandler)->m_pDecoderSpecificInfo =
+                                M4OSA_NULL;
+                            (*pStreamHandler)->m_decoderSpecificInfoSize = 0;
+                        }
+                        (*pStreamHandler)->m_pESDSInfo = M4OSA_NULL;
+                        (*pStreamHandler)->m_ESDSInfoSize = 0;
+                        (*pStreamHandler)->m_pH264DecoderSpecificInfo = M4OSA_NULL;
+                        (*pStreamHandler)->m_H264decoderSpecificInfoSize = 0;
+                    } else {
+                        ALOGV("VE_getNextStreamHandler: H263 dsi not found");
+                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
+                        (*pStreamHandler)->m_decoderSpecificInfoSize = 0;
+                        (*pStreamHandler)->m_H264decoderSpecificInfoSize = 0;
+                        (*pStreamHandler)->m_pH264DecoderSpecificInfo =
+                            M4OSA_NULL;
+                        (*pStreamHandler)->m_pESDSInfo = M4OSA_NULL;
+                        (*pStreamHandler)->m_ESDSInfoSize = 0;
+                    }
+                }
+                else if(M4DA_StreamTypeVideoMpeg4Avc == streamType) {
+                    if(meta->findData(kKeyAVCC, &type, &data, &size)) {
+                        decoderSpecificInfoSize = size;
+                        if (decoderSpecificInfoSize != 0) {
+                            DecoderSpecificInfo = (M4OSA_Int8*)M4OSA_32bitAlignedMalloc(
+                                decoderSpecificInfoSize, M4READER_3GP,
+                                (M4OSA_Char*)"H264 DecoderSpecific" );
+                            if (M4OSA_NULL == DecoderSpecificInfo) {
+                                ALOGV("VideoEditor3gp_getNextStream is NULL ");
+                                return M4ERR_ALLOC;
+                            }
+                            memcpy((void *)DecoderSpecificInfo,
+                                (void *)data, decoderSpecificInfoSize);
+                        } else {
+                            ALOGV("DSI Size %d", decoderSpecificInfoSize);
+                            DecoderSpecificInfo = M4OSA_NULL;
+                        }
+                    }
+                    (*pStreamHandler)->m_pESDSInfo = M4OSA_NULL;
+                    (*pStreamHandler)->m_ESDSInfoSize = 0;
+
+                    err = VideoEditor3gpReader_AnalyseAvcDsi(*pStreamHandler,
+                    (M4OSA_Int32*)DecoderSpecificInfo, decoderSpecificInfoSize);
+
+                    if (M4NO_ERROR != err) {
+                        return err;
+                    }
+                    ALOGV("decsize %d, h264decsize %d: %d", (*pStreamHandler)->\
+                        m_decoderSpecificInfoSize, (*pStreamHandler)->\
+                        m_H264decoderSpecificInfoSize);
+
+                    if(M4OSA_NULL != DecoderSpecificInfo) {
+                        free(DecoderSpecificInfo);
+                        DecoderSpecificInfo = M4OSA_NULL;
+                    }
+                } else if( (M4DA_StreamTypeVideoMpeg4 == streamType) ) {
+                    if (meta->findData(kKeyESDS, &type, &data, &size)) {
+                        ESDS esds((const char *)data, size);
+                        CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+                        (*pStreamHandler)->m_ESDSInfoSize = size;
+                        (*pStreamHandler)->m_pESDSInfo = (M4OSA_UInt8*)\
+                        M4OSA_32bitAlignedMalloc((*pStreamHandler)->m_ESDSInfoSize,
+                        M4READER_3GP, (M4OSA_Char*)"M4V DecoderSpecific" );
+                        if (M4OSA_NULL == (*pStreamHandler)->m_pESDSInfo) {
+                            return M4ERR_ALLOC;
+                        }
+                        memcpy((void *)(*pStreamHandler)->\
+                            m_pESDSInfo, (void *)data, size);
+
+                        esds.getCodecSpecificInfo(&codec_specific_data,
+                            &codec_specific_data_size);
+                        ALOGV("VE MP4 dsisize: %d, %x", codec_specific_data_size,
+                            codec_specific_data);
+
+                        (*pStreamHandler)->m_decoderSpecificInfoSize =
+                            codec_specific_data_size;
+                        if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
+                            DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
+                                (*pStreamHandler)->m_decoderSpecificInfoSize,
+                                M4READER_3GP, (M4OSA_Char*)" DecoderSpecific" );
+                            if (M4OSA_NULL == DecoderSpecific) {
+                                return M4ERR_ALLOC;
+                            }
+                            memcpy((void *)DecoderSpecific,
+                                (void *)codec_specific_data,
+                                codec_specific_data_size);
+                            (*pStreamHandler)->m_pDecoderSpecificInfo =
+                                DecoderSpecific;
+                        }
+                        else {
+                            (*pStreamHandler)->m_pDecoderSpecificInfo =
+                                M4OSA_NULL;
+                        }
+                        (*pStreamHandler)->m_pH264DecoderSpecificInfo =
+                            M4OSA_NULL;
+                        (*pStreamHandler)->m_H264decoderSpecificInfoSize = 0;
+                    }
+                } else {
+                    ALOGV("VideoEditor3gpReader_getNextStream NO video stream");
+                    return M4ERR_READER_UNKNOWN_STREAM_TYPE;
+                }
+            }
+            else {
+                ALOGV("VideoEditor3gpReader_getNextStream NO video stream");
+                return M4ERR_READER_UNKNOWN_STREAM_TYPE;
+            }
+
+        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
+            ALOGV("VideoEditor3gpReader_getNextStream audio getTrack called");
+            pC->mAudioSource = pC->mExtractor->getTrack(pC->mCurrTrack);
+            pC->mAudioSource->start();
+            *pMediaFamily = M4READER_kMediaFamilyAudio;
+
+            if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
+                streamType = M4DA_StreamTypeAudioAmrNarrowBand;
+            } else if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
+                streamType = M4DA_StreamTypeAudioAmrWideBand;
+            }
+            else if(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+                streamType = M4DA_StreamTypeAudioAac;
+            } else {
+                ALOGV("VideoEditor3gpReader_getNextStrea streamtype Unknown ");
+            }
+            if(streamType != M4DA_StreamTypeUnknown) {
+                pC->mStreamType = streamType;
+                pC->mStreamId = pC->mCurrTrack;
+
+                ALOGV("VE streamtype %d ,id %d",  streamType, pC->mCurrTrack);
+
+                pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_32bitAlignedMalloc
+                    (sizeof(M4_AudioStreamHandler), M4READER_3GP,
+                    (M4OSA_Char*)"M4_AudioStreamHandler");
+                if (M4OSA_NULL == pAudioStreamHandler) {
+                    return M4ERR_ALLOC;
+                }
+                pAudioStreamHandler->m_structSize=sizeof(M4_AudioStreamHandler);
+                pAudioStreamHandler->m_byteSampleSize   = 0;
+                pAudioStreamHandler->m_nbChannels       = 0;
+                pAudioStreamHandler->m_samplingFrequency= 0;
+                pAudioStreamHandler->m_byteFrameLength  = 0;
+
+                (*pStreamHandler) = (M4_StreamHandler*)(pAudioStreamHandler);
+                pC->mAudioStreamHandler =
+                    (M4_StreamHandler*)(pAudioStreamHandler);
+                (*pStreamHandler)->m_averageBitRate = 0;
+                haveAudio = true;
+                pC->mAudioStreamHandler=(M4_StreamHandler*)pAudioStreamHandler;
+                pC->mAudioStreamHandler->m_pESDSInfo = M4OSA_NULL;
+                pC->mAudioStreamHandler->m_ESDSInfoSize = 0;
+
+                meta->findInt32(kKeyMaxInputSize, (int32_t*)&(maxAUSize));
+                if(maxAUSize == 0) {
+                    maxAUSize = 70000;
+                }
+                (*pStreamHandler)->m_maxAUSize = maxAUSize;
+                ALOGV("VE Audio mMaxAUSize from MP4 extractor: %d", maxAUSize);
+            }
+            if((M4DA_StreamTypeAudioAmrNarrowBand == streamType) ||
+                (M4DA_StreamTypeAudioAmrWideBand == streamType)) {
+                M4OSA_UInt32 freqIndex = 0; /**< AMR NB */
+                M4OSA_UInt32 modeSet;
+                M4OSA_UInt32 i;
+                M4OSA_Context pBitParserContext = M4OSA_NULL;
+
+                if(M4DA_StreamTypeAudioAmrWideBand == streamType) {
+                    freqIndex = 1; /**< AMR WB */
+                }
+
+                if (meta->findData(kKeyESDS, &type, &data, &size)) {
+                    ESDS esds((const char *)data, size);
+                    CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+                    esds.getCodecSpecificInfo(&codec_specific_data,
+                        &codec_specific_data_size);
+                    (*pStreamHandler)->m_decoderSpecificInfoSize =
+                        codec_specific_data_size;
+
+                    if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
+                        DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
+                            (*pStreamHandler)->m_decoderSpecificInfoSize,
+                            M4READER_3GP, (M4OSA_Char*)"AMR DecoderSpecific" );
+                        if (M4OSA_NULL == DecoderSpecific) {
+                            return M4ERR_ALLOC;
+                        }
+                        memcpy((void *)DecoderSpecific,
+                            (void *)codec_specific_data,
+                            codec_specific_data_size);
+                        (*pStreamHandler)->m_pDecoderSpecificInfo =
+                            DecoderSpecific;
+                    } else {
+                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
+                    }
+                } else {
+                    M4OSA_UChar AmrDsi[] =
+                        {'P','H','L','P',0x00, 0x00, 0x80, 0x00, 0x01,};
+                    (*pStreamHandler)->m_decoderSpecificInfoSize = 9;
+                    DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
+                        (*pStreamHandler)->m_decoderSpecificInfoSize,
+                        M4READER_3GP, (M4OSA_Char*)"PHLP DecoderSpecific" );
+                    if (M4OSA_NULL == DecoderSpecific) {
+                        return M4ERR_ALLOC;
+                    }
+                    if(freqIndex ==0) {
+                        AmrDsi[8] = 0x01;
+                    } else {
+                        AmrDsi[8] = 0x02;
+                    }
+                    for(i = 0; i< 9; i++) {
+                        DecoderSpecific[i] = AmrDsi[i];
+                    }
+                    (*pStreamHandler)->m_pDecoderSpecificInfo = DecoderSpecific;
+                }
+                (*pStreamHandler)->m_averageBitRate =
+                    VideoEditor3gpReader_AmrBitRate[freqIndex][7];
+            } else if((M4DA_StreamTypeAudioAac == streamType)) {
+                if (meta->findData(kKeyESDS, &type, &data, &size)) {
+                    ESDS esds((const char *)data, size);
+                    CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+                    (*pStreamHandler)->m_ESDSInfoSize = size;
+                    (*pStreamHandler)->m_pESDSInfo = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
+                        (*pStreamHandler)->m_ESDSInfoSize, M4READER_3GP,
+                        (M4OSA_Char*)"AAC DecoderSpecific" );
+                    if (M4OSA_NULL == (*pStreamHandler)->m_pESDSInfo) {
+                        return M4ERR_ALLOC;
+                    }
+                    memcpy((void *)(*pStreamHandler)->m_pESDSInfo,
+                    (void *)data, size);
+                    esds.getCodecSpecificInfo(&codec_specific_data,
+                        &codec_specific_data_size);
+
+                    ALOGV("VEdsi %d,%x",codec_specific_data_size,
+                        codec_specific_data);
+
+                    (*pStreamHandler)->m_decoderSpecificInfoSize =
+                        codec_specific_data_size;
+                    if ((*pStreamHandler)->m_decoderSpecificInfoSize != 0) {
+                        DecoderSpecific = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
+                            (*pStreamHandler)->m_decoderSpecificInfoSize,
+                            M4READER_3GP, (M4OSA_Char*)"AAC DecoderSpecific" );
+                        if (M4OSA_NULL == DecoderSpecific) {
+                            return M4ERR_ALLOC;
+                        }
+                        memcpy((void *)DecoderSpecific,
+                            (void *)codec_specific_data,
+                            codec_specific_data_size);
+                        (*pStreamHandler)->m_pDecoderSpecificInfo =
+                            DecoderSpecific;
+                    } else {
+                        (*pStreamHandler)->m_pDecoderSpecificInfo = M4OSA_NULL;
+                    }
+                }
+            } else {
+                ALOGV("VideoEditor3gpReader_getNextStream mStreamType: none ");
+                return M4ERR_READER_UNKNOWN_STREAM_TYPE;
+            }
+        } else {
+            ALOGV("VE noaudio-video stream:pC->mCurrTrack = %d ",pC->mCurrTrack);
+            pC->mCurrTrack++; //Increment current track to get the next track
+            return M4ERR_READER_UNKNOWN_STREAM_TYPE;
+        }
+        ALOGV("VE StreamType: %d, stremhandler %x",streamType, *pStreamHandler );
+        (*pStreamHandler)->m_streamType = streamType;
+        (*pStreamHandler)->m_streamId   = pC->mStreamId;
+        (*pStreamHandler)->m_pUserData  = M4OSA_NULL;
+        (*pStreamHandler)->m_structSize = sizeof(M4_StreamHandler);
+        (*pStreamHandler)->m_bStreamIsOK = M4OSA_TRUE;
+
+        meta->findInt64(kKeyDuration,
+            (int64_t*)&(Duration));
+
+        (*pStreamHandler)->m_duration = (int32_t)(Duration / 1000);
+
+        pC->mMaxDuration = ((*pStreamHandler)->m_duration);
+        ALOGV("VE str duration duration: %d ", (*pStreamHandler)->m_duration);
+
+        /* In AAC case: Put the first AU in pAudioStreamHandler->m_pUserData
+         *since decoder has to know if stream contains SBR data(Implicit sig) */
+        if(M4DA_StreamTypeAudioAac == (*pStreamHandler)->m_streamType) {
+            M4READER_AudioSbrUserdata*  pAudioSbrUserdata;
+
+            pAudioSbrUserdata = (M4READER_AudioSbrUserdata*)M4OSA_32bitAlignedMalloc(
+                sizeof(M4READER_AudioSbrUserdata),M4READER_3GP,
+                (M4OSA_Char*)"M4READER_AudioSbrUserdata");
+            if (M4OSA_NULL == pAudioSbrUserdata) {
+                err = M4ERR_ALLOC;
+                goto Error;
+            }
+            (*pStreamHandler)->m_pUserData = pAudioSbrUserdata;
+            pAudioSbrUserdata->m_bIsSbrEnabled = M4OSA_FALSE;
+
+            pAudioSbrUserdata->m_pFirstAU = (M4_AccessUnit*)M4OSA_32bitAlignedMalloc(
+                sizeof(M4_AccessUnit),M4READER_3GP, (M4OSA_Char*)"1st AAC AU");
+            if (M4OSA_NULL == pAudioSbrUserdata->m_pFirstAU) {
+                pAudioSbrUserdata->m_pAacDecoderUserConfig = M4OSA_NULL;
+                err = M4ERR_ALLOC;
+                goto Error;
+            }
+            pAudioSbrUserdata->m_pAacDecoderUserConfig = (M4_AacDecoderConfig*)\
+                M4OSA_32bitAlignedMalloc(sizeof(M4_AacDecoderConfig),M4READER_3GP,
+                (M4OSA_Char*)"m_pAacDecoderUserConfig");
+            if (M4OSA_NULL == pAudioSbrUserdata->m_pAacDecoderUserConfig) {
+                err = M4ERR_ALLOC;
+                goto Error;
+            }
+        }
+        if(M4DA_StreamTypeAudioAac == (*pStreamHandler)->m_streamType) {
+            M4_AudioStreamHandler* pAudioStreamHandler =
+                (M4_AudioStreamHandler*)(*pStreamHandler);
+            M4READER_AudioSbrUserdata* pUserData = (M4READER_AudioSbrUserdata*)\
+                (pAudioStreamHandler->m_basicProperties.m_pUserData);
+
+            err = VideoEditor3gpReader_fillAuStruct(pC, (*pStreamHandler),
+                (M4_AccessUnit*)pUserData->m_pFirstAU);
+            if (M4NO_ERROR != err) {
+                goto Error;
+            }
+            err = VideoEditor3gpReader_getNextAu(pC, (*pStreamHandler),
+                (M4_AccessUnit*)pUserData->m_pFirstAU);
+
+            /*
+             * 1. "M4WAR_NO_MORE_AU == err" indicates that there is no more
+             * access unit from the current track. In other words, there
+             * is only a single access unit from the current track, and
+             * the parsing of this track has reached EOS. The reason why
+             * the first access unit needs to be parsed here is because for
+             * some audio codec (like AAC), the very first access unit
+             * must be decoded before its configuration/encoding parameters
+             * (such as # of channels and sample rate) can be correctly
+             * determined.
+             *
+             * 2. "trackCount > pC->mCurrTrack" indicates that there are other
+             * tracks to be parsed, in addition to the current track.
+             *
+             * When both conditions 1 & 2 hold, other tracks should be
+             * parsed. Thus, we should not bail out.
+             */
+            if (M4WAR_NO_MORE_AU == err && trackCount > pC->mCurrTrack) {
+                err = M4NO_ERROR;
+            }
+
+            if (M4NO_ERROR != err) {
+                goto Error;
+            }
+            err = VideoEditor3gpReader_reset(pC, (*pStreamHandler));
+            if (M4NO_ERROR != err) {
+                goto Error;
+            }
+        }
+    }
+    pC->mCurrTrack++; //Increment the current track to get next track
+    ALOGV("pC->mCurrTrack = %d",pC->mCurrTrack);
+
+    if (!haveAudio && !haveVideo) {
+        *pMediaFamily=M4READER_kMediaFamilyUnknown;
+        return M4ERR_READER_UNKNOWN_STREAM_TYPE;
+    }
+Error:
+    ALOGV("VideoEditor3gpReader_getNextStreamHandler end error = %d",err);
+    return err;
+}
+
+M4OSA_ERR VideoEditor3gpReader_getPrevRapTime(M4OSA_Context context,
+    M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime)
+{
+    VideoEditor3gpReader_Context *pC = (VideoEditor3gpReader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+    MediaBuffer *mMediaBuffer = M4OSA_NULL;
+    MediaSource::ReadOptions options;
+    M4OSA_Time time64;
+    int64_t tempTime64 = 0;
+    status_t error;
+
+    ALOGV("VideoEditor3gpReader_getPrevRapTime begin");
+
+    M4OSA_DEBUG_IF1((pC == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_getPrevRapTime: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_getPrevRapTime invalid pointer to StreamHandler");
+    M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
+        "VideoEditor3gpReader_getPrevRapTime: invalid time pointer");
+    if (*pTime == (pStreamHandler->m_duration)) {
+        *pTime -= 1;
+    }
+
+    time64 = (M4OSA_Time)*pTime * 1000;
+
+    ALOGV("VideoEditor3gpReader_getPrevRapTime seek time: %ld",time64);
+    options.setSeekTo(time64, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+    error = pC->mVideoSource->read(&mMediaBuffer, &options);
+    if (error != OK) {
+        //Can not get the previous Sync.
+        //Must be end of stream.
+        return M4WAR_NO_MORE_AU;
+    }
+
+    mMediaBuffer->meta_data()->findInt64(kKeyTime, (int64_t*)&tempTime64);
+    ALOGV("VideoEditor3gpReader_getPrevRapTime read time %ld, %x", tempTime64,
+        mMediaBuffer);
+
+    *pTime = (M4OSA_Int32)(tempTime64 / 1000);
+
+    if(mMediaBuffer != M4OSA_NULL) {
+        ALOGV(" mMediaBuffer size = %d length %d", mMediaBuffer->size(),
+            mMediaBuffer->range_length());
+        mMediaBuffer->release();
+        mMediaBuffer = M4OSA_NULL;
+    }
+    options.clearSeekTo();
+
+    if(error != OK) {
+        ALOGV("VideoEditor3gpReader_getPrevRapTime end \
+            M4WAR_READER_INFORMATION_NOT_PRESENT");
+        return M4WAR_READER_INFORMATION_NOT_PRESENT;
+    } else {
+        ALOGV("VideoEditor3gpReader_getPrevRapTime end: err %x", err);
+        err = M4NO_ERROR;
+        return err;
+    }
+}
+
+extern "C" {
+M4OSA_ERR VideoEditor3gpReader_getInterface(M4READER_MediaType *pMediaType,
+        M4READER_GlobalInterface **pRdrGlobalInterface,
+        M4READER_DataInterface **pRdrDataInterface) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pMediaType,      M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrGlobalInterface, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrDataInterface, M4ERR_PARAMETER);
+
+    ALOGV("VideoEditor3gpReader_getInterface begin");
+    ALOGV("VideoEditor3gpReader_getInterface %d 0x%x 0x%x", *pMediaType,
+        *pRdrGlobalInterface,*pRdrDataInterface);
+
+    SAFE_MALLOC(*pRdrGlobalInterface, M4READER_GlobalInterface, 1,
+        "VideoEditor3gpReader_getInterface");
+    SAFE_MALLOC(*pRdrDataInterface, M4READER_DataInterface, 1,
+        "VideoEditor3gpReader_getInterface");
+
+    *pMediaType = M4READER_kMediaType3GPP;
+
+    (*pRdrGlobalInterface)->m_pFctCreate       = VideoEditor3gpReader_create;
+    (*pRdrGlobalInterface)->m_pFctDestroy      = VideoEditor3gpReader_destroy;
+    (*pRdrGlobalInterface)->m_pFctOpen         = VideoEditor3gpReader_open;
+    (*pRdrGlobalInterface)->m_pFctClose        = VideoEditor3gpReader_close;
+    (*pRdrGlobalInterface)->m_pFctGetOption    = VideoEditor3gpReader_getOption;
+    (*pRdrGlobalInterface)->m_pFctSetOption    = VideoEditor3gpReader_setOption;
+    (*pRdrGlobalInterface)->m_pFctGetNextStream =
+        VideoEditor3gpReader_getNextStreamHandler;
+    (*pRdrGlobalInterface)->m_pFctFillAuStruct =
+        VideoEditor3gpReader_fillAuStruct;
+    (*pRdrGlobalInterface)->m_pFctStart        = M4OSA_NULL;
+    (*pRdrGlobalInterface)->m_pFctStop         = M4OSA_NULL;
+    (*pRdrGlobalInterface)->m_pFctJump         = VideoEditor3gpReader_jump;
+    (*pRdrGlobalInterface)->m_pFctReset        = VideoEditor3gpReader_reset;
+    (*pRdrGlobalInterface)->m_pFctGetPrevRapTime =
+        VideoEditor3gpReader_getPrevRapTime;
+    (*pRdrDataInterface)->m_pFctGetNextAu      = VideoEditor3gpReader_getNextAu;
+    (*pRdrDataInterface)->m_readerContext      = M4OSA_NULL;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditor3gpReader_getInterface no error");
+    } else {
+        SAFE_FREE(*pRdrGlobalInterface);
+        SAFE_FREE(*pRdrDataInterface);
+
+        ALOGV("VideoEditor3gpReader_getInterface ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditor3gpReader_getInterface end");
+    return err;
+}
+
+}  /* extern "C" */
+
+}  /* namespace android */
+
+
diff --git a/frameworks/videoedit/stagefrightshells/VideoEditorAudioDecoder.cpp b/frameworks/videoedit/stagefrightshells/VideoEditorAudioDecoder.cpp
new file mode 100644
index 0000000..9b35d07
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/VideoEditorAudioDecoder.cpp
@@ -0,0 +1,991 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+*************************************************************************
+* @file   VideoEditorAudioDecoder.cpp
+* @brief  StageFright shell Audio Decoder
+*************************************************************************
+*/
+
+#define LOG_NDEBUG 1
+#define LOG_TAG "VIDEOEDITOR_AUDIODECODER"
+
+#include "M4OSA_Debug.h"
+#include "VideoEditorAudioDecoder.h"
+#include "VideoEditorUtils.h"
+#include "M4MCS_InternalTypes.h"
+
+#include "utils/Log.h"
+#include "utils/Vector.h"
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+
+/********************
+ *   DEFINITIONS    *
+ ********************/
+// Version
+#define VIDEOEDITOR_AUDIO_DECODER_VERSION_MAJOR 1
+#define VIDEOEDITOR_AUDIO_DECODER_VERSION_MINOR 0
+#define VIDEOEDITOR_AUDIO_DECODER_VERSION_REV   0
+
+// Force using software decoder as engine does not support prefetch
+#define VIDEOEDITOR_FORCECODEC kSoftwareCodecsOnly
+
+namespace android {
+
+struct VideoEditorAudioDecoderSource : public MediaSource {
+    public:
+        static sp<VideoEditorAudioDecoderSource> Create(
+                const sp<MetaData>& format, void *decoderShellContext);
+        virtual status_t start(MetaData *params = NULL);
+        virtual status_t stop();
+        virtual sp<MetaData> getFormat();
+        virtual status_t read(MediaBuffer **buffer,
+        const ReadOptions *options = NULL);
+        virtual void storeBuffer(MediaBuffer *buffer);
+
+    protected:
+        virtual ~VideoEditorAudioDecoderSource();
+
+    private:
+        enum State {
+            CREATED,
+            STARTED,
+            ERROR
+        };
+        VideoEditorAudioDecoderSource(const sp<MetaData>& format,
+         void *decoderShellContext);
+        sp<MetaData> mFormat;
+        Vector<MediaBuffer*> mBuffers;
+        Mutex mLock;  // protects mBuffers
+        bool mIsEOS;
+        State mState;
+        void* mDecShellContext;
+        // Don't call me.
+        VideoEditorAudioDecoderSource(const VideoEditorAudioDecoderSource&);
+        VideoEditorAudioDecoderSource& operator=(
+            const VideoEditorAudioDecoderSource &);
+};
+
+/**
+ ******************************************************************************
+ * structure VideoEditorAudioDecoder_Context
+ * @brief    This structure defines the context of the StageFright audio decoder
+ *           shell
+ ******************************************************************************
+*/
+
+typedef struct {
+    M4AD_Type                          mDecoderType;
+    M4_AudioStreamHandler*             mAudioStreamHandler;
+    sp<VideoEditorAudioDecoderSource>  mDecoderSource;
+    OMXClient                          mClient;
+    sp<MediaSource>                    mDecoder;
+    int32_t                            mNbOutputChannels;
+    uint32_t                           mNbInputFrames;
+    uint32_t                           mNbOutputFrames;
+    M4READER_DataInterface  *m_pReader;
+    M4_AccessUnit* m_pNextAccessUnitToDecode;
+    M4OSA_ERR readerErrCode;
+    int32_t timeStampMs;
+
+} VideoEditorAudioDecoder_Context;
+
+sp<VideoEditorAudioDecoderSource> VideoEditorAudioDecoderSource::Create(
+        const sp<MetaData>& format, void *decoderShellContext) {
+
+    sp<VideoEditorAudioDecoderSource> aSource =
+        new VideoEditorAudioDecoderSource(format, decoderShellContext);
+
+    return aSource;
+}
+
+VideoEditorAudioDecoderSource::VideoEditorAudioDecoderSource(
+        const sp<MetaData>& format, void* decoderShellContext):
+        mFormat(format),
+        mIsEOS(false),
+        mState(CREATED),
+        mDecShellContext(decoderShellContext) {
+}
+
+VideoEditorAudioDecoderSource::~VideoEditorAudioDecoderSource() {
+
+    if( STARTED == mState ) {
+        stop();
+    }
+}
+
+status_t VideoEditorAudioDecoderSource::start(MetaData *meta) {
+    status_t err = OK;
+
+    if( CREATED != mState ) {
+        ALOGV("VideoEditorAudioDecoderSource::start: invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+
+    mState = STARTED;
+
+cleanUp:
+    ALOGV("VideoEditorAudioDecoderSource::start END (0x%x)", err);
+    return err;
+}
+
+status_t VideoEditorAudioDecoderSource::stop() {
+    Mutex::Autolock autolock(mLock);
+    status_t err = OK;
+
+    ALOGV("VideoEditorAudioDecoderSource::stop begin");
+
+    if( STARTED != mState ) {
+        ALOGV("VideoEditorAudioDecoderSource::stop: invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+
+    if (!mBuffers.empty()) {
+        int n = mBuffers.size();
+        for (int i = 0; i < n; i++) {
+            mBuffers.itemAt(i)->release();
+        }
+        ALOGW("VideoEditorAudioDecoderSource::stop : %d buffer remained", n);
+        mBuffers.clear();
+    }
+
+    mState = CREATED;
+
+    ALOGV("VideoEditorAudioDecoderSource::stop END (0x%x)", err);
+    return err;
+}
+
+sp<MetaData> VideoEditorAudioDecoderSource::getFormat() {
+
+    ALOGV("VideoEditorAudioDecoderSource::getFormat");
+    return mFormat;
+}
+
+static MediaBuffer* readBufferFromReader(
+        VideoEditorAudioDecoder_Context* pDecContext) {
+    M4OSA_ERR lerr = M4NO_ERROR;
+    M4_AccessUnit* pAccessUnit = pDecContext->m_pNextAccessUnitToDecode;
+
+    // Get next AU from reader.
+    lerr = pDecContext->m_pReader->m_pFctGetNextAu(
+               pDecContext->m_pReader->m_readerContext,
+               (M4_StreamHandler*)pDecContext->mAudioStreamHandler,
+               pAccessUnit);
+
+    if (lerr == M4WAR_NO_MORE_AU) {
+        ALOGV("readBufferFromReader : EOS");
+        return NULL;
+    }
+
+    pDecContext->timeStampMs = pAccessUnit->m_CTS;
+
+    MediaBuffer* newBuffer = new MediaBuffer((size_t)pAccessUnit->m_size);
+    memcpy((void *)((M4OSA_Int8*)newBuffer->data() + newBuffer->range_offset()),
+        (void *)pAccessUnit->m_dataAddress, pAccessUnit->m_size);
+    newBuffer->meta_data()->setInt64(kKeyTime, (pAccessUnit->m_CTS * 1000LL));
+    return newBuffer;
+}
+
+status_t VideoEditorAudioDecoderSource::read(MediaBuffer **buffer,
+        const ReadOptions *options) {
+    Mutex::Autolock autolock(mLock);
+    MediaSource::ReadOptions readOptions;
+
+    VideoEditorAudioDecoder_Context* pDecContext =
+     (VideoEditorAudioDecoder_Context *)mDecShellContext;
+
+    if ( STARTED != mState ) {
+        ALOGV("VideoEditorAudioDecoderSource::read invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+
+    // Get a buffer from the reader if we don't have any
+    if(mBuffers.empty()) {
+        MediaBuffer* newBuffer = readBufferFromReader(pDecContext);
+        if (!newBuffer) {
+            *buffer = NULL;
+            pDecContext->readerErrCode = M4WAR_NO_MORE_AU;
+            return ERROR_END_OF_STREAM;
+        }
+        mBuffers.push(newBuffer);
+    }
+    *buffer = mBuffers.itemAt(0);
+    mBuffers.removeAt(0);
+
+    return OK;
+}
+
+void VideoEditorAudioDecoderSource::storeBuffer(MediaBuffer *buffer) {
+    Mutex::Autolock autolock(mLock);
+    VideoEditorAudioDecoder_Context* pDecContext =
+     (VideoEditorAudioDecoder_Context *)mDecShellContext;
+
+    ALOGV("VideoEditorAudioDecoderSource::storeBuffer begin");
+
+    // If the user didn't give us a buffer, get it from the reader.
+    if(buffer == NULL) {
+        MediaBuffer* newBuffer = readBufferFromReader(pDecContext);
+        if (!newBuffer) {
+            pDecContext->readerErrCode = M4WAR_NO_MORE_AU;
+            return;
+        }
+        buffer = newBuffer;
+    }
+
+    mBuffers.push(buffer);
+    ALOGV("VideoEditorAudioDecoderSource::storeBuffer END");
+}
+
+/********************
+ *      TOOLS       *
+ ********************/
+
+M4OSA_ERR VideoEditorAudioDecoder_getBits(M4OSA_Int8* pData,
+        M4OSA_UInt32 dataSize, M4OSA_UInt8 nbBits, M4OSA_Int32* pResult,
+        M4OSA_UInt32* pOffset) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    M4OSA_UInt32 startByte = 0;
+    M4OSA_UInt32 startBit = 0;
+    M4OSA_UInt32 endByte = 0;
+    M4OSA_UInt32 endBit = 0;
+    M4OSA_UInt32 currentByte = 0;
+    M4OSA_UInt32 result = 0;
+    M4OSA_UInt32 ui32Tmp = 0;
+    M4OSA_UInt32 ui32Mask = 0;
+
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pData, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pOffset, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(32 >= nbBits, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK((*pOffset + nbBits) <= 8*dataSize, M4ERR_PARAMETER);
+
+    ALOGV("VideoEditorAudioDecoder_getBits begin");
+
+    startByte   = (*pOffset) >> 3;
+    endByte     = (*pOffset + nbBits) >> 3;
+    startBit    = (*pOffset) % 8;
+    endBit      = (*pOffset + nbBits) % 8;
+    currentByte = startByte;
+
+    // Extract the requested nunber of bits from memory
+    while( currentByte <= endByte) {
+        ui32Mask = 0x000000FF;
+        if( currentByte == startByte ) {
+            ui32Mask >>= startBit;
+        }
+        ui32Tmp = ui32Mask & ((M4OSA_UInt32)pData[currentByte]);
+        if( currentByte == endByte ) {
+            ui32Tmp >>= (8-endBit);
+            result <<= endBit;
+        } else {
+            result <<= 8;
+        }
+        result |= ui32Tmp;
+        currentByte++;
+    }
+
+    *pResult = result;
+    *pOffset += nbBits;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_getBits no error");
+    } else {
+        ALOGV("VideoEditorAudioDecoder_getBits ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_getBits end");
+    return err;
+}
+
+
+#define FREQ_TABLE_SIZE 16
+const M4OSA_UInt32 AD_AAC_FREQ_TABLE[FREQ_TABLE_SIZE] =
+    {96000, 88200, 64000, 48000, 44100,
+    32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0};
+
+
+M4OSA_ERR VideoEditorAudioDecoder_parse_AAC_DSI(M4OSA_Int8* pDSI,
+        M4OSA_UInt32 dsiSize, AAC_DEC_STREAM_PROPS* pProperties) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    M4OSA_UInt32 offset = 0;
+    M4OSA_Int32 result = 0;
+
+    ALOGV("VideoEditorAudioDecoder_parse_AAC_DSI begin");
+
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pDSI, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pProperties, M4ERR_PARAMETER);
+
+    // Get the object type
+    err = VideoEditorAudioDecoder_getBits(pDSI, dsiSize, 5, &result, &offset);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+    switch( result ) {
+        case 2:
+            /* Audio Object Type is 2 (AAC Low Complexity) */
+            pProperties->aPSPresent  = 0;
+            pProperties->aSBRPresent = 0;
+            break;
+        case 5:
+            /* Audio Object Type is 5 (Spectral Band Replication) */
+            pProperties->aPSPresent  = 0;
+            pProperties->aSBRPresent = 1;
+            break;
+        case 29:
+            /* Audio Object Type is 29 (Parametric Stereo) */
+            pProperties->aPSPresent  = 1;
+            pProperties->aSBRPresent = 1;
+            break;
+        default:
+            ALOGV("parse_AAC_DSI ERROR : object type %d is not supported",
+                result);
+            VIDEOEDITOR_CHECK(!"invalid AAC object type", M4ERR_BAD_OPTION_ID);
+            break;
+    }
+    pProperties->aAudioObjectType = (M4OSA_Int32)result;
+
+    // Get the frequency index
+    err = VideoEditorAudioDecoder_getBits(pDSI, dsiSize, 4, &result, &offset);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+    VIDEOEDITOR_CHECK((0 <= result) && (FREQ_TABLE_SIZE > result),
+        M4ERR_PARAMETER);
+    pProperties->aSampFreq = AD_AAC_FREQ_TABLE[result];
+    pProperties->aExtensionSampFreq = 0;
+
+    // Get the number of channels
+    err = VideoEditorAudioDecoder_getBits(pDSI, dsiSize, 4, &result, &offset);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+    pProperties->aNumChan = (M4OSA_UInt32)result;
+
+    // Set the max PCM samples per channel
+    pProperties->aMaxPCMSamplesPerCh = (pProperties->aSBRPresent) ? 2048 : 1024;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_parse_AAC_DSI no error");
+    } else {
+        ALOGV("VideoEditorAudioDecoder_parse_AAC_DSI ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_parse_AAC_DSI end");
+    return err;
+}
+
+/********************
+ * ENGINE INTERFACE *
+ ********************/
+
+M4OSA_ERR VideoEditorAudioDecoder_destroy(M4AD_Context pContext) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioDecoder_Context* pDecoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorAudioDecoder_destroy begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pDecoderContext = (VideoEditorAudioDecoder_Context*)pContext;
+
+    // Stop the graph
+    if( M4OSA_NULL != pDecoderContext->mDecoder.get() ) {
+        pDecoderContext->mDecoder->stop();
+    }
+
+    // Destroy the graph
+    pDecoderContext->mDecoderSource.clear();
+    pDecoderContext->mDecoder.clear();
+    pDecoderContext->mClient.disconnect();
+
+    SAFE_FREE(pDecoderContext);
+    pContext = M4OSA_NULL;
+    ALOGV("VideoEditorAudioDecoder_destroy : DONE");
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_destroy no error");
+    } else {
+        ALOGV("VideoEditorAudioDecoder_destroy ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_destroy : end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_create(M4AD_Type decoderType,
+        M4AD_Context* pContext, M4_AudioStreamHandler* pStreamHandler,
+        void* pUserData) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioDecoder_Context* pDecoderContext = M4OSA_NULL;
+    AAC_DEC_STREAM_PROPS aacProperties;
+    status_t result = OK;
+    sp<MetaData> decoderMetaData = NULL;
+    const char* mime = NULL;
+    uint32_t codecFlags = 0;
+
+    ALOGV("VideoEditorAudioDecoder_create begin: decoderType %d", decoderType);
+
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,       M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pStreamHandler, M4ERR_PARAMETER);
+
+    // Context allocation & initialization
+    SAFE_MALLOC(pDecoderContext, VideoEditorAudioDecoder_Context, 1,
+        "AudioDecoder");
+    pDecoderContext->mDecoderType = decoderType;
+    pDecoderContext->mAudioStreamHandler = pStreamHandler;
+
+    pDecoderContext->mNbInputFrames  = 0;
+    pDecoderContext->mNbOutputFrames = 0;
+    pDecoderContext->readerErrCode = M4NO_ERROR;
+    pDecoderContext->timeStampMs = -1;
+
+    ALOGV("VideoEditorAudioDecoder_create : maxAUSize %d",
+        pDecoderContext->mAudioStreamHandler->m_basicProperties.m_maxAUSize);
+
+    // Create the meta data for the decoder
+    decoderMetaData = new MetaData;
+    switch( pDecoderContext->mDecoderType ) {
+        case M4AD_kTypeAMRNB:
+            // StageFright parameters
+            mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
+            // Engine parameters
+            pDecoderContext->mAudioStreamHandler->m_byteFrameLength = 160;
+            // Number of bytes per sample
+            pDecoderContext->mAudioStreamHandler->m_byteSampleSize = 2;
+            pDecoderContext->mAudioStreamHandler->m_samplingFrequency = 8000;
+            pDecoderContext->mAudioStreamHandler->m_nbChannels = 1;
+            break;
+
+        case M4AD_kTypeAMRWB:
+            // StageFright parameters
+            mime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
+
+            pDecoderContext->mAudioStreamHandler->m_byteFrameLength = 160;
+            // Number of bytes per sample
+            pDecoderContext->mAudioStreamHandler->m_byteSampleSize = 2;
+            pDecoderContext->mAudioStreamHandler->m_samplingFrequency = 16000;
+            pDecoderContext->mAudioStreamHandler->m_nbChannels = 1;
+            break;
+
+        case M4AD_kTypeAAC:
+            // Reject ADTS & ADIF (or any incorrect type)
+            VIDEOEDITOR_CHECK(M4DA_StreamTypeAudioAac ==
+                pDecoderContext->mAudioStreamHandler->\
+                m_basicProperties.m_streamType,M4ERR_PARAMETER);
+
+            // StageFright parameters
+            mime = MEDIA_MIMETYPE_AUDIO_AAC;
+
+            decoderMetaData->setData(kKeyESDS, kTypeESDS,
+                pStreamHandler->m_basicProperties.m_pESDSInfo,
+                pStreamHandler->m_basicProperties.m_ESDSInfoSize);
+
+            // Engine parameters
+            // Retrieve sampling frequency and number of channels from the DSI
+            err = VideoEditorAudioDecoder_parse_AAC_DSI(
+                (M4OSA_Int8*)pStreamHandler->m_basicProperties.\
+                    m_pDecoderSpecificInfo,
+                pStreamHandler->m_basicProperties.m_decoderSpecificInfoSize,
+                &aacProperties);
+
+            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+            pDecoderContext->mAudioStreamHandler->m_byteFrameLength = 1024;
+            // Number of bytes per sample
+            pDecoderContext->mAudioStreamHandler->m_byteSampleSize = 2;
+            pDecoderContext->mAudioStreamHandler->m_samplingFrequency =
+                aacProperties.aSampFreq;
+            pDecoderContext->mAudioStreamHandler->m_nbChannels =
+                aacProperties.aNumChan;
+
+            // Copy the stream properties into userdata
+            if( M4OSA_NULL != pUserData ) {
+                memcpy((void *)pUserData,
+                    (void *)&aacProperties,
+                    sizeof(AAC_DEC_STREAM_PROPS));
+            }
+            break;
+
+        case M4AD_kTypeMP3:
+            // StageFright parameters
+            mime = MEDIA_MIMETYPE_AUDIO_MPEG;
+            break;
+
+        default:
+            VIDEOEDITOR_CHECK(!"AudioDecoder_open : incorrect input format",
+                M4ERR_STATE);
+            break;
+    }
+    decoderMetaData->setCString(kKeyMIMEType, mime);
+    decoderMetaData->setInt32(kKeySampleRate,
+        (int32_t)pDecoderContext->mAudioStreamHandler->m_samplingFrequency);
+    decoderMetaData->setInt32(kKeyChannelCount,
+        pDecoderContext->mAudioStreamHandler->m_nbChannels);
+    decoderMetaData->setInt64(kKeyDuration,
+        (int64_t)pDecoderContext->mAudioStreamHandler->\
+        m_basicProperties.m_duration);
+
+    // Create the decoder source
+    pDecoderContext->mDecoderSource = VideoEditorAudioDecoderSource::Create(
+        decoderMetaData, (void *)pDecoderContext);
+    VIDEOEDITOR_CHECK(NULL != pDecoderContext->mDecoderSource.get(),
+        M4ERR_STATE);
+
+    // Connect to the OMX client
+    result = pDecoderContext->mClient.connect();
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+
+    // Create the OMX codec
+#ifdef VIDEOEDITOR_FORCECODEC
+    codecFlags |= OMXCodec::VIDEOEDITOR_FORCECODEC;
+#endif /* VIDEOEDITOR_FORCECODEC */
+
+    pDecoderContext->mDecoder = OMXCodec::Create(pDecoderContext->\
+        mClient.interface(),
+        decoderMetaData, false, pDecoderContext->mDecoderSource, NULL,
+            codecFlags);
+    VIDEOEDITOR_CHECK(NULL != pDecoderContext->mDecoder.get(), M4ERR_STATE);
+
+    // Get the output channels, the decoder might overwrite the input metadata
+    pDecoderContext->mDecoder->getFormat()->findInt32(kKeyChannelCount,
+        &pDecoderContext->mNbOutputChannels);
+    ALOGV("VideoEditorAudioDecoder_create : output chan %d",
+        pDecoderContext->mNbOutputChannels);
+
+    // Start the decoder
+    result = pDecoderContext->mDecoder->start();
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+
+    *pContext = pDecoderContext;
+    ALOGV("VideoEditorAudioDecoder_create : DONE");
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_create no error");
+    } else {
+        VideoEditorAudioDecoder_destroy(pDecoderContext);
+        *pContext = M4OSA_NULL;
+        ALOGV("VideoEditorAudioDecoder_create ERROR 0x%X", err);
+    }
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_create_AAC(M4AD_Context* pContext,
+        M4_AudioStreamHandler* pStreamHandler, void* pUserData) {
+
+    return VideoEditorAudioDecoder_create(
+        M4AD_kTypeAAC, pContext, pStreamHandler,pUserData);
+}
+
+
+M4OSA_ERR VideoEditorAudioDecoder_create_AMRNB(M4AD_Context* pContext,
+        M4_AudioStreamHandler* pStreamHandler, void* pUserData) {
+
+    return VideoEditorAudioDecoder_create(
+        M4AD_kTypeAMRNB, pContext, pStreamHandler, pUserData);
+}
+
+
+M4OSA_ERR VideoEditorAudioDecoder_create_AMRWB(M4AD_Context* pContext,
+        M4_AudioStreamHandler* pStreamHandler, void* pUserData) {
+
+    return VideoEditorAudioDecoder_create(
+        M4AD_kTypeAMRWB, pContext, pStreamHandler, pUserData);
+}
+
+
+M4OSA_ERR VideoEditorAudioDecoder_create_MP3(M4AD_Context* pContext,
+        M4_AudioStreamHandler* pStreamHandler, void* pUserData) {
+
+    return VideoEditorAudioDecoder_create(
+        M4AD_kTypeMP3, pContext, pStreamHandler, pUserData);
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_processInputBuffer(
+        M4AD_Context pContext, M4AD_Buffer* pInputBuffer) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioDecoder_Context* pDecoderContext = M4OSA_NULL;
+    MediaBuffer* buffer = NULL;
+
+    ALOGV("VideoEditorAudioDecoder_processInputBuffer begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+
+    pDecoderContext = (VideoEditorAudioDecoder_Context*)pContext;
+
+    if( M4OSA_NULL != pInputBuffer ) {
+        buffer = new MediaBuffer((size_t)pInputBuffer->m_bufferSize);
+        memcpy((void *)((M4OSA_Int8*)buffer->data() + buffer->range_offset()),
+            (void *)pInputBuffer->m_dataAddress, pInputBuffer->m_bufferSize);
+        buffer->meta_data()->setInt64(kKeyTime, pInputBuffer->m_timeStampUs);
+    }
+    pDecoderContext->mDecoderSource->storeBuffer(buffer);
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_processInputBuffer no error");
+    } else {
+        ALOGV("VideoEditorAudioDecoder_processInputBuffer ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_processInputBuffer end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_processOutputBuffer(M4AD_Context pContext,
+        MediaBuffer* buffer, M4AD_Buffer* pOuputBuffer) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioDecoder_Context* pDecoderContext = M4OSA_NULL;
+    int32_t i32Tmp = 0;
+    int64_t i64Tmp = 0;
+    status_t result = OK;
+
+    ALOGV("VideoEditorAudioDecoder_processOutputBuffer begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != buffer, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pOuputBuffer, M4ERR_PARAMETER);
+
+    pDecoderContext = (VideoEditorAudioDecoder_Context*)pContext;
+
+    // Process the returned data
+    if( 0 == buffer->range_length() ) {
+        // Decoder has no data yet, nothing unusual
+        goto cleanUp;
+    }
+
+    pDecoderContext->mNbOutputFrames++;
+
+    if( pDecoderContext->mAudioStreamHandler->m_nbChannels ==
+        (M4OSA_UInt32)pDecoderContext->mNbOutputChannels ) {
+        // Just copy the PCMs
+        pOuputBuffer->m_bufferSize = (M4OSA_UInt32)buffer->range_length();
+        memcpy((void *)pOuputBuffer->m_dataAddress,
+            (void *)(((M4OSA_MemAddr8)buffer->data())+buffer->range_offset()),
+            buffer->range_length());
+    } else if( pDecoderContext->mAudioStreamHandler->m_nbChannels <
+        (M4OSA_UInt32)pDecoderContext->mNbOutputChannels ) {
+        // The decoder forces stereo output, downsample
+        pOuputBuffer->m_bufferSize = (M4OSA_UInt32)(buffer->range_length()/2);
+        M4OSA_Int16* pDataIn  = ((M4OSA_Int16*)buffer->data()) +
+            buffer->range_offset();
+        M4OSA_Int16* pDataOut = (M4OSA_Int16*)pOuputBuffer->m_dataAddress;
+        M4OSA_Int16* pDataEnd = pDataIn + \
+            (buffer->range_length()/sizeof(M4OSA_Int16));
+        while( pDataIn < pDataEnd ) {
+            *pDataOut = *pDataIn;
+            pDataIn+=2;
+            pDataOut++;
+        }
+    } else {
+        // The decoder forces mono output, not supported
+        VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER);
+    }
+
+cleanUp:
+    // Release the buffer
+    buffer->release();
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_processOutputBuffer no error");
+    } else {
+        pOuputBuffer->m_bufferSize = 0;
+        ALOGV("VideoEditorAudioDecoder_processOutputBuffer ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_processOutputBuffer end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_step(M4AD_Context pContext,
+        M4AD_Buffer* pInputBuffer, M4AD_Buffer* pOutputBuffer,
+        M4OSA_Bool bJump) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioDecoder_Context* pDecoderContext = M4OSA_NULL;
+    status_t result = OK;
+    MediaBuffer* outputBuffer = NULL;
+
+    ALOGV("VideoEditorAudioDecoder_step begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pDecoderContext = (VideoEditorAudioDecoder_Context*)pContext;
+    pDecoderContext->mNbInputFrames++;
+
+    // Push the input buffer to the decoder source
+    err = VideoEditorAudioDecoder_processInputBuffer(pDecoderContext,
+        pInputBuffer);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+    // Read
+    result = pDecoderContext->mDecoder->read(&outputBuffer, NULL);
+    if (INFO_FORMAT_CHANGED == result) {
+        ALOGV("VideoEditorAudioDecoder_step: Audio decoder \
+         returned INFO_FORMAT_CHANGED");
+        CHECK(outputBuffer == NULL);
+        sp<MetaData> meta = pDecoderContext->mDecoder->getFormat();
+        int32_t sampleRate, channelCount;
+
+        CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+        CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
+        ALOGV("VideoEditorAudioDecoder_step: samplingFreq = %d", sampleRate);
+        ALOGV("VideoEditorAudioDecoder_step: channelCnt = %d", channelCount);
+        pDecoderContext->mAudioStreamHandler->m_samplingFrequency =
+         (uint32_t)sampleRate;
+        pDecoderContext->mAudioStreamHandler->m_nbChannels =
+         (uint32_t)channelCount;
+        pDecoderContext->mNbOutputChannels = channelCount;
+
+        return M4WAR_INFO_FORMAT_CHANGE;
+    } else if (ERROR_END_OF_STREAM == result) {
+        ALOGV("VideoEditorAudioDecoder_step: Audio decoder \
+         returned ERROR_END_OF_STREAM");
+        pDecoderContext->readerErrCode = M4WAR_NO_MORE_AU;
+        return M4WAR_NO_MORE_AU;
+    } else if (OK != result) {
+        return M4ERR_STATE;
+    }
+
+    // Convert the PCM buffer
+    err = VideoEditorAudioDecoder_processOutputBuffer(pDecoderContext,
+        outputBuffer, pOutputBuffer);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_step no error");
+    } else {
+        ALOGV("VideoEditorAudioDecoder_step ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_step end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_getVersion(M4_VersionInfo* pVersionInfo) {
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditorAudioDecoder_getVersion begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pVersionInfo, M4ERR_PARAMETER);
+
+    pVersionInfo->m_major      = VIDEOEDITOR_AUDIO_DECODER_VERSION_MAJOR;
+    pVersionInfo->m_minor      = VIDEOEDITOR_AUDIO_DECODER_VERSION_MINOR;
+    pVersionInfo->m_revision   = VIDEOEDITOR_AUDIO_DECODER_VERSION_REV;
+    pVersionInfo->m_structSize = sizeof(M4_VersionInfo);
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_getVersion no error");
+    } else {
+        ALOGV("VideoEditorAudioDecoder_getVersion ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_getVersion end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_setOption(M4AD_Context pContext,
+        M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioDecoder_Context* pDecoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorAudioDecoder_setOption begin 0x%X", optionID);
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pDecoderContext = (VideoEditorAudioDecoder_Context*)pContext;
+
+    switch( optionID ) {
+        case M4AD_kOptionID_UserParam:
+            ALOGV("VideoEditorAudioDecodersetOption UserParam is not supported");
+            err = M4ERR_NOT_IMPLEMENTED;
+            break;
+
+        case M4AD_kOptionID_3gpReaderInterface:
+            ALOGV("VideoEditorAudioDecodersetOption 3gpReaderInterface");
+            pDecoderContext->m_pReader =
+             (M4READER_DataInterface *)optionValue;
+            break;
+
+        case M4AD_kOptionID_AudioAU:
+            ALOGV("VideoEditorAudioDecodersetOption AudioAU");
+            pDecoderContext->m_pNextAccessUnitToDecode =
+             (M4_AccessUnit *)optionValue;
+            break;
+
+        default:
+            ALOGV("VideoEditorAudioDecoder_setOption  unsupported optionId 0x%X",
+                optionID);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID);
+            break;
+    }
+
+cleanUp:
+    if( ((M4OSA_UInt32)M4NO_ERROR == err) || ((M4OSA_UInt32)M4ERR_NOT_IMPLEMENTED == err) ) {
+        ALOGV("VideoEditorAudioDecoder_setOption error 0x%X", err);
+    } else {
+        ALOGV("VideoEditorAudioDecoder_setOption ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_setOption end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_getOption(M4AD_Context pContext,
+        M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioDecoder_Context* pDecoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorAudioDecoder_getOption begin: optionID 0x%X", optionID);
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pDecoderContext = (VideoEditorAudioDecoder_Context*)pContext;
+
+    switch( optionID ) {
+
+        case M4AD_kOptionID_GetAudioAUErrCode:
+            *(uint32_t *)optionValue = pDecoderContext->readerErrCode;
+            break;
+
+        case M4AD_kOptionID_AudioNbChannels:
+            *(uint32_t *)optionValue =
+             pDecoderContext->mAudioStreamHandler->m_nbChannels;
+            break;
+
+        case M4AD_kOptionID_AudioSampFrequency:
+            *(uint32_t *)optionValue =
+             pDecoderContext->mAudioStreamHandler->m_samplingFrequency;
+            break;
+
+        case M4AD_kOptionID_AuCTS:
+            *(uint32_t *)optionValue = pDecoderContext->timeStampMs;
+            break;
+
+        default:
+            ALOGV("VideoEditorAudioDecoder_getOption unsupported optionId 0x%X",
+                optionID);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID);
+            break;
+    }
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_getOption no error");
+    } else {
+        ALOGV("VideoEditorAudioDecoder_getOption ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_getOption end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_getInterface(M4AD_Type decoderType,
+        M4AD_Type* pDecoderType, M4AD_Interface** pDecoderInterface) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pDecoderType, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pDecoderInterface, M4ERR_PARAMETER);
+
+    ALOGV("VideoEditorAudioDecoder_getInterface begin %d 0x%x 0x%x",
+        decoderType, pDecoderType, pDecoderInterface);
+
+    SAFE_MALLOC(*pDecoderInterface, M4AD_Interface, 1,
+        "VideoEditorAudioDecoder");
+
+    *pDecoderType = decoderType;
+
+    switch( decoderType ) {
+        case M4AD_kTypeAMRNB:
+            (*pDecoderInterface)->m_pFctCreateAudioDec =
+                VideoEditorAudioDecoder_create_AMRNB;
+            break;
+        case M4AD_kTypeAMRWB:
+            (*pDecoderInterface)->m_pFctCreateAudioDec =
+                VideoEditorAudioDecoder_create_AMRWB;
+            break;
+        case M4AD_kTypeAAC:
+            (*pDecoderInterface)->m_pFctCreateAudioDec =
+                VideoEditorAudioDecoder_create_AAC;
+            break;
+        case M4AD_kTypeMP3:
+            (*pDecoderInterface)->m_pFctCreateAudioDec =
+                VideoEditorAudioDecoder_create_MP3;
+            break;
+        default:
+            ALOGV("VEAD_getInterface ERROR: unsupported type %d", decoderType);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER);
+        break;
+    }
+    (*pDecoderInterface)->m_pFctDestroyAudioDec   =
+        VideoEditorAudioDecoder_destroy;
+    (*pDecoderInterface)->m_pFctResetAudioDec     = M4OSA_NULL;
+    (*pDecoderInterface)->m_pFctStartAudioDec     = M4OSA_NULL;
+    (*pDecoderInterface)->m_pFctStepAudioDec      =
+        VideoEditorAudioDecoder_step;
+    (*pDecoderInterface)->m_pFctGetVersionAudioDec =
+        VideoEditorAudioDecoder_getVersion;
+    (*pDecoderInterface)->m_pFctSetOptionAudioDec =
+        VideoEditorAudioDecoder_setOption;
+    (*pDecoderInterface)->m_pFctGetOptionAudioDec =
+        VideoEditorAudioDecoder_getOption;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioDecoder_getInterface no error");
+    } else {
+        *pDecoderInterface = M4OSA_NULL;
+        ALOGV("VideoEditorAudioDecoder_getInterface ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioDecoder_getInterface end");
+    return err;
+}
+
+
+extern "C" {
+
+M4OSA_ERR VideoEditorAudioDecoder_getInterface_AAC(M4AD_Type* pDecoderType,
+        M4AD_Interface** pDecoderInterface) {
+    ALOGV("TEST: AAC VideoEditorAudioDecoder_getInterface no error");
+    return VideoEditorAudioDecoder_getInterface(
+        M4AD_kTypeAAC, pDecoderType, pDecoderInterface);
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_getInterface_AMRNB(M4AD_Type* pDecoderType,
+        M4AD_Interface** pDecoderInterface) {
+    ALOGV("TEST: AMR VideoEditorAudioDecoder_getInterface no error");
+    return VideoEditorAudioDecoder_getInterface(
+        M4AD_kTypeAMRNB, pDecoderType, pDecoderInterface);
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_getInterface_AMRWB(M4AD_Type* pDecoderType,
+        M4AD_Interface** pDecoderInterface) {
+
+    return VideoEditorAudioDecoder_getInterface(
+        M4AD_kTypeAMRWB, pDecoderType, pDecoderInterface);
+}
+
+M4OSA_ERR VideoEditorAudioDecoder_getInterface_MP3(M4AD_Type* pDecoderType,
+        M4AD_Interface** pDecoderInterface) {
+
+    return VideoEditorAudioDecoder_getInterface(
+        M4AD_kTypeMP3, pDecoderType, pDecoderInterface);
+}
+
+}  // extern "C"
+
+}  // namespace android
diff --git a/frameworks/videoedit/stagefrightshells/VideoEditorAudioEncoder.cpp b/frameworks/videoedit/stagefrightshells/VideoEditorAudioEncoder.cpp
new file mode 100644
index 0000000..a91f3ee
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/VideoEditorAudioEncoder.cpp
@@ -0,0 +1,755 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+*************************************************************************
+* @file   VideoEditorAudioEncoder.cpp
+* @brief  StageFright shell Audio Encoder
+*************************************************************************
+*/
+
+#define LOG_NDEBUG 1
+#define LOG_TAG "VIDEOEDITOR_AUDIOENCODER"
+
+#include "M4OSA_Debug.h"
+#include "VideoEditorAudioEncoder.h"
+#include "VideoEditorUtils.h"
+
+#include "utils/Log.h"
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+
+/*** DEFINITIONS ***/
+// Force using software encoder as engine does not support prefetch
+#define VIDEOEDITOR_FORCECODEC kSoftwareCodecsOnly
+
+namespace android {
+struct VideoEditorAudioEncoderSource : public MediaSource {
+    public:
+        static sp<VideoEditorAudioEncoderSource> Create(
+            const sp<MetaData> &format);
+        virtual status_t start(MetaData *params = NULL);
+        virtual status_t stop();
+        virtual sp<MetaData> getFormat();
+        virtual status_t read(MediaBuffer **buffer,
+        const ReadOptions *options = NULL);
+        virtual int32_t storeBuffer(MediaBuffer *buffer);
+
+    protected:
+        virtual ~VideoEditorAudioEncoderSource();
+
+    private:
+        struct MediaBufferChain {
+            MediaBuffer* buffer;
+            MediaBufferChain* nextLink;
+        };
+        enum State {
+            CREATED,
+            STARTED,
+            ERROR
+        };
+
+        MediaBufferChain* mFirstBufferLink;
+        MediaBufferChain* mLastBufferLink;
+        int32_t mNbBuffer;
+        State mState;
+        sp<MetaData> mEncFormat;
+
+        VideoEditorAudioEncoderSource(const sp<MetaData> &format);
+
+        // Don't call me.
+        VideoEditorAudioEncoderSource(const VideoEditorAudioEncoderSource&);
+        VideoEditorAudioEncoderSource& operator=(
+            const VideoEditorAudioEncoderSource&);
+};
+
+sp<VideoEditorAudioEncoderSource> VideoEditorAudioEncoderSource::Create(
+    const sp<MetaData> &format) {
+
+    ALOGV("VideoEditorAudioEncoderSource::Create");
+    sp<VideoEditorAudioEncoderSource> aSource =
+        new VideoEditorAudioEncoderSource(format);
+
+    return aSource;
+}
+
+VideoEditorAudioEncoderSource::VideoEditorAudioEncoderSource(
+    const sp<MetaData> &format):
+        mFirstBufferLink(NULL),
+        mLastBufferLink(NULL),
+        mNbBuffer(0),
+        mState(CREATED),
+        mEncFormat(format) {
+    ALOGV("VideoEditorAudioEncoderSource::VideoEditorAudioEncoderSource");
+}
+
+
+VideoEditorAudioEncoderSource::~VideoEditorAudioEncoderSource() {
+    ALOGV("VideoEditorAudioEncoderSource::~VideoEditorAudioEncoderSource");
+
+    if( STARTED == mState ) {
+        stop();
+    }
+}
+
+status_t VideoEditorAudioEncoderSource::start(MetaData *meta) {
+    status_t err = OK;
+
+    ALOGV("VideoEditorAudioEncoderSource::start");
+
+    if( CREATED != mState ) {
+        ALOGV("VideoEditorAudioEncoderSource::start ERROR : invalid state %d",
+            mState);
+        return UNKNOWN_ERROR;
+    }
+
+    mState = STARTED;
+
+cleanUp:
+    ALOGV("VideoEditorAudioEncoderSource::start END (0x%x)", err);
+    return err;
+}
+
+status_t VideoEditorAudioEncoderSource::stop() {
+    status_t err = OK;
+
+    ALOGV("VideoEditorAudioEncoderSource::stop");
+
+    if( STARTED != mState ) {
+        ALOGV("VideoEditorAudioEncoderSource::stop ERROR: invalid state %d",
+            mState);
+        return UNKNOWN_ERROR;
+    }
+
+    int32_t i = 0;
+    MediaBufferChain* tmpLink = NULL;
+    while( mFirstBufferLink ) {
+        i++;
+        tmpLink = mFirstBufferLink;
+        mFirstBufferLink = mFirstBufferLink->nextLink;
+        delete tmpLink;
+    }
+    ALOGV("VideoEditorAudioEncoderSource::stop : %d buffer remained", i);
+    mFirstBufferLink = NULL;
+    mLastBufferLink = NULL;
+
+    mState = CREATED;
+
+    ALOGV("VideoEditorAudioEncoderSource::stop END (0x%x)", err);
+    return err;
+}
+
+sp<MetaData> VideoEditorAudioEncoderSource::getFormat() {
+    ALOGV("VideoEditorAudioEncoderSource::getFormat");
+    return mEncFormat;
+}
+
+status_t VideoEditorAudioEncoderSource::read(MediaBuffer **buffer,
+        const ReadOptions *options) {
+    MediaSource::ReadOptions readOptions;
+    status_t err = OK;
+    MediaBufferChain* tmpLink = NULL;
+
+    ALOGV("VideoEditorAudioEncoderSource::read");
+
+    if ( STARTED != mState ) {
+        ALOGV("VideoEditorAudioEncoderSource::read ERROR : invalid state %d",
+            mState);
+        return UNKNOWN_ERROR;
+    }
+
+    if( NULL == mFirstBufferLink ) {
+        *buffer = NULL;
+        ALOGV("VideoEditorAudioEncoderSource::read : EOS");
+        return ERROR_END_OF_STREAM;
+    }
+    *buffer = mFirstBufferLink->buffer;
+
+    tmpLink = mFirstBufferLink;
+    mFirstBufferLink = mFirstBufferLink->nextLink;
+    if( NULL == mFirstBufferLink ) {
+        mLastBufferLink = NULL;
+    }
+    delete tmpLink;
+    mNbBuffer--;
+
+    ALOGV("VideoEditorAudioEncoderSource::read END (0x%x)", err);
+    return err;
+}
+
+int32_t VideoEditorAudioEncoderSource::storeBuffer(MediaBuffer *buffer) {
+    status_t err = OK;
+
+    ALOGV("VideoEditorAudioEncoderSource::storeBuffer");
+
+    MediaBufferChain* newLink = new MediaBufferChain;
+    newLink->buffer = buffer;
+    newLink->nextLink = NULL;
+    if( NULL != mLastBufferLink ) {
+        mLastBufferLink->nextLink = newLink;
+    } else {
+        mFirstBufferLink = newLink;
+    }
+    mLastBufferLink = newLink;
+    mNbBuffer++;
+
+    ALOGV("VideoEditorAudioEncoderSource::storeBuffer END");
+    return mNbBuffer;
+}
+
+/********************
+ * ENGINE INTERFACE *
+ ********************/
+/**
+ ******************************************************************************
+ * structure VideoEditorAudioEncoder_Context
+ * @brief    This structure defines the context of the StageFright audio
+ *           encoder shell
+ ******************************************************************************
+*/
+typedef struct {
+    M4ENCODER_AudioFormat             mFormat;
+    M4ENCODER_AudioParams*            mCodecParams;
+    M4ENCODER_AudioDecSpecificInfo    mDSI;
+    sp<VideoEditorAudioEncoderSource> mEncoderSource;
+    OMXClient                         mClient;
+    sp<MediaSource>                   mEncoder;
+    uint32_t                          mNbInputFrames;
+    uint32_t                          mNbOutputFrames;
+    int64_t                           mFirstOutputCts;
+    int64_t                           mLastOutputCts;
+} VideoEditorAudioEncoder_Context;
+
+M4OSA_ERR VideoEditorAudioEncoder_cleanup(M4OSA_Context pContext) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorAudioEncoder_cleanup begin");
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
+
+    SAFE_FREE(pEncoderContext->mDSI.pInfo);
+    SAFE_FREE(pEncoderContext);
+    pContext = M4OSA_NULL;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_cleanup no error");
+    } else {
+        ALOGV("VideoEditorAudioEncoder_cleanup ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioEncoder_cleanup end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_init(M4ENCODER_AudioFormat format,
+        M4OSA_Context* pContext, M4OSA_Void* pUserData) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
+
+    ALOGV(" VideoEditorAudioEncoder_init begin: format %d", format);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    SAFE_MALLOC(pEncoderContext, VideoEditorAudioEncoder_Context, 1,
+        "VideoEditorAudioEncoder");
+    pEncoderContext->mFormat = format;
+
+    *pContext = pEncoderContext;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_init no error");
+    } else {
+        VideoEditorAudioEncoder_cleanup(pEncoderContext);
+        *pContext = M4OSA_NULL;
+        ALOGV("VideoEditorAudioEncoder_init ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioEncoder_init end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_init_AAC(M4OSA_Context* pContext,
+        M4OSA_Void* pUserData) {
+    return VideoEditorAudioEncoder_init(M4ENCODER_kAAC, pContext, pUserData);
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_init_AMRNB(M4OSA_Context* pContext,
+        M4OSA_Void* pUserData) {
+    return VideoEditorAudioEncoder_init(M4ENCODER_kAMRNB, pContext, pUserData);
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_init_MP3(M4OSA_Context* pContext,
+        M4OSA_Void* pUserData) {
+    return VideoEditorAudioEncoder_init(M4ENCODER_kMP3, pContext, pUserData);
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_close(M4OSA_Context pContext) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorAudioEncoder_close begin");
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
+
+    SAFE_FREE(pEncoderContext->mCodecParams);
+
+    pEncoderContext->mEncoder->stop();
+    pEncoderContext->mEncoder.clear();
+    pEncoderContext->mClient.disconnect();
+    pEncoderContext->mEncoderSource.clear();
+
+    ALOGV("AudioEncoder_close:IN %d frames,OUT %d frames from %lld to %lld",
+        pEncoderContext->mNbInputFrames,
+        pEncoderContext->mNbOutputFrames, pEncoderContext->mFirstOutputCts,
+        pEncoderContext->mLastOutputCts);
+
+    if( pEncoderContext->mNbInputFrames != pEncoderContext->mNbInputFrames ) {
+        ALOGV("VideoEditorAudioEncoder_close:some frames were not encoded %d %d",
+            pEncoderContext->mNbInputFrames, pEncoderContext->mNbInputFrames);
+    }
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_close no error");
+    } else {
+        ALOGV("VideoEditorAudioEncoder_close ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioEncoder_close begin end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_open(M4OSA_Context pContext,
+        M4ENCODER_AudioParams *pParams, M4ENCODER_AudioDecSpecificInfo *pDSI,
+        M4OSA_Context pGrabberContext) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
+    status_t result = OK;
+    sp<MetaData> encoderMetadata = NULL;
+    const char* mime = NULL;
+    int32_t iNbChannel = 0;
+    uint32_t codecFlags = 0;
+
+    ALOGV("VideoEditorAudioEncoder_open begin");
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pParams,  M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pDSI,     M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
+    pDSI->pInfo = M4OSA_NULL;
+    pDSI->infoSize = 0;
+
+    pEncoderContext->mNbInputFrames  = 0;
+    pEncoderContext->mNbOutputFrames = 0;
+    pEncoderContext->mFirstOutputCts = -1;
+    pEncoderContext->mLastOutputCts  = -1;
+
+    // Allocate & initialize the encoding parameters
+    ALOGV("VideoEditorAudioEncoder_open : params F=%d CN=%d BR=%d F=%d",
+        pParams->Frequency, pParams->ChannelNum, pParams->Bitrate,
+        pParams->Format);
+    SAFE_MALLOC(pEncoderContext->mCodecParams, M4ENCODER_AudioParams, 1,
+        "VIDEOEDITOR CodecParams");
+    pEncoderContext->mCodecParams->Frequency  = pParams->Frequency;
+    pEncoderContext->mCodecParams->ChannelNum = pParams->ChannelNum;
+    pEncoderContext->mCodecParams->Bitrate    = pParams->Bitrate;
+    pEncoderContext->mCodecParams->Format     = pParams->Format;
+
+    // Check output format consistency
+    VIDEOEDITOR_CHECK(pEncoderContext->mCodecParams->Format ==
+        pEncoderContext->mFormat, M4ERR_PARAMETER);
+
+    /**
+     * StageFright graph building
+     */
+    // Create the meta data for the encoder
+    encoderMetadata = new MetaData;
+    switch( pEncoderContext->mCodecParams->Format ) {
+        case M4ENCODER_kAAC:
+        {
+            mime = MEDIA_MIMETYPE_AUDIO_AAC;
+            break;
+        }
+        case M4ENCODER_kAMRNB:
+        {
+            mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
+            break;
+        }
+        default:
+        {
+            VIDEOEDITOR_CHECK(!"AudioEncoder_open : incorrect input format",
+            M4ERR_PARAMETER);
+            break;
+        }
+    }
+    encoderMetadata->setCString(kKeyMIMEType, mime);
+    encoderMetadata->setInt32(kKeySampleRate,
+        (int32_t)pEncoderContext->mCodecParams->Frequency);
+    encoderMetadata->setInt32(kKeyBitRate,
+        (int32_t)pEncoderContext->mCodecParams->Bitrate);
+
+    switch( pEncoderContext->mCodecParams->ChannelNum ) {
+        case M4ENCODER_kMono:
+        {
+            iNbChannel = 1;
+            break;
+        }
+        case M4ENCODER_kStereo:
+        {
+            iNbChannel = 2;
+            break;
+        }
+        default:
+        {
+            VIDEOEDITOR_CHECK(!"AudioEncoder_open : incorrect channel number",
+                M4ERR_STATE);
+            break;
+        }
+    }
+    encoderMetadata->setInt32(kKeyChannelCount, iNbChannel);
+
+    // Create the encoder source
+    pEncoderContext->mEncoderSource = VideoEditorAudioEncoderSource::Create(
+        encoderMetadata);
+    VIDEOEDITOR_CHECK(NULL != pEncoderContext->mEncoderSource.get(),
+        M4ERR_STATE);
+
+    // Connect to the OMX client
+    result = pEncoderContext->mClient.connect();
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+
+    // Create the OMX codec
+#ifdef VIDEOEDITOR_FORCECODEC
+    codecFlags |= OMXCodec::VIDEOEDITOR_FORCECODEC;
+#endif /* VIDEOEDITOR_FORCECODEC */
+    // FIXME:
+    // We are moving away to use software AACEncoder and instead use OMX-based
+    // software AAC audio encoder. We want to use AACEncoder for now. After we
+    // fix the interface issue with the OMX-based AAC audio encoder, we should
+    // then set the component name back to NULL to allow the system to pick up
+    // the right AAC audio encoder.
+    pEncoderContext->mEncoder = OMXCodec::Create(
+            pEncoderContext->mClient.interface(), encoderMetadata, true,
+            pEncoderContext->mEncoderSource, "AACEncoder" /* component name */,
+            codecFlags);
+    VIDEOEDITOR_CHECK(NULL != pEncoderContext->mEncoder.get(), M4ERR_STATE);
+
+    // Start the graph
+    result = pEncoderContext->mEncoder->start();
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+
+    // Get AAC DSI, this code can only work with software encoder
+    if( M4ENCODER_kAAC == pEncoderContext->mCodecParams->Format ) {
+        int32_t      isCodecConfig = 0;
+        MediaBuffer* buffer        = NULL;
+
+        // Read once to get the DSI
+        result = pEncoderContext->mEncoder->read(&buffer, NULL);
+        VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+        VIDEOEDITOR_CHECK(buffer->meta_data()->findInt32(kKeyIsCodecConfig,
+            &isCodecConfig) && isCodecConfig, M4ERR_STATE);
+
+        // Save the DSI
+        pEncoderContext->mDSI.infoSize = (M4OSA_UInt32)buffer->range_length();
+        SAFE_MALLOC(pEncoderContext->mDSI.pInfo, M4OSA_Int8,
+            pEncoderContext->mDSI.infoSize, "Encoder header");
+
+        memcpy((void *)pEncoderContext->mDSI.pInfo,
+            (void *)((M4OSA_MemAddr8)(buffer->data())+buffer->range_offset()),
+            pEncoderContext->mDSI.infoSize);
+
+        buffer->release();
+        *pDSI = pEncoderContext->mDSI;
+    }
+    ALOGV("VideoEditorAudioEncoder_open : DONE");
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_open no error");
+    } else {
+        VideoEditorAudioEncoder_close(pEncoderContext);
+        ALOGV("VideoEditorAudioEncoder_open ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioEncoder_open end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_processInputBuffer(M4OSA_Context pContext,
+        M4ENCODER_AudioBuffer* pInBuffer) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
+    M4OSA_Int8* pData = M4OSA_NULL;
+    MediaBuffer* buffer = NULL;
+    int32_t nbBuffer = 0;
+
+    ALOGV("VideoEditorAudioEncoder_processInputBuffer begin");
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
+
+    switch( pEncoderContext->mCodecParams->ChannelNum ) {
+        case M4ENCODER_kMono:
+        case M4ENCODER_kStereo:
+            // Let the MediaBuffer own the data so we don't have to free it
+            buffer = new MediaBuffer((size_t)pInBuffer->pTableBufferSize[0]);
+            pData = (M4OSA_Int8*)buffer->data() + buffer->range_offset();
+            memcpy((void *)pData, (void *)pInBuffer->pTableBuffer[0],
+                pInBuffer->pTableBufferSize[0]);
+            break;
+        default:
+            ALOGV("VEAE_processInputBuffer unsupported channel configuration %d",
+                pEncoderContext->mCodecParams->ChannelNum);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER);
+            break;
+    }
+
+    ALOGV("VideoEditorAudioEncoder_processInputBuffer : store %d bytes",
+        buffer->range_length());
+    // Push the buffer to the source
+    nbBuffer = pEncoderContext->mEncoderSource->storeBuffer(buffer);
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_processInputBuffer no error");
+    } else {
+        if( NULL != buffer ) {
+            buffer->release();
+        }
+        ALOGV("VideoEditorAudioEncoder_processInputBuffer ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioEncoder_processInputBuffer end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_processOutputBuffer(M4OSA_Context pContext,
+        MediaBuffer* buffer, M4ENCODER_AudioBuffer* pOutBuffer) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
+    M4OSA_UInt32 Cts = 0;
+    int32_t i32Tmp = 0;
+    int64_t i64Tmp = 0;
+    status_t result = OK;
+
+    ALOGV("VideoEditorAudioEncoder_processOutputBuffer begin");
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,   M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != buffer,     M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pOutBuffer, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
+
+    // Process the returned AU
+    if( 0 == buffer->range_length() ) {
+        // Encoder has no data yet, nothing unusual
+        ALOGV("VideoEditorAudioEncoder_processOutputBuffer : buffer is empty");
+        pOutBuffer->pTableBufferSize[0] = 0;
+        goto cleanUp;
+    }
+    if( buffer->meta_data()->findInt32(kKeyIsCodecConfig, &i32Tmp) && i32Tmp ) {
+        /* This should not happen with software encoder,
+         * DSI was retrieved beforehand */
+        VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_STATE);
+    } else {
+        // Check the CTS
+        VIDEOEDITOR_CHECK(buffer->meta_data()->findInt64(kKeyTime, &i64Tmp),
+            M4ERR_STATE);
+        Cts = (M4OSA_Int32)(i64Tmp/1000);
+
+        pEncoderContext->mNbOutputFrames++;
+        if( 0 > pEncoderContext->mFirstOutputCts ) {
+            pEncoderContext->mFirstOutputCts = i64Tmp;
+        }
+        pEncoderContext->mLastOutputCts = i64Tmp;
+
+        // Format the AU
+        memcpy((void *)pOutBuffer->pTableBuffer[0],
+            (void *)((M4OSA_MemAddr8)(buffer->data())+buffer->range_offset()),
+            buffer->range_length());
+        pOutBuffer->pTableBufferSize[0] = (M4OSA_UInt32)buffer->range_length();
+    }
+
+cleanUp:
+    // Release the buffer
+    buffer->release();
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_processOutputBuffer no error");
+    } else {
+        ALOGV("VideoEditorAudioEncoder_processOutputBuffer ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioEncoder_processOutputBuffer end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_step(M4OSA_Context pContext,
+        M4ENCODER_AudioBuffer* pInBuffer, M4ENCODER_AudioBuffer* pOutBuffer) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
+    status_t result = OK;
+    MediaBuffer* buffer = NULL;
+
+    ALOGV("VideoEditorAudioEncoder_step begin");
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,   M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pInBuffer,  M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pOutBuffer, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
+    pEncoderContext->mNbInputFrames++;
+
+    // Push the input buffer to the encoder source
+    err = VideoEditorAudioEncoder_processInputBuffer(pEncoderContext,pInBuffer);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+    // Read
+    result = pEncoderContext->mEncoder->read(&buffer, NULL);
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+
+    // Provide the encoded AU to the writer
+    err = VideoEditorAudioEncoder_processOutputBuffer(pEncoderContext, buffer,
+        pOutBuffer);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_step no error");
+    } else {
+        ALOGV("VideoEditorAudioEncoder_step ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioEncoder_step end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_getOption(M4OSA_Context pContext,
+        M4OSA_OptionID optionID, M4OSA_DataOption* optionValue) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorAudioEncoder_Context* pEncoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorAudioEncoder_getOption begin optionID 0x%X", optionID);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorAudioEncoder_Context*)pContext;
+
+    switch( optionID ) {
+        default:
+            ALOGV("VideoEditorAudioEncoder_getOption: unsupported optionId 0x%X",
+                optionID);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID);
+            break;
+    }
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_getOption no error");
+    } else {
+        ALOGV("VideoEditorAudioEncoder_getOption ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorAudioEncoder_getOption end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_getInterface(
+        M4ENCODER_AudioFormat format, M4ENCODER_AudioFormat* pFormat,
+        M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
+    M4OSA_ERR err = M4NO_ERROR;
+
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pFormat,           M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pEncoderInterface, M4ERR_PARAMETER);
+
+    ALOGV("VideoEditorAudioEncoder_getInterface 0x%x 0x%x",pFormat,
+        pEncoderInterface);
+    SAFE_MALLOC(*pEncoderInterface, M4ENCODER_AudioGlobalInterface, 1,
+        "AudioEncoder");
+
+    *pFormat = format;
+
+    switch( format ) {
+        case M4ENCODER_kAAC:
+        {
+            (*pEncoderInterface)->pFctInit = VideoEditorAudioEncoder_init_AAC;
+            break;
+        }
+        case M4ENCODER_kAMRNB:
+        {
+            (*pEncoderInterface)->pFctInit = VideoEditorAudioEncoder_init_AMRNB;
+            break;
+        }
+        case M4ENCODER_kMP3:
+        {
+            (*pEncoderInterface)->pFctInit = VideoEditorAudioEncoder_init_MP3;
+            break;
+        }
+        default:
+        {
+            ALOGV("VideoEditorAudioEncoder_getInterface: unsupported format %d",
+                format);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER);
+        break;
+        }
+    }
+    (*pEncoderInterface)->pFctCleanUp      = VideoEditorAudioEncoder_cleanup;
+    (*pEncoderInterface)->pFctOpen         = VideoEditorAudioEncoder_open;
+    (*pEncoderInterface)->pFctClose        = VideoEditorAudioEncoder_close;
+    (*pEncoderInterface)->pFctStep         = VideoEditorAudioEncoder_step;
+    (*pEncoderInterface)->pFctGetOption    = VideoEditorAudioEncoder_getOption;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorAudioEncoder_getInterface no error");
+    } else {
+        *pEncoderInterface = M4OSA_NULL;
+        ALOGV("VideoEditorAudioEncoder_getInterface ERROR 0x%X", err);
+    }
+    return err;
+}
+extern "C" {
+
+M4OSA_ERR VideoEditorAudioEncoder_getInterface_AAC(
+        M4ENCODER_AudioFormat* pFormat,
+        M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
+    return VideoEditorAudioEncoder_getInterface(
+        M4ENCODER_kAAC, pFormat, pEncoderInterface);
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_getInterface_AMRNB(
+        M4ENCODER_AudioFormat* pFormat,
+        M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
+
+    return VideoEditorAudioEncoder_getInterface(
+        M4ENCODER_kAMRNB, pFormat, pEncoderInterface);
+}
+
+M4OSA_ERR VideoEditorAudioEncoder_getInterface_MP3(
+        M4ENCODER_AudioFormat* pFormat,
+        M4ENCODER_AudioGlobalInterface** pEncoderInterface) {
+    ALOGV("VideoEditorAudioEncoder_getInterface_MP3 no error");
+
+    return VideoEditorAudioEncoder_getInterface(
+        M4ENCODER_kMP3, pFormat, pEncoderInterface);
+}
+
+}  // extern "C"
+
+}  // namespace android
diff --git a/frameworks/videoedit/stagefrightshells/VideoEditorBuffer.c b/frameworks/videoedit/stagefrightshells/VideoEditorBuffer.c
new file mode 100644
index 0000000..98919d2
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/VideoEditorBuffer.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+*************************************************************************
+* @file   VideoEditorBuffer.c
+* @brief  StageFright shell Buffer
+*************************************************************************
+*/
+#undef M4OSA_TRACE_LEVEL
+#define M4OSA_TRACE_LEVEL 1
+
+#include "VideoEditorBuffer.h"
+#include "utils/Log.h"
+
+#define VIDEOEDITOR_BUFFEPOOL_MAX_NAME_SIZE 40
+
+#define VIDEOEDITOR_SAFE_FREE(p) \
+{ \
+    if(M4OSA_NULL != p) \
+    { \
+        free(p); \
+        p = M4OSA_NULL; \
+    } \
+}
+
+/**
+ ************************************************************************
+ M4OSA_ERR VIDEOEDITOR_BUFFER_allocatePool(VIDEOEDITOR_BUFFER_Pool** ppool,
+ *                                         M4OSA_UInt32 nbBuffers)
+ * @brief   Allocate a pool of nbBuffers buffers
+ *
+ * @param   ppool      : IN The buffer pool to create
+ * @param   nbBuffers  : IN The number of buffers in the pool
+ * @param   poolName   : IN a name given to the pool
+ * @return  Error code
+ ************************************************************************
+*/
+M4OSA_ERR VIDEOEDITOR_BUFFER_allocatePool(VIDEOEDITOR_BUFFER_Pool** ppool,
+        M4OSA_UInt32 nbBuffers, M4OSA_Char* poolName)
+{
+    M4OSA_ERR lerr = M4NO_ERROR;
+    VIDEOEDITOR_BUFFER_Pool* pool;
+
+    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : ppool = 0x%x nbBuffers = %d ",
+        ppool, nbBuffers);
+
+    pool = M4OSA_NULL;
+    pool = (VIDEOEDITOR_BUFFER_Pool*)M4OSA_32bitAlignedMalloc(
+            sizeof(VIDEOEDITOR_BUFFER_Pool), VIDEOEDITOR_BUFFER_EXTERNAL,
+            (M4OSA_Char*)("VIDEOEDITOR_BUFFER_allocatePool: pool"));
+    if (M4OSA_NULL == pool)
+    {
+        lerr = M4ERR_ALLOC;
+        goto VIDEOEDITOR_BUFFER_allocatePool_Cleanup;
+    }
+
+    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : Allocating Pool buffers");
+    pool->pNXPBuffer = M4OSA_NULL;
+    pool->pNXPBuffer = (VIDEOEDITOR_BUFFER_Buffer*)M4OSA_32bitAlignedMalloc(
+                            sizeof(VIDEOEDITOR_BUFFER_Buffer)*nbBuffers,
+                            VIDEOEDITOR_BUFFER_EXTERNAL,
+                            (M4OSA_Char*)("BUFFER_allocatePool: pNXPBuffer"));
+    if(M4OSA_NULL == pool->pNXPBuffer)
+    {
+        lerr = M4ERR_ALLOC;
+        goto VIDEOEDITOR_BUFFER_allocatePool_Cleanup;
+    }
+
+    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : Allocating Pool name buffer");
+    pool->poolName = M4OSA_NULL;
+    pool->poolName = (M4OSA_Char*)M4OSA_32bitAlignedMalloc(
+        VIDEOEDITOR_BUFFEPOOL_MAX_NAME_SIZE,VIDEOEDITOR_BUFFER_EXTERNAL,
+        (M4OSA_Char*)("VIDEOEDITOR_BUFFER_allocatePool: poolname"));
+    if(pool->poolName == M4OSA_NULL)
+    {
+        lerr = M4ERR_ALLOC;
+        goto VIDEOEDITOR_BUFFER_allocatePool_Cleanup;
+    }
+
+    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : Assigning Pool name buffer");
+
+    memset((void *)pool->poolName, 0,VIDEOEDITOR_BUFFEPOOL_MAX_NAME_SIZE);
+    memcpy((void *)pool->poolName, (void *)poolName,
+        VIDEOEDITOR_BUFFEPOOL_MAX_NAME_SIZE-1);
+
+    pool->NB = nbBuffers;
+
+VIDEOEDITOR_BUFFER_allocatePool_Cleanup:
+    if(M4NO_ERROR != lerr)
+    {
+        VIDEOEDITOR_SAFE_FREE(pool->pNXPBuffer);
+        VIDEOEDITOR_SAFE_FREE(pool->poolName);
+        VIDEOEDITOR_SAFE_FREE(pool);
+    }
+    *ppool = pool;
+    ALOGV("VIDEOEDITOR_BUFFER_allocatePool END");
+
+    return lerr;
+}
+
+/**
+ ************************************************************************
+ M4OSA_ERR VIDEOEDITOR_BUFFER_freePool(VIDEOEDITOR_BUFFER_Pool* ppool)
+ * @brief   Deallocate a buffer pool
+ *
+ * @param   ppool      : IN The buffer pool to free
+ * @return  Error code
+ ************************************************************************
+*/
+M4OSA_ERR VIDEOEDITOR_BUFFER_freePool(VIDEOEDITOR_BUFFER_Pool* ppool)
+{
+    M4OSA_ERR err;
+    M4OSA_UInt32  j = 0;
+
+    ALOGV("VIDEOEDITOR_BUFFER_freePool : ppool = 0x%x", ppool);
+
+    err = M4NO_ERROR;
+
+    for (j = 0; j < ppool->NB; j++)
+    {
+        if(M4OSA_NULL != ppool->pNXPBuffer[j].pData)
+        {
+            free(ppool->pNXPBuffer[j].pData);
+            ppool->pNXPBuffer[j].pData = M4OSA_NULL;
+        }
+    }
+
+    if(ppool != M4OSA_NULL)
+    {
+        SAFE_FREE(ppool->pNXPBuffer);
+        SAFE_FREE(ppool->poolName);
+        SAFE_FREE(ppool);
+    }
+
+    return(err);
+}
+
+/**
+ ************************************************************************
+ M4OSA_ERR VIDEOEDITOR_BUFFER_getBuffer(VIDEOEDITOR_BUFFER_Pool* ppool,
+ *         VIDEOEDITOR_BUFFER_Buffer** pNXPBuffer)
+ * @brief   Returns a buffer in a given state
+ *
+ * @param   ppool      : IN The buffer pool
+ * @param   desiredState : IN The buffer state
+ * @param   pNXPBuffer : IN The selected buffer
+ * @return  Error code
+ ************************************************************************
+*/
+M4OSA_ERR VIDEOEDITOR_BUFFER_getBuffer(VIDEOEDITOR_BUFFER_Pool* ppool,
+        VIDEOEDITOR_BUFFER_State desiredState,
+        VIDEOEDITOR_BUFFER_Buffer** pNXPBuffer)
+{
+    M4OSA_ERR err = M4NO_ERROR;
+    M4OSA_Bool bFound = M4OSA_FALSE;
+    M4OSA_UInt32 i, ibuf;
+
+    ALOGV("VIDEOEDITOR_BUFFER_getBuffer from %s in state=%d",
+        ppool->poolName, desiredState);
+
+    ibuf = 0;
+
+    for (i=0; i < ppool->NB; i++)
+    {
+        bFound = (ppool->pNXPBuffer[i].state == desiredState);
+        if (bFound)
+        {
+            ibuf = i;
+            break;
+        }
+    }
+
+    if(!bFound)
+    {
+        ALOGV("VIDEOEDITOR_BUFFER_getBuffer No buffer available in state %d",
+            desiredState);
+        *pNXPBuffer = M4OSA_NULL;
+        return M4ERR_NO_BUFFER_AVAILABLE;
+    }
+
+    /* case where a buffer has been found */
+    *pNXPBuffer = &(ppool->pNXPBuffer[ibuf]);
+
+    ALOGV("VIDEOEDITOR_BUFFER_getBuffer: idx = %d", ibuf);
+
+    return(err);
+}
+
+M4OSA_ERR VIDEOEDITOR_BUFFER_initPoolBuffers(VIDEOEDITOR_BUFFER_Pool* pool,
+    M4OSA_UInt32 lSize)
+{
+    M4OSA_ERR     err = M4NO_ERROR;
+    M4OSA_UInt32  index, j;
+
+    /**
+     * Initialize all the buffers in the pool */
+    for(index = 0; index < pool->NB; index++)
+    {
+        pool->pNXPBuffer[index].pData = M4OSA_NULL;
+        pool->pNXPBuffer[index].pData = (M4OSA_Void*)M4OSA_32bitAlignedMalloc(
+            lSize, VIDEOEDITOR_BUFFER_EXTERNAL,
+            (M4OSA_Char*)("BUFFER_initPoolBuffers: Buffer data"));
+        if(M4OSA_NULL == pool->pNXPBuffer[index].pData)
+        {
+            for (j = 0; j < index; j++)
+            {
+                if(M4OSA_NULL != pool->pNXPBuffer[j].pData)
+                {
+                    free(pool->pNXPBuffer[j].pData);
+                    pool->pNXPBuffer[j].pData = M4OSA_NULL;
+                }
+            }
+            err = M4ERR_ALLOC;
+            return err;
+        }
+        pool->pNXPBuffer[index].size = 0;
+        pool->pNXPBuffer[index].state = VIDEOEDITOR_BUFFER_kEmpty;
+        pool->pNXPBuffer[index].idx = index;
+        pool->pNXPBuffer[index].buffCTS = -1;
+    }
+    return err;
+}
+
+M4OSA_ERR VIDEOEDITOR_BUFFER_getOldestBuffer(VIDEOEDITOR_BUFFER_Pool *pool,
+        VIDEOEDITOR_BUFFER_State desiredState,
+        VIDEOEDITOR_BUFFER_Buffer** pNXPBuffer)
+{
+    M4OSA_ERR     err = M4NO_ERROR;
+    M4OSA_UInt32  index, j;
+    M4_MediaTime  candidateTimeStamp = (M4_MediaTime)0x7ffffff;
+    M4OSA_Bool    bFound = M4OSA_FALSE;
+
+    *pNXPBuffer = M4OSA_NULL;
+    for(index = 0; index< pool->NB; index++)
+    {
+        if(pool->pNXPBuffer[index].state == desiredState)
+        {
+            if(pool->pNXPBuffer[index].buffCTS <= candidateTimeStamp)
+            {
+                bFound = M4OSA_TRUE;
+                candidateTimeStamp = pool->pNXPBuffer[index].buffCTS;
+                    *pNXPBuffer = &(pool->pNXPBuffer[index]);
+            }
+        }
+    }
+    if(M4OSA_FALSE == bFound)
+    {
+        ALOGV("VIDEOEDITOR_BUFFER_getOldestBuffer WARNING no buffer available");
+        err = M4ERR_NO_BUFFER_AVAILABLE;
+    }
+    return err;
+}
diff --git a/frameworks/videoedit/stagefrightshells/VideoEditorMp3Reader.cpp b/frameworks/videoedit/stagefrightshells/VideoEditorMp3Reader.cpp
new file mode 100644
index 0000000..af53c54
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/VideoEditorMp3Reader.cpp
@@ -0,0 +1,803 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+*************************************************************************
+* @file   VideoEditorMp3Reader.cpp
+* @brief  StageFright shell MP3 Reader
+*************************************************************************
+*/
+#define LOG_NDEBUG 1
+#define LOG_TAG "VIDEOEDITOR_MP3READER"
+
+/**
+ * HEADERS
+ *
+ */
+#include "M4OSA_Debug.h"
+#include "M4SYS_AccessUnit.h"
+#include "VideoEditorMp3Reader.h"
+#include "VideoEditorUtils.h"
+
+#include "utils/Log.h"
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/FileSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+/**
+ * SOURCE CLASS
+ */
+
+namespace android {
+/**
+ * ENGINE INTERFACE
+ */
+
+/**
+ **************************************************************************
+ * structure VideoEditorMp3Reader_Context
+ * @brief    This structure defines the context of the SF MP3 reader shell.
+ **************************************************************************
+ */
+typedef struct {
+    sp<DataSource>              mDataSource;
+    sp<MediaExtractor>          mExtractor;
+    sp<MediaSource>             mMediaSource;
+    M4_AudioStreamHandler*      mAudioStreamHandler;
+    M4SYS_AccessUnit            mAudioAu;
+    M4OSA_Time                  mMaxDuration;
+    M4OSA_UInt8                 mStreamNumber;
+    M4OSA_Bool                  mSeeking;
+    M4OSA_Time                  mSeekTime;
+    uint32_t                    mExtractorFlags;
+} VideoEditorMp3Reader_Context;
+
+/**
+ ****************************************************************************
+ * @brief    create an instance of the MP3 reader
+ * @note     allocates the context
+ *
+ * @param    pContext:        (OUT)    pointer on a reader context
+ *
+ * @return    M4NO_ERROR                 there is no error
+ * @return    M4ERR_ALLOC                a memory allocation has failed
+ * @return    M4ERR_PARAMETER            at least one parameter is not valid
+ ****************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_create(M4OSA_Context *pContext) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorMp3Reader_Context *pReaderContext = M4OSA_NULL;
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    ALOGV("VideoEditorMp3Reader_create begin");
+
+    /* Context allocation & initialization */
+    SAFE_MALLOC(pReaderContext, VideoEditorMp3Reader_Context, 1,
+        "VideoEditorMp3Reader");
+
+    pReaderContext->mAudioStreamHandler  = M4OSA_NULL;
+    pReaderContext->mAudioAu.dataAddress = M4OSA_NULL;
+    pReaderContext->mMaxDuration = 0;
+    *pContext = pReaderContext;
+
+cleanUp:
+    if (M4NO_ERROR == err) {
+        ALOGV("VideoEditorMp3Reader_create no error");
+    } else {
+        ALOGV("VideoEditorMp3Reader_create ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorMp3Reader_create end");
+    return err;
+}
+
+/**
+ *******************************************************************************
+ * @brief     destroy the instance of the MP3 reader
+ * @note      after this call the context is invalid
+ * @param     context:        (IN)    Context of the reader
+ * @return    M4NO_ERROR                 there is no error
+ * @return    M4ERR_PARAMETER            The input parameter is not properly set
+ *******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_destroy(M4OSA_Context pContext) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)pContext;
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderContext, M4ERR_PARAMETER);
+    ALOGV("VideoEditorMp3Reader_destroy begin");
+
+    SAFE_FREE(pReaderContext);
+cleanUp:
+    if (M4NO_ERROR == err) {
+        ALOGV("VideoEditorMp3Reader_destroy no error");
+    } else {
+        ALOGV("VideoEditorMp3Reader_destroy ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorMp3Reader_destroy end");
+    return err;
+}
+/**
+ ******************************************************************************
+ * @brief    open the reader and initializes its created instance
+ * @note    this function opens the MP3 file
+ * @param    context:            (IN)    Context of the reader
+ * @param    pFileDescriptor:    (IN)    Pointer to proprietary data identifying
+ *                                       the media to open
+
+ * @return    M4NO_ERROR                     there is no error
+ * @return    M4ERR_PARAMETER                the context is NULL
+ * @return    M4ERR_BAD_CONTEXT              provided context is not a valid one
+ * @return    M4ERR_UNSUPPORTED_MEDIA_TYPE   the media is DRM protected
+ ******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_open(M4OSA_Context context,
+        M4OSA_Void* pFileDescriptor){
+    VideoEditorMp3Reader_Context *pReaderContext =
+    (VideoEditorMp3Reader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditorMp3Reader_open begin");
+    /* Check function parameters*/
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext),  M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_open: invalid context pointer");
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pFileDescriptor), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_open: invalid pointer pFileDescriptor");
+
+    ALOGV("VideoEditorMp3Reader_open Datasource start %s",
+        (char*)pFileDescriptor);
+    pReaderContext->mDataSource = new FileSource ((char*)pFileDescriptor);
+    ALOGV("VideoEditorMp3Reader_open Datasource end");
+
+    if (pReaderContext->mDataSource == NULL) {
+        ALOGV("VideoEditorMp3Reader_open Datasource error");
+        return UNKNOWN_ERROR;
+    }
+
+    ALOGV("VideoEditorMp3Reader_open extractor start");
+    pReaderContext->mExtractor = MediaExtractor::Create(
+        pReaderContext->mDataSource,MEDIA_MIMETYPE_AUDIO_MPEG);
+    ALOGV("VideoEditorMp3Reader_open extractor end");
+
+    if (pReaderContext->mExtractor == NULL)    {
+        ALOGV("VideoEditorMp3Reader_open extractor error");
+        return UNKNOWN_ERROR;
+    }
+    pReaderContext->mStreamNumber = 0;
+
+    int32_t isDRMProtected = 0;
+    sp<MetaData> meta = pReaderContext->mExtractor->getMetaData();
+    meta->findInt32(kKeyIsDRM, &isDRMProtected);
+    if (isDRMProtected) {
+        ALOGV("VideoEditorMp3Reader_open error - DRM Protected");
+        return M4ERR_UNSUPPORTED_MEDIA_TYPE;
+    }
+
+    ALOGV("VideoEditorMp3Reader_open end");
+    return err;
+}
+/**
+ **************************************************************************
+ * @brief    close the reader
+ * @note    this function closes the MP3 reader
+ * @param    context:        (IN)      Context of the reader
+ * @return    M4NO_ERROR               there is no error
+ * @return    M4ERR_PARAMETER          the context is NULL
+ **************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_close(M4OSA_Context context) {
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditorMp3Reader_close begin");
+    /* Check function parameters */
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
+            "VideoEditorMp3Reader_close: invalid context pointer");
+
+    if (pReaderContext->mAudioStreamHandler != NULL) {
+        if (M4OSA_NULL != pReaderContext->mAudioStreamHandler->\
+        m_basicProperties.m_pDecoderSpecificInfo) {
+            free(pReaderContext->mAudioStreamHandler->\
+                m_basicProperties.m_pDecoderSpecificInfo);
+            pReaderContext->mAudioStreamHandler->m_basicProperties.\
+                m_decoderSpecificInfoSize = 0;
+            pReaderContext->mAudioStreamHandler->m_basicProperties.\
+                m_pDecoderSpecificInfo = M4OSA_NULL;
+        }
+
+        /* Finally destroy the stream handler */
+        free(pReaderContext->mAudioStreamHandler);
+        pReaderContext->mAudioStreamHandler = M4OSA_NULL;
+
+        if (pReaderContext->mAudioAu.dataAddress != NULL) {
+            free(pReaderContext->mAudioAu.dataAddress);
+            pReaderContext->mAudioAu.dataAddress = NULL;
+        }
+    }
+
+    pReaderContext->mMediaSource->stop();
+    pReaderContext->mMediaSource.clear();
+    pReaderContext->mExtractor.clear();
+    pReaderContext->mDataSource.clear();
+
+    ALOGV("VideoEditorMp3Reader_close end ");
+    return err;
+}
+/**
+ ******************************************************************************
+ * @brief    get an option value from the reader
+ * @note
+ *          it allows the caller to retrieve a property value:
+ *
+ * @param    context:        (IN)    Context of the reader
+ * @param    optionId:       (IN)    indicates the option to get
+ * @param    pValue:         (OUT)   pointer to structure or value (allocated
+ *                                   by user) where option is stored
+ *
+ * @return    M4NO_ERROR             there is no error
+ * @return    M4ERR_PARAMETER        at least one parameter is not properly set
+ * @return    M4ERR_BAD_OPTION_ID    when the option ID is not a valid one
+ ******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_getOption(M4OSA_Context context,
+          M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditorMp3Reader_getOption begin: optionId= %d ",(int)optionId);
+
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
+        "invalid value pointer");
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
+        "invalid value pointer");
+
+    switch(optionId) {
+    case M4READER_kOptionID_Duration:
+        {
+            ALOGV("Mp3Reader duration=%ld",pReaderContext->mMaxDuration);
+            *(M4OSA_Time*)pValue = pReaderContext->mMaxDuration;
+        }
+        break;
+
+    case M4READER_kOptionID_Bitrate:
+        {
+            M4OSA_UInt32* pBitrate = (M4OSA_UInt32*)pValue;
+            if (M4OSA_NULL != pReaderContext->mAudioStreamHandler) {
+                *pBitrate = pReaderContext->mAudioStreamHandler->\
+                    m_basicProperties.m_averageBitRate;
+            } else {
+                pBitrate = 0;
+                err = M4ERR_PARAMETER;
+            }
+        }
+        break;
+
+    case M4READER_kOptionID_Mp3Id3v1Tag:
+        break;
+
+    case M4READER_kOptionID_Mp3Id3v2Tag:
+        break;
+
+    case M4READER_kOptionID_GetMetadata:
+        break;
+
+    default :
+        {
+            ALOGV("VideoEditorMp3Reader_getOption:  M4ERR_BAD_OPTION_ID");
+            err = M4ERR_BAD_OPTION_ID;
+        }
+    }
+    ALOGV("VideoEditorMp3Reader_getOption end ");
+    return err;
+}
+/**
+ ******************************************************************************
+ * @brief   set an option value of the reader
+ * @note
+ *          it allows the caller to set a property value:
+ *
+ * @param   context:    (IN)        Context of the reader
+ * @param   optionId:   (IN)        Identifier indicating the option to set
+ * @param   pValue:     (IN)        Pointer to structure or value (allocated
+ *                                  by user) where option is stored
+ *
+ * @return  M4NO_ERROR              There is no error
+ * @return  M4ERR_BAD_OPTION_ID     The option ID is not a valid one
+ * @return  M4ERR_STATE             State automaton is not applied
+ * @return  M4ERR_PARAMETER         The option parameter is invalid
+ ******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_setOption(M4OSA_Context context,
+        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditorMp3Reader_Context begin: optionId: %d Value: %d ",
+        (int)optionId,(int)pValue);
+
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pReaderContext), M4ERR_PARAMETER,
+        "invalid context pointer");
+    M4OSA_DEBUG_IF1((M4OSA_NULL == pValue), M4ERR_PARAMETER,
+        "invalid value pointer");
+
+    switch(optionId) {
+        case M4READER_kOptionID_SetOsaFileReaderFctsPtr:
+        default :
+        {
+            err = M4NO_ERROR;
+        }
+    }
+    ALOGV("VideoEditorMp3Reader_Context end ");
+    return err;
+}
+/**
+ ******************************************************************************
+ * @brief    jump into the stream at the specified time
+ * @note
+ * @param    context:      (IN)   Context of the reader
+ * @param    pStreamHandler(IN)   stream description of the stream to make jump
+ * @param    pTime         (I/O)IN:the time to jump to (in ms)
+ *                              OUT: the time to which the stream really jumped
+ * @return    M4NO_ERROR           there is no error
+ * @return    M4ERR_PARAMETER      at least one parameter is not properly set
+ ******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_jump(M4OSA_Context context,
+        M4_StreamHandler *pStreamHandler, M4OSA_Int32* pTime) {
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)context;
+    M4SYS_StreamID streamIdArray[2];
+    M4OSA_ERR err = M4NO_ERROR;
+    M4SYS_AccessUnit* pAu;
+    M4OSA_Time time64 = (M4OSA_Time)*pTime;
+
+    ALOGV("VideoEditorMp3Reader_jump begin");
+    M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_jump: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_jump: invalid pointer to M4_StreamHandler");
+    M4OSA_DEBUG_IF1((pTime == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_jump: invalid time pointer");
+
+    if(pStreamHandler == (M4_StreamHandler*)pReaderContext->\
+        mAudioStreamHandler){
+        pAu = &pReaderContext->mAudioAu;
+    } else {
+        ALOGV("VideoEditorMp3Reader_jump: passed StreamHandler is not known");
+        return M4ERR_PARAMETER;
+    }
+
+    streamIdArray[0] = pStreamHandler->m_streamId;
+    streamIdArray[1] = 0;
+
+    ALOGV("VideoEditorMp3Reader_jump time ms %ld ", time64);
+
+    pAu->CTS = time64;
+    pAu->DTS = time64;
+
+    time64 = time64 * 1000; /* Convert the time into micro sec */
+    ALOGV("VideoEditorMp3Reader_jump time us %ld ", time64);
+
+    pReaderContext->mSeeking = M4OSA_TRUE;
+    pReaderContext->mSeekTime = time64;
+
+    time64 = time64 / 1000; /* Convert the time into milli sec */
+    *pTime = (M4OSA_Int32)time64;
+    ALOGV("VideoEditorMp3Reader_jump end ");
+    return err;
+}
+/**
+ *******************************************************************************
+ * @brief   Get the next stream found in the media file
+ *
+ * @param    context:        (IN)  Context of the reader
+ * @param    pMediaFamily:   (OUT) pointer to a user allocated
+ *                                 M4READER_MediaFamily that will be filled with
+ *                                 the media family of the found stream
+ * @param    pStreamHandler: (OUT) pointer to a stream handler that will be
+ *                                 allocated and filled with stream description
+ *
+ * @return    M4NO_ERROR             there is no error
+ * @return    M4WAR_NO_MORE_STREAM   no more available stream in the media
+ * @return    M4ERR_PARAMETER        at least one parameter is not properly set
+ *******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_getNextStream(M4OSA_Context context,
+        M4READER_MediaFamily *pMediaFamily,
+        M4_StreamHandler **pStreamHandlerParam) {
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+    M4SYS_StreamID streamIdArray[2];
+    M4SYS_StreamDescription streamDesc;
+    M4_AudioStreamHandler* pAudioStreamHandler;
+    M4_StreamHandler* pStreamHandler;
+    M4OSA_UInt8 type, temp;
+    M4OSA_Bool haveAudio = M4OSA_FALSE;
+    sp<MetaData> meta = NULL;
+    int64_t Duration;
+
+    ALOGV("VideoEditorMp3Reader_getNextStream begin");
+    M4OSA_DEBUG_IF1((pReaderContext == 0),      M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_getNextStream: invalid context");
+    M4OSA_DEBUG_IF1((pMediaFamily == 0),        M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_getNextStream: invalid pointer to MediaFamily");
+    M4OSA_DEBUG_IF1((pStreamHandlerParam == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_getNextStream: invalid pointer to StreamHandler");
+
+    ALOGV("VideoEditorMp3Reader_getNextStream stream number = %d",
+        pReaderContext->mStreamNumber);
+    if (pReaderContext->mStreamNumber >= 1) {
+        ALOGV("VideoEditorMp3Reader_getNextStream max number of stream reached");
+        return M4WAR_NO_MORE_STREAM;
+    }
+    pReaderContext->mStreamNumber = pReaderContext->mStreamNumber + 1;
+    ALOGV("VideoEditorMp3Reader_getNextStream number of Tracks%d",
+        pReaderContext->mExtractor->countTracks());
+    for (temp = 0; temp < pReaderContext->mExtractor->countTracks(); temp++) {
+        meta = pReaderContext->mExtractor->getTrackMetaData(temp);
+        const char *mime;
+        CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+        if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
+            pReaderContext->mMediaSource =
+                pReaderContext->mExtractor->getTrack(temp);
+            pReaderContext->mMediaSource->start();
+            haveAudio = true;
+        }
+
+        if (haveAudio) {
+            break;
+        }
+    }
+
+    if (!haveAudio) {
+        ALOGV("VideoEditorMp3Reader_getNextStream no more stream ");
+        pReaderContext->mDataSource.clear();
+        return M4WAR_NO_MORE_STREAM;
+    }
+
+    pReaderContext->mExtractorFlags = pReaderContext->mExtractor->flags();
+    *pMediaFamily = M4READER_kMediaFamilyAudio;
+
+    streamDesc.duration = meta->findInt64(kKeyDuration, &Duration);
+    streamDesc.duration = (M4OSA_Time)Duration/1000;
+
+    meta->findInt32(kKeyBitRate, (int32_t*)&streamDesc.averageBitrate);
+    meta->findInt32(kKeySampleRate, (int32_t*)&streamDesc.timeScale);
+    ALOGV("Bitrate = %d, SampleRate = %d duration = %lld",
+        streamDesc.averageBitrate,streamDesc.timeScale,Duration/1000);
+
+    streamDesc.streamType = M4SYS_kMP3;
+    streamDesc.profileLevel = 0xFF ;
+    streamDesc.streamID = pReaderContext->mStreamNumber;
+    streamDesc.decoderSpecificInfo = M4OSA_NULL;
+    streamDesc.decoderSpecificInfoSize = 0;
+    streamDesc.maxBitrate = streamDesc.averageBitrate;
+
+    /*    Allocate the audio stream handler and set its parameters    */
+    pAudioStreamHandler = (M4_AudioStreamHandler*)M4OSA_32bitAlignedMalloc(
+        sizeof(M4_AudioStreamHandler), M4READER_MP3,
+        (M4OSA_Char*)"M4_AudioStreamHandler");
+
+    if (pAudioStreamHandler == M4OSA_NULL) {
+        ALOGV("VideoEditorMp3Reader_getNextStream malloc failed");
+        pReaderContext->mMediaSource->stop();
+        pReaderContext->mMediaSource.clear();
+        pReaderContext->mDataSource.clear();
+
+        return M4ERR_ALLOC;
+    }
+    pStreamHandler =(M4_StreamHandler*)(pAudioStreamHandler);
+    *pStreamHandlerParam = pStreamHandler;
+    pReaderContext->mAudioStreamHandler = pAudioStreamHandler;
+
+    pAudioStreamHandler->m_structSize = sizeof(M4_AudioStreamHandler);
+
+    if (meta == NULL) {
+        ALOGV("VideoEditorMp3Reader_getNextStream meta is NULL");
+    }
+
+    pAudioStreamHandler->m_samplingFrequency = streamDesc.timeScale;
+    pStreamHandler->m_pDecoderSpecificInfo =
+        (M4OSA_UInt8*)(streamDesc.decoderSpecificInfo);
+    pStreamHandler->m_decoderSpecificInfoSize =
+        streamDesc.decoderSpecificInfoSize;
+
+    meta->findInt32(kKeyChannelCount,
+        (int32_t*)&pAudioStreamHandler->m_nbChannels);
+    pAudioStreamHandler->m_byteFrameLength = 1152;
+    pAudioStreamHandler->m_byteSampleSize = 2;
+
+    pStreamHandler->m_pUserData = NULL;
+    pStreamHandler->m_streamId = streamDesc.streamID;
+    pStreamHandler->m_duration = streamDesc.duration;
+    pReaderContext->mMaxDuration = streamDesc.duration;
+    pStreamHandler->m_averageBitRate = streamDesc.averageBitrate;
+
+    pStreamHandler->m_maxAUSize = 0;
+    pStreamHandler->m_streamType = M4DA_StreamTypeAudioMp3;
+
+    ALOGV("VideoEditorMp3Reader_getNextStream end ");
+    return err;
+}
+
+/**
+ *******************************************************************************
+ * @brief    fill the access unit structure with initialization values
+ * @param    context:        (IN)     Context of the reader
+ * @param    pStreamHandler: (IN)     pointer to the stream handler to which
+ *                                    the access unit will be associated
+ * @param    pAccessUnit:    (IN/OUT) pointer to the access unit (allocated by
+ *                                    the caller) to initialize
+ * @return   M4NO_ERROR               there is no error
+ * @return   M4ERR_PARAMETER          at least one parameter is not properly set
+ *******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_fillAuStruct(M4OSA_Context context,
+        M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)context;
+    M4SYS_AccessUnit *pAu;
+
+    M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_fillAuStruct: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_fillAuStruct invalid pointer to StreamHandler");
+    M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_fillAuStruct: invalid pointer to M4_AccessUnit");
+
+    ALOGV("VideoEditorMp3Reader_fillAuStruct start ");
+    if(pStreamHandler == (M4_StreamHandler*)pReaderContext->\
+        mAudioStreamHandler){
+        pAu = &pReaderContext->mAudioAu;
+    } else {
+        ALOGV("VideoEditorMp3Reader_fillAuStruct StreamHandler is not known");
+        return M4ERR_PARAMETER;
+    }
+
+    /* Initialize pAu structure */
+    pAu->dataAddress = M4OSA_NULL;
+    pAu->size        = 0;
+    pAu->CTS         = 0;
+    pAu->DTS         = 0;
+    pAu->attribute   = 0;
+    pAu->nbFrag      = 0;
+
+    /* Initialize pAccessUnit structure */
+    pAccessUnit->m_size         = 0;
+    pAccessUnit->m_CTS          = 0;
+    pAccessUnit->m_DTS          = 0;
+    pAccessUnit->m_attribute    = 0;
+    pAccessUnit->m_dataAddress  = M4OSA_NULL;
+    pAccessUnit->m_maxsize      = pStreamHandler->m_maxAUSize;
+    pAccessUnit->m_streamID     = pStreamHandler->m_streamId;
+    pAccessUnit->m_structSize   = sizeof(M4_AccessUnit);
+
+    ALOGV("VideoEditorMp3Reader_fillAuStruct end");
+    return M4NO_ERROR;
+}
+
+/**
+ *******************************************************************************
+ * @brief    reset the stream, i.e seek it to the beginning
+ * @note
+ * @param     context:          (IN)  Context of the reader
+ * @param     pStreamHandler    (IN)  The stream handler of the stream to reset
+ * @return    M4NO_ERROR              there is no error
+ * @return    M4ERR_PARAMETER         at least one parameter is not properly set
+ *******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_reset(M4OSA_Context context,
+        M4_StreamHandler *pStreamHandler) {
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)context;
+
+    M4OSA_ERR err = M4NO_ERROR;
+    M4SYS_StreamID streamIdArray[2];
+    M4SYS_AccessUnit* pAu;
+    M4OSA_Time time64 = 0;
+
+    ALOGV("VideoEditorMp3Reader_reset start");
+    M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_reset: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_reset: invalid pointer to M4_StreamHandler");
+
+    if (pStreamHandler == (M4_StreamHandler*)pReaderContext->\
+        mAudioStreamHandler) {
+        pAu = &pReaderContext->mAudioAu;
+    } else {
+        ALOGV("VideoEditorMp3Reader_reset StreamHandler is not known");
+        return M4ERR_PARAMETER;
+    }
+    streamIdArray[0] = pStreamHandler->m_streamId;
+    streamIdArray[1] = 0;
+    pAu->CTS = time64;
+    pAu->DTS = time64;
+
+    pReaderContext->mSeeking = M4OSA_TRUE;
+    pReaderContext->mSeekTime = time64;
+
+    ALOGV("VideoEditorMp3Reader_reset end");
+    return err;
+}
+/**
+ *******************************************************************************
+ * @brief   Gets an access unit (AU) from the stream handler source.
+ * @note    AU is the smallest possible amount of data to be decoded by decoder
+ *
+ * @param   context:       (IN) Context of the reader
+ * @param   pStreamHandler (IN) The stream handler of the stream to make jump
+ * @param   pAccessUnit    (I/O)Pointer to an access unit to fill with read data
+ * @return    M4NO_ERROR        there is no error
+ * @return    M4ERR_PARAMETER   at least one parameter is not properly set
+ * @returns   M4ERR_ALLOC       memory allocation failed
+ * @returns   M4WAR_NO_MORE_AU  there are no more access unit in the stream
+ *******************************************************************************
+*/
+M4OSA_ERR VideoEditorMp3Reader_getNextAu(M4OSA_Context context,
+        M4_StreamHandler *pStreamHandler, M4_AccessUnit *pAccessUnit) {
+    VideoEditorMp3Reader_Context *pReaderContext =
+        (VideoEditorMp3Reader_Context*)context;
+    M4OSA_ERR err = M4NO_ERROR;
+    M4SYS_AccessUnit* pAu;
+    MediaBuffer *mAudioBuffer;
+    MediaSource::ReadOptions options;
+
+    ALOGV("VideoEditorMp3Reader_getNextAu start");
+    M4OSA_DEBUG_IF1((pReaderContext == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_getNextAu: invalid context");
+    M4OSA_DEBUG_IF1((pStreamHandler == 0), M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_getNextAu: invalid pointer to M4_StreamHandler");
+    M4OSA_DEBUG_IF1((pAccessUnit == 0),    M4ERR_PARAMETER,
+        "VideoEditorMp3Reader_getNextAu: invalid pointer to M4_AccessUnit");
+
+    if (pStreamHandler == (M4_StreamHandler*)pReaderContext->\
+        mAudioStreamHandler) {
+        pAu = &pReaderContext->mAudioAu;
+    } else {
+        ALOGV("VideoEditorMp3Reader_getNextAu: StreamHandler is not known\n");
+        return M4ERR_PARAMETER;
+    }
+
+    if (pReaderContext->mSeeking) {
+        options.setSeekTo(pReaderContext->mSeekTime);
+    }
+
+    pReaderContext->mMediaSource->read(&mAudioBuffer, &options);
+
+    if (mAudioBuffer != NULL) {
+        if ((pAu->dataAddress == NULL) ||
+            (pAu->size < mAudioBuffer->range_length())) {
+            if (pAu->dataAddress != NULL) {
+                free((M4OSA_Int32*)pAu->dataAddress);
+                pAu->dataAddress = NULL;
+            }
+            pAu->dataAddress = (M4OSA_Int32*)M4OSA_32bitAlignedMalloc(
+                (mAudioBuffer->range_length() + 3) & ~0x3,
+                M4READER_MP3, (M4OSA_Char*)"pAccessUnit->m_dataAddress" );
+
+            if (pAu->dataAddress == NULL) {
+                ALOGV("VideoEditorMp3Reader_getNextAu malloc failed");
+                pReaderContext->mMediaSource->stop();
+                pReaderContext->mMediaSource.clear();
+                pReaderContext->mDataSource.clear();
+
+                return M4ERR_ALLOC;
+            }
+        }
+        pAu->size = mAudioBuffer->range_length();
+        memcpy((M4OSA_MemAddr8)pAu->dataAddress,
+            (const char *)mAudioBuffer->data() + mAudioBuffer->range_offset(),
+            mAudioBuffer->range_length());
+
+        mAudioBuffer->meta_data()->findInt64(kKeyTime, (int64_t*)&pAu->CTS);
+
+
+        pAu->CTS = pAu->CTS / 1000; /*converting the microsec to millisec */
+        pAu->DTS  = pAu->CTS;
+        pAu->attribute = M4SYS_kFragAttrOk;
+        mAudioBuffer->release();
+
+        ALOGV("VideoEditorMp3Reader_getNextAu AU CTS = %ld",pAu->CTS);
+
+        pAccessUnit->m_dataAddress = (M4OSA_Int8*) pAu->dataAddress;
+        pAccessUnit->m_size = pAu->size;
+        pAccessUnit->m_CTS = pAu->CTS;
+        pAccessUnit->m_DTS = pAu->DTS;
+        pAccessUnit->m_attribute = pAu->attribute;
+    } else {
+        ALOGV("VideoEditorMp3Reader_getNextAu EOS reached.");
+        pAccessUnit->m_size=0;
+        err = M4WAR_NO_MORE_AU;
+    }
+    pAu->nbFrag = 0;
+
+    options.clearSeekTo();
+    pReaderContext->mSeeking = M4OSA_FALSE;
+    mAudioBuffer = NULL;
+    ALOGV("VideoEditorMp3Reader_getNextAu end");
+
+    return err;
+}
+
+extern "C" {
+
+M4OSA_ERR VideoEditorMp3Reader_getInterface(
+        M4READER_MediaType *pMediaType,
+        M4READER_GlobalInterface **pRdrGlobalInterface,
+        M4READER_DataInterface **pRdrDataInterface) {
+    M4OSA_ERR err = M4NO_ERROR;
+
+    ALOGV("VideoEditorMp3Reader_getInterface: begin");
+    /* Input parameters check */
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pMediaType,      M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrGlobalInterface, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pRdrDataInterface, M4ERR_PARAMETER);
+
+    SAFE_MALLOC(*pRdrGlobalInterface, M4READER_GlobalInterface, 1,
+        "VideoEditorMp3Reader_getInterface");
+    SAFE_MALLOC(*pRdrDataInterface, M4READER_DataInterface, 1,
+        "VideoEditorMp3Reader_getInterface");
+
+    *pMediaType = M4READER_kMediaTypeMP3;
+
+    (*pRdrGlobalInterface)->m_pFctCreate       = VideoEditorMp3Reader_create;
+    (*pRdrGlobalInterface)->m_pFctDestroy      = VideoEditorMp3Reader_destroy;
+    (*pRdrGlobalInterface)->m_pFctOpen         = VideoEditorMp3Reader_open;
+    (*pRdrGlobalInterface)->m_pFctClose        = VideoEditorMp3Reader_close;
+    (*pRdrGlobalInterface)->m_pFctGetOption    = VideoEditorMp3Reader_getOption;
+    (*pRdrGlobalInterface)->m_pFctSetOption    = VideoEditorMp3Reader_setOption;
+    (*pRdrGlobalInterface)->m_pFctGetNextStream =
+        VideoEditorMp3Reader_getNextStream;
+    (*pRdrGlobalInterface)->m_pFctFillAuStruct =
+        VideoEditorMp3Reader_fillAuStruct;
+    (*pRdrGlobalInterface)->m_pFctStart        = M4OSA_NULL;
+    (*pRdrGlobalInterface)->m_pFctStop         = M4OSA_NULL;
+    (*pRdrGlobalInterface)->m_pFctJump         = VideoEditorMp3Reader_jump;
+    (*pRdrGlobalInterface)->m_pFctReset        = VideoEditorMp3Reader_reset;
+    (*pRdrGlobalInterface)->m_pFctGetPrevRapTime = M4OSA_NULL;
+
+    (*pRdrDataInterface)->m_pFctGetNextAu      = VideoEditorMp3Reader_getNextAu;
+    (*pRdrDataInterface)->m_readerContext      = M4OSA_NULL;
+
+cleanUp:
+    if( M4NO_ERROR == err )
+    {
+        ALOGV("VideoEditorMp3Reader_getInterface no error");
+    }
+    else
+    {
+        SAFE_FREE(*pRdrGlobalInterface);
+        SAFE_FREE(*pRdrDataInterface);
+
+        ALOGV("VideoEditorMp3Reader_getInterface ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorMp3Reader_getInterface: end");
+    return err;
+}
+}  /* extern "C" */
+}  /* namespace android */
diff --git a/frameworks/videoedit/stagefrightshells/VideoEditorVideoDecoder.cpp b/frameworks/videoedit/stagefrightshells/VideoEditorVideoDecoder.cpp
new file mode 100644
index 0000000..21d3c30
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/VideoEditorVideoDecoder.cpp
@@ -0,0 +1,1778 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+*************************************************************************
+* @file   VideoEditorVideoDecoder.cpp
+* @brief  StageFright shell video decoder
+*************************************************************************
+*/
+#define LOG_NDEBUG 1
+#define LOG_TAG "VIDEOEDITOR_VIDEODECODER"
+/*******************
+ *     HEADERS     *
+ *******************/
+
+#include "VideoEditorVideoDecoder_internal.h"
+#include "VideoEditorUtils.h"
+#include "M4VD_Tools.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MediaDefs.h>
+/********************
+ *   DEFINITIONS    *
+ ********************/
+#define MAX_DEC_BUFFERS 10
+
+/********************
+ *   SOURCE CLASS   *
+ ********************/
+using namespace android;
+static M4OSA_ERR copyBufferToQueue(
+    VideoEditorVideoDecoder_Context* pDecShellContext,
+    MediaBuffer* pDecodedBuffer);
+
+class VideoEditorVideoDecoderSource : public MediaSource {
+    public:
+
+        VideoEditorVideoDecoderSource(
+            const sp<MetaData> &format,
+            VIDEOEDITOR_CodecType codecType,
+            void *decoderShellContext);
+
+        virtual status_t start(MetaData *params = NULL);
+        virtual status_t stop();
+        virtual sp<MetaData> getFormat();
+        virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+    protected :
+        virtual ~VideoEditorVideoDecoderSource();
+
+    private:
+        sp<MetaData> mFormat;
+        MediaBuffer* mBuffer;
+        MediaBufferGroup* mGroup;
+        Mutex mLock;
+        VideoEditorVideoDecoder_Context* mpDecShellContext;
+        int32_t mMaxAUSize;
+        bool mStarted;
+        VIDEOEDITOR_CodecType mCodecType;
+
+        // Don't call me
+        VideoEditorVideoDecoderSource(const VideoEditorVideoDecoderSource &);
+        VideoEditorVideoDecoderSource &operator=(
+            const VideoEditorVideoDecoderSource &);
+};
+
+VideoEditorVideoDecoderSource::VideoEditorVideoDecoderSource(
+        const sp<MetaData> &format, VIDEOEDITOR_CodecType codecType,
+        void *decoderShellContext) :
+        mFormat(format),
+        mBuffer(NULL),
+        mGroup(NULL),
+        mStarted(false),
+        mCodecType(codecType) {
+    mpDecShellContext = (VideoEditorVideoDecoder_Context*) decoderShellContext;
+}
+
+VideoEditorVideoDecoderSource::~VideoEditorVideoDecoderSource() {
+    if (mStarted == true) {
+        stop();
+    }
+}
+
+status_t VideoEditorVideoDecoderSource::start(
+        MetaData *params) {
+
+    if (!mStarted) {
+        if (mFormat->findInt32(kKeyMaxInputSize, &mMaxAUSize) == false) {
+            ALOGE("Could not find kKeyMaxInputSize");
+            return ERROR_MALFORMED;
+        }
+
+        mGroup = new MediaBufferGroup;
+        if (mGroup == NULL) {
+            ALOGE("FATAL: memory limitation ! ");
+            return NO_MEMORY;
+        }
+
+        mGroup->add_buffer(new MediaBuffer(mMaxAUSize));
+
+        mStarted = true;
+    }
+    return OK;
+}
+
+status_t VideoEditorVideoDecoderSource::stop() {
+    if (mStarted) {
+        if (mBuffer != NULL) {
+
+            // FIXME:
+            // Why do we need to check on the ref count?
+            int ref_count = mBuffer->refcount();
+            ALOGV("MediaBuffer refcount is %d",ref_count);
+            for (int i = 0; i < ref_count; ++i) {
+                mBuffer->release();
+            }
+
+            mBuffer = NULL;
+        }
+        delete mGroup;
+        mGroup = NULL;
+        mStarted = false;
+    }
+    return OK;
+}
+
+sp<MetaData> VideoEditorVideoDecoderSource::getFormat() {
+    Mutex::Autolock autolock(mLock);
+
+    return mFormat;
+}
+
+status_t VideoEditorVideoDecoderSource::read(MediaBuffer** buffer_out,
+        const ReadOptions *options) {
+
+    Mutex::Autolock autolock(mLock);
+    if (options != NULL) {
+        int64_t time_us;
+        MediaSource::ReadOptions::SeekMode mode;
+        options->getSeekTo(&time_us, &mode);
+        if (mode != MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC) {
+            ALOGE("Unexpected read options");
+            return BAD_VALUE;
+        }
+
+        M4OSA_ERR err;
+        M4OSA_Int32 rapTime = time_us / 1000;
+
+        /*--- Retrieve the previous RAP time ---*/
+        err = mpDecShellContext->m_pReaderGlobal->m_pFctGetPrevRapTime(
+                  mpDecShellContext->m_pReader->m_readerContext,
+                  (M4_StreamHandler*)mpDecShellContext->m_pVideoStreamhandler,
+                  &rapTime);
+
+        if (err == M4WAR_READER_INFORMATION_NOT_PRESENT) {
+            /* No RAP table, jump backward and predecode */
+            rapTime -= 40000;
+            if(rapTime < 0) rapTime = 0;
+        } else if (err != OK) {
+            ALOGE("get rap time error = 0x%x\n", (uint32_t)err);
+            return UNKNOWN_ERROR;
+        }
+
+        err = mpDecShellContext->m_pReaderGlobal->m_pFctJump(
+                   mpDecShellContext->m_pReader->m_readerContext,
+                   (M4_StreamHandler*)mpDecShellContext->m_pVideoStreamhandler,
+                   &rapTime);
+
+        if (err != OK) {
+            ALOGE("jump err = 0x%x\n", (uint32_t)err);
+            return BAD_VALUE;
+        }
+    }
+
+    *buffer_out = NULL;
+
+    M4OSA_ERR lerr = mGroup->acquire_buffer(&mBuffer);
+    if (lerr != OK) {
+        return lerr;
+    }
+    mBuffer->meta_data()->clear();  // clear all the meta data
+
+    if (mStarted) {
+        //getNext AU from reader.
+        M4_AccessUnit* pAccessUnit = mpDecShellContext->m_pNextAccessUnitToDecode;
+        lerr = mpDecShellContext->m_pReader->m_pFctGetNextAu(
+                   mpDecShellContext->m_pReader->m_readerContext,
+                   (M4_StreamHandler*)mpDecShellContext->m_pVideoStreamhandler,
+                   pAccessUnit);
+        if (lerr == M4WAR_NO_DATA_YET || lerr == M4WAR_NO_MORE_AU) {
+            *buffer_out = NULL;
+            return ERROR_END_OF_STREAM;
+        }
+
+        //copy the reader AU buffer to mBuffer
+        M4OSA_UInt32 lSize  = (pAccessUnit->m_size > (M4OSA_UInt32)mMaxAUSize)\
+            ? (M4OSA_UInt32)mMaxAUSize : pAccessUnit->m_size;
+        memcpy((void *)mBuffer->data(),(void *)pAccessUnit->m_dataAddress,
+            lSize);
+
+        mBuffer->set_range(0, lSize);
+        int64_t frameTimeUs = (int64_t) (pAccessUnit->m_CTS * 1000);
+        mBuffer->meta_data()->setInt64(kKeyTime, frameTimeUs);
+
+        // Replace the AU start code for H264
+        if (VIDEOEDITOR_kH264VideoDec == mCodecType) {
+            uint8_t *data =(uint8_t *)mBuffer->data() + mBuffer->range_offset();
+            data[0]=0;
+            data[1]=0;
+            data[2]=0;
+            data[3]=1;
+        }
+        mBuffer->meta_data()->setInt32(kKeyIsSyncFrame,
+            (pAccessUnit->m_attribute == 0x04)? 1 : 0);
+        *buffer_out = mBuffer;
+    }
+    return OK;
+}
+
+static M4OSA_UInt32 VideoEditorVideoDecoder_GetBitsFromMemory(
+        VIDEOEDITOR_VIDEO_Bitstream_ctxt* parsingCtxt, M4OSA_UInt32 nb_bits) {
+    return (M4VD_Tools_GetBitsFromMemory((M4VS_Bitstream_ctxt*) parsingCtxt,
+            nb_bits));
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_internalParseVideoDSI(M4OSA_UInt8* pVol,
+        M4OSA_Int32 aVolSize, M4DECODER_MPEG4_DecoderConfigInfo* pDci,
+        M4DECODER_VideoSize* pVideoSize) {
+
+    VIDEOEDITOR_VIDEO_Bitstream_ctxt parsingCtxt;
+    M4OSA_UInt32 code, j;
+    M4OSA_MemAddr8 start;
+    M4OSA_UInt8 i;
+    M4OSA_UInt32 time_incr_length;
+    M4OSA_UInt8 vol_verid=0, b_hierarchy_type;
+
+    /* Parsing variables */
+    M4OSA_UInt8 video_object_layer_shape = 0;
+    M4OSA_UInt8 sprite_enable = 0;
+    M4OSA_UInt8 reduced_resolution_vop_enable = 0;
+    M4OSA_UInt8 scalability = 0;
+    M4OSA_UInt8 enhancement_type = 0;
+    M4OSA_UInt8 complexity_estimation_disable = 0;
+    M4OSA_UInt8 interlaced = 0;
+    M4OSA_UInt8 sprite_warping_points = 0;
+    M4OSA_UInt8 sprite_brightness_change = 0;
+    M4OSA_UInt8 quant_precision = 0;
+
+    /* Fill the structure with default parameters */
+    pVideoSize->m_uiWidth      = 0;
+    pVideoSize->m_uiHeight     = 0;
+
+    pDci->uiTimeScale          = 0;
+    pDci->uiProfile            = 0;
+    pDci->uiUseOfResynchMarker = 0;
+    pDci->bDataPartition       = M4OSA_FALSE;
+    pDci->bUseOfRVLC           = M4OSA_FALSE;
+
+    /* Reset the bitstream context */
+    parsingCtxt.stream_byte = 0;
+    parsingCtxt.stream_index = 8;
+    parsingCtxt.in = (M4OSA_MemAddr8) pVol;
+
+    start = (M4OSA_MemAddr8) pVol;
+
+    /* Start parsing */
+    while (parsingCtxt.in - start < aVolSize) {
+        code = VideoEditorVideoDecoder_GetBitsFromMemory(&parsingCtxt, 8);
+        if (code == 0) {
+            code = VideoEditorVideoDecoder_GetBitsFromMemory(&parsingCtxt, 8);
+            if (code == 0) {
+                code = VideoEditorVideoDecoder_GetBitsFromMemory(&parsingCtxt,8);
+                if (code == 1) {
+                    /* start code found */
+                    code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                        &parsingCtxt, 8);
+
+                    /* ----- 0x20..0x2F : video_object_layer_start_code ----- */
+
+                    if ((code > 0x1F) && (code < 0x30)) {
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 8);
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);
+                        if (code == 1) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 4);
+                            vol_verid = (M4OSA_UInt8)code;
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 3);
+                        }
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 4);
+                        if (code == 15) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 16);
+                        }
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);
+                        if (code == 1) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 3);
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);
+                            if (code == 1) {
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 32);
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 31);
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 16);
+                            }
+                        }
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 2);
+                        /* Need to save it for vop parsing */
+                        video_object_layer_shape = (M4OSA_UInt8)code;
+
+                        if (code != 0) {
+                            return 0;    /* only rectangular case supported */
+                        }
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 16);
+                        pDci->uiTimeScale = code;
+
+                        /* Computes time increment length */
+                        j    = code - 1;
+                        for (i = 0; (i < 32) && (j != 0); j >>=1) {
+                            i++;
+                        }
+                        time_incr_length = (i == 0) ? 1 : i;
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);
+                        if (code == 1) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, time_incr_length);
+                        }
+
+                        if(video_object_layer_shape != 1) { /* 1 = Binary */
+                            if(video_object_layer_shape == 0) {
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* Marker bit */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 13);/* Width */
+                                pVideoSize->m_uiWidth = code;
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* Marker bit */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 13);/* Height */
+                                pVideoSize->m_uiHeight = code;
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* Marker bit */
+                            }
+                        }
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* interlaced */
+                        interlaced = (M4OSA_UInt8)code;
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* OBMC disable */
+
+                        if(vol_verid == 1) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* sprite enable */
+                            sprite_enable = (M4OSA_UInt8)code;
+                        } else {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 2);/* sprite enable */
+                            sprite_enable = (M4OSA_UInt8)code;
+                        }
+                        if ((sprite_enable == 1) || (sprite_enable == 2)) {
+                            if (sprite_enable != 2) {
+
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 13);/* sprite width */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* Marker bit */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 13);/* sprite height */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* Marker bit */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 13);/* sprite l coordinate */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* Marker bit */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 13);/* sprite top coordinate */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* Marker bit */
+                            }
+
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 6);/* sprite warping points */
+                            sprite_warping_points = (M4OSA_UInt8)code;
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 2);/* sprite warping accuracy */
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* sprite brightness change */
+                            sprite_brightness_change = (M4OSA_UInt8)code;
+                            if (sprite_enable != 2) {
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);
+                            }
+                        }
+                        if ((vol_verid != 1) && (video_object_layer_shape != 0)){
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* sadct disable */
+                        }
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1); /* not 8 bits */
+                        if (code) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 4);/* quant precision */
+                            quant_precision = (M4OSA_UInt8)code;
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 4);/* bits per pixel */
+                        }
+
+                        /* greyscale not supported */
+                        if(video_object_layer_shape == 3) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 3);
+                        }
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* quant type */
+                        if (code) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* load intra quant mat */
+                            if (code) {
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 8);/* */
+                                i    = 1;
+                                while (i < 64) {
+                                    code =
+                                        VideoEditorVideoDecoder_GetBitsFromMemory(
+                                            &parsingCtxt, 8);
+                                    if (code == 0) {
+                                        break;
+                                    }
+                                    i++;
+                                }
+                            }
+
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* load non intra quant mat */
+                            if (code) {
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 8);/* */
+                                i    = 1;
+                                while (i < 64) {
+                                    code =
+                                        VideoEditorVideoDecoder_GetBitsFromMemory(
+                                        &parsingCtxt, 8);
+                                    if (code == 0) {
+                                        break;
+                                    }
+                                    i++;
+                                }
+                            }
+                        }
+
+                        if (vol_verid != 1) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* quarter sample */
+                        }
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* complexity estimation disable */
+                        complexity_estimation_disable = (M4OSA_UInt8)code;
+                        if (!code) {
+                            //return M4ERR_NOT_IMPLEMENTED;
+                        }
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* resync marker disable */
+                        pDci->uiUseOfResynchMarker = (code) ? 0 : 1;
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* data partitionned */
+                        pDci->bDataPartition = (code) ? M4OSA_TRUE : M4OSA_FALSE;
+                        if (code) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* reversible VLC */
+                            pDci->bUseOfRVLC = (code) ? M4OSA_TRUE : M4OSA_FALSE;
+                        }
+
+                        if (vol_verid != 1) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* newpred */
+                            if (code) {
+                                //return M4ERR_PARAMETER;
+                            }
+
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);
+                            reduced_resolution_vop_enable = (M4OSA_UInt8)code;
+                        }
+
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* scalability */
+                        scalability = (M4OSA_UInt8)code;
+                        if (code) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* hierarchy type */
+                            b_hierarchy_type = (M4OSA_UInt8)code;
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 4);/* ref layer id */
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* ref sampling direct */
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 5);/* hor sampling factor N */
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 5);/* hor sampling factor M */
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 5);/* vert sampling factor N */
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 5);/* vert sampling factor M */
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 1);/* enhancement type */
+                            enhancement_type = (M4OSA_UInt8)code;
+                            if ((!b_hierarchy_type) &&
+                                    (video_object_layer_shape == 1)) {
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* use ref shape */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 1);/* use ref texture */
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 5);
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 5);
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 5);
+                                code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                    &parsingCtxt, 5);
+                            }
+                        }
+                        break;
+                    }
+
+                    /* ----- 0xB0 : visual_object_sequence_start_code ----- */
+
+                    else if(code == 0xB0) {
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 8);/* profile_and_level_indication */
+                        pDci->uiProfile = (M4OSA_UInt8)code;
+                    }
+
+                    /* ----- 0xB5 : visual_object_start_code ----- */
+
+                    else if(code == 0xB5) {
+                        code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                            &parsingCtxt, 1);/* is object layer identifier */
+                        if (code == 1) {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 4); /* visual object verid */
+                            vol_verid = (M4OSA_UInt8)code;
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 3);
+                        } else {
+                            code = VideoEditorVideoDecoder_GetBitsFromMemory(
+                                &parsingCtxt, 7); /* Realign on byte */
+                            vol_verid = 1;
+                        }
+                    }
+
+                    /* ----- end ----- */
+                } else {
+                    if ((code >> 2) == 0x20) {
+                        /* H263 ...-> wrong*/
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    return M4NO_ERROR;
+}
+
+M4VIFI_UInt8 M4VIFI_SemiplanarYVU420toYUV420(void *user_data,
+        M4VIFI_UInt8 *inyuv, M4VIFI_ImagePlane *PlaneOut ) {
+    M4VIFI_UInt8 return_code = M4VIFI_OK;
+    M4VIFI_UInt8 *outyuv =
+        ((M4VIFI_UInt8*)&(PlaneOut[0].pac_data[PlaneOut[0].u_topleft]));
+    int32_t width = PlaneOut[0].u_width;
+    int32_t height = PlaneOut[0].u_height;
+
+    int32_t outYsize = width * height;
+    uint32_t *outy =  (uint32_t *) outyuv;
+    uint16_t *outcb =
+        (uint16_t *) &(PlaneOut[1].pac_data[PlaneOut[1].u_topleft]);
+    uint16_t *outcr =
+        (uint16_t *) &(PlaneOut[2].pac_data[PlaneOut[2].u_topleft]);
+
+    /* Y copying */
+    memcpy((void *)outy, (void *)inyuv, outYsize);
+
+    /* U & V copying */
+    uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
+    for (int32_t i = height >> 1; i > 0; --i) {
+        for (int32_t j = width >> 2; j > 0; --j) {
+            uint32_t temp = *inyuv_4++;
+            uint32_t tempU = temp & 0xFF;
+            tempU = tempU | ((temp >> 8) & 0xFF00);
+
+            uint32_t tempV = (temp >> 8) & 0xFF;
+            tempV = tempV | ((temp >> 16) & 0xFF00);
+
+            // Flip U and V
+            *outcb++ = tempV;
+            *outcr++ = tempU;
+        }
+    }
+    return return_code;
+}
+void logSupportDecodersAndCapabilities(M4DECODER_VideoDecoders* decoders) {
+    VideoDecoder *pDecoder;
+    VideoComponentCapabilities *pOmxComponents = NULL;
+    VideoProfileLevel *pProfileLevel = NULL;
+    pDecoder = decoders->decoder;
+    for (size_t i = 0; i< decoders->decoderNumber; i++) {
+        ALOGV("Supported Codec[%d] :%d", i, pDecoder->codec);
+        pOmxComponents = pDecoder->component;
+        for(size_t j = 0; j <  pDecoder->componentNumber; j++) {
+           pProfileLevel = pOmxComponents->profileLevel;
+           ALOGV("-->component %d", j);
+           for(size_t k = 0; k < pOmxComponents->profileNumber; k++) {
+               ALOGV("-->profile:%ld maxLevel:%ld", pProfileLevel->mProfile,
+                   pProfileLevel->mLevel);
+               pProfileLevel++;
+           }
+           pOmxComponents++;
+        }
+        pDecoder++;
+    }
+}
+
+M4OSA_ERR queryVideoDecoderCapabilities
+    (M4DECODER_VideoDecoders** decoders) {
+    M4OSA_ERR err = M4NO_ERROR;
+    const char *kMimeTypes[] = {
+        MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_MPEG4,
+        MEDIA_MIMETYPE_VIDEO_H263
+    };
+
+    int32_t supportFormats = sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
+    M4DECODER_VideoDecoders *pDecoders;
+    VideoDecoder *pDecoder;
+    VideoComponentCapabilities *pOmxComponents = NULL;
+    VideoProfileLevel *pProfileLevel = NULL;
+    OMXClient client;
+    status_t status = OK;
+    SAFE_MALLOC(pDecoders, M4DECODER_VideoDecoders, 1, "VideoDecoders");
+    SAFE_MALLOC(pDecoder, VideoDecoder, supportFormats,
+        "VideoDecoder");
+    pDecoders->decoder = pDecoder;
+
+    pDecoders->decoderNumber= supportFormats;
+    status = client.connect();
+    CHECK(status == OK);
+    for (size_t k = 0; k < sizeof(kMimeTypes) / sizeof(kMimeTypes[0]);
+             ++k) {
+            Vector<CodecCapabilities> results;
+            CHECK_EQ(QueryCodecs(client.interface(), kMimeTypes[k],
+                                 true, // queryDecoders
+                                 &results), (status_t)OK);
+
+            if (results.size()) {
+                SAFE_MALLOC(pOmxComponents, VideoComponentCapabilities,
+                    results.size(), "VideoComponentCapabilities");
+                ALOGV("K=%d",k);
+                pDecoder->component = pOmxComponents;
+                pDecoder->componentNumber = results.size();
+            }
+
+            for (size_t i = 0; i < results.size(); ++i) {
+                ALOGV("  decoder '%s' supports ",
+                       results[i].mComponentName.string());
+
+                if (results[i].mProfileLevels.size() == 0) {
+                    ALOGV("NOTHING.\n");
+                    continue;
+                }
+
+#if 0
+                // FIXME:
+                // We should ignore the software codecs and make IsSoftwareCodec()
+                // part of pubic API from OMXCodec.cpp
+                if (IsSoftwareCodec(results[i].mComponentName.string())) {
+                    ALOGV("Ignore software codec %s", results[i].mComponentName.string());
+                    continue;
+                }
+#endif
+
+                // Count the supported profiles
+                int32_t profileNumber = 0;
+                int32_t profile = -1;
+                for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
+                    const CodecProfileLevel &profileLevel =
+                        results[i].mProfileLevels[j];
+                    // FIXME: assume that the profiles are ordered
+                    if (profileLevel.mProfile != profile) {
+                        profile = profileLevel.mProfile;
+                        profileNumber++;
+                    }
+                }
+                SAFE_MALLOC(pProfileLevel, VideoProfileLevel,
+                    profileNumber, "VideoProfileLevel");
+                pOmxComponents->profileLevel = pProfileLevel;
+                pOmxComponents->profileNumber = profileNumber;
+
+                // Get the max Level for each profile.
+                int32_t maxLevel = -1;
+                profile = -1;
+                profileNumber = 0;
+                for (size_t j = 0; j < results[i].mProfileLevels.size(); ++j) {
+                    const CodecProfileLevel &profileLevel =
+                        results[i].mProfileLevels[j];
+                    if (profile == -1 && maxLevel == -1) {
+                        profile = profileLevel.mProfile;
+                        maxLevel = profileLevel.mLevel;
+                        pProfileLevel->mProfile = profile;
+                        pProfileLevel->mLevel = maxLevel;
+                        ALOGV("%d profile: %ld, max level: %ld",
+                            __LINE__, pProfileLevel->mProfile, pProfileLevel->mLevel);
+                    }
+                    if (profileLevel.mProfile != profile) {
+                        profile = profileLevel.mProfile;
+                        maxLevel = profileLevel.mLevel;
+                        profileNumber++;
+                        pProfileLevel++;
+                        pProfileLevel->mProfile = profile;
+                        pProfileLevel->mLevel = maxLevel;
+                        ALOGV("%d profile: %ld, max level: %ld",
+                            __LINE__, pProfileLevel->mProfile, pProfileLevel->mLevel);
+                    } else if (profileLevel.mLevel > maxLevel) {
+                        maxLevel = profileLevel.mLevel;
+                        pProfileLevel->mLevel = maxLevel;
+                        ALOGV("%d profile: %ld, max level: %ld",
+                            __LINE__, pProfileLevel->mProfile, pProfileLevel->mLevel);
+                    }
+
+                }
+                pOmxComponents++;
+            }
+            if (!strcmp(MEDIA_MIMETYPE_VIDEO_AVC, kMimeTypes[k]))
+                pDecoder->codec = M4DA_StreamTypeVideoMpeg4Avc;
+            if (!strcmp(MEDIA_MIMETYPE_VIDEO_MPEG4, kMimeTypes[k]))
+                pDecoder->codec = M4DA_StreamTypeVideoMpeg4;
+            if (!strcmp(MEDIA_MIMETYPE_VIDEO_H263, kMimeTypes[k]))
+                pDecoder->codec = M4DA_StreamTypeVideoH263;
+
+            pDecoder++;
+    }
+
+    logSupportDecodersAndCapabilities(pDecoders);
+    *decoders = pDecoders;
+cleanUp:
+    return err;
+}
+/********************
+ * ENGINE INTERFACE *
+ ********************/
+M4OSA_ERR VideoEditorVideoDecoder_configureFromMetadata(M4OSA_Context pContext,
+        MetaData* meta) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoDecoder_Context* pDecShellContext = M4OSA_NULL;
+    bool success = OK;
+    int32_t width = 0;
+    int32_t height = 0;
+    int32_t frameSize = 0;
+    int32_t vWidth, vHeight;
+    int32_t cropLeft, cropTop, cropRight, cropBottom;
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != meta,     M4ERR_PARAMETER);
+
+    ALOGV("VideoEditorVideoDecoder_configureFromMetadata begin");
+
+    pDecShellContext = (VideoEditorVideoDecoder_Context*)pContext;
+
+    success = meta->findInt32(kKeyWidth, &vWidth);
+    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
+    success = meta->findInt32(kKeyHeight, &vHeight);
+    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
+
+    ALOGV("vWidth = %d, vHeight = %d", vWidth, vHeight);
+
+    pDecShellContext->mGivenWidth = vWidth;
+    pDecShellContext->mGivenHeight = vHeight;
+
+    if (!meta->findRect(
+                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
+
+        cropLeft = cropTop = 0;
+        cropRight = vWidth - 1;
+        cropBottom = vHeight - 1;
+
+        ALOGV("got dimensions only %d x %d", width, height);
+    } else {
+        ALOGV("got crop rect %d, %d, %d, %d",
+             cropLeft, cropTop, cropRight, cropBottom);
+    }
+
+    pDecShellContext->mCropRect.left = cropLeft;
+    pDecShellContext->mCropRect.right = cropRight;
+    pDecShellContext->mCropRect.top = cropTop;
+    pDecShellContext->mCropRect.bottom = cropBottom;
+
+    width = cropRight - cropLeft + 1;
+    height = cropBottom - cropTop + 1;
+
+    ALOGV("VideoDecoder_configureFromMetadata : W=%d H=%d", width, height);
+    VIDEOEDITOR_CHECK((0 != width) && (0 != height), M4ERR_PARAMETER);
+
+    if( (M4OSA_NULL != pDecShellContext->m_pDecBufferPool) &&
+        (pDecShellContext->m_pVideoStreamhandler->m_videoWidth  == \
+            (uint32_t)width) &&
+        (pDecShellContext->m_pVideoStreamhandler->m_videoHeight == \
+            (uint32_t)height) ) {
+        // No need to reconfigure
+        goto cleanUp;
+    }
+    ALOGV("VideoDecoder_configureFromMetadata  reset: W=%d H=%d", width, height);
+    // Update the stream handler parameters
+    pDecShellContext->m_pVideoStreamhandler->m_videoWidth  = width;
+    pDecShellContext->m_pVideoStreamhandler->m_videoHeight = height;
+    frameSize = (width * height * 3) / 2;
+
+    // Configure the buffer pool
+    if( M4OSA_NULL != pDecShellContext->m_pDecBufferPool ) {
+        ALOGV("VideoDecoder_configureFromMetadata : reset the buffer pool");
+        VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
+        pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
+    }
+    err =  VIDEOEDITOR_BUFFER_allocatePool(&pDecShellContext->m_pDecBufferPool,
+        MAX_DEC_BUFFERS, (M4OSA_Char*)"VIDEOEDITOR_DecodedBufferPool");
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+    err = VIDEOEDITOR_BUFFER_initPoolBuffers(pDecShellContext->m_pDecBufferPool,
+                frameSize + pDecShellContext->mGivenWidth * 2);
+
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoDecoder_configureFromMetadata no error");
+    } else {
+        if( M4OSA_NULL != pDecShellContext->m_pDecBufferPool ) {
+            VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
+            pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
+        }
+        ALOGV("VideoEditorVideoDecoder_configureFromMetadata ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoDecoder_configureFromMetadata end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_destroy(M4OSA_Context pContext) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoDecoder_Context* pDecShellContext =
+        (VideoEditorVideoDecoder_Context*)pContext;
+
+    // Input parameters check
+    ALOGV("VideoEditorVideoDecoder_destroy begin");
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    // Release the color converter
+    delete pDecShellContext->mI420ColorConverter;
+
+    // Destroy the graph
+    if( pDecShellContext->mVideoDecoder != NULL ) {
+        ALOGV("### VideoEditorVideoDecoder_destroy : releasing decoder");
+        pDecShellContext->mVideoDecoder->stop();
+        pDecShellContext->mVideoDecoder.clear();
+    }
+    pDecShellContext->mClient.disconnect();
+    pDecShellContext->mReaderSource.clear();
+
+    // Release memory
+    if( pDecShellContext->m_pDecBufferPool != M4OSA_NULL ) {
+        VIDEOEDITOR_BUFFER_freePool(pDecShellContext->m_pDecBufferPool);
+        pDecShellContext->m_pDecBufferPool = M4OSA_NULL;
+    }
+    SAFE_FREE(pDecShellContext);
+    pContext = NULL;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoDecoder_destroy no error");
+    } else {
+        ALOGV("VideoEditorVideoDecoder_destroy ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoDecoder_destroy end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_create(M4OSA_Context *pContext,
+        M4_StreamHandler *pStreamHandler,
+        M4READER_GlobalInterface *pReaderGlobalInterface,
+        M4READER_DataInterface *pReaderDataInterface,
+        M4_AccessUnit *pAccessUnit, M4OSA_Void *pUserData) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoDecoder_Context* pDecShellContext = M4OSA_NULL;
+    status_t status = OK;
+    bool success = TRUE;
+    int32_t colorFormat = 0;
+    M4OSA_UInt32 size = 0;
+    sp<MetaData> decoderMetadata = NULL;
+    int decoderOutput = OMX_COLOR_FormatYUV420Planar;
+
+    ALOGV("VideoEditorVideoDecoder_create begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,             M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pStreamHandler,       M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderDataInterface, M4ERR_PARAMETER);
+
+    // Context allocation & initialization
+    SAFE_MALLOC(pDecShellContext, VideoEditorVideoDecoder_Context, 1,
+        "VideoEditorVideoDecoder");
+    pDecShellContext->m_pVideoStreamhandler =
+        (M4_VideoStreamHandler*)pStreamHandler;
+    pDecShellContext->m_pNextAccessUnitToDecode = pAccessUnit;
+    pDecShellContext->m_pReaderGlobal = pReaderGlobalInterface;
+    pDecShellContext->m_pReader = pReaderDataInterface;
+    pDecShellContext->m_lastDecodedCTS = -1;
+    pDecShellContext->m_lastRenderCts = -1;
+    switch( pStreamHandler->m_streamType ) {
+        case M4DA_StreamTypeVideoH263:
+            pDecShellContext->mDecoderType = VIDEOEDITOR_kH263VideoDec;
+            break;
+        case M4DA_StreamTypeVideoMpeg4:
+            pDecShellContext->mDecoderType = VIDEOEDITOR_kMpeg4VideoDec;
+            // Parse the VOL header
+            err = VideoEditorVideoDecoder_internalParseVideoDSI(
+                (M4OSA_UInt8*)pDecShellContext->m_pVideoStreamhandler->\
+                    m_basicProperties.m_pDecoderSpecificInfo,
+                pDecShellContext->m_pVideoStreamhandler->\
+                    m_basicProperties.m_decoderSpecificInfoSize,
+                &pDecShellContext->m_Dci, &pDecShellContext->m_VideoSize);
+            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+            break;
+        case M4DA_StreamTypeVideoMpeg4Avc:
+            pDecShellContext->mDecoderType = VIDEOEDITOR_kH264VideoDec;
+            break;
+        default:
+            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
+                M4ERR_PARAMETER);
+            break;
+    }
+
+    pDecShellContext->mNbInputFrames     = 0;
+    pDecShellContext->mFirstInputCts     = -1.0;
+    pDecShellContext->mLastInputCts      = -1.0;
+    pDecShellContext->mNbRenderedFrames  = 0;
+    pDecShellContext->mFirstRenderedCts  = -1.0;
+    pDecShellContext->mLastRenderedCts   = -1.0;
+    pDecShellContext->mNbOutputFrames    = 0;
+    pDecShellContext->mFirstOutputCts    = -1;
+    pDecShellContext->mLastOutputCts     = -1;
+    pDecShellContext->m_pDecBufferPool   = M4OSA_NULL;
+
+    // Calculate the interval between two video frames.
+    CHECK(pDecShellContext->m_pVideoStreamhandler->m_averageFrameRate > 0);
+    pDecShellContext->mFrameIntervalMs =
+            1000.0 / pDecShellContext->m_pVideoStreamhandler->m_averageFrameRate;
+
+    /**
+     * StageFright graph building
+     */
+    decoderMetadata = new MetaData;
+    switch( pDecShellContext->mDecoderType ) {
+        case VIDEOEDITOR_kH263VideoDec:
+            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+            break;
+        case VIDEOEDITOR_kMpeg4VideoDec:
+            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+            decoderMetadata->setData(kKeyESDS, kTypeESDS,
+                pStreamHandler->m_pESDSInfo,
+                pStreamHandler->m_ESDSInfoSize);
+            break;
+        case VIDEOEDITOR_kH264VideoDec:
+            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+            decoderMetadata->setData(kKeyAVCC, kTypeAVCC,
+                pStreamHandler->m_pH264DecoderSpecificInfo,
+                pStreamHandler->m_H264decoderSpecificInfoSize);
+            break;
+        default:
+            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
+                M4ERR_PARAMETER);
+            break;
+    }
+
+    decoderMetadata->setInt32(kKeyMaxInputSize, pStreamHandler->m_maxAUSize);
+    decoderMetadata->setInt32(kKeyWidth,
+        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
+    decoderMetadata->setInt32(kKeyHeight,
+        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
+
+    // Create the decoder source
+    pDecShellContext->mReaderSource = new VideoEditorVideoDecoderSource(
+        decoderMetadata, pDecShellContext->mDecoderType,
+        (void *)pDecShellContext);
+    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mReaderSource.get(),
+        M4ERR_SF_DECODER_RSRC_FAIL);
+
+    // Connect to the OMX client
+    status = pDecShellContext->mClient.connect();
+    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
+
+    // Create the decoder
+    pDecShellContext->mVideoDecoder = OMXCodec::Create(
+        pDecShellContext->mClient.interface(),
+        decoderMetadata, false, pDecShellContext->mReaderSource);
+    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mVideoDecoder.get(),
+        M4ERR_SF_DECODER_RSRC_FAIL);
+
+
+    // Get the output color format
+    success = pDecShellContext->mVideoDecoder->getFormat()->findInt32(
+        kKeyColorFormat, &colorFormat);
+    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
+    pDecShellContext->decOuputColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
+
+    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyWidth,
+        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
+    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyHeight,
+        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
+
+    // Get the color converter
+    pDecShellContext->mI420ColorConverter = new I420ColorConverter;
+    if (pDecShellContext->mI420ColorConverter->isLoaded()) {
+        decoderOutput = pDecShellContext->mI420ColorConverter->getDecoderOutputFormat();
+    }
+
+    if (decoderOutput == OMX_COLOR_FormatYUV420Planar) {
+        delete pDecShellContext->mI420ColorConverter;
+        pDecShellContext->mI420ColorConverter = NULL;
+    }
+
+    ALOGI("decoder output format = 0x%X\n", decoderOutput);
+
+    // Configure the buffer pool from the metadata
+    err = VideoEditorVideoDecoder_configureFromMetadata(pDecShellContext,
+        pDecShellContext->mVideoDecoder->getFormat().get());
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+    // Start the graph
+    status = pDecShellContext->mVideoDecoder->start();
+    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
+
+    *pContext = (M4OSA_Context)pDecShellContext;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoDecoder_create no error");
+    } else {
+        VideoEditorVideoDecoder_destroy(pDecShellContext);
+        *pContext = M4OSA_NULL;
+        ALOGV("VideoEditorVideoDecoder_create ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoDecoder_create : DONE");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoSoftwareDecoder_create(M4OSA_Context *pContext,
+        M4_StreamHandler *pStreamHandler,
+        M4READER_GlobalInterface *pReaderGlobalInterface,
+        M4READER_DataInterface *pReaderDataInterface,
+        M4_AccessUnit *pAccessUnit, M4OSA_Void *pUserData) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoDecoder_Context* pDecShellContext = M4OSA_NULL;
+    status_t status = OK;
+    bool success = TRUE;
+    int32_t colorFormat = 0;
+    M4OSA_UInt32 size = 0;
+    sp<MetaData> decoderMetadata = NULL;
+
+    ALOGV("VideoEditorVideoDecoder_create begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,             M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pStreamHandler,       M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pReaderDataInterface, M4ERR_PARAMETER);
+
+    // Context allocation & initialization
+    SAFE_MALLOC(pDecShellContext, VideoEditorVideoDecoder_Context, 1,
+        "VideoEditorVideoDecoder");
+    pDecShellContext->m_pVideoStreamhandler =
+        (M4_VideoStreamHandler*)pStreamHandler;
+    pDecShellContext->m_pNextAccessUnitToDecode = pAccessUnit;
+    pDecShellContext->m_pReaderGlobal = pReaderGlobalInterface;
+    pDecShellContext->m_pReader = pReaderDataInterface;
+    pDecShellContext->m_lastDecodedCTS = -1;
+    pDecShellContext->m_lastRenderCts = -1;
+    switch( pStreamHandler->m_streamType ) {
+        case M4DA_StreamTypeVideoH263:
+            pDecShellContext->mDecoderType = VIDEOEDITOR_kH263VideoDec;
+            break;
+        case M4DA_StreamTypeVideoMpeg4:
+            pDecShellContext->mDecoderType = VIDEOEDITOR_kMpeg4VideoDec;
+            // Parse the VOL header
+            err = VideoEditorVideoDecoder_internalParseVideoDSI(
+                (M4OSA_UInt8*)pDecShellContext->m_pVideoStreamhandler->\
+                    m_basicProperties.m_pDecoderSpecificInfo,
+                pDecShellContext->m_pVideoStreamhandler->\
+                    m_basicProperties.m_decoderSpecificInfoSize,
+                &pDecShellContext->m_Dci, &pDecShellContext->m_VideoSize);
+            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+            break;
+        case M4DA_StreamTypeVideoMpeg4Avc:
+            pDecShellContext->mDecoderType = VIDEOEDITOR_kH264VideoDec;
+            break;
+        default:
+            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
+                M4ERR_PARAMETER);
+            break;
+    }
+
+    pDecShellContext->mNbInputFrames     = 0;
+    pDecShellContext->mFirstInputCts     = -1.0;
+    pDecShellContext->mLastInputCts      = -1.0;
+    pDecShellContext->mNbRenderedFrames  = 0;
+    pDecShellContext->mFirstRenderedCts  = -1.0;
+    pDecShellContext->mLastRenderedCts   = -1.0;
+    pDecShellContext->mNbOutputFrames    = 0;
+    pDecShellContext->mFirstOutputCts    = -1;
+    pDecShellContext->mLastOutputCts     = -1;
+    pDecShellContext->m_pDecBufferPool   = M4OSA_NULL;
+
+    /**
+     * StageFright graph building
+     */
+    decoderMetadata = new MetaData;
+    switch( pDecShellContext->mDecoderType ) {
+        case VIDEOEDITOR_kH263VideoDec:
+            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+            break;
+        case VIDEOEDITOR_kMpeg4VideoDec:
+            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+            decoderMetadata->setData(kKeyESDS, kTypeESDS,
+                pStreamHandler->m_pESDSInfo,
+                pStreamHandler->m_ESDSInfoSize);
+            break;
+        case VIDEOEDITOR_kH264VideoDec:
+            decoderMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+            decoderMetadata->setData(kKeyAVCC, kTypeAVCC,
+                pStreamHandler->m_pH264DecoderSpecificInfo,
+                pStreamHandler->m_H264decoderSpecificInfoSize);
+            break;
+        default:
+            VIDEOEDITOR_CHECK(!"VideoDecoder_create : incorrect stream type",
+                M4ERR_PARAMETER);
+            break;
+    }
+
+    decoderMetadata->setInt32(kKeyMaxInputSize, pStreamHandler->m_maxAUSize);
+    decoderMetadata->setInt32(kKeyWidth,
+        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
+    decoderMetadata->setInt32(kKeyHeight,
+        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
+
+    // Create the decoder source
+    pDecShellContext->mReaderSource = new VideoEditorVideoDecoderSource(
+        decoderMetadata, pDecShellContext->mDecoderType,
+        (void *)pDecShellContext);
+    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mReaderSource.get(),
+        M4ERR_SF_DECODER_RSRC_FAIL);
+
+    // Connect to the OMX client
+    status = pDecShellContext->mClient.connect();
+    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
+
+     ALOGI("Using software codecs only");
+    // Create the decoder
+    pDecShellContext->mVideoDecoder = OMXCodec::Create(
+        pDecShellContext->mClient.interface(),
+        decoderMetadata, false, pDecShellContext->mReaderSource,NULL,OMXCodec::kSoftwareCodecsOnly);
+    VIDEOEDITOR_CHECK(NULL != pDecShellContext->mVideoDecoder.get(),
+        M4ERR_SF_DECODER_RSRC_FAIL);
+
+    // Get the output color format
+    success = pDecShellContext->mVideoDecoder->getFormat()->findInt32(
+        kKeyColorFormat, &colorFormat);
+    VIDEOEDITOR_CHECK(TRUE == success, M4ERR_PARAMETER);
+    pDecShellContext->decOuputColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
+
+    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyWidth,
+        pDecShellContext->m_pVideoStreamhandler->m_videoWidth);
+    pDecShellContext->mVideoDecoder->getFormat()->setInt32(kKeyHeight,
+        pDecShellContext->m_pVideoStreamhandler->m_videoHeight);
+
+    // Configure the buffer pool from the metadata
+    err = VideoEditorVideoDecoder_configureFromMetadata(pDecShellContext,
+        pDecShellContext->mVideoDecoder->getFormat().get());
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+    // Start the graph
+    status = pDecShellContext->mVideoDecoder->start();
+    VIDEOEDITOR_CHECK(OK == status, M4ERR_SF_DECODER_RSRC_FAIL);
+
+    *pContext = (M4OSA_Context)pDecShellContext;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoDecoder_create no error");
+    } else {
+        VideoEditorVideoDecoder_destroy(pDecShellContext);
+        *pContext = M4OSA_NULL;
+        ALOGV("VideoEditorVideoDecoder_create ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoDecoder_create : DONE");
+    return err;
+}
+
+
+M4OSA_ERR VideoEditorVideoDecoder_getOption(M4OSA_Context context,
+        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
+    M4OSA_ERR lerr = M4NO_ERROR;
+    VideoEditorVideoDecoder_Context* pDecShellContext =
+        (VideoEditorVideoDecoder_Context*) context;
+    M4_VersionInfo* pVersionInfo;
+    M4DECODER_VideoSize* pVideoSize;
+    M4OSA_UInt32* pNextFrameCts;
+    M4OSA_UInt32 *plastDecodedFrameCts;
+    M4DECODER_AVCProfileLevel* profile;
+    M4DECODER_MPEG4_DecoderConfigInfo* pDecConfInfo;
+
+    ALOGV("VideoEditorVideoDecoder_getOption begin");
+
+    switch (optionId) {
+        case M4DECODER_kOptionID_AVCLastDecodedFrameCTS:
+             plastDecodedFrameCts = (M4OSA_UInt32 *) pValue;
+             *plastDecodedFrameCts = pDecShellContext->m_lastDecodedCTS;
+             break;
+
+        case M4DECODER_kOptionID_Version:
+            pVersionInfo = (M4_VersionInfo*)pValue;
+
+            pVersionInfo->m_major = VIDEOEDITOR_VIDEC_SHELL_VER_MAJOR;
+            pVersionInfo->m_minor= VIDEOEDITOR_VIDEC_SHELL_VER_MINOR;
+            pVersionInfo->m_revision = VIDEOEDITOR_VIDEC_SHELL_VER_REVISION;
+            pVersionInfo->m_structSize=sizeof(M4_VersionInfo);
+            break;
+
+        case M4DECODER_kOptionID_VideoSize:
+            /** Only VPS uses this Option ID. */
+            pVideoSize = (M4DECODER_VideoSize*)pValue;
+            pDecShellContext->mVideoDecoder->getFormat()->findInt32(kKeyWidth,
+                (int32_t*)(&pVideoSize->m_uiWidth));
+            pDecShellContext->mVideoDecoder->getFormat()->findInt32(kKeyHeight,
+                (int32_t*)(&pVideoSize->m_uiHeight));
+            ALOGV("VideoEditorVideoDecoder_getOption : W=%d H=%d",
+                pVideoSize->m_uiWidth, pVideoSize->m_uiHeight);
+            break;
+
+        case M4DECODER_kOptionID_NextRenderedFrameCTS:
+            /** How to get this information. SF decoder does not provide this. *
+            ** Let us provide last decoded frame CTS as of now. *
+            ** Only VPS uses this Option ID. */
+            pNextFrameCts = (M4OSA_UInt32 *)pValue;
+            *pNextFrameCts = pDecShellContext->m_lastDecodedCTS;
+            break;
+        case M4DECODER_MPEG4_kOptionID_DecoderConfigInfo:
+            if(pDecShellContext->mDecoderType == VIDEOEDITOR_kMpeg4VideoDec) {
+                (*(M4DECODER_MPEG4_DecoderConfigInfo*)pValue) =
+                    pDecShellContext->m_Dci;
+            }
+            break;
+        default:
+            lerr = M4ERR_BAD_OPTION_ID;
+            break;
+
+    }
+
+    ALOGV("VideoEditorVideoDecoder_getOption: end with err = 0x%x", lerr);
+    return lerr;
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_setOption(M4OSA_Context context,
+        M4OSA_OptionID optionId, M4OSA_DataOption pValue) {
+    M4OSA_ERR lerr = M4NO_ERROR;
+    VideoEditorVideoDecoder_Context *pDecShellContext =
+        (VideoEditorVideoDecoder_Context*) context;
+
+    ALOGV("VideoEditorVideoDecoder_setOption begin");
+
+    switch (optionId) {
+        case M4DECODER_kOptionID_OutputFilter: {
+                M4DECODER_OutputFilter* pOutputFilter =
+                    (M4DECODER_OutputFilter*) pValue;
+                pDecShellContext->m_pFilter =
+                    (M4VIFI_PlanConverterFunctionType*)pOutputFilter->\
+                    m_pFilterFunction;
+                pDecShellContext->m_pFilterUserData =
+                    pOutputFilter->m_pFilterUserData;
+            }
+            break;
+        case M4DECODER_kOptionID_DeblockingFilter:
+            break;
+        default:
+            lerr = M4ERR_BAD_CONTEXT;
+            break;
+    }
+
+    ALOGV("VideoEditorVideoDecoder_setOption: end with err = 0x%x", lerr);
+    return lerr;
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_decode(M4OSA_Context context,
+        M4_MediaTime* pTime, M4OSA_Bool bJump, M4OSA_UInt32 tolerance) {
+    M4OSA_ERR lerr = M4NO_ERROR;
+    VideoEditorVideoDecoder_Context* pDecShellContext =
+        (VideoEditorVideoDecoder_Context*) context;
+    int64_t lFrameTime;
+    MediaBuffer* pDecoderBuffer = NULL;
+    MediaBuffer* pNextBuffer = NULL;
+    status_t errStatus;
+    bool needSeek = bJump;
+
+    ALOGV("VideoEditorVideoDecoder_decode begin");
+
+    if( M4OSA_TRUE == pDecShellContext->mReachedEOS ) {
+        // Do not call read(), it could lead to a freeze
+        ALOGV("VideoEditorVideoDecoder_decode : EOS already reached");
+        lerr = M4WAR_NO_MORE_AU;
+        goto VIDEOEDITOR_VideoDecode_cleanUP;
+    }
+    if(pDecShellContext->m_lastDecodedCTS >= *pTime) {
+        ALOGV("VideoDecoder_decode: Already decoded up to this time CTS = %lf.",
+            pDecShellContext->m_lastDecodedCTS);
+        goto VIDEOEDITOR_VideoDecode_cleanUP;
+    }
+    if(M4OSA_TRUE == bJump) {
+        ALOGV("VideoEditorVideoDecoder_decode: Jump called");
+        pDecShellContext->m_lastDecodedCTS = -1;
+        pDecShellContext->m_lastRenderCts = -1;
+    }
+
+    pDecShellContext->mNbInputFrames++;
+    if (0 > pDecShellContext->mFirstInputCts){
+        pDecShellContext->mFirstInputCts = *pTime;
+    }
+    pDecShellContext->mLastInputCts = *pTime;
+
+    while (pDecoderBuffer == NULL || pDecShellContext->m_lastDecodedCTS + tolerance < *pTime) {
+        ALOGV("VideoEditorVideoDecoder_decode, frameCTS = %lf, DecodeUpTo = %lf",
+            pDecShellContext->m_lastDecodedCTS, *pTime);
+
+        // Read the buffer from the stagefright decoder
+        if (needSeek) {
+            MediaSource::ReadOptions options;
+            int64_t time_us = *pTime * 1000;
+            options.setSeekTo(time_us, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+            errStatus = pDecShellContext->mVideoDecoder->read(&pNextBuffer, &options);
+            needSeek = false;
+        } else {
+            errStatus = pDecShellContext->mVideoDecoder->read(&pNextBuffer);
+        }
+
+        // Handle EOS and format change
+        if (errStatus == ERROR_END_OF_STREAM) {
+            ALOGV("End of stream reached, returning M4WAR_NO_MORE_AU ");
+            pDecShellContext->mReachedEOS = M4OSA_TRUE;
+            lerr = M4WAR_NO_MORE_AU;
+            // If we decoded a buffer before EOS, we still need to put it
+            // into the queue.
+            if (pDecoderBuffer && bJump) {
+                copyBufferToQueue(pDecShellContext, pDecoderBuffer);
+            }
+            goto VIDEOEDITOR_VideoDecode_cleanUP;
+        } else if (INFO_FORMAT_CHANGED == errStatus) {
+            ALOGV("VideoDecoder_decode : source returns INFO_FORMAT_CHANGED");
+            lerr = VideoEditorVideoDecoder_configureFromMetadata(
+                pDecShellContext,
+                pDecShellContext->mVideoDecoder->getFormat().get());
+            if( M4NO_ERROR != lerr ) {
+                ALOGV("!!! VideoEditorVideoDecoder_decode ERROR : "
+                    "VideoDecoder_configureFromMetadata returns 0x%X", lerr);
+                break;
+            }
+            continue;
+        } else if (errStatus != OK) {
+            ALOGE("VideoEditorVideoDecoder_decode ERROR:0x%x(%d)",
+                errStatus,errStatus);
+            lerr = errStatus;
+            goto VIDEOEDITOR_VideoDecode_cleanUP;
+        }
+
+        // The OMXCodec client should expect to receive 0-length buffers
+        // and drop the 0-length buffers.
+        if (pNextBuffer->range_length() == 0) {
+            pNextBuffer->release();
+            continue;
+        }
+
+        // Now we have a good next buffer, release the previous one.
+        if (pDecoderBuffer != NULL) {
+            pDecoderBuffer->release();
+            pDecoderBuffer = NULL;
+        }
+        pDecoderBuffer = pNextBuffer;
+
+        // Record the timestamp of last decoded buffer
+        pDecoderBuffer->meta_data()->findInt64(kKeyTime, &lFrameTime);
+        pDecShellContext->m_lastDecodedCTS = (M4_MediaTime)(lFrameTime/1000);
+        ALOGV("VideoEditorVideoDecoder_decode,decoded frametime = %lf,size = %d",
+            (M4_MediaTime)lFrameTime, pDecoderBuffer->size() );
+
+        /*
+         * We need to save a buffer if bJump == false to a queue. These
+         * buffers have a timestamp >= the target time, *pTime (for instance,
+         * the transition between two videos, or a trimming postion inside
+         * one video), since they are part of the transition clip or the
+         * trimmed video.
+         *
+         * If *pTime does not have the same value as any of the existing
+         * video frames, we would like to get the buffer right before *pTime
+         * and in the transcoding phrase, this video frame will be encoded
+         * as a key frame and becomes the first video frame for the transition or the
+         * trimmed video to be generated. This buffer must also be queued.
+         *
+         */
+        int64_t targetTimeMs =
+                pDecShellContext->m_lastDecodedCTS +
+                pDecShellContext->mFrameIntervalMs +
+                tolerance;
+        if (!bJump || targetTimeMs > *pTime) {
+            lerr = copyBufferToQueue(pDecShellContext, pDecoderBuffer);
+            if (lerr != M4NO_ERROR) {
+                goto VIDEOEDITOR_VideoDecode_cleanUP;
+            }
+        }
+    }
+
+    pDecShellContext->mNbOutputFrames++;
+    if ( 0 > pDecShellContext->mFirstOutputCts ) {
+        pDecShellContext->mFirstOutputCts = *pTime;
+    }
+    pDecShellContext->mLastOutputCts = *pTime;
+
+VIDEOEDITOR_VideoDecode_cleanUP:
+    *pTime = pDecShellContext->m_lastDecodedCTS;
+    if (pDecoderBuffer != NULL) {
+        pDecoderBuffer->release();
+        pDecoderBuffer = NULL;
+    }
+
+    ALOGV("VideoEditorVideoDecoder_decode: end with 0x%x", lerr);
+    return lerr;
+}
+
+static M4OSA_ERR copyBufferToQueue(
+    VideoEditorVideoDecoder_Context* pDecShellContext,
+    MediaBuffer* pDecoderBuffer) {
+
+    M4OSA_ERR lerr = M4NO_ERROR;
+    VIDEOEDITOR_BUFFER_Buffer* tmpDecBuffer;
+
+    // Get a buffer from the queue
+    lerr = VIDEOEDITOR_BUFFER_getBuffer(pDecShellContext->m_pDecBufferPool,
+        VIDEOEDITOR_BUFFER_kEmpty, &tmpDecBuffer);
+    if (lerr == (M4OSA_UInt32)M4ERR_NO_BUFFER_AVAILABLE) {
+        lerr = VIDEOEDITOR_BUFFER_getOldestBuffer(
+            pDecShellContext->m_pDecBufferPool,
+            VIDEOEDITOR_BUFFER_kFilled, &tmpDecBuffer);
+        tmpDecBuffer->state = VIDEOEDITOR_BUFFER_kEmpty;
+        lerr = M4NO_ERROR;
+    }
+
+    if (lerr != M4NO_ERROR) return lerr;
+
+    // Color convert or copy from the given MediaBuffer to our buffer
+    if (pDecShellContext->mI420ColorConverter) {
+        if (pDecShellContext->mI420ColorConverter->convertDecoderOutputToI420(
+            (uint8_t *)pDecoderBuffer->data(),// ?? + pDecoderBuffer->range_offset(),   // decoderBits
+            pDecShellContext->mGivenWidth,  // decoderWidth
+            pDecShellContext->mGivenHeight,  // decoderHeight
+            pDecShellContext->mCropRect,  // decoderRect
+            tmpDecBuffer->pData /* dstBits */) < 0) {
+            ALOGE("convertDecoderOutputToI420 failed");
+            lerr = M4ERR_NOT_IMPLEMENTED;
+        }
+    } else if (pDecShellContext->decOuputColorFormat == OMX_COLOR_FormatYUV420Planar) {
+        int32_t width = pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
+        int32_t height = pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
+        int32_t yPlaneSize = width * height;
+        int32_t uvPlaneSize = width * height / 4;
+        int32_t offsetSrc = 0;
+
+        if (( width == pDecShellContext->mGivenWidth )  &&
+            ( height == pDecShellContext->mGivenHeight ))
+        {
+            M4OSA_MemAddr8 pTmpBuff = (M4OSA_MemAddr8)pDecoderBuffer->data() + pDecoderBuffer->range_offset();
+
+            memcpy((void *)tmpDecBuffer->pData, (void *)pTmpBuff, yPlaneSize);
+
+            offsetSrc += pDecShellContext->mGivenWidth * pDecShellContext->mGivenHeight;
+            memcpy((void *)((M4OSA_MemAddr8)tmpDecBuffer->pData + yPlaneSize),
+                (void *)(pTmpBuff + offsetSrc), uvPlaneSize);
+
+            offsetSrc += (pDecShellContext->mGivenWidth >> 1) * (pDecShellContext->mGivenHeight >> 1);
+            memcpy((void *)((M4OSA_MemAddr8)tmpDecBuffer->pData + yPlaneSize + uvPlaneSize),
+                (void *)(pTmpBuff + offsetSrc), uvPlaneSize);
+        }
+        else
+        {
+            M4OSA_MemAddr8 pTmpBuff = (M4OSA_MemAddr8)pDecoderBuffer->data() + pDecoderBuffer->range_offset();
+            M4OSA_MemAddr8 pTmpBuffDst = (M4OSA_MemAddr8)tmpDecBuffer->pData;
+            int32_t index;
+
+            for ( index = 0; index < height; index++)
+            {
+                memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width);
+                pTmpBuffDst += width;
+                pTmpBuff += pDecShellContext->mGivenWidth;
+            }
+
+            pTmpBuff += (pDecShellContext->mGivenWidth * ( pDecShellContext->mGivenHeight - height));
+            for ( index = 0; index < height >> 1; index++)
+            {
+                memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width >> 1);
+                pTmpBuffDst += width >> 1;
+                pTmpBuff += pDecShellContext->mGivenWidth >> 1;
+            }
+
+            pTmpBuff += ((pDecShellContext->mGivenWidth * (pDecShellContext->mGivenHeight - height)) / 4);
+            for ( index = 0; index < height >> 1; index++)
+            {
+                memcpy((void *)pTmpBuffDst, (void *)pTmpBuff, width >> 1);
+                pTmpBuffDst += width >> 1;
+                pTmpBuff += pDecShellContext->mGivenWidth >> 1;
+            }
+        }
+    } else {
+        ALOGE("VideoDecoder_decode: unexpected color format 0x%X",
+            pDecShellContext->decOuputColorFormat);
+        lerr = M4ERR_PARAMETER;
+    }
+
+    tmpDecBuffer->buffCTS = pDecShellContext->m_lastDecodedCTS;
+    tmpDecBuffer->state = VIDEOEDITOR_BUFFER_kFilled;
+    tmpDecBuffer->size = pDecoderBuffer->size();
+
+    return lerr;
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_render(M4OSA_Context context,
+        M4_MediaTime* pTime, M4VIFI_ImagePlane* pOutputPlane,
+        M4OSA_Bool bForceRender) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoDecoder_Context* pDecShellContext =
+        (VideoEditorVideoDecoder_Context*) context;
+    M4OSA_UInt32 lindex, i;
+    M4OSA_UInt8* p_buf_src, *p_buf_dest;
+    M4VIFI_ImagePlane tmpPlaneIn, tmpPlaneOut;
+    VIDEOEDITOR_BUFFER_Buffer* pTmpVIDEOEDITORBuffer, *pRenderVIDEOEDITORBuffer
+                                                                  = M4OSA_NULL;
+    M4_MediaTime candidateTimeStamp = -1;
+    M4OSA_Bool bFound = M4OSA_FALSE;
+
+    ALOGV("VideoEditorVideoDecoder_render begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != context, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pTime, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pOutputPlane, M4ERR_PARAMETER);
+
+    // The output buffer is already allocated, just copy the data
+    if ( (*pTime <= pDecShellContext->m_lastRenderCts) &&
+            (M4OSA_FALSE == bForceRender) ) {
+        ALOGV("VIDEOEDITOR_VIDEO_render Frame in the past");
+        err = M4WAR_VIDEORENDERER_NO_NEW_FRAME;
+        goto cleanUp;
+    }
+    ALOGV("VideoDecoder_render: lastRendered time = %lf,requested render time = "
+        "%lf", pDecShellContext->m_lastRenderCts, *pTime);
+
+    /**
+     * Find the buffer appropriate for rendering.  */
+    for (i=0; i < pDecShellContext->m_pDecBufferPool->NB; i++) {
+        pTmpVIDEOEDITORBuffer = &pDecShellContext->m_pDecBufferPool\
+            ->pNXPBuffer[i];
+        if (pTmpVIDEOEDITORBuffer->state == VIDEOEDITOR_BUFFER_kFilled) {
+            /** Free all those buffers older than last rendered frame. */
+            if (pTmpVIDEOEDITORBuffer->buffCTS < pDecShellContext->\
+                    m_lastRenderCts) {
+                pTmpVIDEOEDITORBuffer->state = VIDEOEDITOR_BUFFER_kEmpty;
+            }
+
+            /** Get the buffer with appropriate timestamp  */
+            if ( (pTmpVIDEOEDITORBuffer->buffCTS >= pDecShellContext->\
+                    m_lastRenderCts) &&
+                (pTmpVIDEOEDITORBuffer->buffCTS <= *pTime) &&
+                (pTmpVIDEOEDITORBuffer->buffCTS > candidateTimeStamp)) {
+                bFound = M4OSA_TRUE;
+                pRenderVIDEOEDITORBuffer = pTmpVIDEOEDITORBuffer;
+                candidateTimeStamp = pTmpVIDEOEDITORBuffer->buffCTS;
+                ALOGV("VideoDecoder_render: found a buffer with timestamp = %lf",
+                    candidateTimeStamp);
+            }
+        }
+    }
+    if (M4OSA_FALSE == bFound) {
+        err = M4WAR_VIDEORENDERER_NO_NEW_FRAME;
+        goto cleanUp;
+    }
+
+    ALOGV("VideoEditorVideoDecoder_render 3 ouput %d %d %d %d",
+        pOutputPlane[0].u_width, pOutputPlane[0].u_height,
+        pOutputPlane[0].u_topleft, pOutputPlane[0].u_stride);
+
+    pDecShellContext->m_lastRenderCts = candidateTimeStamp;
+
+    if( M4OSA_NULL != pDecShellContext->m_pFilter ) {
+        // Filtering was requested
+        M4VIFI_ImagePlane tmpPlane[3];
+        // Prepare the output image for conversion
+        tmpPlane[0].u_width   =
+            pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
+        tmpPlane[0].u_height  =
+            pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
+        tmpPlane[0].u_topleft = 0;
+        tmpPlane[0].u_stride  = tmpPlane[0].u_width;
+        tmpPlane[0].pac_data  = (M4VIFI_UInt8*)pRenderVIDEOEDITORBuffer->pData;
+        tmpPlane[1].u_width   = tmpPlane[0].u_width/2;
+        tmpPlane[1].u_height  = tmpPlane[0].u_height/2;
+        tmpPlane[1].u_topleft = 0;
+        tmpPlane[1].u_stride  = tmpPlane[0].u_stride/2;
+        tmpPlane[1].pac_data  = tmpPlane[0].pac_data +
+            (tmpPlane[0].u_stride * tmpPlane[0].u_height);
+        tmpPlane[2].u_width   = tmpPlane[1].u_width;
+        tmpPlane[2].u_height  = tmpPlane[1].u_height;
+        tmpPlane[2].u_topleft = 0;
+        tmpPlane[2].u_stride  = tmpPlane[1].u_stride;
+        tmpPlane[2].pac_data  = tmpPlane[1].pac_data +
+            (tmpPlane[1].u_stride * tmpPlane[1].u_height);
+
+        ALOGV("VideoEditorVideoDecoder_render w = %d H = %d",
+            tmpPlane[0].u_width,tmpPlane[0].u_height);
+        pDecShellContext->m_pFilter(M4OSA_NULL, &tmpPlane[0], pOutputPlane);
+    } else {
+        // Just copy the YUV420P buffer
+        M4OSA_MemAddr8 tempBuffPtr =
+            (M4OSA_MemAddr8)pRenderVIDEOEDITORBuffer->pData;
+        M4OSA_UInt32 tempWidth =
+            pDecShellContext->m_pVideoStreamhandler->m_videoWidth;
+        M4OSA_UInt32 tempHeight =
+            pDecShellContext->m_pVideoStreamhandler->m_videoHeight;
+
+        memcpy((void *) pOutputPlane[0].pac_data, (void *)tempBuffPtr,
+            tempWidth * tempHeight);
+        tempBuffPtr += (tempWidth * tempHeight);
+        memcpy((void *) pOutputPlane[1].pac_data, (void *)tempBuffPtr,
+            (tempWidth/2) * (tempHeight/2));
+        tempBuffPtr += ((tempWidth/2) * (tempHeight/2));
+        memcpy((void *) pOutputPlane[2].pac_data, (void *)tempBuffPtr,
+            (tempWidth/2) * (tempHeight/2));
+    }
+
+    pDecShellContext->mNbRenderedFrames++;
+    if ( 0 > pDecShellContext->mFirstRenderedCts ) {
+        pDecShellContext->mFirstRenderedCts = *pTime;
+    }
+    pDecShellContext->mLastRenderedCts = *pTime;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        *pTime = pDecShellContext->m_lastRenderCts;
+        ALOGV("VideoEditorVideoDecoder_render no error");
+    } else {
+        ALOGV("VideoEditorVideoDecoder_render ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoDecoder_render end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_getInterface(M4DECODER_VideoType decoderType,
+        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
+    M4DECODER_VideoInterface* pDecoderInterface = M4OSA_NULL;
+
+    pDecoderInterface = (M4DECODER_VideoInterface*)M4OSA_32bitAlignedMalloc(
+        sizeof(M4DECODER_VideoInterface), M4DECODER_EXTERNAL,
+        (M4OSA_Char*)"VideoEditorVideoDecoder_getInterface" );
+    if (M4OSA_NULL == pDecoderInterface) {
+        return M4ERR_ALLOC;
+    }
+
+    *pDecoderType = decoderType;
+
+    pDecoderInterface->m_pFctCreate    = VideoEditorVideoDecoder_create;
+    pDecoderInterface->m_pFctDestroy   = VideoEditorVideoDecoder_destroy;
+    pDecoderInterface->m_pFctGetOption = VideoEditorVideoDecoder_getOption;
+    pDecoderInterface->m_pFctSetOption = VideoEditorVideoDecoder_setOption;
+    pDecoderInterface->m_pFctDecode    = VideoEditorVideoDecoder_decode;
+    pDecoderInterface->m_pFctRender    = VideoEditorVideoDecoder_render;
+
+    *pDecInterface = (M4OSA_Context)pDecoderInterface;
+    return M4NO_ERROR;
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_VideoType decoderType,
+        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
+    M4DECODER_VideoInterface* pDecoderInterface = M4OSA_NULL;
+
+    pDecoderInterface = (M4DECODER_VideoInterface*)M4OSA_32bitAlignedMalloc(
+        sizeof(M4DECODER_VideoInterface), M4DECODER_EXTERNAL,
+        (M4OSA_Char*)"VideoEditorVideoDecoder_getInterface" );
+    if (M4OSA_NULL == pDecoderInterface) {
+        return M4ERR_ALLOC;
+    }
+
+    *pDecoderType = decoderType;
+
+    pDecoderInterface->m_pFctCreate    = VideoEditorVideoSoftwareDecoder_create;
+    pDecoderInterface->m_pFctDestroy   = VideoEditorVideoDecoder_destroy;
+    pDecoderInterface->m_pFctGetOption = VideoEditorVideoDecoder_getOption;
+    pDecoderInterface->m_pFctSetOption = VideoEditorVideoDecoder_setOption;
+    pDecoderInterface->m_pFctDecode    = VideoEditorVideoDecoder_decode;
+    pDecoderInterface->m_pFctRender    = VideoEditorVideoDecoder_render;
+
+    *pDecInterface = (M4OSA_Context)pDecoderInterface;
+    return M4NO_ERROR;
+}
+extern "C" {
+
+M4OSA_ERR VideoEditorVideoDecoder_getInterface_MPEG4(
+        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
+    return VideoEditorVideoDecoder_getInterface(M4DECODER_kVideoTypeMPEG4,
+        pDecoderType, pDecInterface);
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_getInterface_H264(
+        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
+    return VideoEditorVideoDecoder_getInterface(M4DECODER_kVideoTypeAVC,
+        pDecoderType, pDecInterface);
+
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface_MPEG4(
+        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
+    return VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_kVideoTypeMPEG4,
+        pDecoderType, pDecInterface);
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_getSoftwareInterface_H264(
+        M4DECODER_VideoType *pDecoderType, M4OSA_Context *pDecInterface) {
+    return VideoEditorVideoDecoder_getSoftwareInterface(M4DECODER_kVideoTypeAVC,
+        pDecoderType, pDecInterface);
+
+}
+
+M4OSA_ERR VideoEditorVideoDecoder_getVideoDecodersAndCapabilities(
+    M4DECODER_VideoDecoders** decoders) {
+    return queryVideoDecoderCapabilities(decoders);
+}
+
+}  // extern "C"
diff --git a/frameworks/videoedit/stagefrightshells/VideoEditorVideoEncoder.cpp b/frameworks/videoedit/stagefrightshells/VideoEditorVideoEncoder.cpp
new file mode 100644
index 0000000..1abc447
--- /dev/null
+++ b/frameworks/videoedit/stagefrightshells/VideoEditorVideoEncoder.cpp
@@ -0,0 +1,1295 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+*************************************************************************
+* @file   VideoEditorVideoEncoder.cpp
+* @brief  StageFright shell video encoder
+*************************************************************************
+*/
+#define LOG_NDEBUG 1
+#define LOG_TAG "VIDEOEDITOR_VIDEOENCODER"
+
+/*******************
+ *     HEADERS     *
+ *******************/
+#include "M4OSA_Debug.h"
+#include "M4SYS_AccessUnit.h"
+#include "VideoEditorVideoEncoder.h"
+#include "MediaBufferPuller.h"
+#include <I420ColorConverter.h>
+
+#include <unistd.h>
+#include "utils/Log.h"
+#include "utils/Vector.h"
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#include <media/MediaProfiles.h>
+#include "OMX_Video.h"
+
+#include "IntelVideoEditorEncoderSource.h"
+#include "IntelVideoEditorAVCEncoder.h"
+#include "IntelVideoEditorH263Encoder.h"
+#include "IntelVideoEditorUtils.h"
+
+/********************
+ *   DEFINITIONS    *
+ ********************/
+
+// Force using hardware encoder
+#define VIDEOEDITOR_FORCECODEC kHardwareCodecsOnly
+
+#if !defined(VIDEOEDITOR_FORCECODEC)
+    #error "Cannot force DSI retrieval if codec type is not fixed"
+#endif
+
+/********************
+ *   SOURCE CLASS   *
+ ********************/
+
+namespace android {
+
+struct VideoEditorVideoEncoderSource : public MediaSource {
+    public:
+        static sp<VideoEditorVideoEncoderSource> Create(
+            const sp<MetaData> &format);
+        virtual status_t start(MetaData *params = NULL);
+        virtual status_t stop();
+        virtual sp<MetaData> getFormat();
+        virtual status_t read(MediaBuffer **buffer,
+            const ReadOptions *options = NULL);
+        virtual int32_t storeBuffer(MediaBuffer *buffer);
+        virtual int32_t getNumberOfBuffersInQueue();
+
+    protected:
+        virtual ~VideoEditorVideoEncoderSource();
+
+    private:
+        struct MediaBufferChain {
+            MediaBuffer* buffer;
+            MediaBufferChain* nextLink;
+        };
+        enum State {
+            CREATED,
+            STARTED,
+            ERROR
+        };
+        VideoEditorVideoEncoderSource(const sp<MetaData> &format);
+
+        // Don't call me
+        VideoEditorVideoEncoderSource(const VideoEditorVideoEncoderSource &);
+        VideoEditorVideoEncoderSource &operator=(
+                const VideoEditorVideoEncoderSource &);
+
+        MediaBufferChain* mFirstBufferLink;
+        MediaBufferChain* mLastBufferLink;
+        int32_t           mNbBuffer;
+        bool              mIsEOS;
+        State             mState;
+        sp<MetaData>      mEncFormat;
+        Mutex             mLock;
+        Condition         mBufferCond;
+};
+
+sp<VideoEditorVideoEncoderSource> VideoEditorVideoEncoderSource::Create(
+    const sp<MetaData> &format) {
+
+    sp<VideoEditorVideoEncoderSource> aSource =
+        new VideoEditorVideoEncoderSource(format);
+    return aSource;
+}
+
+VideoEditorVideoEncoderSource::VideoEditorVideoEncoderSource(
+    const sp<MetaData> &format):
+        mFirstBufferLink(NULL),
+        mLastBufferLink(NULL),
+        mNbBuffer(0),
+        mIsEOS(false),
+        mState(CREATED),
+        mEncFormat(format) {
+    ALOGV("VideoEditorVideoEncoderSource::VideoEditorVideoEncoderSource");
+}
+
+VideoEditorVideoEncoderSource::~VideoEditorVideoEncoderSource() {
+
+    // Safety clean up
+    if( STARTED == mState ) {
+        stop();
+    }
+}
+
+status_t VideoEditorVideoEncoderSource::start(MetaData *meta) {
+    status_t err = OK;
+
+    ALOGV("VideoEditorVideoEncoderSource::start() begin");
+
+    if( CREATED != mState ) {
+        ALOGV("VideoEditorVideoEncoderSource::start: invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+    mState = STARTED;
+
+    ALOGV("VideoEditorVideoEncoderSource::start() END (0x%x)", err);
+    return err;
+}
+
+status_t VideoEditorVideoEncoderSource::stop() {
+    status_t err = OK;
+
+    ALOGV("VideoEditorVideoEncoderSource::stop() begin");
+
+    if( STARTED != mState ) {
+        ALOGV("VideoEditorVideoEncoderSource::stop: invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+
+    // Release the buffer chain
+    int32_t i = 0;
+    MediaBufferChain* tmpLink = NULL;
+    while( mFirstBufferLink ) {
+        i++;
+        tmpLink = mFirstBufferLink;
+        mFirstBufferLink = mFirstBufferLink->nextLink;
+        delete tmpLink;
+    }
+    ALOGV("VideoEditorVideoEncoderSource::stop : %d buffer remained", i);
+    mFirstBufferLink = NULL;
+    mLastBufferLink = NULL;
+
+    mState = CREATED;
+
+    ALOGV("VideoEditorVideoEncoderSource::stop() END (0x%x)", err);
+    return err;
+}
+
+sp<MetaData> VideoEditorVideoEncoderSource::getFormat() {
+
+    ALOGV("VideoEditorVideoEncoderSource::getFormat");
+    return mEncFormat;
+}
+
+status_t VideoEditorVideoEncoderSource::read(MediaBuffer **buffer,
+        const ReadOptions *options) {
+    Mutex::Autolock autolock(mLock);
+    MediaSource::ReadOptions readOptions;
+    status_t err = OK;
+    MediaBufferChain* tmpLink = NULL;
+
+    ALOGV("VideoEditorVideoEncoderSource::read() begin");
+
+    if ( STARTED != mState ) {
+        ALOGV("VideoEditorVideoEncoderSource::read: invalid state %d", mState);
+        return UNKNOWN_ERROR;
+    }
+
+    while (mFirstBufferLink == NULL && !mIsEOS) {
+        mBufferCond.wait(mLock);
+    }
+
+    // End of stream?
+    if (mFirstBufferLink == NULL) {
+        *buffer = NULL;
+        ALOGV("VideoEditorVideoEncoderSource::read : EOS");
+        return ERROR_END_OF_STREAM;
+    }
+
+    // Get a buffer from the chain
+    *buffer = mFirstBufferLink->buffer;
+    tmpLink = mFirstBufferLink;
+    mFirstBufferLink = mFirstBufferLink->nextLink;
+
+    if ( NULL == mFirstBufferLink ) {
+        mLastBufferLink = NULL;
+    }
+    delete tmpLink;
+    mNbBuffer--;
+
+    ALOGV("VideoEditorVideoEncoderSource::read() END (0x%x)", err);
+    return err;
+}
+
+int32_t VideoEditorVideoEncoderSource::storeBuffer(MediaBuffer *buffer) {
+    Mutex::Autolock autolock(mLock);
+    status_t err = OK;
+
+    ALOGV("VideoEditorVideoEncoderSource::storeBuffer() begin");
+
+    if( NULL == buffer ) {
+        ALOGV("VideoEditorVideoEncoderSource::storeBuffer : reached EOS");
+        mIsEOS = true;
+    } else {
+        MediaBufferChain* newLink = new MediaBufferChain;
+        newLink->buffer = buffer;
+        newLink->nextLink = NULL;
+        if( NULL != mLastBufferLink ) {
+            mLastBufferLink->nextLink = newLink;
+        } else {
+            mFirstBufferLink = newLink;
+        }
+        mLastBufferLink = newLink;
+        mNbBuffer++;
+    }
+    mBufferCond.signal();
+    ALOGV("VideoEditorVideoEncoderSource::storeBuffer() end");
+    return mNbBuffer;
+}
+
+int32_t VideoEditorVideoEncoderSource::getNumberOfBuffersInQueue() {
+    Mutex::Autolock autolock(mLock);
+    return mNbBuffer;
+}
+
+/**
+ ******************************************************************************
+ * structure VideoEditorVideoEncoder_Context
+ * @brief    This structure defines the context of the StageFright video encoder
+ *           shell
+ ******************************************************************************
+*/
+typedef enum {
+    CREATED   = 0x1,
+    OPENED    = 0x2,
+    STARTED   = 0x4,
+    BUFFERING = 0x8,
+    READING   = 0x10
+} VideoEditorVideoEncoder_State;
+
+typedef struct {
+    VideoEditorVideoEncoder_State     mState;
+    M4ENCODER_Format                  mFormat;
+    M4WRITER_DataInterface*           mWriterDataInterface;
+    M4VPP_apply_fct*                  mPreProcFunction;
+    M4VPP_Context                     mPreProcContext;
+    M4SYS_AccessUnit*                 mAccessUnit;
+    M4ENCODER_Params*                 mCodecParams;
+    M4ENCODER_Header                  mHeader;
+    H264MCS_ProcessEncodedNALU_fct*   mH264NALUPostProcessFct;
+    M4OSA_Context                     mH264NALUPostProcessCtx;
+    M4OSA_UInt32                      mLastCTS;
+    sp<IntelVideoEditorEncoderSource> mEncoderSource;
+    OMXClient                         mClient;
+    sp<MediaSource>                   mEncoder;
+    OMX_COLOR_FORMATTYPE              mEncoderColorFormat;
+    MediaBufferPuller*                mPuller;
+    I420ColorConverter*               mI420ColorConverter;
+
+    uint32_t                          mNbInputFrames;
+    double                            mFirstInputCts;
+    double                            mLastInputCts;
+    uint32_t                          mNbOutputFrames;
+    int64_t                           mFirstOutputCts;
+    int64_t                           mLastOutputCts;
+
+    MediaProfiles *mVideoEditorProfile;
+    int32_t mMaxPrefetchFrames;
+} VideoEditorVideoEncoder_Context;
+
+/********************
+ *      TOOLS       *
+ ********************/
+
+M4OSA_ERR VideoEditorVideoEncoder_getDSI(M4ENCODER_Context pContext,
+        sp<MetaData> metaData) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context*  pEncoderContext = M4OSA_NULL;
+    status_t result = OK;
+    int32_t nbBuffer = 0;
+    int32_t stride = 0;
+    int32_t height = 0;
+    int32_t framerate = 0;
+    int32_t isCodecConfig = 0;
+    size_t size = 0;
+    uint32_t codecFlags = 0;
+    MediaBuffer* inputBuffer = NULL;
+    MediaBuffer* outputBuffer = NULL;
+    sp<IntelVideoEditorEncoderSource> encoderSource = NULL;
+    sp<MediaSource> encoder = NULL;;
+    OMXClient client;
+
+    ALOGV("VideoEditorVideoEncoder_getDSI begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext,       M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != metaData.get(), M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+    VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE);
+
+    // Create the encoder source
+    encoderSource = IntelVideoEditorEncoderSource::Create(metaData);
+    VIDEOEDITOR_CHECK(NULL != encoderSource.get(), M4ERR_STATE);
+
+    // Create Hardware encoder
+
+    encoder = new IntelVideoEditorAVCEncoder(encoderSource,metaData);
+    VIDEOEDITOR_CHECK(NULL != encoder.get(), M4ERR_STATE);
+
+    /**
+     * Send fake frames and retrieve the DSI
+     */
+    // Send a fake frame to the source
+    metaData->findInt32(kKeyStride,     &stride);
+    metaData->findInt32(kKeyHeight,     &height);
+    metaData->findInt32(kKeySampleRate, &framerate);
+
+    result = encoder->start();
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+
+    encoderSource->requestBuffer(&inputBuffer);
+
+    inputBuffer->meta_data()->setInt64(kKeyTime, 0);
+    nbBuffer = encoderSource->storeBuffer(inputBuffer);
+    encoderSource->storeBuffer(NULL); // Signal EOS
+
+    // Call read once to get the DSI
+    result = encoder->read(&outputBuffer, NULL);
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+    VIDEOEDITOR_CHECK(outputBuffer->meta_data()->findInt32(
+        kKeyIsCodecConfig, &isCodecConfig) && isCodecConfig, M4ERR_STATE);
+
+    VIDEOEDITOR_CHECK(M4OSA_NULL == pEncoderContext->mHeader.pBuf, M4ERR_STATE);
+    if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) {
+        // For H264, format the DSI
+        LOGV("outputBuffer->range_offset() = %d, outputBuffer->range_length() = %d",
+            outputBuffer->range_offset(), outputBuffer->range_length());
+        result = buildAVCCodecSpecificData(
+            (uint8_t**)(&(pEncoderContext->mHeader.pBuf)),
+            (size_t*)(&(pEncoderContext->mHeader.Size)),
+            (const uint8_t*)outputBuffer->data() + outputBuffer->range_offset(),
+            outputBuffer->range_length(), encoder->getFormat().get());
+        outputBuffer->release();
+        VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+    } else {
+        // For MPEG4, just copy the DSI
+        pEncoderContext->mHeader.Size =
+            (M4OSA_UInt32)outputBuffer->range_length();
+        SAFE_MALLOC(pEncoderContext->mHeader.pBuf, M4OSA_Int8,
+            pEncoderContext->mHeader.Size, "Encoder header");
+        memcpy((void *)pEncoderContext->mHeader.pBuf,
+            (void *)((M4OSA_MemAddr8)(outputBuffer->data())+outputBuffer->range_offset()),
+            pEncoderContext->mHeader.Size);
+        outputBuffer->release();
+    }
+
+    result = encoder->stop();
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+
+cleanUp:
+    // Destroy the graph
+    if ( encoder != NULL ) { encoder.clear(); }
+    //client.disconnect();
+    if ( encoderSource != NULL ) { encoderSource.clear(); }
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_getDSI no error");
+    } else {
+        ALOGV("VideoEditorVideoEncoder_getDSI ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_getDSI end");
+    return err;
+}
+/********************
+ * ENGINE INTERFACE *
+ ********************/
+
+M4OSA_ERR VideoEditorVideoEncoder_cleanup(M4ENCODER_Context pContext) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorVideoEncoder_cleanup begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+    VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE);
+
+    // Release memory
+    SAFE_FREE(pEncoderContext->mHeader.pBuf);
+    SAFE_FREE(pEncoderContext);
+    pContext = M4OSA_NULL;
+
+cleanUp:
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_cleanup no error");
+    } else {
+        ALOGV("VideoEditorVideoEncoder_cleanup ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_cleanup end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_init(M4ENCODER_Format format,
+        M4ENCODER_Context* pContext,
+        M4WRITER_DataInterface* pWriterDataInterface,
+        M4VPP_apply_fct* pVPPfct, M4VPP_Context pVPPctxt,
+        M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData) {
+
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+    int encoderInput = OMX_COLOR_FormatYUV420Planar;
+
+    ALOGV("VideoEditorVideoEncoder_init begin: format  %d", format);
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pWriterDataInterface, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pVPPfct, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pVPPctxt, M4ERR_PARAMETER);
+
+    // Context allocation & initialization
+    SAFE_MALLOC(pEncoderContext, VideoEditorVideoEncoder_Context, 1,
+        "VideoEditorVideoEncoder");
+    pEncoderContext->mState = CREATED;
+    pEncoderContext->mFormat = format;
+    pEncoderContext->mWriterDataInterface = pWriterDataInterface;
+    pEncoderContext->mPreProcFunction = pVPPfct;
+    pEncoderContext->mPreProcContext = pVPPctxt;
+    pEncoderContext->mPuller = NULL;
+
+    // Get color converter and determine encoder input format
+    pEncoderContext->mI420ColorConverter = new I420ColorConverter;
+    if (pEncoderContext->mI420ColorConverter->isLoaded()) {
+        encoderInput = pEncoderContext->mI420ColorConverter->getEncoderInputFormat();
+    }
+    if (encoderInput == OMX_COLOR_FormatYUV420Planar) {
+        delete pEncoderContext->mI420ColorConverter;
+        pEncoderContext->mI420ColorConverter = NULL;
+    }
+    pEncoderContext->mEncoderColorFormat = (OMX_COLOR_FORMATTYPE)encoderInput;
+    ALOGI("encoder input format = 0x%X\n", encoderInput);
+
+    *pContext = pEncoderContext;
+
+cleanUp:
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_init no error");
+    } else {
+        VideoEditorVideoEncoder_cleanup(pEncoderContext);
+        *pContext = M4OSA_NULL;
+        ALOGV("VideoEditorVideoEncoder_init ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_init end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_init_H263(M4ENCODER_Context* pContext,
+        M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct,
+        M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData)
+        {
+
+    return VideoEditorVideoEncoder_init(M4ENCODER_kH263, pContext,
+        pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData);
+}
+
+
+M4OSA_ERR VideoEditorVideoEncoder_init_MPEG4(M4ENCODER_Context* pContext,
+        M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct,
+        M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData)
+        {
+
+    return VideoEditorVideoEncoder_init(M4ENCODER_kMPEG4, pContext,
+        pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData);
+}
+
+
+M4OSA_ERR VideoEditorVideoEncoder_init_H264(M4ENCODER_Context* pContext,
+        M4WRITER_DataInterface* pWriterDataInterface, M4VPP_apply_fct* pVPPfct,
+        M4VPP_Context pVPPctxt, M4OSA_Void* pExternalAPI, M4OSA_Void* pUserData)
+        {
+
+    return VideoEditorVideoEncoder_init(M4ENCODER_kH264, pContext,
+        pWriterDataInterface, pVPPfct, pVPPctxt, pExternalAPI, pUserData);
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_close(M4ENCODER_Context pContext) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorVideoEncoder_close begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+    VIDEOEDITOR_CHECK(OPENED == pEncoderContext->mState, M4ERR_STATE);
+
+    // Release memory
+    SAFE_FREE(pEncoderContext->mCodecParams);
+
+    // Destroy the graph
+    pEncoderContext->mEncoder.clear();
+   // pEncoderContext->mClient.disconnect();
+    pEncoderContext->mEncoderSource.clear();
+
+    delete pEncoderContext->mPuller;
+    pEncoderContext->mPuller = NULL;
+
+    delete pEncoderContext->mI420ColorConverter;
+    pEncoderContext->mI420ColorConverter = NULL;
+
+    // Set the new state
+    pEncoderContext->mState = CREATED;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_close no error");
+    } else {
+        ALOGV("VideoEditorVideoEncoder_close ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_close end");
+    return err;
+}
+
+
+M4OSA_ERR VideoEditorVideoEncoder_open(M4ENCODER_Context pContext,
+        M4SYS_AccessUnit* pAU, M4OSA_Void* pParams) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+    M4ENCODER_Params* pCodecParams = M4OSA_NULL;
+    status_t result = OK;
+    sp<MetaData> encoderMetadata = NULL;
+    const char* mime = NULL;
+    int32_t iProfile = 0;
+    int32_t iLevel = 0;
+
+    int32_t iFrameRate = 0;
+    uint32_t codecFlags = 0;
+
+    ALOGV(">>> VideoEditorVideoEncoder_open begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pAU,      M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pParams,  M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+    pCodecParams = (M4ENCODER_Params*)pParams;
+    VIDEOEDITOR_CHECK(CREATED == pEncoderContext->mState, M4ERR_STATE);
+
+    // Context initialization
+    pEncoderContext->mAccessUnit = pAU;
+    pEncoderContext->mVideoEditorProfile = MediaProfiles::getInstance();
+    pEncoderContext->mMaxPrefetchFrames =
+        pEncoderContext->mVideoEditorProfile->getVideoEditorCapParamByName(
+        "maxPrefetchYUVFrames");
+
+    // Allocate & initialize the encoding parameters
+    SAFE_MALLOC(pEncoderContext->mCodecParams, M4ENCODER_Params, 1,
+        "VideoEditorVideoEncoder");
+
+
+    pEncoderContext->mCodecParams->InputFormat = pCodecParams->InputFormat;
+    pEncoderContext->mCodecParams->InputFrameWidth =
+        pCodecParams->InputFrameWidth;
+    pEncoderContext->mCodecParams->InputFrameHeight =
+        pCodecParams->InputFrameHeight;
+    pEncoderContext->mCodecParams->FrameWidth = pCodecParams->FrameWidth;
+    pEncoderContext->mCodecParams->FrameHeight = pCodecParams->FrameHeight;
+    pEncoderContext->mCodecParams->Bitrate = pCodecParams->Bitrate;
+    pEncoderContext->mCodecParams->FrameRate = pCodecParams->FrameRate;
+    pEncoderContext->mCodecParams->Format = pCodecParams->Format;
+    pEncoderContext->mCodecParams->videoProfile = pCodecParams->videoProfile;
+    pEncoderContext->mCodecParams->videoLevel= pCodecParams->videoLevel;
+
+    // Check output format consistency and resolution
+    VIDEOEDITOR_CHECK(
+        pEncoderContext->mCodecParams->Format == pEncoderContext->mFormat,
+        M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(0 == pEncoderContext->mCodecParams->FrameWidth  % 16,
+        M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(0 == pEncoderContext->mCodecParams->FrameHeight % 16,
+        M4ERR_PARAMETER);
+
+    /**
+     * StageFright graph building
+     */
+
+    // Create the meta data for the encoder
+    encoderMetadata = new MetaData;
+    switch( pEncoderContext->mCodecParams->Format ) {
+        case M4ENCODER_kH263:
+            mime     = MEDIA_MIMETYPE_VIDEO_H263;
+            break;
+        case M4ENCODER_kMPEG4:
+            mime     = MEDIA_MIMETYPE_VIDEO_MPEG4;
+            break;
+        case M4ENCODER_kH264:
+            mime     = MEDIA_MIMETYPE_VIDEO_AVC;
+            break;
+        default:
+            VIDEOEDITOR_CHECK(!"VideoEncoder_open : incorrect input format",
+                M4ERR_PARAMETER);
+            break;
+    }
+    iProfile = pEncoderContext->mCodecParams->videoProfile;
+    iLevel = pEncoderContext->mCodecParams->videoLevel;
+    ALOGV("Encoder mime %s profile %d, level %d",
+        mime,iProfile, iLevel);
+    ALOGV("Encoder w %d, h %d, bitrate %d, fps %d",
+        pEncoderContext->mCodecParams->FrameWidth,
+        pEncoderContext->mCodecParams->FrameHeight,
+        pEncoderContext->mCodecParams->Bitrate,
+        pEncoderContext->mCodecParams->FrameRate);
+    CHECK(iProfile != 0x7fffffff);
+    CHECK(iLevel != 0x7fffffff);
+
+    encoderMetadata->setCString(kKeyMIMEType, mime);
+    encoderMetadata->setInt32(kKeyVideoProfile, iProfile);
+    //FIXME:
+    // Temp: Do not set the level for Mpeg4 / H.263 Enc
+    // as OMX.Nvidia.mp4.encoder and OMX.Nvidia.h263.encoder
+    // return 0x80001019
+    if (pEncoderContext->mCodecParams->Format == M4ENCODER_kH264) {
+        encoderMetadata->setInt32(kKeyVideoLevel, iLevel);
+    }
+    encoderMetadata->setInt32(kKeyWidth,
+        (int32_t)pEncoderContext->mCodecParams->FrameWidth);
+    encoderMetadata->setInt32(kKeyStride,
+        (int32_t)pEncoderContext->mCodecParams->FrameWidth);
+    encoderMetadata->setInt32(kKeyHeight,
+        (int32_t)pEncoderContext->mCodecParams->FrameHeight);
+    encoderMetadata->setInt32(kKeySliceHeight,
+        (int32_t)pEncoderContext->mCodecParams->FrameHeight);
+
+    switch( pEncoderContext->mCodecParams->FrameRate ) {
+        case M4ENCODER_k5_FPS:    iFrameRate = 5;  break;
+        case M4ENCODER_k7_5_FPS:  iFrameRate = 8;  break;
+        case M4ENCODER_k10_FPS:   iFrameRate = 10; break;
+        case M4ENCODER_k12_5_FPS: iFrameRate = 13; break;
+        case M4ENCODER_k15_FPS:   iFrameRate = 15; break;
+        case M4ENCODER_k20_FPS:   iFrameRate = 20; break;
+        case M4ENCODER_k25_FPS:   iFrameRate = 25; break;
+        case M4ENCODER_k30_FPS:   iFrameRate = 30; break;
+        case M4ENCODER_kVARIABLE_FPS:
+            iFrameRate = 30;
+            ALOGI("Frame rate set to M4ENCODER_kVARIABLE_FPS: set to 30");
+          break;
+        case M4ENCODER_kUSE_TIMESCALE:
+            iFrameRate = 30;
+            ALOGI("Frame rate set to M4ENCODER_kUSE_TIMESCALE:  set to 30");
+            break;
+
+        default:
+            VIDEOEDITOR_CHECK(!"VideoEncoder_open:incorrect framerate",
+                M4ERR_STATE);
+            break;
+    }
+    encoderMetadata->setInt32(kKeyFrameRate, iFrameRate);
+    encoderMetadata->setInt32(kKeyBitRate,
+        (int32_t)pEncoderContext->mCodecParams->Bitrate);
+    encoderMetadata->setInt32(kKeyIFramesInterval, 1);
+
+    encoderMetadata->setInt32(kKeyColorFormat,
+        pEncoderContext->mEncoderColorFormat);
+
+    if (pEncoderContext->mCodecParams->Format != M4ENCODER_kH263) {
+        // Get the encoder DSI
+        err = VideoEditorVideoEncoder_getDSI(pEncoderContext, encoderMetadata);
+        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+    }
+
+    // Create the encoder source
+    pEncoderContext->mEncoderSource = IntelVideoEditorEncoderSource::Create(
+        encoderMetadata);
+    VIDEOEDITOR_CHECK(
+        NULL != pEncoderContext->mEncoderSource.get(), M4ERR_STATE);
+
+    // Create the HW Encoder
+    if (pEncoderContext->mCodecParams->Format == M4ENCODER_kH264) {
+        pEncoderContext->mEncoder = new IntelVideoEditorAVCEncoder(
+        pEncoderContext->mEncoderSource, encoderMetadata);
+    } else if (pEncoderContext->mCodecParams->Format == M4ENCODER_kH263) {
+        pEncoderContext->mEncoder = new IntelVideoEditorH263Encoder(
+        pEncoderContext->mEncoderSource, encoderMetadata);
+    }
+    VIDEOEDITOR_CHECK(NULL != pEncoderContext->mEncoder.get(), M4ERR_STATE);
+    ALOGV("VideoEditorVideoEncoder_open : DONE");
+    pEncoderContext->mPuller = new MediaBufferPuller(
+        pEncoderContext->mEncoder);
+
+    // Set the new state
+    pEncoderContext->mState = OPENED;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_open no error");
+    } else {
+        VideoEditorVideoEncoder_close(pEncoderContext);
+        ALOGV("VideoEditorVideoEncoder_open ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_open end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_processInputBuffer(
+        M4ENCODER_Context pContext, M4OSA_Double Cts,
+        M4OSA_Bool bReachedEOS) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+    M4VIFI_ImagePlane pOutPlane[3];
+    MediaBuffer* buffer = NULL;
+    int32_t nbBuffer = 0;
+
+    ALOGV("VideoEditorVideoEncoder_processInputBuffer begin: cts  %f", Cts);
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+    pOutPlane[0].pac_data = M4OSA_NULL;
+    pOutPlane[1].pac_data = M4OSA_NULL;
+    pOutPlane[2].pac_data = M4OSA_NULL;
+
+    if ( M4OSA_FALSE == bReachedEOS ) {
+        M4OSA_UInt32 sizeY = pEncoderContext->mCodecParams->FrameWidth *
+            pEncoderContext->mCodecParams->FrameHeight;
+        M4OSA_UInt32 sizeU = sizeY >> 2;
+        M4OSA_UInt32 size  = sizeY + 2*sizeU;
+        M4OSA_UInt8* pData = M4OSA_NULL;
+        buffer = new MediaBuffer((size_t)size);
+        pData = (M4OSA_UInt8*)buffer->data() + buffer->range_offset();
+
+        // Prepare the output image for pre-processing
+        pOutPlane[0].u_width   = pEncoderContext->mCodecParams->FrameWidth;
+        pOutPlane[0].u_height  = pEncoderContext->mCodecParams->FrameHeight;
+        pOutPlane[0].u_topleft = 0;
+        pOutPlane[0].u_stride  = pOutPlane[0].u_width;
+        pOutPlane[1].u_width   = pOutPlane[0].u_width/2;
+        pOutPlane[1].u_height  = pOutPlane[0].u_height/2;
+        pOutPlane[1].u_topleft = 0;
+        pOutPlane[1].u_stride  = pOutPlane[0].u_stride/2;
+        pOutPlane[2].u_width   = pOutPlane[1].u_width;
+        pOutPlane[2].u_height  = pOutPlane[1].u_height;
+        pOutPlane[2].u_topleft = 0;
+        pOutPlane[2].u_stride  = pOutPlane[1].u_stride;
+
+        pOutPlane[0].pac_data = pData;
+        pOutPlane[1].pac_data = pData + sizeY;
+        pOutPlane[2].pac_data = pData + sizeY + sizeU;
+
+        // Apply pre-processing
+        err = pEncoderContext->mPreProcFunction(
+            pEncoderContext->mPreProcContext, M4OSA_NULL, pOutPlane);
+        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+        // Convert MediaBuffer to the encoder input format if necessary
+        if (pEncoderContext->mI420ColorConverter) {
+            I420ColorConverter* converter = pEncoderContext->mI420ColorConverter;
+            int actualWidth = pEncoderContext->mCodecParams->FrameWidth;
+            int actualHeight = pEncoderContext->mCodecParams->FrameHeight;
+
+            int encoderWidth, encoderHeight;
+            ARect encoderRect;
+            int encoderBufferSize;
+
+            if (converter->getEncoderInputBufferInfo(
+                actualWidth, actualHeight,
+                &encoderWidth, &encoderHeight,
+                &encoderRect, &encoderBufferSize) == 0) {
+
+                MediaBuffer* newBuffer;
+                pEncoderContext->mEncoderSource->requestBuffer(&newBuffer);
+                if (converter->convertI420ToEncoderInput(
+                    pData,  // srcBits
+                    actualWidth, actualHeight,
+                    encoderWidth, encoderHeight,
+                    encoderRect,
+                    (uint8_t*)newBuffer->data() + newBuffer->range_offset()) < 0) {
+                    ALOGE("convertI420ToEncoderInput failed");
+                }
+
+                // switch to new buffer
+                buffer->release();
+                buffer = newBuffer;
+            }
+        }
+
+        // Set the metadata
+        buffer->meta_data()->setInt64(kKeyTime, (int64_t)(Cts*1000));
+    }
+
+    // Push the buffer to the source, a NULL buffer, notifies the source of EOS
+    nbBuffer = pEncoderContext->mEncoderSource->storeBuffer(buffer);
+
+cleanUp:
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_processInputBuffer error 0x%X", err);
+    } else {
+        if( NULL != buffer ) {
+            buffer->release();
+        }
+        ALOGV("VideoEditorVideoEncoder_processInputBuffer ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_processInputBuffer end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_processOutputBuffer(
+        M4ENCODER_Context pContext, MediaBuffer* buffer) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+    M4OSA_UInt32 Cts = 0;
+    uint8_t *data;
+    uint32_t length;
+    int32_t i32Tmp = 0;
+    int64_t i64Tmp = 0;
+    status_t result = OK;
+    LOGV("VideoEditorVideoEncoder_processOutputBuffer begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != buffer,   M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+
+    // Process the returned AU
+    if ( 0 == buffer->range_length() ) {
+        // Encoder has no data yet, nothing unusual
+        LOGV("VideoEditorVideoEncoder_processOutputBuffer : buffer is empty");
+        goto cleanUp;
+    }
+    VIDEOEDITOR_CHECK(0 == ((M4OSA_UInt32)buffer->data())%4, M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(buffer->meta_data().get(), M4ERR_PARAMETER);
+    if ( buffer->meta_data()->findInt32(kKeyIsCodecConfig, &i32Tmp) && i32Tmp ){
+        LOGV("VideoEditorVideoEncoder_processOutputBuffer DSI %d",buffer->range_length());
+        removeAVCCodecSpecificData(&data,&length,(const uint8_t*) buffer->data(),buffer->range_length(),NULL);
+        buffer->set_range(buffer->range_offset() + length, buffer->range_length() - length);
+    }
+
+    // Check the CTS
+    VIDEOEDITOR_CHECK(buffer->meta_data()->findInt64(kKeyTime, &i64Tmp),
+        M4ERR_STATE);
+
+    pEncoderContext->mNbOutputFrames++;
+    if ( 0 > pEncoderContext->mFirstOutputCts ) {
+        pEncoderContext->mFirstOutputCts = i64Tmp;
+    }
+    pEncoderContext->mLastOutputCts = i64Tmp;
+
+    Cts = (M4OSA_Int32)(i64Tmp/1000);
+    LOGV("[TS_CHECK] VI/ENC WRITE frame %d @ %lld -> %d (last %d)",
+        pEncoderContext->mNbOutputFrames, i64Tmp, Cts,
+        pEncoderContext->mLastCTS);
+    if ( Cts < pEncoderContext->mLastCTS ) {
+        LOGV("VideoEncoder_processOutputBuffer WARNING : Cts is going "
+        "backwards %d < %d", Cts, pEncoderContext->mLastCTS);
+        goto cleanUp;
+    }
+    LOGV("VideoEditorVideoEncoder_processOutputBuffer : %d %d",
+        Cts, pEncoderContext->mLastCTS);
+
+    // Retrieve the AU container
+    err = pEncoderContext->mWriterDataInterface->pStartAU(
+        pEncoderContext->mWriterDataInterface->pWriterContext,
+        pEncoderContext->mAccessUnit->stream->streamID,
+        pEncoderContext->mAccessUnit);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+    // Format the AU
+    VIDEOEDITOR_CHECK(
+        buffer->range_length() <= pEncoderContext->mAccessUnit->size,
+        M4ERR_PARAMETER);
+    // Remove H264 AU start code
+    if ( M4ENCODER_kH264 == pEncoderContext->mFormat ) {
+        if (!memcmp((const uint8_t *)buffer->data() + \
+                buffer->range_offset(), "\x00\x00\x00\x01", 4) ) {
+            buffer->set_range(buffer->range_offset() + 4,
+                buffer->range_length() - 4);
+        }
+    }
+
+    if ( (M4ENCODER_kH264 == pEncoderContext->mFormat) &&
+        (M4OSA_NULL != pEncoderContext->mH264NALUPostProcessFct) ) {
+    // H264 trimming case, NALU post processing is needed
+        M4OSA_Int32 outputSize = pEncoderContext->mAccessUnit->size;
+        err = pEncoderContext->mH264NALUPostProcessFct(
+            pEncoderContext->mH264NALUPostProcessCtx,
+            (M4OSA_UInt8*)buffer->data()+buffer->range_offset(),
+            buffer->range_length(),
+            (M4OSA_UInt8*)pEncoderContext->mAccessUnit->dataAddress,
+            &outputSize);
+        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+        pEncoderContext->mAccessUnit->size = (M4OSA_UInt32)outputSize;
+    } else {
+        // The AU can just be copied
+        memcpy((void *)pEncoderContext->mAccessUnit->\
+            dataAddress, (void *)((M4OSA_MemAddr8)(buffer->data())+buffer->\
+            range_offset()), buffer->range_length());
+        pEncoderContext->mAccessUnit->size =
+            (M4OSA_UInt32)buffer->range_length();
+    }
+
+    if ( buffer->meta_data()->findInt32(kKeyIsSyncFrame,&i32Tmp) && i32Tmp){
+        pEncoderContext->mAccessUnit->attribute = AU_RAP;
+    } else {
+        pEncoderContext->mAccessUnit->attribute = AU_P_Frame;
+    }
+    pEncoderContext->mLastCTS = Cts;
+    pEncoderContext->mAccessUnit->CTS = Cts;
+    pEncoderContext->mAccessUnit->DTS = Cts;
+
+    LOGV("VideoEditorVideoEncoder_processOutputBuffer: AU @ 0x%X 0x%X %d %d",
+        pEncoderContext->mAccessUnit->dataAddress,
+        *pEncoderContext->mAccessUnit->dataAddress,
+        pEncoderContext->mAccessUnit->size,
+        pEncoderContext->mAccessUnit->CTS);
+
+    // Write the AU
+    err = pEncoderContext->mWriterDataInterface->pProcessAU(
+        pEncoderContext->mWriterDataInterface->pWriterContext,
+        pEncoderContext->mAccessUnit->stream->streamID,
+        pEncoderContext->mAccessUnit);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        LOGV("VideoEditorVideoEncoder_processOutputBuffer no error");
+    } else {
+        if (pEncoderContext != NULL) {
+            SAFE_FREE(pEncoderContext->mHeader.pBuf);
+            pEncoderContext->mHeader.Size = 0;
+        }
+        LOGV("VideoEditorVideoEncoder_processOutputBuffer ERROR 0x%X", err);
+    }
+    LOGV("VideoEditorVideoEncoder_processOutputBuffer end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_encode(M4ENCODER_Context pContext,
+        M4VIFI_ImagePlane* pInPlane, M4OSA_Double Cts,
+        M4ENCODER_FrameMode FrameMode) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+    status_t result = OK;
+    MediaBuffer* outputBuffer = NULL;
+
+    ALOGV("VideoEditorVideoEncoder_encode 0x%X %f %d", pInPlane, Cts, FrameMode);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+    if ( STARTED == pEncoderContext->mState ) {
+        pEncoderContext->mState = BUFFERING;
+    }
+    VIDEOEDITOR_CHECK(
+        (BUFFERING | READING) & pEncoderContext->mState, M4ERR_STATE);
+
+    pEncoderContext->mNbInputFrames++;
+    if ( 0 > pEncoderContext->mFirstInputCts ) {
+        pEncoderContext->mFirstInputCts = Cts;
+    }
+    pEncoderContext->mLastInputCts = Cts;
+
+    ALOGV("VideoEditorVideoEncoder_encode 0x%X %d %f (%d)", pInPlane, FrameMode,
+        Cts, pEncoderContext->mLastCTS);
+
+    // Push the input buffer to the encoder source
+    err = VideoEditorVideoEncoder_processInputBuffer(pEncoderContext, Cts,
+        M4OSA_FALSE);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+    // Notify the source in case of EOS
+    if ( M4ENCODER_kLastFrame == FrameMode ) {
+        err = VideoEditorVideoEncoder_processInputBuffer(
+            pEncoderContext, 0, M4OSA_TRUE);
+        VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+    }
+
+    if ( BUFFERING == pEncoderContext->mState ) {
+        // Prefetch is complete, start reading
+        pEncoderContext->mState = READING;
+    }
+    // Read
+    while (1)  {
+        MediaBuffer *outputBuffer =
+                pEncoderContext->mPuller->getBufferNonBlocking();
+
+        if (outputBuffer == NULL) {
+            break;
+        } else {
+            // Provide the encoded AU to the writer
+            err = VideoEditorVideoEncoder_processOutputBuffer(pEncoderContext,
+                outputBuffer);
+            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+            pEncoderContext->mPuller->putBuffer(outputBuffer);
+        }
+    }
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_encode no error");
+    } else {
+        ALOGV("VideoEditorVideoEncoder_encode ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_encode end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_start(M4ENCODER_Context pContext) {
+    M4OSA_ERR                  err             = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+    status_t                   result          = OK;
+
+    ALOGV("VideoEditorVideoEncoder_start begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+    VIDEOEDITOR_CHECK(OPENED == pEncoderContext->mState, M4ERR_STATE);
+
+    pEncoderContext->mNbInputFrames  = 0;
+    pEncoderContext->mFirstInputCts  = -1.0;
+    pEncoderContext->mLastInputCts   = -1.0;
+    pEncoderContext->mNbOutputFrames = 0;
+    pEncoderContext->mFirstOutputCts = -1;
+    pEncoderContext->mLastOutputCts  = -1;
+
+    result = pEncoderContext->mEncoder->start();
+    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
+
+    pEncoderContext->mPuller->start();
+
+    // Set the new state
+    pEncoderContext->mState = STARTED;
+
+cleanUp:
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_start no error");
+    } else {
+        ALOGV("VideoEditorVideoEncoder_start ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_start end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_stop(M4ENCODER_Context pContext) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+    MediaBuffer* outputBuffer = NULL;
+    status_t result = OK;
+
+    ALOGV("VideoEditorVideoEncoder_stop begin");
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+
+    // Send EOS again to make sure the source doesn't block.
+    err = VideoEditorVideoEncoder_processInputBuffer(pEncoderContext, 0,
+        M4OSA_TRUE);
+    VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+    // Process the remaining buffers if necessary
+    if ( (BUFFERING | READING) & pEncoderContext->mState ) {
+        while (1)  {
+            MediaBuffer *outputBuffer =
+                pEncoderContext->mPuller->getBufferBlocking();
+
+            if (outputBuffer == NULL) break;
+
+            err = VideoEditorVideoEncoder_processOutputBuffer(
+                pEncoderContext, outputBuffer);
+            VIDEOEDITOR_CHECK(M4NO_ERROR == err, err);
+
+            pEncoderContext->mPuller->putBuffer(outputBuffer);
+        }
+
+        pEncoderContext->mState = STARTED;
+    }
+
+    // Stop the graph module if necessary
+    if ( STARTED == pEncoderContext->mState ) {
+        pEncoderContext->mPuller->stop();
+        pEncoderContext->mEncoder->stop();
+        pEncoderContext->mState = OPENED;
+    }
+
+    if (pEncoderContext->mNbInputFrames != pEncoderContext->mNbOutputFrames) {
+        ALOGW("Some frames were not encoded: input(%d) != output(%d)",
+            pEncoderContext->mNbInputFrames, pEncoderContext->mNbOutputFrames);
+    }
+
+cleanUp:
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_stop no error");
+    } else {
+        ALOGV("VideoEditorVideoEncoder_stop ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_stop end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_regulBitRate(M4ENCODER_Context pContext) {
+    ALOGW("regulBitRate is not implemented");
+    return M4NO_ERROR;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_setOption(M4ENCODER_Context pContext,
+        M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorVideoEncoder_setOption start optionID 0x%X", optionID);
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+
+    switch( optionID ) {
+        case M4ENCODER_kOptionID_SetH264ProcessNALUfctsPtr:
+            pEncoderContext->mH264NALUPostProcessFct =
+                (H264MCS_ProcessEncodedNALU_fct*)optionValue;
+            break;
+        case M4ENCODER_kOptionID_H264ProcessNALUContext:
+            pEncoderContext->mH264NALUPostProcessCtx =
+                (M4OSA_Context)optionValue;
+            break;
+        default:
+            ALOGV("VideoEditorVideoEncoder_setOption: unsupported optionId 0x%X",
+                optionID);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID);
+            break;
+    }
+
+cleanUp:
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_setOption no error");
+    } else {
+        ALOGV("VideoEditorVideoEncoder_setOption ERROR 0x%X", err);
+    }
+    ALOGV("VideoEditorVideoEncoder_setOption end");
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_getOption(M4ENCODER_Context pContext,
+        M4OSA_UInt32 optionID, M4OSA_DataOption optionValue) {
+    M4OSA_ERR err = M4NO_ERROR;
+    VideoEditorVideoEncoder_Context* pEncoderContext = M4OSA_NULL;
+
+    ALOGV("VideoEditorVideoEncoder_getOption begin optinId 0x%X", optionID);
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pContext, M4ERR_PARAMETER);
+    pEncoderContext = (VideoEditorVideoEncoder_Context*)pContext;
+
+    switch( optionID ) {
+        case M4ENCODER_kOptionID_EncoderHeader:
+            VIDEOEDITOR_CHECK(
+                    M4OSA_NULL != pEncoderContext->mHeader.pBuf, M4ERR_STATE);
+            *(M4ENCODER_Header**)optionValue = &(pEncoderContext->mHeader);
+            break;
+        default:
+            ALOGV("VideoEditorVideoEncoder_getOption: unsupported optionId 0x%X",
+                optionID);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_BAD_OPTION_ID);
+            break;
+    }
+
+cleanUp:
+    if ( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_getOption no error");
+    } else {
+        ALOGV("VideoEditorVideoEncoder_getOption ERROR 0x%X", err);
+    }
+    return err;
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_getInterface(M4ENCODER_Format format,
+        M4ENCODER_Format* pFormat,
+        M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){
+    M4OSA_ERR err = M4NO_ERROR;
+
+    // Input parameters check
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pFormat,           M4ERR_PARAMETER);
+    VIDEOEDITOR_CHECK(M4OSA_NULL != pEncoderInterface, M4ERR_PARAMETER);
+
+    ALOGV("VideoEditorVideoEncoder_getInterface begin 0x%x 0x%x %d", pFormat,
+        pEncoderInterface, mode);
+
+    SAFE_MALLOC(*pEncoderInterface, M4ENCODER_GlobalInterface, 1,
+        "VideoEditorVideoEncoder");
+
+    *pFormat = format;
+
+    switch( format ) {
+        case M4ENCODER_kH263:
+            {
+                (*pEncoderInterface)->pFctInit =
+                    VideoEditorVideoEncoder_init_H263;
+                break;
+            }
+        case M4ENCODER_kMPEG4:
+            {
+                (*pEncoderInterface)->pFctInit =
+                    VideoEditorVideoEncoder_init_MPEG4;
+                break;
+            }
+        case M4ENCODER_kH264:
+            {
+                (*pEncoderInterface)->pFctInit =
+                    VideoEditorVideoEncoder_init_H264;
+                break;
+            }
+        default:
+            ALOGV("VideoEditorVideoEncoder_getInterface : unsupported format %d",
+                format);
+            VIDEOEDITOR_CHECK(M4OSA_FALSE, M4ERR_PARAMETER);
+        break;
+    }
+    (*pEncoderInterface)->pFctOpen         = VideoEditorVideoEncoder_open;
+    (*pEncoderInterface)->pFctStart        = VideoEditorVideoEncoder_start;
+    (*pEncoderInterface)->pFctStop         = VideoEditorVideoEncoder_stop;
+    (*pEncoderInterface)->pFctPause        = M4OSA_NULL;
+    (*pEncoderInterface)->pFctResume       = M4OSA_NULL;
+    (*pEncoderInterface)->pFctClose        = VideoEditorVideoEncoder_close;
+    (*pEncoderInterface)->pFctCleanup      = VideoEditorVideoEncoder_cleanup;
+    (*pEncoderInterface)->pFctRegulBitRate =
+        VideoEditorVideoEncoder_regulBitRate;
+    (*pEncoderInterface)->pFctEncode       = VideoEditorVideoEncoder_encode;
+    (*pEncoderInterface)->pFctSetOption    = VideoEditorVideoEncoder_setOption;
+    (*pEncoderInterface)->pFctGetOption    = VideoEditorVideoEncoder_getOption;
+
+cleanUp:
+    if( M4NO_ERROR == err ) {
+        ALOGV("VideoEditorVideoEncoder_getInterface no error");
+    } else {
+        *pEncoderInterface = M4OSA_NULL;
+        ALOGV("VideoEditorVideoEncoder_getInterface ERROR 0x%X", err);
+    }
+    return err;
+}
+
+extern "C" {
+
+M4OSA_ERR VideoEditorVideoEncoder_getInterface_H263(M4ENCODER_Format* pFormat,
+        M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){
+    LOGI("VideoEditorVideoEncoder_getInterface_H263: Intel Version");
+    return VideoEditorVideoEncoder_getInterface(M4ENCODER_kH263, pFormat,
+            pEncoderInterface, mode);
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_getInterface_MPEG4(M4ENCODER_Format* pFormat,
+        M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){
+    LOGI("VideoEditorVideoEncoder_getInterface_MPEG4: Intel Version");
+    return VideoEditorVideoEncoder_getInterface(M4ENCODER_kMPEG4, pFormat,
+           pEncoderInterface, mode);
+}
+
+M4OSA_ERR VideoEditorVideoEncoder_getInterface_H264(M4ENCODER_Format* pFormat,
+        M4ENCODER_GlobalInterface** pEncoderInterface, M4ENCODER_OpenMode mode){
+    LOGI("VideoEditorVideoEncoder_getInterface_H264: Intel Version");
+    return VideoEditorVideoEncoder_getInterface(M4ENCODER_kH264, pFormat,
+           pEncoderInterface, mode);
+
+}
+
+}  // extern "C"
+
+}  // namespace android