audioparsers: fix some more parsers
authorEdward Hervey <edward.hervey@collabora.co.uk>
Mon, 6 Jun 2011 18:43:31 +0000 (20:43 +0200)
committerEdward Hervey <edward.hervey@collabora.co.uk>
Mon, 6 Jun 2011 18:43:31 +0000 (20:43 +0200)
gst/audioparsers/gstaacparse.c
gst/audioparsers/gstac3parse.c
gst/audioparsers/gstdcaparse.c
gst/audioparsers/gstflacparse.c
gst/audioparsers/gstmpegaudioparse.c

index 711904d..f84633b 100644 (file)
@@ -469,6 +469,7 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
     int skip_size = 0;
     int bitstream_type;
     int sr_idx;
+    GstCaps *sinkcaps;
 
     aacparse->header_type = DSPAAC_HEADER_ADIF;
     aacparse->mpegversion = 4;
@@ -531,8 +532,9 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
     gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 512);
 
     /* arrange for metadata and get out of the way */
-    gst_aac_parse_set_src_caps (aacparse,
-        GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse)));
+    sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (aacparse));
+    gst_aac_parse_set_src_caps (aacparse, sinkcaps);
+    gst_caps_unref (sinkcaps);
 
     /* not syncable, not easily seekable (unless we push data from start */
     gst_base_parse_set_syncable (GST_BASE_PARSE_CAST (aacparse), FALSE);
@@ -662,14 +664,18 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 
   if (G_UNLIKELY (rate != aacparse->sample_rate
           || channels != aacparse->channels)) {
+    GstCaps *sinkcaps;
+
     aacparse->sample_rate = rate;
     aacparse->channels = channels;
 
-    if (!gst_aac_parse_set_src_caps (aacparse,
-            GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad))) {
+    sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
+    if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
       /* If linking fails, we need to return appropriate error */
+      gst_caps_unref (sinkcaps);
       ret = GST_FLOW_NOT_LINKED;
     }
+    gst_caps_unref (sinkcaps);
 
     gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
         aacparse->sample_rate, 1024, 2, 2);
index b955c69..9569806 100644 (file)
@@ -240,18 +240,24 @@ static gboolean
 gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
     guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
 {
-  GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+  GstBitReader bits;
+  gpointer data;
+  gsize size;
   guint8 fscod, frmsizcod, bsid, acmod, lfe_on;
+  gboolean ret = FALSE;
 
   GST_LOG_OBJECT (ac3parse, "parsing ac3");
 
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+  gst_bit_reader_init (&bits, data, size);
+
   gst_bit_reader_skip_unchecked (&bits, 16 + 16);
   fscod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);
   frmsizcod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 6);
 
   if (G_UNLIKELY (fscod == 3 || frmsizcod >= G_N_ELEMENTS (frmsizcod_table))) {
     GST_DEBUG_OBJECT (ac3parse, "bad fscod=%d frmsizcod=%d", fscod, frmsizcod);
-    return FALSE;
+    goto cleanup;
   }
 
   bsid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 5);
@@ -262,7 +268,7 @@ gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
    * but seemingly only defines 6 and 8 cases */
   if (bsid > 8) {
     GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid);
-    return FALSE;
+    goto cleanup;
   } else if (bsid != 8 && bsid != 6) {
     GST_DEBUG_OBJECT (ac3parse, "undefined bsid=%d", bsid);
   }
@@ -287,24 +293,35 @@ gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
   if (sid)
     *sid = 0;
 
-  return TRUE;
+  ret = TRUE;
+
+cleanup:
+  gst_buffer_unmap (buf, data, size);
+
+  return ret;
 }
 
 static gboolean
 gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
     guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
 {
-  GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+  GstBitReader bits;
+  gpointer data;
+  gsize size;
   guint16 frmsiz, sample_rate, blocks;
   guint8 strmtyp, fscod, fscod2, acmod, lfe_on, strmid, numblkscod;
+  gboolean ret = FALSE;
 
   GST_LOG_OBJECT (ac3parse, "parsing e-ac3");
 
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+  gst_bit_reader_init (&bits, data, size);
+
   gst_bit_reader_skip_unchecked (&bits, 16);
   strmtyp = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2); /* strmtyp     */
   if (G_UNLIKELY (strmtyp == 3)) {
     GST_DEBUG_OBJECT (ac3parse, "bad strmtyp %d", strmtyp);
-    return FALSE;
+    goto cleanup;
   }
 
   strmid = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3);  /* substreamid */
@@ -314,7 +331,7 @@ gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
     fscod2 = gst_bit_reader_get_bits_uint8_unchecked (&bits, 2);        /* fscod2      */
     if (G_UNLIKELY (fscod2 == 3)) {
       GST_DEBUG_OBJECT (ac3parse, "invalid fscod2");
-      return FALSE;
+      goto cleanup;
     }
     sample_rate = fscod_rates[fscod2] / 2;
     blocks = 6;
@@ -340,7 +357,12 @@ gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
   if (sid)
     *sid = (strmtyp & 0x1) << 3 | strmid;
 
-  return TRUE;
+  ret = TRUE;
+
+cleanup:
+  gst_buffer_unmap (buf, data, size);
+
+  return ret;
 }
 
 static gboolean
@@ -348,35 +370,49 @@ gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf,
     guint * framesize, guint * rate, guint * chans, guint * blocks,
     guint * sid, gboolean * eac)
 {
-  GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+  GstBitReader bits;
   guint16 sync;
   guint8 bsid;
+  gpointer data;
+  gsize size;
+  gboolean ret = FALSE;
 
-  GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", GST_BUFFER_DATA (buf), 16);
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+  gst_bit_reader_init (&bits, data, size);
+
+  GST_MEMDUMP_OBJECT (parse, "AC3 frame sync", data, MIN (size, 16));
 
   sync = gst_bit_reader_get_bits_uint16_unchecked (&bits, 16);
   gst_bit_reader_skip_unchecked (&bits, 16 + 8);
   bsid = gst_bit_reader_peek_bits_uint8_unchecked (&bits, 5);
 
   if (G_UNLIKELY (sync != 0x0b77))
-    return FALSE;
+    goto cleanup;
 
   GST_LOG_OBJECT (parse, "bsid = %d", bsid);
 
   if (bsid <= 10) {
     if (eac)
       *eac = FALSE;
-    return gst_ac3_parse_frame_header_ac3 (parse, buf, framesize, rate, chans,
+    ret = gst_ac3_parse_frame_header_ac3 (parse, buf, framesize, rate, chans,
         blocks, sid);
-  } else if (bsid <= 16) {
+    goto cleanup;
+  }
+
+  if (bsid <= 16) {
     if (eac)
       *eac = TRUE;
-    return gst_ac3_parse_frame_header_eac3 (parse, buf, framesize, rate, chans,
+    ret = gst_ac3_parse_frame_header_eac3 (parse, buf, framesize, rate, chans,
         blocks, sid);
-  } else {
-    GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
-    return FALSE;
+    goto cleanup;
   }
+
+  GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
+
+cleanup:
+  gst_buffer_unmap (buf, data, size);
+
+  return ret;
 }
 
 static gboolean
@@ -385,35 +421,40 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
 {
   GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
   GstBuffer *buf = frame->buffer;
-  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+  GstByteReader reader;
   gint off;
   gboolean lost_sync, draining;
+  gpointer data;
+  gsize size;
+  gboolean ret = FALSE;
 
-  if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
-    return FALSE;
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+
+  if (G_UNLIKELY (size < 6))
+    goto cleanup;
 
   off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
-      0, GST_BUFFER_SIZE (buf));
+      0, size);
 
   GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
 
   /* didn't find anything that looks like a sync word, skip */
   if (off < 0) {
-    *skipsize = GST_BUFFER_SIZE (buf) - 3;
-    return FALSE;
+    *skipsize = size - 3;
+    goto cleanup;
   }
 
   /* possible frame header, but not at offset 0? skip bytes before sync */
   if (off > 0) {
     *skipsize = off;
-    return FALSE;
+    goto cleanup;
   }
 
   /* make sure the values in the frame header look sane */
   if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, NULL, NULL,
           NULL, NULL, NULL)) {
     *skipsize = off + 2;
-    return FALSE;
+    goto cleanup;
   }
 
   GST_LOG_OBJECT (parse, "got frame");
