Пример #1
0
static guint
find_psc (GstBuffer * buffer, guint skip)
{
  GstMapInfo map;
  GstByteReader br;
  guint psc_pos = -1, psc;

  gst_buffer_map (buffer, &map, GST_MAP_READ);
  gst_byte_reader_init (&br, map.data, map.size);

  if (!gst_byte_reader_set_pos (&br, skip))
    goto out;

  if (gst_byte_reader_peek_uint24_be (&br, &psc) == FALSE)
    goto out;

  /* Scan for the picture start code (22 bits - 0x0020) */
  while ((gst_byte_reader_get_remaining (&br) >= 3)) {
    if (gst_byte_reader_peek_uint24_be (&br, &psc) &&
        ((psc & 0xffffc0) == 0x000080)) {
      psc_pos = gst_byte_reader_get_pos (&br);
      break;
    } else if (gst_byte_reader_skip (&br, 1) == FALSE)
      break;
  }

out:
  gst_buffer_unmap (buffer, &map);
  return psc_pos;
}
Пример #2
0
static GstFlowReturn
gst_jp2k_decimator_decimate_jpc (GstJP2kDecimator * self, GstBuffer * inbuf,
    GstBuffer ** outbuf_)
{
  GstBuffer *outbuf = NULL;
  GstFlowReturn ret = GST_FLOW_OK;
  GstMapInfo info;
  GstByteReader reader;
  GstByteWriter writer;
  MainHeader main_header;


  if (!gst_buffer_map (inbuf, &info, GST_MAP_READ)) {
    GST_ELEMENT_ERROR (self, STREAM, WRONG_TYPE, ("Unable to map memory"),
        (NULL));
    gst_buffer_unref (inbuf);
    return GST_FLOW_ERROR;
  }

  gst_byte_reader_init (&reader, info.data, info.size);
  gst_byte_writer_init_with_size (&writer, gst_buffer_get_size (inbuf), FALSE);

  /* main header */
  memset (&main_header, 0, sizeof (MainHeader));
  ret = parse_main_header (self, &reader, &main_header);
  if (ret != GST_FLOW_OK)
    goto done;

  ret = decimate_main_header (self, &main_header);
  if (ret != GST_FLOW_OK)
    goto done;

  ret = write_main_header (self, &writer, &main_header);
  if (ret != GST_FLOW_OK)
    goto done;

  outbuf = gst_byte_writer_reset_and_get_buffer (&writer);
  gst_buffer_copy_into (outbuf, inbuf, GST_BUFFER_COPY_METADATA, 0, -1);

  GST_DEBUG_OBJECT (self,
      "Decimated buffer from %" G_GSIZE_FORMAT " bytes to %" G_GSIZE_FORMAT
      " bytes (%.2lf%%)",
      gst_buffer_get_size (inbuf), gst_buffer_get_size (outbuf),
      (100 * gst_buffer_get_size (outbuf)) /
      ((gdouble) gst_buffer_get_size (inbuf)));

done:
  gst_buffer_unmap (inbuf, &info);

  *outbuf_ = outbuf;
  reset_main_header (self, &main_header);
  gst_buffer_unref (inbuf);

  return ret;
}
Пример #3
0
EXPORT_C
#endif

void
gst_byte_reader_init_from_buffer (GstByteReader * reader,
    const GstBuffer * buffer)
{
  g_return_if_fail (GST_IS_BUFFER (buffer));

  gst_byte_reader_init (reader, GST_BUFFER_DATA (buffer),
      GST_BUFFER_SIZE (buffer));
}
Пример #4
0
static void
gst_cenc_decrypt_parse_pssh_box (GstCencDecrypt * self, GstBuffer * pssh)
{
  GstMapInfo info;
  GstByteReader br;
  guint8 version;
  guint32 data_size;

  gst_buffer_map (pssh, &info, GST_MAP_READ);
  gst_byte_reader_init (&br, info.data, info.size);

  gst_byte_reader_skip_unchecked (&br, 8);
  version = gst_byte_reader_get_uint8_unchecked (&br);
  GST_DEBUG_OBJECT (self, "pssh version: %u", version);
  gst_byte_reader_skip_unchecked (&br, 19);

  if (version > 0) {
    /* Parse KeyIDs */
    guint32 key_id_count = 0;
    const guint8 *key_id_data = NULL;
    const guint key_id_size = 16;

    key_id_count = gst_byte_reader_get_uint32_be_unchecked (&br);
    GST_DEBUG_OBJECT (self, "there are %u key IDs", key_id_count);
    key_id_data = gst_byte_reader_get_data_unchecked (&br, key_id_count * 16);

    while (key_id_count > 0) {
      gchar *key_id_string = gst_cenc_create_uuid_string (key_id_data);
      GST_DEBUG_OBJECT (self, "key_id: %s", key_id_string);
      g_free (key_id_string);
      key_id_data += key_id_size;
      --key_id_count;
    }
  }

  /* Parse Data */
  data_size = gst_byte_reader_get_uint32_be_unchecked (&br);
  GST_DEBUG_OBJECT (self, "pssh data size: %u", data_size);

  if (data_size > 0U) {
    gpointer data =
        g_memdup (gst_byte_reader_get_data_unchecked (&br, data_size),
        data_size);
    GstBuffer *buf = gst_buffer_new_wrapped (data, data_size);
    GST_DEBUG_OBJECT (self, "cenc protection system data size: %"
        G_GSIZE_FORMAT, gst_buffer_get_size (buf));
    gst_buffer_unref (buf);
  }
  gst_buffer_unmap (pssh, &info);
}
Пример #5
0
GstIsoffParserResult
gst_isoff_sidx_parser_add_buffer (GstSidxParser * parser, GstBuffer * buffer,
    guint * consumed)
{
  GstIsoffParserResult res = GST_ISOFF_PARSER_OK;
  GstByteReader reader;
  GstMapInfo info;
  guint32 fourcc;

  if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
    *consumed = 0;
    return GST_ISOFF_PARSER_ERROR;
  }

  gst_byte_reader_init (&reader, info.data, info.size);

  if (parser->status == GST_ISOFF_SIDX_PARSER_INIT) {
    if (!gst_isoff_parse_box_header (&reader, &fourcc, NULL, NULL,
            &parser->size))
      goto done;

    if (fourcc != GST_ISOFF_FOURCC_SIDX) {
      res = GST_ISOFF_PARSER_UNEXPECTED;
      gst_byte_reader_set_pos (&reader, 0);
      goto done;
    }

    if (parser->size == 0) {
      res = GST_ISOFF_PARSER_ERROR;
      gst_byte_reader_set_pos (&reader, 0);
      goto done;
    }

    /* Try again once we have enough data for the FullBox header */
    if (gst_byte_reader_get_remaining (&reader) < 4) {
      gst_byte_reader_set_pos (&reader, 0);
      goto done;
    }
  }

  res = gst_isoff_sidx_parser_parse (parser, &reader, consumed);

done:
  gst_buffer_unmap (buffer, &info);
  return res;
}
/**
 * gst_h263_parse:
 * @packet: The #GstMpeg4Packet to fill
 * @offset: offset from which to start the parsing
 * @data: The data to parse
 * @size: The size of the @data to parse
 *
 * Parses @data and fills @packet with the information of the next packet
 * found.
 *
 * Note that the type of the packet is meaningless in this case.
 *
 * Returns: a #GstMpeg4ParseResult
 */
