#include "gstvideoutils.h"
#include <gst/video/gstvideometa.h>
+#include <gst/video/gstvideopool.h>
#include <string.h>
/* FIXME : (and introduce a context ?) */
gboolean drained;
gboolean at_eos;
+ gboolean do_caps;
gint64 min_latency;
gint64 max_latency;
GList *force_key_unit; /* List of pending forced keyunits */
- guint64 system_frame_number;
+ guint32 system_frame_number;
GList *frames; /* Protected with OBJECT_LOCK */
GstVideoCodecState *input_state;
* gst_video_encoder_proxy_getcaps:
* @enc: a #GstVideoEncoder
* @caps: initial caps
+ * @filter: filter caps
*
* Returns caps that express @caps (or sink template caps if @caps == NULL)
* restricted to resolution/format/... combinations supported by downstream
gst_video_encoder_propose_allocation_default (GstVideoEncoder * encoder,
GstQuery * query)
{
+ GstCaps *caps;
+ GstVideoInfo info;
+ GstBufferPool *pool;
+ guint size;
+
+ gst_query_parse_allocation (query, &caps, NULL);
+
+ if (caps == NULL)
+ return FALSE;
+
+ if (!gst_video_info_from_caps (&info, caps))
+ return FALSE;
+
+ size = GST_VIDEO_INFO_SIZE (&info);
+
+ if (gst_query_get_n_allocation_pools (query) == 0) {
+ GstStructure *structure;
+ GstAllocator *allocator = NULL;
+ GstAllocationParams params = { 0, 15, 0, 0 };
+
+ if (gst_query_get_n_allocation_params (query) > 0)
+ gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
+ else
+ gst_query_add_allocation_param (query, allocator, ¶ms);
+
+ pool = gst_video_buffer_pool_new ();
+
+ structure = gst_buffer_pool_get_config (pool);
+ gst_buffer_pool_config_set_params (structure, caps, size, 0, 0);
+ gst_buffer_pool_config_set_allocator (structure, allocator, ¶ms);
+
+ if (allocator)
+ gst_object_unref (allocator);
+
+ if (!gst_buffer_pool_set_config (pool, structure))
+ goto config_failed;
+
+ gst_query_add_allocation_pool (query, pool, size, 0, 0);
+ gst_object_unref (pool);
+ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
+ }
+
return TRUE;
+
+ /* ERRORS */
+config_failed:
+ {
+ GST_ERROR_OBJECT (encoder, "failed to set config");
+ gst_object_unref (pool);
+ return FALSE;
+ }
}
static gboolean
GstCaps *caps;
gst_event_parse_caps (event, &caps);
- ret = gst_video_encoder_setcaps (encoder, caps);
+ ret = TRUE;
+ encoder->priv->do_caps = TRUE;
gst_event_unref (event);
event = NULL;
break;
g_return_val_if_fail (klass->handle_frame != NULL, GST_FLOW_ERROR);
+ if (G_UNLIKELY (encoder->priv->do_caps)) {
+ GstCaps *caps = gst_pad_get_current_caps (encoder->sinkpad);
+ if (!caps)
+ goto not_negotiated;
+ if (!gst_video_encoder_setcaps (encoder, caps)) {
+ gst_caps_unref (caps);
+ goto not_negotiated;
+ }
+ encoder->priv->do_caps = FALSE;
+ }
+
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
pts = GST_BUFFER_PTS (buf);
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
return ret;
+
+ /* ERRORS */
+not_negotiated:
+ {
+ GST_ELEMENT_ERROR (encoder, CORE, NEGOTIATION, (NULL),
+ ("encoder not initialized"));
+ gst_buffer_unref (buf);
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
}
static GstStateChangeReturn
}
}
-static gboolean
-gst_video_encoder_set_src_caps (GstVideoEncoder * encoder)
+/**
+ * gst_video_encoder_negotiate:
+ * @encoder: a #GstVideoEncoder
+ *
+ * Negotiate with downstream elements to currently configured #GstVideoCodecState.
+ *
+ * Returns: #TRUE if the negotiation succeeded, else #FALSE.
+ */
+gboolean
+gst_video_encoder_negotiate (GstVideoEncoder * encoder)
{
GstVideoEncoderClass *klass = GST_VIDEO_ENCODER_GET_CLASS (encoder);
GstAllocator *allocator;
gboolean ret;
GstVideoCodecState *state = encoder->priv->output_state;
GstVideoInfo *info = &state->info;
- GstQuery *query;
+ GstQuery *query = NULL;
g_return_val_if_fail (state->caps != NULL, FALSE);
ret = gst_pad_set_caps (encoder->srcpad, state->caps);
if (!ret)
- return ret;
+ goto done;
query = gst_query_new_allocation (state->caps, TRUE);
if (!gst_pad_peer_query (encoder->srcpad, query)) {
}
/**
- * gst_video_encoder_alloc_output_buffer:
+ * gst_video_encoder_allocate_output_buffer:
* @encoder: a #GstVideoEncoder
* @size: size of the buffer
*
* Returns: (transfer full): allocated buffer
*/
GstBuffer *
-gst_video_encoder_alloc_output_buffer (GstVideoEncoder * encoder, gsize size)
+gst_video_encoder_allocate_output_buffer (GstVideoEncoder * encoder, gsize size)
{
GstBuffer *buffer;
if (G_UNLIKELY (encoder->priv->output_state_changed
|| (encoder->priv->output_state
&& gst_pad_check_reconfigure (encoder->srcpad))))
- gst_video_encoder_set_src_caps (encoder);
+ gst_video_encoder_negotiate (encoder);
buffer =
gst_buffer_new_allocate (encoder->priv->allocator, size,
}
/**
- * gst_video_encoder_alloc_output_frame:
+ * gst_video_encoder_allocate_output_frame:
* @encoder: a #GstVideoEncoder
* @frame: a #GstVideoCodecFrame
* @size: size of the buffer
* Returns: %GST_FLOW_OK if an output buffer could be allocated
*/
GstFlowReturn
-gst_video_encoder_alloc_output_frame (GstVideoEncoder *
+gst_video_encoder_allocate_output_frame (GstVideoEncoder *
encoder, GstVideoCodecFrame * frame, gsize size)
{
g_return_val_if_fail (frame->output_buffer == NULL, GST_FLOW_ERROR);
g_return_val_if_fail (size > 0, GST_FLOW_ERROR);
+ GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
if (G_UNLIKELY (encoder->priv->output_state_changed
|| (encoder->priv->output_state
&& gst_pad_check_reconfigure (encoder->srcpad))))
- gst_video_encoder_set_src_caps (encoder);
+ gst_video_encoder_negotiate (encoder);
- GST_LOG_OBJECT (encoder, "alloc buffer size %d", size);
- GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
+ GST_LOG_OBJECT (encoder, "alloc buffer size %" G_GSIZE_FORMAT, size);
frame->output_buffer =
gst_buffer_new_allocate (encoder->priv->allocator, size,
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
- if (G_UNLIKELY (priv->output_state_changed))
- gst_video_encoder_set_src_caps (encoder);
+ if (G_UNLIKELY (priv->output_state_changed || (priv->output_state
+ && gst_pad_check_reconfigure (encoder->srcpad))))
+ gst_video_encoder_negotiate (encoder);
+
if (G_UNLIKELY (priv->output_state == NULL))
goto no_output_state;