baseparse: use _set_frame_props to configure frame lead_in and lead_out
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 22 Sep 2010 13:07:09 +0000 (15:07 +0200)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Fri, 8 Apr 2011 17:07:08 +0000 (18:07 +0100)
... provided a corresponding decoder with sufficient leading and following
frames to carry out full decoding for a particular segment.

gst/audioparsers/gstaacparse.c
gst/audioparsers/gstac3parse.c
gst/audioparsers/gstamrparse.c
gst/audioparsers/gstbaseparse.c
gst/audioparsers/gstbaseparse.h

index 62e79ba..146acb9 100644 (file)
@@ -465,7 +465,7 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
     aacparse->channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6);
 
     gst_base_parse_set_frame_props (GST_BASE_PARSE (aacparse),
-        aacparse->sample_rate, 1024);
+        aacparse->sample_rate, 1024, 2, 2);
 
     GST_DEBUG ("ADTS: samplerate %d, channels %d, objtype %d",
         aacparse->sample_rate, aacparse->channels, aacparse->object_type);
index 5a3913e..07fcd7d 100644 (file)
@@ -465,7 +465,7 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
     ac3parse->sample_rate = rate;
     ac3parse->channels = chans;
 
-    gst_base_parse_set_frame_props (parse, rate, 256 * blocks);
+    gst_base_parse_set_frame_props (parse, rate, 256 * blocks, 2, 2);
   }
 
   return GST_FLOW_OK;
index 1090708..aea6ec6 100644 (file)
@@ -237,7 +237,7 @@ gst_amrparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
   }
 
   amrparse->need_header = FALSE;
-  gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1);
+  gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
   gst_amrparse_set_src_caps (amrparse);
   return TRUE;
 }
@@ -306,7 +306,7 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse,
     if (dsize >= AMR_MIME_HEADER_SIZE &&
         gst_amrparse_parse_header (amrparse, data, skipsize)) {
       amrparse->need_header = FALSE;
-      gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1);
+      gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
     } else {
       GST_WARNING ("media doesn't look like a AMR format");
     }
index c73d096..4f3699c 100644 (file)
@@ -219,6 +219,8 @@ struct _GstBaseParsePrivate
   guint fps_num, fps_den;
   guint update_interval;
   guint bitrate;
+  guint lead_in, lead_out;
+  GstClockTime lead_in_ts, lead_out_ts;
   GstBaseParseSeekable seekable;
 
   gboolean discont;
@@ -478,6 +480,8 @@ gst_base_parse_reset (GstBaseParse * parse)
   parse->priv->update_interval = 50;
   parse->priv->fps_num = parse->priv->fps_den = 0;
   parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
+  parse->priv->lead_in = parse->priv->lead_out = 0;
+  parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
   parse->priv->seekable = GST_BASE_PARSE_SEEK_DEFAULT;
   parse->priv->bitrate = 0;
   parse->priv->framecount = 0;
@@ -1475,14 +1479,15 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
   if (ret == GST_BASE_PARSE_FLOW_CLIP) {
     if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
         GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
-        GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) {
+        GST_BUFFER_TIMESTAMP (buffer) >
+        parse->segment.stop + parse->priv->lead_out_ts) {
       GST_LOG_OBJECT (parse, "Dropped frame, after segment");
       ret = GST_FLOW_UNEXPECTED;
     } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
         GST_BUFFER_DURATION_IS_VALID (buffer) &&
         GST_CLOCK_TIME_IS_VALID (parse->segment.start) &&
-        GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer)
-        < parse->segment.start) {
+        GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) +
+        parse->priv->lead_in_ts < parse->segment.start) {
       GST_LOG_OBJECT (parse, "Dropped frame, before segment");
       ret = GST_BASE_PARSE_FLOW_DROPPED;
     } else {
@@ -2205,13 +2210,18 @@ gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
  * @parse: the #GstBaseParse to set
  * @fps_num: frames per second (numerator).
  * @fps_den: frames per second (denominator).
+ * @lead_in: frames needed before a segment for subsequent decode
+ * @lead_out: frames needed after a segment
  *
  * If frames per second is configured, parser can take care of buffer duration
- * and timestamping.
+ * and timestamping.  When performing segment clipping, or seeking to a specific
+ * location, a corresponding decoder might need an initial @lead_in and a
+ * following @lead_out number of frames to ensure the desired segment is
+ * entirely filled upon decoding.
  */
 void
 gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
-    guint fps_den)
+    guint fps_den, guint lead_in, guint lead_out)
 {
   g_return_if_fail (parse != NULL);
 
@@ -2223,13 +2233,24 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
         fps_num, fps_den);
     fps_num = fps_den = 0;
     parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
+    parse->priv->lead_in = parse->priv->lead_out = 0;
+    parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
   } else {
     parse->priv->frame_duration =
-        gst_util_uint64_scale (GST_SECOND, parse->priv->fps_den,
-        parse->priv->fps_num);
+        gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
+    parse->priv->lead_in = lead_in;
+    parse->priv->lead_out = lead_out;
+    parse->priv->lead_in_ts =
+        gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num);
+    parse->priv->lead_out_ts =
+        gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num);
   }
   GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms",
       fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND);
+  GST_LOG_OBJECT (parse, "set lead in: %d frames = %" G_GUINT64_FORMAT " ms, "
+      "lead out: %d frames = %" G_GUINT64_FORMAT " ms",
+      lead_in, parse->priv->lead_in_ts / GST_MSECOND,
+      lead_out, parse->priv->lead_out_ts / GST_MSECOND);
   GST_BASE_PARSE_UNLOCK (parse);
 }
 
@@ -2598,8 +2619,14 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event)
     accurate = TRUE;
   }
   if (accurate) {
-    seekpos = gst_base_parse_find_offset (parse, seeksegment.last_stop, TRUE,
-        &start_ts);
+    GstClockTime startpos = seeksegment.last_stop;
+
+    /* accurate requested, so ... seek a bit before target */
+    if (startpos < parse->priv->lead_in_ts)
+      startpos = 0;
+    else
+      startpos -= parse->priv->lead_in_ts;
+    seekpos = gst_base_parse_find_offset (parse, startpos, TRUE, &start_ts);
     seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE,
         NULL);
   } else {
index 8d913b1..27547a9 100644 (file)
@@ -294,7 +294,7 @@ void gst_base_parse_set_min_frame_size (GstBaseParse *parse,
 void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough);
 
 void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
-                                     guint fps_den);
+                                     guint fps_den, guint lead_in, guint lead_out);
 
 gboolean gst_base_parse_get_sync (GstBaseParse * parse);