音视频基础
资料
- 压箱底的音视频学习资料以及面经整理 (qq.com)
- Android 音视频开发学习思路 - 灰色飘零 - 博客园 (cnblogs.com)
- FFMPEG视音频编解码零基础学习方法_雷霄骅的博客-CSDN博客_ffmpeg 雷晓华
- 播放器技术分享(1):架构设计 - 知乎 (zhihu.com)
- 从开发小白到音视频专家 - 知乎 (zhihu.com)
- Android 音视频开发入门指南 - 知乎 (zhihu.com)
- githubhaohao/LearnFFmpeg: Android FFmpeg 音视频开发教程
- 0voice/audio_video_streaming: 音视频流媒体权威资料整理,500+份文章,论文,视频,实践项目,协议,业界大神名单。 (github.com)
- huimingli/QTFFmpegSDLPlayer: 使用ffmpeg做的播放器 (github.com)
- CarGuo/GSYVideoPlayer: 视频播放器(IJKplayer、ExoPlayer、MediaPlayer) (github.com)
- yangchong211/YCVideoPlayer (github.com)
- FFmpeg简易播放器的实现1-最简版 - 叶余 - 博客园 (cnblogs.com)
- ffplay源码分析1-概述 - 叶余 - 博客园 (cnblogs.com)
FFMPEG基础
SDL基础
FFmpeg和SDL实现视频播放器
视频播放
-
函数说明
-
avformat_open_input
:打开视频文件:读取文件头,将文件格式信息存储在"fmt context"中; -
avformat_find_stream_info
:搜索流信息:读取一段视频文件数据,尝试解码,将读取到的流信息填入pFormatCtx->streams; -
avcodec_find_decoder
:利用解编码器的id获取解解码器; -
avcodec_open2
:编解码器的初始化; -
调用
av_read_frame()
从输入文件中读取视频数据包,调用avcodec_send_packet()
和avcodec_receive_frame()
对视频数据解码。 -
图像格式转换的目的,是为了解码后的视频帧能被 SDL 正常显示,因为FFmpeg解码后得到的图像格式不一定就能被SDL支持,这种情况下不作图像转换是无法正常显示的。
-
定时刷新线程 + 解码主线程,定时刷新线程按计算出的帧率发送自定义 SDL 事件,通知解码主线程。解码主线程收到 SDL 事件后,获取一个视频帧解码并显示。
-
codec:编解码器,对应数据结构 AVCodec。编码器将未压缩的原始图像或音频数据编码为压缩数据。解码器与之相反。
-
codec context:编解码器上下文,对应数据结构 AVCodecContext。此为非常重要的一个数据结构,后文分析。各API大量使用 AVCodecContext 来引用编解码器。
-
codec par:编解码器参数,对应数据结构 AVCodecParameters。新版本增加的字段。新版本建议使用 AVStream->codepar 替代 AVStream->codec。
-
packet:经过编码的数据包,对应数据结构 AVPacket。通过 av_read_frame() 从媒体文件中获取得到的一个 packet 可能包含多个(整数个)音频帧或单个视频帧,或者其他类型的流数据。
-
frame:未编码的原始数据帧,对应数据结构 AVFrame。解码器将 packet 解码后生成 frame。
-
plane:如 YUV 有 Y、U、V 三个 plane,RGB 有 R、G、B 三个 plane。
音频播放
此处指播放视频文件里面的音频,即仅播放视频文件中的声音,而不显示图像。
注意:
- 一个音频 packet 中含有多个完整的音频帧,此函数每次只返回一个 frame,当 avcodec_receive_frame() 指示需要新数据时才调用 avcodec_send_packet() 向编码器发送一个 packet;
- 音频 frame 中的数据格式未必被 SDL 支持,对于不支持的音频 frame 格式,需要进行重采样,转换为 SDL 支持的格式声音才能正常播放;
- 解码器内部会有缓冲机制,会缓存一定量的音频帧,不冲洗(flush)解码器的话,缓存帧是取不出来的,未冲洗(flush)解码器情况下,avcodec_receive_frame() 返回 AVERROR(EAGAIN),表示解码器中改取的帧已取完了(当然缓存帧还是在的),需要用 avcodec_send_packet() 向解码器提供新数据;
- 文件播放完毕时,应冲洗(flush)解码器。冲洗(flush)解码器的方法就是调用 avcodec_send_packet(…, NULL),然后按之前同样的方式多次调用 avcodec_receive_frame() 将缓存帧取尽。缓存帧取完后,avcodec_receive_frame() 返回 AVERROR_EOF。
视频播放原理
从**解复用器(Media Extractor、AVFormatContetext->stream)**开始,会有两个线程分别负责解析音频和视频。
视频录制原理
音频:PCM->ACC数据,视频:YUV->H264,音视频封装:FLV / MP4。
视频基础
I帧是一个关键帧,能够独立解码并显示画面,可指定I帧出现的频率。
常用的是H264。