v4l2videoenc: fix type conversion errors
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / gstv4l2videoenc.c
index ee89cec..7c17c74 100644 (file)
@@ -64,13 +64,11 @@ gst_v4l2_video_enc_set_property (GObject * object,
   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (object);
 
   switch (prop_id) {
-    case PROP_OUTPUT_IO_MODE:
-      gst_v4l2_object_set_property_helper (self->v4l2output,
-          prop_id, value, pspec);
-      break;
     case PROP_CAPTURE_IO_MODE:
-      gst_v4l2_object_set_property_helper (self->v4l2capture,
-          prop_id, value, pspec);
+      if (!gst_v4l2_object_set_property_helper (self->v4l2capture,
+              prop_id, value, pspec)) {
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      }
       break;
 
       /* By default, only set on output */
@@ -90,13 +88,11 @@ gst_v4l2_video_enc_get_property (GObject * object,
   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (object);
 
   switch (prop_id) {
-    case PROP_OUTPUT_IO_MODE:
-      gst_v4l2_object_get_property_helper (self->v4l2output,
-          prop_id, value, pspec);
-      break;
     case PROP_CAPTURE_IO_MODE:
-      gst_v4l2_object_get_property_helper (self->v4l2output,
-          PROP_IO_MODE, value, pspec);
+      if (!gst_v4l2_object_get_property_helper (self->v4l2capture,
+              prop_id, value, pspec)) {
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      }
       break;
 
       /* By default read from output */
@@ -278,6 +274,7 @@ gst_v4l2_video_enc_finish (GstVideoEncoder * encoder)
     GstTask *task = encoder->srcpad->task;
 
     /* Wait for the task to be drained */
+    GST_DEBUG_OBJECT (self, "Waiting for encoder stop");
     GST_OBJECT_LOCK (task);
     while (GST_TASK_STATE (task) == GST_TASK_STARTED)
       GST_TASK_WAIT (task);
@@ -321,6 +318,9 @@ gst_v4l2_video_enc_set_format (GstVideoEncoder * encoder,
     if (gst_v4l2_video_enc_finish (encoder) != GST_FLOW_OK)
       return FALSE;
 
+    gst_v4l2_object_stop (self->v4l2output);
+    gst_v4l2_object_stop (self->v4l2capture);
+
     gst_video_codec_state_unref (self->input_state);
     self->input_state = NULL;
   }
@@ -522,6 +522,10 @@ gst_v4l2_video_enc_negotiate (GstVideoEncoder * encoder)
   GST_DEBUG_OBJECT (self, "Negotiating %s profile and level.",
       klass->codec_name);
 
+  /* Only renegotiate on upstream changes */
+  if (self->input_state)
+    return TRUE;
+
   allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_ENCODER_SRC_PAD (encoder));
 
   if (allowed_caps) {
@@ -576,12 +580,6 @@ gst_v4l2_video_enc_negotiate (GstVideoEncoder * encoder)
   if (!GST_VIDEO_ENCODER_CLASS (parent_class)->negotiate (encoder))
     return FALSE;
 
-  if (!gst_buffer_pool_set_active (GST_BUFFER_POOL (self->v4l2capture->pool),
-          TRUE)) {
-    GST_WARNING_OBJECT (self, "Could not activate capture buffer pool.");
-    return FALSE;
-  }
-
   return TRUE;
 
 g_ctrl_failed:
@@ -663,6 +661,15 @@ gst_v4l2_video_enc_loop (GstVideoEncoder * encoder)
   frame = gst_v4l2_video_enc_get_oldest_frame (encoder);
 
   if (frame) {
+    /* At this point, the delta unit buffer flag is already correctly set by
+     * gst_v4l2_buffer_pool_process. Since gst_video_encoder_finish_frame
+     * will overwrite it from GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame),
+     * set that here.
+     */
+    if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT))
+      GST_VIDEO_CODEC_FRAME_UNSET_SYNC_POINT (frame);
+    else
+      GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
     frame->output_buffer = buffer;
     buffer = NULL;
     ret = gst_video_encoder_finish_frame (encoder, frame);
@@ -706,14 +713,15 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
 {
   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
   GstFlowReturn ret = GST_FLOW_OK;
+  GstTaskState task_state;
 
   GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number);
 
   if (G_UNLIKELY (!g_atomic_int_get (&self->active)))
     goto flushing;
 
-  if (gst_pad_get_task_state (GST_VIDEO_DECODER_SRC_PAD (self)) ==
-      GST_TASK_STOPPED) {
+  task_state = gst_pad_get_task_state (GST_VIDEO_ENCODER_SRC_PAD (self));
+  if (task_state == GST_TASK_STOPPED || task_state == GST_TASK_PAUSED) {
     GstBufferPool *pool = GST_BUFFER_POOL (self->v4l2output->pool);
 
     /* It possible that the processing thread stopped due to an error */
@@ -740,6 +748,12 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
         goto activate_failed;
     }
 
+    if (!gst_buffer_pool_set_active
+        (GST_BUFFER_POOL (self->v4l2capture->pool), TRUE)) {
+      GST_WARNING_OBJECT (self, "Could not activate capture buffer pool.");
+      goto activate_failed;
+    }
+
     GST_DEBUG_OBJECT (self, "Starting encoding thread");
 
     /* Start the processing task, when it quits, the task will disable input
@@ -813,6 +827,7 @@ gst_v4l2_video_enc_decide_allocation (GstVideoEncoder *
 {
   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
   GstVideoCodecState *state = gst_video_encoder_get_output_state (encoder);
+  GstCaps *caps;
   GstV4l2Error error = GST_V4L2_ERROR_INIT;
   GstClockTime latency;
   gboolean ret = FALSE;
@@ -821,11 +836,15 @@ gst_v4l2_video_enc_decide_allocation (GstVideoEncoder *
    * GstVideoEncoder have set the width, height and framerate into the state
    * caps. These are needed by the driver to calculate the buffer size and to
    * implement bitrate adaptation. */
-  if (!gst_v4l2_object_set_format (self->v4l2capture, state->caps, &error)) {
+  caps = gst_caps_copy (state->caps);
+  gst_structure_remove_field (gst_caps_get_structure (caps, 0), "colorimetry");
+  if (!gst_v4l2_object_set_format (self->v4l2capture, caps, &error)) {
     gst_v4l2_error (self, &error);
+    gst_caps_unref (caps);
     ret = FALSE;
     goto done;
   }
+  gst_caps_unref (caps);
 
   if (gst_v4l2_object_decide_allocation (self->v4l2capture, query)) {
     GstVideoEncoderClass *enc_class = GST_VIDEO_ENCODER_CLASS (parent_class);
@@ -954,8 +973,9 @@ gst_v4l2_video_enc_sink_event (GstVideoEncoder * encoder, GstEvent * event)
 {
   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (encoder);
   gboolean ret;
+  GstEventType type = GST_EVENT_TYPE (event);
 
-  switch (GST_EVENT_TYPE (event)) {
+  switch (type) {
     case GST_EVENT_FLUSH_START:
       GST_DEBUG_OBJECT (self, "flush start");
       gst_v4l2_object_unlock (self->v4l2output);
@@ -967,7 +987,7 @@ gst_v4l2_video_enc_sink_event (GstVideoEncoder * encoder, GstEvent * event)
 
   ret = GST_VIDEO_ENCODER_CLASS (parent_class)->sink_event (encoder, event);
 
-  switch (GST_EVENT_TYPE (event)) {
+  switch (type) {
     case GST_EVENT_FLUSH_START:
       gst_pad_stop_task (encoder->srcpad);
       GST_DEBUG_OBJECT (self, "flush start done");
@@ -1030,16 +1050,16 @@ gst_v4l2_video_enc_subinstance_init (GTypeInstance * instance, gpointer g_class)
   GstV4l2VideoEnc *self = GST_V4L2_VIDEO_ENC (instance);
 
   self->v4l2output = gst_v4l2_object_new (GST_ELEMENT (self),
+      GST_OBJECT (GST_VIDEO_ENCODER_SINK_PAD (self)),
       V4L2_BUF_TYPE_VIDEO_OUTPUT, klass->default_device,
       gst_v4l2_get_output, gst_v4l2_set_output, NULL);
   self->v4l2output->no_initial_format = TRUE;
   self->v4l2output->keep_aspect = FALSE;
 
   self->v4l2capture = gst_v4l2_object_new (GST_ELEMENT (self),
+      GST_OBJECT (GST_VIDEO_ENCODER_SRC_PAD (self)),
       V4L2_BUF_TYPE_VIDEO_CAPTURE, klass->default_device,
       gst_v4l2_get_input, gst_v4l2_set_input, NULL);
-  self->v4l2capture->no_initial_format = TRUE;
-  self->v4l2output->keep_aspect = FALSE;
 }
 
 static void
@@ -1111,6 +1131,8 @@ gst_v4l2_video_enc_subclass_init (gpointer g_class, gpointer data)
       gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
           cdata->src_caps));
 
+  gst_caps_unref (cdata->sink_caps);
+  gst_caps_unref (cdata->src_caps);
   g_free (cdata);
 }
 
@@ -1130,7 +1152,7 @@ gst_v4l2_is_video_enc (GstCaps * sink_caps, GstCaps * src_caps,
   }
 
   if (gst_caps_is_subset (sink_caps, gst_v4l2_object_get_raw_caps ())
-      && check_caps (src_caps, gst_v4l2_object_get_codec_caps ()))
+      && check_caps (src_caps, codec_caps))
     ret = TRUE;
 
   return ret;