@@ -431,12 +472,12 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
       GST_DEBUG_OBJECT (ac3parse, "... but not sufficient data");
       gst_base_parse_set_min_frame_size (parse, *framesize + 6);
       *skipsize = 0;
-      return FALSE;
+      goto cleanup;
     } else {
       if (word != 0x0b77) {
         GST_DEBUG_OBJECT (ac3parse, "0x%x not OK", word);
         *skipsize = off + 2;
-        return FALSE;
+        goto cleanup;
       } else {
         /* ok, got sync now, let's assume constant frame size */
         gst_base_parse_set_min_frame_size (parse, *framesize);
@@ -444,7 +485,12 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
     }
   }
 
-  return TRUE;
+  ret = TRUE;
+
+cleanup:
+  gst_buffer_unmap (buf, data, size);
+
+  return ret;
 }
 
 static GstFlowReturn
@@ -480,7 +526,6 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
     GstCaps *caps = gst_caps_new_simple (eac ? "audio/x-eac3" : "audio/x-ac3",
         "framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate,
         "channels", G_TYPE_INT, chans, NULL);
-    gst_buffer_set_caps (buf, caps);
     gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
     gst_caps_unref (caps);
 
index 2bf0e38..b4bbe87 100644 (file)
@@ -78,27 +78,14 @@ static gboolean gst_dca_parse_check_valid_frame (GstBaseParse * parse,
 static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse,
     GstBaseParseFrame * frame);
 
-GST_BOILERPLATE (GstDcaParse, gst_dca_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
-
-static void
-gst_dca_parse_base_init (gpointer klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_template));
-
-  gst_element_class_set_details_simple (element_class,
-      "DTS Coherent Acoustics audio stream parser", "Codec/Parser/Audio",
-      "DCA parser", "Tim-Philipp Müller <tim centricular net>");
-}
+#define gst_dca_parse_parent_class parent_class
+G_DEFINE_TYPE (GstDcaParse, gst_dca_parse, GST_TYPE_BASE_PARSE);
 
 static void
 gst_dca_parse_class_init (GstDcaParseClass * klass)
 {
   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   GST_DEBUG_CATEGORY_INIT (dca_parse_debug, "dcaparse", 0,
@@ -111,6 +98,15 @@ gst_dca_parse_class_init (GstDcaParseClass * klass)
   parse_class->check_valid_frame =
       GST_DEBUG_FUNCPTR (gst_dca_parse_check_valid_frame);
   parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_dca_parse_parse_frame);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_template));
+
+  gst_element_class_set_details_simple (element_class,
+      "DTS Coherent Acoustics audio stream parser", "Codec/Parser/Audio",
+      "DCA parser", "Tim-Philipp Müller <tim centricular net>");
 }
 
 static void
@@ -126,7 +122,7 @@ gst_dca_parse_reset (GstDcaParse * dcaparse)
 }
 
 static void
-gst_dca_parse_init (GstDcaParse * dcaparse, GstDcaParseClass * klass)
+gst_dca_parse_init (GstDcaParse * dcaparse)
 {
   gst_base_parse_set_min_frame_size (GST_BASE_PARSE (dcaparse),
       DCA_MIN_FRAMESIZE);
@@ -255,7 +251,7 @@ gst_dca_parse_parse_header (GstDcaParse * dcaparse,
 
 static gint
 gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
-    const GstBuffer * buf, guint32 * sync)
+    gsize bufsize, guint32 * sync)
 {
   guint32 best_sync = 0;
   guint best_offset = G_MAXUINT;
@@ -265,7 +261,7 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
 
   /* Raw little endian */
   off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xfe7f0180,
-      0, GST_BUFFER_SIZE (buf));
+      0, bufsize);
   if (off >= 0 && off < best_offset) {
     best_offset = off;
     best_sync = 0xfe7f0180;
@@ -273,7 +269,7 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
 
   /* Raw big endian */
   off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x7ffe8001,
-      0, GST_BUFFER_SIZE (buf));
+      0, bufsize);
   if (off >= 0 && off < best_offset) {
     best_offset = off;
     best_sync = 0x7ffe8001;
@@ -284,7 +280,7 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
 
   /* 14-bit little endian  */
   off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xff1f00e8,
-      0, GST_BUFFER_SIZE (buf));
+      0, bufsize);
   if (off >= 0 && off < best_offset) {
     best_offset = off;
     best_sync = 0xff1f00e8;
@@ -292,7 +288,7 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
 
   /* 14-bit big endian  */
   off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x1fffe800,
-      0, GST_BUFFER_SIZE (buf));
+      0, bufsize);
   if (off >= 0 && off < best_offset) {
     best_offset = off;
     best_sync = 0x1fffe800;
@@ -311,33 +307,40 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
 {
   GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
   GstBuffer *buf = frame->buffer;
-  GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+  GstByteReader r;
   gboolean parser_draining;
   gboolean parser_in_sync;
   gboolean terminator;
   guint32 sync = 0;
   guint size, rate, chans, num_blocks, samples_per_block;
   gint off = -1;
+  gpointer data;
+  gsize bufsize;
+  gboolean ret = FALSE;
 
-  if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16))
-    return FALSE;
+  data = gst_buffer_map (buf, &bufsize, NULL, GST_MAP_READ);
+
+  if (G_UNLIKELY (bufsize < 16))
+    goto cleanup;
 
   parser_in_sync = !GST_BASE_PARSE_LOST_SYNC (parse);
 
