- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想在 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);
解码器的使用:
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);
}
我正在测试此代码的设备是 Google Nexus 5。当我运行此代码时,outIndex
始终等于 MediaCodec.INFO_TRY_AGAIN_LATER
。
我之前为Notebooks写过一个Client,效果很好,所以我猜从Server端来的h264 Stream应该没问题。
谢谢你的帮助
编辑:如果有人遇到同样的问题,建议的 fadden 修正案 (1) 解决了这个问题。我更正了上面的代码。它现在工作。我展示的示例的另一个错误是,您不能将 null 传递给 .dequeueOutputBuffers(...);。你必须做类似的事情
BufferInfo buffInfo = new MediaCodec.BufferInfo();
int outIndex = codec.dequeueOutputBuffer(buffInfo, 10000);
即使您对此不感兴趣。 ;)
最佳答案
我看到了一些问题......
(1) 您正在尝试替换输入缓冲区数组中的缓冲区。 MediaCodec
不是这样工作的——框架提供缓冲区,然后您将数据复制到其中。这个想法是,通过允许框架进行分配,它可以避免以后复制数据。
您需要从 decoder.getInputBuffers()
获取输入缓冲区数组,并使用它们。确保 clear()
ByteBuffer
每次重置位置和限制。
(2) 您正在编写单个数据包并期望输出一帧数据。实际上,您可能需要在生成第一帧之前提供多个数据缓冲区。参见 this post举个例子。在某些配置文件中,允许编码器对帧重新排序,因此即使在解码器开始运行后,您也不能只提供一个帧并等待解码数据从另一侧弹出。
(3) AVC解码器needs the SPS/PPS data ,您可以通过设置了 BUFFER_FLAG_CODEC_CONFIG
标志的缓冲区提供,或者通过使用“csd-0”/“csd-1”键将数据添加到 MediaFormat
使用MediaFormat#setByteBuffer()
。可以在 EncodeDecodeTest 中找到这两种方法的示例。 .
bigflake上有大量AVC解码示例, 但数据源是 MediaCodec
编码器,所以他们通常免费获得第 3 点。
This posting可能对您有用。
为了显示框架,您可以在 Grafika 中看到不同的方法。 (它通常适用于 .mp4 文件,因此那里的编码/解码实现不那么相关)。
关于java - 在 Android 上解码 h264 字节流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22332003/
我是一名优秀的程序员,十分优秀!