最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c - How to create a video segment in GStreamer? gst_segment_do_seek: assertion 'segment->format == format&#39

programmeradmin3浏览0评论

With ffmpeg it's pretty easy to create a video segment with the -ss and -t option. But it's hard with GStreamer.

The gst-launch-1.0 program does not provide options like -ss and -t. We have to write a program (in C or Python) and call gst_element_seek in order to jump to a specific time. However, such a program cannot be easily implemented. An unexpected error would be reported.

To reproduce the error, first download a video file called sintel_trailer-480p.webm

(This file is frequently used in GStreamer's tutorials)

Convert it to h264/aac:

ffmpeg -i sintel_trailer-480p.webm sintel_trailer-480p.mp4

Open Visual Studio and create a simple command-line project with code below (main.c):

#include <gst/gst.h>

GMainLoop* loop = NULL;
GstElement* pipeline = NULL;

gboolean gst_bus_handler(GstBus* bus, GstMessage* message, gpointer data)
{
    GstMessageType type = message->type;

    if (type == GST_MESSAGE_EOS) {
        g_main_loop_quit(loop);
    }
    else if (type == GST_MESSAGE_STATE_CHANGED) {
        GstState old_state, new_state;
        gst_message_parse_state_changed(message, &old_state, &new_state, NULL);
        g_printerr(" - %s: %d => %d\n", message->src->name, old_state, new_state);

        if (GST_MESSAGE_SRC(message) == GST_OBJECT_CAST(pipeline)) {
            if (old_state != GST_STATE_PAUSED && new_state == GST_STATE_PAUSED) {
                gst_element_seek(
                    pipeline, 1.0, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
                    GST_SEEK_TYPE_SET, 12 * GST_SECOND,
                    GST_SEEK_TYPE_SET, 20 * GST_SECOND);
            }
        }
    }
    else if (type == GST_MESSAGE_ASYNC_DONE) {
        gst_element_set_state(pipeline, GST_STATE_PLAYING);
    }

    return TRUE;
}

int main(int argc, char* argv[])
{
    // SetEnvironmentVariable(L"GST_DEBUG", L"3");

    gst_init(NULL, NULL);

    // create the pipeline
#ifdef PLAY
    pipeline = gst_parse_launch(
        "filesrc location=sintel_trailer-480p.mp4 name=src ! qtdemux name=demux"
        " demux.video_0 ! nvh264dec name=dec ! d3d11videosink name=sink", NULL);
#else
    pipeline = gst_parse_launch(
        "filesrc location=sintel_trailer-480p.mp4 name=src ! qtdemux name=demux"
        " demux.video_0 ! nvh264dec name=dec ! nvh264enc name=enc ! h264parse name=parse ! mux.video_0"
        " mp4mux name=mux ! filesink name=sink location=clip.mp4", NULL);
#endif
    if (!pipeline) exit(-1);

    // create the main loop
    loop = g_main_loop_new(NULL, FALSE);

    // set gst bus handler
    GstBus* bus = gst_element_get_bus(pipeline);
    guint watch_id = gst_bus_add_watch(bus, gst_bus_handler, NULL);
    gst_object_unref(bus);

    // preroll
    GstStateChangeReturn ret = gst_element_set_state(pipeline, GST_STATE_PAUSED);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        g_printerr("Unable to set the pipeline to the PAUSED state\n");
    }
    else {
        g_main_loop_run(loop);
    }

    g_printerr("Setting pipeline state to NULL\n");
    gst_element_set_state(pipeline, GST_STATE_NULL);
    g_source_remove(watch_id);
    g_main_loop_unref(loop);
    g_printerr("Freeing pipeline\n");
    gst_object_unref(pipeline);
    gst_deinit();
    return 0;
}

There's a macro that controls the mode. In PLAY mode, the program plays the video from 00:00:12 to 00:00:20.

In CONVERT mode, the program attempts to create a video segment from 00:00:12 to 00:00:20.

The playback works fine, but the conversion always fails with this error:

gst_segment_do_seek: assertion 'segment->format == format' failed

The script is tested on Windows with GStreamer 1.24.11 (latest stable release).

What is the correct way to create a video segment with GStreamer?

发布评论

评论列表(0)

  1. 暂无评论