+  gst_byte_reader_init (&r, data, bufsize);
+
   if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) {
     off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff,
-        dcaparse->last_sync, 0, GST_BUFFER_SIZE (buf));
+        dcaparse->last_sync, 0, size);
   }
 
   if (G_UNLIKELY (off < 0)) {
-    off = gst_dca_parse_find_sync (dcaparse, &r, buf, &sync);
+    off = gst_dca_parse_find_sync (dcaparse, &r, bufsize, &sync);
   }
 
   /* didn't find anything that looks like a sync word, skip */
   if (off < 0) {
-    *skipsize = GST_BUFFER_SIZE (buf) - 3;
+    *skipsize = bufsize - 3;
     GST_DEBUG_OBJECT (dcaparse, "no sync, skipping %d bytes", *skipsize);
-    return FALSE;
+    goto cleanup;
   }
 
   GST_LOG_OBJECT (parse, "possible sync %08x at buffer offset %d", sync, off);
@@ -345,14 +348,14 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
   /* possible frame header, but not at offset 0? skip bytes before sync */
   if (off > 0) {
     *skipsize = off;
-    return FALSE;
+    goto cleanup;
   }
 
   /* make sure the values in the frame header look sane */
   if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, NULL,
           NULL, &num_blocks, &samples_per_block, &terminator)) {
     *skipsize = 4;
-    return FALSE;
+    goto cleanup;
   }
 
   GST_LOG_OBJECT (parse, "got frame, sync %08x, size %u, rate %d, channels %d",
@@ -367,19 +370,19 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
   if (!parser_in_sync && !parser_draining) {
     /* check for second frame to be sure */
     GST_DEBUG_OBJECT (dcaparse, "resyncing; checking next frame syncword");
-    if (GST_BUFFER_SIZE (buf) >= (size + 16)) {
+    if (bufsize >= (size + 16)) {
       guint s2, r2, c2, n2, s3;
       gboolean t;
 
-      GST_MEMDUMP ("buf", GST_BUFFER_DATA (buf), size + 16);
-      gst_byte_reader_init_from_buffer (&r, buf);
+      GST_MEMDUMP ("buf", data, size + 16);
+      gst_byte_reader_init (&r, data, bufsize);
       gst_byte_reader_skip_unchecked (&r, size);
 
       if (!gst_dca_parse_parse_header (dcaparse, &r, &s2, &r2, &c2, NULL, NULL,
               &n2, &s3, &t)) {
         GST_DEBUG_OBJECT (dcaparse, "didn't find second syncword");
         *skipsize = 4;
-        return FALSE;
+        goto cleanup;
       }
 
       /* ok, got sync now, let's assume constant frame size */
@@ -388,13 +391,17 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
       /* FIXME: baseparse always seems to hand us buffers of min_frame_size
        * bytes, which is unhelpful here */
       GST_LOG_OBJECT (dcaparse, "next sync out of reach (%u < %u)",
-          GST_BUFFER_SIZE (buf), size + 16);
+          bufsize, size + 16);
       /* *skipsize = 0; */
       /* return FALSE; */
     }
   }
 
-  return TRUE;
+  ret = TRUE;
+
+cleanup:
+  gst_buffer_unmap (buf, data, bufsize);
+  return ret;
 }
 
 static GstFlowReturn
@@ -402,10 +409,15 @@ gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
   GstBuffer *buf = frame->buffer;
-  GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+  GstByteReader r;
   guint size, rate, chans, depth, block_size, num_blocks, samples_per_block;
   gint endianness;
   gboolean terminator;
+  gpointer data;
+  gsize bufsize;
+
+  data = gst_buffer_map (buf, &bufsize, NULL, GST_MAP_READ);
+  gst_byte_reader_init (&r, data, bufsize);
 
   if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, &depth,
           &endianness, &num_blocks, &samples_per_block, &terminator))
@@ -425,7 +437,6 @@ gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
         "endianness", G_TYPE_INT, endianness, "depth", G_TYPE_INT, depth,
         "block-size", G_TYPE_INT, block_size, "frame-size", G_TYPE_INT, size,
         NULL);
-    gst_buffer_set_caps (buf, caps);
     gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
     gst_caps_unref (caps);
 
@@ -439,6 +450,7 @@ gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
     gst_base_parse_set_frame_rate (parse, rate, block_size, 0, 0);
   }
 
+  gst_buffer_unmap (buf, data, bufsize);
   return GST_FLOW_OK;
 
 /* ERRORS */
@@ -446,6 +458,7 @@ broken_header:
   {
     /* this really shouldn't ever happen */
     GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
+    gst_buffer_unmap (buf, data, bufsize);
     return GST_FLOW_ERROR;
   }
 }
index 0c6c529..3b2ff36 100644 (file)
@@ -202,34 +202,19 @@ static gboolean gst_flac_parse_convert (GstBaseParse * parse,
     GstFormat src_format, gint64 src_value, GstFormat dest_format,
     gint64 * dest_value);
 
-GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
-    GST_TYPE_BASE_PARSE);
-
-static void
-gst_flac_parse_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_factory));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_factory));
-
-  gst_element_class_set_details_simple (element_class, "FLAC audio parser",
-      "Codec/Parser/Audio",
-      "Parses audio with the FLAC lossless audio codec",
-      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
-
-  GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
-      "Flac parser element");
-}
+#define gst_flac_parse_parent_class parent_class
+G_DEFINE_TYPE (GstFlacParse, gst_flac_parse, GST_TYPE_BASE_PARSE);
 
 static void
 gst_flac_parse_class_init (GstFlacParseClass * klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
   GstBaseParseClass *baseparse_class = GST_BASE_PARSE_CLASS (klass);
 
+  GST_DEBUG_CATEGORY_INIT (flacparse_debug, "flacparse", 0,
+      "Flac parser element");
+
   gobject_class->finalize = gst_flac_parse_finalize;
   gobject_class->set_property = gst_flac_parse_set_property;
   gobject_class->get_property = gst_flac_parse_get_property;
@@ -248,10 +233,20 @@ gst_flac_parse_class_init (GstFlacParseClass * klass)
   baseparse_class->pre_push_frame =
       GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
   baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_factory));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_factory));
+
+  gst_element_class_set_details_simple (element_class, "FLAC audio parser",
+      "Codec/Parser/Audio",
+      "Parses audio with the FLAC lossless audio codec",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 }
 
 static void
-gst_flac_parse_init (GstFlacParse * flacparse, GstFlacParseClass * klass)
+gst_flac_parse_init (GstFlacParse * flacparse)
 {
   flacparse->check_frame_checksums = DEFAULT_CHECK_FRAME_CHECKSUMS;
 }
@@ -571,15 +566,16 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
     GstBaseParseFrame * frame, guint * ret)
 {
   GstBuffer *buffer;
-  const guint8 *data;
-  guint max, size, remaining;
+  guint8 *data;
+  gsize size;
+  guint max, remaining;
   guint i, search_start, search_end;
   FrameHeaderCheckReturn header_ret;
   guint16 block_size;
+  gboolean result = FALSE;
 
   buffer = frame->buffer;
-  data = GST_BUFFER_DATA (buffer);
-  size = GST_BUFFER_SIZE (buffer);
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
 
   if (size <= flacparse->min_framesize)
     goto need_more;
@@ -589,10 +585,10 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
       &block_size);
   if (header_ret == FRAME_HEADER_INVALID) {
     *ret = 0;
-    return FALSE;
-  } else if (header_ret == FRAME_HEADER_MORE_DATA) {
-    goto need_more;
+    goto cleanup;
   }
+  if (header_ret == FRAME_HEADER_MORE_DATA)
+    goto need_more;
 
   /* mind unknown framesize */
   search_start = MAX (2, flacparse->min_framesize);
@@ -619,7 +615,8 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
         }
         *ret = i;
         flacparse->block_size = block_size;
-        return TRUE;
+        result = TRUE;
+        goto cleanup;
       } else if (header_ret == FRAME_HEADER_MORE_DATA) {
         goto need_more;
       }
@@ -635,12 +632,14 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
       if (actual_crc == expected_crc) {
         *ret = size;
         flacparse->block_size = block_size;
-        return TRUE;
+        result = TRUE;
+        goto cleanup;
       }
     } else {
       *ret = size;
       flacparse->block_size = block_size;
-      return TRUE;
+      result = TRUE;
+      goto cleanup;
     }
   }
 
@@ -649,7 +648,11 @@ need_more:
   if (max == 16)
     max = 1 << 24;
   *ret = MIN (size + 4096, max);
-  return FALSE;
+  result = TRUE;
+
+cleanup:
+  gst_buffer_unmap (buffer, data, size);
+  return result;
 }
 
 static gboolean
@@ -658,100 +661,124 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
 {
   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
   GstBuffer *buffer = frame->buffer;
-  const guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data;
+  gsize bufsize;
+  gboolean result = TRUE;
+
+  data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
 
-  if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
-    return FALSE;
+  if (G_UNLIKELY (bufsize < 4)) {
+    result = FALSE;
+    goto cleanup;
+  }
 
   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
-    if (memcmp (GST_BUFFER_DATA (buffer), "fLaC", 4) == 0) {
+    if (memcmp (data, "fLaC", 4) == 0) {
       GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
       *framesize = 4;
-      return TRUE;
-    } else if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
+      goto cleanup;
+    }
+    if (data[0] == 0xff && (data[1] >> 2) == 0x3e) {
       GST_DEBUG_OBJECT (flacparse, "Found headerless FLAC");
       /* Minimal size of a frame header */
       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 9);
       flacparse->state = GST_FLAC_PARSE_STATE_GENERATE_HEADERS;
       *skipsize = 0;
-      return FALSE;
-    } else {
-      GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
-      return FALSE;
+      result = FALSE;
+      goto cleanup;
     }
-  } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
+    GST_DEBUG_OBJECT (flacparse, "fLaC marker not found");
+    result = FALSE;
+    goto cleanup;
+  }
+
+  if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
     guint size = 4 + ((data[1] << 16) | (data[2] << 8) | (data[3]));
 
     GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
     *framesize = size;
-    return TRUE;
-  } else {
-    if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
-      gboolean ret;
-      guint next;
+    goto cleanup;
+  }
 
-      flacparse->offset = GST_BUFFER_OFFSET (buffer);
-      flacparse->blocking_strategy = 0;
-      flacparse->block_size = 0;
-      flacparse->sample_number = 0;
-
-      GST_DEBUG_OBJECT (flacparse, "Found sync code");
-      ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
-      if (ret) {
-        *framesize = next;
-        return TRUE;
-      } else {
-        /* If we're at EOS and the frame was not valid, drop it! */
-        if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
-          GST_WARNING_OBJECT (flacparse, "EOS");
-          return FALSE;
-        }
+  if ((GST_READ_UINT16_BE (data) & 0xfffe) == 0xfff8) {
+    gboolean ret;
+    guint next;
 
-        if (next == 0) {
-        } else if (next > GST_BUFFER_SIZE (buffer)) {
-          GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
-          *skipsize = 0;
-          gst_base_parse_set_min_frame_size (parse, next);
-          return FALSE;
-        } else {
-          GST_ERROR_OBJECT (flacparse,
-              "Giving up on invalid frame (%d bytes)",
-              GST_BUFFER_SIZE (buffer));
-          return FALSE;
-        }
-      }
-    } else {
-      GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
-      gint off;
+    flacparse->offset = GST_BUFFER_OFFSET (buffer);
+    flacparse->blocking_strategy = 0;
+    flacparse->block_size = 0;
+    flacparse->sample_number = 0;
 
-      off =
-          gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
-          0, GST_BUFFER_SIZE (buffer));
+    GST_DEBUG_OBJECT (flacparse, "Found sync code");
+    ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
+    if (ret) {
+      *framesize = next;
+      goto cleanup;
+    } else {
+      /* If we're at EOS and the frame was not valid, drop it! */
+      if (G_UNLIKELY (GST_BASE_PARSE_DRAINING (flacparse))) {
+        GST_WARNING_OBJECT (flacparse, "EOS");
+        result = FALSE;
+        goto cleanup;
+      }
 
-      if (off > 0) {
-        GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
-        *skipsize = off;
-        return FALSE;
+      if (next == 0) {
+      } else if (next > bufsize) {
+        GST_DEBUG_OBJECT (flacparse, "Requesting %u bytes", next);
+        *skipsize = 0;
+        gst_base_parse_set_min_frame_size (parse, next);
+        result = FALSE;
+        goto cleanup;
       } else {
-        GST_DEBUG_OBJECT (flacparse, "Sync code not found");
-        *skipsize = GST_BUFFER_SIZE (buffer) - 3;
-        return FALSE;
+        GST_ERROR_OBJECT (flacparse,
+            "Giving up on invalid frame (%d bytes)", bufsize);
+        result = FALSE;
+        goto cleanup;
       }
     }
+  } else {
+    GstByteReader reader;
+    gint off;
+
+    gst_byte_reader_init (&reader, data, bufsize);
+    off =
+        gst_byte_reader_masked_scan_uint32 (&reader, 0xfffc0000, 0xfff80000,
+        0, bufsize);
+
+    if (off > 0) {
+      GST_DEBUG_OBJECT (parse, "Possible sync at buffer offset %d", off);
+      *skipsize = off;
+      result = FALSE;
+      goto cleanup;
+    } else {
+      GST_DEBUG_OBJECT (flacparse, "Sync code not found");
+      *skipsize = bufsize - 3;
+      result = FALSE;
+      goto cleanup;
+    }
   }
 
