QT 6.6.0 + FFmpeg + SDL2实现视频播放器(视频和音频同时播放-改进)

B站视频讲解

GitHub源码下载地址

目录

实现思路

音频播放核心部分

第一点:互斥锁Mutex + 条件变量Cond

第二点:音频格式转换

第三点:窗口关闭事件触发


初学案例教程
QT6.6.0实现打开电脑摄像头或其他的外接摄像头(实现拍照功能)
QT6.6.0实现简单的录音器
QT6.6.0实现一个简单的视频和音频播放器
QT6.6.0实现简单的视频录制(包含语音录制)器
QT6.6.0关于QMediaMetaData功能以及列子说明使用方法
QT6.6.0实现QtCamera功能(拍照,录像以及图像和视频的相关配置)
T6.6.0实现更好的视频播放器(前期改进)
QT6.6.0实现图表如饼图,柱状图,散点图以及盒图等的基本使用
QT6.6.0实现客户端Socket编程以及socket测试软件通信
QT6.6.0 实现服务端Server和多个客户端Client通信以及socket测试软件通信
QT6.6.0 实现QNetworkAccessManager的基本应用以及其拓展使用
QT6.6.0 实现服务端Server和多个客户端Client互相发送文件信息
QT6.6.0和QT6.0以下的版本实现FTP文件上传和下载(过程详解)
QT6.6.0实现QNetworkInterface网络接口,QHostAddress网络地址IP以及域名解析等相关信息查询。
QT6.6.0基于QTcpSocket和QTcpServer实现多个客户端群聊
QT6.6.0实现基于UDP协议的简单通信(过程详解)
QT 6.6.0基于UDP协议实现广播和多播机制(过程详解)
QT 6.6.0基于UDP协议实现群聊功能(过程详解)
QT 6.6.0中OpenCV两种环境的配置方法以及基本使用例子
QT 6.6.0 中基于OpenCV的图像变换以及基于鼠标点击移动事件的图像绘制
QT 6.6.0 基于OpenCV对图像进行旋转,缩放和裁剪等操作
QT 6.6.0 基于OpenCV实现图像风格的改变(add和subtract)
PyTorch 训练之后的网络模型.pth转.onnx文件并对图像进行预测
QT 6.6.0 基于OpenCV加载.pth模型文件转换之后的ONNX模型文件,并且实现图像分类
QT 6.6.0 基于OpenCV中的cv::dnn::ClassificationModel实现图像分类
yolov5目标检测和QT 6.6.0 基于OpenCV加载yolov5.onnx模型文件实现目标检测
FCN图像分割和QT 6.6.0 加载分割FCN_Resnet50.ONNX模型文件进行图像分割(过程详解)
QT 6.6.0 中基于SDL2库实现WAV音频格式的播放(过程详解)
QT 6.6.0 中SDL2库的基本使用以及利用SDL2库创建的界面实现音频播放(过程详解)
QT 6.6.0 中基于SDL2,SDL2_ttf,SDL2_image,SDL2_mixer实现音频播放器(改进版)
QT 6.6.0 + SDL2 + SDL2_mixer实现音频播放器(改进)
QT 6.6.0 中基于FFmpeg + SDL2 + SDL2_mixer实现音频录音(过程详解)
QT 6.6.0 + FFmpeg + SDL2实现MP4视频播放(过程详解)

        在前面的文章QT 6.6.0 + FFmpeg + SDL2实现MP4视频播放 已经实现了一个简单的视频播放,但是前面实现的视频播放功能中不包含音频播放,并且界面也实现的比较简单,只是一个简单视频播放弹出窗口。因此,本文基于上一次的视频播放进行改进,不仅仅实现了视频 + 音频的播放,同时界面也更加的完善,相比于其他实现的更加容易理解。但是其中需要了解以及注意的地方非常多,这也是为什么花了比较长的时间才完成了这个功能。

        首先看一下整体实现流程:

     

实现思路

  1. 创建窗口和渲染器,用于视频文件的选择,播放以及程序关闭
  2. 选择视频MP4文件
  3. 根据打开的视频文件,得到视频流和音频流其对应的流索引号,用于后面视频帧和音频数据读取时所用
  4. 找到对应的视频流和音频流索引号的同时,分别找到对应的视频和音频解码信息
  5. 创建播放视频和播放音频的线程
    1.  视频播放线程
      1.  读取视频帧(根据视频流索引号判断当前是否为视频帧数据)
      2. 视频帧解码(视频帧的缩放和转换操作)
      3. 实时更新视频帧
      4. 将条件信号通知给音频播放线程,唤醒音频播放线程
      5. 重复上述操作
    2.  音频播放线程
      1.  读取音频数据(根据音频流索引号判断当前是否为音频数据)
      2. 加锁Mutex
      3. 等待视频播放线程的信号通知
      4. 音频数据解码(音频数据的转换操作)
      5. 将音频数据添加到音频流,播放音频
      6. 解锁Mutex
  6. 视频播放完成之后,关闭播放窗口,可以继续选择播放或者选择其他视频文件播放
  7. 关闭主线程窗口,完全结束视频播放。

