【问题标题】:decoding android h264 encoded stream on windows using media foundation使用媒体基础在 Windows 上解码 android h264 编码流
【发布时间】:2015-05-14 14:01:58
【问题描述】:

我正在尝试解码从 Windows pc 上的 android 设备流式传输的 h264 编码相机帧。 我正在使用 MediaFoundation H264 解码器来解码从 android 设备发送的每一帧。但是我不断收到错误“需要更多输入样本来处理输出错误”。

MF H264解码器的要求如下:

Media samples contain H.264 bitstream data with start codes and has interleaved SPS/PPS. Each sample contains one complete picture, either one field or one frame.

我想知道这是否与我从 android 设备发送的内容兼容。

我正在使用下面的代码向 windows 设备发送帧:

    private static class AvcEncoder {

        private MediaCodec mediaCodec;
        final static int FRAME_RATE = 15;
        final static int MOTION_RANK = 2;

        public AvcEncoder(int width, int height) { 

            mediaCodec = MediaCodec.createEncoderByType("video/avc");
            MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height);
            mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, (int)(width*height*FRAME_RATE*MOTION_RANK*0.07));
            mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
            mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
            mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
            mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            mediaCodec.start();
        }

        public void close() {
            try {
                mediaCodec.stop();
                mediaCodec.release();
                outputStream.flush();
                outputStream.close();
            } catch (Exception e){ 
                e.printStackTrace();
            }
        }

        //frames are sent here
        public void offerEncoder(byte[] input) {
            try {
                ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
                ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
                int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
                if (inputBufferIndex >= 0) {
                    ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
                    inputBuffer.clear();
                    inputBuffer.put(input);
                    mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, 0);
                }

                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo,0);
                while (outputBufferIndex >= 0) {
                    ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
                    byte[] outData = new byte[bufferInfo.size];
                    outputBuffer.get(outData);
// write frame length
                    byte frameLength[] = ByteBuffer.allocate(4).putInt(outData.length).array();
                    outputStream.write(frameLength, 0, 4);
// write the actual frame
                    outputStream.write(outData, 0, outData.length);
                    Log.i("AvcEncoder", outData.length + " bytes written");
                    mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
                    outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
                }
            } catch (Throwable t) {
                t.printStackTrace();
            }

        }

如果需要,我也可以发布 Windows 代码。

另外,当我将流数据保存到文件时,我可以在 VLC 中播放它,因此 VLC 能够很好地理解和解码它。

【问题讨论】:

    标签: android streaming video-streaming live-streaming ms-media-foundation


    【解决方案1】:

    嗯,修复很简单。我不知道为什么,但 Media Foundation 要求您设置输入解码器的每个样本的持续时间或时间戳。然而,这两个参数似乎不会以任何方式影响输出。

    编辑: 请注意,如果样本持续时间或时间戳未在传递给InputProcess 方法的IMFSample 对象中设置,则IMFTransformInputProcess 方法应返回MF_E_NO_SAMPLE_DURATIONMF_E_NO_SAMPLE_TIMESTAMP。但是,就我而言,它没有返回任何此类值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-26
      • 1970-01-01
      相关资源
      最近更新 更多