Example #1
0
/**
 * gst_amrparse_sink_setcaps:
 * @sinkpad: GstPad
 * @caps: GstCaps
 *
 * Returns: TRUE on success.
 */
static gboolean
gst_amrparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
{
  GstAmrParse *amrparse;
  GstStructure *structure;
  const gchar *name;

  amrparse = GST_AMRPARSE (parse);
  structure = gst_caps_get_structure (caps, 0);
  name = gst_structure_get_name (structure);

  GST_DEBUG_OBJECT (amrparse, "setcaps: %s", name);

  if (!strncmp (name, "audio/x-amr-wb-sh", 17)) {
    amrparse->block_size = block_size_wb;
    amrparse->wide = 1;
  } else if (!strncmp (name, "audio/x-amr-nb-sh", 17)) {
    amrparse->block_size = block_size_nb;
    amrparse->wide = 0;
  } else {
    GST_WARNING ("Unknown caps");
    return FALSE;
  }

  amrparse->need_header = FALSE;
  gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
  gst_amrparse_set_src_caps (amrparse);
  return TRUE;
}
Example #2
0
/**
 * gst_amrparse_check_valid_frame:
 * @parse: #GstBaseParse.
 * @buffer: #GstBuffer.
 * @framesize: Output variable where the found frame size is put.
 * @skipsize: Output variable which tells how much data needs to be skipped
 *            until a frame header is found.
 *
 * Implementation of "check_valid_frame" vmethod in #GstBaseParse class.
 *
 * Returns: TRUE if the given data contains valid frame.
 */
gboolean
gst_amrparse_check_valid_frame (GstBaseParse * parse,
    GstBuffer * buffer, guint * framesize, gint * skipsize)
{
  const guint8 *data;
  gint fsize, mode, dsize;
  GstAmrParse *amrparse;

  amrparse = GST_AMRPARSE (parse);
  data = GST_BUFFER_DATA (buffer);
  dsize = GST_BUFFER_SIZE (buffer);

  GST_LOG ("buffer: %d bytes", dsize);

  if (amrparse->need_header) {
    if (dsize >= AMR_MIME_HEADER_SIZE &&
        gst_amrparse_parse_header (amrparse, data, skipsize)) {
      amrparse->need_header = FALSE;
      gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2);
    } else {
      GST_WARNING ("media doesn't look like a AMR format");
    }
    /* We return FALSE, so this frame won't get pushed forward. Instead,
       the "skip" value is set, so next time we will receive a valid frame. */
    return FALSE;
  }

  /* Does this look like a possible frame header candidate? */
  if ((data[0] & 0x83) == 0) {
    /* Yep. Retrieve the frame size */
    mode = (data[0] >> 3) & 0x0F;
    fsize = amrparse->block_size[mode] + 1;     /* +1 for the header byte */

    /* We recognize this data as a valid frame when:
     *     - We are in sync. There is no need for extra checks then
     *     - We are in EOS. There might not be enough data to check next frame
     *     - Sync is lost, but the following data after this frame seem
     *       to contain a valid header as well (and there is enough data to
     *       perform this check)
     */
    if (gst_base_parse_get_sync (parse) || gst_base_parse_get_drain (parse) ||
        (dsize >= fsize && (data[fsize] & 0x83) == 0)) {
      *framesize = fsize;
      return TRUE;
    }
  }
Example #3
0
static void
gst_h264_parse_update_src_caps (GstH264Parse * h264parse)
{
  GstH264ParamsSPS *sps;
  GstCaps *caps = NULL, *sink_caps;
  gboolean modified = FALSE;
  GstBuffer *buf = NULL;

  if (G_UNLIKELY (!GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (h264parse))))
    modified = TRUE;
  else if (G_UNLIKELY (!h264parse->update_caps))
    return;

  /* carry over input caps as much as possible; override with our own stuff */
  sink_caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h264parse));
  if (sink_caps)
    gst_caps_ref (sink_caps);
  else
    sink_caps = gst_caps_new_simple ("video/x-h264", NULL);

  sps = h264parse->params->sps;
  GST_DEBUG_OBJECT (h264parse, "sps: %p", sps);

  /* only codec-data for nice-and-clean au aligned packetized avc format */
  if (h264parse->format == GST_H264_PARSE_FORMAT_AVC &&
      h264parse->align == GST_H264_PARSE_ALIGN_AU) {
    buf = gst_h264_parse_make_codec_data (h264parse);
    if (buf && h264parse->codec_data) {
      if (GST_BUFFER_SIZE (buf) != GST_BUFFER_SIZE (h264parse->codec_data) ||
          memcmp (GST_BUFFER_DATA (buf),
              GST_BUFFER_DATA (h264parse->codec_data), GST_BUFFER_SIZE (buf)))
        modified = TRUE;
    } else {
      if (h264parse->codec_data)
        buf = gst_buffer_ref (h264parse->codec_data);
      modified = TRUE;
    }
  }

  if (G_UNLIKELY (!sps)) {
    caps = gst_caps_copy (sink_caps);
  } else if (G_UNLIKELY (h264parse->width != sps->width ||
          h264parse->height != sps->height || h264parse->fps_num != sps->fps_num
          || h264parse->fps_den != sps->fps_den || modified)) {
    caps = gst_caps_copy (sink_caps);
    /* sps should give this */
    gst_caps_set_simple (caps, "width", G_TYPE_INT, sps->width,
        "height", G_TYPE_INT, sps->height, NULL);
    h264parse->height = sps->height;
    h264parse->width = sps->width;
    /* but not necessarily or reliably this */
    if ((!h264parse->fps_num || !h264parse->fps_den) &&
        sps->fps_num > 0 && sps->fps_den > 0) {
      gst_caps_set_simple (caps, "framerate",
          GST_TYPE_FRACTION, sps->fps_num, sps->fps_den, NULL);
      h264parse->fps_num = sps->fps_num;
      h264parse->fps_den = sps->fps_den;
      gst_base_parse_set_frame_props (GST_BASE_PARSE (h264parse),
          h264parse->fps_num, h264parse->fps_den, 0, 0);
    }
  }

  if (caps) {
    gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
        "stream-format", G_TYPE_STRING,
        gst_h264_parse_get_string (h264parse, TRUE, h264parse->format),
        "alignment", G_TYPE_STRING,
        gst_h264_parse_get_string (h264parse, FALSE, h264parse->align), NULL);
    if (buf) {
      gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
      gst_buffer_replace (&h264parse->codec_data, buf);
      gst_buffer_unref (buf);
      buf = NULL;
    } else {
      GstStructure *s;
      /* remove any left-over codec-data hanging around */
      s = gst_caps_get_structure (caps, 0);
      gst_structure_remove_field (s, "codec_data");
    }
    gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h264parse), caps);
    gst_caps_unref (caps);
  }

  gst_caps_unref (sink_caps);
  if (buf)
    gst_buffer_unref (buf);
}