android c++ android-ndk stagefright openmax

Android: MPEG4Writer no se puede iniciar al usar OMXCodec como MediaSource



c++ android-ndk (2)

MPEG4Writer codificar un video desde un buffer de matriz de bytes y para hacerlo estoy usando MPEG4Writer API desde código nativo.

OMXCodec mi clase MediaSource personalizada para proporcionar los datos y la OMXCodec con OMXCodec para dársela a MPEG4Writer :

sp<MediaSource> mVideoEncoder = OMXCodec::Create(client.interface(), omxEncMeta, true, mVideoOutSource); mVideoEncoder->start();

mVideoOutSource es mi clase MediaSource personalizada, omxEncMeta es la siguiente:

int32_t colorFormat = OMX_COLOR_FormatYUV420SemiPlanar; int32_t width = 480; int32_t height = 360; int32_t frameRate = 24; int32_t bitRate = 500 * 1024; int32_t iFrameInterval = 1; sp<MetaData> omxEncMeta = new MetaData; omxEncMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); omxEncMeta->setInt32(kKeyColorFormat, colorFormat); omxEncMeta->setInt32(kKeyWidth, width); omxEncMeta->setInt32(kKeyHeight, height); omxEncMeta->setInt32(kKeyStride, width); omxEncMeta->setInt32(kKeySliceHeight, height); omxEncMeta->setInt32(kKeyFrameRate, frameRate); omxEncMeta->setInt32(kKeySampleRate, frameRate); omxEncMeta->setInt32(kKeyBitRate, bitRate); omxEncMeta->setInt32(kKeyIFramesInterval, iFrameInterval);

pero cuando llamo al método start() , devuelve el código de error UNKNOWN_ERROR .

En cambio, si trato de darle a MPEG4Writer directamente mi MediaSource personalizado (sin envolverlo con OMXCodec se inicia con éxito pero finalmente dejará de grabar con el error Missing codec specific data (después de 12 fotogramas), y creo que es porque mi costumbre MediaSource proporciona solo información sobre los marcos reales, pero nada sobre el formato del códec.

Estoy seguro de que me falta algo con OMXCodec , pero no puedo entender qué ... ¿Hay alguien que pueda proporcionarme un ejemplo MediaSource de un MediaSource personalizado para la codificación? ¿O darme algunas pistas sobre por qué esto no funciona en absoluto?
Si necesita más información, solo pregunte, ¡gracias!

EDITAR : Estoy desarrollando esto contra API 14 así que no me sugiera que use MediaCodec desde API 16 :)

EDITAR : Así es como estoy comenzando MPEG4Writer :

int32_t outputFormat = OUTPUT_FORMAT_MPEG_4; int64_t startTimeUs = systemTime() / 1000; int32_t totalBitRate = bitRate; sp<MetaData> meta = new MetaData; meta->setInt64(kKeyTime, startTimeUs); meta->setInt32(kKeyFileType, outputFormat); meta->setInt32(kKeyBitRate, totalBitRate); sp<MPEG4Writer> mWriter = new MPEG4Writer("/sdcard/encode_manual.mp4"); mWriter->addSource(mVideoEncoder); status_t error = mWriter->start(meta.get()); if (error != OK) { LOGE("Writer NOT started! %x", error); } else { LOGI("Writer started!"); }

Este es el resultado de logcat ( adb logcat OMXClient:V OMXCodec:V *:W ):

