Change pipeline encoder h264 to h265 at runtime

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Change pipeline encoder h264 to h265 at runtime

MustafaBkrc
This post was updated on .
Hello,

I have an issue about changing GStreamer encoder elements, h264 to h265, at
runtime. I followed the instruction and used example code from gstreamer
pipeline manipulation.

https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c#dynamically-changing-the-pipeline
<https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c#dynamically-changing-the-pipeline

I can successfully change the h264 to h265 encoder element at runtime but I
think there are something left about the h264 encoder signature in the
pipeline and also I cannot get the frame from pipeline  these is the output
from ffplay command (ffplay  udp://@:9000?listen -analyzeduration 1M)


https://i.stack.imgur.com/auV14.png

I wonder how can I overcome this issue, is it about a timing issue or
something? I would be very appreciated of any help. Thanks.

This is the full code

    #include <iostream>
    #include <gst/gst.h>
    #include <thread>
    #include <unistd.h>

    using namespace std;

    /// Example Pipeline ///
    //gst-launch-1.0 filesrc
location=/home/ubuntu18/Desktop/BigBuckBunny.mp4 ! video/x-raw, width=1920,
    //height=1080, format=NV16_LE32, framerate=60/1 ! decodebin ! x264enc !
mpegtsmux alignment=7 !
    //udpsink host=127.0.0.1 port=9000 --gst-debug=3
   
    static gboolean my_bus_callback (GstBus * bus, GstMessage * message,
gpointer data);

        struct GstreamerStream
        {
            GstElement *pipeline;
            GstElement *filesrc;
            GstElement *capsfilter;
            GstElement *decodebin;
            GstElement *x264enc;
            GstElement *x265enc;
            GstElement *mpegtsmux1;
            GstElement *udpsink1 ;

            GstPad *decodebinPad;

            GMainLoop *loop;
            GstBus    *bus;
            GstMessage  *msg;
        };

        void signal_cb (GstElement* object, GstPad* pad, gpointer user_data)
        {
            auto data = reinterpret_cast<GstreamerStream*>(user_data);
            GstPad *decodebin_src_pad= gst_element_get_static_pad (object,
"src%u");
            GstPad* x264enc_sink_pad =
gst_element_get_static_pad(data->x264enc,"sink");

            g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME
(pad), GST_ELEMENT_NAME (object));

            /* If our converter is already linked, we have nothing to do
here */
            if (gst_pad_is_linked (pad)) {
              g_print ("We are already linked. Ignoring.\n");
            }

            /* Attempt the link */
            auto ret = gst_pad_link (pad, x264enc_sink_pad);

            if (GST_PAD_LINK_FAILED (ret)) {
              g_print ("Type is '%s' but link failed.\n", pad);
            } else {
              g_print ("Link succeeded (type '%s').\n", pad);
              data->decodebinPad = pad;
            }

            gst_object_unref (x264enc_sink_pad);
        }

        static GstPadProbeReturn
        event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer
user_data)
        {
            auto stream =  reinterpret_cast<GstreamerStream*>(user_data);

            GstElement *next = stream->x265enc;

            if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) !=
GST_EVENT_EOS)
              return GST_PAD_PROBE_PASS;

            gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));

            g_print ("Switching from '%s' to '%s'..\n", GST_OBJECT_NAME
(stream->x264enc),
                GST_OBJECT_NAME (next));

            gst_element_set_state (stream->x264enc, GST_STATE_NULL);

            /* remove unlinks automatically */
            GST_DEBUG_OBJECT (stream->pipeline, "removing %" GST_PTR_FORMAT,
stream->x264enc);
            gst_bin_remove (GST_BIN (stream->pipeline), stream->x264enc);

            GST_DEBUG_OBJECT (stream->pipeline, "adding   %" GST_PTR_FORMAT,
next);
            gst_bin_add (GST_BIN (stream->pipeline), next);

            auto enc265sinkpad = gst_element_get_static_pad(next,"sink");
            if(!gst_pad_link(stream->decodebinPad,enc265sinkpad))
              std::cout << "Linked src and sink pad success " << std::endl;

            GST_DEBUG_OBJECT (stream->pipeline, "linking..");

            gst_element_link_many (next, stream->mpegtsmux1, NULL);
            gst_element_sync_state_with_parent(next);
            GST_DEBUG_OBJECT (stream->pipeline, "done");

            auto elem =
