gst: Set alignment at the correct place of GstAllocationParams
[platform/upstream/gstreamer.git] / gst-libs / gst / video / gstvideoencoder.c
index bdcf518..5b96569 100644 (file)
 #include "gstvideoutils.h"
 
 #include <gst/video/gstvideometa.h>
+#include <gst/video/gstvideopool.h>
 
 #include <string.h>
 
@@ -141,6 +142,7 @@ struct _GstVideoEncoderPrivate
   /* FIXME : (and introduce a context ?) */
   gboolean drained;
   gboolean at_eos;
+  gboolean do_caps;
 
   gint64 min_latency;
   gint64 max_latency;
@@ -152,7 +154,7 @@ struct _GstVideoEncoderPrivate
 
   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;
@@ -616,6 +618,7 @@ parse_fail:
  * 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
@@ -744,7 +747,57 @@ static gboolean
 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, &params);
+    else
+      gst_query_add_allocation_param (query, allocator, &params);
+
+    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, &params);
+
+    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
@@ -851,7 +904,8 @@ gst_video_encoder_sink_event_default (GstVideoEncoder * encoder,
       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;
@@ -1149,6 +1203,17 @@ gst_video_encoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 
   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);
@@ -1240,6 +1305,15 @@ done:
   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
@@ -1317,8 +1391,16 @@ close_failed:
   }
 }
 
-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;
@@ -1326,7 +1408,7 @@ gst_video_encoder_set_src_caps (GstVideoEncoder * encoder)
   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);
 
@@ -1355,7 +1437,7 @@ gst_video_encoder_set_src_caps (GstVideoEncoder * encoder)
 
   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)) {
@@ -1400,7 +1482,7 @@ no_decide_allocation:
 }
 
 /**
- * gst_video_encoder_alloc_output_buffer:
+ * gst_video_encoder_allocate_output_buffer:
  * @encoder: a #GstVideoEncoder
  * @size: size of the buffer
  *
@@ -1410,7 +1492,7 @@ no_decide_allocation:
  * 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;
 
@@ -1422,7 +1504,7 @@ gst_video_encoder_alloc_output_buffer (GstVideoEncoder * encoder, gsize size)
   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,
@@ -1434,7 +1516,7 @@ gst_video_encoder_alloc_output_buffer (GstVideoEncoder * encoder, gsize size)
 }
 
 /**
- * gst_video_encoder_alloc_output_frame:
+ * gst_video_encoder_allocate_output_frame:
  * @encoder: a #GstVideoEncoder
  * @frame: a #GstVideoCodecFrame
  * @size: size of the buffer
@@ -1449,19 +1531,19 @@ gst_video_encoder_alloc_output_buffer (GstVideoEncoder * encoder, gsize size)
  * 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,
@@ -1507,8 +1589,10 @@ gst_video_encoder_finish_frame (GstVideoEncoder * encoder,
 
   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;