Crash when trying to stop pipeline containing encodebin

Michael Guinzbourg mguinzbourg at gmail.com
Thu May 12 01:21:46 UTC 2016


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;
}


On 11 May 2016 at 02:33, Sebastian Dröge <sebastian at centricular.com> wrote:

> On Mi, 2016-05-11 at 02:24 -0400, Michael Guinzbourg wrote:
> > I 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
> gstreamer-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20160511/fadfb952/attachment-0001.html>


More information about the gstreamer-devel mailing list