Android Media Codec视频解码

时间:2012-11-26 15:07:41

标签: android video media codec decoding

这是我的第一个问题,如果我错过了什么,请告诉我!

使用Android API 16的新媒体编解码器实现来尝试解码视频,以便我可以发送要应用为纹理的帧(纹理部分已经完成)。所以我在堆栈的帮助下提出了以下代码,但在runOutputBuffer() outputBufIndex我的-1回来了-1(或者在我提供public MediaDecoder( BPRenderView bpview ) { surface = bpview; extractor = new MediaExtractor( ); extractor.setDataSource( filePath ); format = extractor.getTrackFormat( 0 ); mime = format.getString( MediaFormat.KEY_MIME ); createDecoder( ); runInputBuffer( ); } public void createDecoder( ) { codec = MediaCodec.createDecoderByType( "video/avc" ); // format =extractor.getTrackFormat( 0 ); Log.d( LOG_TAG, "Track Format: " + mime ); // format.setInteger( MediaFormat.KEY_BIT_RATE, 125000 ); // format.setInteger( MediaFormat.KEY_FRAME_RATE, 15 ); // format.setInteger( MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar ); // format.setInteger( MediaFormat.KEY_I_FRAME_INTERVAL, 5 ); codec.configure( format, null, null, 0 ); codec.start( ); codecInputBuffers = codec.getInputBuffers( ); codecOutputBuffers = codec.getOutputBuffers( ); extractor.selectTrack( 0 ); } public void runInputBuffer( ) { // This should take in the entire video and put it in the input buffer int inputBufIndex = codec.dequeueInputBuffer( -1 ); if( inputBufIndex >= 0 ) { ByteBuffer dstBuf = codecInputBuffers[ inputBufIndex ]; int sampleSize = extractor.readSampleData( dstBuf, 0 ); Log.d( "Sample Size", String.valueOf( sampleSize ) ); long presentationTimeUs = 0; if( sampleSize < 0 ) { sawInputEOS = true; sampleSize = 0; } else { presentationTimeUs = extractor.getSampleTime( ); } Log.d( LOG_TAG, "Input Buffer" ); Log.d( "InputBufIndex:", String.valueOf( inputBufIndex ) ); Log.d( "PresentationTimeUS", String.valueOf( presentationTimeUs ) ); codec.queueInputBuffer( inputBufIndex, 0, // offset sampleSize, presentationTimeUs, sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0 ); if( !sawInputEOS ) { Log.d( "Extractor", " Advancing" ); extractor.advance( ); } } runOutputBuffer( ); } public void runOutputBuffer( ) { BufferInfo info = new BufferInfo( ); final int res = codec.dequeueOutputBuffer( info, -1 ); Log.d( "RES: ", String.valueOf( res ) ); if( res >= 0 ) { int outputBufIndex = res; ByteBuffer buf = codecOutputBuffers[ outputBufIndex ]; final byte[ ] chunk = new byte[ info.size ]; buf.get( chunk ); // Read the buffer all at once buf.clear( ); // ** MUST DO!!! OTHERWISE THE NEXT TIME YOU GET THIS SAME BUFFER BAD THINGS WILL HAPPEN if( chunk.length > 0 ) { Log.d( "Chunk: ", String.valueOf( chunk.length ) ); surface.setTexture( chunk, 320, 240 ); // mAudioTrack.write( chunk, 0, chunk.length ); // do the things } codec.releaseOutputBuffer( outputBufIndex, false /* render */); if( ( info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM ) != 0 ) { sawOutputEOS = true; } } else if( res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ) { codecOutputBuffers = codec.getOutputBuffers( ); } else if( res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED ) { final MediaFormat oformat = codec.getOutputFormat( ); Log.d( LOG_TAG, "Output format has changed to " + oformat ); // mAudioTrack.setPlaybackRate( oformat.getInteger( MediaFormat.KEY_SAMPLE_RATE ) ); } } 的无限循环中作为暂停)任何人都可以帮助这个,和/或提供从那里去哪里的任何建议?

感谢您的帮助,这是我的代码:

{{1}}

}

1 个答案:

答案 0 :(得分:9)

詹姆斯,欢迎来到Stack Overflow(作为提问者)!

我曾试图使用MediaCodec类玩具,它非常有限并且记录不完整。但是,请查看Cedric Fung的这个漂亮的solid post(及其链接的github)。他的github项目应该在API-17(JellyBean 4.2)+设备上开箱即用。

我确信你可以确定你需要从那里改变什么,虽然我之前提到过,你现在对API的当前水平的灵活性有限。

关于您的具体问题,我认为您使用媒体解码器调用锁定了UI,这是不推荐的。您应该采用线程方法,而不是将-1设置为超时,超时为10000并允许它被多次调用,直到它处于活动状态。

希望这会有所帮助(虽然你提出这个问题已有好几个月了!)