项目简介
写这个项目的初衷,是为了给初学NDK和FFMPEG的人提供一个完善的模版项目
除了实现ffmpeg解码在线视频,ndk直接绘制SurfaceView,OpenSL播放音频等基本功能
还封装了很多常用的NDK功能,设计了很完善的播放器控制机制
暂停,恢复,播放,停止,销毁,视频源切换,横竖屏切换,所有功能快速乱点也不会有问题
花了很大精力把这个项目做完善,就是为了让大家能学到更多细节上的东西
以后在NDK开发的路上就能少走弯路
通过这个项目,大家可以学习到以下知识
C++和NDK知识
CMakeLists脚本的使用
NDK同时编译多种指令集的so库
C++语法巩固
JNI集成Logcat
JNI中的线程切换和方法回调
iostream打印到Logcat
线程等待,互斥锁,条件锁,队列的组合使用
音视频知识
音视频基本原理
FFmpeg视频API的使用
OpenSL音频API的使用
音视频同步
通过ANativeWindow实现视频渲染
实现帧数据回调
业务方案
播放器功能的设计和实现
暂停、恢复、横竖屏切换等细节的高效实现方案
用户频繁操作时,如何解决高并发问题,保证操作的有序性
FFMPEG解码播放原理
代码较多,先帮大家把核心思路给提取出来了
对于对C++和NDK还不是很熟的新手,建议一行行阅读代码和博客
因为真的能学到很多比较细的东西,少走弯路,代码注释也非常全
FFMpeg::prepare 修改标志位为准备中(在复杂情况下,标志位的控制也是一种哲学,设计得好,通过标志位就能避免很多并发问题) 通过avformat_alloc_context创建格式上下文AVFormatContext 通过avformat_open_input打开url,打开成功后,AVFormatContext中会记录格式信息 通过avformat_find_stream_info查找媒体流信息,获得AVStream[] 遍历stream,获得每个stream的解码参数AVCodecParameters 通过avcodec_find_decoder,找到AVCodecParameters对应的解码器AVCodec 通过avcodec_alloc_context3创建解码上下文AVCodecContext 通过avcodec_parameters_to_context,将解码参数设置给AVCodecContext 通过avcodec_open2打开解码上下文 通过AVCodecParameters和AVCodecContext,判断stream格式是否正确 通过AVStream和AVCodecContext,创建AudioChannel和VideoChannel AudioChannel和VideoChannel分别创建decode和play线程,一个用于将AVPacket解码为AVFrame,一个用于播放AVFrame ffmpeg创建read线程,通过av_read_frame,不断从AVCodecContext中读取AVPacket,再交给channel去decode和play channel通过avcodec_send_packet将读取到的AVPacket交给AvCodecContext解码 channel通过avcodec_receive_frame从AvCodecContext获取到解码后的AVFrame VideoChannel通过SwsContext将AVFrame转化为ARGB图像,交给ANativeWindow/Surface进行渲染 AudioChannel通过SwrContext将AVFrame重采样为PCM数据,交给OpenSL进行播放 read、decode、play线程都根据ffmpeg.playing这个标志位来决定是否继续工作,初始化值为false,即只创建线程,不立刻工作 修改标志位为已准备
FFMpeg::resume 将ffmpeg.playing字段设置为true,read、decode、play线程开始工作
FFMpeg::pause 将ffmpeg.playing字段设置为false,read、decode、play线程暂停工作
FFMpeg::release 修改标志位为释放中 通过pthread_join等待ffmpeg.read线程结束 通过avformat_close_input关闭并释放AVFormatContext 通过pthread_join等待channel.decode和channel.play线程结束 通过avcodec_close关闭并释放AVCodecContext 关闭并释channel中的数据队列,再释放channel 修改标志位为已释放
源码下载
ffmpeg-MediaPlayer.zip