gst_bin_get_by_name(GST_BIN(stream->pipeline),"x265enc_elem");
            if(elem)
                std::cout <<" ***** Element name : " <<
GST_OBJECT_NAME(elem) << " *****" << std::endl;
            else
            {
                auto elem2 =
gst_bin_get_by_name(GST_BIN(stream->pipeline),"x264enc_elem");
                std::cout <<" ***** Element name : " <<
GST_OBJECT_NAME(elem2) << " *****" << std::endl;
            }

          return GST_PAD_PROBE_DROP;
        }


        static GstPadProbeReturn
        pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer
user_data)
        {
          GstPad *srcpad, *sinkpad;
          auto stream = reinterpret_cast<GstreamerStream*>(user_data);

          GST_DEBUG_OBJECT (pad, "pad is blocked now");

          /* remove the probe first */
          gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
          auto filesrcPad =
gst_element_get_static_pad(stream->filesrc,"src");

          /* install new probe for EOS */
          srcpad = gst_element_get_static_pad (stream->x264enc, "src");

          gst_pad_add_probe (srcpad,
static_cast<GstPadProbeType>(GST_PAD_PROBE_TYPE_BLOCK |
              GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), event_probe_cb,
user_data, NULL);
          gst_object_unref (srcpad);

          /* push EOS into the element, the probe will be fired when the
           * EOS leaves the effect and it has thus drained all of its data
*/
          sinkpad = gst_element_get_static_pad (stream->x264enc, "sink");
          gst_pad_send_event (sinkpad, gst_event_new_eos ());

          gst_object_unref (sinkpad);

          return GST_PAD_PROBE_OK;
        }

        static gboolean
        timeout_cb (gpointer user_data)
        {
            auto stream = reinterpret_cast<GstreamerStream*>(user_data);
            auto blockPad = stream->decodebinPad;

            std::cout  << "Pad name : " << (GST_DEBUG_PAD_NAME(blockPad)) <<
std::endl;

          gst_pad_add_probe (blockPad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
              pad_probe_cb, user_data, NULL);


          return TRUE;
        }

        int main()
        {

            gst_init(NULL,NULL);

            static GstreamerStream stream;
            stream.pipeline =
gst_element_factory_make("pipeline","pipeline_elem");
            stream.filesrc =
gst_element_factory_make("filesrc","filesrc_elem");
            stream.capsfilter =
gst_element_factory_make("capsfilter","capsfilter_elem");
            stream.decodebin =
gst_element_factory_make("decodebin","decodebin_elem");

            stream.x264enc =
gst_element_factory_make("x264enc","x264enc_elem");
            stream.x265enc =
gst_element_factory_make("x265enc","x265enc_elem");
            stream.mpegtsmux1 =
gst_element_factory_make("mpegtsmux","mpegtsmux_element");
            stream.udpsink1 =
gst_element_factory_make("udpsink","udpsink_element");

            if(!stream.pipeline, !stream.filesrc || !stream.capsfilter ||
!stream.decodebin  || !stream.x264enc || !stream.mpegtsmux1 ||
!stream.udpsink1)
            {
                g_error("Element create error");
            }

           
g_object_set(stream.filesrc,"location","/home/mbkrc/Desktop/ElephantsDream.mp4",NULL);


            g_object_set(stream.mpegtsmux1,"alignment",7,NULL);
           
g_object_set(stream.udpsink1,"host","127.0.0.1","port",9000,"sync", FALSE,
"async", FALSE,NULL);
            g_object_set (G_OBJECT (stream.x264enc), "bitrate", 1000, NULL);


           
gst_bin_add_many(GST_BIN(stream.pipeline),stream.filesrc,stream.capsfilter,stream.decodebin,stream.x264enc,
                             stream.mpegtsmux1,stream.udpsink1,NULL);


           auto newCaps = gst_caps_new_simple("video/x-raw",
                   "width", G_TYPE_INT, 1920,
                   "height", G_TYPE_INT, 1080,
                   "framerate", GST_TYPE_FRACTION, 60, 1, NULL);

           g_object_set(stream.capsfilter,"caps",newCaps,NULL);

           
gst_element_link_many(stream.filesrc,stream.capsfilter,stream.decodebin,NULL);

           
if(!gst_element_link_many(stream.x264enc,stream.mpegtsmux1,stream.udpsink1,NULL))
                std::cerr << "Link Failed" << std::endl;

           
g_signal_connect(stream.decodebin,"pad-added",(GCallback)signal_cb,&stream);

            stream.bus = gst_pipeline_get_bus (GST_PIPELINE
(stream.pipeline));
            auto bus_watch_id = gst_bus_add_watch (stream.bus,
my_bus_callback, stream.loop);
            gst_object_unref (stream.bus);


            gst_element_set_state(stream.pipeline,GST_STATE_PLAYING);

            std::thread th{[&]()
                           {
                            sleep(5);
                            timeout_cb(&stream);
                           }};

            stream.loop = g_main_loop_new (NULL, FALSE);
            g_main_loop_run (stream.loop);

            /* clean up */
            gst_element_set_state (stream.pipeline, GST_STATE_NULL);
            gst_object_unref (stream.pipeline);
            g_source_remove (bus_watch_id);
            g_main_loop_unref (stream.loop);

            return 0;
        }

        static gboolean
        my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
        {
          g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
          auto loop = reinterpret_cast<GMainLoop*>(data);

          switch (GST_MESSAGE_TYPE (message)) {
            case GST_MESSAGE_ERROR:{
              GError *err;
              gchar *debug;

              gst_message_parse_error (message, &err, &debug);
              g_print ("Error: %s\n", err->message);
              g_error_free (err);
              g_free (debug);

              g_main_loop_quit (loop);
              break;
            }
          case GST_MESSAGE_ASYNC_DONE:
          {
              std::cout << "Asyn Done : " << std::endl;
              break;
          }
            case GST_MESSAGE_EOS:
              /* end-of-stream */
              g_main_loop_quit (loop);
              break;
            default:
              /* unhandled message */
              break;
          }
        }
        `
--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
gstreamer-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Change pipeline encoder h264 to h265 at runtime

Toshick
Hello,

From my quick look, I can suggest next:
You're blocking Downstream at the decodebin's pad. But as I understand from your code, EOS event travels downstream from the encoder to udpsink.
So, you should consider or block upstream on the udpsink, or catch EOS event before it went downstream, or re-initialize udpsink (through READY->PLAYING) STATES again.
But IMHO, you should avoid sending EOS (as you do not actually have EOS, 'cos you're planning to continue streaming with another encoding)

Best regards,
Anton.


On Mon, Dec 7, 2020 at 1:25 AM MustafaBkrc <[hidden email]> wrote:
Hello,

I have an issue about changing GStreamer encoder elements, h264 to h265, at
runtime. I followed the instruction and used example code from gstreamer
pipeline manipulation.

https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c#dynamically-changing-the-pipeline
<https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c#dynamically-changing-the-pipeline

I can successfully change the h264 to h265 encoder element at runtime but I
think there are something left about the h264 encoder signature in the
pipeline and also I cannot get the frame from pipeline  these is the output
from ffplay command (ffplay  udp://@:9000?listen -analyzeduration 1M)


https://i.stack.imgur.com/auV14.png

I wonder how can I overcome this issue, is it about a timing issue or
something? I would be very appreciated of any help. Thanks.

This is the full code

    #include <iostream>
    #include <gst/gst.h>
    #include <thread>
    #include <unistd.h>

    using namespace std;

    /// Example Pipeline ///
    //gst-launch-1.0 filesrc
location=/home/ubuntu18/Desktop/BigBuckBunny.mp4 ! video/x-raw, width=1920,
    //height=1080, format=NV16_LE32, framerate=60/1 ! decodebin ! x264enc !
mpegtsmux alignment=7 !
    //udpsink host=127.0.0.1 port=9000 --gst-debug=3

    static gboolean my_bus_callback (GstBus * bus, GstMessage * message,
gpointer data);

        struct GstreamerStream
        {
            GstElement *pipeline;
            GstElement *filesrc;
            GstElement *capsfilter;
            GstElement *decodebin;
            GstElement *x264enc;
            GstElement *x265enc;
            GstElement *mpegtsmux1;
            GstElement *udpsink1 ;

            GstPad *decodebinPad;

            GMainLoop *loop;
            GstBus    *bus;
            GstMessage  *msg;
        };

        void signal_cb (GstElement* object, GstPad* pad, gpointer user_data)
        {
            auto data = reinterpret_cast<GstreamerStream*>(user_data);
            GstPad *decodebin_src_pad= gst_element_get_static_pad (object,
"src%u");
            GstPad* x264enc_sink_pad =
gst_element_get_static_pad(data->x264enc,"sink");

            g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME
(pad), GST_ELEMENT_NAME (object));

            /* If our converter is already linked, we have nothing to do
here */
            if (gst_pad_is_linked (pad)) {
              g_print ("We are already linked. Ignoring.\n");
            }

            /* Attempt the link */
            auto ret = gst_pad_link (pad, x264enc_sink_pad);

            if (GST_PAD_LINK_FAILED (ret)) {
              g_print ("Type is '%s' but link failed.\n", pad);
            } else {
              g_print ("Link succeeded (type '%s').\n", pad);
              data->decodebinPad = pad;
            }

            gst_object_unref (x264enc_sink_pad);
        }

        static GstPadProbeReturn
        event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer
user_data)
        {
            auto stream =  reinterpret_cast<GstreamerStream*>(user_data);

            GstElement *next = stream->x265enc;

            if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) !=
GST_EVENT_EOS)
              return GST_PAD_PROBE_PASS;

            gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));

            g_print ("Switching from '%s' to '%s'..\n", GST_OBJECT_NAME
(stream->x264enc),
                GST_OBJECT_NAME (next));

            gst_element_set_state (stream->x264enc, GST_STATE_NULL);

            /* remove unlinks automatically */
            GST_DEBUG_OBJECT (stream->pipeline, "removing %" GST_PTR_FORMAT,
stream->x264enc);
            gst_bin_remove (GST_BIN (stream->pipeline), stream->x264enc);

            GST_DEBUG_OBJECT (stream->pipeline, "adding   %" GST_PTR_FORMAT,
next);
            gst_bin_add (GST_BIN (stream->pipeline), next);

            auto enc265sinkpad = gst_element_get_static_pad(next,"sink");
            if(!gst_pad_link(stream->decodebinPad,enc265sinkpad))
              std::cout << "Linked src and sink pad success " << std::endl;

            GST_DEBUG_OBJECT (stream->pipeline, "linking..");

            gst_element_link_many (next, stream->mpegtsmux1, NULL);
            gst_element_sync_state_with_parent(next);
            GST_DEBUG_OBJECT (stream->pipeline, "done");

            auto elem =
gst_bin_get_by_name(GST_BIN(stream->pipeline),"x265enc_elem");
            if(elem)
                std::cout <<" ***** Element name : " <<
GST_OBJECT_NAME(elem) << " *****" << std::endl;
            else
            {
                auto elem2 =
gst_bin_get_by_name(GST_BIN(stream->pipeline),"x264enc_elem");
                std::cout <<" ***** Element name : " <<
GST_OBJECT_NAME(elem2) << " *****" << std::endl;
            }

          return GST_PAD_PROBE_DROP;
        }


        static GstPadProbeReturn
        pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer
user_data)
        {
          GstPad *srcpad, *sinkpad;
          auto stream = reinterpret_cast<GstreamerStream*>(user_data);

          GST_DEBUG_OBJECT (pad, "pad is blocked now");

          /* remove the probe first */
          gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
          auto filesrcPad =
gst_element_get_static_pad(stream->filesrc,"src");

          /* install new probe for EOS */
          srcpad = gst_element_get_static_pad (stream->x264enc, "src");

          gst_pad_add_probe (srcpad,
static_cast<GstPadProbeType>(GST_PAD_PROBE_TYPE_BLOCK |
              GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), event_probe_cb,
user_data, NULL);
          gst_object_unref (srcpad);

          /* push EOS into the element, the probe will be fired when the
           * EOS leaves the effect and it has thus drained all of its data
*/
          sinkpad = gst_element_get_static_pad (stream->x264enc, "sink");
          gst_pad_send_event (sinkpad, gst_event_new_eos ());

          gst_object_unref (sinkpad);

          return GST_PAD_PROBE_OK;
        }

        static gboolean
        timeout_cb (gpointer user_data)
        {
            auto stream = reinterpret_cast<GstreamerStream*>(user_data);
            auto blockPad = stream->decodebinPad;

            std::cout  << "Pad name : " << (GST_DEBUG_PAD_NAME(blockPad)) <<
std::endl;

          gst_pad_add_probe (blockPad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
              pad_probe_cb, user_data, NULL);


          return TRUE;
        }

        int main()
        {

            gst_init(NULL,NULL);

            static GstreamerStream stream;
            stream.pipeline =
gst_element_factory_make("pipeline","pipeline_elem");
            stream.filesrc =
gst_element_factory_make("filesrc","filesrc_elem");
            stream.capsfilter =
gst_element_factory_make("capsfilter","capsfilter_elem");
            stream.decodebin =
gst_element_factory_make("decodebin","decodebin_elem");

            stream.x264enc =
gst_element_factory_make("x264enc","x264enc_elem");
            stream.x265enc =
gst_element_factory_make("x265enc","x265enc_elem");
            stream.mpegtsmux1 =
gst_element_factory_make("mpegtsmux","mpegtsmux_element");
            stream.udpsink1 =
gst_element_factory_make("udpsink","udpsink_element");

            if(!stream.pipeline, !stream.filesrc || !stream.capsfilter ||
!stream.decodebin  || !stream.x264enc || !stream.mpegtsmux1 ||
!stream.udpsink1)
            {
                g_error("Element create error");
            }


g_object_set(stream.filesrc,"location","/home/mbkrc/Desktop/ElephantsDream.mp4",NULL);


            g_object_set(stream.mpegtsmux1,"alignment",7,NULL);

g_object_set(stream.udpsink1,"host","127.0.0.1","port",9000,"sync", FALSE,
"async", FALSE,NULL);
            g_object_set (G_OBJECT (stream.x264enc), "bitrate", 1000, NULL);



gst_bin_add_many(GST_BIN(stream.pipeline),stream.filesrc,stream.capsfilter,stream.decodebin,stream.x264enc,
                             stream.mpegtsmux1,stream.udpsink1,NULL);


           auto newCaps = gst_caps_new_simple("video/x-raw",
                   "width", G_TYPE_INT, 1920,
                   "height", G_TYPE_INT, 1080,
                   "framerate", GST_TYPE_FRACTION, 60, 1, NULL);

           g_object_set(stream.capsfilter,"caps",newCaps,NULL);


gst_element_link_many(stream.filesrc,stream.capsfilter,stream.decodebin,NULL);


if(!gst_element_link_many(stream.x264enc,stream.mpegtsmux1,stream.udpsink1,NULL))
                std::cerr << "Link Failed" << std::endl;


g_signal_connect(stream.decodebin,"pad-added",(GCallback)signal_cb,&stream);

            stream.bus = gst_pipeline_get_bus (GST_PIPELINE
(stream.pipeline));
            auto bus_watch_id = gst_bus_add_watch (stream.bus,
my_bus_callback, stream.loop);
            gst_object_unref (stream.bus);


            gst_element_set_state(stream.pipeline,GST_STATE_PLAYING);

            std::thread th{[&]()
                           {
                            sleep(5);
                            timeout_cb(&stream);
                           }};

            stream.loop = g_main_loop_new (NULL, FALSE);
            g_main_loop_run (stream.loop);

            /* clean up */
            gst_element_set_state (stream.pipeline, GST_STATE_NULL);
            gst_object_unref (stream.pipeline);
            g_source_remove (bus_watch_id);
            g_main_loop_unref (stream.loop);

            return 0;
        }

        static gboolean
        my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
        {
          g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
          auto loop = reinterpret_cast<GMainLoop*>(data);

          switch (GST_MESSAGE_TYPE (message)) {
            case GST_MESSAGE_ERROR:{
              GError *err;
              gchar *debug;

              gst_message_parse_error (message, &err, &debug);
              g_print ("Error: %s\n", err->message);
              g_error_free (err);
              g_free (debug);

              g_main_loop_quit (loop);
              break;
            }
          case GST_MESSAGE_ASYNC_DONE:
          {
              std::cout << "Asyn Done : " << std::endl;
              break;
          }
            case GST_MESSAGE_EOS:
              /* end-of-stream */
              g_main_loop_quit (loop);
              break;
            default:
              /* unhandled message */
              break;
          }
        }
        `


 Hello,

