Chr*_*oph 8 java video android decode mediacodec
我想在Android中解码并显示原始的h264视频字节流,因此我目前正在使用这些MediaCodec/Format类.我从服务器通过Udp获取帧数据.但是,遗憾的是,目前没有显示任何内容.
这是我到目前为止所拥有的.
初始化MediaCodec类:
codec = MediaCodec.createDecoderByType("video/avc");
MediaFormat format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, "video/avc");
format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 100000);
format.setInteger(MediaFormat.KEY_WIDTH, 800);
format.setInteger(MediaFormat.KEY_HEIGHT, 600);
format.setInteger("max-width", 800);
format.setInteger("max-height", 600);
format.setInteger("push-blank-buffers-on-shutdown", 1);
codec.configure(format, surface, null, 0);
Run Code Online (Sandbox Code Playgroud)
解码器的用法:
int inIndex = codec.dequeueInputBuffer(10000);
if(inIndex >= 0)
{
ByteBuffer inputBuffer = codecInputBuffers[inIndex];
inputBuffer.clear();
inputBuffer.put(frameData);
codec.queueInputBuffer(inIndex, 0, frameSize, 33, 0);
}
int outIndex = codec.dequeueOutputBuffer(null, 10000);
switch(outIndex)
{
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
codecOutputBuffers = codec.getOutputBuffers();
System.out.println("OB Changed");
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
System.out.println("OF Changed");
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
System.out.println("l8r");
break;
default:
ByteBuffer buffer = codecOutputBuffers[outIndex];
codec.releaseOutputBuffer(outIndex, true);
}
Run Code Online (Sandbox Code Playgroud)
我正在测试此代码的设备是Google Nexus 5.当我运行它时,它outIndex等于MediaCodec.INFO_TRY_AGAIN_LATER整个时间.
我以前写的笔记本客户端,工作正常,所以我猜服务器的h264流应该没问题.
谢谢你的帮助
编辑:如果有人遇到同样的问题,fadden的拟议修正案(1)解决了这个问题.我纠正了上面的代码.它现在正在工作.我所示示例的另一个错误是,您无法将null传递给.dequeueOutputBuffers(...);. 你必须做类似的事情
BufferInfo buffInfo = new MediaCodec.BufferInfo();
int outIndex = codec.dequeueOutputBuffer(buffInfo, 10000);
Run Code Online (Sandbox Code Playgroud)
即使你没有加入其中.;)
我看到一些问题......
(1)您正在尝试替换输入缓冲区数组中的缓冲区. MediaCodec不起作用 - 框架提供缓冲区,并将数据复制到它们中.这个想法是,通过允许框架进行分配,它可以避免以后复制数据.
您需要从中获取输入缓冲区数组decoder.getInputBuffers(),并使用它们.请务必clear()在ByteBuffer复位位置和每个时间限制.
(2)您正在编写单个数据包并期望输出数据帧.实际上,您可能需要在生成第一帧之前提供多个数据缓冲区.有关示例,请参阅此帖子.在某些配置文件中,编码器可以重新排序帧,因此即使在解码器开始运行之后,您也不能只提供帧并等待解码数据从另一侧弹出.
(3)AVC解码器需要SPS/PPS数据,您可以通过BUFFER_FLAG_CODEC_CONFIG设置了标志的缓冲区提供数据,或者通过将带有"csd-0"/"csd-1"键的数据添加到MediaFormat使用中MediaFormat#setByteBuffer().两种方法的示例可以在EncodeDecodeTest中找到.
bigflake上有许多AVC解码示例,但数据源是MediaCodec编码器,因此它们通常免费得到#3点.
此帖子可能对您有用.
为了显示帧,您可以在Grafika中看到不同的方法(通常与.mp4文件一起使用,因此编码/解码实现没有相关性).