Android Camera2管道:如何从输入界面使用MediaCodec对h.264单元进行编码?

Android Camera2管道:如何从输入界面使用MediaCodec对h.264单元进行编码?,android,android-camera,android-camera2,video-encoding,android-mediacodec,Android,Android Camera,Android Camera2,Video Encoding,Android Mediacodec,我有一个使用Camera2API的Android应用程序。最终目标是让h264单元写入流。到目前为止我有 已成功创建捕获会话,并可通过以下方式写入预览、本地录制和流媒体表面: 设置MediaCodec以对上面的streamer.suface参数中的数据进行编码,其中曲面是从以下创建的MediaCodec调用MediaCodec.createInputSurface派生的 当上面的surface的ByteBuffer 我的困惑是,ByteBuffer中的值是否正确编码?我是否需要使用MediaEx

我有一个使用Camera2API的Android应用程序。最终目标是让h264单元写入流。到目前为止我有

  • 已成功创建捕获会话,并可通过以下方式写入预览、本地录制和流媒体表面:
  • 设置MediaCodec以对上面的
    streamer.suface
    参数中的数据进行编码,其中曲面是从以下创建的MediaCodec调用
    MediaCodec.createInputSurface
    派生的
  • 当上面的
    surface
    ByteBuffer

  • 我的困惑是,
    ByteBuffer
    中的值是否正确编码?我是否需要使用
    MediaExtractor
    清除从输入
    表面
    传入的数据,然后再将
    MediaCodec
    传递给它进行编码?管道已经足够干净了,但我不太确定有没有必要。这是最大的指南,它提到了
    MediaCodec
    对原始数据进行操作,这让我觉得我需要
    mediacextractor
    ,但这并不需要一个
    表面
    作为输入,使得管道中项目的正确顺序变得更加混乱。

    您不需要MediaExtractor,它用于处理一个完整的容器文件并拆分其各种流和其他组件

    MediaCodec直接从相机接收原始图像缓冲区,并输出编码缓冲区。如果要保存标准视频文件,需要将这些编码的ByteBuffers馈送到MediaMuxer实例中。如果您只是将编码的缓冲区发送到其他地方进行解码(如视频聊天应用程序),那么您可以将字节缓冲区馈送到目的地的MediaCodec


    我不知道您对MediaCodec的所有参数是否正确,但我看不出有任何明显的错误。

    您不需要MediaExtractor—它用于处理完整的容器文件并拆分其各种流和其他组件

    MediaCodec直接从相机接收原始图像缓冲区,并输出编码缓冲区。如果要保存标准视频文件,需要将这些编码的ByteBuffers馈送到MediaMuxer实例中。如果您只是将编码的缓冲区发送到其他地方进行解码(如视频聊天应用程序),那么您可以将字节缓冲区馈送到目的地的MediaCodec


    我无法判断您对MediaCodec的所有参数是否正确,但我看不出任何明显的错误。

    结果证明我创建
    MediaCodec
    的方式是错误的:
    MediaCodec.createEncoderByType(“视频/avc”)
    修复了它,而不是上面的
    MediaCodec.CreateByCodeName(encoderName)
    结果证明我创建
    MediaCodec
    的方法是错误的:
    MediaCodec.createEncoderByType(“视频/avc”)
    修复了它,而不是上面的
    MediaCodec.CreateByCodeName(encoderName)
        session.device.createCaptureRequest(CameraDevice.TEMPLATE_RECORD).run {
                        addTarget(previewSurface)
                        addTarget(recorder.surface)
                        addTarget(streamer.surface)
                        set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, Range(args.fps, args.fps))
                        build()
                    }
    
        internal fun streamingCodec(args: CameraFragmentArgs): MediaCodec {
            val mediaFormat = MediaFormat.createVideoFormat("video/avc", args.width, args.height).apply {
                setInteger(MediaFormat.KEY_BIT_RATE, 2000 * 1024)
                setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2)
                setInteger(MediaFormat.KEY_FRAME_RATE, args.fps)
                setInteger(
                    MediaFormat.KEY_COLOR_FORMAT,
                    MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
                )
            }
    
            val encoderName = MediaCodecList(MediaCodecList.REGULAR_CODECS).findEncoderForFormat(mediaFormat)
    
            return MediaCodec.createByCodecName(encoderName).apply {
                configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
            }
        }
    
    private class StreamingCallBack) : MediaCodec.Callback() {
    
        override fun onInputBufferAvailable(codec: MediaCodec, index: Int) = Unit
    
        override fun onOutputBufferAvailable(codec: MediaCodec, index: Int, info: BufferInfo) {
    
           val byteBuffer = codec.getOutputBuffer(index)
           // Is the data in the buffer properly encoded as h.264 here? Did I need to use MediaExtractor?
        }
    
        override fun onOutputFormatChanged(codec: MediaCodec, format: MediaFormat) = Unit
    
        override fun onError(codec: MediaCodec, e: MediaCodec.CodecException) {
            Log.i("TEST", "onError in codec")
        }
    
    }