gstreamer:通过线程动态切换帧率,用GST_OBJECT_LOCK卡死
本来这不是个问题,切换个帧率,算什么事?可是实际工作中,高通平台切换帧率会卡死,合作人员又不服。于是不得不写了个代码测试
- 具体代码
#include <gst/gst.h> #include <pthread.h> #include <stdio.h> #include <unistd.h> /* 全局句柄(实际项目建议用结构体封装,避免全局) */ static GstElement *pipeline = NULL; static GstElement *capsfilter = NULL; static gboolean run_thread = TRUE; #define DEFAULT_FORMAT "NV12" #define DEFAULT_WIDTH 1280 #define DEFAULT_HEIGHT 720 #define FPS_COUNT 5 static int fpss[] = {30, 25, 20, 15, 10}; /** * @brief 子线程:动态切换帧率(示例:10fps <-> 30fps 循环切换) */ void* fps_change_thread(void* arg) { int count = 0; sleep(5); while (run_thread) { int new_fps = fpss[count%FPS_COUNT]; printf("fps = %d\n", new_fps); // 1. 构造新的 Caps:video/x-raw,修改帧率 GstCaps* new_caps = gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, DEFAULT_FORMAT, "width", G_TYPE_INT, DEFAULT_WIDTH, "height", G_TYPE_INT, DEFAULT_HEIGHT, "framerate", GST_TYPE_FRACTION, new_fps, 1, NULL); // 2. GStreamer 线程安全:加锁再修改元素属性 //GST_OBJECT_LOCK(capsfilter); g_object_set(capsfilter, "caps", new_caps, NULL); //GST_OBJECT_UNLOCK(capsfilter); gst_caps_unref(new_caps); // 释放 caps sleep(10); count ++; } return NULL; } int main(int argc, char *argv[]) { GstBus *bus; GstMessage *msg; pthread_t thread; // 1. 初始化 GStreamer gst_init(&argc, &argv); // 2. 创建管道与元素 pipeline = gst_pipeline_new("fps-change-pipeline"); GstElement *src = gst_element_factory_make("videotestsrc", "src"); capsfilter = gst_element_factory_make("capsfilter", "capsfilter"); GstElement *sink = gst_element_factory_make("autovideosink", "sink"); if (!pipeline || !src || !capsfilter || !sink) { g_printerr("创建元素失败!\n"); return -1; } // 3. 构建初始 Caps(初始 30fps) GstCaps *init_caps = gst_caps_new_simple( "video/x-raw", "framerate", GST_TYPE_FRACTION, 30, 1, NULL ); g_object_set(capsfilter, "caps", init_caps, NULL); gst_caps_unref(init_caps); // 4. 添加元素到管道并链接 gst_bin_add_many(GST_BIN(pipeline), src, capsfilter, sink, NULL); if (!gst_element_link_many(src, capsfilter, sink, NULL)) { g_printerr("元素链接失败!\n"); gst_object_unref(pipeline); return -1; } // 5. 启动帧率修改子线程 run_thread = TRUE; pthread_create(&thread, NULL, fps_change_thread, NULL); // 6. 启动管道播放 gst_element_set_state(pipeline, GST_STATE_PLAYING); // 7. 监听总线消息(等待退出/错误) bus = gst_element_get_bus(pipeline); msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS)); // 8. 收尾工作 run_thread = FALSE; pthread_join(thread, NULL); // 停止管道 gst_element_set_state(pipeline, GST_STATE_NULL); // 释放资源 gst_message_unref(msg); gst_object_unref(bus); gst_object_unref(pipeline); return 0; }- 编译脚本:
rm fps gcc \ test.cpp \ -o fps \ $(pkg-config --cflags --libs gstreamer-1.0) ./fps