GstMpeg4ParseResult
gst_h263_parse (GstMpeg4Packet * packet,
    const guint8 * data, guint offset, gsize size)
{
  gint off1, off2;
  GstByteReader br;

  gst_byte_reader_init (&br, data + offset, size - offset);

  g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR);

  if (size - offset < 3) {
    GST_DEBUG ("Can't parse, buffer is to small size %" G_GSIZE_FORMAT
        " at offset %d", size, offset);
    return GST_MPEG4_PARSER_ERROR;
  }

  off1 = find_psc (&br);

  if (off1 == -1) {
    GST_DEBUG ("No start code prefix in this buffer");
    return GST_MPEG4_PARSER_NO_PACKET;
  }

  packet->offset = off1 + offset;
  packet->data = data;

  gst_byte_reader_skip_unchecked (&br, 3);
  off2 = find_psc (&br);

  if (off2 == -1) {
    GST_DEBUG ("Packet start %d, No end found", off1);

    packet->size = G_MAXUINT;
    return GST_MPEG4_PARSER_NO_PACKET_END;
  }

  packet->size = (gsize) off2 - off1;

  GST_DEBUG ("Complete packet found at: %d, Size: %" G_GSIZE_FORMAT,
      packet->offset, packet->size);

  return GST_MPEG4_PARSER_OK;
}
/**
 * gst_mpeg4_next_resync:
 * @packet: The #GstMpeg4Packet to fill
 * @vop: The previously parsed #GstMpeg4VideoObjectPlane
 * @offset: offset from which to start the parsing
 * @data: The data to parse
 * @size: The size of the @data to parse
 *
 * Parses @data and fills @packet with the information of the next resync packet
 * found.
 *
 * Returns: a #GstMpeg4ParseResult
 */
static GstMpeg4ParseResult
gst_mpeg4_next_resync (GstMpeg4Packet * packet,
    const GstMpeg4VideoObjectPlane * vop, const guint8 * data, gsize size,
    gboolean first_resync_marker)
{
  guint markersize = 0, off1, off2;
  guint32 mask = 0xff, pattern = 0xff;
  GstByteReader br;

  gst_byte_reader_init (&br, data, size);

  g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR);
  g_return_val_if_fail (vop != NULL, GST_MPEG4_PARSER_ERROR);

  markersize = compute_resync_marker_size (vop, &pattern, &mask);

  if (first_resync_marker) {
    off1 = 0;
  } else {
    off1 = gst_byte_reader_masked_scan_uint32 (&br, mask, pattern, 0, size);
  }

  if (off1 == -1)
    return GST_MPEG4_PARSER_NO_PACKET;

  GST_DEBUG ("Resync code found at %i", off1);

  packet->offset = off1;
  packet->type = GST_MPEG4_RESYNC;
  packet->marker_size = markersize;

  off2 = gst_byte_reader_masked_scan_uint32 (&br, mask, pattern,
      off1 + 2, size - off1 - 2);

  if (off2 == -1)
    return GST_MPEG4_PARSER_NO_PACKET_END;

  packet->size = off2 - off1;

  return GST_MPEG4_PARSER_OK;
}
Пример #8
0
static GstFlowReturn
gst_png_parse_handle_frame (GstBaseParse * parse,
                            GstBaseParseFrame * frame, gint * skipsize)
{
    GstPngParse *pngparse = GST_PNG_PARSE (parse);
    GstMapInfo map;
    GstByteReader reader;
    GstFlowReturn ret = GST_FLOW_OK;
    guint64 signature;
    guint width = 0, height = 0;

    gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
    gst_byte_reader_init (&reader, map.data, map.size);

    if (!gst_byte_reader_peek_uint64_be (&reader, &signature))
        goto beach;

    if (signature != PNG_SIGNATURE) {
        for (;;) {
            guint offset;

            offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
                     0x89504E47, 0, gst_byte_reader_get_remaining (&reader));

            if (offset == -1) {
                *skipsize = gst_byte_reader_get_remaining (&reader) - 4;
                goto beach;
            }

            gst_byte_reader_skip (&reader, offset);

            if (!gst_byte_reader_peek_uint64_be (&reader, &signature))
                goto beach;

            if (signature == PNG_SIGNATURE) {
                /* We're skipping, go out, we'll be back */
                *skipsize = gst_byte_reader_get_pos (&reader);
                goto beach;
            }
            gst_byte_reader_skip (&reader, 4);
        }
    }

    gst_byte_reader_skip (&reader, 8);

    for (;;) {
        guint32 length;
        guint32 code;

        if (!gst_byte_reader_get_uint32_be (&reader, &length))
            goto beach;
        if (!gst_byte_reader_get_uint32_le (&reader, &code))
            goto beach;

        if (code == GST_MAKE_FOURCC ('I', 'H', 'D', 'R')) {
            if (!gst_byte_reader_get_uint32_be (&reader, &width))
                goto beach;
            if (!gst_byte_reader_get_uint32_be (&reader, &height))
                goto beach;
            length -= 8;
        }

        if (!gst_byte_reader_skip (&reader, length + 4))
            goto beach;

        if (code == GST_MAKE_FOURCC ('I', 'E', 'N', 'D')) {
            if (pngparse->width != width || pngparse->height != height) {
                GstCaps *caps;

                pngparse->height = height;
                pngparse->width = width;

                caps = gst_caps_new_simple ("image/png",
                                            "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
                if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps)) {
                    ret = GST_FLOW_NOT_NEGOTIATED;
                }
                gst_caps_unref (caps);

                if (ret != GST_FLOW_OK)
                    goto beach;
            }


            gst_buffer_unmap (frame->buffer, &map);
            return gst_base_parse_finish_frame (parse, frame,
                                                gst_byte_reader_get_pos (&reader));
        }
    }

beach:

    gst_buffer_unmap (frame->buffer, &map);

    return ret;
}
Пример #9
0
/* Ideas from gstjpegparse.c */
GstTagList *
gst_droidcamsrc_exif_tags_from_jpeg_data (void *data, size_t size)
{
  GstByteReader reader;
  guint16 len = 0;
  const gchar *id;
  const guint8 *exif = NULL;
  GstBuffer *buff;
  GstTagList *tags = NULL;

  void *app1 = memmem (data, size, marker, 2);
  if (!app1) {
    GST_ERROR ("No tags found");
    goto out;
  }

  size -= (app1 - data);

  gst_byte_reader_init (&reader, app1, size);

  if (!gst_byte_reader_skip (&reader, 2)) {
    GST_ERROR ("Not enough jpeg data for tags");
    goto out;
  }

  if (!gst_byte_reader_get_uint16_be (&reader, &len)) {
    GST_ERROR ("Failed to get APP1 size");
    goto out;
  }

  len -= 2;                     /* for the marker itself */

  if (!gst_byte_reader_peek_string_utf8 (&reader, &id)) {
    goto out;
  }

  if (!strncmp (id, "Exif", 4)) {
    /* id + NUL + padding */
    if (!gst_byte_reader_skip (&reader, 6)) {
      goto out;
    }

    len -= 6;

    if (!gst_byte_reader_get_data (&reader, len, &exif)) {
      goto out;
    }

    buff =
        gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, (gpointer) exif,
        len, 0, len, NULL, NULL);

    tags = gst_tag_list_from_exif_buffer_with_tiff_header (buff);
    gst_buffer_unref (buff);

    return tags;
  }

