繁体   English   中英

在Android上解码h264 ByteStream

[英]Decoding h264 ByteStream on Android

我想在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 outIndex 。运行此代码时, outIndex等于MediaCodec.INFO_TRY_AGAIN_LATER

我以前已经写了一个Client for Notebooks,它可以正常工作,所以我猜服务器的h264流应该可以。

谢谢你的帮助

编辑:如果有人遇到相同的问题,建议的fadden的修订(1)解决了该问题。 我更正了上面的代码。 现在正在工作。 我显示的示例的另一个错误是,您不能将null传递给.dequeueOutputBuffers(...);。 你必须做类似的事情

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

即使您没有兴趣。 ;)

我看到一些问题...

(1)您正在尝试替换输入缓冲区数组中的缓冲区。 MediaCodec不能这样工作-框架提供了缓冲区,然后将数据复制到缓冲区中。 这个想法是,通过允许框架进行分配,它有可能避免以后再复制数据。

您需要从decoder.getInputBuffers()decoder.getInputBuffers()获取输入缓冲区的数组,并使用它们。 确保clear() ByteBuffer以重置位置并每次限制。

(2)您正在写入单个数据包,并期待一帧输出数据。 实际上,您可能需要在生成第一帧之前提供多个数据缓冲区。 有关示例,请参见本文 在某些配置文件中,允许编码器对帧进行重新排序,因此,即使在解码器开始运行后,您也不能只输入帧并等待解码后的数据弹出另一端。

(3)AVC解码器需要SPS / PPS数据 ,您可以通过设置了BUFFER_FLAG_CODEC_CONFIG标志的缓冲区或通过使用MediaFormat#setByteBuffer()将带有“ csd-0” /“ csd-1”键的数据添加到MediaFormat来提供这些数据。 MediaFormat#setByteBuffer() 两种方法的示例都可以在EncodeDecodeTest中找到。

bigflake上有许多AVC解码示例,但是数据源是MediaCodec编码器,因此它们通常免费获得第3点。

此帖子可能对您有用。

对于显示帧,您可以在Grafika中看到不同的方法(通常适用于.mp4文件,因此,编码/解码实现并不重要)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM