当前位置: 首页 > 知识库问答 >
问题:

Mediacodec解码h264 OutputBuffer索引返回-1

宇文元明
2023-03-14
inputBuffer.put(SPS_PPS,0,SPS_PPS.length);
mCodec.queueInputBuffer(inIndex, 0, SPS_PPS.length, presentationTime, BUFFER_FLAG_CODEC_CONFIG);

我做了一些假设:

1.我给Mediacodec的每个输入缓冲区提供一个完整的访问单元,从00 00 00 01 09开始

2.我使用GLSurface.getholder().getsurface()从xml布局中预定义的GLSurface解码为一个表面。我不确定这是不是正确的做法。

3.字节数组包含NAL单元,我要自己拆分。但这些nal单元只有0x25、0x27、0x28、0x06和0x09类型。我只知道0x09表示AUD

我真的希望任何人都能提供哪怕是最小的建议,因为这件事这些天都快把我逼疯了。

我的代码段:

private DjiGLSurfaceView mDjiGLSurfaceView;
mDjiGLSurfaceView = (DjiGLSurfaceView)findViewById(R.id.DjiSurfaceView_);
mDjiGLSurfaceView.getHolder().addCallback(this);
BufferedInputStream buf = new BufferedInputStream(is);
buf.read(iframe, 0, iframe.length);

我的异步处理部分:

当接收到包含视频数据的字节数组时,调用DJIReceivedVideoDataCallBack。

public void surfaceCreated(SurfaceHolder holder){
    Log.e(TAG, "Surface Created!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    format.setString("KEY_MIME", videoFormat);
    try
    {
        mCodec = MediaCodec.createDecoderByType(videoFormat);
        mCodec.configure(format, mDjiGLSurfaceView.getHolder().getSurface(), null, 0 );
        mCodec.start();

        mReceivedVideoDataCallBack = new DJIReceivedVideoDataCallBack(){
            private int packetLength = 0;
            private ByteBuffer accessUnitBuffer = ByteBuffer.allocate(50000);
            int inIndex;
            long presentationTime = 0;

            @Override
            public void onResult(byte[] videoBuffer, int size){
                ArrayList<byte []> NAL_Units = splitNALunits(videoBuffer,size);
                //Send the I-Frame first
                if (!seq_start && iframe_ready){
                    inIndex = mCodec.dequeueInputBuffer(0);
                    if (inIndex >= 0) {
                        ByteBuffer inputBuffer = mCodec.getInputBuffer(inIndex);
                        inputBuffer.put(iframe,0,iframe.length);
                        mCodec.queueInputBuffer(inIndex, 0, iframe.length, presentationTime, 0);
                        presentationTime += 100;
                        seq_start = true;
                        handler.sendMessage(handler.obtainMessage(SHOWTOAST, "I-Frame queued!!!"));
                    }
                }
                for( int i=0; i< NAL_Units.size(); i++ ) {
                    if( NAL_Units.get(i)[4] == 0x09 ) {
                        // Send off the current buffer of data (Access Unit)
                        inIndex = mCodec.dequeueInputBuffer(0);
                        if (inIndex >= 0) {
                            ByteBuffer inputBuffer = mCodec.getInputBuffer(inIndex);
                            if (packetLength > 0)
                                inputBuffer.put(accessUnitBuffer.array(), 0, packetLength);
                            mCodec.queueInputBuffer(inIndex, 0, packetLength, presentationTime, 0);
                            presentationTime += 100;
                            packetLength = 0;
                            accessUnitBuffer.clear();
                            accessUnitBuffer.rewind();
                        }
                    }
                    accessUnitBuffer.put(NAL_Units.get(i));
                    packetLength += NAL_Units.get(i).length;
                }
                MediaCodec.BufferInfo bufferinfo = new MediaCodec.BufferInfo();
                int outputBufferIndex = mCodec.dequeueOutputBuffer(bufferinfo, 0);
                handler.sendMessage(handler.obtainMessage(SHOWTOAST, "outputBufferIndex = "+ outputBufferIndex));
                while (outputBufferIndex >= 0){
                    mCodec.releaseOutputBuffer(outputBufferIndex, true);
                    outputBufferIndex = mCodec.dequeueOutputBuffer(bufferinfo, 0);
                }
            }
        };
        DJIDrone.getDjiCamera().setReceivedVideoDataCallBack(mReceivedVideoDataCallBack);
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }
}

共有1个答案

王亮
2023-03-14

在media codec.configure()中,如果不设置surface(设置null),它会得到decoded的结果,需要自己绘制图像。

你可以搜索关键字:“媒体编解码器OpenGL”。你会找到样品的。

ps.输出的格式是不确定的。(可能是RGBA)

 类似资料:
  • 我正在尝试使用MediaCodec API解码现场流屏幕捕获从PC由FFMPEG。 对于发件人(PC ffmpeg) 输出如下所示 用于接收器(Android MediaCodec) 我用surface创建了活动并实现了SurfaceHolder.Callback 对于PlayerThread 前四个字节是头和序列号 接下来的四个字节是时间戳 下四个字节是源标识符 因此,我删除了前12个字节,并将

  • 我正在解码从Android上的wifi摄像头接收到的原始h264。 这是解码时产生的视频的一个例子,除了底部部分看起来很好。 我还注意到一些奇怪的事情,当我移动摄像机时,饲料似乎运行几乎完全流畅(底部没有垃圾),一旦我把它放下,垃圾视频返回(我会以为它是相反的方式...) 我正在将h264数据解析成以澳元开头的块,每个块以澳元开头,当另一个开始时结束。 我的理解是,每个解析的“块”(以AUD开头)

  • 首先,我对我的英语感到抱歉。我是一个使用VS Express 2013的C#初学者程序员。 我认为这是我的简单问题:我有一个组合框(cboMantello),里面有两个项目。然后我有一个按钮,使用所选项目的属性并将它们添加到我的角色统计中。另一个按钮删除该属性。 为了避免用户垃圾邮件,我禁用了第一个按钮,并设置了我的组合框。启用为false。这时问题来了。禁用组合框后,它会返回列表中的第一项,因此

  • 我正在使用对三星S6上的h264流进行解码,发现mediacodec的输入缓冲区必须以“0001”开头(并且不需要设置pps、sps),否则ACodec将报告错误。 我也尝试使用mediaextractor播放一个mp4文件,它工作良好,但缓冲区到mediacodec不是以“0001”开始。 我不知道为什么decodec一个h264流有这样的限制,目前我需要从socket分析流,并将数据切割成小包

  • 问题内容: 我有像 由Web服务器呈现为HTML。我需要将这些字符串转换为 当前,这就是我正在做的事情(借助于jQuery): 但是我有一种不安的感觉,我做错了。我努力了 但它似乎无效,decodeURI / decodeURIComponent也无效。 还有其他更自然,更优雅的方式吗? 问题答案: 用于从JavaScript解释HTML(文本和其他形式)的一个更现代的选项是API中的HTML支持

  • 我正在尝试解码一个Base64编码的字符串,而当使用UTF8编码时,它总是返回nil。我尝试将字符编码更改为几种不同的选项,但无法使其返回与将其放入https://www.base64decode.org/这样的网站时相同的值 我尝试解码的字符串是“qc6msdfm1pizbp0szoqmoq==” 下面是我用来测试的代码