【问题标题】:Android Mediacodec decodes h264 video stream single frames with large green paddingAndroid Mediacodec 解码具有大绿色填充的 h264 视频流单帧
【发布时间】:2021-07-29 14:40:58
【问题描述】:

我想解码服务器发送的视频流的单帧,但是当我这样做时,结果图片有很大的填充。

代码和结果:

代码:

val singleFrameMediaCodec= MediaCodec.createDecoderByType("video/hevc")
mediaFormat.setInteger(
            MediaFormat.KEY_COLOR_FORMAT,
            MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible
        )

singleFrameMediaCodec.configure(mediaFormat, null, null, 0)


singleFrameMediaCodec.setCallback(object : MediaCodec.Callback() {
                        override fun onInputBufferAvailable(
                            _codec: MediaCodec,
                            index: Int
                        ) {
                            val buffer = _codec.getInputBuffer(index)
                            singleFrameMediaCodec.queueInputBuffer(
                                index,
                                0,
                                data.size,
                                0,
                                /*BUFFER_FLAG_END_OF_STREAM*/0
                            )
                        }

                        override fun onOutputBufferAvailable(
                            _codec: MediaCodec,
                            index: Int,
                            info: MediaCodec.BufferInfo
                        ) {
                            try {    
                                val info = MediaCodec.BufferInfo()
                                val outputIndex = index
                                val image: Image? = _codec.getOutputImage(outputIndex)
                                val rect = image.cropRect
                                val yuvImage = YuvImage(
                                    YUV_420_888toNV21(image),
                                    NV21,
                                    rect.width(),
                                    rect.height(),
                                    null
                                )

                                val stream = ByteArrayOutputStream()
                                yuvImage.compressToJpeg(
                                    Rect(0, 0, rect.width(), rect.height()),
                                    80,
                                    stream
                                )
                                val frameBitmap: Bitmap =
                                    BitmapFactory.decodeByteArray(
                                        stream.toByteArray(),
                                        0,
                                        stream.size()
                                    )    
                                imageView.setImageBitmap(frameBitmap)

                                _codec.stop()
                                stream.close()
                                image.close()
                                if (outputIndex >= 0) {
                                    _codec.releaseOutputBuffer(outputIndex, false)
                                }

                            } catch (e: Exception) {
                                Log.d(SLIDER_PRECISION, "errors here: " + e.toString())
                            }
                        }

                        override fun onError(
                            _codec: MediaCodec,
                            e: MediaCodec.CodecException
                        ) {
                        }

                        override fun onOutputFormatChanged(
                            _codec: MediaCodec,
                            format: MediaFormat
                        ) {
                        }
                    })
                    singleFrameMediaCodec.start();

现在结果有很多像这样的添加:

我做错了什么?重新缩放 YUV 图像没有帮助,并导致图片的尺寸为 0。 (我放了 200 和 600)

我的YUV转换代码:

public static byte[] YUV_420_888toNV21(Image image) {
    byte[] nv21;
    ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
    ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
    ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
    int ySize = yBuffer.remaining();
    int uSize = uBuffer.remaining();
    int vSize = vBuffer.remaining();
    nv21 = new byte[ySize + uSize + vSize];
    //U and V are swapped
    yBuffer.get(nv21, 0, ySize);
    vBuffer.get(nv21, ySize, vSize);
    uBuffer.get(nv21, ySize + vSize, uSize);
    return nv21;
}

我也抛出了这个异常:

android mediacodec 分配组件'OMX.qcom.video.decoder.hevc' 失败,尝试下一个。

【问题讨论】:

  • 您确定您获得了正确的配置数据吗?你能发布初始化数据吗?
  • 你是说参数?我只是多出了一行,我在代码中添加了:val mediaCodec = MediaCodec.createDecoderByType("video/hevc")
  • 我没有 BUFFER_FLAG_CODEC_CONFIG 之类的东西,也没有其他配置。只是MediaCodec.createDecoderByType("video/hevc")
  • @AliHas 确保在创建 MediaCodecFormat 时向 MediaCodecFormat 传递正确的宽度和高度

标签: java android kotlin h.264 android-mediacodec


【解决方案1】:

我想解释问题出在哪里,以便任何有相同问题的人都可以学习。我按照上面的代码设置了正确的填充。那么是什么导致了这个错误的输出呢?问题是我在活动中生成了 TWO 的 MediaCodec 实例,因此操作系统遇到资源不足并给出了这个错误的结果。只有ONE 的MediaCodec 实例解决了这个问题。 (请注意,此问题会发生,但更可能出现在具有较旧 Android 版本(a.k.a

【讨论】:

    猜你喜欢
    • 2014-02-06
    • 2017-12-16
    • 1970-01-01
    • 2019-06-21
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多