MediaCodec解码过程
1解码流程
解码流程大致分为创建解码器,配置解码器,解码操作,释放解码器。
1.1创建解码器
创建解码器可以直接创建默认的,也可以通过两种方式来创建,分别是:视频类型和解码器名。
指定视频类型的创建接口是:createDecoderByType(type),示例代码:
try { mCodec = MediaCodec.createDecoderByType("video/avc"); } catch (IOException e) { throw new RuntimeException("Failed to create codec", e); }
指定解码器创建接口是:createByCodecName(decoderName)。示例代码:
try { mCodec = MediaCodec.createByCodecName("OMX.ffmpeg.h264.decoder"); } catch (IOException e) { throw new RuntimeException("Failed to create codec", e); }
这一步调用了MediaCodec的private构造函数创建了MediaCodec对象,并调用native_setup来初始化native_setup<->android_media_MediaCodec_native_setup,这里创建JMediaCodec对象,JMediaCodec实例对应的接口调到真正的MediaCodec.cpp相关借口,真正实现编解码相关流程是在MediaCodec.cpp中实现。
1.2配置解码器
配置解码器需要构造一个MediaFormat对象作为参数,MediaFormat需要指定视频的格式,width和height,以及sps,这个是编码时产生的第一帧数据,配置帧csd-0。如果需要将解码后的数据直接输出到Surface,则需要传入一个Surface对象。示例代码:
MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height); // little tricky here, csd-0 is required in order to configure the codec properly // it is basically the first sample from encoder with flag: BUFFER_FLAG_CODEC_CONFIG format.setByteBuffer("csd-0", csd0); mCodec.configure(format, surface, null, 0);
这一步会把MediaFormat所携带的各种信息,通过native_configure方法传递到JNI层,对应android_media_MediaCodec.cpp的方法是android_media_MediaCodec_native_configure,该接口会调用到MediaCodec.cpp的configure,完成解码器的配置。大致流程如下
configure(format, surface, null, 0)(MediaCodec.java)
->native_configure(keys, values, surface, crypto, descramblerBinder, flags)(MediaCodec.java)
->android_media_MediaCodec_native_configure(android_media_MediaCodec.cpp)
->JMediaCodec.configure(format, bufferProducer, crypto, descrambler, flags)(android_media_MediaCodec.cpp)
->configure(format, mSurfaceTextureClient, crypto, descrambler, flags)
(MediaCodec.cpp)
mCodec是MediaCodec.cpp实例进入MediaCodec的configure函数,只能配置一次,如果需要重新配置需要调用stop接口,让解码器进入Uninitialized状态,才可以进行重新配置,不然设置会报错误码-38。MediaFormat对象在MediaCodec.cpp的configure函数中,被重新封装成一个AMessage对象。
本步骤结束后,解码器进入Configured状态。
1.3解码操作
在解码器配置号以后,可以调用mCodec.start()接口,Codec会转入 Executing 状态。start后Codec立即进入 Flushed 子状态,此时的Codec拥有所有的input and output buffers,Client无法操作这些buffers。在 Executing状态下可以调用 MediaCodec.flush()方法使MediaCodec进入 Flushed 子状态。
解码分为两个平行的过程,1.填充已编码的数据;2.获取已解码的数据。一般会分为两个线程来实现,一个填充线程,一个消费线程,当然也支持一个线程搞定,先填充后解码,一帧一帧的处理(我们在云手机项目上的相机就是使用的该方案)。
1.3.1填充数据
Client通过调用 MediaCodec.dequeueInputBuffer(...)请求得到了一个有效的input buffer index,Codec进入到 Running 子状态,这个状态下Codec会进行实际的数据处理。获取到buffer的index之后,需要调用MediaCodec.getInputBuffer(index)来直接获取到ByteBuffer,然后把需要解码的数据填充到ByteBuffer里,再调用MediaCodec.queueInputBuffer(...)进行解码。实例代码:
int index = mCodec.dequeueInputBuffer(mTimeoutUs); if (index >= 0) { ByteBuffer buffer; // since API 21 we have new API to use if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { buffer = mCodec.getInputBuffers()[index]; buffer.clear(); } else { buffer = mCodec.getInputBuffer(index); } if (buffer != null) { buffer.put(data, offset, size);//填充数据 mCodec.queueInputBuffer(index, 0, size, 0, 0); } }
每个MediaCodec的操作,最终都会通过JNI层android_media_MediaCodec.cpp调到native层的MediaCodec.cpp中,至于最终用的哪个解码器,是由系统自动决定的,如果是指定了解码器(常用的OMX.ffmpeg.h264.decoder,OMX.google.h264.decoder),则会使用Client端指定的解码器。是硬解码还是软解码,这个也是由系统决定的,如果没有硬件解码则会转为软件解码(x86的PC上使用时,没有软解码,FFMPG同时支持软解码和硬解码)
1.3.2消费解码数据
Client通过调用MediaCodec.dequeueOutputBuffer(...)请求得到了一个有效的output buffer index,需要传入一个MediaCodec.BufferInfo实例,用以存储解码数据,获取到buffer的index后调用MediaCodec.releaseOutputBuffer(...)来释放缓冲区数据到Surface或者你的BufferInfo。实例代码:
if (index >= 0) { // setting true is telling system to render frame onto Surface mCodec.releaseOutputBuffer(index, true); if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) == MediaCodec.BUFFER_FLAG_END_OF_STREAM) { break; } }
1.4释放解码器
当MediaCodec数据处理任务完成时或不再需要MediaCodec时,可使用 MediaCodec.release()方法释放其资源。实例代码:
if (mConfigured) { mCodec.stop(); mCodec.release(); }
相关推荐
MediaCodec 实现h264硬编解码全过程,视频数据从摄像头读出 yv12格式,转换为I420,投递给encoder,再从encoder取出编码后的h264数据投递给decoder后显示到surfaceView; 实现了udp将h264数据发送到指定主机,可通过...
在这个特定的示例中,我们关注的是如何使用MediaCodec解码AAC(Advanced Audio Coding)音频,并通过AudioTrack将其播放出来。让我们深入探讨这个过程的细节。 首先,AAC是一种高效的有损音频压缩格式,广泛应用于...
Android 使用 MediaCodec 编解码总结 Android 中使用 MediaCodec 类实现视频文件的硬解码和硬编码是非常重要的技术。MediaCodec 是 Android 提供的一个多媒体编解码器,能够实现视频和音频的编解码。下面将详细介绍...
在Android平台上,MediaCodec是系统提供的一个核心API,用于处理媒体数据的编码和解码,尤其是在硬件加速的情况下。本文将深入探讨如何利用Android的Mediacodec进行硬编解码,以及如何实现在两个Surface上同时预览和...
以上是使用MediaCodec进行硬解码的基本流程,实际应用中可能需要处理更多细节,例如处理SPS、PPS信息、处理B帧、处理不同类型的NAL单元、同步音频和视频播放等。同时,考虑到兼容性问题,需要检查设备是否支持硬件...
5. **使用流程**:使用MediaCodec进行解码通常包括以下步骤: - 创建MediaCodec实例,指定要解码的媒体格式。 - 将编码后的数据送入输入缓冲区。 - 当MediaCodec准备好输出数据时,获取输出缓冲区并解封数据。 -...
将Camera数据显示到OpenGL ES渲染的图像中,并通过MediaCodeC 将 OpenGL ES 缓冲数据,硬编码写入到 mp4 视频文件中,完成视频的录制。 文件介绍请见: https://xiaxl.blog.csdn.net/article/details/72530314 ...
在Android平台上,MediaCodec是一个核心组件,用于处理多媒体数据的编码和解码。它提供了对硬件加速编码和解码的支持,极大地提高了性能和效率。在本文中,我们将深入探讨如何使用MediaCodec播放文件,以及如何将PES...
本篇将详细探讨如何使用MediaCodec解码H264原始视频数据,并结合socket实现实时传输。 首先,H264是一种高效的视频编码标准,广泛应用于网络视频传输、数字电视等领域。它的主要优点在于能够在较低的比特率下保持较...
在Android平台上,MediaCodec是一个关键组件,用于处理多媒体数据的编码和解码。在本话题中,我们将深入探讨如何在Native层实现MediaCodec进行H264视频编码,这是一个高效且广泛使用的视频压缩标准。文章《Android ...
首先,Android的MediaCodec API是系统提供的低级接口,用于处理多媒体编码和解码任务。它能够直接访问设备的硬件加速器,以高效地编码或解码视频流。在我们的例子中,MediaCodec用于将摄像头捕获的原始图像数据转换...
在Android平台上,MediaCodec是一个关键的组件,用于处理音频和视频编码与解码。这个组件直接与硬件加速的媒体处理功能进行交互,为开发者提供了高效、低延迟的媒体处理能力。MediaCodecExample是一个开源项目,它...
整个流程涉及到文件读取、数据分包、MediaExtractor用于从文件中提取媒体数据,MediaCodec进行解码,以及Surface显示。 解码H264文件播放与解码MP4类似,只是数据来源不同。在这种情况下,可能H264数据是直接从网络...
本文将深入探讨Android的硬件编解码器(MediaCodec)以及与其密切相关的SurfaceView渲染技术。 首先,MediaCodec是Android系统提供的一种低级API,用于访问设备的硬件编解码能力。它允许开发者直接控制媒体数据的...
解码流程主要包括以下几个步骤: 1. 读取视频流数据,通常是TS、MP4或其它容器格式中的NAL单元。 2. 将NAL单元包装成AVPacket,这是FFmpeg中的数据包结构。 3. 调用`avcodec_send_packet()`发送AVPacket到解码器,这...
5. **解码流程**:编码后的H264 bitstream数据被送入另一个MediaCodec实例,该实例作为解码器。解码器将编码数据还原成原始的视频帧,然后这些帧可以被显示在Surface上。 6. **Surface**:在Android中,Surface是...
这个项目可能包含了初始化MediaExtractor、MediaCodec、AudioTrack的代码,以及数据提取、解码、播放的流程控制。 通过理解以上知识点,开发者能够构建一个在Android平台上实现AAC音频解码播放的应用。然而,实际...
在Android平台上,MediaCodec是系统提供的一个核心API,用于实现音频和视频的硬件编码与解码功能。这个库使得开发者可以高效地处理多媒体数据,利用设备的硬件加速能力,提高性能并减少功耗。本文将深入探讨...
学习者可以通过实际操作,深入了解Android开发的整个流程,提升自己的实战能力。 此外,我们还提供了一系列练习题,旨在巩固所学知识,检验学习成果。这些练习题既有基础题,也有难度较高的挑战题,适合不同层次的...
5. **解码流程**: 视频解码通常分为以下几个步骤:加载视频文件,解析容器格式,找到视频流,选择合适的解码器,然后将编码后的数据送入解码器进行解码,生成原始的YUV数据,最后显示在屏幕上。 6. **Android ...