对gstreamer官方教程中的基于appsink的视频帧采样代码进行了重新封装,以达到通过GTK的button事件直接调用封装进行视频截图。注意设置好主pipeline中的节点tee与封装中的tee_main进行同步。参考代码如下:appdata.mediaData.tee_main = data.tee_main;
typedef struct _MediaData
{
GstElement *pipeline;
GstElement *tee_main ;
GstElement *capsfilter_cap, *videoconvert_cap, *capture_queue,*file_sink_capture;
GstCaps *filter_caps_cap;
GstPad *queue_capture_pad, *tee_capture_pad;
} MediaData;
typedef struct _AppData
{
GstElement *pipeline_app;
GstElement *video_sink;
MediaData mediaData;
} AppData;
static int image_cap_cb (GtkEventBox *e, CustomData * data)
{
static int screenshot_time = 1;
GstSample *sample;
MediaData* imageData = &appdata.mediaData;
GstPadTemplate *templ;
templ = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (imageData->tee_main), "src_%u");
imageData->tee_capture_pad = gst_element_request_pad (imageData->tee_main, templ, NULL, NULL);
if ( 1 )
{
imageData->capture_queue = gst_element_factory_make ("queue", "record_queue");
imageData->videoconvert_cap = gst_element_factory_make ("videoconvert", "videoconvert_cap");
imageData->capsfilter_cap = gst_element_factory_make ("capsfilter", "capsfilter_cap");
imageData->file_sink_capture = gst_element_factory_make ("appsink", "file_sink_capture");
g_object_set (imageData->file_sink_capture, "emit-signals", TRUE, NULL);
/* set the resolution */
char resolution_cap[200];
sprintf(resolution_cap, "video/x-raw,format=RGBA, pixel-aspect-ratio=1/1");
g_printerr("%s\n",resolution_cap);
imageData->filter_caps_cap = gst_caps_from_string (resolution_cap);
g_object_set(GST_OBJECT( imageData->capsfilter_cap), "caps", imageData->filter_caps_cap, NULL);
gst_caps_unref ( imageData->filter_caps_cap);
char filename_png[1000];
sprintf(filename_png, "/home/123/screeshot%d.jpg", screenshot_time);
screenshot_time++;
gst_bin_add_many (GST_BIN (imageData->pipeline), imageData->capture_queue,imageData->videoconvert_cap, imageData->capsfilter_cap, imageData->file_sink_capture,NULL);
if (gst_element_link_many (imageData->capture_queue, imageData->videoconvert_cap, imageData->capsfilter_cap, imageData->file_sink_capture, NULL) != TRUE)
{
g_printerr ("Elements could not be linked in record branch\n");
}
gst_element_sync_state_with_parent (imageData->capture_queue);
gst_element_sync_state_with_parent (imageData->videoconvert_cap);
gst_element_sync_state_with_parent (imageData->capsfilter_cap);
gst_element_sync_state_with_parent (imageData->file_sink_capture);
imageData->queue_capture_pad = gst_element_get_static_pad (imageData->capture_queue, "sink");
if(gst_pad_link (imageData->tee_capture_pad, imageData->queue_capture_pad) != GST_PAD_LINK_OK)
{
g_printerr ("Elements could not be linked in record branch\n");
}
if (sample)
{
GstBuffer *buffer;
GstPad *pad;
GstStructure *s;
gint width, height;
GstPadTemplate *template;
g_signal_emit_by_name (imageData->file_sink_capture, "pull-preroll", &sample, NULL);
GstCaps *videosink_caps = gst_sample_get_caps (sample);
s = gst_caps_get_structure (videosink_caps, 0);
gboolean res;
res = gst_structure_get_int (s, "width", &width);
res |= gst_structure_get_int (s, "height", &height);
GstMapInfo map;
GError *error = NULL;
buffer = gst_sample_get_buffer (sample);
gst_buffer_map (buffer, &map, GST_MAP_READ);
g_printerr("width :%d, height :%d \n", width, height);
pixbuf = gdk_pixbuf_new_from_data (map.data, GDK_COLORSPACE_RGB, TRUE, 8, width, height, GST_ROUND_UP_4 (width*4), NULL, NULL);
gdk_pixbuf_save (pixbuf, filename_png, "jpeg", &error,NULL);
gst_buffer_unmap (buffer, &map);
}
usleep(100*1000);
gst_element_set_state (imageData->file_sink_capture, GST_STATE_NULL);
gst_element_set_state (imageData->videoconvert_cap, GST_STATE_NULL);
gst_element_set_state (imageData->capture_queue, GST_STATE_NULL);
gst_element_set_state (imageData->capsfilter_cap, GST_STATE_NULL);
imageData->queue_capture_pad = gst_element_get_static_pad (imageData->capture_queue, "sink");
if(gst_pad_unlink(imageData->tee_capture_pad, imageData->queue_capture_pad) != TRUE)
{
g_printerr ("Tee record queue could not be unlinked.\n");
}
gst_bin_remove(GST_BIN (imageData->pipeline), imageData->capture_queue);
gst_bin_remove(GST_BIN (imageData->pipeline), imageData->videoconvert_cap);
gst_bin_remove(GST_BIN (imageData->pipeline), imageData->file_sink_capture);
gst_bin_remove(GST_BIN (imageData->pipeline), imageData->capsfilter_cap);
gst_element_release_request_pad (imageData->tee_main, imageData->tee_capture_pad);
gst_object_unref (imageData->queue_capture_pad);
gst_object_unref (imageData->tee_capture_pad);
g_printerr("TRUE \n");
}
return 1;
}