eqMerge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gstreamer.git] / gst / matroska / matroska-read-common.c
index d2c2bea..2f147ea 100644 (file)
@@ -58,7 +58,7 @@ GST_DEBUG_CATEGORY (matroskareadcommon_debug);
 
 static gboolean
 gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
-    guint8 ** data_out, guint * size_out,
+    gpointer * data_out, gsize * size_out,
     GstMatroskaTrackCompressionAlgorithm algo)
 {
   guint8 *new_data = NULL;
@@ -237,8 +237,8 @@ gst_matroska_decode_content_encodings (GArray * encodings)
   for (i = 0; i < encodings->len; i++) {
     GstMatroskaTrackEncoding *enc =
         &g_array_index (encodings, GstMatroskaTrackEncoding, i);
-    guint8 *data = NULL;
-    guint size;
+    gpointer data = NULL;
+    gsize size;
 
     if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
         == 0)
@@ -270,11 +270,11 @@ gst_matroska_decode_content_encodings (GArray * encodings)
 }
 
 gboolean
-gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
-    guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
+gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
+    gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
 {
-  guint8 *data;
-  guint size;
+  gpointer data;
+  gsize size;
   gboolean ret = TRUE;
   gint i;
 
@@ -288,8 +288,8 @@ gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
   for (i = 0; i < encodings->len; i++) {
     GstMatroskaTrackEncoding *enc =
         &g_array_index (encodings, GstMatroskaTrackEncoding, i);
-    guint8 *new_data = NULL;
-    guint new_size = 0;
+    gpointer new_data = NULL;
+    gsize new_size = 0;
 
     if ((enc->scope & scope) == 0)
       continue;
@@ -430,21 +430,31 @@ gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
     gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
     gst_tag_list_free (taglist);
   } else {
+    GstEvent *tag_event = gst_event_new_tag (taglist);
+    gint i;
+
     /* hm, already sent, no need to cache and wait anymore */
     GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT,
         taglist);
-    gst_element_found_tags (el, taglist);
+
+    for (i = 0; i < common->src->len; i++) {
+      GstMatroskaTrackContext *stream;
+
+      stream = g_ptr_array_index (common->src, i);
+      gst_pad_push_event (stream->pad, gst_event_ref (tag_event));
+    }
+
+    gst_event_unref (tag_event);
   }
 }
 
 gint64
 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
 {
-  GstFormat fmt = GST_FORMAT_BYTES;
   gint64 end = -1;
 
-  if (!gst_pad_query_peer_duration (common->sinkpad, &fmt, &end) ||
-      fmt != GST_FORMAT_BYTES || end < 0)
+  if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES,
+          &end) || end < 0)
     GST_DEBUG_OBJECT (common, "no upstream length");
 
   return end;
@@ -569,7 +579,9 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
   if (filename && mimetype && data && datalen > 0) {
     GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
     GstBuffer *tagbuffer = NULL;
-    GstCaps *caps;
+    GstSample *tagsample = NULL;
+    GstStructure *info = NULL;
+    GstCaps *caps = NULL;
     gchar *filename_lc = g_utf8_strdown (filename, -1);
 
     GST_DEBUG_OBJECT (common, "Creating tag for attachment with "
@@ -595,47 +607,52 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
 
     /* First try to create an image tag buffer from this */
     if (image_type != GST_TAG_IMAGE_TYPE_NONE) {
-      tagbuffer =
-          gst_tag_image_data_to_image_buffer (data, datalen, image_type);
+      tagsample =
+          gst_tag_image_data_to_image_sample (data, datalen, image_type);
 
-      if (!tagbuffer)
+      if (!tagsample)
         image_type = GST_TAG_IMAGE_TYPE_NONE;
+      else {
+        data = NULL;
+        tagbuffer = gst_buffer_ref (gst_sample_get_buffer (tagsample));
+        caps = gst_caps_ref (gst_sample_get_caps (tagsample));
+        info = gst_structure_copy (gst_sample_get_info (tagsample));
+        gst_sample_unref (tagsample);
+      }
     }
 
     /* if this failed create an attachment buffer */
     if (!tagbuffer) {
-      tagbuffer = gst_buffer_new_and_alloc (datalen);
-
-      memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen);
-      GST_BUFFER_SIZE (tagbuffer) = datalen;
+      tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen);
 
       caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
       if (caps == NULL)
-        caps = gst_caps_new_simple (mimetype, NULL);
-      gst_buffer_set_caps (tagbuffer, caps);
-      gst_caps_unref (caps);
+        caps = gst_caps_new_empty_simple (mimetype);
     }
 
-    /* Set filename and description on the caps */
-    caps = GST_BUFFER_CAPS (tagbuffer);
-    gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL);
+    /* Set filename and description in the info */
+    if (info == NULL)
+      info = gst_structure_new_empty ("GstTagImageInfo");
+
+    gst_structure_set (info, "filename", G_TYPE_STRING, filename, NULL);
     if (description)
-      gst_caps_set_simple (caps, "description", G_TYPE_STRING, description,
-          NULL);
+      gst_structure_set (info, "description", G_TYPE_STRING, description, NULL);
+
+    tagsample = gst_sample_new (tagbuffer, caps, NULL, info);
 
     GST_DEBUG_OBJECT (common,
-        "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps);
+        "Created attachment sample: %" GST_PTR_FORMAT, tagsample);
 
     /* and append to the tag list */
     if (image_type != GST_TAG_IMAGE_TYPE_NONE)
-      gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagbuffer,
+      gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagsample,
           NULL);
     else
       gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT,
-          tagbuffer, NULL);
+          tagsample, NULL);
 
-    /* the tag list adds it own ref */
-    gst_buffer_unref (tagbuffer);
+    /* the list adds it own ref */
+    gst_buffer_unref (tagsample);
   }
 
   g_free (filename);
@@ -661,7 +678,7 @@ gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common,
     return ret;
   }
 
-  taglist = gst_tag_list_new ();
+  taglist = gst_tag_list_new_empty ();
 
   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
@@ -1000,11 +1017,11 @@ gst_matroska_read_common_parse_index_cuetrack (GstMatroskaReadCommon * common,
     }
   }
 
-  if ((ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED)
+  if ((ret == GST_FLOW_OK || ret == GST_FLOW_EOS)
       && idx.pos != (guint64) - 1 && idx.track > 0) {
     g_array_append_val (common->index, idx);
     (*nentries)++;
-  } else if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED) {
+  } else if (ret == GST_FLOW_OK || ret == GST_FLOW_EOS) {
     GST_DEBUG_OBJECT (common, "CueTrackPositions without valid content");
   }
 
@@ -1156,6 +1173,7 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
     gint track_num;
     GstMatroskaTrackContext *ctx;
 
+#if 0
     if (common->element_index) {
       gint writer_id;
 
@@ -1183,6 +1201,7 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common,
           GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, idx->time,
           GST_FORMAT_BYTES, idx->pos + common->ebml_segment_start, NULL);
     }
+#endif
 
     if (idx->track == 0)
       continue;
@@ -1298,9 +1317,7 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
           break;
 
         GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text));
-        taglist = gst_tag_list_new ();
-        gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text,
-            NULL);
+        taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL);
         gst_matroska_read_common_found_global_tag (common, el, taglist);
         g_free (text);
         break;
@@ -1331,7 +1348,7 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
     dur_u = gst_gdouble_to_guint64 (dur_f *
         gst_guint64_to_gdouble (common->time_scale));
     if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64)
-      gst_segment_set_duration (&common->segment, GST_FORMAT_TIME, dur_u);
+      common->segment.duration = dur_u;
   }
 
   DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
@@ -1536,7 +1553,7 @@ gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common,
     return ret;
   }
 
-  taglist = gst_tag_list_new ();
+  taglist = gst_tag_list_new_empty ();
 
   while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
     if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
@@ -1569,9 +1586,10 @@ static GstFlowReturn
 gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
     peek, const guint8 ** data)
 {
-  *data = gst_adapter_peek (common->adapter, peek);
+  /* Caller needs to gst_adapter_unmap. */
+  *data = gst_adapter_map (common->adapter, peek);
   if (*data == NULL)
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
 
   return GST_FLOW_OK;
 }
