FFmpeg: 自实现ijkplayer播放器--05ijkplayer–连接UI界面和ffplay.c

文章目录

      • ijkplayer时序图
      • 消息循环--回调函数实现
      • 播放器播放时状态转换
        • 播放
        • 停止
      • ijkmediaPlay
        • 成员变量
        • 成员函数

ijkplayer时序图

请添加图片描述
stream_open:
frame_queue_init
packet_queue_init
init_clock
创建read_thread线程
创建video_refresh_thread线程

消息循环–回调函数实现

ui 和播放器核心直接的交互有以下几种方式:

  1. ui直接调用IjkMediaPlayer的接口
  2. ui发送消息给消息循环线程,然后调⽤IjkMediaPlayer的接口
  3. IjkMediaPlayer发消息给消息循环线程,线程调⽤ui的接口

UI发送消息给循环线程,通过c++11中bind实现回调函数:
void MainWind::OnPlayOrPause() {
mp_ = new IjkMediaPlayer();
mp_->ijkmp_create(std::bind(&MainWind::message_loop, this, std::placeholders::_1))
mp_->ijkmp_prepare_async();

}

ijkmp_create: msg_loop函数赋值给ijkMediaPlay函数指针msg_loop
int IjkMediaPlayer::ijkmp_create(std::function<int (void *)> msg_loop)
{
msg_loop_ = msg_loop;
}

ijkMediaPlay的成员函数ijk_msg_loop,调用msg_loop_函数指针
int IjkMediaPlayer::ijkmp_msg_loop(void *arg)
{
msg_loop_(arg);
return 0;
}

jikMediaPlay在ijkmp_prepare_async中启动线程,调用ijk_msg_loop
int IjkMediaPlayer::ijkmp_prepare_async()
{
// 创建循环线程
msg_thread_ = new std::thread(&IjkMediaPlayer::ijkmp_msg_loop, this, this);
}

至此,调用MainWind中调用ijkmp_prepare_async即可实现message_loop消息循环函数回调

void MainWind::OnPlayOrPause()
{qDebug() << "OnPlayOrPause call";int ret = 0;// 1. 先检测mp是否已经创建if(!mp_) {mp_ = new IjkMediaPlayer();//1.1 创建ret = mp_->ijkmp_create(std::bind(&MainWind::message_loop, this, std::placeholders::_1));if(ret <0) {qDebug() << "IjkMediaPlayer create failed";delete mp_;mp_ = NULL;return;}// 1.2 设置urlmp_->ijkmp_set_data_source("2_audio.mp4");// 1.3 准备工作ret = mp_->ijkmp_prepare_async();if(ret <0) {qDebug() << "IjkMediaPlayer create failed";delete mp_;mp_ = NULL;return;}} else {// 已经准备好了,则暂停或者恢复播放}
}

播放器播放时状态转换

IjkMediaPlayer 成员函数:mp_state_,表示播放状态

播放

ijkmp_create
ijkmp_set_data_source
ijkmp_prepare_async
然后等待消息MP_STATE_PREPARED再调⽤ijkmp_start启动播放。

停止

