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