虽然源元素已暂停或源视频数据被阻止,但接收元素仍会继续渲染并将数据写入文件

问题描述 投票:0回答:0

我想知道为什么 autovideosink 元素不断显示,filesink 元素不断写入最后一个输入帧,即使源元素已暂停并且视频数据不流动。

当源元素暂停时,我认为接收器元素显示或写入空白帧是正确的行为。

我尝试插入阀元件,在源元件和接收器元件之间放置帧缓冲区,但结果是相同的。

即使视频源元素暂停,仍保持显示最后一个输入帧的示例源代码如下所示。

对于一些其他上下文,它在 Windows 11 和 Gstreamer 版本 1.22.4 中运行。

#include <gst/gst.h>
#include <cstdio>

enum class STATE
{
    WAITING,
    RECORDING,
    PAUSING,
};

typedef struct _CustomData
{
    GstElement* pipeline;
    GstElement* src;
    GstElement* rendersink;
    GMainLoop* loop;
    STATE state;
} CustomData;

static gboolean handle_keyboard(GIOChannel* source, GIOCondition cond, CustomData* data)
{
    gchar* str = NULL;
    GstBus* bus = NULL;
    GstMessage* msg = NULL;

    if (g_io_channel_read_line(source, &str, NULL, NULL,NULL) != G_IO_STATUS_NORMAL) {
        return TRUE;
    }

    switch (g_ascii_tolower(str[0])) {
    case 'p':
        if (data->state == STATE::RECORDING)
        {
            g_print("Setting state to %s\n", "PAUSE");
            data->state = STATE::PAUSING;
            gst_element_set_state(data->src, GST_STATE_PAUSED);
        }
        else if (data->state == STATE::PAUSING)
        {
            g_print("Setting state to %s\n", "PLAYING");
            data->state = STATE::RECORDING;
            gst_element_set_state(data->src, GST_STATE_PLAYING);
        }
        break;
    case 'q':
        g_print("Finish\n");
        g_main_loop_quit(data->loop);
        break;
    default:
        break;
    }

    g_free(str);

    return TRUE;
}

int main(int argc, char* argv[])
{
    CustomData data;
    GstStateChangeReturn ret;

    gst_init(&argc, &argv);

    data.pipeline = gst_pipeline_new("pipeline");
    data.src = gst_element_factory_make("dshowvideosrc", "src");
    data.rendersink = gst_element_factory_make("autovideosink", "autovideosink");

    if (!data.pipeline || !data.src || !data.rendersink)
    {
        g_printerr("Failed to create elements\n");
        return -1;
    }

    gst_bin_add_many(GST_BIN(data.pipeline), data.src, data.rendersink, NULL);

    g_object_set(G_OBJECT(data.src), "device-index", 0, "do-timestamp", true, NULL);

    if (!gst_element_link_filtered(data.src, data.rendersink, gst_caps_new_simple("video/x-raw",
        "width", G_TYPE_INT, 1920,
        "height", G_TYPE_INT, 1080,
        "framerate", GST_TYPE_FRACTION, 30, 1,
        NULL))) {
        g_printerr("Failed to link src1 and comp\n");
        gst_object_unref(data.pipeline);
        return -1;
    }

    g_print("USAGE: Choose one of the following options, then press enter:\n"
        " 'P' to toggle between PAUSE and PLAY\n"
        " 'Q' to quit\n");

    GIOChannel* io_stdin = g_io_channel_unix_new(_fileno(stdin));
    g_io_add_watch(io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);

    ret = gst_element_set_state(data.pipeline, GST_STATE_PLAYING);
    data.state = STATE::RECORDING;

    data.loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(data.loop);

    gst_element_set_state(data.pipeline, GST_STATE_NULL);
    gst_object_unref(data.pipeline);
    return 0;
}
gstreamer pause resume
© www.soinside.com 2019 - 2024. All rights reserved.