gpt4 book ai didi

gstreamer - 从 tee 中删除分支时将 EoS 发送到文件接收器

转载 作者:行者123 更新时间:2023-12-04 02:06:33 28 4
gpt4 key购买 nike

我写了一个v4l2src同时显示和录制的代码。我的管道看起来像:

               / [queue] ! [videosink]
v4l2src ! tee !
\ [queue] ! [filesink]

目前我可以同时显示+记录,也可以随意动态启动和停止记录分支(使用ctrl+c sigint handler 启动/停止)。我在 this 中使用了@thiagoss 的建议答案,以及 this 的部分内容文章。

问题:

我面临的唯一问题是在取消链接时将 EoS 发送到 filesink 分支。我向哪个元素发送 gst_element_send_event(-->?<--, gst_event_new_eos());事件到?我无法将它发送到整个管道,因为 1. 分支现在已取消链接,并且 2. 即使我这样做,它也会关闭视频接收器。

我尝试过的:删除 mp4mux 并保存 h264 编码的视频后,我可以使用 gst-playbin 来查看视频,这意味着分支创建和取消链接正在正确进行。

以下是我的代码。

#include <string.h>
#include <gst/gst.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

// v4l2src ! tee name=t t. ! x264enc ! mp4mux ! filesink location=/home/rish/Desktop/okay.264 t. ! videoconvert ! autovideosink

static GMainLoop *loop;
static GstElement *pipeline, *src, *tee, *encoder, *muxer, *filesink, *videoconvert, *videosink, *queue_record, *queue_display;
static GstBus *bus;
static GstPad *teepad;
static gboolean recording = FALSE;
static gint counter = 0;

static gboolean
message_cb (GstBus * bus, GstMessage * message, gpointer user_data)
{
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:{
GError *err = NULL;
gchar *name, *debug = NULL;

name = gst_object_get_path_string (message->src);
gst_message_parse_error (message, &err, &debug);

g_printerr ("ERROR: from element %s: %s\n", name, err->message);
if (debug != NULL)
g_printerr ("Additional debug info:\n%s\n", debug);

g_error_free (err);
g_free (debug);
g_free (name);

g_main_loop_quit (loop);
break;
}
case GST_MESSAGE_WARNING:{
GError *err = NULL;
gchar *name, *debug = NULL;

name = gst_object_get_path_string (message->src);
gst_message_parse_warning (message, &err, &debug);

g_printerr ("ERROR: from element %s: %s\n", name, err->message);
if (debug != NULL)
g_printerr ("Additional debug info:\n%s\n", debug);

g_error_free (err);
g_free (debug);
g_free (name);
break;
}
case GST_MESSAGE_EOS:{
g_print ("Got EOS\n");
g_main_loop_quit (loop);
gst_element_set_state (pipeline, GST_STATE_NULL);
g_main_loop_unref (loop);
gst_object_unref (pipeline);
exit(0);
break;
}
default:
break;
}

return TRUE;
}

static GstPadProbeReturn unlink_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
g_print("Unlinking...");
GstPad *sinkpad;
sinkpad = gst_element_get_static_pad (queue_record, "sink");
gst_pad_unlink (teepad, sinkpad);
gst_object_unref (sinkpad);

gst_element_send_event(filesink, gst_event_new_eos());

sleep(1);
gst_bin_remove(GST_BIN (pipeline), queue_record);
gst_bin_remove(GST_BIN (pipeline), encoder);
// gst_bin_remove(GST_BIN (pipeline), muxer);
gst_bin_remove(GST_BIN (pipeline), filesink);

gst_element_set_state(queue_record, GST_STATE_NULL);
gst_element_set_state(encoder, GST_STATE_NULL);
// gst_element_set_state(muxer, GST_STATE_NULL);
gst_element_set_state(filesink, GST_STATE_NULL);

gst_object_unref(queue_record);
gst_object_unref(encoder);
// gst_object_unref(muxer);
gst_object_unref(filesink);

