static void push_query (gpointer data, gpointer user_data) { GstHarness *h = user_data; GstCaps *caps = gst_caps_new_empty_simple ("mycaps"); GstQuery *query = gst_query_new_allocation (caps, FALSE); gst_caps_unref (caps); gst_pad_peer_query (h->srcpad, query); gst_query_unref (query); }
static gboolean gst_gl_base_mixer_do_bufferpool (GstGLBaseMixer * mix, GstCaps * outcaps) { GstQuery *query; gboolean result = TRUE; GstBufferPool *pool = NULL; GstAllocator *allocator; GstAllocationParams params; GstAggregator *agg = GST_AGGREGATOR (mix); /* find a pool for the negotiated caps now */ GST_DEBUG_OBJECT (mix, "doing allocation query"); query = gst_query_new_allocation (outcaps, TRUE); if (!gst_pad_peer_query (agg->srcpad, query)) { /* not a problem, just debug a little */ GST_DEBUG_OBJECT (mix, "peer ALLOCATION query failed"); } GST_DEBUG_OBJECT (mix, "calling decide_allocation"); result = gst_gl_base_mixer_decide_allocation (mix, query); GST_DEBUG_OBJECT (mix, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, result, query); if (!result) goto no_decide_allocation; /* we got configuration from our peer or the decide_allocation method, * parse them */ if (gst_query_get_n_allocation_params (query) > 0) { gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); } else { allocator = NULL; gst_allocation_params_init (¶ms); } if (gst_query_get_n_allocation_pools (query) > 0) gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL); /* now store */ result = gst_gl_base_mixer_set_allocation (mix, pool, allocator, ¶ms, query); return result; /* Errors */ no_decide_allocation: { GST_WARNING_OBJECT (mix, "Failed to decide allocation"); gst_query_unref (query); return result; } }
static gboolean gst_gdk_pixbuf_dec_setup_pool (GstGdkPixbufDec * filter, GstVideoInfo * info) { GstCaps *target; GstQuery *query; GstBufferPool *pool; GstStructure *config; guint size, min, max; target = gst_pad_get_current_caps (filter->srcpad); /* try to get a bufferpool now */ /* find a pool for the negotiated caps now */ query = gst_query_new_allocation (target, TRUE); if (!gst_pad_peer_query (filter->srcpad, query)) { /* not a problem, we use the query defaults */ GST_DEBUG_OBJECT (filter, "ALLOCATION query failed"); } if (gst_query_get_n_allocation_pools (query) > 0) { /* we got configuration from our peer, parse them */ gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); } else { pool = NULL; size = info->size; min = max = 0; } gst_query_unref (query); if (pool == NULL) { /* we did not get a pool, make one ourselves then */ pool = gst_buffer_pool_new (); } /* and configure */ config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, target, size, min, max); gst_buffer_pool_set_config (pool, config); if (filter->pool) { gst_buffer_pool_set_active (filter->pool, FALSE); gst_object_unref (filter->pool); } filter->pool = pool; /* and activate */ gst_buffer_pool_set_active (filter->pool, TRUE); gst_caps_unref (target); return TRUE; }
static void gst_dvdec_negotiate_pool (GstDVDec * dec, GstCaps * caps, GstVideoInfo * info) { GstQuery *query; GstBufferPool *pool; guint size, min, max; GstStructure *config; /* find a pool for the negotiated caps now */ query = gst_query_new_allocation (caps, TRUE); if (!gst_pad_peer_query (dec->srcpad, query)) { GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints"); } if (gst_query_get_n_allocation_pools (query) > 0) { /* we got configuration from our peer, parse them */ gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); size = MAX (size, info->size); } else { pool = NULL; size = info->size; min = max = 0; } if (pool == NULL) { /* we did not get a pool, make one ourselves then */ pool = gst_video_buffer_pool_new (); } if (dec->pool) { gst_buffer_pool_set_active (dec->pool, FALSE); gst_object_unref (dec->pool); } dec->pool = pool; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, min, max); if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) { /* just set the option, if the pool can support it we will transparently use * it through the video info API. We could also see if the pool support this * option and only activate it then. */ gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); } gst_buffer_pool_set_config (pool, config); /* and activate */ gst_buffer_pool_set_active (pool, TRUE); gst_query_unref (query); }
static GstFlowReturn gst_rtp_vraw_depay_negotiate_pool (GstRtpVRawDepay * depay, GstCaps * caps, GstVideoInfo * info) { GstQuery *query; GstBufferPool *pool = NULL; guint size, min, max; GstStructure *config; /* find a pool for the negotiated caps now */ query = gst_query_new_allocation (caps, TRUE); if (!gst_pad_peer_query (GST_RTP_BASE_DEPAYLOAD_SRCPAD (depay), query)) { /* not a problem, we use the defaults of query */ GST_DEBUG_OBJECT (depay, "could not get downstream ALLOCATION hints"); } if (gst_query_get_n_allocation_pools (query) > 0) { /* we got configuration from our peer, parse them */ gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); } else { GST_DEBUG_OBJECT (depay, "didn't get downstream pool hints"); size = info->size; min = max = 0; } if (pool == NULL) { /* we did not get a pool, make one ourselves then */ pool = gst_video_buffer_pool_new (); } if (depay->pool) gst_object_unref (depay->pool); depay->pool = pool; config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, min, max); if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) { /* just set the metadata, if the pool can support it we will transparently use * it through the video info API. We could also see if the pool support this * metadata and only activate it then. */ gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); } gst_buffer_pool_set_config (pool, config); /* and activate */ gst_buffer_pool_set_active (pool, TRUE); gst_query_unref (query); return GST_FLOW_OK; }
static gboolean stereosplit_do_bufferpool (GstGLStereoSplit * self, GstCaps * caps) { GstQuery *query; query = gst_query_new_allocation (caps, TRUE); if (!gst_pad_peer_query (self->left_pad, query)) { if (!gst_pad_peer_query (self->right_pad, query)) { GST_DEBUG_OBJECT (self, "peer ALLOCATION query failed on both src pads"); } } if (!stereosplit_decide_allocation (self, query)) { gst_query_unref (query); return FALSE; } gst_query_unref (query); return TRUE; }
static gpointer thread_func (gpointer data) { int i = 0; for (i = 0; i < 100; i++) { GstCaps *caps; GstQuery *query; gboolean ok; caps = gst_caps_new_any (); query = gst_query_new_allocation (caps, FALSE); ok = gst_pad_peer_query (mysrcpad, query); gst_query_unref (query); gst_caps_unref (caps); query = NULL; caps = NULL; if (!ok) break; } return NULL; }
static gboolean gst_monoscope_src_negotiate (GstMonoscope * monoscope) { GstCaps *othercaps, *target; GstStructure *structure; GstCaps *templ; GstQuery *query; GstBufferPool *pool; GstStructure *config; guint size, min, max; templ = gst_pad_get_pad_template_caps (monoscope->srcpad); GST_DEBUG_OBJECT (monoscope, "performing negotiation"); /* see what the peer can do */ othercaps = gst_pad_peer_query_caps (monoscope->srcpad, NULL); if (othercaps) { target = gst_caps_intersect (othercaps, templ); gst_caps_unref (othercaps); gst_caps_unref (templ); if (gst_caps_is_empty (target)) goto no_format; target = gst_caps_truncate (target); } else { target = templ; } target = gst_caps_make_writable (target); structure = gst_caps_get_structure (target, 0); gst_structure_fixate_field_nearest_int (structure, "width", 320); gst_structure_fixate_field_nearest_int (structure, "height", 240); gst_structure_fixate_field_nearest_fraction (structure, "framerate", 25, 1); gst_monoscope_src_setcaps (monoscope, target); /* try to get a bufferpool now */ /* find a pool for the negotiated caps now */ query = gst_query_new_allocation (target, TRUE); if (!gst_pad_peer_query (monoscope->srcpad, query)) { } if (gst_query_get_n_allocation_pools (query) > 0) { /* we got configuration from our peer, parse them */ gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); } else { pool = NULL; size = monoscope->outsize; min = max = 0; } if (pool == NULL) { /* we did not get a pool, make one ourselves then */ pool = gst_buffer_pool_new (); } config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, target, size, min, max); gst_buffer_pool_set_config (pool, config); if (monoscope->pool) { gst_buffer_pool_set_active (monoscope->pool, TRUE); gst_object_unref (monoscope->pool); } monoscope->pool = pool; /* and activate */ gst_buffer_pool_set_active (pool, TRUE); gst_caps_unref (target); return TRUE; no_format: { gst_caps_unref (target); return FALSE; } }
static gboolean gst_goom_src_negotiate (GstGoom * goom) { GstCaps *othercaps, *target; GstStructure *structure; GstCaps *templ; GstQuery *query; GstBufferPool *pool; GstStructure *config; guint size, min, max; templ = gst_pad_get_pad_template_caps (goom->srcpad); GST_DEBUG_OBJECT (goom, "performing negotiation"); /* see what the peer can do */ othercaps = gst_pad_peer_query_caps (goom->srcpad, NULL); if (othercaps) { target = gst_caps_intersect (othercaps, templ); gst_caps_unref (othercaps); gst_caps_unref (templ); if (gst_caps_is_empty (target)) goto no_format; target = gst_caps_truncate (target); } else { target = templ; } structure = gst_caps_get_structure (target, 0); gst_structure_fixate_field_nearest_int (structure, "width", DEFAULT_WIDTH); gst_structure_fixate_field_nearest_int (structure, "height", DEFAULT_HEIGHT); gst_structure_fixate_field_nearest_fraction (structure, "framerate", DEFAULT_FPS_N, DEFAULT_FPS_D); gst_goom_src_setcaps (goom, target); /* try to get a bufferpool now */ /* find a pool for the negotiated caps now */ query = gst_query_new_allocation (target, TRUE); if (!gst_pad_peer_query (goom->srcpad, query)) { /* no problem, we use the query defaults */ GST_DEBUG_OBJECT (goom, "ALLOCATION query failed"); } if (gst_query_get_n_allocation_pools (query) > 0) { /* we got configuration from our peer, parse them */ gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); } else { pool = NULL; size = goom->outsize; min = max = 0; } if (pool == NULL) { /* we did not get a pool, make one ourselves then */ pool = gst_buffer_pool_new (); } config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, target, size, min, max); gst_buffer_pool_set_config (pool, config); if (goom->pool) { gst_buffer_pool_set_active (goom->pool, FALSE); gst_object_unref (goom->pool); } goom->pool = pool; /* and activate */ gst_buffer_pool_set_active (pool, TRUE); gst_caps_unref (target); return TRUE; no_format: { gst_caps_unref (target); return FALSE; } }
/* only negotiate/query video overlay composition support for now */ static gboolean gst_dvbsub_overlay_negotiate (GstDVBSubOverlay * overlay, GstCaps * caps) { gboolean ret; gboolean attach = FALSE; gboolean caps_has_meta = TRUE; GstCapsFeatures *f; GST_DEBUG_OBJECT (overlay, "performing negotiation"); if (!caps) { caps = gst_pad_get_current_caps (overlay->srcpad); } else { gst_caps_ref (caps); } if (!caps || gst_caps_is_empty (caps)) goto no_format; /* Try to use the overlay meta if possible */ f = gst_caps_get_features (caps, 0); /* if the caps doesn't have the overlay meta, we query if downstream * accepts it before trying the version without the meta * If upstream already is using the meta then we can only use it */ if (!f || !gst_caps_features_contains (f, GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)) { GstCaps *overlay_caps; GstCaps *peercaps; /* In this case we added the meta, but we can work without it * so preserve the original caps so we can use it as a fallback */ overlay_caps = gst_caps_copy (caps); f = gst_caps_get_features (overlay_caps, 0); gst_caps_features_add (f, GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); /* FIXME: We should probably check if downstream *prefers* the * overlay meta, and only enforce usage of it if we can't handle * the format ourselves and thus would have to drop the overlays. * Otherwise we should prefer what downstream wants here. */ peercaps = gst_pad_peer_query_caps (overlay->srcpad, NULL); caps_has_meta = gst_caps_can_intersect (peercaps, overlay_caps); gst_caps_unref (peercaps); GST_DEBUG_OBJECT (overlay, "Downstream accepts the overlay meta: %d", caps_has_meta); if (caps_has_meta) { gst_caps_unref (caps); caps = overlay_caps; } else { /* fallback to the original */ gst_caps_unref (overlay_caps); caps_has_meta = FALSE; } } GST_DEBUG_OBJECT (overlay, "Using caps %" GST_PTR_FORMAT, caps); ret = gst_pad_set_caps (overlay->srcpad, caps); if (ret) { GstQuery *query; /* find supported meta */ query = gst_query_new_allocation (caps, FALSE); if (!gst_pad_peer_query (overlay->srcpad, query)) { /* no problem, we use the query defaults */ GST_DEBUG_OBJECT (overlay, "ALLOCATION query failed"); } if (caps_has_meta && gst_query_find_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL)) attach = TRUE; overlay->attach_compo_to_buffer = attach; gst_query_unref (query); } gst_caps_unref (caps); return ret; no_format: { if (caps) gst_caps_unref (caps); return FALSE; } }
/* Based on gstbasetextoverlay.c */ static gboolean gst_overlay_composition_negotiate (GstOverlayComposition * self, GstCaps * caps) { gboolean upstream_has_meta = FALSE; gboolean caps_has_meta = FALSE; gboolean alloc_has_meta = FALSE; gboolean attach = FALSE; gboolean ret = TRUE; guint width, height; GstCapsFeatures *f; GstCaps *overlay_caps; GstQuery *query; guint alloc_index; GST_DEBUG_OBJECT (self, "performing negotiation"); /* Clear any pending reconfigure to avoid negotiating twice */ gst_pad_check_reconfigure (self->srcpad); self->window_width = self->window_height = 0; if (!caps) caps = gst_pad_get_current_caps (self->sinkpad); else gst_caps_ref (caps); if (!caps || gst_caps_is_empty (caps)) goto no_format; /* Check if upstream caps have meta */ if ((f = gst_caps_get_features (caps, 0))) { upstream_has_meta = gst_caps_features_contains (f, GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); } /* Initialize dimensions */ width = self->info.width; height = self->info.height; if (upstream_has_meta) { overlay_caps = gst_caps_ref (caps); } else { GstCaps *peercaps; /* BaseTransform requires caps for the allocation query to work */ overlay_caps = gst_caps_copy (caps); f = gst_caps_get_features (overlay_caps, 0); gst_caps_features_add (f, GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION); /* Then check if downstream accept overlay composition in caps */ /* FIXME: We should probably check if downstream *prefers* the * overlay meta, and only enforce usage of it if we can't handle * the format ourselves and thus would have to drop the overlays. * Otherwise we should prefer what downstream wants here. */ peercaps = gst_pad_peer_query_caps (self->srcpad, overlay_caps); caps_has_meta = !gst_caps_is_empty (peercaps); gst_caps_unref (peercaps); GST_DEBUG_OBJECT (self, "caps have overlay meta %d", caps_has_meta); } if (upstream_has_meta || caps_has_meta) { /* Send caps immediatly, it's needed by GstBaseTransform to get a reply * from allocation query */ ret = gst_pad_set_caps (self->srcpad, overlay_caps); /* First check if the allocation meta has compositon */ query = gst_query_new_allocation (overlay_caps, FALSE); if (!gst_pad_peer_query (self->srcpad, query)) { /* no problem, we use the query defaults */ GST_DEBUG_OBJECT (self, "ALLOCATION query failed"); /* In case we were flushing, mark reconfigure and fail this method, * will make it retry */ if (GST_PAD_IS_FLUSHING (self->srcpad)) ret = FALSE; } alloc_has_meta = gst_query_find_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, &alloc_index); GST_DEBUG_OBJECT (self, "sink alloc has overlay meta %d", alloc_has_meta); if (alloc_has_meta) { const GstStructure *params; gst_query_parse_nth_allocation_meta (query, alloc_index, ¶ms); if (params) { if (gst_structure_get (params, "width", G_TYPE_UINT, &width, "height", G_TYPE_UINT, &height, NULL)) { GST_DEBUG_OBJECT (self, "received window size: %dx%d", width, height); g_assert (width != 0 && height != 0); } } } gst_query_unref (query); } /* Update render size if needed */ self->window_width = width; self->window_height = height; /* For backward compatbility, we will prefer bliting if downstream * allocation does not support the meta. In other case we will prefer * attaching, and will fail the negotiation in the unlikely case we are * force to blit, but format isn't supported. */ if (upstream_has_meta) { attach = TRUE; } else if (caps_has_meta) { if (alloc_has_meta) { attach = TRUE; } else { /* Don't attach unless we cannot handle the format */ attach = !can_blend_caps (caps); } } else { ret = can_blend_caps (caps); } /* If we attach, then pick the overlay caps */ if (attach) { GST_DEBUG_OBJECT (self, "Using caps %" GST_PTR_FORMAT, overlay_caps); /* Caps where already sent */ } else if (ret) { GST_DEBUG_OBJECT (self, "Using caps %" GST_PTR_FORMAT, caps); ret = gst_pad_set_caps (self->srcpad, caps); } self->attach_compo_to_buffer = attach; if (!ret) { GST_DEBUG_OBJECT (self, "negotiation failed, schedule reconfigure"); gst_pad_mark_reconfigure (self->srcpad); } g_signal_emit (self, overlay_composition_signals[SIGNAL_CAPS_CHANGED], 0, caps, self->window_width, self->window_height, NULL); gst_caps_unref (overlay_caps); gst_caps_unref (caps); return ret; no_format: { if (caps) gst_caps_unref (caps); gst_pad_mark_reconfigure (self->srcpad); return FALSE; } }
static GstFlowReturn gst_y4m_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstY4mDec *y4mdec; int n_avail; GstFlowReturn flow_ret = GST_FLOW_OK; #define MAX_HEADER_LENGTH 80 char header[MAX_HEADER_LENGTH]; int i; int len; y4mdec = GST_Y4M_DEC (parent); GST_DEBUG_OBJECT (y4mdec, "chain"); if (GST_BUFFER_IS_DISCONT (buffer)) { GST_DEBUG ("got discont"); gst_adapter_clear (y4mdec->adapter); } gst_adapter_push (y4mdec->adapter, buffer); n_avail = gst_adapter_available (y4mdec->adapter); if (!y4mdec->have_header) { gboolean ret; GstCaps *caps; GstQuery *query; if (n_avail < MAX_HEADER_LENGTH) return GST_FLOW_OK; gst_adapter_copy (y4mdec->adapter, (guint8 *) header, 0, MAX_HEADER_LENGTH); header[MAX_HEADER_LENGTH - 1] = 0; for (i = 0; i < MAX_HEADER_LENGTH; i++) { if (header[i] == 0x0a) header[i] = 0; } ret = gst_y4m_dec_parse_header (y4mdec, header); if (!ret) { GST_ELEMENT_ERROR (y4mdec, STREAM, DECODE, ("Failed to parse YUV4MPEG header"), (NULL)); return GST_FLOW_ERROR; } y4mdec->header_size = strlen (header) + 1; gst_adapter_flush (y4mdec->adapter, y4mdec->header_size); caps = gst_video_info_to_caps (&y4mdec->info); ret = gst_pad_set_caps (y4mdec->srcpad, caps); query = gst_query_new_allocation (caps, FALSE); y4mdec->video_meta = FALSE; if (y4mdec->pool) { gst_buffer_pool_set_active (y4mdec->pool, FALSE); gst_object_unref (y4mdec->pool); } y4mdec->pool = NULL; if (gst_pad_peer_query (y4mdec->srcpad, query)) { y4mdec->video_meta = gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); /* We only need a pool if we need to do stride conversion for downstream */ if (!y4mdec->video_meta && memcmp (&y4mdec->info, &y4mdec->out_info, sizeof (y4mdec->info)) != 0) { GstBufferPool *pool = NULL; GstAllocator *allocator = NULL; GstAllocationParams params; GstStructure *config; guint size, min, max; if (gst_query_get_n_allocation_params (query) > 0) { gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); } else { allocator = NULL; gst_allocation_params_init (¶ms); } if (gst_query_get_n_allocation_pools (query) > 0) { gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); size = MAX (size, y4mdec->out_info.size); } else { pool = NULL; size = y4mdec->out_info.size; min = max = 0; } if (pool == NULL) { pool = gst_video_buffer_pool_new (); } config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, size, min, max); gst_buffer_pool_config_set_allocator (config, allocator, ¶ms); gst_buffer_pool_set_config (pool, config); if (allocator) gst_object_unref (allocator); y4mdec->pool = pool; } } else if (memcmp (&y4mdec->info, &y4mdec->out_info, sizeof (y4mdec->info)) != 0) { GstBufferPool *pool; GstStructure *config; /* No pool, create our own if we need to do stride conversion */ pool = gst_video_buffer_pool_new (); config = gst_buffer_pool_get_config (pool); gst_buffer_pool_config_set_params (config, caps, y4mdec->out_info.size, 0, 0); gst_buffer_pool_set_config (pool, config); y4mdec->pool = pool; } if (y4mdec->pool) { gst_buffer_pool_set_active (y4mdec->pool, TRUE); } gst_query_unref (query); gst_caps_unref (caps); if (!ret) { GST_DEBUG_OBJECT (y4mdec, "Couldn't set caps on src pad"); return GST_FLOW_ERROR; } y4mdec->have_header = TRUE; } if (y4mdec->have_new_segment) { GstEvent *event; GstClockTime start = gst_y4m_dec_bytes_to_timestamp (y4mdec, y4mdec->segment.start); GstClockTime stop = gst_y4m_dec_bytes_to_timestamp (y4mdec, y4mdec->segment.stop); GstClockTime time = gst_y4m_dec_bytes_to_timestamp (y4mdec, y4mdec->segment.time); GstSegment seg; gst_segment_init (&seg, GST_FORMAT_TIME); seg.start = start; seg.stop = stop; seg.time = time; event = gst_event_new_segment (&seg); gst_pad_push_event (y4mdec->srcpad, event); //gst_event_unref (event); y4mdec->have_new_segment = FALSE; y4mdec->frame_index = gst_y4m_dec_bytes_to_frames (y4mdec, y4mdec->segment.time); GST_DEBUG ("new frame_index %d", y4mdec->frame_index); } while (1) { n_avail = gst_adapter_available (y4mdec->adapter); if (n_avail < MAX_HEADER_LENGTH) break; gst_adapter_copy (y4mdec->adapter, (guint8 *) header, 0, MAX_HEADER_LENGTH); header[MAX_HEADER_LENGTH - 1] = 0; for (i = 0; i < MAX_HEADER_LENGTH; i++) { if (header[i] == 0x0a) header[i] = 0; } if (memcmp (header, "FRAME", 5) != 0) { GST_ELEMENT_ERROR (y4mdec, STREAM, DECODE, ("Failed to parse YUV4MPEG frame"), (NULL)); flow_ret = GST_FLOW_ERROR; break; } len = strlen (header); if (n_avail < y4mdec->info.size + len + 1) { /* not enough data */ GST_DEBUG ("not enough data for frame %d < %" G_GSIZE_FORMAT, n_avail, y4mdec->info.size + len + 1); break; } gst_adapter_flush (y4mdec->adapter, len + 1); buffer = gst_adapter_take_buffer (y4mdec->adapter, y4mdec->info.size); GST_BUFFER_TIMESTAMP (buffer) = gst_y4m_dec_frames_to_timestamp (y4mdec, y4mdec->frame_index); GST_BUFFER_DURATION (buffer) = gst_y4m_dec_frames_to_timestamp (y4mdec, y4mdec->frame_index + 1) - GST_BUFFER_TIMESTAMP (buffer); y4mdec->frame_index++; if (y4mdec->video_meta) { gst_buffer_add_video_meta_full (buffer, 0, y4mdec->info.finfo->format, y4mdec->info.width, y4mdec->info.height, y4mdec->info.finfo->n_planes, y4mdec->info.offset, y4mdec->info.stride); } else if (memcmp (&y4mdec->info, &y4mdec->out_info, sizeof (y4mdec->info)) != 0) { GstBuffer *outbuf; GstVideoFrame iframe, oframe; gint i, j; gint w, h, istride, ostride; guint8 *src, *dest; /* Allocate a new buffer and do stride conversion */ g_assert (y4mdec->pool != NULL); flow_ret = gst_buffer_pool_acquire_buffer (y4mdec->pool, &outbuf, NULL); if (flow_ret != GST_FLOW_OK) { gst_buffer_unref (buffer); break; } gst_video_frame_map (&iframe, &y4mdec->info, buffer, GST_MAP_READ); gst_video_frame_map (&oframe, &y4mdec->out_info, outbuf, GST_MAP_WRITE); for (i = 0; i < 3; i++) { w = GST_VIDEO_FRAME_COMP_WIDTH (&iframe, i); h = GST_VIDEO_FRAME_COMP_HEIGHT (&iframe, i); istride = GST_VIDEO_FRAME_COMP_STRIDE (&iframe, i); ostride = GST_VIDEO_FRAME_COMP_STRIDE (&oframe, i); src = GST_VIDEO_FRAME_COMP_DATA (&iframe, i); dest = GST_VIDEO_FRAME_COMP_DATA (&oframe, i); for (j = 0; j < h; j++) { memcpy (dest, src, w); dest += ostride; src += istride; } } gst_video_frame_unmap (&iframe); gst_video_frame_unmap (&oframe); gst_buffer_copy_into (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS, 0, -1); gst_buffer_unref (buffer); buffer = outbuf; } flow_ret = gst_pad_push (y4mdec->srcpad, buffer); if (flow_ret != GST_FLOW_OK) break; } GST_DEBUG ("returning %d", flow_ret); return flow_ret; }
/* This will get invoked in the following situations: * 1: begining of the stream, which requires initialization (== complete reset) * 2: upstream notified a resolution change and set do_renego to TRUE. * new resoulution may or may not requires full reset * 3: upstream failed to notify the resoulution change but * msdk detected the change (eg: vp9 stream in ivf elementary form * with varying resolution frames). * * for any input configuration change, we deal with notification * from upstream and also use msdk apis to handle the parameter initialization * efficiently */ static gboolean gst_msdkdec_negotiate (GstMsdkDec * thiz, gboolean hard_reset) { GstVideoDecoder *decoder = GST_VIDEO_DECODER (thiz); GST_DEBUG_OBJECT (thiz, "Start Negotiating caps, pool and Init the msdk decdoer subsystem"); if (hard_reset) { /* Retrieve any pending frames and push them downstream */ if (gst_msdkdec_drain (GST_VIDEO_DECODER (thiz)) != GST_FLOW_OK) goto error_drain; /* This will initiate the allocation query which will help to flush * all the pending buffers in the pipeline so that we can stop * the active bufferpool and safely invoke gst_msdk_frame_free() */ if (thiz->initialized) { GstCaps *caps = gst_pad_get_current_caps (decoder->srcpad); GstQuery *query = NULL; if (caps) { query = gst_query_new_allocation (caps, FALSE); gst_pad_peer_query (decoder->srcpad, query); gst_query_unref (query); gst_caps_unref (caps); } } /* De-initialize the decoder if it is already active */ /* Not resetting the mfxVideoParam since it already * possessing the required parameters for new session decode */ gst_msdkdec_close_decoder (thiz, FALSE); /* request for pool renegotiation by setting do_realloc */ thiz->do_realloc = TRUE; } /* At this point all pending frames(if there is any) are pushed downsteram * and we are ready to negotiate the output caps */ if (!gst_msdkdec_set_src_caps (thiz, hard_reset)) return FALSE; /* this will initiate the allocation query, we create the * bufferpool in decide_allocation inorder to account * the downstream min_buffer requirement * Required initializations for MediaSDK operations * will all be inited from decide_allocation after considering * some of the downstream requirements */ if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (thiz))) goto error_negotiate; thiz->do_renego = FALSE; thiz->do_realloc = FALSE; return TRUE; error_drain: GST_ERROR_OBJECT (thiz, "Failed to Drain the queued decoded frames"); return FALSE; error_negotiate: GST_ERROR_OBJECT (thiz, "Failed to renegotiation"); return FALSE; }