make %u in all request pad templates
[platform/upstream/gst-plugins-good.git] / gst / matroska / matroska-mux.c
index 2a639d4..d48d56c 100644 (file)
@@ -95,7 +95,7 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
  */
 
 static GstStaticPadTemplate videosink_templ =
-    GST_STATIC_PAD_TEMPLATE ("video_%d",
+    GST_STATIC_PAD_TEMPLATE ("video_%u",
     GST_PAD_SINK,
     GST_PAD_REQUEST,
     GST_STATIC_CAPS ("video/mpeg, "
@@ -140,7 +140,7 @@ static GstStaticPadTemplate videosink_templ =
  * * require codec data, etc as needed
  */
 static GstStaticPadTemplate audiosink_templ =
-    GST_STATIC_PAD_TEMPLATE ("audio_%d",
+    GST_STATIC_PAD_TEMPLATE ("audio_%u",
     GST_PAD_SINK,
     GST_PAD_REQUEST,
     GST_STATIC_CAPS ("audio/mpeg, "
@@ -205,7 +205,7 @@ static GstStaticPadTemplate audiosink_templ =
     );
 
 static GstStaticPadTemplate subtitlesink_templ =
-GST_STATIC_PAD_TEMPLATE ("subtitle_%d",
+GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
     GST_PAD_SINK,
     GST_PAD_REQUEST,
     GST_STATIC_CAPS ("subtitle/x-kate"));
@@ -391,6 +391,8 @@ gst_matroska_mux_finalize (GObject * object)
 {
   GstMatroskaMux *mux = GST_MATROSKA_MUX (object);
 
+  gst_event_replace (&mux->force_key_unit_event, NULL);
+
   gst_object_unref (mux->collect);
   gst_object_unref (mux->ebml_write);
   if (mux->writing_app)
@@ -656,12 +658,29 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event)
       event = NULL;
       break;
     }
-    case GST_EVENT_NEWSEGMENT:
-      /* We don't support NEWSEGMENT events */
-      ret = FALSE;
-      gst_event_unref (event);
-      event = NULL;
+    case GST_EVENT_NEWSEGMENT:{
+      GstFormat format;
+
+      gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
+          NULL);
+      if (format != GST_FORMAT_TIME) {
+        ret = FALSE;
+        gst_event_unref (event);
+        event = NULL;
+      }
       break;
+    }
+    case GST_EVENT_CUSTOM_DOWNSTREAM:{
+      const GstStructure *structure;
+
+      structure = gst_event_get_structure (event);
+      if (gst_structure_has_name (structure, "GstForceKeyUnit")) {
+        gst_event_replace (&mux->force_key_unit_event, NULL);
+        mux->force_key_unit_event = event;
+        event = NULL;
+      }
+      break;
+    }
     default:
       break;
   }
@@ -777,15 +796,14 @@ skip_details:
   if (!strcmp (mimetype, "video/x-raw-yuv")) {
     context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
     gst_structure_get_fourcc (structure, "format", &videocontext->fourcc);
-  } else if (!strcmp (mimetype, "image/jpeg")) {
-    context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
   } else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
       ||!strcmp (mimetype, "video/x-huffyuv")
       || !strcmp (mimetype, "video/x-divx")
       || !strcmp (mimetype, "video/x-dv")
       || !strcmp (mimetype, "video/x-h263")
       || !strcmp (mimetype, "video/x-msmpeg")
-      || !strcmp (mimetype, "video/x-wmv")) {
+      || !strcmp (mimetype, "video/x-wmv")
+      || !strcmp (mimetype, "image/jpeg")) {
     gst_riff_strf_vids *bih;
     gint size = sizeof (gst_riff_strf_vids);
     guint32 fourcc = 0;
@@ -842,6 +860,8 @@ skip_details:
           fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '3');
         }
       }
+    } else if (!strcmp (mimetype, "image/jpeg")) {
+      fourcc = GST_MAKE_FOURCC ('M', 'J', 'P', 'G');
     }
 
     if (!fourcc)
@@ -1831,13 +1851,13 @@ gst_matroska_mux_request_new_pad (GstElement * element,
   GstMatroskaTrackContext *context = NULL;
   gint pad_id;
 
-  if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
+  if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
     /* don't mix named and unnamed pads, if the pad already exists we fail when
      * trying to add it */
-    if (req_name != NULL && sscanf (req_name, "audio_%d", &pad_id) == 1) {
+    if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
       pad_name = req_name;
     } else {
-      name = g_strdup_printf ("audio_%d", mux->num_a_streams++);
+      name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
       pad_name = name;
     }
     setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
@@ -1845,13 +1865,13 @@ gst_matroska_mux_request_new_pad (GstElement * element,
         g_new0 (GstMatroskaTrackAudioContext, 1);
     context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
     context->name = g_strdup ("Audio");
-  } else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
+  } else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
     /* don't mix named and unnamed pads, if the pad already exists we fail when
      * trying to add it */
