Exemplo n.º 1
0
static void gst_imx_ipu_blitter_init_dummy_black_buffer(GstImxIpuBlitter *ipu_blitter)
{
	GstVideoInfo video_info;

	gst_video_info_init(&video_info);
	gst_video_info_set_format(&video_info, GST_VIDEO_FORMAT_RGBx, 64, 64);

	ipu_blitter->dummy_black_buffer = gst_buffer_new_allocate(ipu_blitter->allocator, GST_VIDEO_INFO_SIZE(&video_info), NULL);
	gst_buffer_memset(ipu_blitter->dummy_black_buffer, 0, 0, GST_VIDEO_INFO_SIZE(&video_info));

	gst_buffer_add_video_meta_full(
		ipu_blitter->dummy_black_buffer,
		GST_VIDEO_FRAME_FLAG_NONE,
		GST_VIDEO_INFO_FORMAT(&video_info),
		GST_VIDEO_INFO_WIDTH(&video_info),
		GST_VIDEO_INFO_HEIGHT(&video_info),
		GST_VIDEO_INFO_N_PLANES(&video_info),
		&(GST_VIDEO_INFO_PLANE_OFFSET(&video_info, 0)),
		&(GST_VIDEO_INFO_PLANE_STRIDE(&video_info, 0))
	);

	{
		GstImxPhysMemory *imx_phys_mem_mem = (GstImxPhysMemory *)gst_buffer_peek_memory(ipu_blitter->dummy_black_buffer, 0);
		GstImxPhysMemMeta *phys_mem_meta = (GstImxPhysMemMeta *)GST_IMX_PHYS_MEM_META_ADD(ipu_blitter->dummy_black_buffer);

		phys_mem_meta->phys_addr = imx_phys_mem_mem->phys_addr;
	}
}
Exemplo n.º 2
0
/* The produced buffer contains only metadata, no memory blocks - the IPU sink does not need anything more
 * TODO: add some logic to wrap the framebuffer memory block, including map/unmap code etc. */
GstBuffer* gst_imx_ipu_blitter_wrap_framebuffer(GstImxIpuBlitter *ipu_blitter, int framebuffer_fd, guint x, guint y, guint width, guint height)
{
	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;

	if (ioctl(framebuffer_fd, FBIOGET_FSCREENINFO, &fb_fix) == -1)
	{
		GST_ERROR_OBJECT(ipu_blitter, "could not open get fixed screen info: %s", strerror(errno));
		return NULL;
	}

	if (ioctl(framebuffer_fd, FBIOGET_VSCREENINFO, &fb_var) == -1)
	{
		GST_ERROR_OBJECT(ipu_blitter, "could not open get variable screen info: %s", strerror(errno));
		return NULL;
	}

	fb_width = fb_var.xres;
	fb_height = fb_var.yres;
	fb_format = gst_imx_ipu_blitter_get_format_from_fb(ipu_blitter, &fb_var, &fb_fix);

	GST_DEBUG_OBJECT(ipu_blitter, "framebuffer resolution is %u x %u", fb_width, fb_height);

	buffer = gst_buffer_new();
	gst_buffer_add_video_meta(buffer, GST_VIDEO_FRAME_FLAG_NONE, fb_format, fb_width, fb_height);

	if ((width != 0) && (height != 0))
	{
		GstVideoCropMeta *video_crop_meta;
		
		video_crop_meta = gst_buffer_add_video_crop_meta(buffer);
		video_crop_meta->x = x;
		video_crop_meta->y = y;
		video_crop_meta->width = width;
		video_crop_meta->height = height;
	}

	phys_mem_meta = GST_IMX_PHYS_MEM_META_ADD(buffer);
	phys_mem_meta->phys_addr = (guintptr)(fb_fix.smem_start);

	return buffer;
}
Exemplo n.º 3
0
static GstFlowReturn gst_imx_v4l2_buffer_pool_alloc_buffer(GstBufferPool *bpool, GstBuffer **buffer, G_GNUC_UNUSED GstBufferPoolAcquireParams *params)
{
	GstImxV4l2BufferPool *pool = GST_IMX_V4L2_BUFFER_POOL(bpool);
	GstBuffer *buf;
	GstImxV4l2Meta *meta;
	GstImxPhysMemMeta *phys_mem_meta;
	GstVideoInfo *info;

	buf = gst_buffer_new();
	if (buf == NULL)
	{
		GST_ERROR_OBJECT(pool, "could not create new buffer");
		return GST_FLOW_ERROR;
	}

	GST_DEBUG_OBJECT(pool, "alloc %u %p", pool->num_allocated, (gpointer)buf);

	meta = GST_IMX_V4L2_META_ADD(buf);
	meta->vbuffer.index = pool->num_allocated;
	meta->vbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	meta->vbuffer.memory = V4L2_MEMORY_MMAP;

	if (ioctl(GST_IMX_FD_OBJECT_GET_FD(pool->fd_obj_v4l), VIDIOC_QUERYBUF, &meta->vbuffer) < 0)
	{
		GST_ERROR_OBJECT(pool, "VIDIOC_QUERYBUF error: %s",
				g_strerror(errno));
		gst_buffer_unref(buf);
		return GST_FLOW_ERROR;
	}

	meta->mem = mmap(NULL, meta->vbuffer.length,
			PROT_READ | PROT_WRITE, MAP_SHARED, GST_IMX_FD_OBJECT_GET_FD(pool->fd_obj_v4l),
			meta->vbuffer.m.offset);
	g_assert(meta->mem);

	/* Need to query twice to get the physical address */
	if (ioctl(GST_IMX_FD_OBJECT_GET_FD(pool->fd_obj_v4l), VIDIOC_QUERYBUF, &meta->vbuffer) < 0)
	{
		GST_ERROR_OBJECT(pool, "VIDIOC_QUERYBUF for physical address error: %s",
				g_strerror(errno));
		gst_buffer_unref(buf);
		return GST_FLOW_ERROR;
	}

	phys_mem_meta = GST_IMX_PHYS_MEM_META_ADD(buf);
	phys_mem_meta->phys_addr = meta->vbuffer.m.offset;

	/* Safeguard to catch data loss if in any future i.MX version the types do not match */
	g_assert(meta->vbuffer.m.offset == (__u32)(phys_mem_meta->phys_addr));

	if (pool->add_videometa)
	{
		info = &pool->video_info;

		gst_buffer_add_video_meta_full(
				buf,
				GST_VIDEO_FRAME_FLAG_NONE,
				GST_VIDEO_INFO_FORMAT(info),
				GST_VIDEO_INFO_WIDTH(info),
				GST_VIDEO_INFO_HEIGHT(info),
				GST_VIDEO_INFO_N_PLANES(info),
				info->offset,
				info->stride
				);
	}

#ifdef HAVE_VIV_UPLOAD
	if (pool->add_vivuploadmeta)
	{
		gst_imx_buffer_add_vivante_gl_texture_upload_meta(buf);
	}
#endif

	pool->num_allocated++;

	*buffer = buf;

	return GST_FLOW_OK;
}
Exemplo n.º 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;
}