Ejemplo n.º 1
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;
  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);

  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);
  }

  if (framesize <= map.size) {
    gst_buffer_unmap (buf, &map);
    /* 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);
  }

exit:
  gst_buffer_unmap (buf, &map);
  return GST_FLOW_OK;
}
Ejemplo n.º 2
0
static GstFlowReturn
gst_mpegv_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
{
  GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
  GstTagList *taglist;
  GstMpegVideoMeta *meta;
  GstMpegVideoSequenceHdr *seq_hdr = NULL;
  GstMpegVideoSequenceExt *seq_ext = NULL;
  GstMpegVideoSequenceDisplayExt *disp_ext = NULL;
  GstMpegVideoPictureHdr *pic_hdr = NULL;
  GstMpegVideoPictureExt *pic_ext = NULL;
  GstMpegVideoQuantMatrixExt *quant_ext = NULL;

  /* tag sending done late enough in hook to ensure pending events
   * have already been sent */

  if (G_UNLIKELY (mpvparse->send_codec_tag)) {
    gchar *codec;

    /* codec tag */
    codec =
        g_strdup_printf ("MPEG %d Video",
        (mpvparse->config_flags & FLAG_MPEG2) ? 2 : 1);
    taglist = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec, NULL);
    g_free (codec);

    gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (mpvparse),
        gst_event_new_tag (taglist));

    mpvparse->send_codec_tag = FALSE;
  }

  /* usual clipping applies */
  frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;

  if (mpvparse->send_mpeg_meta) {
    GstBuffer *buf;

    if (mpvparse->seqhdr_updated)
      seq_hdr = &mpvparse->sequencehdr;
    if (mpvparse->seqext_updated)
      seq_ext = &mpvparse->sequenceext;
    if (mpvparse->seqdispext_updated)
      disp_ext = &mpvparse->sequencedispext;
    if (mpvparse->picext_updated)
      pic_ext = &mpvparse->picext;
    if (mpvparse->quantmatrext_updated)
      quant_ext = &mpvparse->quantmatrext;
    pic_hdr = &mpvparse->pichdr;

    GST_DEBUG_OBJECT (mpvparse,
        "Adding GstMpegVideoMeta (slice_count:%d, slice_offset:%d)",
        mpvparse->slice_count, mpvparse->slice_offset);

    if (frame->out_buffer) {
      buf = frame->out_buffer = gst_buffer_make_writable (frame->out_buffer);
    } else {
      buf = frame->buffer = gst_buffer_make_writable (frame->buffer);
    }

    meta =
        gst_buffer_add_mpeg_video_meta (buf, seq_hdr, seq_ext, disp_ext,
        pic_hdr, pic_ext, quant_ext);
    meta->num_slices = mpvparse->slice_count;
    meta->slice_offset = mpvparse->slice_offset;
  }
  return GST_FLOW_OK;
}
Ejemplo n.º 3
0
static void
gst_h263_parse_set_src_caps (GstH263Parse * h263parse,
    const H263Params * params)
{
  GstStructure *st = NULL;
  GstCaps *caps, *sink_caps;
  gint fr_num, fr_denom, par_num, par_denom;

  g_assert (h263parse->state == PASSTHROUGH || h263parse->state == GOT_HEADER);

  caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h263parse));
  if (caps) {
    caps = gst_caps_make_writable (caps);
  } else {
    caps = gst_caps_new_simple ("video/x-h263",
        "variant", G_TYPE_STRING, "itu", NULL);
  }
  gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);

  sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (h263parse));
  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 (h263parse, "sink caps override framerate from headers");
  } else {
    /* Caps didn't have the framerate - get it from params */
    gst_h263_parse_get_framerate (params, &fr_num, &fr_denom);
  }
  gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, fr_num, fr_denom,
      NULL);

  if (params->width && params->height)
    gst_caps_set_simple (caps, "width", G_TYPE_INT, params->width,
        "height", G_TYPE_INT, params->height, NULL);

  if (st != NULL
      && gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_num,
          &par_denom)) {
    /* Got it in caps - nothing more to do */
    GST_DEBUG_OBJECT (h263parse, "sink caps override PAR");
  } else {
    /* Caps didn't have the framerate - get it from params */
    gst_h263_parse_get_par (params, &par_num, &par_denom);
  }
  gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
      par_num, par_denom, NULL);

  if (h263parse->state == GOT_HEADER) {
    gst_caps_set_simple (caps,
        "annex-d", G_TYPE_BOOLEAN, (params->features & H263_OPTION_UMV_MODE),
        "annex-e", G_TYPE_BOOLEAN, (params->features & H263_OPTION_SAC_MODE),
        "annex-f", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AP_MODE),
        "annex-g", G_TYPE_BOOLEAN, (params->features & H263_OPTION_PB_MODE),
        "annex-i", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AIC_MODE),
        "annex-j", G_TYPE_BOOLEAN, (params->features & H263_OPTION_DF_MODE),
        "annex-k", G_TYPE_BOOLEAN, (params->features & H263_OPTION_SS_MODE),
        "annex-m", G_TYPE_BOOLEAN, (params->type == PICTURE_IMPROVED_PB),
        "annex-n", G_TYPE_BOOLEAN, (params->features & H263_OPTION_RPS_MODE),
        "annex-q", G_TYPE_BOOLEAN, (params->features & H263_OPTION_RRU_MODE),
        "annex-r", G_TYPE_BOOLEAN, (params->features & H263_OPTION_ISD_MODE),
        "annex-s", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AIV_MODE),
        "annex-t", G_TYPE_BOOLEAN, (params->features & H263_OPTION_MQ_MODE),
        "annex-u", G_TYPE_BOOLEAN, (params->features & H263_OPTION_ERPS_MODE),
        "annex-v", G_TYPE_BOOLEAN, (params->features & H263_OPTION_DPS_MODE),
        NULL);

    h263parse->profile = gst_h263_parse_get_profile (params);
    if (h263parse->profile != -1) {
      gchar *profile_str;

      profile_str = g_strdup_printf ("%u", h263parse->profile);
      gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_str, NULL);
      g_free (profile_str);
    }

    h263parse->level = gst_h263_parse_get_level (params, h263parse->profile,
        h263parse->bitrate, fr_num, fr_denom);
    if (h263parse->level != -1) {
      gchar *level_str;

      level_str = g_strdup_printf ("%u", h263parse->level);
      gst_caps_set_simple (caps, "level", G_TYPE_STRING, level_str, NULL);
      g_free (level_str);
    }
  }

  gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (h263parse)), caps);
  gst_caps_unref (caps);
}
Ejemplo n.º 4
0
static void
gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse)
{
  GstCaps *caps = NULL;
  GstStructure *s = NULL;

  /* only update if no src caps yet or explicitly triggered */
  if (G_LIKELY (gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (mpvparse)) &&
          !mpvparse->update_caps))
    return;

  /* carry over input caps as much as possible; override with our own stuff */
  caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (mpvparse));
  if (caps) {
    caps = gst_caps_make_writable (caps);
    s = gst_caps_get_structure (caps, 0);
  } else {
    caps = gst_caps_new_empty_simple ("video/mpeg");
  }

  /* typically we don't output buffers until we have properly parsed some
   * config data, so we should at least know about version.
   * If not, it means it has been requested not to drop data, and
   * upstream and/or app must know what they are doing ... */
  gst_caps_set_simple (caps,
      "mpegversion", G_TYPE_INT, (mpvparse->config_flags & FLAG_MPEG2) ? 2 : 1,
      NULL);

  gst_caps_set_simple (caps, "systemstream", G_TYPE_BOOLEAN, FALSE,
      "parsed", G_TYPE_BOOLEAN, TRUE, NULL);

  if (mpvparse->sequencehdr.width > 0 && mpvparse->sequencehdr.height > 0) {
    GstMpegVideoSequenceDisplayExt *seqdispext;
    gint width, height;

    width = mpvparse->sequencehdr.width;
    height = mpvparse->sequencehdr.height;

    if (mpvparse->config_flags & FLAG_SEQUENCE_DISPLAY_EXT) {
      seqdispext = &mpvparse->sequencedispext;

      if (seqdispext->display_horizontal_size <= width
          && seqdispext->display_vertical_size <= height) {
        width = seqdispext->display_horizontal_size;
        height = seqdispext->display_vertical_size;
        GST_INFO_OBJECT (mpvparse,
            "stream has display extension: display_width=%d display_height=%d",
            width, height);
      }
    }
    gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
        "height", G_TYPE_INT, height, NULL);
  }

  /* perhaps we have a framerate */
  {
    gint fps_num = mpvparse->fps_num;
    gint fps_den = mpvparse->fps_den;
    GstClockTime latency;

    /* upstream overrides */
    if (s && gst_structure_has_field (s, "framerate"))
      gst_structure_get_fraction (s, "framerate", &fps_num, &fps_den);

    if (fps_den > 0 && fps_num > 0) {
      gst_caps_set_simple (caps, "framerate",
          GST_TYPE_FRACTION, fps_num, fps_den, NULL);
      gst_base_parse_set_frame_rate (GST_BASE_PARSE (mpvparse),
          fps_num, fps_den, 0, 0);
      latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num);
      gst_base_parse_set_latency (GST_BASE_PARSE (mpvparse), latency, latency);
    }
  }

  /* or pixel-aspect-ratio */
  if (mpvparse->sequencehdr.par_w && mpvparse->sequencehdr.par_h > 0 &&
      (!s || !gst_structure_has_field (s, "pixel-aspect-ratio"))) {
    gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
        mpvparse->sequencehdr.par_w, mpvparse->sequencehdr.par_h, NULL);
  }

  if (mpvparse->config != NULL) {
    gst_caps_set_simple (caps, "codec_data",
        GST_TYPE_BUFFER, mpvparse->config, NULL);
  }

  if (mpvparse->config_flags & FLAG_SEQUENCE_EXT) {
    const guint profile_c = mpvparse->sequenceext.profile;
    const guint level_c = mpvparse->sequenceext.level;
    const gchar *profile = NULL, *level = NULL;
    /*
     * Profile indication - 1 => High, 2 => Spatially Scalable,
     *                      3 => SNR Scalable, 4 => Main, 5 => Simple
     * 4:2:2 and Multi-view have profile = 0, with the escape bit set to 1
     */
    const gchar *const profiles[] =
        { "high", "spatial", "snr", "main", "simple" };
    /*
     * Level indication - 4 => High, 6 => High-1440, 8 => Main, 10 => Low,
     *                    except in the case of profile = 0
     */
    const gchar *const levels[] = { "high", "high-1440", "main", "low" };

    if (profile_c > 0 && profile_c < 6)
      profile = profiles[profile_c - 1];

    if ((level_c > 3) && (level_c < 11) && (level_c % 2 == 0))
      level = levels[(level_c >> 1) - 2];

    if (profile_c == 8) {
      /* Non-hierarchical profile */
      switch (level_c) {
        case 2:
          level = levels[0];
        case 5:
          level = levels[2];
          profile = "4:2:2";
          break;
        case 10:
          level = levels[0];
        case 11:
          level = levels[1];
        case 13:
          level = levels[2];
        case 14:
          level = levels[3];
          profile = "multiview";
          break;
        default:
          break;
      }
    }

    /* FIXME does it make sense to expose profile/level in the caps ? */

    GST_DEBUG_OBJECT (mpvparse, "profile:'%s' level:'%s'", profile, level);

    if (profile)
      gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
    else
      GST_DEBUG_OBJECT (mpvparse, "Invalid profile - %u", profile_c);

    if (level)
      gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
    else
      GST_DEBUG_OBJECT (mpvparse, "Invalid level - %u", level_c);

    gst_caps_set_simple (caps, "interlace-mode",
        G_TYPE_STRING,
        (mpvparse->sequenceext.progressive ? "progressive" : "mixed"), NULL);
  }

  gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (mpvparse), caps);
  gst_caps_unref (caps);

  mpvparse->update_caps = FALSE;
}