0

我的目标是对带有刻录字幕的视频进行转码(使用 textoverlay)。我参考 Gstreamer 教程并编写了一个小程序来测试 2 个管道:

管道1(无字幕):

multiqueue max-size-buffers=10000 max-size-bytes=0 max-size-time=0 name=mq splitfilesrc location="/share/Multimedia/debug/harry/Harry.Potter.and.the.Deathly.Hallows. Part.1.2010.BluRay.1080p.AAC.4Audio.x264-CHD.mkv”!matroskademux 名称=dmx dmx。!队列 !身份同步=假!h264解析!omxh264dec !omxh264enc 强制关键帧周期=40 缩放宽度=1920 缩放高度=800 !h264解析!mq.sink_0 mq.src_0 !mpegtsmux 名称=mux !文件接收器位置="/share/Public/aaa.ts" dmx。!不一样!队列 !身份同步=假!faad 名称=adec !音频转换!音频重采样!音频/x-raw,channels=2,rate=44100 !队列 !呸!音频/mpeg,mpegversion=4,流格式=原始!不一样!mq.sink_1 mq.src_1 !音频/mpeg,mpegversion=4,流格式=原始!多路复用器。

管道2(带字幕):

multiqueue max-size-buffers=10000 max-size-bytes=0 max-size-time=0 name=mq textoverlay wait-text=false name=txo splitfilesrc location="/share/Multimedia/debug/harry/Harry.Potter .and.the.Deathly.Hallows.Part.1.2010.BluRay.1080p.AAC.4Audio.x264-CHD.mkv”!matroskademux 名称=dmx dmx。!队列 !身份同步=假!h264解析!omxh264dec !txo.video_sink txo.src !omxh264enc 强制关键帧周期=40 缩放宽度=1920 缩放高度=800 !h264解析!mq.sink_0 mq.src_0 !mpegtsmux 名称=mux !filesink location="/share/Public/aaa.ts" filesrc location="/share/Multimedia/debug/harry/Harry.Potter.and.the.Deathly.Hallows.Part.1.2010.BluRay.1080p.AAC.4Audio。 x264-CHD.zh-TW.srt" !subparse 字幕编码=UTF-8 !txo.text_sink dmx。!不一样!队列 !身份同步=假!faad 名称=adec !音频转换!音频重采样!音频/x-raw,channels=2,rate=44100 !队列 !呸!音频/mpeg,mpegversion=4,流格式=原始!不一样!mq.sink_1 mq.src_1 !音频/mpeg,mpegversion=4,流格式=原始!多路复用器。

无论是否执行搜索事件,管道 1 都能正常工作。管道 2 也可以正常工作而无需搜索,但在执行搜索时会出现问题。它会在

ret = gst_element_seek_simple (pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_KEY_UNIT, 7280 * GST_SECOND);

并且永远不会回来。

对此我能做些什么吗?以下是我的测试代码

问候, 坦尼

#include <gst/gst.h>

