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