I've made for you very simple application which you can use to reproduce
the problem. It takes the video stream as a source, decodes it, encodes it
into mpeg2, mux it into mpegts container, saves it to file. you can use any
video file as a source. As the file reaches the end pipeline receives EOS
event, at the event I try to set pipeline to GST_STATE_READY, it causes a
crash. Here's complete code below. I will try to give you backtrace with
gdb later.
typedef struct _CustomData {
//GstElement *pipeline;
GstElement *source;
GstElement *convert;
GstElement *q;
GstElement *q1;
GstElement *sink;
GstElement *filter;
GstCaps *filtercaps;
} CustomData;
static CustomData data;
GstElement *pipeline;
GstElement *ebin;
GstEncodingProfile *prof;
GstBus *bus;
GstMessage *msg;
GstStateChangeReturn ret;
GstPadLinkReturn res;
GMainLoop *loop;
gchar *format= "video/mpegts,systemstream=True,packetsize=188";
gchar *aformat= "audio/mpeg, mpegversion=(int)4, rate=(int)16000,
stream-format=(string)adts, base-profile=(string)lc, bitrate=(int)192";
//audio/x-ac3";
gchar *vformat= "video/mpeg,mpegversion=2,systemstream=False,
bitrate=(int)7500";//"video/x-h264";
static GstEncodingProfile *
create_profile (GstCaps * cf, GstCaps * vf, GstCaps * af)
{
GstEncodingContainerProfile *cprof = NULL;
GstEncodingProfile * vtmp = NULL;
cprof = gst_encoding_container_profile_new ((gchar *)
"test-application-profile", NULL, cf, NULL);
if (vf)
{
vtmp = (GstEncodingProfile *) gst_encoding_video_profile_new (vf, NULL,
NULL, 0);
gst_encoding_container_profile_add_profile (cprof, vtmp);
}
if (af)
gst_encoding_container_profile_add_profile (cprof, (GstEncodingProfile
*)
gst_encoding_audio_profile_new (af, NULL, NULL, 0));
/* print out some info */
{
gchar *desc = gst_pb_utils_get_codec_description (cf);
gchar *cd = gst_caps_to_string (cf);
g_print ("Encoding parameters\n");
g_print (" Container format : %s (%s)\n", desc, cd);
g_free (desc);
g_free (cd);
if (vf) {
desc = gst_pb_utils_get_codec_description (vf);
cd = gst_caps_to_string (vf);
g_print (" Video format : %s (%s)\n", desc, cd);
g_free (desc);
g_free (cd);
}
if (af) {
desc = gst_pb_utils_get_codec_description (af);
cd = gst_caps_to_string (af);
g_print (" Audio format : %s (%s)\n", desc, cd);
g_free (desc);
g_free (cd);
}
}
return (GstEncodingProfile *) cprof;
}
static GstEncodingProfile *
create_profile_from_string (gchar * format, gchar * vformat, gchar *
aformat)
{
GstEncodingProfile *prof = NULL;
GstCaps *cf = NULL, *vf = NULL, *af = NULL;
if (format)
cf = gst_caps_from_string (format);
if (vformat)
vf = gst_caps_from_string (vformat);
if (aformat)
af = gst_caps_from_string (aformat);
if (G_UNLIKELY ((vformat && (vf == NULL)) || (aformat && (af == NULL))))
goto beach;
prof = create_profile (cf, vf, af);
beach:
if (cf)
gst_caps_unref (cf);
if (vf)
gst_caps_unref (vf);
if (af)
gst_caps_unref (af);
return prof;
}
gboolean bus_call(GstBus *bus, GstMessage *msg, void *data)
{
gchar *debug;
GError *err;
GMainLoop *loop = (GMainLoop*)data;
switch (GST_MESSAGE_TYPE(msg))
{
case GST_MESSAGE_EOS:
g_print("EOS received on OBJ NAME
%s\n",GST_OBJECT_NAME(msg->src));
//g_main_loop_quit (loop);
gst_element_set_state (pipeline, GST_STATE_READY);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
break;
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug);
g_free(debug);
g_print("BUS CALL %s\n", err->message);
g_error_free(err);
g_main_loop_quit (loop);
break;
default:
break;
}
return TRUE;
}
/* This function will be called by the pad-added signal */
static void pad_added_handler (GstElement *src, GstPad *new_pad, GstElement
*sink) {
GstPad *gsink_pad = gst_element_get_static_pad (sink, "sink");
GstPadLinkReturn ret;
GstCaps *new_pad_caps = NULL;
GstStructure *new_pad_struct = NULL;
const gchar *new_pad_type = NULL;
g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad),
GST_ELEMENT_NAME (src));
/* Check the new pad's type */
new_pad_caps = gst_pad_query_caps (new_pad, NULL);
new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
new_pad_type = gst_structure_get_name (new_pad_struct);
if (!g_str_has_prefix (new_pad_type, "video/x-raw") && !g_str_has_prefix
(new_pad_type, "audio/x-raw")) {
g_print (" It has type '%s' which is not raw video or audio.
Ignoring.\n", new_pad_type);
goto exit;
}
if (g_str_has_prefix (new_pad_type, "video/x-raw"))
{
ret = gst_pad_link (new_pad, gsink_pad);
}
else
{
return;
}
if (GST_PAD_LINK_FAILED (ret)) {
g_print (" Type is '%s' but link failed.\n", new_pad_type);
} else {
g_print (" Link succeeded (type '%s').\n", new_pad_type);
}
exit:
/* Unreference the new pad's caps, if we got them */
if (new_pad_caps != NULL)
gst_caps_unref (new_pad_caps);
/* Unreference the sink pad */
gst_object_unref (gsink_pad);
}
int
main (int argc,
char *argv[])
{
gst_init (&argc, &argv);
g_print ("gstreamer initialized.\n");
/* Create the elements */
data.source = gst_element_factory_make ("uridecodebin", "source");
data.convert = gst_element_factory_make ("videoscale", "convert");
data.q = gst_element_factory_make ("queue", "q");
data.q1 = gst_element_factory_make ("queue", "q1");
data.sink = gst_element_factory_make ("filesink", "sink");
g_object_set (G_OBJECT (data.sink), "location", "c:\\tmp\\channel.ts",
NULL);
data.filter = gst_element_factory_make("capsfilter","filter");
data.filtercaps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, "I420",
"width", G_TYPE_INT, 854,
"height", G_TYPE_INT, 480,
NULL);
g_object_set (G_OBJECT (data.filter), "caps", data.filtercaps, NULL);
g_print ("starting profile initialization\n");
/* Create the profile */
prof = create_profile_from_string (format, vformat, aformat);
if (G_UNLIKELY (prof == NULL)) {
g_print ("Encoding arguments are not valid !\n");
return -1;
}
/* Create the encodebin */
ebin = gst_element_factory_make ("encodebin", NULL);
g_object_set (ebin, "profile", prof, NULL);
/* Create the empty pipeline */
pipeline = gst_pipeline_new ("test-pipeline");
loop = g_main_loop_new (NULL, FALSE);
if (!pipeline || !data.source || !data.q || !data.sink) {
g_printerr ("Not all elements could be created.\n");
return -1;
}
/* Build the pipeline. */
gst_bin_add_many (GST_BIN (pipeline), data.source, data.q,data.convert,
data.filter, ebin, data.q1, data.sink, NULL);
if (!gst_element_link_many (data.q, data.convert, data.filter, ebin,
data.q1, data.sink, NULL)) {
g_printerr ("Elements could not be linked.\n");
gst_object_unref (pipeline);
return -1;
}
/* Set the URI to play */
g_object_set (data.source, "uri", "
http://www.quebec511.info/diffusion/fr/camera/camera.ashx?format=mp4&id=3505",
NULL);
/* Connect to the pad-added signal */
g_signal_connect (data.source, "pad-added", G_CALLBACK
(pad_added_handler), data.q);
/* we add a message handler */
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
/* Set the pipeline to "playing" state*/
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* Iterate */
g_print ("Running...\n");
//g_timeout_add_seconds (1, timeout_cb, loop);
g_main_loop_run (loop);
/* Out of the main loop, clean up nicely */
g_print ("Returned, stopping playback\n");
gst_element_set_state (pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (pipeline));
return 0;
}
Post by Sebastian DrögePost by Michael GuinzbourgI think the issue is very easy to reproduce: build any pipeline which
has encodebin element and ask encodebin to encode in mpeg2. then play
any file and try to restart pipeline when it reaches the end of file.
Can you provide such code then? That makes it more likely someone tries
to find the reason for your crash. Your code does not really provide a
lot of details about what you're doing there.
Also please provide a backtrace of all threads with gdb.
--
Sebastian Dröge, Centricular Ltd · http://www.centricular.com
_______________________________________________
gstreamer-devel mailing list
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel