Android Mediacodec 解码带有大绿色填充的 h264 视频流单帧
Android Mediacodec decodes h264 video stream single frames with large green padding
我想解码服务器发送的 H.264 视频流的单帧,但是当我这样做时,结果图片有很大的填充。
代码和结果:
代码:
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 Allocating component 'OMX.qcom.video.decoder.hevc'
failed, try next one.
我想解释问题出在哪里,以便遇到相同问题的任何人都可以学习。我已经按照上面的代码设置了正确的填充。那么是什么导致了这个错误的输出呢?问题是我在 activity 中生成了 TWO 个 MediaCodec 实例,因此 OS 遇到了资源不足的情况,并给出了这个错误的结果。只有 ONE 个 MediaCodec 实例解决了这个问题。 (请注意,此问题会发生,但在具有较旧 Android 版本 (a.k.a =<8) 的手机中更可能发生。)
我想解码服务器发送的 H.264 视频流的单帧,但是当我这样做时,结果图片有很大的填充。
代码和结果:
代码:
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 Allocating component 'OMX.qcom.video.decoder.hevc' failed, try next one.
我想解释问题出在哪里,以便遇到相同问题的任何人都可以学习。我已经按照上面的代码设置了正确的填充。那么是什么导致了这个错误的输出呢?问题是我在 activity 中生成了 TWO 个 MediaCodec 实例,因此 OS 遇到了资源不足的情况,并给出了这个错误的结果。只有 ONE 个 MediaCodec 实例解决了这个问题。 (请注意,此问题会发生,但在具有较旧 Android 版本 (a.k.a =<8) 的手机中更可能发生。)