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); }
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; }
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; }