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