out:
  return NULL;
}
static GstFlowReturn
gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstByteReader reader;
  GstBuffer *input;
  GstMapInfo map_info;
  GstCaps *caps;
  guint available;
  GstFlowReturn res = GST_FLOW_OK;

  GstFlxDec *flxdec;
  FlxHeader *flxh;

  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
  flxdec = (GstFlxDec *) parent;
  g_return_val_if_fail (flxdec != NULL, GST_FLOW_ERROR);

  gst_adapter_push (flxdec->adapter, buf);
  available = gst_adapter_available (flxdec->adapter);
  input = gst_adapter_get_buffer (flxdec->adapter, available);
  if (!gst_buffer_map (input, &map_info, GST_MAP_READ)) {
    GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
        ("%s", "Failed to map buffer"), (NULL));
    goto error;
  }
  gst_byte_reader_init (&reader, map_info.data, map_info.size);

  if (flxdec->state == GST_FLXDEC_READ_HEADER) {
    if (available >= FlxHeaderSize) {
      GstByteReader header;
      GstCaps *templ;

      if (!gst_byte_reader_get_sub_reader (&reader, &header, FlxHeaderSize)) {
        GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
            ("%s", "Could not read header"), (NULL));
        goto unmap_input_error;
      }
      gst_adapter_flush (flxdec->adapter, FlxHeaderSize);
      available -= FlxHeaderSize;

      if (!_read_flx_header (flxdec, &header, &flxdec->hdr)) {
        GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
            ("%s", "Failed to parse header"), (NULL));
        goto unmap_input_error;
      }

      flxh = &flxdec->hdr;

      /* check header */
      if (flxh->type != FLX_MAGICHDR_FLI &&
          flxh->type != FLX_MAGICHDR_FLC && flxh->type != FLX_MAGICHDR_FLX) {
        GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL),
            ("not a flx file (type %x)", flxh->type));
        goto unmap_input_error;
      }

      GST_INFO_OBJECT (flxdec, "size      :  %d", flxh->size);
      GST_INFO_OBJECT (flxdec, "frames    :  %d", flxh->frames);
      GST_INFO_OBJECT (flxdec, "width     :  %d", flxh->width);
      GST_INFO_OBJECT (flxdec, "height    :  %d", flxh->height);
      GST_INFO_OBJECT (flxdec, "depth     :  %d", flxh->depth);
      GST_INFO_OBJECT (flxdec, "speed     :  %d", flxh->speed);

      flxdec->next_time = 0;

      if (flxh->type == FLX_MAGICHDR_FLI) {
        flxdec->frame_time = JIFFIE * flxh->speed;
      } else if (flxh->speed == 0) {
        flxdec->frame_time = GST_SECOND / 70;
      } else {
        flxdec->frame_time = flxh->speed * GST_MSECOND;
      }

      flxdec->duration = flxh->frames * flxdec->frame_time;
      GST_LOG ("duration   :  %" GST_TIME_FORMAT,
          GST_TIME_ARGS (flxdec->duration));

      templ = gst_pad_get_pad_template_caps (flxdec->srcpad);
      caps = gst_caps_copy (templ);
      gst_caps_unref (templ);
      gst_caps_set_simple (caps,
          "width", G_TYPE_INT, flxh->width,
          "height", G_TYPE_INT, flxh->height,
          "framerate", GST_TYPE_FRACTION, (gint) GST_MSECOND,
          (gint) flxdec->frame_time / 1000, NULL);

      gst_pad_set_caps (flxdec->srcpad, caps);
      gst_caps_unref (caps);

      if (flxdec->need_segment) {
        gst_pad_push_event (flxdec->srcpad,
            gst_event_new_segment (&flxdec->segment));
        flxdec->need_segment = FALSE;
      }

      /* zero means 8 */
      if (flxh->depth == 0)
        flxh->depth = 8;

      if (flxh->depth != 8) {
        GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE,
            ("%s", "Don't know how to decode non 8 bit depth streams"), (NULL));
        goto unmap_input_error;
      }

      flxdec->converter =
          flx_colorspace_converter_new (flxh->width, flxh->height);

      if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) {
        GST_INFO_OBJECT (flxdec, "(FLC) aspect_dx :  %d", flxh->aspect_dx);
        GST_INFO_OBJECT (flxdec, "(FLC) aspect_dy :  %d", flxh->aspect_dy);
        GST_INFO_OBJECT (flxdec, "(FLC) oframe1   :  0x%08x", flxh->oframe1);
        GST_INFO_OBJECT (flxdec, "(FLC) oframe2   :  0x%08x", flxh->oframe2);
      }

      flxdec->size = ((guint) flxh->width * (guint) flxh->height);
      if (flxdec->size >= G_MAXSIZE / 4) {
        GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
            ("%s", "Cannot allocate required memory"), (NULL));
        goto unmap_input_error;
      }

      /* create delta and output frame */
      flxdec->frame_data = g_malloc0 (flxdec->size);
      flxdec->delta_data = g_malloc0 (flxdec->size);

      flxdec->state = GST_FLXDEC_PLAYING;
    }
  } else if (flxdec->state == GST_FLXDEC_PLAYING) {
    GstBuffer *out;

    /* while we have enough data in the adapter */
    while (available >= FlxFrameChunkSize && res == GST_FLOW_OK) {
      guint32 size;
      guint16 type;

      if (!gst_byte_reader_get_uint32_le (&reader, &size))
        goto parse_error;
      if (available < size)
        goto need_more_data;

      available -= size;
      gst_adapter_flush (flxdec->adapter, size);

      if (!gst_byte_reader_get_uint16_le (&reader, &type))
        goto parse_error;

      switch (type) {
        case FLX_FRAME_TYPE:{
          GstByteReader chunks;
          GstByteWriter writer;
          guint16 n_chunks;
          GstMapInfo map;

          GST_LOG_OBJECT (flxdec, "Have frame type 0x%02x of size %d", type,
              size);

          if (!gst_byte_reader_get_sub_reader (&reader, &chunks,
                  size - FlxFrameChunkSize))
            goto parse_error;

          if (!gst_byte_reader_get_uint16_le (&chunks, &n_chunks))
            goto parse_error;
          GST_LOG_OBJECT (flxdec, "Have %d chunks", n_chunks);

          if (n_chunks == 0)
            break;
          if (!gst_byte_reader_skip (&chunks, 8))       /* reserved */
            goto parse_error;

          gst_byte_writer_init_with_data (&writer, flxdec->frame_data,
              flxdec->size, TRUE);

          /* decode chunks */
          if (!flx_decode_chunks (flxdec, n_chunks, &chunks, &writer)) {
            GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
                ("%s", "Could not decode chunk"), NULL);
            goto unmap_input_error;
          }
          gst_byte_writer_reset (&writer);

          /* save copy of the current frame for possible delta. */
          memcpy (flxdec->delta_data, flxdec->frame_data, flxdec->size);

          out = gst_buffer_new_and_alloc (flxdec->size * 4);
          if (!gst_buffer_map (out, &map, GST_MAP_WRITE)) {
            GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
                ("%s", "Could not map output buffer"), NULL);
            gst_buffer_unref (out);
            goto unmap_input_error;
          }

          /* convert current frame. */
          flx_colorspace_convert (flxdec->converter, flxdec->frame_data,
              map.data);
          gst_buffer_unmap (out, &map);

          GST_BUFFER_TIMESTAMP (out) = flxdec->next_time;
          flxdec->next_time += flxdec->frame_time;

          res = gst_pad_push (flxdec->srcpad, out);
          break;
        }
        default:
          GST_DEBUG_OBJECT (flxdec, "Unknown frame type 0x%02x, skipping %d",
              type, size);
          if (!gst_byte_reader_skip (&reader, size - FlxFrameChunkSize))
            goto parse_error;
          break;
      }
    }
  }

