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;
}
Exemplo n.º 2
0
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;
}
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;
}
Exemplo n.º 4
0
/**
 ****************************************************************************
 * @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;
}
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);

    LOGV("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 {
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;
}
Exemplo n.º 7
0
/**
 *******************************************************************************
 * @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;
}
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 = new MediaBuffer(encoderBufferSize);

                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));
    }
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 = VideoEditorVideoEncoderSource::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 */
    pEncoderContext->mEncoder = OMXCodec::Create(
        pEncoderContext->mClient.interface(), encoderMetadata, true,
        pEncoderContext->mEncoderSource, NULL, codecFlags);
    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_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<VideoEditorVideoEncoderSource> 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 = VideoEditorVideoEncoderSource::Create(metaData);
    VIDEOEDITOR_CHECK(NULL != encoderSource.get(), M4ERR_STATE);

    // Connect to the OMX client
    result = client.connect();
    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);

    // Create the OMX codec
    // VIDEOEDITOR_FORCECODEC MUST be defined here
    codecFlags |= OMXCodec::VIDEOEDITOR_FORCECODEC;
    encoder = OMXCodec::Create(client.interface(), metaData, true,
        encoderSource, NULL, codecFlags);
    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);
    size = (size_t)(stride*height*3)/2;
    inputBuffer = new MediaBuffer(size);
    inputBuffer->meta_data()->setInt64(kKeyTime, 0);
    nbBuffer = encoderSource->storeBuffer(inputBuffer);
    encoderSource->storeBuffer(NULL); // Signal EOS

    // Call read once to get the DSI
    result = encoder->start();;
    VIDEOEDITOR_CHECK(OK == result, M4ERR_STATE);
    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
        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;
}