GStreamer —— 2.15、Windows下Qt加载GStreamer库后运行 - “播放教程 1:Playbin 使用“(附:完整源码)

运行效果

在这里插入图片描述

介绍

     我们已经使用了这个元素,它能够构建一个完整的播放管道,而无需做太多工作。 本教程介绍如何进一步自定义,以防其默认值不适合我们的特定需求。将学习:

          • 如何确定文件包含多少个流,以及如何切换 其中。

          • 如何收集有关每个流的信息。

     通常情况下,多个音频、视频和字幕流可以是嵌入在单个文件中。最常见的情况是常规电影,其中包含一个视频和音频流(立体声或 5.1 音轨被视为单个流)。它也越来越 常见查找具有一个视频和多个音频流的电影,以考虑不同的语言。在这种情况下,用户选择一个 audio 流,并且应用程序将仅播放该流。为了能够选择合适的流,用户需要知道有关他们的某些信息,例如他们的语言。这 信息以 “元数据” 的形式嵌入到流中 (附加的数据),本教程将介绍如何检索它。

GStreamer相关运行库
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/gstreamer-1.0/gst
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/gstreamer-1.0
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/glib-2.0
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/lib/glib-2.0/includeLIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/gstreamer-1.0.lib
LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/glib-2.0.lib
LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/gobject-2.0.lib