int main(int argc, char *argv[]) {
    GstElement *pipeline;
    GstBus *bus;
    GstMessage *msg;
    gboolean ret;
    int isSeek=0;

    /* Initialize GStreamer */
    gst_init (&argc, &argv);

    /* Build the pipeline */
#if 1 // with subtitle
    pipeline = gst_parse_launch("multiqueue max-size-buffers=10000 max-size-bytes=0 max-size-time=0 name=mq textoverlay wait-text=false name=txo splitfilesrc location=\"/share/Multimedia/debug/harry/Harry.Potter.and.the.Deathly.Hallows.Part.1.2010.BluRay.1080p.AAC.4Audio.x264-CHD.mkv\" ! matroskademux name=dmx  dmx. ! queue ! identity sync=false ! h264parse ! omxh264dec ! txo.video_sink  txo.src ! omxh264enc force-keyframe-period=40 scaling-width=1920 scaling-height=800 ! h264parse ! mq.sink_0  mq.src_0 ! mpegtsmux name=mux ! filesink location=\"/share/Public/aaa.ts\"  filesrc location=\"/share/Multimedia/debug/harry/Harry.Potter.and.the.Deathly.Hallows.Part.1.2010.BluRay.1080p.AAC.4Audio.x264-CHD.zh-TW.srt\" ! subparse subtitle-encoding=UTF-8 ! txo.text_sink dmx. ! aacparse ! queue ! identity sync=false ! faad name=adec ! audioconvert ! audioresample ! audio/x-raw,channels=2,rate=44100 ! queue ! voaacenc ! audio/mpeg,mpegversion=4,stream-format=raw ! aacparse ! mq.sink_1  mq.src_1 ! audio/mpeg,mpegversion=4,stream-format=raw ! mux.", NULL);
#else // constantine without subtitle
    pipeline = gst_parse_launch("multiqueue max-size-buffers=10000 max-size-bytes=0 max-size-time=0 name=mq splitfilesrc location=\"/share/Multimedia/debug/harry/Harry.Potter.and.the.Deathly.Hallows.Part.1.2010.BluRay.1080p.AAC.4Audio.x264-CHD.mkv\" ! matroskademux name=dmx  dmx. ! queue ! identity sync=false ! h264parse ! omxh264dec ! omxh264enc force-keyframe-period=40 scaling-width=1920 scaling-height=800 ! h264parse ! mq.sink_0  mq.src_0 ! mpegtsmux name=mux ! filesink location=\"/share/Public/aaa.ts\"  dmx. ! aacparse ! queue ! identity sync=false ! faad name=adec ! audioconvert ! audioresample ! audio/x-raw,channels=2,rate=44100 ! queue ! voaacenc ! audio/mpeg,mpegversion=4,stream-format=raw ! aacparse ! mq.sink_1  mq.src_1 ! audio/mpeg,mpegversion=4,stream-format=raw ! mux.", NULL);
#endif  

    /* Start playing */
    //gst_element_set_state (pipeline, GST_STATE_PLAYING);
    gst_element_set_state (pipeline, GST_STATE_PAUSED);

    bus = gst_element_get_bus (pipeline);

    do{
      msg = gst_bus_timed_pop_filtered (bus, 1 * GST_SECOND, 
                GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_DURATION);
        if(msg != NULL){
            GError *err;
            gchar *debug_info;
            switch(GST_MESSAGE_TYPE(msg)){
                case GST_MESSAGE_ERROR:
                    gst_message_parse_error (msg, &err, &debug_info);
                    g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
                    g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
                    g_clear_error (&err);
                    g_free (debug_info);
                    break;
                case GST_MESSAGE_EOS:
                    g_print ("End-Of-Stream reached.\n");
                    goto _exit;
                    break;
                case GST_MESSAGE_DURATION:
                    g_print ("The duration has changed.\n");
                    break;
                case GST_MESSAGE_STATE_CHANGED:{
                        GstState old_state, new_state, pending_state;
                        gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
                        if (GST_MESSAGE_SRC (msg) == GST_OBJECT (pipeline)) {
                            g_print ("Pipeline state changed from %s to %s:\n",
                                gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));

                            if (new_state == GST_STATE_PLAYING) {
                                g_printerr("[%s:%d]: do nothing now.\n", __FILE__, __LINE__);
                            }else if (new_state == GST_STATE_PAUSED){
                                // do seek
                                if(isSeek == 0){
                                    // show seek info
                                    GstQuery *query;
                                    gint64 start, end;
                                    gboolean seek_enabled;
                                    query = gst_query_new_seeking (GST_FORMAT_TIME);
                                    if (gst_element_query (pipeline, query)) {
                                        gst_query_parse_seeking (query, NULL, &seek_enabled, &start, &end);
                                        if (seek_enabled) {
                                            g_print ("Seeking is ENABLED from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT "\n",
                                                GST_TIME_ARGS (start), GST_TIME_ARGS (end));
                                        } else {
                                            g_print ("Seeking is DISABLED for this stream.\n");
                                        }
                                    }else {
                                        g_printerr ("Seeking query failed.");
                                    }
                                    gst_query_unref (query);

                                    // do seek
                                    isSeek = 1;
                                    g_printerr("[%s:%d]start to seek \n", __FILE__, __LINE__);  
                                    ret = gst_element_seek_simple (pipeline, GST_FORMAT_TIME,
                                              //GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, 
                                              GST_SEEK_FLAG_KEY_UNIT,
                                              //GST_SEEK_FLAG_ACCURATE,
                                              //GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
                                              //GST_SEEK_FLAG_FLUSH,
                                              //GST_SEEK_FLAG_NONE,
                                              7280 * GST_SECOND);
                                    g_printerr("[%s:%d]end to seek \n", __FILE__, __LINE__);
                                    if(ret == TRUE){
                                        g_printerr("[%s:%d]ret=true\n", __FILE__, __LINE__);
                                    }else{
                                        g_printerr("[%s:%d]ret=false\n", __FILE__, __LINE__);
                                    }
                                    gst_element_set_state (pipeline, GST_STATE_PLAYING);
                                }                           
                            }
                        }
                    }
                default:
                    //g_printerr ("Unexpected message received.\n");
                    break;
            }
            gst_message_unref (msg);
        }else{
            GstFormat fmt = GST_FORMAT_TIME;
            gint64 current = -1;
            gint64 duration;

            if (!gst_element_query_position (pipeline, fmt, &current)) {
                g_printerr ("Could not query current position.\n");
            }

            if (!GST_CLOCK_TIME_IS_VALID (duration)) {
                if (!gst_element_query_duration (pipeline, fmt, &duration)) {
                    g_printerr ("Could not query current duration.\n");
                }
            }

            g_print ("Position %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\n",
            GST_TIME_ARGS (current), GST_TIME_ARGS (duration));

        }
    }while(1);  

_exit:   
    /* Free resources */
    if (msg != NULL)
    gst_message_unref (msg);
    gst_object_unref (bus);
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);
    return 0;
}
4

0 回答 0