gpt4 book ai didi

stream - Gstreamer - appsrc 推送模型

转载 作者:行者123 更新时间:2023-12-02 07:42:50 24 4
gpt4 key购买 nike

我正在开发一个 C 应用程序(在 Linux 下),它接收原始 h.264 流,并应使用 gstreamer API 可视化该流。我是 GStreamer 的新手,所以也许我犯了巨大的愚蠢错误或忽略了众所周知的东西,对此感到抱歉。

我得到了一个原始的 h264 视频(我知道它与我需要的格式完全相同)并开发了一个播放它的应用程序。它可以在拉模式下正确地与 appsrc 配合使用(当调用需要数据时,我从文件中获取新数据并执行推送缓冲区)。

现在我正在尝试做完全相同的事情,但是在推送模式下,这基本上是因为我没有视频,而是流。因此,我的代码中有一个方法,每次新数据(以 uint8_t 缓冲区的形式)到达时都会调用该方法,这是我的视频源。

我用谷歌搜索了我的问题并查看了 documentation ,但我没有发现适合我的用例的简单代码片段,即使它看起来非常简单。我知道我必须初始化管道和 appsrc,然后只有在有新数据时才推送缓冲区。

嗯,我开发了两种方法:用于管道/appsrc初始化的init_stream()和用于在可用时发送数据的populate_app(void *inBuf, size_t len)。它编译并正确运行,但没有视频:

struct _App
{
GstAppSrc *appsrc;
GstPipeline *pipeline;
GstElement *h264parse;
GstElement *mfw_vpudecoder;
GstElement *mfw_v4lsin;
GMainLoop *loop;
};

typedef struct _App App;
App s_app;
App *app = &s_app;


static gboolean bus_message (GstBus * bus, GstMessage * message, App * app)
{
GST_DEBUG ("got message %s", gst_message_type_get_name (GST_MESSAGE_TYPE (message)));

switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:
g_error ("received error");
g_main_loop_quit (app->loop);
break;
case GST_MESSAGE_EOS:
g_main_loop_quit (app->loop);
break;
default:
break;
}
return TRUE;
}

int init_stream()
{
GstBus *bus;

gst_init (NULL, NULL);
fprintf(stderr, "gst_init done\n");

/* create a mainloop to get messages */
app->loop = g_main_loop_new (NULL, TRUE);
fprintf(stderr, "app loop initialized\n");


app->pipeline = gst_parse_launch("appsrc name=mysource ! h264parse ! mfw_vpudecoder ! mfw_v4lsin", NULL);

app->appsrc = gst_bin_get_by_name (GST_BIN(app->pipeline), "mysource");
gst_app_src_set_stream_type(app->appsrc, GST_APP_STREAM_TYPE_STREAM);

gst_app_src_set_emit_signals(app->appsrc, TRUE);
fprintf(stderr, "Pipeline and appsrc initialized\n");

/* Create Bus from pipeline */
bus = gst_pipeline_get_bus(app->pipeline);
fprintf(stderr, "bus created\n");

/* add watch for messages */
gst_bus_add_watch (bus, (GstBusFunc) bus_message, app);
gst_object_unref(bus);
fprintf(stderr, "bus_add_watch done\n");

GstCaps* video_caps = gst_caps_new_simple ("video/x-h264",
"width", G_TYPE_INT, 800,
"height", G_TYPE_INT, 480,
"framerate", GST_TYPE_FRACTION, 25,
1, NULL);

gst_app_src_set_caps(GST_APP_SRC(app->appsrc), video_caps);

/* go to playing and wait in a mainloop. */
gst_element_set_state ((GstElement*) app->pipeline, GST_STATE_PLAYING);
fprintf(stderr, "gst_element_set_state play\n");

/* this mainloop is stopped when we receive an error or EOS */
g_main_loop_run (app->loop);
fprintf(stderr, "g_main_loop_run called\n");

gst_element_set_state ((GstElement*) app->pipeline, GST_STATE_NULL);

fprintf(stderr, "gst_element_set_state GST_STATE_NULL\n");

/* free the file */
// g_mapped_file_unref (app->file);

gst_object_unref (bus);
g_main_loop_unref (app->loop);

return 0;
}

void populateApp(void *inBuf , size_t len) {

guint8 *_buffer = (guint8*) inBuf;
GstFlowReturn ret;
GstBuffer *buffer = gst_buffer_new();

GstCaps* video_caps = gst_caps_new_simple ("video/x-h264",
"width", G_TYPE_INT, 800,
"height", G_TYPE_INT, 480,
"framerate", GST_TYPE_FRACTION, 25,
1, NULL);

gst_buffer_set_caps(buffer, video_caps);

GST_BUFFER_DATA (buffer) = _buffer;
GST_BUFFER_SIZE (buffer) = len;

// g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret);
ret = gst_app_src_push_buffer(GST_APP_SRC(app->appsrc), buffer);
gst_buffer_unref (buffer);
}

如前所述,我是 GStreamer 的新手,因此有很多来自互联网的剪切和粘贴代码,但恕我直言,它应该可以工作。您发现任何问题吗?

最佳答案

目前尚不清楚如何调用 populateApp,但是当您有数据要推送到管道时,您需要重复调​​用它。这可以在与 g_main_loop_run 阻止的线程不同的线程中完成,或者您可以重组程序以避免使用 GMainLoop。

关于stream - Gstreamer - appsrc 推送模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17861041/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com