-  return FALSE;
+  result = FALSE;
+
+cleanup:
+  gst_buffer_unmap (buffer, data, bufsize);
+  return result;
 }
 
 static gboolean
 gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
 {
-  GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);
+  GstBitReader reader;
+  guint8 *data;
+  gsize size;
 
-  if (GST_BUFFER_SIZE (buffer) != 4 + 34) {
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+  gst_bit_reader_init (&reader, data, size);
+
+  if (size != 4 + 34) {
     GST_ERROR_OBJECT (flacparse, "Invalid metablock size for STREAMINFO: %u",
-        GST_BUFFER_SIZE (buffer));
-    return FALSE;
+        size);
+    goto failure;
   }
 
   /* Skip metadata block header */
@@ -780,7 +807,7 @@ gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
     goto error;
   if (flacparse->samplerate == 0) {
     GST_ERROR_OBJECT (flacparse, "Invalid sample rate 0");
-    return FALSE;
+    goto failure;
   }
 
   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->channels, 3))
@@ -789,7 +816,7 @@ gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
   if (flacparse->channels > 8) {
     GST_ERROR_OBJECT (flacparse, "Invalid number of channels %u",
         flacparse->channels);
-    return FALSE;
+    goto failure;
   }
 
   if (!gst_bit_reader_get_bits_uint8 (&reader, &flacparse->bps, 5))
@@ -803,6 +830,8 @@ gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
         GST_FORMAT_DEFAULT, flacparse->total_samples, 0);
   }
 
+  gst_buffer_unmap (buffer, data, size);
+
   GST_DEBUG_OBJECT (flacparse, "STREAMINFO:\n"
       "\tmin/max blocksize: %u/%u,\n"
       "\tmin/max framesize: %u/%u,\n"
@@ -819,6 +848,8 @@ gst_flac_parse_handle_streaminfo (GstFlacParse * flacparse, GstBuffer * buffer)
 
 error:
   GST_ERROR_OBJECT (flacparse, "Failed to read data");
+failure:
+  gst_buffer_unmap (buffer, data, size);
   return FALSE;
 }
 
@@ -826,8 +857,13 @@ static gboolean
 gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
     GstBuffer * buffer)
 {
-  flacparse->tags = gst_tag_list_from_vorbiscomment_buffer (buffer,
-      GST_BUFFER_DATA (buffer), 4, NULL);
+  guint8 *data;
+  gsize size;
+
+  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
+
+  flacparse->tags = gst_tag_list_from_vorbiscomment (data, size, data, 4, NULL);
+  gst_buffer_unmap (buffer, data, size);
 
   if (flacparse->tags == NULL) {
     GST_ERROR_OBJECT (flacparse, "Invalid vorbiscomment block");
@@ -842,11 +878,15 @@ gst_flac_parse_handle_vorbiscomment (GstFlacParse * flacparse,
 static gboolean
 gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
 {
-  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer);
-  const guint8 *data = GST_BUFFER_DATA (buffer);
+  GstByteReader reader;
+  guint8 *data;
+  gsize bufsize;
   guint32 img_len = 0, img_type = 0;
   guint32 img_mimetype_len = 0, img_description_len = 0;
 
+  data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
+  gst_byte_reader_init (&reader, data, bufsize);
+
   if (!gst_byte_reader_skip (&reader, 4))
     goto error;
 
@@ -880,10 +920,12 @@ gst_flac_parse_handle_picture (GstFlacParse * flacparse, GstBuffer * buffer)
     flacparse->tags = NULL;
   }
 
+  gst_buffer_unmap (buffer, data, bufsize);
   return TRUE;
 
 error:
   GST_ERROR_OBJECT (flacparse, "Error reading data");
+  gst_buffer_unmap (buffer, data, bufsize);
   return FALSE;
 }
 
@@ -904,6 +946,8 @@ gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
 {
   GstByteReader br;
   gint64 offset = 0, samples = 0;
+  gpointer data;
+  gsize bufsize;
 
   GST_DEBUG_OBJECT (flacparse,
       "parsing seektable; base offset %" G_GINT64_FORMAT, boffset);
@@ -911,7 +955,9 @@ gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
   if (boffset <= 0)
     goto done;
 
-  gst_byte_reader_init_from_buffer (&br, flacparse->seektable);
+  data = gst_buffer_map (flacparse->seektable, &bufsize, NULL, GST_MAP_READ);
+  gst_byte_reader_init (&br, data, bufsize);
+
   /* skip header */
   if (!gst_byte_reader_skip (&br, 4))
     goto done;
@@ -937,6 +983,7 @@ gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset)
   }
 
 done:
+  gst_buffer_unmap (flacparse->seektable, data, bufsize);
   gst_buffer_unref (flacparse->seektable);
   flacparse->seektable = NULL;
 }
@@ -978,8 +1025,10 @@ gst_flac_parse_handle_headers (GstFlacParse * flacparse)
 
   for (l = flacparse->headers; l; l = l->next) {
     GstBuffer *header = l->data;
-    const guint8 *data = GST_BUFFER_DATA (header);
-    guint size = GST_BUFFER_SIZE (header);
+    guint8 *data;
+    gsize size;
+
+    data = gst_buffer_map (header, &size, NULL, GST_MAP_READ);
 
     GST_BUFFER_FLAG_SET (header, GST_BUFFER_FLAG_IN_CAPS);
 
@@ -990,6 +1039,8 @@ gst_flac_parse_handle_headers (GstFlacParse * flacparse)
     } else if (size > 1 && (data[0] & 0x7f) == 4) {
       vorbiscomment = header;
     }