need_more_data:
  gst_buffer_unmap (input, &map_info);
  gst_buffer_unref (input);
  return res;

  /* ERRORS */
parse_error:
  GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
      ("%s", "Failed to parse stream"), (NULL));
unmap_input_error:
  gst_buffer_unmap (input, &map_info);
error:
  gst_buffer_unref (input);
  return GST_FLOW_ERROR;
}
Пример #11
0
static gboolean
gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer)
{
  GstByteReader reader;
  guint8 marker = 0;
  gboolean foundSOF = FALSE;
  guint8 *data;
  gsize size;

  data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
  gst_byte_reader_init (&reader, data, size);

  if (!gst_byte_reader_peek_uint8 (&reader, &marker))
    goto error;

  while (marker == 0xff) {
    if (!gst_byte_reader_skip (&reader, 1))
      goto error;

    if (!gst_byte_reader_get_uint8 (&reader, &marker))
      goto error;

    GST_DEBUG_OBJECT (parse, "marker = %x", marker);

    switch (marker) {
      case SOS:                /* start of scan (begins compressed data) */
        goto done;

      case SOI:
        break;

      case DRI:
        if (!gst_byte_reader_skip (&reader, 4)) /* fixed size */
          goto error;
        break;

      case COM:
        if (!gst_jpeg_parse_com (parse, &reader))
          goto error;
        break;

      case APP1:
        if (!gst_jpeg_parse_app1 (parse, &reader))
          goto error;
        break;

      case DHT:
      case DQT:
        /* Ignore these codes */
        if (!gst_jpeg_parse_skip_marker (parse, &reader, marker))
          goto error;
        break;

      case SOF2:
        parse->priv->interlaced = TRUE;
        /* fall through */
      case SOF0:
        /* parse Start Of Frame */
        if (!gst_jpeg_parse_sof (parse, &reader))
          goto error;

        foundSOF = TRUE;
        goto done;

      default:
        if (marker == JPG || (marker >= JPG0 && marker <= JPG13)) {
          /* we'd like to remove them from the buffer */
          if (!gst_jpeg_parse_remove_marker (parse, &reader, marker, buffer))
            goto error;
        } else if (marker >= APP0 && marker <= APP15) {
          if (!gst_jpeg_parse_skip_marker (parse, &reader, marker))
            goto error;
        } else
          goto unhandled;
    }

    if (!gst_byte_reader_peek_uint8 (&reader, &marker))
      goto error;
  }
done:
  gst_buffer_unmap (buffer, data, size);

  return foundSOF;

  /* ERRORS */
error:
  {
    GST_WARNING_OBJECT (parse,
        "Error parsing image header (need more than %u bytes available)",
        gst_byte_reader_get_remaining (&reader));
    gst_buffer_unmap (buffer, data, size);
    return FALSE;
  }
unhandled:
  {
    GST_WARNING_OBJECT (parse, "unhandled marker %x, leaving", marker);
    /* Not SOF or SOI.  Must not be a JPEG file (or file pointer
     * is placed wrong).  In either case, it's an error. */
    gst_buffer_unmap (buffer, data, size);
    return FALSE;
  }
}
Пример #12
0
static GstFlowReturn
gst_ac3_parse_handle_frame (GstBaseParse * parse,
    GstBaseParseFrame * frame, gint * skipsize)
{
  GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
  GstBuffer *buf = frame->buffer;
  GstByteReader reader;
  gint off;
  gboolean lost_sync, draining, eac, more = FALSE;
  guint frmsiz, blocks, sid;
  guint rate, chans;
  gboolean update_rate = FALSE;
  gint framesize = 0;
  gint have_blocks = 0;
  GstMapInfo map;
  gboolean ret = FALSE;
  GstFlowReturn res = GST_FLOW_OK;

  gst_buffer_map (buf, &map, GST_MAP_READ);

  if (G_UNLIKELY (map.size < 8)) {
    *skipsize = 1;
    goto cleanup;
  }

  gst_byte_reader_init (&reader, map.data, map.size);
  off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
      0, map.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 = map.size - 3;
    goto cleanup;
  }

  /* possible frame header, but not at offset 0? skip bytes before sync */
  if (off > 0) {
    *skipsize = off;
    goto cleanup;
  }

  /* make sure the values in the frame header look sane */
  if (!gst_ac3_parse_frame_header (ac3parse, buf, 0, &frmsiz, &rate, &chans,
          &blocks, &sid, &eac)) {
    *skipsize = off + 2;
    goto cleanup;
  }

  GST_LOG_OBJECT (parse, "size: %u, blocks: %u, rate: %u, chans: %u", frmsiz,
      blocks, rate, chans);

  framesize = frmsiz;

  if (G_UNLIKELY (g_atomic_int_get (&ac3parse->align) ==
          GST_AC3_PARSE_ALIGN_NONE))
    gst_ac3_parse_set_alignment (ac3parse, eac);

  GST_LOG_OBJECT (parse, "got frame");

  lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
  draining = GST_BASE_PARSE_DRAINING (parse);

  if (g_atomic_int_get (&ac3parse->align) == GST_AC3_PARSE_ALIGN_IEC61937) {
    /* We need 6 audio blocks from each substream, so we keep going forwards
     * till we have it */

    g_assert (blocks > 0);
    GST_LOG_OBJECT (ac3parse, "Need %d frames before pushing", 6 / blocks);

    if (sid != 0) {
      /* We need the first substream to be the one with id 0 */
      GST_LOG_OBJECT (ac3parse, "Skipping till we find sid 0");
      *skipsize = off + 2;
      goto cleanup;
    }

    framesize = 0;

    /* Loop till we have 6 blocks per substream */
    for (have_blocks = 0; !more && have_blocks < 6; have_blocks += blocks) {
      /* Loop till we get one frame from each substream */
      do {
        framesize += frmsiz;

        if (!gst_byte_reader_skip (&reader, frmsiz)
            || map.size < (framesize + 6)) {
          more = TRUE;
          break;
        }

        if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, &frmsiz,
                NULL, NULL, NULL, &sid, &eac)) {
          *skipsize = off + 2;
          goto cleanup;
        }
      } while (sid);
    }

    /* We're now at the next frame, so no need to skip if resyncing */
    frmsiz = 0;
  }

  if (lost_sync && !draining) {
    guint16 word = 0;

    GST_DEBUG_OBJECT (ac3parse, "resyncing; checking next frame syncword");

    if (more || !gst_byte_reader_skip (&reader, frmsiz) ||
        !gst_byte_reader_get_uint16_be (&reader, &word)) {
      GST_DEBUG_OBJECT (ac3parse, "... but not sufficient data");
      gst_base_parse_set_min_frame_size (parse, framesize + 8);
      *skipsize = 0;
      goto cleanup;
    } else {
      if (word != 0x0b77) {
        GST_DEBUG_OBJECT (ac3parse, "0x%x not OK", word);
        *skipsize = off + 2;
        goto cleanup;
      } else {
        /* ok, got sync now, let's assume constant frame size */
        gst_base_parse_set_min_frame_size (parse, framesize);
      }
    }
  }

  /* expect to have found a frame here */
  g_assert (framesize);
  ret = TRUE;

  /* arrange for metadata setup */
  if (G_UNLIKELY (sid)) {
    /* dependent frame, no need to (ac)count for or consider further */
    GST_LOG_OBJECT (parse, "sid: %d", sid);
    frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME;
    /* TODO maybe also mark as DELTA_UNIT,
     * if that does not surprise baseparse elsewhere */
    /* occupies same time space as previous base frame */
    if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf)))
      GST_BUFFER_TIMESTAMP (buf) -= GST_BUFFER_DURATION (buf);
    /* only shortcut if we already arranged for caps */
    if (G_LIKELY (ac3parse->sample_rate > 0))
      goto cleanup;
  }

  if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
          || ac3parse->eac != eac)) {
    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_caps_set_simple (caps, "alignment", G_TYPE_STRING,
        g_atomic_int_get (&ac3parse->align) == GST_AC3_PARSE_ALIGN_IEC61937 ?
        "iec61937" : "frame", NULL);
    gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
    gst_caps_unref (caps);

    ac3parse->sample_rate = rate;
    ac3parse->channels = chans;
    ac3parse->eac = eac;

    update_rate = TRUE;
  }

  if (G_UNLIKELY (ac3parse->blocks != blocks)) {
    ac3parse->blocks = blocks;

    update_rate = TRUE;
  }

  if (G_UNLIKELY (update_rate))
    gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2);

