Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/190.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android使用MediaCodec解码原始h264流_Android_H.264_Decoding_Android Mediacodec_Grafika - Fatal编程技术网

Android使用MediaCodec解码原始h264流

Android使用MediaCodec解码原始h264流,android,h.264,decoding,android-mediacodec,grafika,Android,H.264,Decoding,Android Mediacodec,Grafika,我在使用TextureView上的MediaCodec解码和绘制原始h264数据时遇到问题。我以字节数组的形式接收原始数据,每个数组都是NAL单元(以0x00 0x00 0x00 0x01开头),还有以恒定间隔排列的SP和PPS NAL单元。当新数据到达时,我将其放入LinkedBlockingQueue: public void pushData(byte[] videoBuffer) { dataQueue.add(videoBuffer); if (!decoderCon

我在使用TextureView上的MediaCodec解码和绘制原始h264数据时遇到问题。我以字节数组的形式接收原始数据,每个数组都是NAL单元(以
0x00 0x00 0x00 0x01
开头),还有以恒定间隔排列的SP和PPS NAL单元。当新数据到达时,我将其放入
LinkedBlockingQueue

public void pushData(byte[] videoBuffer) {
    dataQueue.add(videoBuffer);

    if (!decoderConfigured) {
        // we did not receive first SPS NAL unit, we want to throw away all data until we do
        if (dataQueue.peek() != null && checkIfParameterSet(dataQueue.peek(), SPSID)) {

            // SPS NAL unit is followed by PPS NAL unit, we wait until both are present at the
            // start of the queue
            if (dataQueue.size() == 2) {

                // iterator will point head of the queue (SPS NALU),
                // iterator.next() will point PPS NALU
                Iterator<byte[]> iterator = dataQueue.iterator();

                String videoFormat = "video/avc";
                MediaFormat format = MediaFormat.createVideoFormat(videoFormat, width, height);
                format.setString("KEY_MIME", videoFormat);
                format.setByteBuffer("csd-0", ByteBuffer.wrap(concat(dataQueue.peek(), iterator.next())));

                try {
                    decoder = MediaCodec.createDecoderByType(videoFormat);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                decoder.configure(format, mOutputSurface, null, 0);
                decoder.start();

                inputBuffer = decoder.getInputBuffers();

                decoderConfigured = true;
            }
        } else {
            // throw away the data which appear before first SPS NALU
            dataQueue.clear();
        }
    }
}
queueInputBuffer
如下所示:

private void queueInputBuffer(byte[] data) {
    int inIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC);
    if (inIndex >= 0) {
        inputBuffer[inIndex].clear();
        inputBuffer[inIndex].put(data, 0, data.length);
        decoder.queueInputBuffer(inIndex, 0, data.length, System.currentTimeMillis() * 1000, 0);
    }
}
封装此机制的类在单独的线程上运行,类似于来自的
MoviePlayer
。另外,
FrameCallback
是来自grafika的
SpeedControlCallback

结果预览已损坏。当相机(视频源)静止时,它很好,但当它移动时,会出现撕裂、像素化和伪影。当我将原始视频数据保存到文件中,并在桌面上用ffplay播放时,它看起来还不错

在寻找解决方案时,我发现问题可能是由于演示时间无效造成的。我试图修复它(您可以在代码中看到,我提供了系统时间,同时使用了
preRender()
)但没有成功。但是我不确定这个小故障是否是由这些时间戳引起的。

有人能帮我解决这个问题吗

更新1

正如法登所建议的,我已经根据MediaCodec本身创建的数据测试了我的播放器。我的代码捕获相机预览,对其进行编码并将其保存到文件中。我之前用我的目标设备的摄像头feed做了这个,所以我可以切换数据源。基于手机摄像头预览的文件在播放时不会显示任何瑕疵。因此,结论可能是来自目标设备摄像机的原始数据被不直接地处理(或传递到解码器),或者与MediaCodec不兼容(正如法登建议的那样)。

接下来我做的是比较两个视频流的NAL单位。 MediaCodec编码的视频如下所示:

0x00, 0x00, 0x00, 0x01, 0x67, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x65, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x21, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x21, 0xNN, 0xNN ...
.
. 
.    
0x00, 0x00, 0x00, 0x01, 0x21, 0xNN, 0xNN ...
第一个NALU只在流的开头出现一次,然后出现第二个(0x65),然后是多个(0x21)。然后是0x65、多个0x21,依此类推

但是,目标设备的摄像头显示:

0x00, 0x00, 0x00, 0x01, 0x67, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x68, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x61, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x61, 0xNN, 0xNN ...
.
. 
.    
0x00, 0x00, 0x00, 0x01, 0x61, 0xNN, 0xNN ...

整个序列在流中不断重复。

这似乎与所看到的问题有本质上的不同,但您可能还是想比较一下。@fadden谢谢,我没有注意到这个问题。@fadden先生,我很高兴您已经注意到我的问题(stackoverflow.com/questions/32723393)。有两种基本的可能性:(1)源材料与MediaCodec不兼容;(2) 你的球员做错了什么。通过使用MediaCodec本身创建的H.264数据消除第一个问题。你可以通过将摄像机送入编码器(可能是克隆格拉菲卡的“连续捕捉”),然后将编码器中的NAL单元直接发送到你的播放器中来实现这一点。如果这样做有效,您需要找出您提供的视频数据与编码器输出不同的原因。@fadden谢谢,这真的很有帮助!我会检查的。
0x00, 0x00, 0x00, 0x01, 0x67, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x68, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x61, 0xNN, 0xNN ...
0x00, 0x00, 0x00, 0x01, 0x61, 0xNN, 0xNN ...
.
. 
.    
0x00, 0x00, 0x00, 0x01, 0x61, 0xNN, 0xNN ...