W/ResourceType( 370): Skipping entry 0x7f04002f in package table 0 because it is not complex! E/ ( 4127): Can''t open file for reading E/ ( 4127): Can''t open file for reading E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): omx_video(): Inside Constructor() E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): omx_venc(): Inside component_init() E/OMX-VENC-720p( 155): bool venc_dev::venc_validate_profile_level(OMX_U32*, OMX_U32*): Returning with eProfile = 1Level = 4 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): bool venc_dev::venc_open(OMX_U32)(): Init Profile/Level setting success E/OMX-VENC-720p( 155): vidc.venc.debug.sliceinfo value is 0 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): Component_init return value = 0x0 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): WARNING: Requested i/p bufsize[40960],Driver''s updated i/p bufsize = 262144 E/OMX-VENC-720p( 155): bool venc_dev::venc_validate_profile_level(OMX_U32*, OMX_U32*): Returning with eProfile = 1Level = 256 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): bool venc_dev::venc_set_param(void*, OMX_INDEXTYPE)(): Profile/Level setting success E/OMX-VENC-720p( 155): bool venc_dev::venc_validate_profile_level(OMX_U32*, OMX_U32*): Returning with eProfile = 1Level = 64 E/OMX-VENC-720p( 155): Calling set level (Framerate) with 15 E/OMX-VENC-720p( 155): bool venc_dev::venc_validate_profile_level(OMX_U32*, OMX_U32*): Returning with eProfile = 1Level = 64 E/OMX-VENC-720p( 155): Calling set level (Bitrate) with 15 E/OMX-VENC-720p( 155): get_parameter: OMX_IndexParamVideoProfileLevelQuerySupported for Input port returned Profile:1, Level:2048 E/OMX-VENC-720p( 155): Profile/Level set equal to 1/64 E/OMX-VENC-720p( 155): bool venc_dev::venc_validate_profile_level(OMX_U32*, OMX_U32*): Returning with eProfile = 1Level = 64 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): venc_set_intra_period: nPFrames = 25 nBFrames = 0 E/OMX-VENC-720p( 155): bool venc_dev::venc_validate_profile_level(OMX_U32*, OMX_U32*): Returning with eProfile = 1Level = 64 E/OMX-VENC-720p( 155): Calling set level (Bitrate) with 15 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): allocate_input_buffer():: E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): allocate_input_buffer():: E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): allocate_input_buffer():: E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): allocate_output_buffer():: E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): actual cnt = 5 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): allocate_output_buffer():: E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): actual cnt = 5 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): allocate_output_buffer():: E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): actual cnt = 5 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): allocate_output_buffer():: E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): actual cnt = 5 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): allocate_output_buffer():: E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): actual cnt = 5 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): unsigned int venc_dev::venc_start()(): Check Profile/Level set in driver before start E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): unsigned int venc_dev::venc_start()(): Driver Profile[3]/Level[15] successfully SET E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): ENC_CONFIG: Codec: 2, Profile 3, level : 15 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): ENC_CONFIG: Width: 480, Height:360, Fps: 25 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): ENC_CONFIG: Bitrate: 512000, RC: 3, I-Period: 25 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): ENC_CONFIG: qpI: 0, qpP: 80, qpb: 0 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): ENC_CONFIG: VOP_Resolution: 4343391, Slice-Mode: 1, Slize_Size: 0 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): ENC_CONFIG: EntropyMode: 1, CabacModel: 0 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): ENC_CONFIG: DB-Mode: 2, alpha: 0, Beta: 0 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): ENC_CONFIG: IntraMB/Frame: 18, HEC: 843271745 E/OMX-VENC-720p( 155): Width 480, Height 360, w_round 480, h_round 368, yuv_size 294912 alignment 8192 count 2 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): Allocated virt:0x4432e000, FD: 145 of size 294912 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): Allocated virt:0x4432e000, FD: 145 of size 294912 at index: 0 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): Allocated virt:0x44895000, FD: 147 of size 294912 E/OMX-VENC-720p( 155): E/OMX-VENC-720p( 155): Allocated virt:0x44895000, FD: 147 of size 294912 at index: 1 E/TestEnc-JNI( 4127): Writer NOT started! 80000000


Acabo de descubrir mi problema ( tonto ): estaba llamando a start() en mVideoEncoder (la instancia de OMXCodec ) antes de llamar a start() en MPEG4Writer , y esto daba el UNKNOWN_ERROR .

Lo resolví llamando a start() solo en la instancia de MPEG4Writer .


Hay un error que creo que es importante:

omxEncMeta->setInt32(kKeyBitRate, frameRate); // should set bitrate, 24 is too small

además

omxEncMeta->setInt32(kKeySampleRate, frameRate); // i don''t think is of any use

Entonces: asegúrate de que tu fuente devuelve esto

virtual sp<MetaData> getFormat() { sp<MetaData> meta = new MetaData; meta->setInt32(kKeyWidth, mWidth); meta->setInt32(kKeyHeight, mHeight); meta->setInt32(kKeyColorFormat, mColorFormat); meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW); return meta; }

El MediaBuffer que devuelve desde la fuente debe tener el tamaño correcto: 480 * 360 * 4 (creo que ese es el caso).

Debe proporcionar la salida de adb logcat: adb.exe logcat OMXClient: V OMXCodec: V *: W