gst_element_release_request_pad (tee, teepad);
gst_object_unref (teepad);

g_print("Unlinked\n");

return GST_PAD_PROBE_REMOVE;
}

void stopRecording() {
g_print("stopRecording\n");
gst_pad_add_probe(teepad, GST_PAD_PROBE_TYPE_IDLE, unlink_cb, NULL, (GDestroyNotify) g_free);
recording = FALSE;
}

void startRecording() {
g_print("startRecording\n");
GstPad *sinkpad;
GstPadTemplate *templ;

templ = gst_element_class_get_pad_template(GST_ELEMENT_GET_CLASS(tee), "src_%u");
teepad = gst_element_request_pad(tee, templ, NULL, NULL);
queue_record = gst_element_factory_make("queue", "queue_record");
encoder = gst_element_factory_make("x264enc", NULL);
// muxer = gst_element_factory_make("mp4mux", NULL);
filesink = gst_element_factory_make("filesink", NULL);
char *file_name = (char*) malloc(100*sizeof(char));
sprintf(file_name, "/home/rish/Desktop/rec%d.mp4", counter++);
g_print(file_name);
g_object_set(filesink, "location", file_name, NULL);
g_object_set(encoder, "tune", 4, NULL);
free(file_name);

gst_bin_add_many(GST_BIN(pipeline), gst_object_ref(queue_record), gst_object_ref(encoder), gst_object_ref(filesink), NULL);
gst_element_link_many(queue_record, encoder, filesink, NULL);

gst_element_sync_state_with_parent(queue_record);
gst_element_sync_state_with_parent(encoder);
// gst_element_sync_state_with_parent(muxer);
gst_element_sync_state_with_parent(filesink);

sinkpad = gst_element_get_static_pad(queue_record, "sink");
gst_pad_link(teepad, sinkpad);
gst_object_unref(sinkpad);

recording = TRUE;
}

int sigintHandler(int unused) {
g_print("You ctrl-c!\n");
if (recording)
stopRecording();
else
startRecording();
return 0;
}

int main(int argc, char *argv[])
{
signal(SIGINT, sigintHandler);
gst_init (&argc, &argv);

pipeline = gst_pipeline_new(NULL);
src = gst_element_factory_make("v4l2src", NULL);
tee = gst_element_factory_make("tee", "tee");
queue_display = gst_element_factory_make("queue", "queue_display");
videoconvert = gst_element_factory_make("videoconvert", NULL);
videosink = gst_element_factory_make("autovideosink", NULL);

if (!pipeline || !src || !tee || !videoconvert || !videosink || !queue_display) {
g_error("Failed to create elements");
return -1;
}

gst_bin_add_many(GST_BIN(pipeline), src, tee, queue_display, videoconvert, videosink, NULL);
if (!gst_element_link_many(src, tee, NULL)
|| !gst_element_link_many(tee, queue_display, videoconvert, videosink, NULL)) {
g_error("Failed to link elements");
return -2;
}

startRecording();
loop = g_main_loop_new(NULL, FALSE);

bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));
gst_bus_add_signal_watch(bus);
g_signal_connect(G_OBJECT(bus), "message", G_CALLBACK(message_cb), NULL);
gst_object_unref(GST_OBJECT(bus));

gst_element_set_state(pipeline, GST_STATE_PLAYING);

g_print("Starting loop\n");
g_main_loop_run(loop);

return 0;
}

最佳答案

您应该将它发送给编码器,以便他们可以正确地完成他们的工作,然后他们会将它转发给 muxer,该 muxer 也需要通过写入他们只能在最后写入的 header 部分来包装文件.

此外,删除 sleep ,您将需要确保 filesink 发布了一条 EOS 消息,以确保它已全部处理并且可以安全地删除它们。您可能需要为管道启用 message-forward ,否则它会保留 EOS 消息,直到所有接收器发布它们的 EOS(由于视频接收器,这在您的情况下不会发生)。

关于gstreamer - 从 tee 中删除分支时将 EoS 发送到文件接收器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42908694/

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