java在android上解码h264 bytestream

9nvpjoqh  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(511)

我想在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);
}

我测试这个代码的设备是googlenexus5。当我运行这个时 outIndex 等于 MediaCodec.INFO_TRY_AGAIN_LATER 一直如此。
我以前为笔记本电脑编写过一个客户机,工作正常,所以我想服务器上的h264流应该可以。
谢谢你的帮助
编辑:如果有人遇到同样的问题,建议的修正案(1)法登解决了这个问题。我更正了上面的代码。现在开始工作了。我展示的示例的另一个错误是,不能将null传递给.dequeueoutputbuffers(…);。你必须做一些像

BufferInfo buffInfo = new MediaCodec.BufferInfo();
        int outIndex = codec.dequeueOutputBuffer(buffInfo, 10000);

即使你对此不感兴趣

ulmd4ohb

ulmd4ohb1#

我看到一些问题。。。
(1) 您正在尝试替换输入缓冲区数组中的缓冲区。 MediaCodec 不是这样工作的——框架提供缓冲区,您将数据复制到缓冲区中。其思想是,通过允许框架进行分配,它可以潜在地避免以后复制数据。
您需要从 decoder.getInputBuffers() ,并使用这些。确保 clear() 这个 ByteBuffer 每次重置位置和限制。
(2) 您正在编写一个数据包,并期望一帧输出数据。实际上,在生成第一帧之前,可能需要提供多个数据缓冲区。看这篇文章的例子。在某些配置文件中,编码器可以对帧进行重新排序,因此即使在解码器开始运行之后,也不能只输入一个帧,然后等待解码数据从另一侧弹出。
(3) avc解码器需要sps/pps数据,您可以使用 BUFFER_FLAG_CODEC_CONFIG 设置标志,或通过将带有“csd-0”/“csd-1”键的数据添加到 MediaFormat 使用 MediaFormat#setByteBuffer() . 这两种方法的示例可以在测试中找到。
bigflake上有许多avc解码示例,但数据源是 MediaCodec 编码器,所以他们通常免费获得点#3。
这个帖子可能对你有用。
对于显示帧,您可以在grafika中看到不同的方法(它通常与.mp4文件一起工作,因此那里的编码/解码实现没有那么相关)。

相关问题