簡體   English   中英

使用 MediaCodec 在 Android 上使用 H264 數據解碼 RTP 流

[英]Decoding an RTP stream with H264 data on Android Using MediaCodec

我目前正在嘗試從 RTP 流中解析 H264 數據,然后將其發送到 MediaCodec 以在 Android 的 SurfaceView 上呈現。

但是,我不確定如何:

  • 從 RTP 數據包中正確構建 H264 切片
  • 將 H264 切片組裝成切片后,將它們發送到媒體編解碼器

我還沒有看到任何以清晰簡潔的方式實現的示例,我也沒有發現 MediaCodec 文檔有任何幫助。

任何人在這個領域有任何經驗嗎?

void videoCodec(ByteBuffer input, int flags) {

    bufferInfo.set(0, 0, 0, flags);

    int inputBufferId = codec.dequeueInputBuffer(10000);

    if (inputBufferId >= 0) {

        //put data
        ByteBuffer inputData = inputBuffers[inputBufferId];

        inputData.clear();
        inputData.put(input);

        //queue it up
        codec.queueInputBuffer(inputBufferId, 0, input.limit(), 0, flags);
    }

    int outputBufferId = codec.dequeueOutputBuffer(bufferInfo, 10000);

    if (outputBufferId >= 0) {
        // outputBuffers[outputBufferId] is ready to be processed or rendered.
        Timber.e("Rendering Data with Index of: %s", outputBufferId);
        codec.releaseOutputBuffer(outputBufferId, true);

    } else if (outputBufferId == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
        outputBuffers = codec.getOutputBuffers();
    } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
        // Subsequent data will conform to new format.
        //format = codec.getOutputFormat();
    }
}

 MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080);
                    codec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
                    codec.configure(format, surfaceVideo.getHolder().getSurface(), null, 0);
                    codec.start();


                    inputBuffers = codec.getInputBuffers();
                    outputBuffers = codec.getOutputBuffers();

      while (streaming) {

          //receive RTP Packet
          h264Parser(rtpPacket.getPayload());

      }

h264Parser 看起來像這樣:

void h264Parser(byte[] payload) {

    int packetType = (byte) payload[0] & (byte) 0x1F;
    boolean startBit = (payload[1] & 0x80) != 0;
    boolean endBit = (payload[1] & 0x40) != 0;
    int flags = 0;

    switch (packetType) {
        case 7:
            pps = new ByteArrayOutputStream();
            pps.write(prefix);
            pps.write(payload);
            break;
        case 8:
            if (pps.size() > 0) {
               pps.write(payload);
               hasPps = true;
               flags = MediaCodec.BUFFER_FLAG_CODEC_CONFIG;
               payload = pps.toByteArray();
               //Send packet to decoder
               videoCodec(ByteBuffer.wrap(payload), flags);
            break;
        case 28:

            if (hasPps) {
                if (startBit) {
                    baos = new ByteArrayOutputStream();
                    baos.write(prefix);
                    baos.write(payload);
                } else if (endBit) {
                        if(baos != null) {
                            baos.write(payload);
                            flags = MediaCodec.BUFFER_FLAG_KEY_FRAME;
                            payload = baos.toByteArray();
                            //Send packet to decoder
                            videoCodec(ByteBuffer.wrap(payload), flags);
                            hasPps = false;
                } else {
                        if(baos != null ) {
                            baos.write(payload);
                        }
                }
            }

            break;
        case 1:
            break;
        default:
    }

據我所知 MediaCodec 使用完整的訪問單元,而不僅僅是切片(有人糾正我我錯了)

因此,您必須構建一個完整的 RTP 訪問單元並將其提供給解碼器(遺憾的是我沒有 RTP 經驗,無法幫助您構建一個)。

您將訪問單元發送到解碼器,如下所示:

出列輸入緩沖區

int inputBufferIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); ByteBuffer inputBuffer = videoDecoderInputBuffers[videoInputBufIndex];

填寫您的訪問單元

inputBuffer.put(acessUnit); inputBuffer.flip();

將緩沖區排隊以進行解碼

decoder.queueInputBuffer(inputBufferIndex,0,inputBuffer.limit(), 0, FLAGS);

希望這會有幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM