[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#699603: unblock: gst-plugins-bad0.10/0.10.23-7.1



debdiff attached.

diff -Nru gst-plugins-bad0.10-0.10.23/debian/changelog gst-plugins-bad0.10-0.10.23/debian/changelog
--- gst-plugins-bad0.10-0.10.23/debian/changelog	2012-08-06 12:50:29.000000000 +0200
+++ gst-plugins-bad0.10-0.10.23/debian/changelog	2012-12-31 20:43:40.000000000 +0100
@@ -1,3 +1,10 @@
+gst-plugins-bad0.10 (0.10.23-7.1) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * Add 0030-really-fix-h264-parsing.patch from upstream (Closes: #681652)
+
+ -- intrigeri <intrigeri@debian.org>  Mon, 31 Dec 2012 20:42:40 +0100
+
 gst-plugins-bad0.10 (0.10.23-7) unstable; urgency=low
 
   * debian/patches/*opus*:
diff -Nru gst-plugins-bad0.10-0.10.23/debian/patches/0030-really-fix-h264-parsing.patch gst-plugins-bad0.10-0.10.23/debian/patches/0030-really-fix-h264-parsing.patch
--- gst-plugins-bad0.10-0.10.23/debian/patches/0030-really-fix-h264-parsing.patch	1970-01-01 01:00:00.000000000 +0100
+++ gst-plugins-bad0.10-0.10.23/debian/patches/0030-really-fix-h264-parsing.patch	2012-12-31 20:43:40.000000000 +0100
@@ -0,0 +1,474 @@
+# Description: Fixes failure to decode many common video files encoded as AVC 1 Baseline - L2.1, Baseline - L1.1 & others 
+# Forwarded: not-needed
+# Origin: upstream
+# Bug-Ubuntu: https://bugs.launchpad.net/bugs/973014
+--- gst-plugins-bad0.10-0.10.23.orig/gst/videoparsers/gsth264parse.c
++++ gst-plugins-bad0.10-0.10.23/gst/videoparsers/gsth264parse.c
+@@ -177,11 +177,7 @@ gst_h264_parse_reset_frame (GstH264Parse
+   GST_DEBUG_OBJECT (h264parse, "reset frame");
+ 
+   /* done parsing; reset state */
+-  h264parse->nalu.valid = FALSE;
+-  h264parse->nalu.offset = 0;
+-  h264parse->nalu.sc_offset = 0;
+-  h264parse->nalu.size = 0;
+-  h264parse->current_off = 0;
++  h264parse->current_off = -1;
+ 
+   h264parse->picture_start = FALSE;
+   h264parse->update_caps = FALSE;
+@@ -213,6 +209,8 @@ gst_h264_parse_reset (GstH264Parse * h26
+ 
+   h264parse->last_report = GST_CLOCK_TIME_NONE;
+   h264parse->push_codec = FALSE;
++  h264parse->have_pps = FALSE;
++  h264parse->have_sps = FALSE;
+ 
+   h264parse->dts = GST_CLOCK_TIME_NONE;
+   h264parse->ts_trn_nb = GST_CLOCK_TIME_NONE;
+@@ -468,8 +466,15 @@ gst_h264_parse_process_nal (GstH264Parse
+ 
+       GST_DEBUG_OBJECT (h264parse, "triggering src caps check");
+       h264parse->update_caps = TRUE;
+-      /* found in stream, no need to forcibly push at start */
+-      h264parse->push_codec = FALSE;
++      h264parse->have_sps = TRUE;
++      if (h264parse->push_codec && h264parse->have_pps) {
++        /* SPS and PPS found in stream before the first pre_push_frame, no need
++         * to forcibly push at start */
++        GST_INFO_OBJECT (h264parse, "have SPS/PPS in stream");
++        h264parse->push_codec = FALSE;
++        h264parse->have_sps = FALSE;
++        h264parse->have_pps = FALSE;
++      }
+ 
+       gst_h264_parser_store_nal (h264parse, sps.id, nal_type, nalu);
+       break;
+@@ -478,8 +483,15 @@ gst_h264_parse_process_nal (GstH264Parse
+       /* parameters might have changed, force caps check */
+       GST_DEBUG_OBJECT (h264parse, "triggering src caps check");
+       h264parse->update_caps = TRUE;
+-      /* found in stream, no need to forcibly push at start */
+-      h264parse->push_codec = FALSE;
++      h264parse->have_pps = TRUE;
++      if (h264parse->push_codec && h264parse->have_sps) {
++        /* SPS and PPS found in stream before the first pre_push_frame, no need
++         * to forcibly push at start */
++        GST_INFO_OBJECT (h264parse, "have SPS/PPS in stream");
++        h264parse->push_codec = FALSE;
++        h264parse->have_sps = FALSE;
++        h264parse->have_pps = FALSE;
++      }
+ 
+       gst_h264_parser_store_nal (h264parse, pps.id, nal_type, nalu);
+       break;
+@@ -640,10 +652,12 @@ gst_h264_parse_check_valid_frame (GstBas
+   GstH264Parse *h264parse = GST_H264_PARSE (parse);
+   GstBuffer *buffer = frame->buffer;
+   guint8 *data;
+-  guint size, current_off = 0;
+-  gboolean drain;
++  guint size;
++  gint current_off = 0;
++  gboolean drain, nonext;
+   GstH264NalParser *nalparser = h264parse->nalparser;
+   GstH264NalUnit nalu;
++  GstH264ParserResult pres;
+ 
+   /* expect at least 3 bytes startcode == sc, and 2 bytes NALU payload */
+   if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 5))
+@@ -665,16 +679,39 @@ gst_h264_parse_check_valid_frame (GstBas
+   data = GST_BUFFER_DATA (buffer);
+   size = GST_BUFFER_SIZE (buffer);
+ 
+-  drain = FALSE;
+-  nalu = h264parse->nalu;
++  drain = GST_BASE_PARSE_DRAINING (parse);
++  nonext = FALSE;
++
+   current_off = h264parse->current_off;
++  if (current_off < 0)
++    current_off = 0;
+ 
+   g_assert (current_off < size);
++  GST_DEBUG_OBJECT (h264parse, "last parse position %d", current_off);
+ 
+-  GST_DEBUG_OBJECT (h264parse, "last parse position %u", current_off);
+-  while (TRUE) {
+-    GstH264ParserResult pres;
++  /* check for initial skip */
++  if (h264parse->current_off == -1) {
++    pres =
++        gst_h264_parser_identify_nalu_unchecked (nalparser, data, current_off,
++        size, &nalu);
++    switch (pres) {
++      case GST_H264_PARSER_OK:
++        if (nalu.sc_offset > 0) {
++          *skipsize = nalu.sc_offset;
++          goto skip;
++        }
++        break;
++      case GST_H264_PARSER_NO_NAL:
++        *skipsize = size - 3;
++        goto skip;
++        break;
++      default:
++        g_assert_not_reached ();
++        break;
++    }
++  }
+ 
++  while (TRUE) {
+     if (h264parse->packetized_chunked)
+       pres =
+           gst_h264_parser_identify_nalu_unchecked (nalparser, data, current_off,
+@@ -686,99 +723,85 @@ gst_h264_parse_check_valid_frame (GstBas
+ 
+     switch (pres) {
+       case GST_H264_PARSER_OK:
+-        GST_DEBUG_OBJECT (h264parse, "complete nal found. "
+-            "current offset: %u, Nal offset: %u, Nal Size: %u",
+-            current_off, nalu.offset, nalu.size);
+-
+-        GST_DEBUG_OBJECT (h264parse, "current off. %u",
+-            nalu.offset + nalu.size);
+-
+-        if (!h264parse->nalu.size && !h264parse->nalu.valid)
+-          h264parse->nalu = nalu;
+-
+-        /* need 2 bytes of next nal */
+-        if (!h264parse->packetized_chunked &&
+-            (nalu.offset + nalu.size + 4 + 2 > size)) {
+-          if (GST_BASE_PARSE_DRAINING (parse)) {
+-            drain = TRUE;
+-          } else {
+-            GST_DEBUG_OBJECT (h264parse, "need more bytes of next nal");
+-            current_off = nalu.sc_offset;
+-            goto more;
+-          }
+-        } else if (h264parse->packetized_chunked) {
+-          /* normal next nal based collection not possible,
+-           * _chain will have to tell us whether this was last one for AU */
+-          drain = h264parse->packetized_last;
+-        }
++        GST_DEBUG_OBJECT (h264parse, "complete nal (offset, size): (%u, %u) ",
++            nalu.offset, nalu.size);
+         break;
++      case GST_H264_PARSER_NO_NAL_END:
++        GST_DEBUG_OBJECT (h264parse, "not a complete nal found at offset %u",
++            nalu.offset);
++        /* if draining, accept it as complete nal */
++        if (drain) {
++          nonext = TRUE;
++          nalu.size = size - nalu.offset;
++          GST_DEBUG_OBJECT (h264parse, "draining, accepting with size %u",
++              nalu.size);
++          /* if it's not too short at least */
++          if (nalu.size < 2)
++            goto broken;
++          break;
++        }
++        /* otherwise need more */
++        goto more;
+       case GST_H264_PARSER_BROKEN_LINK:
+-        return FALSE;
++        g_assert_not_reached ();
++        break;
+       case GST_H264_PARSER_ERROR:
+-        current_off = size - 3;
+-        goto parsing_error;
++        /* should not really occur either */
++        GST_DEBUG_OBJECT (h264parse, "error parsing Nal Unit");
++        /* fall-through */
+       case GST_H264_PARSER_NO_NAL:
+-        /* don't expect to have found any NAL so far */
+-        g_assert (h264parse->nalu.size == 0);
+-        current_off = h264parse->nalu.sc_offset = size - 3;
+-        goto more;
++        g_assert_not_reached ();
++        break;
+       case GST_H264_PARSER_BROKEN_DATA:
+         GST_WARNING_OBJECT (h264parse, "input stream is corrupt; "
+-            "it contains a NAL unit of length %d", nalu.size);
+-
++            "it contains a NAL unit of length %u", nalu.size);
++      broken:
+         /* broken nal at start -> arrange to skip it,
+          * otherwise have it terminate current au
+          * (and so it will be skipped on next frame round) */
+-        if (nalu.sc_offset == h264parse->nalu.sc_offset) {
+-          *skipsize = nalu.offset;
+-
++        if (current_off == 0) {
+           GST_DEBUG_OBJECT (h264parse, "skipping broken nal");
+-          goto invalid;
++          *skipsize = nalu.offset;
++          goto skip;
+         } else {
++          GST_DEBUG_OBJECT (h264parse, "terminating au");
+           nalu.size = 0;
++          nalu.offset = nalu.sc_offset;
+           goto end;
+         }
+-      case GST_H264_PARSER_NO_NAL_END:
+-        GST_DEBUG_OBJECT (h264parse, "not a complete nal found at offset %u",
+-            nalu.offset);
+-
+-        current_off = nalu.sc_offset;
+-        /* We keep the reference to this nal so we start over the parsing
+-         * here */
+-        if (!h264parse->nalu.size && !h264parse->nalu.valid)
+-          h264parse->nalu = nalu;
+-
+-        if (GST_BASE_PARSE_DRAINING (parse)) {
+-          drain = TRUE;
+-          GST_DEBUG_OBJECT (h264parse, "draining NAL %u %u %u", size,
+-              h264parse->nalu.offset, h264parse->nalu.size);
+-          /*  Can't parse the nalu */
+-          if (size - h264parse->nalu.offset < 2) {
+-            *skipsize = nalu.offset;
+-            goto invalid;
+-          }
+-
+-          /* We parse it anyway */
+-          nalu.size = size - nalu.offset;
+-          break;
+-        }
+-        goto more;
++        break;
++      default:
++        g_assert_not_reached ();
++        break;
+     }
+ 
+-    current_off = nalu.offset + nalu.size;
+-
+     GST_DEBUG_OBJECT (h264parse, "%p complete nal found. Off: %u, Size: %u",
+         data, nalu.offset, nalu.size);
+ 
++    /* simulate no next nal if none needed */
++    nonext = nonext || (h264parse->align == GST_H264_PARSE_ALIGN_NAL);
++
++    if (!nonext && !h264parse->packetized_chunked) {
++      if (nalu.offset + nalu.size + 4 + 2 > size) {
++        GST_DEBUG_OBJECT (h264parse, "not enough data for next NALU");
++        if (drain) {
++          GST_DEBUG_OBJECT (h264parse, "but draining anyway");
++          nonext = TRUE;
++        } else {
++          goto more;
++        }
++      }
++    }
++
+     gst_h264_parse_process_nal (h264parse, &nalu);
+ 
+-    /* simulate no next nal if none needed */
+-    drain = drain || (h264parse->align == GST_H264_PARSE_ALIGN_NAL);
++    if (nonext)
++      break;
+ 
+     /* In packetized mode we know there's only on NALU in each input packet,
+      * but we may not have seen the whole AU already, possibly need more */
+     if (h264parse->packetized_chunked) {
+-      if (drain)
++      if (h264parse->packetized_last)
+         break;
+       /* next NALU expected at end of current data */
+       current_off = size;
+@@ -786,42 +809,30 @@ gst_h264_parse_check_valid_frame (GstBas
+     }
+ 
+     /* if no next nal, we know it's complete here */
+-    if (drain || gst_h264_parse_collect_nal (h264parse, data, size, &nalu))
++    if (gst_h264_parse_collect_nal (h264parse, data, size, &nalu))
+       break;
+ 
+     GST_DEBUG_OBJECT (h264parse, "Looking for more");
++    current_off = nalu.offset + nalu.size;
+   }
+ 
+ end:
+-  *skipsize = h264parse->nalu.sc_offset;
+-  *framesize = nalu.offset + nalu.size - h264parse->nalu.sc_offset;
+-  h264parse->current_off = current_off;
+-
++  *framesize = nalu.offset + nalu.size;
+   return TRUE;
+ 
+-parsing_error:
+-  GST_DEBUG_OBJECT (h264parse, "error parsing Nal Unit");
+-
+ more:
+   /* ask for best next available */
+   *framesize = G_MAXUINT;
+-  if (!h264parse->nalu.size) {
+-    /* skip up to initial startcode */
+-    *skipsize = h264parse->nalu.sc_offset;
+-    /* but mind some stuff will have been skipped */
+-    g_assert (current_off >= *skipsize);
+-    current_off -= *skipsize;
+-    h264parse->nalu.sc_offset = 0;
+-  } else {
+-    *skipsize = 0;
+-  }
++  *skipsize = 0;
+ 
+   /* Restart parsing from here next time */
+-  h264parse->current_off = current_off;
++  if (current_off > 0)
++    h264parse->current_off = current_off;
+ 
+   return FALSE;
+ 
+-invalid:
++skip:
++  GST_DEBUG_OBJECT (h264parse, "skipping %d", *skipsize);
+   gst_h264_parse_reset_frame (h264parse);
+   return FALSE;
+ }
+@@ -835,6 +846,7 @@ gst_h264_parse_make_codec_data (GstH264P
+   guint8 profile_idc = 0, profile_comp = 0, level_idc = 0;
+   gboolean found = FALSE;
+   guint8 *data;
++  gint nl;
+ 
+   /* only nal payload in stored nals */
+ 
+@@ -867,12 +879,13 @@ gst_h264_parse_make_codec_data (GstH264P
+ 
+   buf = gst_buffer_new_and_alloc (5 + 1 + sps_size + 1 + pps_size);
+   data = GST_BUFFER_DATA (buf);
++  nl = h264parse->nal_length_size;
+ 
+   data[0] = 1;                  /* AVC Decoder Configuration Record ver. 1 */
+   data[1] = profile_idc;        /* profile_idc                             */
+   data[2] = profile_comp;       /* profile_compability                     */
+   data[3] = level_idc;          /* level_idc                               */
+-  data[4] = 0xfc | (4 - 1);     /* nal_length_size_minus1                  */
++  data[4] = 0xfc | (nl - 1);    /* nal_length_size_minus1                  */
+   data[5] = 0xe0 | num_sps;     /* number of SPSs */
+ 
+   data += 6;
+@@ -1341,12 +1354,10 @@ check_pending_key_unit_event (GstEvent *
+       running_time < pending_key_unit_ts)
+     goto out;
+ 
+-#if 0
+   if (flags & GST_BUFFER_FLAG_DELTA_UNIT) {
+     GST_DEBUG ("pending force key unit, waiting for keyframe");
+     goto out;
+   }
+-#endif
+ 
+   stream_time = gst_segment_to_stream_time (segment,
+       GST_FORMAT_TIME, timestamp);
+@@ -1479,32 +1490,38 @@ gst_h264_parse_pre_push_frame (GstBasePa
+           GstByteWriter bw;
+           GstBuffer *new_buf;
+           const gboolean bs = h264parse->format == GST_H264_PARSE_FORMAT_BYTE;
++          const gint nls = 4 - h264parse->nal_length_size;
++          gboolean ok;
+ 
+           gst_byte_writer_init_with_size (&bw, GST_BUFFER_SIZE (buffer), FALSE);
+-          gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (buffer),
++          ok = gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (buffer),
+               h264parse->idr_pos);
+           GST_DEBUG_OBJECT (h264parse, "- inserting SPS/PPS");
+           for (i = 0; i < GST_H264_MAX_SPS_COUNT; i++) {
+             if ((codec_nal = h264parse->sps_nals[i])) {
+               GST_DEBUG_OBJECT (h264parse, "inserting SPS nal");
+-              gst_byte_writer_put_uint32_be (&bw,
+-                  bs ? 1 : GST_BUFFER_SIZE (codec_nal));
+-              gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (codec_nal),
+-                  GST_BUFFER_SIZE (codec_nal));
++              ok &= gst_byte_writer_put_uint32_be (&bw,
++                  bs ? 1 : (GST_BUFFER_SIZE (codec_nal) << (nls * 8)));
++              ok &= gst_byte_writer_set_pos (&bw,
++                  gst_byte_writer_get_pos (&bw) - nls);
++              ok &= gst_byte_writer_put_data (&bw,
++                  GST_BUFFER_DATA (codec_nal), GST_BUFFER_SIZE (codec_nal));
+               h264parse->last_report = new_ts;
+             }
+           }
+           for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++) {
+             if ((codec_nal = h264parse->pps_nals[i])) {
+               GST_DEBUG_OBJECT (h264parse, "inserting PPS nal");
+-              gst_byte_writer_put_uint32_be (&bw,
+-                  bs ? 1 : GST_BUFFER_SIZE (codec_nal));
+-              gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (codec_nal),
+-                  GST_BUFFER_SIZE (codec_nal));
++              ok &= gst_byte_writer_put_uint32_be (&bw,
++                  bs ? 1 : (GST_BUFFER_SIZE (codec_nal) << (nls * 8)));
++              ok &= gst_byte_writer_set_pos (&bw,
++                  gst_byte_writer_get_pos (&bw) - nls);
++              ok &= gst_byte_writer_put_data (&bw,
++                  GST_BUFFER_DATA (codec_nal), GST_BUFFER_SIZE (codec_nal));
+               h264parse->last_report = new_ts;
+             }
+           }
+-          gst_byte_writer_put_data (&bw,
++          ok &= gst_byte_writer_put_data (&bw,
+               GST_BUFFER_DATA (buffer) + h264parse->idr_pos,
+               GST_BUFFER_SIZE (buffer) - h264parse->idr_pos);
+           /* collect result and push */
+@@ -1515,10 +1532,16 @@ gst_h264_parse_pre_push_frame (GstBasePa
+           GST_BUFFER_FLAG_UNSET (new_buf, GST_BUFFER_FLAG_DELTA_UNIT);
+           gst_buffer_replace (&frame->buffer, new_buf);
+           gst_buffer_unref (new_buf);
++          /* some result checking seems to make some compilers happy */
++          if (G_UNLIKELY (!ok)) {
++            GST_ERROR_OBJECT (h264parse, "failed to insert SPS/PPS");
++          }
+         }
+       }
+       /* we pushed whatever we had */
+       h264parse->push_codec = FALSE;
++      h264parse->have_sps = FALSE;
++      h264parse->have_pps = FALSE;
+     }
+   }
+ 
+@@ -1623,10 +1646,10 @@ gst_h264_parse_set_caps (GstBaseParse *
+ 
+     /* if upstream sets codec_data without setting stream-format and alignment, we
+      * assume stream-format=avc,alignment=au */
+-    if (format == GST_H264_PARSE_FORMAT_NONE) {
++    if (format == GST_H264_PARSE_FORMAT_NONE)
+       format = GST_H264_PARSE_FORMAT_AVC;
++    if (align == GST_H264_PARSE_ALIGN_NONE)
+       align = GST_H264_PARSE_ALIGN_AU;
+-    }
+   } else {
+     GST_DEBUG_OBJECT (h264parse, "have bytestream h264");
+     /* nothing to pre-process */
+@@ -1665,6 +1688,8 @@ gst_h264_parse_set_caps (GstBaseParse *
+     /* arrange to insert codec-data in-stream if needed.
+      * src caps are only arranged for later on */
+     h264parse->push_codec = TRUE;
++    h264parse->have_sps = FALSE;
++    h264parse->have_pps = FALSE;
+     h264parse->split_packetized = TRUE;
+     h264parse->packetized = TRUE;
+   }
+--- gst-plugins-bad0.10-0.10.23.orig/gst/videoparsers/gsth264parse.h
++++ gst-plugins-bad0.10-0.10.23/gst/videoparsers/gsth264parse.h
+@@ -67,15 +67,16 @@ struct _GstH264Parse
+ 
+   /* state */
+   GstH264NalParser *nalparser;
+-  GstH264NalUnit nalu;
+   guint align;
+   guint format;
+-  guint current_off;
++  gint current_off;
+   gboolean packetized_last;
+   gboolean packetized_chunked;
+ 
+   GstClockTime last_report;
+   gboolean push_codec;
++  gboolean have_sps;
++  gboolean have_pps;
+ 
+   /* collected SPS and PPS NALUs */
+   GstBuffer *sps_nals[GST_H264_MAX_SPS_COUNT];
diff -Nru gst-plugins-bad0.10-0.10.23/debian/patches/series gst-plugins-bad0.10-0.10.23/debian/patches/series
--- gst-plugins-bad0.10-0.10.23/debian/patches/series	2012-08-06 10:31:44.000000000 +0200
+++ gst-plugins-bad0.10-0.10.23/debian/patches/series	2012-12-31 20:43:40.000000000 +0100
@@ -11,3 +11,4 @@
 0016-opusdec-do-not-assert-on-bad-header-error-out-instea.patch
 0017-opusdec-read-gain-from-the-right-place-in-the-header.patch
 0020-opusenc-add-missing-mutex-unlock-on-error-path.patch
+0030-really-fix-h264-parsing.patch

Reply to: