static void gst_imx_blitter_video_sink_close_framebuffer_device(GstImxBlitterVideoSink *blitter_video_sink) { /* must be called with lock held */ g_assert(blitter_video_sink != NULL); if (blitter_video_sink->framebuffer_fd == -1) return; GST_INFO_OBJECT(blitter_video_sink, "closing framebuffer %s with FD %d", blitter_video_sink->framebuffer_name, blitter_video_sink->framebuffer_fd); if (blitter_video_sink->blitter != NULL) { /* switch back to the first page if vsync was used */ if (blitter_video_sink->use_vsync) { GST_DEBUG_OBJECT(blitter_video_sink, "cleaning up page flipping by flipping to page 0"); gst_imx_blitter_video_sink_select_fb_page(blitter_video_sink, 0); gst_imx_blitter_video_sink_flip_to_selected_fb_page(blitter_video_sink); if (blitter_video_sink->original_fb_virt_height != 0) gst_imx_blitter_video_sink_restore_original_fb_config(blitter_video_sink); } gst_imx_blitter_flush(blitter_video_sink->blitter); } gst_buffer_unref(blitter_video_sink->framebuffer); close(blitter_video_sink->framebuffer_fd); blitter_video_sink->framebuffer = NULL; blitter_video_sink->framebuffer_fd = -1; }
static void gst_imx_blitter_dispose(GObject *object) { GstImxBlitter *blitter = GST_IMX_BLITTER(object); gst_imx_blitter_flush(blitter); if (blitter->dma_bufferpool != NULL) { gst_object_unref(GST_OBJECT(blitter->dma_bufferpool)); blitter->dma_bufferpool = NULL; } G_OBJECT_CLASS(gst_imx_blitter_parent_class)->dispose(object); }
static gboolean gst_imx_blitter_video_sink_event(GstBaseSink *sink, GstEvent *event) { GstImxBlitterVideoSink *blitter_video_sink = GST_IMX_BLITTER_VIDEO_SINK(sink); switch (GST_EVENT_TYPE(event)) { case GST_EVENT_FLUSH_STOP: { GST_IMX_BLITTER_VIDEO_SINK_LOCK(blitter_video_sink); if (blitter_video_sink->blitter != NULL) gst_imx_blitter_flush(blitter_video_sink->blitter); GST_IMX_BLITTER_VIDEO_SINK_UNLOCK(blitter_video_sink); break; } default: break; } return GST_BASE_SINK_CLASS(gst_imx_blitter_video_sink_parent_class)->event(sink, event); }
static gboolean gst_imx_blitter_video_transform_sink_event(GstBaseTransform *transform, GstEvent *event) { GstImxBlitterVideoTransform *blitter_video_transform = GST_IMX_BLITTER_VIDEO_TRANSFORM(transform); switch (GST_EVENT_TYPE(event)) { case GST_EVENT_FLUSH_STOP: { GST_IMX_BLITTER_VIDEO_TRANSFORM_LOCK(blitter_video_transform); if (blitter_video_transform->blitter != NULL) gst_imx_blitter_flush(blitter_video_transform->blitter); GST_IMX_BLITTER_VIDEO_TRANSFORM_UNLOCK(blitter_video_transform); break; } default: break; } return GST_BASE_TRANSFORM_CLASS(gst_imx_blitter_video_transform_parent_class)->sink_event(transform, event); }
static GstFlowReturn gst_imx_blitter_video_sink_show_frame(GstVideoSink *video_sink, GstBuffer *buf) { GstImxBlitterVideoSink *blitter_video_sink = GST_IMX_BLITTER_VIDEO_SINK_CAST(video_sink); GstVideoCropMeta *video_crop_meta; GST_IMX_BLITTER_VIDEO_SINK_LOCK(blitter_video_sink); if (blitter_video_sink->input_crop && ((video_crop_meta = gst_buffer_get_video_crop_meta(buf)) != NULL)) { /* Crop metadata present. Reconfigure canvas. */ GstImxRegion source_region; source_region.x1 = video_crop_meta->x; source_region.y1 = video_crop_meta->y; source_region.x2 = video_crop_meta->x + video_crop_meta->width; source_region.y2 = video_crop_meta->y + video_crop_meta->height; /* Make sure the source region does not exceed valid bounds */ source_region.x1 = MAX(0, source_region.x1); source_region.y1 = MAX(0, source_region.y1); source_region.x2 = MIN(GST_VIDEO_INFO_WIDTH(&(blitter_video_sink->input_video_info)), source_region.x2); source_region.y2 = MIN(GST_VIDEO_INFO_HEIGHT(&(blitter_video_sink->input_video_info)), source_region.y2); GST_LOG_OBJECT(blitter_video_sink, "retrieved crop rectangle %" GST_IMX_REGION_FORMAT, GST_IMX_REGION_ARGS(&source_region)); /* Canvas needs to be updated if either one of these applies: * - the current frame has crop metadata, the last one didn't * - the new crop rectangle and the last are different */ if (!(blitter_video_sink->last_frame_with_cropdata) || !gst_imx_region_equal(&source_region, &(blitter_video_sink->last_source_region))) { GST_LOG_OBJECT(blitter_video_sink, "using new crop rectangle %" GST_IMX_REGION_FORMAT, GST_IMX_REGION_ARGS(&source_region)); blitter_video_sink->last_source_region = source_region; blitter_video_sink->canvas_needs_update = TRUE; } blitter_video_sink->last_frame_with_cropdata = TRUE; /* Update canvas and input region if necessary */ if (blitter_video_sink->canvas_needs_update) gst_imx_blitter_video_sink_update_canvas(blitter_video_sink, &(blitter_video_sink->last_source_region)); } else { /* Force an update if this frame has no crop metadata but the last one did */ if (blitter_video_sink->last_frame_with_cropdata) blitter_video_sink->canvas_needs_update = TRUE; blitter_video_sink->last_frame_with_cropdata = FALSE; /* Update canvas and input region if necessary */ if (blitter_video_sink->canvas_needs_update) gst_imx_blitter_video_sink_update_canvas(blitter_video_sink, NULL); } if (blitter_video_sink->canvas.visibility_mask == 0) { /* Visibility mask 0 -> nothing to blit */ GST_IMX_BLITTER_VIDEO_SINK_UNLOCK(blitter_video_sink); return GST_FLOW_OK; } gst_imx_blitter_set_input_frame(blitter_video_sink->blitter, buf); /* If using vsync, blit to the backbuffer, and flip * The flipping is done by scrolling in Y direction * by the same number of rows as there are on screen * The scrolling is implicitely vsync'ed */ if (blitter_video_sink->use_vsync) { /* Select which page to write/blit to */ ++blitter_video_sink->old_fb_page; blitter_video_sink->old_fb_page %= 3; gst_imx_blitter_video_sink_select_fb_page(blitter_video_sink, blitter_video_sink->old_fb_page); /* The actual blitting */ gst_imx_blitter_blit(blitter_video_sink->blitter, 255); /* Flush the blitter to make sure it does not use any cached output * information (for example, the physical address of the previously * selected fb page) */ gst_imx_blitter_flush(blitter_video_sink->blitter); /* Move the current_fb_page index to the next page. See the explanation * at the set_property PROP_USE_VSYNC block for the reason why three * pages are expected instead of 2. */ blitter_video_sink->current_fb_page++; blitter_video_sink->current_fb_page %= 3; /* Flip pages now */ gst_imx_blitter_video_sink_flip_to_selected_fb_page(blitter_video_sink); } else { gst_imx_blitter_blit(blitter_video_sink->blitter, 255); } GST_IMX_BLITTER_VIDEO_SINK_UNLOCK(blitter_video_sink); return GST_FLOW_OK; }