I have an issue about changing GStreamer encoder elements, h264 to h265, at
runtime. I followed the instruction and used example code from [gstreamer
pipeline manipulation at runtime][1]


I can successfully change the h264 to h265 encoder element at runtime but I
think there are something left about the h264 encoder signature in the
pipeline and also I cannot get the frame from pipeline  these is the output
from ffplay command (ffplay  udp://@:9000?listen -analyzeduration
1M)org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c#dynamically-changing-the-pipeline
  [2]: https://i.stack.imgur.com/auV14.png

I wonder how can I overcome this issue, is it about a timing issue or
something? I would be very appreciated of any help. Thanks.

This is the full code

    #include <iostream>
    #include <gst/gst.h>
    #include <thread>
    #include <unistd.h>

    using namespace std;

    /// Example Pipeline ///
    //gst-launch-1.0 filesrc
location=/home/ubuntu18/Desktop/BigBuckBunny.mp4 ! video/x-raw, width=1920,
    //height=1080, format=NV16_LE32, framerate=60/1 ! decodebin ! x264enc !
mpegtsmux alignment=7 !
    //udpsink host=127.0.0.1 port=9000 --gst-debug=3

    static gboolean my_bus_callback (GstBus * bus, GstMessage * message,
gpointer data);

        struct GstreamerStream
        {
            GstElement *pipeline;
            GstElement *filesrc;
            GstElement *capsfilter;
            GstElement *decodebin;
            GstElement *x264enc;
            GstElement *x265enc;
            GstElement *mpegtsmux1;
            GstElement *udpsink1 ;

            GstPad *decodebinPad;

            GMainLoop *loop;
            GstBus    *bus;
            GstMessage  *msg;
        };

        void signal_cb (GstElement* object, GstPad* pad, gpointer user_data)
        {
            auto data = reinterpret_cast<GstreamerStream*>(user_data);
            GstPad *decodebin_src_pad= gst_element_get_static_pad (object,
"src%u");
            GstPad* x264enc_sink_pad =
gst_element_get_static_pad(data->x264enc,"sink");

            g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME
(pad), GST_ELEMENT_NAME (object));

            /* If our converter is already linked, we have nothing to do
here */
            if (gst_pad_is_linked (pad)) {
              g_print ("We are already linked. Ignoring.\n");
            }

            /* Attempt the link */
            auto ret = gst_pad_link (pad, x264enc_sink_pad);

            if (GST_PAD_LINK_FAILED (ret)) {
              g_print ("Type is '%s' but link failed.\n", pad);
            } else {
              g_print ("Link succeeded (type '%s').\n", pad);
              data->decodebinPad = pad;
            }

            gst_object_unref (x264enc_sink_pad);
        }

        static GstPadProbeReturn
        event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer
