MediaCodec不解码H264编码视频数据

问题描述 投票:1回答:1

我开发了RTP接收H264编码数据的应用程序,我有麻烦越来越Android的MediaCodec输出任何东西。我在这里所描述的解包RTP包https://stackoverflow.com/a/7668578/10788248

经过编码的帧已经被重新组装我喂它们到取出的输入缓冲器。

当我排队,输入缓冲器我没有得到任何错误,但该方法onOutputBufferAvailable从未被解码器的回调调用。

我能够得到它调用的唯一方法是通过传递结束流的标志,然后输出大小为0。

我的问题是,'有什么明显错误我失踪?和“什么潜在的问题可能会导致输出缓冲器从未变得可用,但编解码器不引发错误?

代码更新

LinkedList<DatagramPacket> packets = new LinkedList<>();
Thread socketReader = new Thread(() -> {
        try {
            DatagramSocket socket  = new DatagramSocket(videoPort);
            socket.connect(InetAddress.getByName(remoteAddress),remotePort);
            byte[] b;
            while (true){
                b = new byte[1500];
                DatagramPacket p = new DatagramPacket(b,1500);
                socket.receive(p);
                //Log.d(TAG,"RTP: "+bytesToHex(p.getData()));
                packets.add(p);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
@SuppressLint({"NewApi", "LocalSuppress"}) Thread packetHandler = new Thread(() -> {
        try {
            MediaCodec decoder = MediaCodec.createDecoderByType(MIME_TYPE);
            MediaFormat decoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, 1280, 720);
            LinkedList<ByteBuffer> decoderInputs = new LinkedList<>();
            LinkedList<Integer> decoderIndices = new LinkedList<>();

            decoder.setCallback(new MediaCodec.Callback() {
                @Override
                public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
                    decoderInputs.add(codec.getInputBuffer(index));
                    decoderIndices.add(new Integer(index));
                }

                @Override
                public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
                    Log.d(TAG,"OUTPUT AVAILABLE!!!!");
                    Log.d(TAG, String.valueOf(info.size));
                }

                @Override
                public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {
                    Log.e(TAG,e.toString());
                }
                @Override
                public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) {
                    Log.d(TAG,"FORMAT CHANGED");
                }
            });
            decoder.configure(decoderFormat, null,null,0);
            decoder.start();
            RTPFrame frame = new RTPFrame();
            boolean sps = false;
            boolean pps = false;
            while (true){
                if(decoderIndices.peek()!=null){
                    DatagramPacket packet = packets.poll();
                    if(packet!=null){
                        byte[] data = packet.getData();
                        if(frame==null||(!frame.isInitialized())){
                            frame = new RTPFrame(data);
                        }
                        else{
                            if(frame.isComplete()){
                                Integer index = null;
                                ByteBuffer decoderInput = null;
                                try {
                                    decoderInput = decoderInputs.poll().put(frame.getFrame());
                                    index = decoderIndices.poll();
                                    int size = frame.getFrameSize();
                                    if (frame.SPS) {
                                        Log.d(TAG,"Depacketized at "+Integer.toUnsignedString(frame.getTime())+" length = "+frame.getFrameSize()+": " + bytesToHex(frame.getFrame().array()));
                                        decoder.queueInputBuffer(index, 0, size, frame.getTime(), MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
                                        sps = true;
                                        pps = false;
                                    } else if (frame.PPS) {
                                        if(sps){
                                            Log.d(TAG,"Depacketized at "+Integer.toUnsignedString(frame.getTime())+" length = "+frame.getFrameSize()+": " + bytesToHex(frame.getFrame().array()));
                                            decoder.queueInputBuffer(index, 0, size, frame.getTime(), MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
                                            pps = true;
                                        }
                                    } else if (!frame.badFrame) {
                                        if(sps&&pps){
                                            Log.d(TAG,"Depacketized at "+Integer.toUnsignedString(frame.getTime())+" length = "+frame.getFrameSize()+": " + bytesToHex(frame.getFrame().array()));
                                            decoder.queueInputBuffer(index, 0, size, frame.getTime(), 0);
                                        }
                                    }
                                    else{
                                        throw new RuntimeException();
                                    }
                                }
                                catch(Exception e){
                                    e.printStackTrace();
                                    if(index!=null){
                                        decoderIndices.push(index);
                                    }
                                    decoderInput.clear();
                                    decoderInputs.push(decoderInput);
                                }
                                frame = new RTPFrame();
                            }
                            else{
                                frame.addNALUnit(data);
                            }
                        }
                        if(frame.isComplete()){
                            Integer index = null;
                            ByteBuffer decoderInput = null;
                            try {
                                decoderInput = decoderInputs.poll().put(frame.getFrame());
                                index = decoderIndices.poll();
                                int size = frame.getFrameSize();
                                if (frame.SPS) {
                                    Log.d(TAG,"Depacketized at "+Integer.toUnsignedString(frame.getTime())+" length = "+frame.getFrameSize()+": " + bytesToHex(frame.getFrame().array()));
                                    decoder.queueInputBuffer(index, 0, size, frame.getTime(), MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
                                    sps = true;
                                    pps = false;
                                } else if (frame.PPS) {
                                    if(sps){
                                        Log.d(TAG,"Depacketized at "+Integer.toUnsignedString(frame.getTime())+" length = "+frame.getFrameSize()+": " + bytesToHex(frame.getFrame().array()));
                                        decoder.queueInputBuffer(index, 0, size, frame.getTime(), MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
                                        pps = true;
                                    }
                                } else if (!frame.badFrame) {
                                    if(sps&&pps){
                                        Log.d(TAG,"Depacketized at "+Integer.toUnsignedString(frame.getTime())+" length = "+frame.getFrameSize()+": " + bytesToHex(frame.getFrame().array()));
                                        decoder.queueInputBuffer(index, 0, size, frame.getTime(), 0);
                                    }
                                }
                                else{
                                    throw new Exception("bad frame");
                                }
                            }
                            catch(Exception e){
                                e.printStackTrace();
                                if(index!=null){
                                    decoderIndices.push(index);
                                }
                                decoderInput.clear();
                                decoderInputs.push(decoderInput);
                            }
                            frame = new RTPFrame();
                        }
                    }
                }
            }
        } catch (Exception e) {e.printStackTrace();}
    });

这里就是我1帧中接收的NAL单元的样本,我怎么解包它们。

RTP:80欧米伽00 2E 27 0E SCH 30 YY BX军ZTS 42 81 00 E0 80 SV ...

RTP:80 63 00 2E 27 0E 64 30 66 B4 42 BA 01 3C 0F F3 E0 3F ...

RTP:80欧米伽2F 00 27 30 0E SCH YY BX军42 ZTS 01 zsht镱FA巴...

RTP:80 63 00 30 27 64 30 66 0E B4 BA 42 01 3C 75 EA 7F 7C ...

RTP:欧米茄80 00 31 27 30 0E SCH YY BX军ZTS 42 01 FA D8绫FF ...

RTP:80 63 00 32 27 0E 64 30 66 B4 42 BA 01 3C 1B C5 BC C0 ...

RTP:80 63 00 33 27 64 30 66 0E B4 BA 42 01 3C 0F F4 9A DE ...

RTP:80 63 00 34 27 64 30 66 0E B4 BA 42 01 3C 35 F4 28 CD ...

RTP:80 63 00 35 27 64 30 66 0E B4 BA 42 01 3C 9E 45 70 13 ...

CTP:80结00的Qm 27 0E 30 SCH YY BX AD 42个ZTS 41 0F 18 83 0D ...

d / RTPreader:解包在2985639104长度= 12611:00 00 00 01 21 E0 00 80 6F F0 B4 24 CD 45 5F 80 79 6E 0C ...

这里的前和后拆包的样本SPS和PPS

顺序:80 63 00 00 DF 5F 70 A1 4F 2F 8A 3E 27 42 00 1F 68 8D 05 00 5B 00 A1 00 03 00 01 00 00 03 00 1E 10 0F 80 7A

在1608491376长度解包= 27:00 00 01 27 42 00 1F 68 8D 05 00 5B 00 A1 00 03 00 01 00 00 03 00 1E 10 0F 80 7A

在1608491376长度解包= 7:00 00 01 28 CE 32 48

顺序:80 63 00 01 DF 5F 70 A1 4F 2F 8A 3E 28 CE 32 48

android h.264 rtp mediacodec
1个回答
2
投票

我要感谢@ greeble31和@ChrisBe他们在搞清楚这个问题的帮助。这个问题的确是我的RTPFrame类。具体地说,该方法getFrame(),其通过含有NAL单元数据的ByteBuffers的列表迭代和用于put(ByteBuffer)其添加到bb。这增加positionbb直到它等于limit

public ByteBuffer getFrame() {
    size = 4;
    int nalCount = nalUnits.size();
    for (int i = 0;i<nalCount;i++){
        size+=nalUnits.get(i).data.length;
    }

    ByteBuffer bb = ByteBuffer.allocate(size);
    bb.put(new byte[]{0,0,0,1});
    for(NALUnit unit:nalUnits){
        bb.put(unit.data);
    }
    return bb;
}

更改return bb;return (ByteBuffer)bb.position(0);固定的问题。

© www.soinside.com 2019 - 2024. All rights reserved.