cleanup:
  gst_buffer_unmap (buf, &map);

  if (ret && framesize <= map.size) {
    res = gst_base_parse_finish_frame (parse, frame, framesize);
  }

  return res;
}
Пример #13
0
GstIsoffParserResult
gst_isoff_sidx_parser_add_buffer (GstSidxParser * parser, GstBuffer * buffer,
    guint * consumed)
{
  GstIsoffParserResult res = GST_ISOFF_PARSER_OK;
  GstByteReader reader;
  GstMapInfo info;
  gsize remaining;
  guint32 fourcc;

  if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
    *consumed = 0;
    return GST_ISOFF_PARSER_ERROR;
  }

  gst_byte_reader_init (&reader, info.data, info.size);

  switch (parser->status) {
    case GST_ISOFF_SIDX_PARSER_INIT:
      if (gst_byte_reader_get_remaining (&reader) < GST_ISOFF_FULL_BOX_SIZE) {
        break;
      }

      parser->size = gst_byte_reader_get_uint32_be_unchecked (&reader);
      fourcc = gst_byte_reader_get_uint32_le_unchecked (&reader);
      if (fourcc != GST_ISOFF_FOURCC_SIDX) {
        res = GST_ISOFF_PARSER_UNEXPECTED;
        gst_byte_reader_set_pos (&reader, 0);
        break;
      }
      if (parser->size == 1) {
        if (gst_byte_reader_get_remaining (&reader) < 12) {
          gst_byte_reader_set_pos (&reader, 0);
          break;
        }

        parser->size = gst_byte_reader_get_uint64_be_unchecked (&reader);
      }
      if (parser->size == 0) {
        res = GST_ISOFF_PARSER_ERROR;
        gst_byte_reader_set_pos (&reader, 0);
        break;
      }
      parser->sidx.version = gst_byte_reader_get_uint8_unchecked (&reader);
      parser->sidx.flags = gst_byte_reader_get_uint24_le_unchecked (&reader);

      parser->status = GST_ISOFF_SIDX_PARSER_HEADER;

    case GST_ISOFF_SIDX_PARSER_HEADER:
      remaining = gst_byte_reader_get_remaining (&reader);
      if (remaining < 12 + (parser->sidx.version == 0 ? 8 : 16)) {
        break;
      }

      parser->sidx.ref_id = gst_byte_reader_get_uint32_be_unchecked (&reader);
      parser->sidx.timescale =
          gst_byte_reader_get_uint32_be_unchecked (&reader);
      if (parser->sidx.version == 0) {
        parser->sidx.earliest_pts =
            gst_byte_reader_get_uint32_be_unchecked (&reader);
        parser->sidx.first_offset = parser->sidx.earliest_pts =
            gst_byte_reader_get_uint32_be_unchecked (&reader);
      } else {
        parser->sidx.earliest_pts =
            gst_byte_reader_get_uint64_be_unchecked (&reader);
        parser->sidx.first_offset =
            gst_byte_reader_get_uint64_be_unchecked (&reader);
      }
      /* skip 2 reserved bytes */
      gst_byte_reader_skip_unchecked (&reader, 2);
      parser->sidx.entries_count =
          gst_byte_reader_get_uint16_be_unchecked (&reader);

      GST_LOG ("Timescale: %" G_GUINT32_FORMAT, parser->sidx.timescale);
      GST_LOG ("Earliest pts: %" G_GUINT64_FORMAT, parser->sidx.earliest_pts);
      GST_LOG ("First offset: %" G_GUINT64_FORMAT, parser->sidx.first_offset);

      parser->cumulative_pts =
          gst_util_uint64_scale_int_round (parser->sidx.earliest_pts,
          GST_SECOND, parser->sidx.timescale);

      if (parser->sidx.entries_count) {
        parser->sidx.entries =
            g_malloc (sizeof (GstSidxBoxEntry) * parser->sidx.entries_count);
      }
      parser->sidx.entry_index = 0;

      parser->status = GST_ISOFF_SIDX_PARSER_DATA;

    case GST_ISOFF_SIDX_PARSER_DATA:
      while (parser->sidx.entry_index < parser->sidx.entries_count) {
        GstSidxBoxEntry *entry =
            &parser->sidx.entries[parser->sidx.entry_index];

        remaining = gst_byte_reader_get_remaining (&reader);;
        if (remaining < 12)
          break;

        entry->offset = parser->cumulative_entry_size;
        entry->pts = parser->cumulative_pts;
        gst_isoff_parse_sidx_entry (entry, &reader);
        entry->duration = gst_util_uint64_scale_int_round (entry->duration,
            GST_SECOND, parser->sidx.timescale);
        parser->cumulative_entry_size += entry->size;
        parser->cumulative_pts += entry->duration;

        GST_LOG ("Sidx entry %d) offset: %" G_GUINT64_FORMAT ", pts: %"
            GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT " - size %"
            G_GUINT32_FORMAT, parser->sidx.entry_index, entry->offset,
            GST_TIME_ARGS (entry->pts), GST_TIME_ARGS (entry->duration),
            entry->size);

        parser->sidx.entry_index++;
      }

      if (parser->sidx.entry_index == parser->sidx.entries_count)
        parser->status = GST_ISOFF_SIDX_PARSER_FINISHED;
      else
        break;
    case GST_ISOFF_SIDX_PARSER_FINISHED:
      parser->sidx.entry_index = 0;
      res = GST_ISOFF_PARSER_DONE;
      break;
  }

  *consumed = gst_byte_reader_get_pos (&reader);
  gst_buffer_unmap (buffer, &info);
  return res;
}
Пример #14
0
static GstFlowReturn
gst_irtsp_parse_handle_frame (GstBaseParse * parse,
    GstBaseParseFrame * frame, gint * skipsize)
{
  GstIRTSPParse *IRTSPParse = GST_IRTSP_PARSE (parse);
  GstBuffer *buf = frame->buffer;
  GstByteReader reader;
  gint off;
  GstMapInfo map;
  gboolean ret = FALSE;
  guint framesize;

  gst_buffer_map (buf, &map, GST_MAP_READ);
  if (G_UNLIKELY (map.size < 4))
    goto exit;

  gst_byte_reader_init (&reader, map.data, map.size);

  off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000,
      0x24000000 + (IRTSPParse->channel_id << 16), 0, map.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 = map.size - 3;
    goto exit;
  }

  /* possible frame header, but not at offset 0? skip bytes before sync */
  if (off > 0) {
    *skipsize = off;
    goto exit;
  }

  framesize = GST_READ_UINT16_BE (map.data + 2) + 4;
  GST_LOG_OBJECT (parse, "got frame size %d", framesize);
  ret = TRUE;

  if (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (parse))) {
    GstCaps *caps;

    caps = gst_caps_new_empty_simple ("application/x-rtp");
    gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
    gst_caps_unref (caps);
  }

