avidemux: push mode; use proper movi offset for movi based index
[platform/upstream/gst-plugins-good.git] / gst / avi / gstavidemux.c
index d0fb95b..eb12702 100644 (file)
 
 #define DIV_ROUND_UP(s,v) (((s) + ((v)-1)) / (v))
 
+#define GST_AVI_KEYFRAME 1
+#define ENTRY_IS_KEYFRAME(e) ((e)->flags == GST_AVI_KEYFRAME)
+#define ENTRY_SET_KEYFRAME(e) ((e)->flags = GST_AVI_KEYFRAME)
+#define ENTRY_UNSET_KEYFRAME(e) ((e)->flags = 0)
+
+
 GST_DEBUG_CATEGORY_STATIC (avidemux_debug);
 #define GST_CAT_DEFAULT avidemux_debug
 
@@ -638,9 +644,9 @@ gst_avi_demux_seek_streams (GstAviDemux * avi, guint64 offset, gboolean before)
 
     if (before) {
       if (entry) {
+        gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &val);
         GST_DEBUG_OBJECT (avi, "stream %d, previous entry at %"
             G_GUINT64_FORMAT, i, val);
-        gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &val);
         if (val < min)
           min = val;
       }
@@ -705,9 +711,9 @@ gst_avi_demux_seek_streams_index (GstAviDemux * avi, guint64 offset,
 
     if (before) {
       if (entry) {
+        val = stream->index[index].offset;
         GST_DEBUG_OBJECT (avi,
             "stream %d, previous entry at %" G_GUINT64_FORMAT, i, val);
-        val = stream->index[index].offset;
         if (val < min)
           min = val;
       }
@@ -1982,22 +1988,36 @@ gst_avi_demux_parse_stream (GstAviDemux * avi, GstBuffer * buf)
             GST_DEBUG_OBJECT (element, "marking video as VBR, res %d", res);
             break;
           case GST_RIFF_FCC_auds:
-            stream->is_vbr = (stream->strh->samplesize == 0)
-                && stream->strh->scale > 1;
             res =
                 gst_riff_parse_strf_auds (element, sub, &stream->strf.auds,
                 &stream->extradata);
+            stream->is_vbr = (stream->strh->samplesize == 0)
+                && stream->strh->scale > 1
+                && stream->strf.auds->blockalign != 1;
             sub = NULL;
             GST_DEBUG_OBJECT (element, "marking audio as VBR:%d, res %d",
                 stream->is_vbr, res);
             /* we need these or we have no way to come up with timestamps */
-            if ((stream->is_vbr && !stream->strf.auds->av_bps) ||
-                (!stream->is_vbr && (!stream->strh->scale ||
+            if ((!stream->is_vbr && !stream->strf.auds->av_bps) ||
+                (stream->is_vbr && (!stream->strh->scale ||
                         !stream->strh->rate))) {
               GST_WARNING_OBJECT (element,
                   "invalid audio header, ignoring stream");
               goto fail;
             }
+            /* some more sanity checks */
+            if (stream->is_vbr) {
+              if (stream->strf.auds->blockalign <= 4) {
+                /* that would mean (too) many frames per chunk,
+                 * so not likely set as expected */
+                GST_DEBUG_OBJECT (element,
+                    "suspicious blockalign %d for VBR audio; "
+                    "overriding to 1 frame per chunk",
+                    stream->strf.auds->blockalign);
+                /* this should top any likely value */
+                stream->strf.auds->blockalign = (1 << 12);
+              }
+            }
             break;
           case GST_RIFF_FCC_iavs:
             stream->is_vbr = TRUE;
@@ -2749,7 +2769,7 @@ gst_avi_demux_stream_index_push (GstAviDemux * avi)
   GST_DEBUG ("will parse index chunk size %u for tag %"
       GST_FOURCC_FORMAT, GST_BUFFER_SIZE (buf), GST_FOURCC_ARGS (tag));
 
-  avi->offset = avi->first_movi_offset - 8;
+  avi->offset = avi->first_movi_offset;
   gst_avi_demux_parse_index (avi, buf);
 
 #ifndef GST_DISABLE_GST_DEBUG
@@ -4853,9 +4873,13 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
        * through the whole file */
       if (avi->abort_buffering) {
         avi->abort_buffering = FALSE;
-        gst_adapter_flush (avi->adapter, 8);
+        if (size) {
+          gst_adapter_flush (avi->adapter, 8);
+          return GST_FLOW_OK;
+        }
+      } else {
+        return GST_FLOW_OK;
       }
-      return GST_FLOW_OK;
     }
     GST_DEBUG ("chunk ID %" GST_FOURCC_FORMAT ", size %u",
         GST_FOURCC_ARGS (tag), size);
@@ -4884,9 +4908,13 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
       if (saw_desired_kf) {
         gst_adapter_flush (avi->adapter, 8);
         /* get buffer */
-        buf = gst_adapter_take_buffer (avi->adapter, GST_ROUND_UP_2 (size));
-        /* patch the size */
-        GST_BUFFER_SIZE (buf) = size;
+        if (size) {
+          buf = gst_adapter_take_buffer (avi->adapter, GST_ROUND_UP_2 (size));
+          /* patch the size */
+          GST_BUFFER_SIZE (buf) = size;
+        } else {
+          buf = NULL;
+        }
       } else {
         GST_DEBUG_OBJECT (avi,
             "Desired keyframe not yet reached, flushing chunk");
@@ -4960,6 +4988,7 @@ gst_avi_demux_stream_data (GstAviDemux * avi)
             stream->discont = FALSE;
           }
           res = gst_pad_push (stream->pad, buf);
+          buf = NULL;
 
           /* combine flows */
           res = gst_avi_demux_combine_flows (avi, stream, res);
@@ -5339,6 +5368,7 @@ gst_avi_demux_change_state (GstElement * element, GstStateChange transition)
 
   switch (transition) {
     case GST_STATE_CHANGE_PAUSED_TO_READY:
+      avi->have_index = FALSE;
       gst_avi_demux_reset (avi);
       break;
     default: