示例#1
0
gboolean gst_imx_blitter_compositor_set_output_video_info(GstImxCompositor *compositor, GstVideoInfo const *info)
{
	GstImxBlitterCompositor *blitter_compositor = GST_IMX_BLITTER_COMPOSITOR(compositor);
	g_assert(blitter_compositor->blitter != NULL);

	return gst_imx_blitter_set_output_video_info(blitter_compositor->blitter, info);
}
示例#2
0
static gboolean gst_imx_blitter_video_transform_set_caps(GstBaseTransform *transform, GstCaps *in, GstCaps *out)
{
	gboolean inout_info_equal;
	GstVideoInfo in_info, out_info;
	GstImxBlitterVideoTransform *blitter_video_transform = GST_IMX_BLITTER_VIDEO_TRANSFORM(transform);
	GstImxBlitterVideoTransformClass *klass = GST_IMX_BLITTER_VIDEO_TRANSFORM_CLASS(G_OBJECT_GET_CLASS(transform));
	GstImxCanvas *canvas = &(blitter_video_transform->canvas);
	GstImxRegion source_subset;

	g_assert(klass->are_video_infos_equal != NULL);
	g_assert(blitter_video_transform->blitter != NULL);

	if (!gst_video_info_from_caps(&in_info, in) || !gst_video_info_from_caps(&out_info, out))
	{
		GST_ERROR_OBJECT(transform, "caps are invalid");
		blitter_video_transform->inout_info_set = FALSE;
		return FALSE;
	}

	inout_info_equal = klass->are_video_infos_equal(blitter_video_transform, &in_info, &out_info);

	if (inout_info_equal)
		GST_DEBUG_OBJECT(transform, "input and output caps are equal");
	else
		GST_DEBUG_OBJECT(transform, "input and output caps are not equal:  input: %" GST_PTR_FORMAT "  output: %" GST_PTR_FORMAT, (gpointer)in, (gpointer)out);

	gst_imx_blitter_set_input_video_info(blitter_video_transform->blitter, &in_info);
	gst_imx_blitter_set_output_video_info(blitter_video_transform->blitter, &out_info);

	/* setting new caps changes the canvas, so recalculate it
	 * the recalculation here is done without any input cropping, so set
	 * last_frame_with_cropdata to FALSE, in case subsequent frames do
	 * contain crop metadata */

	blitter_video_transform->last_frame_with_cropdata = FALSE;

	/* the canvas always encompasses the entire output frame */
	canvas->outer_region.x1 = 0;
	canvas->outer_region.y1 = 0;
	canvas->outer_region.x2 = GST_VIDEO_INFO_WIDTH(&out_info);
	canvas->outer_region.y2 = GST_VIDEO_INFO_HEIGHT(&out_info);

	gst_imx_canvas_calculate_inner_region(canvas, &in_info);
	gst_imx_canvas_clip(canvas, &(canvas->outer_region), &in_info, NULL, &source_subset);

	gst_imx_blitter_set_input_region(blitter_video_transform->blitter, &source_subset);
	gst_imx_blitter_set_output_canvas(blitter_video_transform->blitter, canvas);

	blitter_video_transform->input_video_info = in_info;
	blitter_video_transform->output_video_info = out_info;
	blitter_video_transform->inout_info_equal = inout_info_equal;
	blitter_video_transform->inout_info_set = TRUE;

	return TRUE;
}
示例#3
0
static gboolean gst_imx_blitter_video_sink_acquire_blitter(GstImxBlitterVideoSink *blitter_video_sink)
{
	/* must be called with lock held */

	GstImxBlitterVideoSinkClass *klass = GST_IMX_BLITTER_VIDEO_SINK_CLASS(G_OBJECT_GET_CLASS(blitter_video_sink));

	g_assert(blitter_video_sink != NULL);
	g_assert(blitter_video_sink->framebuffer != NULL);
	g_assert(klass->create_blitter != NULL);

	/* Do nothing if the blitter is already acquired */
	if (blitter_video_sink->blitter != NULL)
		return TRUE;

	if ((blitter_video_sink->blitter = klass->create_blitter(blitter_video_sink)) == NULL)
	{
		GST_ERROR_OBJECT(blitter_video_sink, "could not acquire blitter");
		return FALSE;
	}

	if (!gst_imx_blitter_set_output_frame(blitter_video_sink->blitter, blitter_video_sink->framebuffer))
	{
		GST_ERROR_OBJECT(blitter_video_sink, "could not set the output frame");
		return FALSE;
	}

	if (!gst_imx_blitter_set_output_canvas(blitter_video_sink->blitter, &(blitter_video_sink->canvas)))
	{
		GST_ERROR_OBJECT(blitter_video_sink, "could not set the output canvas");
		return FALSE;
	}

	if (!gst_imx_blitter_set_output_video_info(blitter_video_sink->blitter, &(blitter_video_sink->output_video_info)))
	{
		GST_ERROR_OBJECT(blitter_video_sink, "could not set the output video info");
		return FALSE;
	}

	if (!gst_imx_blitter_set_num_output_pages(blitter_video_sink->blitter, blitter_video_sink->use_vsync ? 3 : 1))
	{
		GST_ERROR_OBJECT(blitter_video_sink, "could not set the number of output pages");
		return FALSE;
	}

	return TRUE;
}
示例#4
0
static gboolean gst_imx_blitter_video_sink_open_framebuffer_device(GstImxBlitterVideoSink *blitter_video_sink)
{
	/* must be called with lock held */

	gboolean ret = TRUE;
	int fd;
	guint fb_width, fb_height;
	GstVideoFormat fb_format;
	GstBuffer *buffer;
	GstImxPhysMemMeta *phys_mem_meta;
	struct fb_var_screeninfo fb_var;
	struct fb_fix_screeninfo fb_fix;

	g_assert(blitter_video_sink != NULL);
	g_assert(blitter_video_sink->framebuffer_name != NULL);


	/* Close any currently open framebuffer first */
	if (blitter_video_sink->framebuffer_fd != -1)
		gst_imx_blitter_video_sink_close_framebuffer_device(blitter_video_sink);

	GST_INFO_OBJECT(blitter_video_sink, "opening framebuffer %s", blitter_video_sink->framebuffer_name);


	/* Open framebuffer and get its variable and fixed information */

	fd = open(blitter_video_sink->framebuffer_name, O_RDWR, 0);
	if (fd < 0)
	{
		GST_ELEMENT_ERROR(blitter_video_sink, RESOURCE, OPEN_READ_WRITE, ("could not open %s: %s", blitter_video_sink->framebuffer_name, strerror(errno)), (NULL));
		return FALSE;
	}

	if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix) == -1)
	{
		close(fd);
		GST_ERROR_OBJECT(blitter_video_sink, "could not get fixed screen info: %s", strerror(errno));
		return FALSE;
	}

	if (ioctl(fd, FBIOGET_VSCREENINFO, &fb_var) == -1)
	{
		close(fd);
		GST_ERROR_OBJECT(blitter_video_sink, "could not get variable screen info: %s", strerror(errno));
		return FALSE;
	}


	/* Copy FD, variable and fixed screen information structs
	 * These are also needed during the vsync setup below*/
	blitter_video_sink->framebuffer_fd = fd;
	blitter_video_sink->fb_var = fb_var;
	blitter_video_sink->fb_fix = fb_fix;


	/* Set up vsync (vsync is done via page flipping) */
	if (blitter_video_sink->use_vsync)
	{
		/* Check how many pages can currently be used. If this number is
		 * less than 3, reconfigure the framebuffer to allow for 3 pages.
		 * See the explanation at the set_property PROP_USE_VSYNC block
		 * for the reason why three pages are expected instead of 2. */

		guint cur_num_pages = fb_var.yres_virtual / fb_var.yres;
		if (cur_num_pages < 3)
		{
			GST_INFO_OBJECT(
				blitter_video_sink,
				"framebuffer configuration:  resolution is %u x %u , virtual %u x %u => need to reconfigure virtual height",
				fb_var.xres, fb_var.yres,
				fb_var.xres_virtual, fb_var.yres_virtual
			);
			if (!gst_imx_blitter_video_sink_reconfigure_fb(blitter_video_sink, 3))
			{
				GST_ERROR_OBJECT(blitter_video_sink, "could not reconfigure framebuffer");
				close(fd);
				blitter_video_sink->framebuffer_fd = -1;
				return FALSE;
			}
		}
		else
		{
			GST_INFO_OBJECT(
				blitter_video_sink,
				"framebuffer configuration:  resolution is %u x %u , virtual %u x %u => don't need to reconfigure virtual height",
				fb_var.xres, fb_var.yres,
				fb_var.xres_virtual, fb_var.yres_virtual
			);
		}

		/* Fetch fixed screen info again in case it changed after the FB reconfiguration */
		if (ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix) == -1)
		{
			GST_ERROR_OBJECT(blitter_video_sink, "could not open get fixed screen info: %s", strerror(errno));
			close(fd);
			blitter_video_sink->framebuffer_fd = -1;
			return FALSE;
		}

		/* Update the fixed screen info copy */
		blitter_video_sink->fb_fix = fb_fix;
	}


	/* Get width, height, format for framebuffer */
	fb_width = fb_var.xres;
	fb_height = fb_var.yres;
	fb_format = gst_imx_blitter_video_sink_get_format_from_fb(blitter_video_sink, &fb_var, &fb_fix);
	if (fb_format == GST_VIDEO_FORMAT_UNKNOWN)
	{
		GST_ELEMENT_ERROR(blitter_video_sink, RESOURCE, OPEN_READ_WRITE, ("framebuffer has unknown format"), (NULL));
		return FALSE;
	}


	/* Construct framebuffer and add meta to it
	 * Note: not adding any GstMemory blocks, since none are needed */
	buffer = gst_buffer_new();
	gst_buffer_add_video_meta(buffer, GST_VIDEO_FRAME_FLAG_NONE, fb_format, fb_width, fb_height);
	phys_mem_meta = GST_IMX_PHYS_MEM_META_ADD(buffer);
	phys_mem_meta->phys_addr = (gst_imx_phys_addr_t)(fb_fix.smem_start);


	/* Set up framebuffer related information */
	blitter_video_sink->framebuffer = buffer;
	blitter_video_sink->framebuffer_fd = fd;
	blitter_video_sink->framebuffer_region.x1 = 0;
	blitter_video_sink->framebuffer_region.y1 = 0;
	blitter_video_sink->framebuffer_region.x2 = fb_width;
	blitter_video_sink->framebuffer_region.y2 = fb_height;
	GST_INFO_OBJECT(blitter_video_sink, "framebuffer FD is %d", blitter_video_sink->framebuffer_fd);


	/* Create videoinfo structure for the framebuffer */
	gst_video_info_set_format(&(blitter_video_sink->output_video_info), fb_format, fb_width, fb_height);


	/* New framebuffer means the canvas most likely changed -> update */
	blitter_video_sink->canvas_needs_update = TRUE;


	/* If a blitter is present, set its output video info
	 * and output frame, since these two items changed */
	if (blitter_video_sink->blitter != NULL)
	{
		ret = ret && gst_imx_blitter_set_output_video_info(blitter_video_sink->blitter, &(blitter_video_sink->output_video_info));
		ret = ret && gst_imx_blitter_set_output_frame(blitter_video_sink->blitter, blitter_video_sink->framebuffer);
		ret = ret && gst_imx_blitter_set_num_output_pages(blitter_video_sink->blitter, blitter_video_sink->use_vsync ? 3 : 1);
	}

	if (!ret)
	{
		close(fd);
		blitter_video_sink->framebuffer_fd = -1;
	}

	return ret;
}