exit:
  gst_buffer_unmap (buf, &map);

  if (ret && framesize <= map.size) {
    /* HACK HACK skip header.
     * could also ask baseparse to skip this,
     * but that would give us a discontinuity for free
     * which is a bit too much to have on all our packets */
    frame->out_buffer = gst_buffer_copy (frame->buffer);
    gst_buffer_resize (frame->out_buffer, 4, -1);
    GST_BUFFER_FLAG_UNSET (frame->out_buffer, GST_BUFFER_FLAG_DISCONT);
    return gst_base_parse_finish_frame (parse, frame, framesize);
  }

  return GST_FLOW_OK;
}
Пример #15
0
static GstFlowReturn
gst_png_parse_handle_frame (GstBaseParse * parse,
    GstBaseParseFrame * frame, gint * skipsize)
{
  GstPngParse *pngparse = GST_PNG_PARSE (parse);
  GstMapInfo map;
  GstByteReader reader;
  GstFlowReturn ret = GST_FLOW_OK;
  guint64 signature;
  guint width = 0, height = 0;

  gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
  gst_byte_reader_init (&reader, map.data, map.size);

  if (!gst_byte_reader_peek_uint64_be (&reader, &signature))
    goto beach;

  if (signature != PNG_SIGNATURE) {
    for (;;) {
      guint offset;

      offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
          0x89504E47, 0, gst_byte_reader_get_remaining (&reader));

      if (offset == -1) {
        *skipsize = gst_byte_reader_get_remaining (&reader) - 4;
        goto beach;
      }

      gst_byte_reader_skip (&reader, offset);

      if (!gst_byte_reader_peek_uint64_be (&reader, &signature))
        goto beach;

      if (signature == PNG_SIGNATURE) {
        /* We're skipping, go out, we'll be back */
        *skipsize = gst_byte_reader_get_pos (&reader);
        goto beach;
      }
      gst_byte_reader_skip (&reader, 4);
    }
  }

  gst_byte_reader_skip (&reader, 8);

  for (;;) {
    guint32 length;
    guint32 code;

    if (!gst_byte_reader_get_uint32_be (&reader, &length))
      goto beach;
    if (!gst_byte_reader_get_uint32_le (&reader, &code))
      goto beach;

    if (code == GST_MAKE_FOURCC ('I', 'H', 'D', 'R')) {
      if (!gst_byte_reader_get_uint32_be (&reader, &width))
        goto beach;
      if (!gst_byte_reader_get_uint32_be (&reader, &height))
        goto beach;
      length -= 8;
    }

    if (!gst_byte_reader_skip (&reader, length + 4))
      goto beach;

    if (code == GST_MAKE_FOURCC ('I', 'E', 'N', 'D')) {
      if (pngparse->width != width || pngparse->height != height) {
        GstStructure *st = NULL;
        GstCaps *caps, *sink_caps;
        gint fr_num, fr_denom;

        pngparse->height = height;
        pngparse->width = width;

        sink_caps =
            gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (pngparse));
        if (sink_caps && (st = gst_caps_get_structure (sink_caps, 0))
            && gst_structure_get_fraction (st, "framerate", &fr_num, &fr_denom)) {
          /* Got it in caps - nothing more to do */
          GST_DEBUG_OBJECT (pngparse,
              "sink caps override framerate from headers");
        } else {
          GST_INFO_OBJECT (pngparse, "No framerate set");
        }

        caps = gst_caps_new_simple ("image/png",
            "width", G_TYPE_INT, width, "height", G_TYPE_INT, height,
            "framerate", GST_TYPE_FRACTION, fr_num, fr_denom, NULL);

        if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps)) {
          ret = GST_FLOW_NOT_NEGOTIATED;
        }
        gst_caps_unref (caps);

        if (ret != GST_FLOW_OK)
          goto beach;
      }


      gst_buffer_unmap (frame->buffer, &map);
      return gst_base_parse_finish_frame (parse, frame,
          gst_byte_reader_get_pos (&reader));
    }
  }

beach:

  gst_buffer_unmap (frame->buffer, &map);

  return ret;
}
Пример #16
0
static GstFlowReturn
gst_pngdec_parse (GstVideoDecoder * decoder, GstVideoCodecFrame * frame,
    GstAdapter * adapter, gboolean at_eos)
{
  gsize toadd = 0;
  GstByteReader reader;
  gconstpointer data;
  guint64 signature;
  gsize size;
  GstPngDec *pngdec = (GstPngDec *) decoder;

  GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);

  /* FIXME : The overhead of using scan_uint32 is massive */

  size = gst_adapter_available (adapter);
  GST_DEBUG ("Parsing PNG image data (%" G_GSIZE_FORMAT " bytes)", size);

  if (size < 8)
    goto need_more_data;

  data = gst_adapter_map (adapter, size);
  gst_byte_reader_init (&reader, data, size);

  if (pngdec->read_data == 0) {
    if (!gst_byte_reader_peek_uint64_be (&reader, &signature))
      goto need_more_data;

    if (signature != PNG_SIGNATURE) {
      for (;;) {
        guint offset;

        offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
            0x89504E47, 0, gst_byte_reader_get_remaining (&reader));

        if (offset == -1) {
          gst_adapter_flush (adapter,
              gst_byte_reader_get_remaining (&reader) - 4);
          goto need_more_data;
        }

        if (!gst_byte_reader_skip (&reader, offset))
          goto need_more_data;

        if (!gst_byte_reader_peek_uint64_be (&reader, &signature))
          goto need_more_data;

        if (signature == PNG_SIGNATURE) {
          /* We're skipping, go out, we'll be back */
          gst_adapter_flush (adapter, gst_byte_reader_get_pos (&reader));
          goto need_more_data;
        }
        if (!gst_byte_reader_skip (&reader, 4))
          goto need_more_data;
      }
    }
    pngdec->read_data = 8;
  }

  if (!gst_byte_reader_skip (&reader, pngdec->read_data))
    goto need_more_data;

  for (;;) {
    guint32 length;
    guint32 code;

    if (!gst_byte_reader_get_uint32_be (&reader, &length))
      goto need_more_data;
    if (!gst_byte_reader_get_uint32_le (&reader, &code))
      goto need_more_data;

    if (!gst_byte_reader_skip (&reader, length + 4))
      goto need_more_data;

    if (code == GST_MAKE_FOURCC ('I', 'E', 'N', 'D')) {
      /* Have complete frame */
      toadd = gst_byte_reader_get_pos (&reader);
      GST_DEBUG_OBJECT (decoder, "Have complete frame of size %" G_GSIZE_FORMAT,
          toadd);
      pngdec->read_data = 0;
      goto have_full_frame;
    } else
      pngdec->read_data += length + 12;
  }

  g_assert_not_reached ();
  return GST_FLOW_ERROR;

