Beispiel #1
0
static gboolean
gst_vdp_mpeg_dec_parse_sequence (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer)
{
    MPEGSeqHdr hdr;

    if (!mpeg_util_parse_sequence_hdr (&hdr, buffer))
        return FALSE;

    memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix,
            &hdr.intra_quantizer_matrix, 64);
    memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix,
            &hdr.non_intra_quantizer_matrix, 64);

    if (mpeg_dec->state == GST_VDP_MPEG_DEC_NEED_SEQUENCE)
        mpeg_dec->state = GST_VDP_MPEG_DEC_NEED_DATA;

    return TRUE;
}
static GstFlowReturn
gst_vdp_mpeg_dec_handle_sequence (GstVdpMpegDec * mpeg_dec,
    GstBuffer * seq, GstBuffer * seq_ext)
{
  GstBaseVideoDecoder *base_video_decoder = GST_BASE_VIDEO_DECODER (mpeg_dec);

  MPEGSeqHdr hdr;
  GstVdpMpegStreamInfo stream_info;

  if (!mpeg_util_parse_sequence_hdr (&hdr, seq))
    return GST_FLOW_CUSTOM_ERROR;

  memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix,
      &hdr.intra_quantizer_matrix, 64);
  memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix,
      &hdr.non_intra_quantizer_matrix, 64);

  stream_info.width = hdr.width;
  stream_info.height = hdr.height;

  stream_info.fps_n = hdr.fps_n;
  stream_info.fps_d = hdr.fps_d;

  stream_info.par_n = hdr.par_w;
  stream_info.par_d = hdr.par_h;

  stream_info.interlaced = FALSE;
  stream_info.version = 1;
  stream_info.profile = VDP_DECODER_PROFILE_MPEG1;

  if (seq_ext) {
    MPEGSeqExtHdr ext;

    if (!mpeg_util_parse_sequence_extension (&ext, seq_ext))
      return GST_FLOW_CUSTOM_ERROR;

    stream_info.fps_n *= (ext.fps_n_ext + 1);
    stream_info.fps_d *= (ext.fps_d_ext + 1);

    stream_info.width += (ext.horiz_size_ext << 12);
    stream_info.height += (ext.vert_size_ext << 12);

    stream_info.interlaced = !ext.progressive;
    stream_info.version = 2;
    stream_info.profile = gst_vdp_mpeg_dec_get_profile (&ext);
  }

  if (memcmp (&mpeg_dec->stream_info, &stream_info,
          sizeof (GstVdpMpegStreamInfo)) != 0) {
    GstVideoState state;
    GstFlowReturn ret;

    state = gst_base_video_decoder_get_state (base_video_decoder);

    state.width = stream_info.width;
    state.height = stream_info.height;

    state.fps_n = stream_info.fps_n;
    state.fps_d = stream_info.fps_d;

    state.par_n = stream_info.par_n;
    state.par_d = stream_info.par_d;

    state.interlaced = stream_info.interlaced;

    gst_base_video_decoder_set_state (base_video_decoder, state);

    ret = gst_vdp_decoder_init_decoder (GST_VDP_DECODER (mpeg_dec),
        stream_info.profile, 2);
    if (ret != GST_FLOW_OK)
      return ret;

    memcpy (&mpeg_dec->stream_info, &stream_info,
        sizeof (GstVdpMpegStreamInfo));
  }

  mpeg_dec->state = GST_VDP_MPEG_DEC_STATE_NEED_DATA;

  return GST_FLOW_OK;
}
static gboolean
mpegvideoparse_handle_sequence (MpegVideoParse * mpegvideoparse,
    GstBuffer * buf)
{
  MPEGSeqHdr new_hdr;
  guint8 *cur, *end;

  cur = GST_BUFFER_DATA (buf);
  end = GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf);

  memset (&new_hdr, 0, sizeof (MPEGSeqHdr));

  if (G_UNLIKELY (!mpeg_util_parse_sequence_hdr (&new_hdr, cur, end)))
    return FALSE;

  if (new_hdr.width < 16 || new_hdr.width > 4096 ||
      new_hdr.height < 16 || new_hdr.height > 4096) {
    GST_WARNING_OBJECT (mpegvideoparse, "Width/height out of valid range "
        "[16, 4096]");
    return FALSE;
  }

  if (memcmp (&mpegvideoparse->seq_hdr, &new_hdr, sizeof (MPEGSeqHdr)) != 0) {
    GstCaps *caps;
    GstBuffer *seq_buf;
    /*
     * 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 *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 *levels[] = { "high", "high-1440", "main", "low" };

    /* Store the entire sequence header + sequence header extension
       for output as codec_data */
    seq_buf = gst_buffer_copy (buf);
    gst_buffer_replace (&mpegvideoparse->seq_hdr_buf, seq_buf);
    gst_buffer_unref (seq_buf);

    caps = gst_caps_new_simple ("video/mpeg",
        "systemstream", G_TYPE_BOOLEAN, FALSE,
        "parsed", G_TYPE_BOOLEAN, TRUE,
        "mpegversion", G_TYPE_INT, new_hdr.mpeg_version,
        "width", G_TYPE_INT, new_hdr.width,
        "height", G_TYPE_INT, new_hdr.height,
        "framerate", GST_TYPE_FRACTION, new_hdr.fps_n, new_hdr.fps_d,
        "pixel-aspect-ratio", GST_TYPE_FRACTION, new_hdr.par_w, new_hdr.par_h,
        "interlaced", G_TYPE_BOOLEAN, !new_hdr.progressive,
        "codec_data", GST_TYPE_BUFFER, seq_buf, NULL);

    if (new_hdr.mpeg_version == 2) {
      const gchar *profile = NULL, *level = NULL;

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

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

      if (new_hdr.profile == 8) {
        /* Non-hierarchical profile */
        switch (new_hdr.level) {
          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;
        }
      }

      if (profile)
        gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
      else
        GST_DEBUG ("Invalid profile - %u", new_hdr.profile);

      if (level)
        gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
      else
        GST_DEBUG ("Invalid level - %u", new_hdr.level);
    }

    GST_DEBUG ("New mpegvideoparse caps: %" GST_PTR_FORMAT, caps);
    if (!gst_pad_set_caps (mpegvideoparse->srcpad, caps)) {
      gst_caps_unref (caps);
      return FALSE;
    }
    gst_caps_unref (caps);

    if (new_hdr.bitrate > 0) {
      GstTagList *taglist;

      taglist = gst_tag_list_new_full (GST_TAG_BITRATE, new_hdr.bitrate, NULL);
      gst_element_found_tags_for_pad (GST_ELEMENT_CAST (mpegvideoparse),
          mpegvideoparse->srcpad, taglist);
    }

    /* And update the new_hdr into our stored version */
    mpegvideoparse->seq_hdr = new_hdr;
  }
