Android音视频开发框架(下)
内容提要
本文介绍了Android音视频开发结构中的音视频读取和解码过程,包括使用MediaExtractor类进行音视频读取和使用MediaCodec类进行音视频解码。音视频播放依靠TextureView和AudioTrack等组件,音视频同步通过比较解码出来的帧的时刻戳和独立时刻轴的时刻戳来实现。文章还提到了播放/暂停、获取预览图和播放进度条等功能。
延伸解读
MediaExtractor:解封装的关键角色
文章将MediaExtractor视为MediaMuxer的逆过程,后者负责封装写入,前者负责解封装读取。它从MP4文件中提取编码后的音频和视频轨迹,通过getTrackFormat区分类型,selectTrack选择轨迹,readSampleData读取采样数据,advance推进指针。由于音频和视频在独立线程中处理,读取也分两个线程互不干扰,这种设计为后续解码提供了清晰的数据源。
音视频解码的异步回调与输出差异
解码使用MediaCodec,采用异步回调模式。视频解码在onInputBufferAvailable中读取数据并queueInputBuffer,在onOutputBufferAvailable中通过releaseOutputBuffer(index, true)将数据直接渲染到Surface;音频解码则releaseOutputBuffer(index, false),并将输出缓冲区数据写入AudioTrack。两者都需在configure时传入MediaFormat,并分别运行在独立的HandlerThrea
音视频同步:独立时间轴与暂停处理
同步的核心是维护一条独立时间轴,以解码开始时刻为起点。每次解码输出后,比较帧的PTS与独立时间轴已流逝时间,若PTS大于已流逝时间则休眠等待。暂停时需记录暂停时长,恢复后调整起点或减去暂停时长,否则时间轴持续流逝会导致同步错误。文章也提到Android的MediaSync可辅助同步,但未深入。
播放组件的分工与协作
视频播放依赖TextureView或SurfaceView,通过SurfaceTextureListener在Surface可用时将其传给解码器,实现视频帧渲染。音频播放则完全在后台,使用AudioTrack,需根据音频格式配置采样率、声道和编码,并调用play()和write()写入数据。两者路径不同,但需协同工作,且音频解码通常与视频解码同时触发。
Q&A
Android音视频开发中如何读取音视频数据?
音视频数据读取依赖于MediaExtractor类,主要通过设置数据源、获取轨迹数、选择轨迹等方法进行操作。
MediaExtractor的主要功能是什么?
MediaExtractor用于从文件中提取编码过的音频和视频信息,支持读取采样数据和轨迹选择等功能。
Android中音视频解码是如何实现的?
音视频解码使用MediaCodec类,视频解码通过SurfaceView或TextureView进行,音频解码则在后台进行。
如何实现音视频同步?
音视频同步通过比较解码帧的时刻戳与独立时刻轴的时刻戳来实现,确保音视频在播放时保持一致。
在Android中如何播放音频和视频?
音视频播放依赖于TextureView等组件,音频播放则通过音频设备进行,二者的播放方式不同。
暂停和恢复播放时需要注意什么?
暂停和恢复播放时需要记录暂停时长,以保持音视频同步,避免时刻戳不一致。