need_more_data:
  return GST_VIDEO_DECODER_FLOW_NEED_DATA;

have_full_frame:
  if (toadd)
    gst_video_decoder_add_to_frame (decoder, toadd);
  return gst_video_decoder_have_frame (decoder);
}
/**
 * gst_mpeg4_parse:
 * @packet: The #GstMpeg4Packet to fill
 * @skip_user_data: %TRUE to skip user data packet %FALSE otherwise
 * @vop: The last parsed #GstMpeg4VideoObjectPlane or %NULL if you do
 * not need to detect the resync codes.
 * @offset: offset from which to start the parsing
 * @data: The data to parse
 * @size: The size of the @data to parse
 *
 * Parses @data and fills @packet with the information of the next packet
 * found.
 *
 * Returns: a #GstMpeg4ParseResult
 */
GstMpeg4ParseResult
gst_mpeg4_parse (GstMpeg4Packet * packet, gboolean skip_user_data,
    GstMpeg4VideoObjectPlane * vop, const guint8 * data, guint offset,
    gsize size)
{
  gint off1, off2;
  GstByteReader br;
  GstMpeg4ParseResult resync_res;
  static guint first_resync_marker = TRUE;

  gst_byte_reader_init (&br, data, size);

  g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR);

  if (size - offset <= 4) {
    GST_DEBUG ("Can't parse, buffer is to small size %" G_GSIZE_FORMAT
        " at offset %d", size, offset);
    return GST_MPEG4_PARSER_ERROR;
  }

  if (vop) {
    resync_res =
        gst_mpeg4_next_resync (packet, vop, data + offset, size - offset,
        first_resync_marker);
    first_resync_marker = FALSE;

    /*  We found a complet slice */
    if (resync_res == GST_MPEG4_PARSER_OK)
      return resync_res;
    else if (resync_res == GST_MPEG4_PARSER_NO_PACKET_END) {
      /* It doesn't mean there is no standard packet end, look for it */
      off1 = packet->offset;
      goto find_end;
    } else if (resync_res == GST_MPEG4_PARSER_NO_PACKET)
      return resync_res;
  } else {
    first_resync_marker = TRUE;
  }

  off1 = gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100,
      offset, size - offset);

  if (off1 == -1) {
    GST_DEBUG ("No start code prefix in this buffer");
    return GST_MPEG4_PARSER_NO_PACKET;
  }

  /* Recursively skip user data if needed */
  if (skip_user_data && data[off1 + 3] == GST_MPEG4_USER_DATA)
    /* If we are here, we know no resync code has been found the first time, so we
     * don't look for it this time */
    return gst_mpeg4_parse (packet, skip_user_data, NULL, data, off1 + 3, size);

  packet->offset = off1 + 3;
  packet->data = data;
  packet->type = (GstMpeg4StartCode) (data[off1 + 3]);

find_end:
  if (off1 < size - 4)
    off2 = gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100,
        off1 + 4, size - off1 - 4);
  else
    off2 = -1;

  if (off2 == -1) {
    GST_DEBUG ("Packet start %d, No end found", off1 + 4);

    packet->size = G_MAXUINT;
    return GST_MPEG4_PARSER_NO_PACKET_END;
  }

  if (packet->type == GST_MPEG4_RESYNC) {
    packet->size = (gsize) off2 - off1;
  } else {
    packet->size = (gsize) off2 - off1 - 3;
  }

  GST_DEBUG ("Complete packet of type %x found at: %d, Size: %" G_GSIZE_FORMAT,
      packet->type, packet->offset, packet->size);
  return GST_MPEG4_PARSER_OK;

}
Пример #18
0
static GstFlowReturn
gst_dirac_parse_handle_frame (GstBaseParse * parse,
                              GstBaseParseFrame * frame, gint * skipsize)
{
    int off;
    guint32 next_header;
    GstMapInfo map;
    guint8 *data;
    gsize size;
    gboolean have_picture = FALSE;
    int offset;
    guint framesize = 0;

    gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
    data = map.data;
    size = map.size;

    if (G_UNLIKELY (size < 13)) {
        *skipsize = 1;
        goto out;
    }

    GST_DEBUG ("%" G_GSIZE_FORMAT ": %02x %02x %02x %02x", size, data[0], data[1],
               data[2], data[3]);

    if (GST_READ_UINT32_BE (data) != 0x42424344) {
        GstByteReader reader;

        gst_byte_reader_init (&reader, data, size);
        off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
                0x42424344, 0, size);

        if (off < 0) {
            *skipsize = size - 3;
            goto out;
        }

        GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);

        GST_DEBUG ("skipping %d", off);
        *skipsize = off;
        goto out;
    }

    /* have sync, parse chunks */

    offset = 0;
    while (!have_picture) {
        GST_DEBUG ("offset %d:", offset);

        if (offset + 13 >= size) {
            framesize = offset + 13;
            goto out;
        }

        GST_DEBUG ("chunk type %02x", data[offset + 4]);

        if (GST_READ_UINT32_BE (data + offset) != 0x42424344) {
            GST_DEBUG ("bad header");
            *skipsize = 3;
            goto out;
        }

        next_header = GST_READ_UINT32_BE (data + offset + 5);
        GST_DEBUG ("next_header %d", next_header);
        if (next_header == 0)
            next_header = 13;

        if (SCHRO_PARSE_CODE_IS_PICTURE (data[offset + 4])) {
            have_picture = TRUE;
        }

        offset += next_header;
        if (offset >= size) {
            framesize = offset;
            goto out;
        }
    }

    gst_buffer_unmap (frame->buffer, &map);

    framesize = offset;
    GST_DEBUG ("framesize %d", framesize);

    g_assert (framesize <= size);

    if (data[4] == SCHRO_PARSE_CODE_SEQUENCE_HEADER) {
        GstCaps *caps;
        GstDiracParse *diracparse = GST_DIRAC_PARSE (parse);
        DiracSequenceHeader sequence_header;
        int ret;

        ret = dirac_sequence_header_parse (&sequence_header, data + 13, size - 13);
        if (ret) {
            memcpy (&diracparse->sequence_header, &sequence_header,
                    sizeof (sequence_header));
            caps = gst_caps_new_simple ("video/x-dirac",
                                        "width", G_TYPE_INT, sequence_header.width,
                                        "height", G_TYPE_INT, sequence_header.height,
                                        "framerate", GST_TYPE_FRACTION,
                                        sequence_header.frame_rate_numerator,
                                        sequence_header.frame_rate_denominator,
                                        "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                        sequence_header.aspect_ratio_numerator,
                                        sequence_header.aspect_ratio_denominator,
                                        "interlace-mode", G_TYPE_STRING,
                                        sequence_header.interlaced ? "interleaved" : "progressive",
                                        "profile", G_TYPE_STRING, get_profile_name (sequence_header.profile),
                                        "level", G_TYPE_STRING, get_level_name (sequence_header.level), NULL);
            gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
            gst_caps_unref (caps);

            gst_base_parse_set_frame_rate (parse,
                                           sequence_header.frame_rate_numerator,
                                           sequence_header.frame_rate_denominator, 0, 0);
        }
    }

    gst_base_parse_set_min_frame_size (parse, 13);

    return gst_base_parse_finish_frame (parse, frame, framesize);