+
+    gst_buffer_unmap (header, data, size);
   }
 
   if (marker == NULL || streaminfo == NULL || vorbiscomment == NULL) {
@@ -1005,21 +1056,29 @@ gst_flac_parse_handle_headers (GstFlacParse * flacparse)
   {
     GstBuffer *buf;
     guint16 num;
+    guint8 *sinfodata, *writedata;
+    gsize sinfosize, writesize;
+
+    sinfodata = gst_buffer_map (streaminfo, &sinfosize, NULL, GST_MAP_READ);
 
     /* minus one for the marker that is merged with streaminfo here */
     num = g_list_length (flacparse->headers) - 1;
 
-    buf = gst_buffer_new_and_alloc (13 + GST_BUFFER_SIZE (streaminfo));
-    GST_BUFFER_DATA (buf)[0] = 0x7f;
-    memcpy (GST_BUFFER_DATA (buf) + 1, "FLAC", 4);
-    GST_BUFFER_DATA (buf)[5] = 0x01;    /* mapping version major */
-    GST_BUFFER_DATA (buf)[6] = 0x00;    /* mapping version minor */
-    GST_BUFFER_DATA (buf)[7] = (num & 0xFF00) >> 8;
-    GST_BUFFER_DATA (buf)[8] = (num & 0x00FF) >> 0;
-    memcpy (GST_BUFFER_DATA (buf) + 9, "fLaC", 4);
-    memcpy (GST_BUFFER_DATA (buf) + 13, GST_BUFFER_DATA (streaminfo),
-        GST_BUFFER_SIZE (streaminfo));
+    buf = gst_buffer_new_and_alloc (13 + sinfosize);
+    writedata = gst_buffer_map (buf, &writesize, NULL, GST_MAP_WRITE);
+
+    writedata[0] = 0x7f;
+    memcpy (writedata + 1, "FLAC", 4);
+    writedata[5] = 0x01;        /* mapping version major */
+    writedata[6] = 0x00;        /* mapping version minor */
+    writedata[7] = (num & 0xFF00) >> 8;
+    writedata[8] = (num & 0x00FF) >> 0;
+    memcpy (writedata + 9, "fLaC", 4);
+    memcpy (writedata + 13, sinfodata, sinfosize);
     _value_array_append_buffer (&array, buf);
+
+    gst_buffer_unmap (streaminfo, sinfodata, sinfosize);
+    gst_buffer_unmap (buf, writedata, writesize);
     gst_buffer_unref (buf);
   }
 
@@ -1053,9 +1112,7 @@ push_headers:
 
     flacparse->headers =
         g_list_delete_link (flacparse->headers, flacparse->headers);
-    buf = gst_buffer_make_metadata_writable (buf);
-    gst_buffer_set_caps (buf,
-        GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
+    buf = gst_buffer_make_writable (buf);
 
     /* init, set and give away frame */
     gst_base_parse_frame_init (&frame);
@@ -1079,9 +1136,12 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse)
 {
   GstBuffer *marker, *streaminfo, *vorbiscomment;
   guint8 *data;
+  gsize bufsize;
 
   marker = gst_buffer_new_and_alloc (4);
-  memcpy (GST_BUFFER_DATA (marker), "fLaC", 4);
+  data = gst_buffer_map (marker, &bufsize, NULL, GST_MAP_WRITE);
+  memcpy (data, "fLaC", 4);
+  gst_buffer_unmap (marker, data, bufsize);
   GST_BUFFER_TIMESTAMP (marker) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_DURATION (marker) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_OFFSET (marker) = 0;
@@ -1089,7 +1149,7 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse)
   flacparse->headers = g_list_append (flacparse->headers, marker);
 
   streaminfo = gst_buffer_new_and_alloc (4 + 34);
-  data = GST_BUFFER_DATA (streaminfo);
+  data = gst_buffer_map (streaminfo, &bufsize, NULL, GST_MAP_WRITE);
   memset (data, 0, 4 + 34);
 
   /* metadata block header */
@@ -1138,6 +1198,7 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse)
   }
   /* MD5 = 0; */
 
+  gst_buffer_unmap (streaminfo, data, bufsize);
   GST_BUFFER_TIMESTAMP (streaminfo) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_DURATION (streaminfo) = GST_CLOCK_TIME_NONE;
   GST_BUFFER_OFFSET (streaminfo) = 0;
@@ -1157,23 +1218,27 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse)
         sizeof (header), NULL);
     gst_tag_list_free (taglist);
 
+    data = gst_buffer_map (vorbiscomment, &bufsize, NULL, GST_MAP_WRITE);
+
     /* Get rid of framing bit */
-    if (GST_BUFFER_DATA (vorbiscomment)[GST_BUFFER_SIZE (vorbiscomment) -
-            1] == 1) {
+    if (data[bufsize - 1] == 1) {
       GstBuffer *sub;
 
       sub =
-          gst_buffer_create_sub (vorbiscomment, 0,
-          GST_BUFFER_SIZE (vorbiscomment) - 1);
+          gst_buffer_copy_region (vorbiscomment, GST_BUFFER_COPY_ALL, 0,
+          bufsize - 1);
+      gst_buffer_unmap (vorbiscomment, data, bufsize);
       gst_buffer_unref (vorbiscomment);
       vorbiscomment = sub;
+      data = gst_buffer_map (vorbiscomment, &bufsize, NULL, GST_MAP_WRITE);
     }
 
-    size = GST_BUFFER_SIZE (vorbiscomment) - 4;
-    GST_BUFFER_DATA (vorbiscomment)[1] = ((size & 0xFF0000) >> 16);
-    GST_BUFFER_DATA (vorbiscomment)[2] = ((size & 0x00FF00) >> 8);
-    GST_BUFFER_DATA (vorbiscomment)[3] = (size & 0x0000FF);
+    size = bufsize - 4;
+    data[1] = ((size & 0xFF0000) >> 16);
+    data[2] = ((size & 0x00FF00) >> 8);
+    data[3] = (size & 0x0000FF);
 
+    gst_buffer_unmap (vorbiscomment, data, bufsize);
     GST_BUFFER_TIMESTAMP (vorbiscomment) = GST_CLOCK_TIME_NONE;
     GST_BUFFER_DURATION (vorbiscomment) = GST_CLOCK_TIME_NONE;
     GST_BUFFER_OFFSET (vorbiscomment) = 0;
@@ -1189,7 +1254,11 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
   GstBuffer *buffer = frame->buffer;
-  const guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data = NULL;
+  gsize bufsize;
+  GstFlowReturn res = GST_FLOW_ERROR;
+
+  data = gst_buffer_map (buffer, &bufsize, NULL, GST_MAP_READ);
 
   if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
     GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
@@ -1204,14 +1273,15 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
     flacparse->headers =
         g_list_append (flacparse->headers, gst_buffer_ref (buffer));
 
-    return GST_BASE_PARSE_FLOW_DROPPED;
+    res = GST_BASE_PARSE_FLOW_DROPPED;
   } else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
     gboolean is_last = ((data[0] & 0x80) == 0x80);
     guint type = (data[0] & 0x7F);
 
     if (type == 127) {
       GST_WARNING_OBJECT (flacparse, "Invalid metadata block type");
-      return GST_BASE_PARSE_FLOW_DROPPED;
+      res = GST_BASE_PARSE_FLOW_DROPPED;
+      goto cleanup;
     }
 
     GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
