0

我正在使用 JavaCPP av_read_packet 从 H264 (MPEG4 AVC) 源读取 AVPackets,然后我尝试仅将视频数据包传递给 Android 的 MediaCodec 以对其进行解码并渲染到 Surface 中(用于显示)。我已经读过,当您使用 AVC 源以与 MediaCodec 兼容时,必须将 av_bitstream_filter_filter 与 h264_mp4toannexb 过滤器一起使用。

问题是dequeueOutputBuffer总是返回-1,我不知道问题是在使用过滤器时还是其他原因。

这是代码片段:

bsfc = new AVBitStreamFilterContext();
bsfc = av_bitstream_filter_init("h264_mp4toannexb");

public void FilterPacket(AVPacket paquete){

    IntPointer size_pointer = new IntPointer(1);
    size_pointer.put(paquete.size());
    BytePointer data = new BytePointer();

    int sal = av_bitstream_filter_filter(bsfc, video_codec, (BytePointer)null, data, size_pointer, paquete.data(), paquete.size(), paquete.flags() & AV_PKT_FLAG_KEY );

    paquete.size(size_pointer.get());
    paquete.data(data);

}

这是解码循环内部的内容:

public void DecoderLoop(AVPacket paquete){
    int inputBufferIndex = decoder.dequeueInputBuffer(5000);
    if (inputBufferIndex >= 0) {
        ByteBuffer bufferSalida = inputBuffers[inputBufferIndex]; 
        FilterPacket(paquete);
        bufferSalida.put(paquete.data().asByteBuffer());
        //double presentationTemp = (double)(paquete.pts()/paquete.duration()) * (1000000/30); 
        //long presentationTime = (long)presentationTemp;
        decoder.queueInputBuffer(inputBufferIndex, 0, paquete.size(), 0, 0);

    }

    int outputBufferIndex = decoder.dequeueOutputBuffer(info, 10000);
    if (outputBufferIndex >= 0) {
        // outputBuffer is ready to be processed or rendered.
        decoder.releaseOutputBuffer(outputBufferIndex, true); 
    } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
        outputBuffers = decoder.getOutputBuffers();
    } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
        // Subsequent data will conform to new format.
        format = decoder.getOutputFormat();
    }
}

dequeueInputBuffer 返回一个正值,而 av_bitstream_filter_filter 返回 1(但我不知道它是否有效),但 dequeueOutputBuffers 总是返回 -1。谁能帮我解决问题?

我怀疑问题可能出在其中之一:

  • av_bitstream_filter_filter

  • bufferSalida.put(paquete.data().asByteBuffer()); ¿ 我可以使用这些方式吗?

  • 如果我使用 .asByteBuffer,我可以使用 paquete.size() 还是可以使用不同的东西?

非常感谢

4

1 回答 1

1

我不熟悉 libavcodec 库的 JavaCPP 包装,但除了普通的 AVPackets,您还需要 AVCodecContext.extradata(在初始化比特流过滤器和过滤第一个数据包之后)。在发送第一个 AVPacket 之前,您需要将来自 extradata 的数据作为您传递给配置的输入 MediaFormat 中名称为“csd-0”的 ByteBuffer 传递,或者作为具有 BUFFER_FLAG_CODEC_CONFIG 的单独缓冲区传递。

于 2014-10-07T20:02:47.837 回答