qtmux: add subtitle support to qtmuxmap structures
authorThiago Santos <ts.santos@sisa.samsung.com>
Wed, 5 Feb 2014 13:27:54 +0000 (10:27 -0300)
committerThiago Santos <ts.santos@sisa.samsung.com>
Fri, 7 Feb 2014 16:10:24 +0000 (13:10 -0300)
adds basic stubs for subtitle support around the qtmux and
qtmuxmap structures. Still no real subtitle implemented, but
basic functions in place

https://bugzilla.gnome.org/show_bug.cgi?id=581295

gst/isomp4/gstqtmux.c
gst/isomp4/gstqtmux.h
gst/isomp4/gstqtmuxmap.c
gst/isomp4/gstqtmuxmap.h

index 3231963..085542b 100644 (file)
@@ -235,7 +235,8 @@ gst_qt_mux_base_init (gpointer g_class)
   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
   GstQTMuxClass *klass = (GstQTMuxClass *) g_class;
   GstQTMuxClassParams *params;
-  GstPadTemplate *videosinktempl, *audiosinktempl, *srctempl;
+  GstPadTemplate *videosinktempl, *audiosinktempl, *subtitlesinktempl;
+  GstPadTemplate *srctempl;
   gchar *longname, *description;
 
   params =
@@ -270,6 +271,12 @@ gst_qt_mux_base_init (gpointer g_class)
     gst_element_class_add_pad_template (element_class, videosinktempl);
   }
 
+  if (params->subtitle_sink_caps) {
+    subtitlesinktempl = gst_pad_template_new ("subtitle_%u",
+        GST_PAD_SINK, GST_PAD_REQUEST, params->subtitle_sink_caps);
+    gst_element_class_add_pad_template (element_class, subtitlesinktempl);
+  }
+
   klass->format = params->prop->format;
 }
 
@@ -2478,11 +2485,11 @@ gst_qtmux_caps_is_subset_full (GstQTMux * qtmux, GstCaps * subset,
 }
 
 static gboolean
-gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
+gst_qt_mux_audio_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
 {
+  GstPad *pad = qtpad->collect.pad;
   GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
   GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
-  GstQTPad *qtpad = NULL;
   GstStructure *structure;
   const gchar *mimetype;
   gint rate, channels;
@@ -2494,10 +2501,6 @@ gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
   gint constant_size = 0;
   const gchar *stream_format;
 
-  /* find stream data */
-  qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
-  g_assert (qtpad);
-
   qtpad->prepare_buf_func = NULL;
 
   /* does not go well to renegotiate stream mid-way, unless
@@ -2794,11 +2797,11 @@ adjust_rate (guint64 rate)
 }
 
 static gboolean
-gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
+gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
 {
+  GstPad *pad = qtpad->collect.pad;
   GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
   GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
-  GstQTPad *qtpad = NULL;
   GstStructure *structure;
   const gchar *mimetype;
   gint width, height, depth = -1;
@@ -2813,10 +2816,6 @@ gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
   gboolean sync = FALSE;
   int par_num, par_den;
 
-  /* find stream data */
-  qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
-  g_assert (qtpad);
-
   qtpad->prepare_buf_func = NULL;
 
   /* does not go well to renegotiate stream mid-way, unless
@@ -3139,6 +3138,57 @@ refuse_renegotiation:
 }
 
 static gboolean
+gst_qt_mux_subtitle_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
+{
+  GstPad *pad = qtpad->collect.pad;
+  GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
+
+  qtpad->prepare_buf_func = NULL;
+
+  /* does not go well to renegotiate stream mid-way, unless
+   * the old caps are a subset of the new one (this means upstream
+   * added more info to the caps, as both should be 'fixed' caps) */
+  if (qtpad->fourcc) {
+    GstCaps *current_caps;
+
+    current_caps = gst_pad_get_current_caps (pad);
+    g_assert (caps != NULL);
+
+    if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
+      gst_caps_unref (current_caps);
+      goto refuse_renegotiation;
+    }
+    GST_DEBUG_OBJECT (qtmux,
+        "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
+        GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, current_caps);
+    gst_caps_unref (current_caps);
+  }
+
+  GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
+      GST_DEBUG_PAD_NAME (pad), caps);
+
+  /* subtitles default */
+  qtpad->is_out_of_order = FALSE;
+  qtpad->sync = FALSE;
+
+  /* TODO fill me */
+
+  gst_object_unref (qtmux);
+  /* not implemented */
+  return FALSE;
+
+  /* ERRORS */
+refuse_renegotiation:
+  {
+    GST_WARNING_OBJECT (qtmux,
+        "pad %s refused renegotiation to %" GST_PTR_FORMAT, GST_PAD_NAME (pad),
+        caps);
+    gst_object_unref (qtmux);
+    return FALSE;
+  }
+}
+
+static gboolean
 gst_qt_mux_sink_event (GstCollectPads * pads, GstCollectData * data,
     GstEvent * event, gpointer user_data)
 {
@@ -3161,7 +3211,7 @@ gst_qt_mux_sink_event (GstCollectPads * pads, GstCollectData * data,
       g_assert (collect_pad);
       g_assert (collect_pad->set_caps);
 
-      ret = collect_pad->set_caps (pad, caps);
+      ret = collect_pad->set_caps (collect_pad, caps);
       gst_event_unref (event);
       event = NULL;
       break;
@@ -3253,7 +3303,7 @@ gst_qt_mux_request_new_pad (GstElement * element,
   GstQTMux *qtmux = GST_QT_MUX_CAST (element);
   GstQTPad *collect_pad;
   GstPad *newpad;
-  gboolean audio;
+  GstQTPadSetCapsFunc setcaps_func;
   gchar *name;
   gint pad_id;
 
@@ -3264,19 +3314,26 @@ gst_qt_mux_request_new_pad (GstElement * element,
     goto too_late;
 
   if (templ == gst_element_class_get_pad_template (klass, "audio_%u")) {
-    audio = TRUE;
+    setcaps_func = gst_qt_mux_audio_sink_set_caps;
     if (req_name != NULL && sscanf (req_name, "audio_%u", &pad_id) == 1) {
       name = g_strdup (req_name);
     } else {
       name = g_strdup_printf ("audio_%u", qtmux->audio_pads++);
     }
   } else if (templ == gst_element_class_get_pad_template (klass, "video_%u")) {
-    audio = FALSE;
+    setcaps_func = gst_qt_mux_video_sink_set_caps;
     if (req_name != NULL && sscanf (req_name, "video_%u", &pad_id) == 1) {
       name = g_strdup (req_name);
     } else {
       name = g_strdup_printf ("video_%u", qtmux->video_pads++);
     }
+  } else if (templ == gst_element_class_get_pad_template (klass, "subtitle_%u")) {
+    setcaps_func = gst_qt_mux_subtitle_sink_set_caps;
+    if (req_name != NULL && sscanf (req_name, "subtitle_%u", &pad_id) == 1) {
+      name = g_strdup (req_name);
+    } else {
+      name = g_strdup_printf ("subtitle_%u", qtmux->subtitle_pads++);
+    }
   } else
     goto wrong_template;
 
@@ -3296,10 +3353,7 @@ gst_qt_mux_request_new_pad (GstElement * element,
   qtmux->sinkpads = g_slist_append (qtmux->sinkpads, collect_pad);
 
   /* set up pad functions */
-  if (audio)
-    collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps);
-  else
-    collect_pad->set_caps = GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps);
+  collect_pad->set_caps = setcaps_func;
 
   gst_pad_set_active (newpad, TRUE);
   gst_element_add_pad (element, newpad);
@@ -3506,6 +3560,7 @@ gst_qt_mux_register (GstPlugin * plugin)
 
   while (TRUE) {
     GstQTMuxFormatProp *prop;
+    GstCaps *subtitle_caps;
 
     prop = &gst_qt_mux_format_list[i];
     format = prop->format;
@@ -3518,6 +3573,12 @@ gst_qt_mux_register (GstPlugin * plugin)
     params->src_caps = gst_static_caps_get (&prop->src_caps);
     params->video_sink_caps = gst_static_caps_get (&prop->video_sink_caps);
     params->audio_sink_caps = gst_static_caps_get (&prop->audio_sink_caps);
+    subtitle_caps = gst_static_caps_get (&prop->subtitle_sink_caps);
+    if (!gst_caps_is_equal (subtitle_caps, GST_CAPS_NONE)) {
+      params->subtitle_sink_caps = subtitle_caps;
+    } else {
+      gst_caps_unref (subtitle_caps);
+    }
 
     /* create the type now */
     type = g_type_register_static (GST_TYPE_ELEMENT, prop->type_name, &typeinfo,
index e61831d..277283f 100644 (file)
@@ -78,6 +78,8 @@ typedef struct _GstQTPad GstQTPad;
 typedef GstBuffer * (*GstQTPadPrepareBufferFunc) (GstQTPad * pad,
     GstBuffer * buf, GstQTMux * qtmux);
 
+typedef gboolean (*GstQTPadSetCapsFunc) (GstQTPad * pad, GstCaps * caps);
+
 #define QTMUX_NO_OF_TS   10
 
 struct _GstQTPad
@@ -126,7 +128,7 @@ struct _GstQTPad
 
   /* if nothing is set, it won't be called */
   GstQTPadPrepareBufferFunc prepare_buf_func;
-  gboolean (*set_caps) (GstPad * pad, GstCaps * caps);
+  GstQTPadSetCapsFunc set_caps;
 };
 
 typedef enum _GstQTMuxState
@@ -192,7 +194,7 @@ struct _GstQTMux
   gboolean streamable;
 
   /* for request pad naming */
-  guint video_pads, audio_pads;
+  guint video_pads, audio_pads, subtitle_pads;
 };
 
 struct _GstQTMuxClass
@@ -209,6 +211,7 @@ typedef struct _GstQTMuxClassParams
   GstCaps *src_caps;
   GstCaps *video_sink_caps;
   GstCaps *audio_sink_caps;
+  GstCaps *subtitle_sink_caps;
 } GstQTMuxClassParams;
 
 #define GST_QT_MUX_PARAMS_QDATA g_quark_from_static_string("qt-mux-params")
index ff85e09..3cf8136 100644 (file)
@@ -166,8 +166,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
             ADPCM_CAPS " ; "
             "audio/x-alaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
             "audio/x-mulaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
-            AMR_CAPS " ; " ALAC_CAPS)
-      }
+            AMR_CAPS " ; " ALAC_CAPS),
+      GST_STATIC_CAPS_NONE}
   ,
   /* ISO 14496-14: mp42 as ISO base media extension
    * (supersedes original ISO 144996-1 mp41) */