@@ -1219,19 +1289,19 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
     switch (type) {
       case 0:                  /* STREAMINFO */
         if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
-          return GST_FLOW_ERROR;
+          goto cleanup;
         break;
       case 3:                  /* SEEKTABLE */
         if (!gst_flac_parse_handle_seektable (flacparse, buffer))
-          return GST_FLOW_ERROR;
+          goto cleanup;
         break;
       case 4:                  /* VORBIS_COMMENT */
         if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
-          return GST_FLOW_ERROR;
+          goto cleanup;
         break;
       case 6:                  /* PICTURE */
         if (!gst_flac_parse_handle_picture (flacparse, buffer))
-          return GST_FLOW_ERROR;
+          goto cleanup;
         break;
       case 1:                  /* PADDING */
       case 2:                  /* APPLICATION */
@@ -1250,7 +1320,7 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
 
     if (is_last) {
       if (!gst_flac_parse_handle_headers (flacparse))
-        return GST_FLOW_ERROR;
+        goto cleanup;
 
       /* Minimal size of a frame header */
       gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
@@ -1259,7 +1329,7 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
     }
 
     /* DROPPED because we pushed already or will push all headers manually */
-    return GST_BASE_PARSE_FLOW_DROPPED;
+    res = GST_BASE_PARSE_FLOW_DROPPED;
   } else {
     if (flacparse->offset != GST_BUFFER_OFFSET (buffer)) {
       FrameHeaderCheckReturn ret;
@@ -1267,17 +1337,17 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
       flacparse->offset = GST_BUFFER_OFFSET (buffer);
       ret =
           gst_flac_parse_frame_header_is_valid (flacparse,
-          GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), TRUE, NULL);
+          data, bufsize, TRUE, NULL);
       if (ret != FRAME_HEADER_VALID) {
         GST_ERROR_OBJECT (flacparse,
             "Baseclass didn't provide a complete frame");
-        return GST_FLOW_ERROR;
+        goto cleanup;
       }
     }
 
     if (flacparse->block_size == 0) {
       GST_ERROR_OBJECT (flacparse, "Unparsed frame");
-      return GST_FLOW_ERROR;
+      goto cleanup;
     }
 
     if (flacparse->seektable)
@@ -1289,15 +1359,15 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
             "Generating headers for variable blocksize streams not supported");
 
         if (!gst_flac_parse_handle_headers (flacparse))
-          return GST_FLOW_ERROR;
+          goto cleanup;
       } else {
         GST_DEBUG_OBJECT (flacparse, "Generating headers");
 
         if (!gst_flac_parse_generate_headers (flacparse))
-          return GST_FLOW_ERROR;
+          goto cleanup;
 
         if (!gst_flac_parse_handle_headers (flacparse))
-          return GST_FLOW_ERROR;
+          goto cleanup;
       }
       flacparse->state = GST_FLAC_PARSE_STATE_DATA;
     }
@@ -1336,8 +1406,14 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
     flacparse->blocking_strategy = 0;
     flacparse->block_size = 0;
     flacparse->sample_number = 0;
-    return GST_FLOW_OK;
+    res = GST_FLOW_OK;
   }
+
+cleanup:
+  if (data)
+    gst_buffer_unmap (buffer, data, bufsize);
+
+  return res;
 }
 
 static GstFlowReturn
index 0c55704..badc901 100644 (file)
@@ -98,8 +98,8 @@ static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
     GstFormat src_format, gint64 src_value,
     GstFormat dest_format, gint64 * dest_value);
 
-GST_BOILERPLATE (GstMpegAudioParse, gst_mpeg_audio_parse, GstBaseParse,
-    GST_TYPE_BASE_PARSE);
+#define gst_mpeg_audio_parse_parent_class parent_class
+G_DEFINE_TYPE (GstMpegAudioParse, gst_mpeg_audio_parse, GST_TYPE_BASE_PARSE);
 
 #define GST_TYPE_MPEG_AUDIO_CHANNEL_MODE  \
     (gst_mpeg_audio_channel_mode_get_type())
@@ -138,26 +138,10 @@ gst_mpeg_audio_channel_mode_get_nick (gint mode)
 }
 
 static void
-gst_mpeg_audio_parse_base_init (gpointer klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_template));
-
-  gst_element_class_set_details_simple (element_class, "MPEG1 Audio Parser",
-      "Codec/Parser/Audio",
-      "Parses and frames mpeg1 audio streams (levels 1-3), provides seek",
-      "Jan Schmidt <thaytan@mad.scientist.com>,"
-      "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
-}
-
-static void
 gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass)
 {
   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   GST_DEBUG_CATEGORY_INIT (mpeg_audio_parse_debug, "mpegaudioparse", 0,
@@ -185,6 +169,17 @@ gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass)
       "channel mode", "MPEG audio channel mode", NULL);
 
   g_type_class_ref (GST_TYPE_MPEG_AUDIO_CHANNEL_MODE);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&sink_template));
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&src_template));
+
+  gst_element_class_set_details_simple (element_class, "MPEG1 Audio Parser",
+      "Codec/Parser/Audio",
+      "Parses and frames mpeg1 audio streams (levels 1-3), provides seek",
+      "Jan Schmidt <thaytan@mad.scientist.com>,"
+      "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
 }
 
 static void
@@ -220,8 +215,7 @@ gst_mpeg_audio_parse_reset (GstMpegAudioParse * mp3parse)
 }
 
 static void
-gst_mpeg_audio_parse_init (GstMpegAudioParse * mp3parse,
-    GstMpegAudioParseClass * klass)
+gst_mpeg_audio_parse_init (GstMpegAudioParse * mp3parse)
 {
   gst_mpeg_audio_parse_reset (mp3parse);
 }
@@ -374,13 +368,13 @@ gst_mp3parse_validate_extended (GstMpegAudioParse * mp3parse, GstBuffer * buf,
     guint32 header, int bpf, gboolean at_eos, gint * valid)
 {
   guint32 next_header;
-  const guint8 *data;
-  guint available;
+  guint8 *data;
+  gsize available;
+  gboolean res = TRUE;
   int frames_found = 1;
   int offset = bpf;
 
-  available = GST_BUFFER_SIZE (buf);
-  data = GST_BUFFER_DATA (buf);
+  data = gst_buffer_map (buf, &available, NULL, GST_MAP_READ);
 
   while (frames_found < MIN_RESYNC_FRAMES) {
     /* Check if we have enough data for all these frames, plus the next
@@ -389,10 +383,11 @@ gst_mp3parse_validate_extended (GstMpegAudioParse * mp3parse, GstBuffer * buf,
       if (at_eos) {
         /* Running out of data at EOS is fine; just accept it */
         *valid = TRUE;
-        return TRUE;
+        goto cleanup;
       } else {
         *valid = offset + 4;
-        return FALSE;
+        res = FALSE;
+        goto cleanup;
       }
     }
 
@@ -413,14 +408,14 @@ gst_mp3parse_validate_extended (GstMpegAudioParse * mp3parse, GstBuffer * buf,
           (guint) header, (guint) header & HDRMASK, (guint) next_header,
           (guint) next_header & HDRMASK, bpf);
       *valid = FALSE;
-      return TRUE;
+      goto cleanup;
     } else if ((((next_header >> 12) & 0xf) == 0) ||
         (((next_header >> 12) & 0xf) == 0xf)) {
       /* The essential parts were the same, but the bitrate held an
          invalid value - also reject */
       GST_DEBUG_OBJECT (mp3parse, "next header invalid (bitrate)");
       *valid = FALSE;
-      return TRUE;
+      goto cleanup;
     }
 
     bpf = mp3_type_frame_length_from_header (mp3parse, next_header,
@@ -431,7 +426,10 @@ gst_mp3parse_validate_extended (GstMpegAudioParse * mp3parse, GstBuffer * buf,
   }
 
   *valid = TRUE;
-  return TRUE;
+
+cleanup:
+  gst_buffer_unmap (buf, data, available);
+  return res;
 }
 
 static gboolean