out:
    gst_buffer_unmap (frame->buffer, &map);
    if (framesize)
        gst_base_parse_set_min_frame_size (parse, framesize);
    return GST_FLOW_OK;
}
Пример #19
0
static GstFlowReturn
gst_png_parse_handle_frame (GstBaseParse * parse,
    GstBaseParseFrame * frame, gint * skipsize)
{
  GstPngParse *pngparse = GST_PNG_PARSE (parse);
  GstMapInfo map;
  GstByteReader reader;
  GstFlowReturn ret = GST_FLOW_OK;
  guint64 signature;
  guint width = 0, height = 0;

  gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
  gst_byte_reader_init (&reader, map.data, map.size);

  if (!gst_byte_reader_peek_uint64_be (&reader, &signature))
    goto beach;

  if (signature != PNG_SIGNATURE) {
    for (;;) {
      guint offset;

      offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
          0x89504E47, 0, gst_byte_reader_get_remaining (&reader));

      if (offset == -1) {
        *skipsize = gst_byte_reader_get_remaining (&reader) - 4;
        goto beach;
      }

      gst_byte_reader_skip (&reader, offset);

      if (!gst_byte_reader_peek_uint64_be (&reader, &signature))
        goto beach;

      if (signature == PNG_SIGNATURE) {
        /* We're skipping, go out, we'll be back */
        *skipsize = gst_byte_reader_get_pos (&reader);
        goto beach;
      }
      gst_byte_reader_skip (&reader, 4);
    }
  }

  gst_byte_reader_skip (&reader, 8);

  for (;;) {
    guint32 length;
    guint32 code;

    if (!gst_byte_reader_get_uint32_be (&reader, &length))
      goto beach;
    if (!gst_byte_reader_get_uint32_le (&reader, &code))
      goto beach;

    GST_TRACE_OBJECT (parse, "%" GST_FOURCC_FORMAT " chunk, %u bytes",
        GST_FOURCC_ARGS (code), length);

    if (code == GST_MAKE_FOURCC ('I', 'H', 'D', 'R')) {
      if (!gst_byte_reader_get_uint32_be (&reader, &width))
        goto beach;
      if (!gst_byte_reader_get_uint32_be (&reader, &height))
        goto beach;
      length -= 8;
    } else if (code == GST_MAKE_FOURCC ('I', 'D', 'A', 'T')) {
      gst_base_parse_set_min_frame_size (parse,
          gst_byte_reader_get_pos (&reader) + 4 + length + 12);
    }

    if (!gst_byte_reader_skip (&reader, length + 4))
      goto beach;

    if (code == GST_MAKE_FOURCC ('I', 'E', 'N', 'D')) {
      /* the start code and at least 2 empty frames (IHDR and IEND) */
      gst_base_parse_set_min_frame_size (parse, 8 + 12 + 12);

      if (pngparse->width != width || pngparse->height != height) {
        GstCaps *caps, *sink_caps;

        pngparse->height = height;
        pngparse->width = width;

        caps = gst_caps_new_simple ("image/png",
            "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);

        sink_caps =
            gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (pngparse));

        if (sink_caps) {
          GstStructure *st;
          gint fr_num, fr_denom;

          st = gst_caps_get_structure (sink_caps, 0);
          if (st
              && gst_structure_get_fraction (st, "framerate", &fr_num,
                  &fr_denom)) {
            gst_caps_set_simple (caps,
                "framerate", GST_TYPE_FRACTION, fr_num, fr_denom, NULL);
          } else {
            GST_WARNING_OBJECT (pngparse, "No framerate set");
          }

          gst_caps_unref (sink_caps);
        }

        if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps))
          ret = GST_FLOW_NOT_NEGOTIATED;

        gst_caps_unref (caps);

        if (ret != GST_FLOW_OK)
          goto beach;
      }


      gst_buffer_unmap (frame->buffer, &map);
      return gst_base_parse_finish_frame (parse, frame,
          gst_byte_reader_get_pos (&reader));
    }
  }

beach:

  gst_buffer_unmap (frame->buffer, &map);

  return ret;
}
Пример #20
0
gboolean
gst_mss_fragment_parser_add_buffer (GstMssFragmentParser * parser,
    GstBuffer * buffer)
{
  GstByteReader reader;
  GstMapInfo info;
  guint64 size;
  guint32 fourcc;
  guint header_size;
  gboolean error = FALSE;

  if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
    return FALSE;
  }

  gst_byte_reader_init (&reader, info.data, info.size);
  GST_TRACE ("Total buffer size: %u", gst_byte_reader_get_size (&reader));

  do {
    parser->current_fourcc = 0;

    if (!gst_isoff_parse_box_header (&reader, &fourcc, NULL, &header_size,
            &size)) {
      break;
    }

    parser->current_fourcc = fourcc;

    GST_LOG ("box %" GST_FOURCC_FORMAT " size %" G_GUINT64_FORMAT,
        GST_FOURCC_ARGS (fourcc), size);

    parser->current_fourcc = fourcc;

    if (parser->current_fourcc == GST_ISOFF_FOURCC_MOOF) {
      GstByteReader sub_reader;

      g_assert (parser->moof == NULL);
      gst_byte_reader_get_sub_reader (&reader, &sub_reader, size - header_size);
      parser->moof = gst_isoff_moof_box_parse (&sub_reader);
      if (parser->moof == NULL) {
        GST_ERROR ("Failed to parse moof");
        error = TRUE;
      }
    } else if (parser->current_fourcc == GST_ISOFF_FOURCC_MDAT) {
      goto beach;
    } else {
      gst_byte_reader_skip (&reader, size - header_size);
    }
  } while (gst_byte_reader_get_remaining (&reader) > 0);

beach:

  /* Do sanity check */
  if (parser->current_fourcc != GST_ISOFF_FOURCC_MDAT || !parser->moof ||
      parser->moof->traf->len == 0)
    error = TRUE;

  if (!error) {
    GstTrafBox *traf = &g_array_index (parser->moof->traf, GstTrafBox, 0);
    if (!traf->tfxd) {
      GST_ERROR ("no tfxd box");
      error = TRUE;
    } else if (!traf->tfrf) {
      GST_ERROR ("no tfrf box");
      error = TRUE;
    }
  }

  if (!error)
    parser->status = GST_MSS_FRAGMENT_HEADER_PARSER_FINISHED;

  GST_LOG ("Fragment parsing successful: %s", error ? "no" : "yes");
  gst_buffer_unmap (buffer, &info);
  return !error;
}