@@ -180,8 +180,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
         GST_STATIC_CAPS ("video/quicktime, variant = (string) iso"),
         GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS ";"
             "video/x-mp4-part," COMMON_VIDEO_CAPS),
-        GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS " ; " ALAC_CAPS)
-      }
+        GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS " ; " ALAC_CAPS),
+      GST_STATIC_CAPS_NONE}
   ,
   /* Microsoft Smooth Streaming fmp4/isml */
   /* TODO add WMV/WMA support */
@@ -193,8 +193,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
         "GstISMLMux",
         GST_STATIC_CAPS ("video/quicktime, variant = (string) iso-fragmented"),
         GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS),
-        GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS)
-      }
+        GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS),
+      GST_STATIC_CAPS_NONE}
   ,
   /* 3GPP Technical Specification 26.244 V7.3.0
    * (extended in 3GPP2 File Formats for Multimedia Services) */
@@ -206,8 +206,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
         "Gst3GPPMux",
         GST_STATIC_CAPS ("video/quicktime, variant = (string) 3gpp"),
         GST_STATIC_CAPS (H263_CAPS "; " MPEG4V_CAPS "; " H264_CAPS),
-        GST_STATIC_CAPS (AMR_CAPS "; " MP3_CAPS "; " AAC_CAPS)
-      }
+        GST_STATIC_CAPS (AMR_CAPS "; " MP3_CAPS "; " AAC_CAPS),
+      GST_STATIC_CAPS_NONE}
   ,
   /* ISO 15444-3: Motion-JPEG-2000 (also ISO base media extension) */
   {
@@ -219,8 +219,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
         GST_STATIC_CAPS ("video/mj2"),
         GST_STATIC_CAPS ("image/x-j2c, " COMMON_VIDEO_CAPS "; "
             "image/x-jpc, " COMMON_VIDEO_CAPS),
-        GST_STATIC_CAPS (PCM_CAPS)
-      }
+        GST_STATIC_CAPS (PCM_CAPS),
+      GST_STATIC_CAPS_NONE}
   ,
   {
         GST_QT_MUX_FORMAT_NONE,
index 1c5829c..e578a36 100644 (file)
@@ -69,6 +69,7 @@ typedef struct _GstQTMuxFormatProp
   GstStaticCaps src_caps;
   GstStaticCaps video_sink_caps;
   GstStaticCaps audio_sink_caps;
+  GstStaticCaps subtitle_sink_caps;
 } GstQTMuxFormatProp;
 
 extern GstQTMuxFormatProp gst_qt_mux_format_list[];