@@ -487,37 +485,43 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
 {
   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
   GstBuffer *buf = frame->buffer;
-  GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+  GstByteReader reader;
   gint off, bpf;
   gboolean lost_sync, draining, valid, caps_change;
   guint32 header;
   guint bitrate, layer, rate, channels, version, mode, crc;
+  guint8 *data;
+  gsize bufsize;
+  gboolean res = FALSE;
 
-  if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
-    return FALSE;
+  data = gst_buffer_map (buf, &bufsize, NULL, GST_MAP_READ);
+  if (G_UNLIKELY (bufsize < 6))
+    goto cleanup;
+
+  gst_byte_reader_init (&reader, data, bufsize);
 
   off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffe00000, 0xffe00000,
-      0, GST_BUFFER_SIZE (buf));
+      0, bufsize);
 
   GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
 
   /* didn't find anything that looks like a sync word, skip */
   if (off < 0) {
-    *skipsize = GST_BUFFER_SIZE (buf) - 3;
-    return FALSE;
+    *skipsize = bufsize - 3;
+    goto cleanup;
   }
 
   /* possible frame header, but not at offset 0? skip bytes before sync */
   if (off > 0) {
     *skipsize = off;
-    return FALSE;
+    goto cleanup;
   }
 
   /* make sure the values in the frame header look sane */
-  header = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf));
+  header = GST_READ_UINT32_BE (data);
   if (!gst_mpeg_audio_parse_head_check (mp3parse, header)) {
     *skipsize = 1;
-    return FALSE;
+    goto cleanup;
   }
 
   GST_LOG_OBJECT (parse, "got frame");
@@ -541,21 +545,25 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
       /* not enough data */
       gst_base_parse_set_min_frame_size (parse, valid);
       *skipsize = 0;
-      return FALSE;
+      goto cleanup;
     } else {
       if (!valid) {
         *skipsize = off + 2;
-        return FALSE;
+        goto cleanup;
       }
     }
   } else if (draining && lost_sync && caps_change && mp3parse->rate > 0) {
     /* avoid caps jitter that we can't be sure of */
     *skipsize = off + 2;
-    return FALSE;
+    goto cleanup;
   }
 
   *framesize = bpf;
-  return TRUE;
+  res = TRUE;
+
+cleanup:
+  gst_buffer_unmap (buf, data, bufsize);
+  return res;
 }
 
 static void
@@ -571,7 +579,8 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
   gint64 upstream_total_bytes = 0;
   GstFormat fmt = GST_FORMAT_BYTES;
   guint32 read_id_xing = 0, read_id_vbri = 0;
-  const guint8 *data;
+  guint8 *data, *origdata;
+  gsize bufsize;
   guint bitrate;
 
   if (mp3parse->sent_codec_tag)
@@ -598,8 +607,8 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
   offset_vbri += 4;
 
   /* Check if we have enough data to read the Xing header */
-  avail = GST_BUFFER_SIZE (buf);
-  data = GST_BUFFER_DATA (buf);
+  origdata = data = gst_buffer_map (buf, &bufsize, NULL, GST_MAP_READ);
+  avail = bufsize;
 
   if (avail >= offset_xing + 4) {
     read_id_xing = GST_READ_UINT32_BE (data + offset_xing);
@@ -639,7 +648,7 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
     if (avail < bytes_needed) {
       GST_DEBUG_OBJECT (mp3parse,
           "Not enough data to read Xing header (need %d)", bytes_needed);
-      return;
+      goto cleanup;
     }
 
     GST_DEBUG_OBJECT (mp3parse, "Reading Xing header");
@@ -795,7 +804,7 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
     if (avail < offset_vbri + 26) {
       GST_DEBUG_OBJECT (mp3parse,
           "Not enough data to read VBRI header (need %d)", offset_vbri + 26);
-      return;
+      goto cleanup;
     }
 
     GST_DEBUG_OBJECT (mp3parse, "Reading VBRI header");
@@ -806,7 +815,7 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
     if (GST_READ_UINT16_BE (data) != 0x0001) {
       GST_WARNING_OBJECT (mp3parse,
           "Unsupported VBRI version 0x%x", GST_READ_UINT16_BE (data));
-      return;
+      goto cleanup;
     }
     data += 2;
 
@@ -879,10 +888,10 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
         GST_DEBUG_OBJECT (mp3parse,
             "Not enough data to read VBRI header (need %d)",
             offset_vbri + 26 + nseek_points * seek_bytes);
-        return;
+        goto cleanup;
       }
 
-      data = GST_BUFFER_DATA (buf);
+      data = origdata;
       data += offset_vbri + 26;
 
       /* VBRI seek table: frame/seek_frames -> byte */
@@ -956,6 +965,9 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
     bitrate = 0;
 
   gst_base_parse_set_average_bitrate (GST_BASE_PARSE (mp3parse), bitrate);
+
+cleanup:
+  gst_buffer_unmap (buf, origdata, bufsize);
 }
 
 static GstFlowReturn
@@ -964,12 +976,16 @@ gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
 {
   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
   GstBuffer *buf = frame->buffer;
+  guint8 *data;
+  gsize bufsize;
   guint bitrate, layer, rate, channels, version, mode, crc;
 
-  g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 4, GST_FLOW_ERROR);
+  data = gst_buffer_map (buf, &bufsize, NULL, GST_MAP_READ);
+  if (G_UNLIKELY (bufsize < 4))
+    goto short_buffer;
 
   if (!mp3_type_frame_length_from_header (mp3parse,
-          GST_READ_UINT32_BE (GST_BUFFER_DATA (buf)),
+          GST_READ_UINT32_BE (data),
           &version, &layer, &channels, &bitrate, &rate, &mode, &crc))
     goto broken_header;
 
@@ -981,7 +997,6 @@ gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
         "layer", G_TYPE_INT, layer,
         "rate", G_TYPE_INT, rate,
         "channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
-    gst_buffer_set_caps (buf, caps);
     gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
     gst_caps_unref (caps);
 
@@ -1025,15 +1040,23 @@ gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
   mp3parse->last_crc = crc;
   mp3parse->last_mode = mode;
 
+  gst_buffer_unmap (buf, data, bufsize);
   return GST_FLOW_OK;
 
 /* ERRORS */
 broken_header:
   {
     /* this really shouldn't ever happen */
+    gst_buffer_unmap (buf, data, bufsize);
     GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
     return GST_FLOW_ERROR;
   }
+
+short_buffer:
+  {
+    gst_buffer_unmap (buf, data, bufsize);
+    return GST_FLOW_ERROR;
+  }
 }
 
 static gboolean