
Huguang Wuwang的博客地址:
对于许多Android程序员来说,视频编解码器是Android中相对困难的知识点。在Android 4.1之前,Android没有提供硬编码的API,因此,在基本上将FFMPEG用于视频软件编码和解码。现在,FFMPEG仍然广泛用于Android编码和解码。该博客主要谈论使用Android 4.1添加的API MediaCodec和Android 4.3添加的API MediaMuxer录制MP4视频。
概述
一般而言,对于同一平台和相同的硬件环境,硬编码和硬编码的速度比软件编解码器快。此外,与软件编解码器的高CPU使用相比,硬件编解码器也具有很大的优势,因此,当硬件支持它时,一般硬件编解码器是我们的首选。
在Android中,我们可以直接使用Mediarecord录制视频,但是许多合适的Mediarecord无法满足我们的需求。例如,在我们需要在录制的视频中添加水印或其他处理后,所有平台将以相同的大小传输到服务器。
在此博客中,我们将讨论使用AudioreCord录制,并使用OpenGL渲染相机数据并进行处理。然后,使用MediaCodec将音频和视频分别编码,并且编码的音频和视频被混合并保存为MP4编码过程和代码示例。
值得注意的是,用于音频和视频编码和解码的MediaCodec是添加到Android 4.1中的新API,而用于音频和视频混合的MediaMuxer是Android 4.3中添加的新API,因此此博客中的示例仅用于Android 4.3上方的设备。
Audiorecord(记录API)
Audiorecord是比Mediarecord更基础的API。 Audiorecord也可以非常轻松地完成录制功能。 AudioreCord记录记录原始的PCM音频数据,我们可以使用Audiotrack播放PCM音频文件。
Audiorecord的最简单代码如下:
遵循上述步骤,我们可以成功记录PCM音频文件,但是就传输和存储注意事项而言,一般而言,我们不会直接记录PCM音频文件。相反,在录制过程中,音频数据以其他格式(例如AAC,MP3,WAV等)编码为其他格式。
MediaCodec(硬件编解码器API)
了解MediaCodec
在Android开发人员官方网站上详细介绍了MediaCodec的使用。官方网站上的图片可以很好地说明如何使用MediaCodec。我们只需要理解此图,然后熟悉MediaCodec API,我们可以很快开始使用MediaCodec来编码音频和视频。
对于上图,我们可以简单地理解输入式和输出袋形成圆形输送带,并且输送带上覆盖着空盒子。编解码器启动后,我们需要获取一个空盒子(DequeueInputBuffer),然后用原材料(需要编码/解码的音频/视频数据)填充空盒子,然后将其放回您取出的位置(QueueInputBuffer)。
输送带通过处理器(编解码器)后,将框中的原材料处理成您的期望(编码数据)。您可以按照原材料的顺序取出处理过的东西(DequeUeoutputBuffer),并标记您取出的东西(不需要数据标头)和包装(结合编码的框架数据)。然后,将框放回其原始位置(ReleaseOututputbuffer)。
音频编码示例
官方网站上有更多标准化的用法示例。结合上述音频录制,将其编码为AAC音频文件的示例代码如下:
AAC编码加文件标头的实现是指AAC编码规则,只需填写数据即可。在互联网上很容易找到。具体实现如下:
这样,获得的文件是AAC音频文件,可以由Android系统提供的播放器直接播放。
视频编码示例
视频的编码类似于上面音频的编码。相机的数据回调时间尚不确定。即使将相机的FPS范围设置为30-30帧,它也不会为您提供每秒30帧的数据。 Android相机的数据回调受光的严重影响。这是由HAL层的3A算法确定的。您可以关闭自动曝光补偿,自动白光等,以便获得稳定的帧速率。
当我们录制和编码视频时,我们绝对希望获得带有固定帧速率的视频。因此,在录制和编码视频的过程中,您需要考虑一些解决帧速率的方法。最简单,最有效的方法是在固定时间进行编码,如果没有新的相机数据回调,请使用上一个帧中的数据。
参考代码如下:
只要MediaCodec支持它,音频和视频编码和解码也是如此。
MediaMuxer(音频和视频混合API)
MediaMuxer非常易于使用。在Android开发人员的官方网站上的MediaMuxer API描述中,也有简单的用法示例代码:
在参考官方说明和代码示例时,我们可以知道音频和视频混合(也可以是音频和音频混合),您只需要将编码器的媒体形式添加到MediaMuxer中即可获得音频轨道视频轨道的索引,然后在编写(WriteSampleData)的轨道上,并将其添加到Expoder所在的位置,即可。
应该在这里注意到,您必须等到编码器设置编码格式,然后将其添加到混音器中。设置编码器编码格式的标志是DequeUeOutputBuffer,以获取_output_format_changed的返回值。
音频和视频记录MP4文件
上面给出了录音的代码和视频录制的代码。将其与MediaMuxer相结合可以轻松完成使用声音和图像录制MP4文件的功能。录音和视频录制的基本流程保持不变。录制和编码后,编码的结果不再写入文件流,而是写为混音器的示例数据。以视频为例,更改循环编码的代码是:
当然,在使用MediaMuxer之前,您必须创建MediaMuxer的实例:
mMuxer=new MediaMuxer(path+"."+postfix, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
音频操作与视频相同。音频编码还添加到Meidamuxer轨道中,并获得了轨道索引,并将编码的数据添加到MediaMuxer当前音频轨道的示例数据中。上面的音轨和视觉轨道都是制作的。录制完成后,发送端标志。编码完成后,可以停止混合器,并可以获得固定代码速率MP4文件。
总结
在这一点上,此博客结束了。但是,在实际使用MediaCodec和MediaMuxer时,您将始终遇到一个或另一个问题,该问题已硬编码和硬化,这与硬件密切相关。尽管Android提供了良好的API,但各种制造商将始终做一些使自己在实施过程中独一无二的事情。当然,他们的目的不是独一无二。有些是要使产品更好(尽管最终可能是一团糟),有些是为了节省金钱并使用软件来弥补硬件的缺陷。最终的结果是对于高级开发编码者来说是一项艰苦的工作。
从博客作者在使用MediaCodec和MediaMuxer的过程中遇到的问题中,我们应该总结以下几点:
MediaCodec是Android 4.1的新API,MediaMuxer是Android 4.3的新API。
彩色空间。根据Android本身,所有硬件平台应支持Color_FormatyUv420 Planar。但是实际上,情况并非如此。因此,在设置颜色空间时,您应该获得由硬件平台支持的颜色空间,以确保其支持您打算使用的颜色空间。如果不支持它,则应启用替代解决方案(使用其他当前硬件支持的颜色空间)。
视频尺寸,在某些手机上,视频录制大小可能是任意的。但是,某些手机,不支持的大小设置会导致录制的视频变得不一致。博客作者使用了Oppo R7测试和360*640视频,分别录制视频很好。混合了音频和视频后,颜色不一致,但是在360F4手机上,很好。将视频宽度和高度设置为16的倍数可以解决此问题。
编码器格式设置(例如采样率,音频编码的比特速率等)也需要与硬件平台结合使用,否则它也会导致崩溃或其他问题。这实际上与色彩空间的选择相同。
我已经在Internet上看到了许多排队式延误,将演示时间设置为System.nanotime()/1000。这样做会导致编码的音频和视频在播放过程中显示总持续时间。应该记录在开始时的纳米频率,然后应将演示时间设置为(system.nanotime() - 纳米段)/1000。
在录制结束时,应发送末端标志MediaCodec.buffer_flag_end_of_stream,当编码区域获得此标志而不是直接终止循环时,应终止循环。
应该有其他问题需要注意。我还没有遇到过。
源代码在
如果您有一篇好文章并想与您分享,请直接将其提交给我。