[gst-devel] Video freeze

lithium cmaster2 at hotmail.com
Mon Jan 10 08:41:34 CET 2011


Well I've been working on debugging this. I've created debug logs of my
program run with --gst-debug-level 5

if i use gst_pad_set_blocked:
the first run of take screenshot causes a 0byte jpeg to be created.
The second time i click screenshot I get the image that was there when
screenshot was clicked the first time written to the jpeg, the video freezes
and the log shows this:
0:00:03.492790081  6199      0x1703f30 LOG    
      GST_SCHEDULING
gstpad.c:1036:gst_pad_set_blocked_async_full:<splitter:src2> blocking
pad
0:00:03.492806842  6199      0x1703f30 LOG    
      GST_SCHEDULING
gstpad.c:1048:gst_pad_set_blocked_async_full:<splitter:src2> waiting
for block
after which point nothing more shows up

if i remove the gst_pad_set_blocked lines:
the first run of take screenshot causes a 0byte jpeg to be created.
The second time i click screenshot I get the image that was there when
screenshot was clicked the first time written to the jpeg, the video does
not freeze, and the log continues having information about everything im
doing written to it.
Further clicks cause the image that was there when the screenshot was
clicked the first time to be re-written to the jpeg file.

In the bus sync handler I check for state paused because for reasons unknown
to me the message i construct telling it to set it to GST_STATE_NULL does
not set it to GST_STATE_NULL but GST_STATE_PAUSED

heres the current functions:

void close_screenshot(GstElement *jpegEncode, videoIOStruct *videoIO)
{
	GstPad *sinkpad = gst_element_get_pad(videoIO->screenshotBin, "sink");
	GstPad *srcpad = gst_pad_get_peer(sinkpad);
	if (!srcpad)
		return; //if we dont have a src pad its already been released need to
check because another jpeg may be encoded before we close the screenshot

	gst_pad_set_blocked(srcpad, TRUE);
	gst_pad_unlink(srcpad, sinkpad);
	gst_pad_set_blocked(srcpad, FALSE);
	gst_element_release_request_pad(videoIO->tee, srcpad);
	gst_object_unref(srcpad);
	gst_object_unref(sinkpad);

	//send a state request back to main thread
	GstMessage *setState =
gst_message_new_request_state(GST_OBJECT(videoIO->screenshotBin),
GST_STATE_NULL);
	GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE(videoIO->pipeline));
	gst_bus_post(bus, setState);
	gst_object_unref(bus);
}

void take_screenshot(GtkWidget *widget, videoIOStruct *videoIO)
{
	gst_element_set_state(videoIO->screenshotBin, GST_STATE_PAUSED);

	gst_bin_add(GST_BIN(videoIO->pipeline), videoIO->screenshotBin);

	GstPad *sinkpad = gst_element_get_pad(videoIO->screenshotBin, "sink");
	GstPad *srcpad = gst_element_get_request_pad(videoIO->tee, "src%d");
	g_print("srcpadref: %d\n", GST_OBJECT_REFCOUNT(GST_OBJECT(srcpad)));
	gst_pad_set_blocked(srcpad, TRUE);
	gst_pad_link(srcpad, sinkpad);
	gst_pad_set_blocked(srcpad, FALSE);
	gst_object_unref(sinkpad);
	gst_element_set_state(videoIO->pipeline, GST_STATE_PLAYING);
}

