static gboolean gst_imx_ipu_blitter_fill_region(GstImxBlitter *blitter, GstImxRegion const *region, guint32 color) { GstImxIpuBlitter *ipu_blitter = GST_IMX_IPU_BLITTER(blitter); struct ipu_task *task = &(ipu_blitter->priv->fill_task); int ioctl_ret; task->output.rotate = IPU_ROTATE_NONE; task->output.crop.pos.x = region->x1; task->output.crop.pos.y = region->y1; task->output.crop.w = region->x2 - region->x1; task->output.crop.h = region->y2 - region->y1; GST_LOG_OBJECT( ipu_blitter, "fill op task input: width: %u height: %u format: 0x%x crop: %u,%u %ux%u phys addr %" GST_IMX_PHYS_ADDR_FORMAT " deinterlace enable %u motion 0x%x", task->input.width, task->input.height, task->input.format, task->input.crop.pos.x, task->input.crop.pos.y, task->input.crop.w, task->input.crop.h, (gst_imx_phys_addr_t)(task->input.paddr), task->input.deinterlace.enable, task->input.deinterlace.motion ); GST_LOG_OBJECT( ipu_blitter, "fill op task output: width: %u height: %u format: 0x%x crop: %u,%u %ux%u paddr %" GST_IMX_PHYS_ADDR_FORMAT " rotate: %u", task->output.width, task->output.height, task->output.format, task->output.crop.pos.x, task->output.crop.pos.y, task->output.crop.w, task->output.crop.h, (gst_imx_phys_addr_t)(task->output.paddr), task->output.rotate ); { GstMapInfo map_info; guint32 *pixels, *pixels_end; guint32 opaque_color = color | 0xFF000000; gst_buffer_map(ipu_blitter->fill_frame, &map_info, GST_MAP_WRITE); pixels = (guint32 *)(map_info.data); pixels_end = pixels + fill_frame_width * fill_frame_height; for (; pixels < pixels_end; ++pixels) *pixels = opaque_color; gst_buffer_unmap(ipu_blitter->fill_frame, &map_info); } if ((ioctl_ret = ioctl(gst_imx_ipu_get_fd(), IPU_QUEUE_TASK, task)) == -1) { GST_ERROR_OBJECT(ipu_blitter, "queuing IPU task failed: %s", strerror(errno)); return FALSE; } return TRUE; }
static gboolean gst_imx_ipu_blitter_blit(GstImxBlitter *blitter, guint8 alpha) { gboolean ret = TRUE; GstImxIpuBlitter *ipu_blitter = GST_IMX_IPU_BLITTER(blitter); if (ipu_blitter->clipped_outer_region_updated) { GST_DEBUG_OBJECT(ipu_blitter, "cleared page %u of %u", ipu_blitter->num_cleared_output_pages, ipu_blitter->num_output_pages); if (!gst_imx_ipu_blitter_fill_region(blitter, &(ipu_blitter->clipped_outer_region), ipu_blitter->fill_color | 0xFF000000)) return FALSE; ipu_blitter->num_cleared_output_pages++; if (ipu_blitter->num_cleared_output_pages >= ipu_blitter->num_output_pages) ipu_blitter->clipped_outer_region_updated = FALSE; } if (ret && (ipu_blitter->visibility_mask & GST_IMX_CANVAS_VISIBILITY_FLAG_REGION_INNER)) { char fourcc[5]; int ioctl_ret; gst_imx_ipu_blitter_print_ipu_fourcc(ipu_blitter->priv->main_task.input.format, fourcc); GST_LOG_OBJECT( ipu_blitter, "main_task input: width: %u height: %u format: 0x%x (%s) crop: %u,%u %ux%u phys addr %" GST_IMX_PHYS_ADDR_FORMAT " deinterlace enable %u motion 0x%x", ipu_blitter->priv->main_task.input.width, ipu_blitter->priv->main_task.input.height, ipu_blitter->priv->main_task.input.format, fourcc, ipu_blitter->priv->main_task.input.crop.pos.x, ipu_blitter->priv->main_task.input.crop.pos.y, ipu_blitter->priv->main_task.input.crop.w, ipu_blitter->priv->main_task.input.crop.h, (gst_imx_phys_addr_t)(ipu_blitter->priv->main_task.input.paddr), ipu_blitter->priv->main_task.input.deinterlace.enable, ipu_blitter->priv->main_task.input.deinterlace.motion ); gst_imx_ipu_blitter_print_ipu_fourcc(ipu_blitter->priv->main_task.output.format, fourcc); GST_LOG_OBJECT( ipu_blitter, "main_task output: width: %u height: %u format: 0x%x (%s) crop: %u,%u %ux%u paddr %" GST_IMX_PHYS_ADDR_FORMAT " rotate: %u", ipu_blitter->priv->main_task.output.width, ipu_blitter->priv->main_task.output.height, ipu_blitter->priv->main_task.output.format, fourcc, ipu_blitter->priv->main_task.output.crop.pos.x, ipu_blitter->priv->main_task.output.crop.pos.y, ipu_blitter->priv->main_task.output.crop.w, ipu_blitter->priv->main_task.output.crop.h, (gst_imx_phys_addr_t)(ipu_blitter->priv->main_task.output.paddr), ipu_blitter->priv->main_task.output.rotate ); if ((ioctl_ret = ioctl(gst_imx_ipu_get_fd(), IPU_QUEUE_TASK, &(ipu_blitter->priv->main_task))) == -1) { GST_ERROR_OBJECT(ipu_blitter, "queuing IPU task failed: %s", strerror(errno)); ret = FALSE; } } return ret; }
static gboolean gst_imx_ipu_blitter_blit_frame(GstImxBaseBlitter *base_blitter, GstImxBaseBlitterRegion const *input_region) { int ret; GstImxIpuBlitter *ipu_blitter = GST_IMX_IPU_BLITTER(base_blitter); char fourcc[5]; ipu_blitter->priv->task.input.crop.pos.x = input_region->x1; ipu_blitter->priv->task.input.crop.pos.y = input_region->y1; ipu_blitter->priv->task.input.crop.w = input_region->x2 - input_region->x1; ipu_blitter->priv->task.input.crop.h = input_region->y2 - input_region->y1; gst_imx_ipu_blitter_print_ipu_fourcc(ipu_blitter->priv->task.input.format, fourcc); GST_LOG_OBJECT( ipu_blitter, "task input: width: %u height: %u format: 0x%x (%s) crop: %u,%u %ux%u phys addr %" GST_IMX_PHYS_ADDR_FORMAT " deinterlace enable %u motion 0x%x", ipu_blitter->priv->task.input.width, ipu_blitter->priv->task.input.height, ipu_blitter->priv->task.input.format, fourcc, ipu_blitter->priv->task.input.crop.pos.x, ipu_blitter->priv->task.input.crop.pos.y, ipu_blitter->priv->task.input.crop.w, ipu_blitter->priv->task.input.crop.h, (gst_imx_phys_addr_t)(ipu_blitter->priv->task.input.paddr), ipu_blitter->priv->task.input.deinterlace.enable, ipu_blitter->priv->task.input.deinterlace.motion ); gst_imx_ipu_blitter_print_ipu_fourcc(ipu_blitter->priv->task.output.format, fourcc); GST_LOG_OBJECT( ipu_blitter, "task output: width: %u height: %u format: 0x%x (%s) crop: %u,%u %ux%u paddr %" GST_IMX_PHYS_ADDR_FORMAT " rotate: %u", ipu_blitter->priv->task.output.width, ipu_blitter->priv->task.output.height, ipu_blitter->priv->task.output.format, fourcc, ipu_blitter->priv->task.output.crop.pos.x, ipu_blitter->priv->task.output.crop.pos.y, ipu_blitter->priv->task.output.crop.w, ipu_blitter->priv->task.output.crop.h, (gst_imx_phys_addr_t)(ipu_blitter->priv->task.output.paddr), ipu_blitter->priv->task.output.rotate ); /* Clear empty regions if necessary * Do so by clearing the entire output region * XXX this is necessary because unlike G2D, the IPU has problems with * pixel perfect positioning, that is, neighbouring regions sometimes * have a few pixels of space between them */ if (!(ipu_blitter->output_region_uptodate)) { struct ipu_task task; GstImxBaseBlitterRegion *output_region = &(ipu_blitter->output_region); GST_LOG_OBJECT(ipu_blitter, "need to clear empty regions"); /* Copy main task object, and replace its input data with the one * for the dummy input object. This way, the data for the output * is copied implicitely as well. */ task = ipu_blitter->priv->task; GST_IMX_FILL_IPU_TASK(ipu_blitter, ipu_blitter->dummy_black_buffer, task.input); task.input.deinterlace.enable = 0; task.input.crop.pos.x = 0; task.input.crop.pos.y = 0; task.input.crop.w = task.input.width; task.input.crop.h = task.input.height; task.output.rotate = IPU_ROTATE_NONE; task.output.crop.pos.x = output_region->x1; task.output.crop.pos.y = output_region->y1; task.output.crop.w = output_region->x2 - output_region->x1; task.output.crop.h = output_region->y2 - output_region->y1; GST_LOG_OBJECT( ipu_blitter, "clear op task input: width: %u height: %u format: 0x%x crop: %u,%u %ux%u phys addr %" GST_IMX_PHYS_ADDR_FORMAT " deinterlace enable %u motion 0x%x", task.input.width, task.input.height, task.input.format, task.input.crop.pos.x, task.input.crop.pos.y, task.input.crop.w, task.input.crop.h, (gst_imx_phys_addr_t)(task.input.paddr), task.input.deinterlace.enable, task.input.deinterlace.motion ); GST_LOG_OBJECT( ipu_blitter, "clear op task output: width: %u height: %u format: 0x%x crop: %u,%u %ux%u paddr %" GST_IMX_PHYS_ADDR_FORMAT " rotate: %u", task.output.width, task.output.height, task.output.format, task.output.crop.pos.x, task.output.crop.pos.y, task.output.crop.w, task.output.crop.h, (gst_imx_phys_addr_t)(task.output.paddr), task.output.rotate ); ret = ioctl(gst_imx_ipu_get_fd(), IPU_QUEUE_TASK, &task); if (ret == -1) GST_ERROR_OBJECT(ipu_blitter, "queuing IPU task failed: %s", strerror(errno)); ipu_blitter->output_region_uptodate = TRUE; } /* The actual blit operation * Input and output frame are assumed to be set up properly at this point */ ret = ioctl(gst_imx_ipu_get_fd(), IPU_QUEUE_TASK, &(ipu_blitter->priv->task)); if (ipu_blitter->deinterlace_mode == GST_IMX_IPU_BLITTER_DEINTERLACE_SLOW_MOTION) { gst_imx_ipu_blitter_clear_previous_buffer(ipu_blitter); if (ipu_blitter->current_frame != NULL) { ipu_blitter->previous_frame = gst_buffer_ref(ipu_blitter->current_frame); ipu_blitter->current_frame = NULL; } } if (ret == -1) { GST_ERROR_OBJECT(ipu_blitter, "queuing IPU task failed: %s", strerror(errno)); return FALSE; } return TRUE; }