-    if (req_name != NULL && sscanf (req_name, "video_%d", &pad_id) == 1) {
+    if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
       pad_name = req_name;
     } else {
-      name = g_strdup_printf ("video_%d", mux->num_v_streams++);
+      name = g_strdup_printf ("video_%u", mux->num_v_streams++);
       pad_name = name;
     }
     setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
@@ -1859,13 +1879,13 @@ gst_matroska_mux_request_new_pad (GstElement * element,
         g_new0 (GstMatroskaTrackVideoContext, 1);
     context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
     context->name = g_strdup ("Video");
-  } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%d")) {
+  } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%u")) {
     /* don't mix named and unnamed pads, if the pad already exists we fail when
      * trying to add it */
-    if (req_name != NULL && sscanf (req_name, "subtitle_%d", &pad_id) == 1) {
+    if (req_name != NULL && sscanf (req_name, "subtitle_%u", &pad_id) == 1) {
       pad_name = req_name;
     } else {
-      name = g_strdup_printf ("subtitle_%d", mux->num_t_streams++);
+      name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++);
       pad_name = name;
     }
     setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
@@ -2204,6 +2224,10 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
       child = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKENTRY);
       gst_matroska_mux_track_header (mux, collect_pad->track);
       gst_ebml_write_master_finish (ebml, child);
+      /* some remaing pad/track setup */
+      collect_pad->default_duration_scaled =
+          gst_util_uint64_scale (collect_pad->track->default_duration,
+          1, mux->time_scale);
     }
   }
   gst_ebml_write_master_finish (ebml, master);
@@ -2474,6 +2498,10 @@ gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
             collect_pad->buffer = NULL;
             return NULL;
           } else {
+            GST_LOG_OBJECT (mux, "buffer ts %" GST_TIME_FORMAT " -> %"
+                GST_TIME_FORMAT " running time",
+                GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (collect_pad->buffer)),
+                GST_TIME_ARGS (time));
             collect_pad->buffer =
                 gst_buffer_make_metadata_writable (collect_pad->buffer);
             GST_BUFFER_TIMESTAMP (collect_pad->buffer) = time;
@@ -2567,7 +2595,7 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
 
     next_parse_offset = GST_READ_UINT32_BE (data + 5);
 
-    if (G_UNLIKELY (next_parse_offset == 0))
+    if (G_UNLIKELY (next_parse_offset == 0 || next_parse_offset > size))
       break;
 
     data += next_parse_offset;
@@ -2688,13 +2716,20 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
   }
 
   if (mux->cluster) {
-    /* start a new cluster at every keyframe or when we may be reaching the
-     * limit of the relative timestamp */
+    /* start a new cluster at every keyframe, at every GstForceKeyUnit event,
+     * or when we may be reaching the limit of the relative timestamp */
     if (mux->cluster_time +
         mux->max_cluster_duration < GST_BUFFER_TIMESTAMP (buf)
-        || is_video_keyframe) {
+        || is_video_keyframe || mux->force_key_unit_event) {
       if (!mux->streamable)
         gst_ebml_write_master_finish (ebml, mux->cluster);
+
+      /* Forward the GstForceKeyUnit event after finishing the cluster */
+      if (mux->force_key_unit_event) {
+        gst_pad_push_event (mux->srcpad, mux->force_key_unit_event);
+        mux->force_key_unit_event = NULL;
+      }
+
       mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
       mux->cluster_pos = ebml->pos;
       gst_ebml_write_set_cache (ebml, 0x20);
@@ -2767,9 +2802,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
 
   /* Check if the duration differs from the default duration. */
   write_duration = FALSE;
-  block_duration = GST_BUFFER_DURATION (buf);
+  block_duration = 0;
   if (GST_BUFFER_DURATION_IS_VALID (buf)) {
-    if (block_duration != collect_pad->track->default_duration) {
+    block_duration = gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
+        1, mux->time_scale);
+
+    /* small difference should be ok. */
+    if (block_duration > collect_pad->default_duration_scaled + 1 ||
+        block_duration < collect_pad->default_duration_scaled - 1) {
       write_duration = TRUE;
     }
   }
@@ -2810,10 +2850,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
     hdr =
         gst_matroska_mux_create_buffer_header (collect_pad->track,
         relative_timestamp, 0);
-    if (write_duration) {
-      gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION,
-          gst_util_uint64_scale (block_duration, 1, mux->time_scale));
-    }
+    if (write_duration)
+      gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
     gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
         GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
     gst_ebml_write_buffer (ebml, hdr);