static GstFlowReturn gst_imx_blitter_video_transform_transform_frame(GstBaseTransform *transform, GstBuffer *in, GstBuffer *out) { gboolean ret = TRUE; GstImxBlitterVideoTransform *blitter_video_transform = GST_IMX_BLITTER_VIDEO_TRANSFORM(transform); g_assert(blitter_video_transform->blitter != NULL); if (!blitter_video_transform->inout_info_set) { GST_ELEMENT_ERROR(transform, CORE, NOT_IMPLEMENTED, (NULL), ("unknown format")); return GST_FLOW_NOT_NEGOTIATED; } if (in == out) { GST_LOG_OBJECT(transform, "passing buffer through"); return GST_FLOW_OK; } GST_IMX_BLITTER_VIDEO_TRANSFORM_LOCK(blitter_video_transform); ret = ret && gst_imx_blitter_set_input_frame(blitter_video_transform->blitter, in); ret = ret && gst_imx_blitter_set_output_frame(blitter_video_transform->blitter, out); ret = ret && gst_imx_blitter_blit(blitter_video_transform->blitter, 255); ret = ret && gst_imx_blitter_set_output_frame(blitter_video_transform->blitter, NULL); GST_IMX_BLITTER_VIDEO_TRANSFORM_UNLOCK(blitter_video_transform); return ret ? GST_FLOW_OK : GST_FLOW_ERROR; }
gboolean gst_imx_blitter_compositor_set_output_frame(GstImxCompositor *compositor, GstBuffer *output_frame) { GstImxBlitterCompositor *blitter_compositor = GST_IMX_BLITTER_COMPOSITOR(compositor); g_assert(blitter_compositor->blitter != NULL); return gst_imx_blitter_set_output_frame(blitter_compositor->blitter, output_frame); }
static gboolean gst_imx_blitter_video_sink_select_fb_page(GstImxBlitterVideoSink *blitter_video_sink, guint page) { GstImxPhysMemMeta *phys_mem_meta = GST_IMX_PHYS_MEM_META_GET(blitter_video_sink->framebuffer); guint height = GST_VIDEO_INFO_HEIGHT(&(blitter_video_sink->output_video_info)); guint page_size = GST_VIDEO_INFO_PLANE_STRIDE(&(blitter_video_sink->output_video_info), 0) * height; if (blitter_video_sink->framebuffer_fd == -1) return FALSE; GST_LOG_OBJECT(blitter_video_sink, "switching to page %u", page); phys_mem_meta->phys_addr = (gst_imx_phys_addr_t)(blitter_video_sink->fb_fix.smem_start) + page_size * page; blitter_video_sink->fb_var.yoffset = height * page; return gst_imx_blitter_set_output_frame(blitter_video_sink->blitter, blitter_video_sink->framebuffer); }
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; }
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; }