源码
#include <gst/gst.h>#include <iostream>
#include <stdio.h>typedef struct _CustomData
{GstElement *playbin;    /* 播放元素 */gint n_video;          /* 视频流数量 */gint n_audio;          /* 音频流数量 */gint n_text;           /* 字幕流数量 */gint current_video;    /* 当前正在播放视频流 */gint current_audio;    /* 当前正在播放音频流 */gint current_text;     /* 当前正在播放字母流*/GMainLoop *main_loop;  /* glib主循环 */
} CustomData;/* playbin flags */
typedef enum 
{GST_PLAY_FLAG_VIDEO         = (1 << 0), /* We want video output */GST_PLAY_FLAG_AUDIO         = (1 << 1), /* We want audio output */GST_PLAY_FLAG_TEXT          = (1 << 2)  /* We want subtitle output */
} GstPlayFlags;/* Forward definition for the message and keyboard processing functions */
static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data);
static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data);int main(int argc, char *argv[])
{/* 初始化GStreamer */gst_init (&argc, &argv);/* 创建元素 */CustomData data;data.playbin = gst_element_factory_make ("playbin", "playbin");if (!data.playbin) { g_printerr ("Not all elements could be created.\n"); return -1;}/* 设置播放的uri */g_object_set (data.playbin, "uri", "https://gstreamer.freedesktop.org/data/media/sintel_cropped_multilingual.webm", NULL);/* 设置标志以显示音频和视频,但忽略字幕 */gint flags;g_object_get (data.playbin, "flags", &flags, NULL);flags |= GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO;flags &= ~GST_PLAY_FLAG_TEXT;g_object_set (data.playbin, "flags", flags, NULL);/* 设置连接速度。这将影响playbin的一些内部决策 */g_object_set (data.playbin, "connection-speed", 56, NULL);/* 添加bus监视,这样就可以在消息到达时收到通知 */GstBus *bus = gst_element_get_bus (data.playbin);gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data);/* 添加键盘监视,以便我们收到按键通知 */
#ifdef G_OS_WIN32GIOChannel *io_stdin = g_io_channel_win32_new_fd (fileno (stdin));
#elseGIOChannel *io_stdin = g_io_channel_unix_new (fileno (stdin));
#endifg_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);/* 开始播放 */GstStateChangeReturn ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING);if (ret == GST_STATE_CHANGE_FAILURE){g_printerr ("Unable to set the pipeline to the playing state.\n");gst_object_unref (data.playbin); return -1;}/* 创建GLib主循环并将其设置为运行 */data.main_loop = g_main_loop_new (NULL, FALSE);g_main_loop_run (data.main_loop);/* 释放资源 */g_main_loop_unref (data.main_loop);g_io_channel_unref (io_stdin);gst_object_unref (bus);gst_element_set_state (data.playbin, GST_STATE_NULL);gst_object_unref (data.playbin);return 0;
}/* 从流中提取一些元数据并将其打印在屏幕上 */
static void analyze_streams (CustomData *data)
{gchar *str;guint rate;/* 读取一些属性 */g_object_get (data->playbin, "n-video", &data->n_video, NULL);g_object_get (data->playbin, "n-audio", &data->n_audio, NULL);g_object_get (data->playbin, "n-text", &data->n_text, NULL);g_print ("%d video stream(s), %d audio stream(s), %d text stream(s)\n", data->n_video, data->n_audio, data->n_text);g_print ("\n");GstTagList *tags;for (gint i = 0; i < data->n_video; i++){tags = NULL;/* 检索流的视频标签 */g_signal_emit_by_name (data->playbin, "get-video-tags", i, &tags);if (tags){g_print ("video stream %d:\n", i);gst_tag_list_get_string (tags, GST_TAG_VIDEO_CODEC, &str);g_print ("  codec: %s\n", str ? str : "unknown");g_free (str);gst_tag_list_free (tags);}}g_print ("\n");for (gint i = 0; i < data->n_audio; i++){tags = NULL;/* 检索流的音频标签 */g_signal_emit_by_name (data->playbin, "get-audio-tags", i, &tags);if (tags){g_print ("audio stream %d:\n", i);if (gst_tag_list_get_string (tags, GST_TAG_AUDIO_CODEC, &str)){g_print ("  codec: %s\n", str);g_free (str);}if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)){g_print ("  language: %s\n", str);g_free (str);}if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &rate)){g_print ("  bitrate: %d\n", rate);}gst_tag_list_free (tags);}}g_print ("\n");for (gint i = 0; i < data->n_text; i++){tags = NULL;/* 检索流的字幕标签 */g_signal_emit_by_name (data->playbin, "get-text-tags", i, &tags);if (tags){g_print ("subtitle stream %d:\n", i);if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)){g_print ("  language: %s\n", str);g_free (str);}gst_tag_list_free (tags);}}g_object_get (data->playbin, "current-video", &data->current_video, NULL);g_object_get (data->playbin, "current-audio", &data->current_audio, NULL);g_object_get (data->playbin, "current-text", &data->current_text, NULL);g_print ("\n");g_print ("Currently playing video stream %d, audio stream %d and text stream %d\n", data->current_video, data->current_audio, data->current_text);g_print ("Type any number and hit ENTER to select a different audio stream\n");
}/* 处理GStreamer的消息 */
static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data)
{GError *err;gchar *debug_info;switch (GST_MESSAGE_TYPE (msg)){case GST_MESSAGE_ERROR:gst_message_parse_error (msg, &err, &debug_info);g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");g_clear_error (&err); g_free (debug_info); g_main_loop_quit (data->main_loop);break;case GST_MESSAGE_EOS:g_print ("End-Of-Stream reached.\n");g_main_loop_quit (data->main_loop);break;case GST_MESSAGE_STATE_CHANGED:{GstState old_state, new_state, pending_state;gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)){if (new_state == GST_STATE_PLAYING){/* 一旦我们进入播放状态,分析流 */analyze_streams (data);}}} break;}/* 继续收到消息 */return TRUE;
}/* 处理键盘输入 */
static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data)
{gchar *str = NULL;if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL){int index = g_ascii_strtoull (str, NULL, 0);if (index < 0 || index >= data->n_audio){g_printerr ("Index out of bounds\n");}else{/* 如果输入是有效的音频流索引,请设置当前音频流 */g_print ("Setting current audio stream to %d\n", index);g_object_set (data->playbin, "current-audio", index, NULL);}}g_free (str);return TRUE;
}

关注

笔者 - jxd

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

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

相关文章

30、Vuex 为啥可以进行缓存处理

