基于FFmpeg开发视频播放器, 基本流程(一)
刚开始学习FFmpeg,用几篇文章记录下,使用ffmpeg开发一个简单的视频播放器,大概的过程.这里只讨论核心代码,如解封装,音频的解码播放,视频的解码播放,音视频同步,不涉及UI布局.
基于FFmpeg开发视频播放器, 基本流程(一) https://blog.csdn.net/lin20044140410/article/details/104847588
基于FFmpeg开发视频播放器,视频解码播放(二) https://blog.csdn.net/lin20044140410/article/details/104849552
基于FFmpeg开发视频播放器,音频解码播放(三) https://blog.csdn.net/lin20044140410/article/details/104851476
基于FFmpeg开发视频播放器,音视频同步(四) https://blog.csdn.net/lin20044140410/article/details/104857038
http://ffmpeg.org/
一, FFmpeg是一套用来记录,转换数字音频,视频,并能将其转化为流的开源项目,拥有丰富的命令来实现音视频相关的操作,其源码是以模块化的方式进行构建,可以根据需要选择不同模块进行集成使用.
FFmpeg还可以集成第三方的库,用ffmpeg的统一接口来使用,比如常用的librtmp,libMP3lame等.
FFmpeg主要有以下几个模块:
libavformat 用于各种音视频封装格式的生成和解析
libacodec 用于声音,图像的编解码
libavfilter 用于音视频滤波器的开发.
libavutil 提供一些公共的工具函数
libswresample 用于音频格式的转码,如转成PCM流
libswscale 用于图像格式的转换,缩放,如RGB 和YUV的转换
libpostproc 用于后期效果的处理.
二, 播放器开发中涉及到的一些概念
原始数据 :能够表示完整的图像,声音的数据格式,如RGB,PCM.
编码格式:存储编码后数据的容器,如MP4,FLV等,
AVPacket 解码前的数据结构体.
AVFrame 解码后的数据结构体.
AVFormatContext 媒体文件的构成和基本信息上下文.
AVCodecContext 解码信息上下文.
三,播放器的开发流程,借用一张网上的图片:
四, 准备环境,
对音视频的处理都是在native层,所以要新建一个Native项目,当然也可以新建Android项目,然后手动添加CPP模块,
前提是要先编译好ffmpeg相关的库,静态库,动态库都行,这里用的时静态库,这个库要依据你手机CPU的架构来导入.
gradle的配置没有特别注意的地方,如果你是Android项目,要注意在build.gradle中配置:
externalNativeBuild {cmake {path "src/main/cpp/CMakeLists.txt"version "3.10.2"}}
CMakeLists.txt的配置,主要时设置源文件路径,引入头文件,链接依赖库,
cmake_minimum_required(VERSION 3.4.1)aux_source_directory(. SOURCE)
add_library( # Sets the name of the library.native-libSHARED${SOURCE})find_library( # Sets the name of the path variable.log-liblog )
include_directories(${CMAKE_SOURCE_DIR}/include)set(libs ${CMAKE_SOURCE_DIR}/armeabi-v7a)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${libs}")target_link_libraries( # Specifies the target library.native-libavfilter avformat avcodec avutil swresample swscale rtmp z android OpenSLES${log-lib} )
这里除了ffmpeg相关的库,还引入了libz.so, 这个ffmpeg链接时用到的,否则会报各种错误.
OpenSlES 是用于音频的解码和播放的.
libandroid.so ,这个库用于支持视频播放时的ANativeWindow的相关引用.
五,代码结构
Java层代码比较简单,一个Activity类,主要用来加载一个SurfaceView控件,用来渲染视频,
一个Player.java类,通过native方法,调用ffmpeg的接口,所以有一个同样名字的Player.cpp类,用来跟Player.java对接,会在Native层创建Player.cpp的对象,然后把这个对象的指针传到Java层,这样Java层再去调用Native层方法时,只要把这个指针传过去,就可以在Native层再转回Player.cpp的对象.
extern "C"
JNIEXPORT jlong JNICALL
Java_com_test_ffmpegapplication_EnjoyPlayer_nativeInit(JNIEnv *env, jobject thiz) {EnjoyPlayer * enjoyPlayer = new EnjoyPlayer(new JavaCallHelper(javaVm, env, thiz));return (jlong) enjoyPlayer;
}extern "C"
JNIEXPORT void JNICALL
Java_com_test_ffmpegapplication_EnjoyPlayer_setDataSource(JNIEnv *env, jobject thiz,jlong native_handler, jstring path_) {const char* path = env->GetStringUTFChars(path_,0);EnjoyPlayer *enjoyPlayer = reinterpret_cast<EnjoyPlayer *>(native_handler);enjoyPlayer->setDataSource(path);env->ReleaseStringUTFChars(path_, path);
}
然后是几个基础类:
BaseChannel.h, 对Audio,Video的解码,显示,提取了公共的基类,这里只列出了基本的函数,完整的实现,可以下载附件查看.
class BaseChannel{
virtual void play() =0;virtual void stop() = 0;virtual void decode() = 0;//这是两个线程安全的队列,
//AVPacket 解码前的数据结构体,从媒体文件读取出的媒体数据,就放入这个队列中,SafeQueue<AVPacket *> pkt_queue;//AVFrame 解码后的数据结构体,VideoChannel中解码线程会从pkt_queue队列中取出数据,进行解码,// 解码后的数据放入frame_queue.后续的播放线程,会从frame_queue队列取出数据,进行渲染。SafeQueue<AVFrame *> frame_queue;
}
JavaCallHelper.cpp,用于native层回调java层的实现,用于通知java层,播放准备完成,可以play了,及native层出错后的提示回调.
JavaCallHelper::JavaCallHelper(JavaVM *_javaVM, JNIEnv *_env, jobject &_jobj) :javaVM(_javaVM), env(_env){//把_jobj创建成一个全局的引用,这里_jobj就是java层的EnjoyPlayer对象。jobj = env->NewGlobalRef(_jobj);//获取它的class对象,类似反射。jclass jclazz = env->GetObjectClass(jobj);jmid_error = env->GetMethodID(jclazz, "onError", "(I)V");jmid_prepare = env->GetMethodID(jclazz, "onPrepare", "()V");jmid_progress = env->GetMethodID(jclazz, "onProgress", "(I)V");
}
SafeQueue.h 一个加了锁的队列,用来存放解码前的AVPackt,和解码后的AVFrame,
在队列执行出队操作时,多加了一个标记 ,避免死锁.
//当队列是空的时候,会阻塞这里,如果这时调用了stop,因为不会再enqueue,就会一直wait在这里,//所以加了mEnable标记,在stop时,mEnable=false,唤醒等待,退出线程,
template<typename T>
class SafeQueue{int deQueue(T &value) {int ret = 0;pthread_mutex_lock(&mutex);//当队列是空的时候,会阻塞这里,如果这时调用了stop,因为不会再enqueue,就会一直wait在这里,//所以加了mEnable标记,在stop时,mEnable=false,唤醒等待,退出线程,while (mEnable && q.empty()) {pthread_cond_wait(&cond, &mutex);}if (!q.empty()) {value = q.front();q.pop();ret = 1;}pthread_mutex_unlock(&mutex);return ret;}
}
这一篇文档,先介绍这么多,从下篇开始,讨论下视频的解码,播放.
附件(源码):https://download.csdn.net/download/lin20044140410/12247488
基于FFmpeg开发视频播放器, 基本流程(一)相关推荐
- QT软件开发-基于FFMPEG设计视频播放器-软解图像(一)
QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于 ...
- QT软件开发-基于FFMPEG设计视频播放器-解码音频(三)
QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于 ...
- QT软件开发-基于FFMPEG设计视频播放器-GPU硬解、OpenGL渲染、解码音频完整例子(六)
QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于 ...
- QT软件开发-基于FFMPEG设计视频播放器-GPU硬解、OpenGL渲染(四)
QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于 ...
- 基于FFmpeg的视频播放器之一:开篇
FFmpeg的研究几乎都是从ffplay开始的,ffplay是FFmpeg自带播放器,它的源码虽然只有一个文件,但是麻雀虽小五脏俱全,播放器的基本功能都有了.初看ffplay的源码,会感觉特别绕,跳转 ...
- C++---基于ffmpeg实现视频播放器(一)
ffmpeg.exe 功能: ffmpeg.exe实现视频的转码. 命令格式 ffmpeg -i [输入文件的路径] -b:v [输出文件的码率] [输入文件的路径] 简单命令 ffmpeg -i i ...
- 基于FFmpeg的视频播放器之七:音频解码
一.流程 音频解码的流程和视频解码几乎一样,最大的区别是解码后需要进行重采样.因为解码出的AVSampleFormat格式是AV_SAMPLE_FMT_FLTP(float, planar),该格式无 ...
- 基于FFmpeg的视频播放器之四:视频解码
一.流程 1.avcodec_find_decoder 提供两种方式查找解码器,通过codecId查找avcodec_find_decoder与通过名字查找avcodec_find_decoder_b ...
- QT应用编程: 基于mdk-sdk开发视频播放器
一.环境介绍 操作系统: win10 64位 QT版本: QT5.12.6 编译器: MinGW 32 二.mdk-sdk 介绍 github 首页地址: https://github.com/ ...
最新文章
- [字符编码]Invalid byte 1 of 1-byte UTF-8 sequence终极解决方案
- Python的scrapy之爬取顶点小说网的所有小说
- C指针原理(27)-编译基本原理-语法树及其实现7
- 【机器学习】机器学习概述
- mybatis.mapper-locations 配置多个mapper路径
- 深信服安全软件产品配置概况
- 计算机网络--接入互联网方式
- leetcode 1052. 爱生气的书店老板(滑动窗口)
- CoreAnimation编程指南(一)概念
- (140)FPGA面试题-FPGA IP简介
- 比特币收购足球队,区块链准备登上绿茵场
- HTML做成信纸格式,css3实现信纸/同学录效果的示例代码
- 内置模块--又称为常用模块
- 阿里云毕龙飞:五个维度推进企业生产关系数字化
- php经过twemproxy无法delete后端memcache值的解决方法
- input只能输入数字和小数点_Python 3 学习笔记:数字和布尔
- Pr 视频效果:颜色校正
- UDP协议实现聊天小程序
- pygame 鼠标事件
- python汉语叫什么意思_Python是什么-百度经验
热门文章
- golang解析支付宝公钥证书
- 辉芒微FMD-FT60F024-RB-八位单片机
- 游戏装备强化java机制,要说装备强化,这个游戏真心最良心
- 什么是CDN?为什么要使用CDN加速?
- Vue选项: Methods方法
- golang中的gob
- Golang中的println和fmt.Println
- 联合国与LoveLove Films动画团队合作,在世界环境日为“击败塑料污染”
- 计算机专业眼睛怎么保护,[专业地带]电脑一族如何保护自己眼睛
- 蘑菇君深入源码学习Tomcat系列 (1) - Tomcat与Servlet的那些事