Beispiel #4
0
static gboolean
gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps)
{
    GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (gst_pad_get_parent (pad));
    GstStructure *structure;

    gint width, height;
    gint fps_n, fps_d;
    gint par_n, par_d;
    gboolean interlaced = FALSE;

    GstCaps *src_caps;
    gboolean res;

    const GValue *value;

    structure = gst_caps_get_structure (caps, 0);

    /* create src_pad caps */
    gst_structure_get_int (structure, "width", &width);
    gst_structure_get_int (structure, "height", &height);
    gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d);
    gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_n, &par_d);
    gst_structure_get_boolean (structure, "interlaced", &interlaced);

    src_caps = gst_caps_new_simple ("video/x-vdpau-video",
                                    "chroma-type", G_TYPE_INT, VDP_CHROMA_TYPE_420,
                                    "width", G_TYPE_INT, width,
                                    "height", G_TYPE_INT, height,
                                    "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
                                    "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d,
                                    "interlaced", G_TYPE_BOOLEAN, interlaced, NULL);

    GST_DEBUG_OBJECT (mpeg_dec, "Setting source caps to %" GST_PTR_FORMAT,
                      src_caps);

    res = gst_pad_set_caps (mpeg_dec->src, src_caps);
    gst_caps_unref (src_caps);
    if (!res)
        goto done;

    mpeg_dec->width = width;
    mpeg_dec->height = height;
    mpeg_dec->fps_n = fps_n;
    mpeg_dec->fps_d = fps_d;
    mpeg_dec->interlaced = interlaced;

    /* parse caps to setup decoder */
    gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version);

    /* Default to MPEG1 until we find otherwise */
    mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG1;

    value = gst_structure_get_value (structure, "codec_data");
    if (value) {
        GstBuffer *codec_data, *buf;
        GstVdpMpegPacketizer packetizer;

        codec_data = gst_value_get_buffer (value);
        gst_vdp_mpeg_packetizer_init (&packetizer, codec_data);
        if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) {
            MPEGSeqHdr hdr;
            guint32 bitrate;

            mpeg_util_parse_sequence_hdr (&hdr, buf);

            memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix,
                    &hdr.intra_quantizer_matrix, 64);
            memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix,
                    &hdr.non_intra_quantizer_matrix, 64);

            bitrate = hdr.bitrate;
            gst_buffer_unref (buf);

            if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) {
                MPEGSeqExtHdr ext;

                mpeg_util_parse_sequence_extension (&ext, buf);
                if (mpeg_dec->version != 1) {
                    switch (ext.profile) {
                    case 5:
                        mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE;
                        break;
                    default:
                        mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG2_MAIN;
                        break;
                    }
                }

                bitrate += (ext.bitrate_ext << 18);
                gst_buffer_unref (buf);
            }

            mpeg_dec->duration =
                gst_util_uint64_scale (1, GST_SECOND * mpeg_dec->fps_d,
                                       mpeg_dec->fps_n);

            mpeg_dec->byterate = bitrate * 50;
            GST_DEBUG ("byterate: %" G_GINT64_FORMAT, mpeg_dec->byterate);
        }
    }

    res = TRUE;

done:
    gst_object_unref (mpeg_dec);

    return res;
}