使用gstreamer创建管道播放avi视频
前言
环境:ubuntu14.04
qt5.9.11
以一个简单demo来介绍gst如何进行播放、暂停、结束播放、快进、跳转、设置播放速率等操作
代码段解释
初始化
在main.cpp中初始化gst
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
gst_init (&argc, &argv);//初始化gstreamer
MainWindow w;
w.show();
return a.exec();
}
没有初始化的情况下也可以通过编译,但是会在播放视频的时候报错初始化失败
设置管道并播放
videoscale表明我们需要缩放,我这里将视频的高度设置为480,并且由于我需要同时指定两个播放路径,所以需要声明播放队列
之后创建管道,创建完毕后通过定时器(如果你会回调函数也可以使用回调函数这里提供我认为更为简单的方法)来获取当前播放位置以及总视频时长,将在下一个part记载。
QString SameScreenCmd;
std::string strSameScrValue = " ! decodebin ! videoscale ! video/x-raw,height=480 ! tee name=t ! queue ! videoconvert ! fbdevsink device=/dev/fb0 t. ! queue ! videoconvert ! fbdevsink device=/dev/fb2";//分别指定两个播放设备的路径,只需要指定一个设备路径的话如下:
//" ! decodebin ! videoscale ! video/x-raw,height=480 ! videoconvert ! fbdevsink device=/dev/fb0"
QByteArray stdSameScrByte = QByteArray::fromStdString(strSameScrValue);
QString SameScreenCmdPara = stdSameScrByte;
SameScreenCmd = "filesrc location=" + 完整的播放路径 + SameScreenCmdPara;
pipeline = gst_parse_launch(SameScreenCmd.toLocal8Bit().data(), NULL);
if (!pipeline) {
qDebug() << "Failed to create pipeline";
}
else
{
// 获取管道总线
m_pipeLineMsgTimer->start(1000);//定时获取播放时长信息
bus = gst_element_get_bus(pipeline);
}
gst_element_set_state(pipeline, GST_STATE_PLAYING);//设置为播放状态GST_STATE_PLAYING, 暂停为GST_STATE_PAUSED,从暂停恢复播放只需要重新设置为PLAYING即可
定时获取播放时长
定义两个gint64类型的变量,用于保存当前播放位置以及视频总时长
gint64其实是long long int类型,单位是纳秒,所以要除1000000000才是正常的秒数,想要转换成QString可以用QString::number来转换
需要提到的是通过这个方式创建的管道在播放完毕之后不会自己销毁,需要手动销毁
gint64 position, duration;
if (gst_element_query_position(pipeline, GST_FORMAT_TIME, &position) &&
gst_element_query_duration(pipeline, GST_FORMAT_TIME, &duration)) {
QString currTime = QString::number(position / 1000000000);
QString totalTime = QString::number(duration / 1000000000);
qDebug() << currTime.toInt() << totalTime.toInt() << currTime << totalTime;
if(currTime.toInt() >= totalTime.toInt())
{
on_toolButton_close_clicked();
}
}
这个函数可以在开始后的任意点调用,来获取当前的播放位置和视频的总时长。
结束播放
//结束播放释放管道
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
m_pipeLineMsgTimer->stop();
跳转至任意点播放、修改播放速率等操作
GStreamer的gst_element_seek()
函数确实有很多参数,需要非常小心地按照正确的顺序和数据类型进行传递。
void MainWindow::seekToPosition(gint64 time_nanoseconds)
{
if (!pipeline) {
qDebug() << "Pipeline is not initialized";
return;
}
gboolean seek_success = gst_element_seek(pipeline,
1.0, // rate
GST_FORMAT_TIME, // format
GST_SEEK_FLAG_FLUSH, // flags
GST_SEEK_TYPE_SET, // start_type
time_nanoseconds, // start
GST_SEEK_TYPE_NONE, // stop_type
GST_CLOCK_TIME_NONE); // stop
if (!seek_success) {
qDebug() << "Seek operation failed";
} else {
qDebug() << "Seek operation succeeded";
}
}
element: 进行seek操作的GstElement。
rate: 播放速率,1.0 表示正常速率。
format: 位置和时间的格式,通常是GST_FORMAT_TIME,表示时间以纳秒为单位。
flags: 寻求行为的标志,例如GST_SEEK_FLAG_FLUSH(在seek前刷新管道)。
start_type: 开始位置的类型,通常是GST_SEEK_TYPE_SET(从绝对位置开始)。
start: 开始位置的具体值(如从视频的第几纳秒开始)。
stop_type: 结束位置的类型,可以是GST_SEEK_TYPE_NONE(不指定结束位置)。
stop: 具体的结束位置(如果stop_type不是GST_SEEK_TYPE_NONE)。