Ошибка записи субтитров в видео при поиске с использованием Gstreamer
Моя цель - перекодировать видео с записью субтитров (используя 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 name = dmx dmx.! очередь! идентичность синхронизации = ложь! 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! очередь! идентичность синхронизации = ложь! faad name = adec! аудиоконвертировать! аудиосэмпл! аудио /x-raw, каналы =2, скорость =44100! очередь! voaacenc! audio/mpeg,mpegversion=4,stream-format=raw! aacparse! mq.sink_1 mq.src_1! audio/mpeg,mpegversion=4,stream-format=raw! Мультиплексор.
конвейер 2(с субтитрами):
multi-queue 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.! очередь! идентичность синхронизации = ложь! 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! очередь! идентичность синхронизации = ложь! faad name = adec! аудиоконвертировать! аудиосэмпл! аудио /x-raw, каналы =2, скорость =44100! очередь! voaacenc! audio/mpeg,mpegversion=4,stream-format=raw! aacparse! mq.sink_1 mq.src_1! audio/mpeg,mpegversion=4,stream-format=raw! Мультиплексор.
Конвейер 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, ¤t)) {
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;
}