@@ -1589,19 +1607,26 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
    * We do it mainly to avoid pulling buffers of 1 byte all the time */
   if (common->cached_buffer) {
     guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
-    guint cache_size = GST_BUFFER_SIZE (common->cached_buffer);
+    gsize cache_size = gst_buffer_get_size (common->cached_buffer);
 
     if (cache_offset <= common->offset &&
         (common->offset + size) <= (cache_offset + cache_size)) {
       if (p_buf)
-        *p_buf = gst_buffer_create_sub (common->cached_buffer,
-            common->offset - cache_offset, size);
-      if (bytes)
-        *bytes = GST_BUFFER_DATA (common->cached_buffer) + common->offset -
-            cache_offset;
+        *p_buf = gst_buffer_copy_region (common->cached_buffer,
+            GST_BUFFER_COPY_ALL, common->offset - cache_offset, size);
+      if (bytes) {
+        if (!common->cached_data)
+          common->cached_data = gst_buffer_map (common->cached_buffer,
+              NULL, NULL, GST_MAP_READ);
+        *bytes = common->cached_data + common->offset - cache_offset;
+      }
       return GST_FLOW_OK;
     }
     /* not enough data in the cache, free cache and get a new one */
+    if (common->cached_data) {
+      gst_buffer_unmap (common->cached_buffer, common->cached_data, -1);
+      common->cached_data = NULL;
+    }
     gst_buffer_unref (common->cached_buffer);
     common->cached_buffer = NULL;
   }
@@ -1614,11 +1639,15 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
     return ret;
   }
 
-  if (GST_BUFFER_SIZE (common->cached_buffer) >= size) {
+  if (gst_buffer_get_size (common->cached_buffer) >= size) {
     if (p_buf)
-      *p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size);
-    if (bytes)
-      *bytes = GST_BUFFER_DATA (common->cached_buffer);
+      *p_buf = gst_buffer_copy_region (common->cached_buffer,
+          GST_BUFFER_COPY_ALL, 0, size);
+    if (bytes) {
+      common->cached_data = gst_buffer_map (common->cached_buffer,
+          NULL, NULL, GST_MAP_READ);
+      *bytes = common->cached_data;
+    }
     return GST_FLOW_OK;
   }
 
@@ -1639,10 +1668,10 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
     return ret;
   }
 
-  if (GST_BUFFER_SIZE (common->cached_buffer) < size) {
+  if (gst_buffer_get_size (common->cached_buffer) < size) {
     GST_WARNING_OBJECT (common, "Dropping short buffer at offset %"
         G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", common->offset,
-        size, GST_BUFFER_SIZE (common->cached_buffer));
+        size, gst_buffer_get_size (common->cached_buffer));
 
     gst_buffer_unref (common->cached_buffer);
     common->cached_buffer = NULL;
@@ -1650,13 +1679,17 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
       *p_buf = NULL;
     if (bytes)
       *bytes = NULL;
-    return GST_FLOW_UNEXPECTED;
+    return GST_FLOW_EOS;
   }
 
   if (p_buf)
-    *p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size);
-  if (bytes)
-    *bytes = GST_BUFFER_DATA (common->cached_buffer);
+    *p_buf = gst_buffer_copy_region (common->cached_buffer,
+        GST_BUFFER_COPY_ALL, 0, size);
+  if (bytes) {
+    common->cached_data = gst_buffer_map (common->cached_buffer,
+        NULL, NULL, GST_MAP_READ);
+    *bytes = common->cached_data;
+  }
 
   return GST_FLOW_OK;
 }
@@ -1682,9 +1715,15 @@ GstFlowReturn
 gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
     GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
 {
-  return gst_ebml_peek_id_length (_id, _length, _needed,
+  GstFlowReturn ret;
+
+  ret = gst_ebml_peek_id_length (_id, _length, _needed,
       (GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
       el, common->offset);
+
+  gst_adapter_unmap (common->adapter);
+
+  return ret;
 }
 
 static GstFlowReturn
@@ -1840,7 +1879,7 @@ gst_matroska_read_common_read_track_encoding (GstMatroskaReadCommon * common,
   }
 
   DEBUG_ELEMENT_STOP (common, ebml, "ContentEncoding", ret);
-  if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
+  if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
     return ret;
 
   /* TODO: Check if the combination of values is valid */
@@ -1885,7 +1924,7 @@ gst_matroska_read_common_read_track_encodings (GstMatroskaReadCommon * common,
   }
 
   DEBUG_ELEMENT_STOP (common, ebml, "ContentEncodings", ret);
-  if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED)
+  if (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)
     return ret;
 
   /* Sort encodings according to their order */