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 设置url
        mp_->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;
    //字符串,就是一个播放url
    char *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);
    // 调用ffplayer
    int 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;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis限流插件

Redis限流插件: 1:搭建层级结构 同时对 redis.log 授权 chmod 777 redis.log2:确认 redis 版本 3:下载redis配置文件 redis.conf https://redis.io/docs/management/config/ 4:上传/redis/conf作为原始 redis.conf 5:在/redis_6390/conf下编辑redis.conf docker run -it \ --…

ORB-SLAM3中的IMU预积分

ORB-SLAM3中IMU预积分 文章目录 ORB-SLAM3中IMU预积分1读取IMU参数2 预积分噪声递推与预测2.1 更新预积分测量值dP和dV2.2 更新预积分噪声项的递推模型的矩阵A和B部分元素2.3 位置、速度预积分测量值对零偏的雅可比矩阵2.4 更新旋转预积分测量2.5 补充A和B矩阵剩余部分&#xf…

【SpringBoot整合系列】SpringBoot整合Shiro——权限控制

目录 安全框架?安全框架都有哪些&#xff1f; 什么是RBAC?ShiroShiro核心组件Shiro的运行机制 SpringBoot整合Shiro整合思路1.引入依赖2.项目结构及配置3.创建前端页面index.jsplogin.jsp 4.自定义Realm5.自定义配置类6.启动测试 认证和退出1.在index.jsp添加a标签2.Controll…

IIS服务器更换即将过期的SSL证书

公司IIS服务器证书快要过期&#xff0c;替换证书的步骤&#xff1a; Winr输入mstsc命令&#xff0c;显示远程登录&#xff1b;输入服务器IP以及密码&#xff0c;进行远程登陆登陆IIS服务器&#xff0c;winr输入inetmgr命令显示IIS操控器&#xff1b;选择服务器证书--点击服务器…

【数据结构】05树

树 树1.2 结点的分类1.3 结点间的关系1.4 树的其他概念1.5 树的性质 2. 二叉树2.1 满二叉树2.2 完全二叉树2.3 二叉排序树&#xff08;二叉查找树&#xff09; 3. 二叉树的存储结构3.1 二叉树顺序存储结构3.2 二叉树的链式存储结构 4. 二叉树的遍历4.1 层次遍历4.1 前序遍历4.2…

服务器代理

服务器代理 配置&#xff1a;64G内存1 3090&#xff08;24g&#xff09;1P4000&#xff08;8g&#xff09; SSH连接 工作路径&#xff1a;/home/ubuntu/workspace/python Anaconda路径&#xff1a;/home/Ubuntu 1.在工作路径下创建自己的文件夹作为workspace 2.以用户ubunbtu登…

Java技术学习|SpringBoot面试篇

学习材料声明 黑马程序员黑马程序员SpringBoot3Vue3全套视频教程&#xff0c;springbootvue企业级全栈开发从基础、实战到面试一套通关 经过了基础知识后端开发前端开发&#xff0c;终于到了面试篇。 前置知识 1.ApplicationContextInitializer 首先&#xff0c;SpringBoot…

(学习日记)2024.04.16:UCOSIII第四十四节:内存管理

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

【GD32】MQ-8氢气检测传感器

2.36 MQ-8氢气检测传感器 MQ-8气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(Sn0s)。当传感器所处环境中存在氢气时&#xff0c;传感器的电导率随空气中氢气浓度的增加而增大。使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的输出信号。MQ-8气体…

数字乡村发展新模式:科技创新引领农业现代化与乡村振兴协同发展

随着信息技术的飞速发展&#xff0c;数字乡村已成为新时代农业现代化与乡村振兴协同发展的新模式。科技创新作为推动这一模式的核心动力&#xff0c;正引领着乡村产业结构的优化升级&#xff0c;促进农村经济的全面振兴&#xff0c;让农民在现代化的进程中共享发展成果。 一、科…

VUE_H5页面跳转第三方地图导航,兼容微信浏览器

当前项目是uniapp项目&#xff0c;若不是需要替换uni.showActionSheet选择api onMap(address , organName , longitude 0, latitude 0){var ua navigator.userAgent.toLowerCase();var isWeixin ua.indexOf(micromessenger) ! -1;if(isWeixin) {const mapUrl_tx "…

Python数据分析案例39——电商直播间评论可视化分析(LDA)

1. 引言 1.1 直播电商的发展背景 随着互联网技术的飞速发展&#xff0c;电商行业迎来了新的变革——直播电商。直播电商是一种结合了直播技术和电子商务的新型销售模式。在这种模式下&#xff0c;商家或主播通过实时视频直播的方式&#xff0c;展示产品并与消费者互动&#x…

ipad协议847最新版

iPad协议是一种模拟iPad端微信的人工操作&#xff0c;并与微信服务器进行通信的协议。该协议涉及到一些关键点&#xff0c;包括PB协议、mmtls、07加密算法、rqt算法、aes加密、rsa加密等。只要理解了这些关键点&#xff0c;就可以模拟官方微信的所有功能&#xff0c;并且还可以…

AndroidAutomotive模块介绍(二)应用及接口介绍

前言 上一篇文章中从整体角度描述了 Android Automotive 模块。本篇文章将对 Android Automotive 中的 APP 以及 API 部分展开描述。 上一篇&#xff1a;AndroidAutomotive模块介绍&#xff08;一&#xff09;整体介绍 下一篇&#xff1a;AndroidAutomotive模块介绍&#xff0…

自然语言处理NLP:文本预处理Text Pre-Processing

大家好&#xff0c;自然语言处理(NLP)是计算机科学领域与人工智能领域中的一个重要方向&#xff0c;其研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。本文将介绍文本预处理的本质、原理、应用等内容&#xff0c;助力自然语言处理和模型的生成使用。 1.文本…

SqlServer功能性配置选择

功能性配置 下面的是必选的

SpringBoot整合Nacos

文章目录 nacosnacos下载nacos启动nacos相关配置demo-dev.yamldemo-test.yamluser.yaml 代码pom.xmlUserConfigBeanAutoRefreshConfigExampleValueAnnotationExampleDemoApplicationbootstrap.yml测试结果补充.刷新静态配置 nacos nacos下载 下载地址 一键傻瓜试安装即可,官…

5.0 HDFS 集群

5.0 HDFS 集群 分类 编程 HDFS 集群是建立在 Hadoop 集群之上的&#xff0c;由于 HDFS 是 Hadoop 最主要的守护进程&#xff0c;所以 HDFS 集群的配置过程是 Hadoop 集群配置过程的代表。 使用 Docker 可以更加方便地、高效地构建出一个集群环境。 每台计算机中的配置 Hado…

【Python】读取时间判定操作次数问题和一些解决办法

几种类 datetime.striptime() 计算两个字符串之间的时间差 datetime.striptime()计算两个字符串之间的时间差 datatime类提供函数处理日期和时间 Striptime()分析字符串值以固定格式表示时间然后存储为函数参数 输出就是&#xff1a; time.sleep() time模块打印时间按照对…

动态规划-路径问题

文章目录 1. 不同路径&#xff08;62&#xff09;2. 不同路径 II&#xff08;63&#xff09;3. 珠宝的最高价值&#xff08;LCR 166&#xff09;4. 下降路径最小和&#xff08;931&#xff09;5. 最小路径和&#xff08;64&#xff09;6. 地下城游戏&#xff08;174&#xff09…