先调⽤ijkmp_stop
再调⽤ijkmp_destroy (ijkplayer⾥⾯是通过release调⽤destro

ijkmediaPlay

成员变量
std::mutex mutex_;// 真正的播放器FFPlayer *ffplayer_ = NULL;//函数指针, 指向创建的message_loop,即消息循环函数//    int (*msg_loop)(void*);std::function<int(void *)> msg_loop_ = NULL; // ui处理消息的循环//消息机制线程std::thread *msg_thread_; // 执行msg_loop//    SDL_Thread _msg_thread;//字符串,就是一个播放urlchar *data_source_;//播放器状态,例如prepared,resumed,error,completed等int mp_state_;  // 播放状态
成员函数
  • ijkmp_create
    创建IjkMediaPlayer
    创建FFPlayer(ffplay.c)
    保存ui传⼊的回调msg_loop函数
    初始化mutex
    最终如果失败则调⽤destroy_p
int IjkMediaPlayer::ijkmp_create(std::function<int (void *)> msg_loop)
{int ret = 0;ffplayer_= new FFPlayer();if(!ffplayer_) {std::cout << " new FFPlayer() failed\n ";return -1;}// msg_loop_ 函数指针msg_loop_ = msg_loop;ret = ffplayer_->ffp_create();if(ret < 0) {return -1;}return 0;
}
  • ijkmp_destroy
    停⽌msg_loop线程
    释放mutex
    释放自己delete this

int IjkMediaPlayer::ijkmp_destroy()
{ffplayer_->ffp_destroy();return 0;
}
  • ijkmp_prepare_async
    状态设置为MP_STATE_ASYNC_PREPARING(正在准备)
    启动消息队列msg_queue_start
    调用FFplayer的prepare_async_l
int IjkMediaPlayer::ijkmp_prepare_async()
{// 判断mp的状态// 正在准备中mp_state_ = MP_STATE_ASYNC_PREPARING;// 启用消息队列msg_queue_start(&ffplayer_->msg_queue_);// 创建循环线程msg_thread_ = new std::thread(&IjkMediaPlayer::ijkmp_msg_loop, this, this);// 调用ffplayerint ret = ffplayer_->ffp_prepare_async_l(data_source_);if(ret < 0) {mp_state_ = MP_STATE_ERROR;return -1;}return 0;
}
  • ijkmp_start
    先检测当前的状态是否可以转为start,删除队列⾥的FFP_REQ_START消息,删除队列⾥的FFP_REQ_PAUSE消息
    发送FFP_REQ_START消息,jkMediaPlayer的循环⾥,ijkmp_get_msg处理FFP_REQ_START,然后调⽤ffp_start_l触发播放
int IjkMediaPlayer::ijkmp_start()
{ffp_notify_msg1(ffplayer_, FFP_REQ_START);
}
  • ijkmp_stop
    先检测当前的状态是否可以执⾏stop,⽐如MP_STATE_IDLE状态就没有必要调⽤stop,删除队列⾥的FFP_REQ_START/PAUSE消息
    调⽤FFPlayer的ffp_stop_l,先请求abort_request = 1,然后暂停输出toggle_pause

int IjkMediaPlayer::ijkmp_stop()
{int retval = ffplayer_->ffp_stop_l();if (retval < 0) {return retval;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/812890.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中级物流师、高级物流师资格认证考试大纲《物流管理实务》

物流管理实务 第一章 物流市场调查 一、市场调查基本知识 二、物流市场调研 三、物流市场预测 四、物流市场调研报告 第二章 仓库规划与设计 一、仓储规划概述 二、仓库规模和数量规划 三、仓库选址规划 四、仓库的结构与布局 五、自动化立体仓库的规划与设计 第…

微服务(基础篇-008-Elasticsearch分布式搜索【上】)

目录 初识elasticsearch&#xff08;1&#xff09; 了解ES&#xff08;1.1&#xff09; 倒排索引&#xff08;1.2&#xff09; es的一些概念&#xff08;1.3&#xff09; 安装es、kibana&#xff08;1.4&#xff09; ik分词器&#xff08;1.5&#xff09; ik分词器的拓展…

Kubernetes学习笔记12

k8s核心概念&#xff1a;控制器&#xff1a; 我们删除Pod是可以直接删除的&#xff0c;如果生产环境中的误操作&#xff0c;Pod同样也会被轻易地被删除掉。 所以&#xff0c;在K8s中引入另外一个概念&#xff1a;Controller&#xff08;控制器&#xff09;的概念&#xff0c;…

html基础——CSS

在HTML中&#xff0c;CSS的作用是用于控制网页的样式&#xff0c;包括字体、颜色、背景、布局等方面的设计。通过一个样例来说明CSS的作用&#xff1a; 如下是一个名为global.css的CSS文件&#xff1a; .C1{font-size: 10px;color: blue;border:1px solid red;height: 200px;…

Springboot+Vue项目-基于Java+MySQL的旅游网站系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

免费升级至HTTPS协议教程

一、前言 HTTPS协议以其安全性和数据加密特性&#xff0c;逐渐取代HTTP成为互联网通信的主流协议。本文将为您简洁明了地介绍如何免费升级至HTTPS协议。 二、获取免费SSL证书 选择证书提供商&#xff1a;如JoySSL等提供免费SSL证书的服务。 免费申请地址https://www.joyssl.…

一键开启Scrum回顾会议的精彩时刻

其实回顾会议作为一个检视、反馈、改进环节&#xff0c;不仅在传统的瀑布管理模式中&#xff0c;还是在Scrum一类的敏捷管理流程中&#xff0c;都是非常重要的活动。一些团队认为它无法产生直接的价值&#xff0c;所以有意忽略了这个会议&#xff1b;一些团队在越来越多的回顾中…

java快速构建飞书API消息推送、消息加急等功能

文章目录 飞书机器人自定义机器人自定义应用机器人 自定义应用发送消息普通文本 text富文本 post图片 image文件 file语音 audio视频 media消息卡片 interactive分享群名片 share_chat分享个人名片 share_user 批量发送消息消息加急发送应用内加急发送短信加急 发送电话加急spr…

JavaScript入门--变量

JavaScript入门--变量 一、JS变量二、变量命名三、常量四、局部变量 一、JS变量 定义变量a, b, c&#xff0c;并输出到控制台。 var a 1; var b 13.14; var c hello Js;console.log(a, b, c) //console.log()语句用于输出结果到控制台&#xff0c;类似python的print语句…

【Java】Set集合的基本使用

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 一、HashSet集合 1.HashSet集合的特点 2.HashSet常用方法 ①&#xff1a;add(Object o)&#xff1a;向Set集合中添加元素&#xff0c;不允许添加重复数据。 ②&#xff1a;size()&#xff1a;返回Set集合中的元素个数…

Ubuntu无网络标识的解决方法

1.出现的情况的特点 2.解决办法 2.1 进入root并输入密码 sudo su 2.2 更新NetworkManager的配置 得先有gedit或者vim&#xff0c;两个随意一个&#xff0c;这里用的gedit&#xff0c;没有就先弄gedit&#xff0c;有的话直接下一步 apt-get install gedit 或者vim apt-get ins…

Docker部署Logstash同步Mysql数据到ES

1、准备配置文件文件夹 2、部署logstash & elasticsearch docker pull docker.elastic.co/logstash/logstash:7.15.0 ## 替换{你的ES地址}为ES地址 docker run -d --name logstash -p 5044:5044 -p 9600:9600 -v D:\logstash\data\:/usr/share/logstash/data -v D:\logst…

Flink学习(四)-数据管道 ETL

一、状态转换 map() 只适用于一对一的转换&#xff0c;即对每个进入算子的流元素&#xff0c;map() 将仅输出一个转换后的元素。 flatmap() 可以输出任意数量的元素&#xff0c;也可以一个都不发。 二、Keyed Streams keyBy() 相当于 sql 中的 group by&#xff0c;通过…

图片合成二维码怎么实现?图片二维码的生成技巧

图片合成二维码如何制作呢&#xff1f;现在很多的二维码都会提供图片预览的功能&#xff0c;我们可以用手机扫描二维码来查看图片的信息&#xff0c;比如很多的产品信息、旅游攻略、产品海报等等类型经常会制作这种类型的二维码。 其实图片制作二维码的方法很简单&#xff0c;…

生产者和消费者模型 | 阻塞队列 | 信号量 | 环形队列

文章目录 1.生产者和消费者模型2.生产者和消费者模型优点3.阻塞队列4.POSIX信号量5.基于环形队列的生产消费模型 本文完整的代码放在了这&#xff1a; Gitee链接 1.生产者和消费者模型 生产者和消费者模型&#xff0c;概括起来其实是一个321原则&#xff1a;3是&#xff1a;三…

Spring Boot(04):让你的Spring Boot应用“火力全开”,从零开始学习starter

1. 前言 Spring Boot是一款非常流行的Java开发框架&#xff0c;其具有快速开发、自动化配置、内嵌服务器、易于扩展等特点&#xff0c;因此备受开发者欢迎。在日常开发中&#xff0c;我们经常需要在不同的环境中进行测试和部署&#xff0c;此时&#xff0c;如何实现开发、测试、…

电子方案 红外遥控蜘蛛玩具

东莞市酷得智能科技在消费类电子市场深耕多年&#xff0c;依托于市场团队对市场的敏锐度、工程团队的技术积累、结合自身的创新以及和上游原厂深度合作&#xff0c;在2.4G通信、BLE、语音、马达驱动控制等领域&#xff0c;采用方案代理的模式&#xff0c;形成了自己的多条具有市…

k8s-配置与存储-持久化存储-NFS 挂载、StorageClass 存储类 动态创建NFS-PV案例

文章目录 Volumes (依赖本机来实现&#xff09;1.1EmptyDir1.2 HostPath NFS 挂载(依赖远程服务来实现)安装 nfs挂载 NFS 共享目录配置文件 NFS 挂在到容器里去 高级存储 PV与PVC 概念详解PV与PVC 生命周期构建绑定使用回收策略 创建PV与PVC以及关联Pod创建 PersistentVolume&a…

【Python】面向对象(专版提升2)

面向对象 1. 概述1.1面向过程1.2 面向对象 2. 类和对象2.1 语法2.1.1 定义类2.1.2 实例化对象 2.2 实例成员2.2.1 实例变量2.2.2 实例方法2.2.3 跨类调用 3. 三大特征3.1 封装3.1.1 数据角度3.1.2 行为角度3.1.3 案例:信息管理系统3.1.3.1 需求3.1.3.2 分析3.1.3.3 设计 3.2 继…

服务器 安装1Panel服务器运维管理面板

服务器 安装1Panel服务器运维管理面板 SSH链接服务器安装1Panel 出现此提示时输入目标路径&#xff0c;须以“/”开头&#xff0c;默认&#xff1a;/opt&#xff0c;本例&#xff1a;/www。 出现此提示时输入目标端口&#xff0c;须未被使用的端口&#xff0c;默认&#xff1…