[MOVED FROM BAD 27/57] gst/flv/: Get an approximate duration of the file by looking...
authorSebastian Dröge <slomo@circular-chaos.org>
Thu, 9 Oct 2008 16:20:26 +0000 (16:20 +0000)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 12 May 2009 19:20:55 +0000 (21:20 +0200)
Original commit message from CVS:
* gst/flv/gstflvdemux.c: (gst_flv_demux_loop):
* gst/flv/gstflvparse.c: (gst_flv_parse_tag_timestamp):
* gst/flv/gstflvparse.h:
Get an approximate duration of the file by looking at the timestamp
of the last tag in pull mode. If we get (maybe better) duration from
metadata later we'll use that instead.

gst/flv/gstflvdemux.c
gst/flv/gstflvparse.c
gst/flv/gstflvparse.h

index dc148507f2fa9c7d7a99697fc00e404bdb2498ff..8cc74f1d6e2488d5fc61b36f988bd78f06c1cf9e 100644 (file)
@@ -443,6 +443,38 @@ gst_flv_demux_loop (GstPad * pad)
         break;
       default:
         ret = gst_flv_demux_pull_header (pad, demux);
+
+        /* If we parsed the header successfully try to get an
+         * approximate duration by looking at the last tag's timestamp */
+        if (ret == GST_FLOW_OK) {
+          gint64 size;
+          GstFormat fmt = GST_FORMAT_BYTES;
+
+          if (gst_pad_query_peer_duration (pad, &fmt, &size) &&
+              fmt == GST_FORMAT_BYTES && size != -1 && size > FLV_HEADER_SIZE) {
+            GstBuffer *buffer;
+
+            if (gst_flv_demux_pull_range (demux, pad, size - 4, 4,
+                    &buffer) == GST_FLOW_OK) {
+              guint32 prev_tag_size =
+                  GST_READ_UINT32_BE (GST_BUFFER_DATA (buffer));
+
+              gst_buffer_unref (buffer);
+
+              if (size - 4 - prev_tag_size > FLV_HEADER_SIZE &&
+                  prev_tag_size >= 8 &&
+                  gst_flv_demux_pull_range (demux, pad,
+                      size - prev_tag_size - 4, prev_tag_size,
+                      &buffer) == GST_FLOW_OK) {
+                demux->duration =
+                    gst_flv_parse_tag_timestamp (demux,
+                    GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
+
+                gst_buffer_unref (buffer);
+              }
+            }
+          }
+        }
     }
 
     /* pause if something went wrong */
index fd51cbfe408c67645184de2ad43371c605039842..c5545054ecdf2b294c085f8067aeabdf4987d05f 100644 (file)
@@ -1006,6 +1006,37 @@ beach:
   return ret;
 }
 
+GstClockTime
+gst_flv_parse_tag_timestamp (GstFLVDemux * demux, const guint8 * data,
+    size_t data_size)
+{
+  guint32 pts = 0, pts_ext = 0;
+
+  if (data[0] != 9 && data[0] != 8 && data[0] != 18) {
+    GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  if (FLV_GET_BEUI24 (data + 1, data_size - 1) != data_size - 11) {
+    GST_WARNING_OBJECT (demux, "Invalid tag");
+    return GST_CLOCK_TIME_NONE;
+  }
+
+  data += 4;
+
+  GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X", data[0], data[1],
+      data[2], data[3]);
+
+  /* Grab timestamp of tag tag */
+  pts = FLV_GET_BEUI24 (data, data_size);
+  /* read the pts extension to 32 bits integer */
+  pts_ext = GST_READ_UINT8 (data + 3);
+  /* Combine them */
+  pts |= pts_ext << 24;
+
+  return pts * GST_MSECOND;
+}
+
 GstFlowReturn
 gst_flv_parse_tag_type (GstFLVDemux * demux, const guint8 * data,
     size_t data_size)
index 7b9d498efc2c330426294a494558319adf810b3f..0dfeaa976289283a3fa2cc7841c255c468638e1a 100644 (file)
@@ -38,5 +38,7 @@ GstFlowReturn gst_flv_parse_tag_type (GstFLVDemux * demux, const guint8 * data,
 GstFlowReturn gst_flv_parse_header (GstFLVDemux * demux, const guint8 * data,
     size_t data_size);
 
+GstClockTime gst_flv_parse_tag_timestamp (GstFLVDemux *demux, const guint8 *data, size_t data_size);
+
 G_END_DECLS
 #endif /* __FLV_PARSE_H__ */