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 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; }
/** **************************************************************************** * @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; }
/** ******************************************************************************* * @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; }