Vuex 状态管理基础与缓存的关联 Vuex 的核心概念&#xff1a; Vuex 主要由五个部分组成&#xff1a;state、mutations、actions、getters和modules。其中&#xff0c;state是存储数据的地方&#xff0c;类似于一个全局的数据仓库。在这个菜谱 APP 的例子中&#xff0c;缓存的数…

25届数字IC验证秋招总结

一、个人概况 双非本9硕&#xff0c;2024年初开始通过白皮书蓝皮书自学验证&#xff0c;半年实习经验&#xff0c;有竞赛无专利论文&#xff0c;在秋招期间投递企业130余家&#xff0c;绝大部分投递岗位为数字验证&#xff0c;面试20家&#xff0c;收到5个offer。因为背景和相关…

【商城实战(37)】Spring Boot配置优化:解锁高效商城开发密码

【商城实战】专栏重磅来袭&#xff01;这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建&#xff0c;运用 uniapp、Element Plus、SpringBoot 搭建商城框架&#xff0c;到用户、商品、订单等核心模块开发&#xff0c;再到性能优化、安全加固、多端适配&#xf…

网页制作12-html,css,javascript初认识のJavascipt脚本基础

一、JavaScript的三种基本使用方法:body|head|外部 网页效果: 运行代码: .html <!doctype html> <html> <head> <meta charset="utf-8"> <title>无标题文档</title><script> function n1(){document.getElementById(…

全面对比分析:HDMI、DP、DVI、VGA、Type-C、SDI视频接口特点详解

在当今的多媒体时代&#xff0c;视频接口的选择对于设备连接和显示效果至关重要。不同的视频接口在传输质量、兼容性、带宽等方面各有优劣。本文将全面对比分析常用的视频接口HDMI、DP、DVI、VGA、Type-C、SDI&#xff0c;帮助读者更好地理解它们的特点和适用场景。 一、HDMI&…

麒麟服务器操作系统PostgreSQL环境部署手册

软件简介 PostgreSQL 是一个免费的对象-关系数据库服务器(ORDBMS),在灵活的BSD许可证下发行。 ORDBMS(对象关系数据库系统)是面向对象技术与传统的关系数据库相结合的产物,查询处理是 ORDBMS 的重要组成部分,它的性能优劣将直接影响到DBMS 的性能。 软件环境 操作系统…

【蓝桥杯速成】| 4.递归

递归 题目一&#xff1a;最大公约数 问题描述 1979. 找出数组的最大公约数 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 nums &#xff0c;返回数组中最大数和最小数的 最大公约数 。 两个数的 最大公约数 是能够被两个数整除的最大正整数。 解题步骤 需要…

当大模型训练遇上“双向飙车”:DeepSeek开源周 DualPipe解析指南

前言 在大模型训练中&#xff0c;传统流水线并行因单向数据流和通信延迟的限制&#xff0c;导致GPU利用率不足60%&#xff0c;成为算力瓶颈。DeepSeek团队提出的DualPipe双向流水线架构&#xff0c;通过双向计算流与计算-通信重叠的创新设计&#xff0c;将前向与反向传播拆解为…

蓝桥杯好题推荐---前缀和

&#x1f308;个人主页&#xff1a; 羽晨同学-CSDN博客 &#x1f4ab;个人格言:“成为自己未来的主人~” 题目链接 【模板】前缀和https://ac.nowcoder.com/acm/problem/226282 解题思路 这种题目是要求我们找到一个数组中从l到r的元素的和&#xff0c;查询Q次&#xff0c;…

Nginx快速上手

什么是nginx Nginx 是一款开源的高性能 HTTP 和反向代理服务器&#xff0c;同时也提供了 IMAP/POP3/SMTP 代理功能。它由俄罗斯程序员 Igor Sysoev 于2004年首次发布&#xff0c;最初设计目的是为了解决 C10k 问题&#xff0c;即如何让单台服务器同时处理1万个并发连接的问题。…

【C++】:STL详解 —— 布隆过滤器

目录 布隆过滤器的概念 布隆过滤器的优点 布隆过滤器的缺点 布隆过滤器使用场景 布隆过滤器的实现 布隆过滤器的概念 布隆过滤器&#xff08;Bloom Filter&#xff09; 是一种空间效率极高的概率型数据结构&#xff0c;用于快速判断一个元素是否属于某个集合。其核心特点…

从Instagram到画廊:社交平台如何改变艺术家的展示方式

从Instagram到画廊&#xff1a;社交平台如何改变艺术家的展示方式 在数字时代&#xff0c;艺术家的展示方式正在经历一场革命。社交平台&#xff0c;尤其是Instagram&#xff0c;已经成为艺术家展示作品、与观众互动和建立品牌的重要渠道。本文将探讨社交平台如何改变艺术家的…

MySQL(事物上)

目录 示例&#xff1a; 一 引入事物 1. 概念 2. 事物的4大特性 3. 为什么要有事物&#xff1f; 二 事物操作 1. 查看存储引擎支持的事物 2. 事物的提交方式 2.1 查看事物的默认提交方式 2.2 设置事物的默认提交方式 2.3 查看事物的全局隔离级别 2.4 验证事物的回滚…

Spring Boot 实现多数据源配置

一、配置流程 在 Spring Boot 中实现多数据源配置通常用于需要连接多个数据库的场景。主要有以下几个步骤&#xff1a; 配置多个数据源的连接信息。定义多个数据源的 Bean。为每个数据源配置MyBatis的SqlSessionFactory和事务管理器。为每个数据源定义Mapper接口和Mapper XML…

p5.js:绘制各种内置的几何体,能旋转

向 豆包 提问&#xff1a;请编写 p5.js 示例&#xff0c; 绘制各种内置的几何体&#xff0c;能让这些几何体缓慢旋转。 cd p5-demo copy .\node_modules\p5\lib\p5.min.js . 此代码创建了一个包含多个内置几何体的 3D 场景&#xff0c;每个几何体都有不同的颜色和位置。运行代…

结构体定义与应用

引言 到今天为止,c语言的基础操作和基础数据类型,就都已经结束了,大家都知道,如果要实现复杂的功能,大家都可以通过函数封装调用,那么如果要实现基础数据类型的封装,该怎么办呢?答案就是结构体。 在C语言编程中,结构体(struct)是非常重要的一个概念,它为程序员提供…

MindGYM:一个用于增强视觉-语言模型推理能力的合成数据集框架,通过生成自挑战问题来提升模型的多跳推理能力。

2025-03-13&#xff0c;由中山大学和阿里巴巴集团的研究团队提出了MindGYM框架&#xff0c;通过合成自挑战问题来增强视觉-语言模型&#xff08;VLMs&#xff09;的推理能力。MindGYM框架通过生成多跳推理问题和结构化课程训练&#xff0c;显著提升了模型在推理深度和广度上的表…

R语言零基础系列教程-01-R语言初识与学习路线

代码、讲义、软件回复【R语言01】获取。 R语言初识 R是一个开放的统计编程环境&#xff0c;是一门用于统计计算和作图的语言。“一切皆是对象”&#xff0c;数据、函数、运算符、环境等等都是对象。易学&#xff0c;代码像伪代码一样简洁&#xff0c;可读性高强大的统计和可视…

PythonWeb开发框架—Flask-APScheduler超详细使用讲解

1.定时任务的两种实现方式 1.1 用scheduler.task装饰任务 安装插件&#xff1a; pip install Flask-APScheduler pip install apscheduler 脚本实现&#xff1a; ###app.py##导入依赖库 from flask import Flask import datetime import config from flask_apscheduler i…

python_巨潮年报pdf下载

目录 前置&#xff1a; 步骤&#xff1a; step one: pip安装必要包&#xff0c;获取年报url列表 step two: 将查看url列表转换为pdf url step three: 多进程下载pdf 前置&#xff1a; 1 了解一些股票的基本面需要看历年年报&#xff0c;在巨潮一个个下载比较费时间&…