user_data)
        {
            auto stream =  reinterpret_cast<GstreamerStream*>(user_data);

            GstElement *next = stream->x265enc;

            if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) !=
GST_EVENT_EOS)
              return GST_PAD_PROBE_PASS;

            gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));

            g_print ("Switching from '%s' to '%s'..\n", GST_OBJECT_NAME
(stream->x264enc),
                GST_OBJECT_NAME (next));

            gst_element_set_state (stream->x264enc, GST_STATE_NULL);

            /* remove unlinks automatically */
            GST_DEBUG_OBJECT (stream->pipeline, "removing %" GST_PTR_FORMAT,
stream->x264enc);
            gst_bin_remove (GST_BIN (stream->pipeline), stream->x264enc);

            GST_DEBUG_OBJECT (stream->pipeline, "adding   %" GST_PTR_FORMAT,
next);
            gst_bin_add (GST_BIN (stream->pipeline), next);

            auto enc265sinkpad = gst_element_get_static_pad(next,"sink");
            if(!gst_pad_link(stream->decodebinPad,enc265sinkpad))
              std::cout << "Linked src and sink pad success " << std::endl;

            GST_DEBUG_OBJECT (stream->pipeline, "linking..");

            gst_element_link_many (next, stream->mpegtsmux1, NULL);
            gst_element_sync_state_with_parent(next);
            GST_DEBUG_OBJECT (stream->pipeline, "done");

            auto elem =