注:关于视频帧读取以及实时更新部分,之前的文章已经讲解,请看QT 6.6.0 + FFmpeg + SDL2实现MP4视频播放(过程详解) 

音频播放核心部分

第一点:互斥量Mutex + 条件变量Cond

互斥锁和条件变量的简单例子

  • 创建互斥量和条件变量
mutex = SDL_CreateMutex();
cond = SDL_CreateCond();
  • 加锁和解锁
ret = SDL_LockMutex(mutex);
if(ret == 0){
      .....执行程序
      SDL_UnlockMutex(mutex);
}else{
      printf("lock is failed");

}
  • 等待条件变量和发送信号(唤醒等待在条件变量上的线程)
SDL_CondWait(cond, mutex);
SDL_CondSignal(cond);

   注:其实在使用加锁解锁的中间部分代码并没有对其出现异常以及等其他的情况的过多考虑,读者可以去完善这一点,因为如果加锁解锁的中间部分出现异常等其他情况时,导致不能解锁,最后造成死锁情况。

第二点:音频格式转换

  • swr_alloc()用于分配并初始化一个 SwrContext 结构体,这是进行音频重采样的上下文。

  • swr_alloc_set_opts2(): 用于设置音频重采样器的参数,如源和目标采样率、源和目标通道布局、源和目标样本格式等。

  • swr_init(): 根据 swr_alloc_set_opts2() 设置的参数初始化音频重采样器。

  • swr_convert(): 用于执行实际的音频重采样转换。

  • swr_free(): 释放与音频重采样器相关联的资源。

int swr_alloc_set_opts2(struct SwrContext **ps, //创建的上下文结构体
                        const AVChannelLayout *out_ch_layout,  //输出通道布局 比如AV_CHANNEL_LAYOUT_*
                        enum AVSampleFormat out_sample_fmt, //输出采样格式 比如AV_SAMPLE_FMT_*
                        int out_sample_rate, //输出采样比率,就是频率freq
                        const AVChannelLayout *in_ch_layout, //输入通道布局,同上
                        enum AVSampleFormat  in_sample_fmt, //输入采样格式,同上
                        int  in_sample_rate, //输入采样比率,同上
                        int log_offset, //日志偏移 一般为0
                        void *log_ctx); //日志上下文 一般为NULL

获取最大输出采样,用于后面对音频数据的转换: 

获取下一个输入样本相对于下一个输出样本将经历的延迟。
swr_get_delay(struct SwrContext *s, int64_t base)
其中base参数的几种不用输入:
①如果设置为1,则返回的延迟以秒为单位
②如果设置为1000,返回的延迟以毫秒为单位
③如果设置为输入采样率,则返回延迟是在输入样本中
④如果设置为输出采样率,则返回延迟是在输出样本
⑤如果它是in_sample_rate和的最小公倍数out_sample_rate则精确的无舍入延迟将是返回
av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
用于在获取时间(通常是使用 AVRational 结构表示的时间单位)和
更高精度的时间单位之间进行转换,并且支持四舍五入选项。
src:需要转换的源时间,由 int64_t 形式的时间戳表示,通常是以某种时间单位(例如帧数、采样数等)表示            
     的值。
src_tb:源时间的时间基(time base),表示源时间戳的单位。
dst_tb:目标时间的时间基,表示目标时间戳的单位。
rounding:是一个枚举类型 AVRounding,指示如何处理舍入。包含的值包括:
    AV_ROUND_NEAR:将值四舍五入到最接近的整数。
    AV_ROUND_INF:向正无穷大方向舍入。
    AV_ROUND_DOWN:向下舍入。
    AV_ROUND_UP:向上舍入。

第三点:获得缓冲区大小和用样本格式sample_fmt填充样本的平面数据指针和行大小

注:关于av_samples_get_buffer_sizeav_samples_fill_arrays参数不再详细解释,其实和视频播放 博文中所讲的av_image_get_buffer_sizeav_image_fill_arrays是相呼应的,参数都比较好理解。

最后:窗口关闭事件触发

QT 6.6.0 + FFmpeg +SDL2实现视频播放器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值