gboolean gst_imx_blitter_set_input_frame(GstImxBlitter *blitter, GstBuffer *frame) { gboolean ret; GstImxPhysMemMeta *phys_mem_meta; GstImxBlitterClass *klass; g_assert(blitter != NULL); klass = GST_IMX_BLITTER_CLASS(G_OBJECT_GET_CLASS(blitter)); g_assert(klass->set_input_frame != NULL); if (frame == NULL) return klass->set_input_frame(blitter, NULL); phys_mem_meta = GST_IMX_PHYS_MEM_META_GET(frame); if ((phys_mem_meta == NULL) || (phys_mem_meta->phys_addr == 0)) { GstFlowReturn flow_ret; GstBuffer *internal_input_frame; /* No DMA memory present; the input frame needs to be copied to an internal input frame */ GST_TRACE_OBJECT(blitter, "input frame does not use DMA memory - copying input frame to internal frame"); { if (blitter->dma_bufferpool == NULL) { GST_TRACE_OBJECT(blitter, "need to create internal bufferpool"); /* DMA bufferpool does not exist yet - create it now, * so that it can in turn create the internal input frame */ GstCaps *caps = gst_video_info_to_caps(&(blitter->input_video_info)); blitter->dma_bufferpool = gst_imx_blitter_create_bufferpool( blitter, caps, blitter->input_video_info.size, 0, 0, NULL, NULL ); gst_caps_unref(caps); if (blitter->dma_bufferpool == NULL) { GST_ERROR_OBJECT(blitter, "failed to create internal bufferpool"); return FALSE; } } /* Future versions of this code may propose the internal bufferpool upstream; * hence the is_active check */ if (!gst_buffer_pool_is_active(blitter->dma_bufferpool)) gst_buffer_pool_set_active(blitter->dma_bufferpool, TRUE); } /* Create new internal input frame */ GST_TRACE_OBJECT(blitter, "acquiring buffer for internal input frame"); internal_input_frame = NULL; flow_ret = gst_buffer_pool_acquire_buffer(blitter->dma_bufferpool, &internal_input_frame, NULL); if (flow_ret != GST_FLOW_OK) { if (internal_input_frame != NULL) gst_buffer_unref(internal_input_frame); GST_ERROR_OBJECT(blitter, "error acquiring input frame buffer: %s", gst_pad_mode_get_name(flow_ret)); return FALSE; } /* Copy the input buffer's pixels to the internal input frame */ { GstVideoFrame input_vidframe, internal_input_vidframe; gst_video_frame_map(&input_vidframe, &(blitter->input_video_info), frame, GST_MAP_READ); gst_video_frame_map(&internal_input_vidframe, &(blitter->input_video_info), internal_input_frame, GST_MAP_WRITE); /* gst_video_frame_copy() makes sure stride and plane offset values from both frames are respected */ gst_video_frame_copy(&internal_input_vidframe, &input_vidframe); /* copy interlace flags */ GST_BUFFER_FLAGS(internal_input_frame) |= (GST_BUFFER_FLAGS(frame) & (GST_VIDEO_BUFFER_FLAG_INTERLACED | GST_VIDEO_BUFFER_FLAG_TFF | GST_VIDEO_BUFFER_FLAG_RFF | GST_VIDEO_BUFFER_FLAG_ONEFIELD)); gst_video_frame_unmap(&internal_input_vidframe); gst_video_frame_unmap(&input_vidframe); } ret = klass->set_input_frame(blitter, internal_input_frame); gst_buffer_unref(internal_input_frame); } else { GST_TRACE_OBJECT(blitter, "input frame uses DMA memory - setting it directly as input frame"); ret = klass->set_input_frame(blitter, frame); } return ret; }
static gboolean gst_imx_blitter_video_transform_decide_allocation(GstBaseTransform *transform, GstQuery *query) { GstImxBlitterVideoTransform *blitter_video_transform = GST_IMX_BLITTER_VIDEO_TRANSFORM(transform); GstCaps *outcaps; GstBufferPool *pool = NULL; guint size, min = 0, max = 0; GstStructure *config; GstVideoInfo vinfo; gboolean update_pool; g_assert(blitter_video_transform->blitter != NULL); gst_query_parse_allocation(query, &outcaps, NULL); gst_video_info_init(&vinfo); gst_video_info_from_caps(&vinfo, outcaps); GST_DEBUG_OBJECT(blitter_video_transform, "num allocation pools: %d", gst_query_get_n_allocation_pools(query)); /* Look for an allocator which can allocate physical memory buffers */ if (gst_query_get_n_allocation_pools(query) > 0) { for (guint i = 0; i < gst_query_get_n_allocation_pools(query); ++i) { gst_query_parse_nth_allocation_pool(query, i, &pool, &size, &min, &max); if (gst_buffer_pool_has_option(pool, GST_BUFFER_POOL_OPTION_IMX_PHYS_MEM)) break; } size = MAX(size, vinfo.size); update_pool = TRUE; } else { pool = NULL; size = vinfo.size; min = max = 0; update_pool = FALSE; } /* Either no pool or no pool with the ability to allocate physical memory buffers * has been found -> create a new pool */ if ((pool == NULL) || !gst_buffer_pool_has_option(pool, GST_BUFFER_POOL_OPTION_IMX_PHYS_MEM)) { if (pool == NULL) GST_DEBUG_OBJECT(blitter_video_transform, "no pool present; creating new pool"); else GST_DEBUG_OBJECT(blitter_video_transform, "no pool supports physical memory buffers; creating new pool"); pool = gst_imx_blitter_create_bufferpool(blitter_video_transform->blitter, outcaps, size, min, max, NULL, NULL); } else { config = gst_buffer_pool_get_config(pool); gst_buffer_pool_config_set_params(config, outcaps, size, min, max); gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_IMX_PHYS_MEM); gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META); gst_buffer_pool_set_config(pool, config); } GST_DEBUG_OBJECT( blitter_video_transform, "pool config: outcaps: %" GST_PTR_FORMAT " size: %u min buffers: %u max buffers: %u", (gpointer)outcaps, size, min, max ); if (update_pool) gst_query_set_nth_allocation_pool(query, 0, pool, size, min, max); else gst_query_add_allocation_pool(query, pool, size, min, max); if (pool != NULL) gst_object_unref(pool); return TRUE; }