gst_bin_get_by_name(GST_BIN(stream->pipeline),"x265enc_elem");
            if(elem)
                std::cout <<" ***** Element name : " <<
GST_OBJECT_NAME(elem) << " *****" << std::endl;
            else
            {
                auto elem2 =
gst_bin_get_by_name(GST_BIN(stream->pipeline),"x264enc_elem");
                std::cout <<" ***** Element name : " <<
GST_OBJECT_NAME(elem2) << " *****" << std::endl;
            }

          return GST_PAD_PROBE_DROP;
        }


        static GstPadProbeReturn
        pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer
user_data)
        {
          GstPad *srcpad, *sinkpad;
          auto stream = reinterpret_cast<GstreamerStream*>(user_data);

          GST_DEBUG_OBJECT (pad, "pad is blocked now");

          /* remove the probe first */
          gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
          auto filesrcPad =
gst_element_get_static_pad(stream->filesrc,"src");

          /* install new probe for EOS */
          srcpad = gst_element_get_static_pad (stream->x264enc, "src");

          gst_pad_add_probe (srcpad,
static_cast<GstPadProbeType>(GST_PAD_PROBE_TYPE_BLOCK |
              GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), event_probe_cb,
user_data, NULL);
          gst_object_unref (srcpad);

          /* push EOS into the element, the probe will be fired when the
           * EOS leaves the effect and it has thus drained all of its data
*/
          sinkpad = gst_element_get_static_pad (stream->x264enc, "sink");
          gst_pad_send_event (sinkpad, gst_event_new_eos ());

          gst_object_unref (sinkpad);

          return GST_PAD_PROBE_OK;
        }

        static gboolean
        timeout_cb (gpointer user_data)
        {
            auto stream = reinterpret_cast<GstreamerStream*>(user_data);
            auto blockPad = stream->decodebinPad;

            std::cout  << "Pad name : " << (GST_DEBUG_PAD_NAME(blockPad)) <<
std::endl;

          gst_pad_add_probe (blockPad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
              pad_probe_cb, user_data, NULL);


          return TRUE;
        }

        int main()
        {

            gst_init(NULL,NULL);

            static GstreamerStream stream;
            stream.pipeline =
gst_element_factory_make("pipeline","pipeline_elem");
            stream.filesrc =
gst_element_factory_make("filesrc","filesrc_elem");
            stream.capsfilter =
gst_element_factory_make("capsfilter","capsfilter_elem");
            stream.decodebin =
gst_element_factory_make("decodebin","decodebin_elem");

            stream.x264enc =
gst_element_factory_make("x264enc","x264enc_elem");
            stream.x265enc =
gst_element_factory_make("x265enc","x265enc_elem");
            stream.mpegtsmux1 =
gst_element_factory_make("mpegtsmux","mpegtsmux_element");
            stream.udpsink1 =
gst_element_factory_make("udpsink","udpsink_element");

            if(!stream.pipeline, !stream.filesrc || !stream.capsfilter ||
!stream.decodebin  || !stream.x264enc || !stream.mpegtsmux1 ||
!stream.udpsink1)
            {
                g_error("Element create error");
            }


g_object_set(stream.filesrc,"location","/home/mbkrc/Desktop/ElephantsDream.mp4",NULL);


            g_object_set(stream.mpegtsmux1,"alignment",7,NULL);

g_object_set(stream.udpsink1,"host","127.0.0.1","port",9000,"sync", FALSE,
"async", FALSE,NULL);
            g_object_set (G_OBJECT (stream.x264enc), "bitrate", 1000, NULL);



gst_bin_add_many(GST_BIN(stream.pipeline),stream.filesrc,stream.capsfilter,stream.decodebin,stream.x264enc,
                             stream.mpegtsmux1,stream.udpsink1,NULL);


           auto newCaps = gst_caps_new_simple("video/x-raw",
                   "width", G_TYPE_INT, 1920,
                   "height", G_TYPE_INT, 1080,
                   "framerate", GST_TYPE_FRACTION, 60, 1, NULL);

           g_object_set(stream.capsfilter,"caps",newCaps,NULL);


gst_element_link_many(stream.filesrc,stream.capsfilter,stream.decodebin,NULL);


if(!gst_element_link_many(stream.x264enc,stream.mpegtsmux1,stream.udpsink1,NULL))
                std::cerr << "Link Failed" << std::endl;


g_signal_connect(stream.decodebin,"pad-added",(GCallback)signal_cb,&stream);

            stream.bus = gst_pipeline_get_bus (GST_PIPELINE
(stream.pipeline));
            auto bus_watch_id = gst_bus_add_watch (stream.bus,
my_bus_callback, stream.loop);
            gst_object_unref (stream.bus);


            gst_element_set_state(stream.pipeline,GST_STATE_PLAYING);

            std::thread th{[&]()
                           {
                            sleep(5);
                            timeout_cb(&stream);
                           }};

            stream.loop = g_main_loop_new (NULL, FALSE);
            g_main_loop_run (stream.loop);

            /* clean up */
            gst_element_set_state (stream.pipeline, GST_STATE_NULL);
            gst_object_unref (stream.pipeline);
            g_source_remove (bus_watch_id);
            g_main_loop_unref (stream.loop);

            return 0;
        }

        static gboolean
        my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
        {
          g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
          auto loop = reinterpret_cast<GMainLoop*>(data);

          switch (GST_MESSAGE_TYPE (message)) {
            case GST_MESSAGE_ERROR:{
              GError *err;
              gchar *debug;

              gst_message_parse_error (message, &err, &debug);
              g_print ("Error: %s\n", err->message);
              g_error_free (err);
              g_free (debug);

              g_main_loop_quit (loop);
              break;
            }
          case GST_MESSAGE_ASYNC_DONE:
          {
              std::cout << "Asyn Done : " << std::endl;
              break;
          }
            case GST_MESSAGE_EOS:
              /* end-of-stream */
              g_main_loop_quit (loop);
              break;
            default:
              /* unhandled message */
              break;
          }
        }
        `






--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Change pipeline encoder h264 to h265 at runtime

MustafaBkrc
Hello Toshick

Thank you for your reply, you are right, I dont need to send EOS event to
downstream. Which event you can suggest? Maybe GST_EVENT_RECONFIGURE event
could be useful. And is there any function to catch eos event before go to
donwstream ?

I also understood  the problem that I wrote, the reason that I cannot send
the stream is , after EOS event all pipeline stream stops so I have to start
stream with the start stream event. I send the start event to the pad I
blocked in which is decodebin element.  

But I face with another problem, the mpegtsmux still have the same metadata
(about h264enc metadata I think). I realised that output of the ffplay.
ffplay was still trying to solve stream with h264 encoder.

So I also changed the mpegtsmux with the new one at runtime, them problem is
solved. But this way code can be much more complicated if I add more element
after decodebin or mpegtsmux element (maybe I have to change the all
elements after decodebin until the udpsink element).

I dont  know how to reconfigure or inject metadata to mpegtsmux element or
any element. Maybe If I change the metadata of mpegtsmux I dont have to
change any element.

If you know how can I change the metadata of mpegtsmux ( h264 metadata to
h265 metadata ), I searched but I could not find a solution of doing this.
Could you point me to correct way of changing metadata . I would be very
appreciated.

Best Regards,
Mustafa.



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: Change pipeline encoder h264 to h265 at runtime

Toshick
Hello Mustafa.

First of all, I don't think you need to do anything particular with h264 pipeline. Of course, you can lose some number of last frames, but IMHO it is not very critical to the Viewer. So, either send PIPELINE_FLUSH event or do nothing with it at all. Just change the encoder.
Second, about metadata. I haven't the chance to work with mpegtsmux element, but I did the same trick with other elements and notice, that some elements create a separate pad for different GST_CAPS. So, while debugging this, try to put on_pad_added callback to your mpegtsmux element, and check, is it being called while you're pushing different frames to it. If does, try to re-link sink to the new pad.

Best regards,
Anton.

On Wed, Dec 9, 2020 at 12:15 PM MustafaBkrc <[hidden email]> wrote:
Hello Toshick

Thank you for your reply, you are right, I dont need to send EOS event to
downstream. Which event you can suggest? Maybe GST_EVENT_RECONFIGURE event
could be useful. And is there any function to catch eos event before go to
donwstream ?

I also understood  the problem that I wrote, the reason that I cannot send
the stream is , after EOS event all pipeline stream stops so I have to start
stream with the start stream event. I send the start event to the pad I
blocked in which is decodebin element. 

But I face with another problem, the mpegtsmux still have the same metadata
(about h264enc metadata I think). I realised that output of the ffplay.
ffplay was still trying to solve stream with h264 encoder.

So I also changed the mpegtsmux with the new one at runtime, them problem is
solved. But this way code can be much more complicated if I add more element
after decodebin or mpegtsmux element (maybe I have to change the all
elements after decodebin until the udpsink element).

I dont  know how to reconfigure or inject metadata to mpegtsmux element or
any element. Maybe If I change the metadata of mpegtsmux I dont have to
change any element.

If you know how can I change the metadata of mpegtsmux ( h264 metadata to
h265 metadata ), I searched but I could not find a solution of doing this.
Could you point me to correct way of changing metadata . I would be very
appreciated.

Best Regards,
Mustafa.



--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel

_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.freedesktop.org/mailman/listinfo/gstreamer-devel