int setup_screenshotBin(videoIOStruct *videoIO)
{
	videoIO->screenshotBin = gst_bin_new("screenshot_bin");
	GstElement *jpegOutput = gst_element_factory_make("filesink",
"jpegoutput");
	GstElement *jpegQueue = gst_element_factory_make("queue", "jpgqueue");
	GstElement *jpegEncode = gst_element_factory_make("jpegenc",
"jpegencoder");

	if (!jpegOutput || !jpegQueue || !jpegEncode || !videoIO->screenshotBin)
		return 0;

	//set arguments
//	g_object_set(G_OBJECT(jpegOutput), "location", g_strdup("test.jpg"),
NULL); //FIXME: why cant i use set_data???

	//set arguments
	gchar filename[] = "test.jpg";
	g_object_set(G_OBJECT(jpegOutput), "location", filename, NULL);

	//link stuff
	gst_bin_add_many(GST_BIN(videoIO->screenshotBin), jpegQueue, jpegEncode,
jpegOutput, NULL);
	gst_element_link_many(jpegQueue, jpegEncode, jpegOutput, NULL);

	g_signal_connect(jpegEncode, "frame-encoded", G_CALLBACK(close_screenshot),
videoIO);

	GstPad *sinkpad = gst_element_get_static_pad(jpegQueue, "sink");
	gst_element_add_pad(videoIO->screenshotBin, gst_ghost_pad_new("sink",
sinkpad));
	gst_object_unref(GST_OBJECT(sinkpad));

	return 1;
}

int openVideoPipeline(videoIOStruct *videoIO)
{
	/*
						/----queue----xvimagesink //screenoutput
	v4l2src-----tee-----
						\----queue----filesink //screenshot
						\----queue----\
									   ----multiplexer ---filesink //recording
						/----queue----/
	alsasrc-----tee-----
						\----queue----alsasink //playback from capture if needed
	*/

	//create elements
	videoIO->pipeline = gst_pipeline_new("tvVideo");
	videoIO->vidSrc = gst_element_factory_make("v4l2src", "v4lsource");
	GstElement *vidSink = gst_element_factory_make("xvimagesink", "xvsink");
	videoIO->tee = gst_element_factory_make("tee", "splitter");
	GstElement *vidQueue = gst_element_factory_make("queue", "screenQueue");

	if (!videoIO->pipeline || !videoIO->vidSrc || !vidSink || !videoIO->tee ||
!vidQueue)
		return 0;

	//set arguments
	g_object_set(videoIO->vidSrc, "device", videoIO->devName, NULL);

	gst_bin_add_many(GST_BIN(videoIO->pipeline), videoIO->vidSrc, videoIO->tee,
vidQueue, vidSink, NULL);

	GstPad *teeSrc = gst_element_get_request_pad(videoIO->tee, "src%d");
//FIXME: release on program exit
	GstPad *screenQueue = gst_element_get_static_pad(vidQueue, "sink");

	//link stuff
	gst_pad_link(teeSrc, screenQueue);

	gst_object_unref(screenQueue);

	gst_element_link(videoIO->vidSrc, videoIO->tee);

	gst_element_link(vidQueue, vidSink);

	if (!videoIO->pipeline)
		return 0;

	return 1;
}

GstBusSyncReply bus_sync_handler(GstBus *bus, GstMessage *message,
videoIOStruct *videoIO)
{
	if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_ASYNC_DONE)
	{
		GstState state;
		GstState pending;
		gst_element_get_state(videoIO->screenshotBin, &state, &pending, NULL);
		if (state == GST_STATE_PAUSED)
		{
			GstObject *parent = gst_element_get_parent(videoIO->screenshotBin);
			if (parent)
			{
				gst_bin_remove(GST_BIN(videoIO->pipeline), videoIO->screenshotBin);
				gst_object_unref(parent);
			}
		}
	}
	if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
		return GST_BUS_PASS;
	if (!gst_structure_has_name(message->structure, "prepare-xwindow-id"))
		return GST_BUS_PASS;

	if (*videoIO->videoWindowXId != 0)
	{
		GstXOverlay *xOverlay = GST_X_OVERLAY(GST_MESSAGE_SRC(message));
		gst_x_overlay_set_xwindow_id(xOverlay, *videoIO->videoWindowXId);
	}
	else
		g_warning("Should have obtained video_window_xid by now!");

	gst_message_unref(message);
	return GST_BUS_DROP;
}

any ideas?
-- 
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Video-freeze-tp3171570p3206707.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.




More information about the gstreamer-devel mailing list