Reading streaming video frame by frame

isak3t isak3t at gmail.com
Thu Nov 26 11:32:30 UTC 2020


Hello Omer,

Thank you so much for the help. I was finally able to get things working.
Will now implement in actual application and evaluate performance.

Also I found the code to read frame data from the following link :  Click
Here
<https://stackoverflow.com/questions/60512213/how-to-process-frames-from-video-received-from-a-file>  

------------Below this only for reference of anybody who might require this
later--------------------

The code for reading a video data frame by frame is as follows

    #include <gst/gst.h>
    #include <string.h>
    #include <stdio.h>

    typedef struct _CustomData {
      GstElement *pipeline,*sink;
      GstBus *bus;
      GstMessage *msg;
      GMainLoop *loop;
      gboolean is_live;
    } CustomData;

    static void cb_message (GstBus *bus, GstMessage *msg, CustomData *data)
{
          switch (GST_MESSAGE_TYPE (msg)) {
            case GST_MESSAGE_ERROR: {
              GError *err;
              gchar *debug;
              gst_message_parse_error (msg, &err, &debug);
              g_print ("Error: %s\n", err->message);
              g_error_free (err);
              g_free (debug);
              gst_element_set_state (data->pipeline, GST_STATE_READY);
              g_main_loop_quit (data->loop);
              break;
            }
            case GST_MESSAGE_EOS:
              /* end-of-stream */
              gst_element_set_state (data->pipeline, GST_STATE_READY);
              g_main_loop_quit (data->loop);
              break;
            case GST_MESSAGE_BUFFERING: {
              gint percent = 0;
              /* If the stream is live, we do not care about buffering. */
              if (data->is_live) break;
              gst_message_parse_buffering (msg, &percent);
              g_print ("Buffering (%3d%%)\n", percent);
              /* Wait until buffering is complete before start/resume
playing */
              if (percent < 100)
                gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
              else
                gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
              break;
            }
            case GST_MESSAGE_CLOCK_LOST:
              /* Get a new clock */
              gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
              gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
              break;
            default:
              g_print ("Unknown message over bus\n");
              /* Unhandled message */
              break;
        }
    }

    static GstFlowReturn frame_func (GstElement *sink, CustomData *data){
      GstSample *sample;
      g_signal_emit_by_name(sink,"pull_sample",&sample);
      if(sample){
          GstBuffer *buf=gst_sample_get_buffer(sample);         
          GstMapInfo map;
          gboolean mapping_succ=gst_buffer_map(buf, &map, GST_MAP_READ);
          if(mapping_succ){
              int width=160;
            int height=240;
              int loc=(width*3*height/2)+(width*3/2)-1; //selecting mid
point of video
              printf("%hhx %hhx
%hhx\n",map.data[loc],map.data[loc+1],map.data[loc+2]);         
              gst_buffer_unmap(buf,&map);
          }
          else
              printf("failure in mapping\n");
        gst_sample_unref(sample);
        return GST_FLOW_OK;
      }
      else
          printf("error in sample\n");         
    return GST_FLOW_ERROR;
    }

    int main(int argc, char *argv[]) {
      GstStateChangeReturn ret;
      CustomData data;
      gst_init (&argc, &argv);
      memset (&data, 0, sizeof (data));

      //replace videotestsrc with "uridecodebin uri=path to video" for
actual test
      data.pipeline = gst_parse_launch ("videotestsrc ! videoconvert !
appsink name=video-sink
caps=\"video/x-raw,format=RGB,pixel-aspect-ratio=1/1\"", NULL);
      data.sink=gst_bin_get_by_name(GST_BIN(data.pipeline),"video-sink");
      ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
      if (ret == GST_STATE_CHANGE_FAILURE)  {
        g_printerr ("Unable to set the pipeline to the playing state.\n");
        gst_object_unref (data.pipeline);
        return -1;
      } else{
         if (ret == GST_STATE_CHANGE_NO_PREROLL)
          printf("for live sources, state changed but data could not be
produced\n");
        else if (ret == GST_STATE_CHANGE_ASYNC)
          printf("state will change async\n");
        else if (ret == GST_STATE_CHANGE_SUCCESS)
          printf("successfully played\n");
        else
          printf("unknown %d\n",ret);
        data.is_live=TRUE;
      }
      data.bus = gst_element_get_bus (data.pipeline);
      g_object_set(G_OBJECT(data.sink),"emit-signals",TRUE,NULL);
      g_signal_connect (data.sink, "new-sample", G_CALLBACK(frame_func),
&data);
      gst_bus_add_signal_watch (data.bus);
        g_signal_connect (data.bus, "message", G_CALLBACK (cb_message),
&data);     
     
      data.loop = g_main_loop_new (NULL, FALSE);       
      g_main_loop_run (data.loop);
      g_main_loop_unref (data.loop);
      gst_object_unref (data.bus);
      gst_element_set_state (data.pipeline, GST_STATE_NULL);
      gst_object_unref (data.pipeline);
      return 0;
    }

I compiled using following command. You can modify accordingly as per your
environment path

.\gcc.exe code.c -I "D:\gstreamer\1.0\x86\include\gdk-pixbuf-2.0\" -I
"D:\gstreamer\1.0\x86\include\gstreamer-1.0\gst\app\" -I
"D:\gstreamer\1.0\x86\include\gstreamer-1.0\" -I
"D:\gstreamer\1.0\x86\include\glib-2.0\" -I
"D:\gstreamer\1.0\x86\lib\glib-2.0\include\" -L "D:\gstreamer\1.0\x86\bin\"
-L "D:\gstreamer\1.0\x86\lib" -l glib-2.0-0 -l gstreamer-1.0-0 -l
gobject-2.0-0 -l gthread-2.0-0  -l gdk_pixbuf-2.0-0 -l gstapp-1.0 -o
"D:\test.exe"





--
Sent from: http://gstreamer-devel.966125.n4.nabble.com/


More information about the gstreamer-devel mailing list