static GstCaps * gst_ac3_parse_get_sink_caps (GstBaseParse * parse) { GstCaps *peercaps; GstCaps *res; peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse)); if (peercaps) { guint i, n; /* Remove the framed and alignment field. We can convert * between different alignments. */ peercaps = gst_caps_make_writable (peercaps); n = gst_caps_get_size (peercaps); for (i = 0; i < n; i++) { GstStructure *s = gst_caps_get_structure (peercaps, i); gst_structure_remove_field (s, "framed"); gst_structure_remove_field (s, "alignment"); } res = gst_caps_intersect_full (peercaps, gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)), GST_CAPS_INTERSECT_FIRST); gst_caps_unref (peercaps); } else { res = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse))); } return res; }
static GstCaps * gst_h263_parse_get_sink_caps (GstBaseParse * parse) { GstCaps *peercaps; GstCaps *res; peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse)); if (peercaps) { guint i, n; /* Remove parsed field */ peercaps = gst_caps_make_writable (peercaps); n = gst_caps_get_size (peercaps); for (i = 0; i < n; i++) { GstStructure *s = gst_caps_get_structure (peercaps, i); gst_structure_remove_field (s, "parsed"); } res = gst_caps_intersect_full (peercaps, gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)), GST_CAPS_INTERSECT_FIRST); gst_caps_unref (peercaps); } else { res = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse))); } return res; }
static void gst_dirac_parse_init (GstDiracParse * diracparse) { gst_base_parse_set_min_frame_size (GST_BASE_PARSE (diracparse), 13); gst_base_parse_set_pts_interpolation (GST_BASE_PARSE (diracparse), FALSE); GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (diracparse)); GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (diracparse)); }
/** * gst_amr_parse_init: * @amrparse: #GstAmrParse * @klass: #GstAmrParseClass. * */ static void gst_amr_parse_init (GstAmrParse * amrparse) { /* init rest */ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (amrparse), 62); GST_DEBUG ("initialized"); GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (amrparse)); GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (amrparse)); }
static void gst_ac3_parse_init (GstAc3Parse * ac3parse) { gst_base_parse_set_min_frame_size (GST_BASE_PARSE (ac3parse), 8); gst_ac3_parse_reset (ac3parse); ac3parse->baseparse_chainfunc = GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE (ac3parse))->chainfunc; GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (ac3parse)); GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (ac3parse)); }
static void gst_h264_parse_init (GstH264Parse * h264parse, GstH264ParseClass * g_class) { h264parse->frame_out = gst_adapter_new (); /* retrieve and intercept baseparse. * Quite HACKish, but fairly OK since it is needed to perform avc packet * splitting, which is the penultimate de-parsing */ h264parse->parse_chain = GST_PAD_CHAINFUNC (GST_BASE_PARSE_SINK_PAD (h264parse)); gst_pad_set_chain_function (GST_BASE_PARSE_SINK_PAD (h264parse), gst_h264_parse_chain); }
static GstCaps * gst_amr_parse_sink_getcaps (GstBaseParse * parse, GstCaps * filter) { GstCaps *peercaps, *templ; GstCaps *res; templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)); peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), filter); if (peercaps) { guint i, n; /* Rename structure names */ peercaps = gst_caps_make_writable (peercaps); n = gst_caps_get_size (peercaps); for (i = 0; i < n; i++) { GstStructure *s = gst_caps_get_structure (peercaps, i); if (gst_structure_has_name (s, "audio/AMR")) gst_structure_set_name (s, "audio/x-amr-nb-sh"); else gst_structure_set_name (s, "audio/x-amr-wb-sh"); } res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (peercaps); res = gst_caps_make_writable (res); /* Append the template caps because we still want to accept * caps without any fields in the case upstream does not * know anything. */ gst_caps_append (res, templ); } else { res = templ; } if (filter) { GstCaps *intersection; intersection = gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (res); res = intersection; } return res; }
static GstCaps * gst_ac3_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter) { GstCaps *peercaps, *templ; GstCaps *res; templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)); peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), filter); if (peercaps) { guint i, n; /* Remove the framed and alignment field. We can convert * between different alignments. */ peercaps = gst_caps_make_writable (peercaps); n = gst_caps_get_size (peercaps); for (i = 0; i < n; i++) { GstStructure *s = gst_caps_get_structure (peercaps, i); gst_structure_remove_field (s, "framed"); gst_structure_remove_field (s, "alignment"); } res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (peercaps); res = gst_caps_make_writable (res); /* Append the template caps because we still want to accept * caps without any fields in the case upstream does not * know anything. */ gst_caps_append (res, templ); } else { res = templ; } if (filter) { GstCaps *intersection; intersection = gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (res); res = intersection; } return res; }
static GstCaps * gst_ac3_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter) { GstCaps *peercaps, *templ; GstCaps *res; templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)); if (filter) { GstCaps *fcopy = gst_caps_copy (filter); /* Remove the fields we convert */ remove_fields (fcopy); /* we do not ask downstream to handle x-private1-ac3 */ fcopy = extend_caps (fcopy, FALSE); peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy); gst_caps_unref (fcopy); } else peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL); if (peercaps) { /* Remove the framed and alignment field. We can convert * between different alignments. */ peercaps = gst_caps_make_writable (peercaps); remove_fields (peercaps); /* also allow for x-private1-ac3 input */ peercaps = extend_caps (peercaps, TRUE); res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (peercaps); gst_caps_unref (templ); } else { res = templ; } if (filter) { GstCaps *intersection; intersection = gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (res); res = intersection; } return res; }
static GstCaps * gst_dirac_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter) { GstCaps *peercaps, *templ; GstCaps *res; templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse)); if (filter) { GstCaps *fcopy = gst_caps_copy (filter); /* Remove the fields we convert */ remove_fields (fcopy); peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy); gst_caps_unref (fcopy); } else peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL); if (peercaps) { /* Remove the parsed field */ peercaps = gst_caps_make_writable (peercaps); remove_fields (peercaps); res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (peercaps); gst_caps_unref (templ); } else { res = templ; } if (filter) { GstCaps *intersection; intersection = gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST); gst_caps_unref (res); res = intersection; } return res; }
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); }
static void gst_mpegv_parse_update_src_caps (GstMpegvParse * mpvparse) { GstCaps *caps = 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); } 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) { gst_caps_set_simple (caps, "width", G_TYPE_INT, mpvparse->sequencehdr.width, "height", G_TYPE_INT, mpvparse->sequencehdr.height, NULL); } /* perhaps we have a framerate */ if (mpvparse->fps_num > 0 && mpvparse->fps_den > 0) { gint fps_num = mpvparse->fps_num; gint fps_den = mpvparse->fps_den; GstClockTime latency = gst_util_uint64_scale (GST_SECOND, fps_den, fps_num); 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); 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) { 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; }
static void gst_h263_parse_set_src_caps (GstH263Parse * h263parse, const H263Params * params) { GstStructure *st; GstCaps *caps, *sink_caps; gint fr_num, fr_denom; g_assert (h263parse->state == PASSTHROUGH || h263parse->state == GOT_HEADER); caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h263parse)); if (caps) { caps = gst_caps_copy (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_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 (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) gst_caps_set_simple (caps, "profile", G_TYPE_UINT, h263parse->profile, NULL); h263parse->level = gst_h263_parse_get_level (params, h263parse->profile, h263parse->bitrate, fr_num, fr_denom); if (h263parse->level != -1) gst_caps_set_simple (caps, "level", G_TYPE_UINT, h263parse->level, NULL); } gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (h263parse)), caps); gst_caps_unref (caps); }
static GstFlowReturn gst_opus_parse_parse_frame (GstBaseParse * base, GstBaseParseFrame * frame) { guint64 duration; GstOpusParse *parse; gboolean is_idheader, is_commentheader; GstMapInfo map; GstAudioClippingMeta *cmeta = gst_buffer_get_audio_clipping_meta (frame->buffer); parse = GST_OPUS_PARSE (base); g_assert (!cmeta || cmeta->format == GST_FORMAT_DEFAULT); is_idheader = gst_opus_header_is_id_header (frame->buffer); is_commentheader = gst_opus_header_is_comment_header (frame->buffer); if (!parse->got_headers || !parse->header_sent) { GstCaps *caps; /* Opus streams can decode to 1 or 2 channels, so use the header value if we have one, or 2 otherwise */ if (is_idheader) { gst_buffer_replace (&parse->id_header, frame->buffer); GST_DEBUG_OBJECT (parse, "Found ID header, keeping"); return GST_BASE_PARSE_FLOW_DROPPED; } else if (is_commentheader) { gst_buffer_replace (&parse->comment_header, frame->buffer); GST_DEBUG_OBJECT (parse, "Found comment header, keeping"); return GST_BASE_PARSE_FLOW_DROPPED; } parse->got_headers = TRUE; if (cmeta && cmeta->start) { parse->pre_skip += cmeta->start; gst_buffer_map (frame->buffer, &map, GST_MAP_READ); duration = packet_duration_opus (map.data, map.size); gst_buffer_unmap (frame->buffer, &map); /* Queue frame for later once we know all initial padding */ if (duration == cmeta->start) { frame->flags |= GST_BASE_PARSE_FRAME_FLAG_QUEUE; } } if (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_QUEUE)) { if (FALSE && parse->id_header && parse->comment_header) { guint16 pre_skip; gst_buffer_map (parse->id_header, &map, GST_MAP_READWRITE); pre_skip = GST_READ_UINT16_LE (map.data + 10); if (pre_skip != parse->pre_skip) { GST_DEBUG_OBJECT (parse, "Fixing up pre-skip %u -> %" G_GUINT64_FORMAT, pre_skip, parse->pre_skip); GST_WRITE_UINT16_LE (map.data + 10, parse->pre_skip); } gst_buffer_unmap (parse->id_header, &map); caps = gst_codec_utils_opus_create_caps_from_header (parse->id_header, parse->comment_header); } else { GstCaps *sink_caps; guint32 sample_rate = 48000; guint8 n_channels, n_streams, n_stereo_streams, channel_mapping_family; guint8 channel_mapping[256]; GstBuffer *id_header; sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse)); if (!sink_caps || !gst_codec_utils_opus_parse_caps (sink_caps, &sample_rate, &n_channels, &channel_mapping_family, &n_streams, &n_stereo_streams, channel_mapping)) { GST_INFO_OBJECT (parse, "No headers and no caps, blindly setting up canonical stereo"); n_channels = 2; n_streams = 1; n_stereo_streams = 1; channel_mapping_family = 0; channel_mapping[0] = 0; channel_mapping[1] = 1; } if (sink_caps) gst_caps_unref (sink_caps); id_header = gst_codec_utils_opus_create_header (sample_rate, n_channels, channel_mapping_family, n_streams, n_stereo_streams, channel_mapping, parse->pre_skip, 0); caps = gst_codec_utils_opus_create_caps_from_header (id_header, NULL); gst_buffer_unref (id_header); } gst_buffer_replace (&parse->id_header, NULL); gst_buffer_replace (&parse->comment_header, NULL); gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); gst_caps_unref (caps); parse->header_sent = TRUE; } } GST_BUFFER_TIMESTAMP (frame->buffer) = parse->next_ts; gst_buffer_map (frame->buffer, &map, GST_MAP_READ); duration = packet_duration_opus (map.data, map.size); gst_buffer_unmap (frame->buffer, &map); parse->next_ts += duration; GST_BUFFER_DURATION (frame->buffer) = duration; GST_BUFFER_OFFSET_END (frame->buffer) = gst_util_uint64_scale (parse->next_ts, 48000, GST_SECOND); GST_BUFFER_OFFSET (frame->buffer) = parse->next_ts; return GST_FLOW_OK; }
static GstFlowReturn gst_png_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame, gint * skipsize) { GstPngParse *pngparse = GST_PNG_PARSE (parse); GstMapInfo map; GstByteReader reader; GstFlowReturn ret = GST_FLOW_OK; guint64 signature; guint width = 0, height = 0; gst_buffer_map (frame->buffer, &map, GST_MAP_READ); gst_byte_reader_init (&reader, map.data, map.size); if (!gst_byte_reader_peek_uint64_be (&reader, &signature)) goto beach; if (signature != PNG_SIGNATURE) { for (;;) { guint offset; offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, 0x89504E47, 0, gst_byte_reader_get_remaining (&reader)); if (offset == -1) { *skipsize = gst_byte_reader_get_remaining (&reader) - 4; goto beach; } gst_byte_reader_skip (&reader, offset); if (!gst_byte_reader_peek_uint64_be (&reader, &signature)) goto beach; if (signature == PNG_SIGNATURE) { /* We're skipping, go out, we'll be back */ *skipsize = gst_byte_reader_get_pos (&reader); goto beach; } gst_byte_reader_skip (&reader, 4); } } gst_byte_reader_skip (&reader, 8); for (;;) { guint32 length; guint32 code; if (!gst_byte_reader_get_uint32_be (&reader, &length)) goto beach; if (!gst_byte_reader_get_uint32_le (&reader, &code)) goto beach; if (code == GST_MAKE_FOURCC ('I', 'H', 'D', 'R')) { if (!gst_byte_reader_get_uint32_be (&reader, &width)) goto beach; if (!gst_byte_reader_get_uint32_be (&reader, &height)) goto beach; length -= 8; } if (!gst_byte_reader_skip (&reader, length + 4)) goto beach; if (code == GST_MAKE_FOURCC ('I', 'E', 'N', 'D')) { if (pngparse->width != width || pngparse->height != height) { GstStructure *st = NULL; GstCaps *caps, *sink_caps; gint fr_num, fr_denom; pngparse->height = height; pngparse->width = width; sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (pngparse)); 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 (pngparse, "sink caps override framerate from headers"); } else { GST_INFO_OBJECT (pngparse, "No framerate set"); } caps = gst_caps_new_simple ("image/png", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, fr_num, fr_denom, NULL); if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps)) { ret = GST_FLOW_NOT_NEGOTIATED; } gst_caps_unref (caps); if (ret != GST_FLOW_OK) goto beach; } gst_buffer_unmap (frame->buffer, &map); return gst_base_parse_finish_frame (parse, frame, gst_byte_reader_get_pos (&reader)); } } beach: gst_buffer_unmap (frame->buffer, &map); return ret; }
static GstFlowReturn gst_png_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame, gint * skipsize) { GstPngParse *pngparse = GST_PNG_PARSE (parse); GstMapInfo map; GstByteReader reader; GstFlowReturn ret = GST_FLOW_OK; guint64 signature; guint width = 0, height = 0; gst_buffer_map (frame->buffer, &map, GST_MAP_READ); gst_byte_reader_init (&reader, map.data, map.size); if (!gst_byte_reader_peek_uint64_be (&reader, &signature)) goto beach; if (signature != PNG_SIGNATURE) { for (;;) { guint offset; offset = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, 0x89504E47, 0, gst_byte_reader_get_remaining (&reader)); if (offset == -1) { *skipsize = gst_byte_reader_get_remaining (&reader) - 4; goto beach; } gst_byte_reader_skip (&reader, offset); if (!gst_byte_reader_peek_uint64_be (&reader, &signature)) goto beach; if (signature == PNG_SIGNATURE) { /* We're skipping, go out, we'll be back */ *skipsize = gst_byte_reader_get_pos (&reader); goto beach; } gst_byte_reader_skip (&reader, 4); } } gst_byte_reader_skip (&reader, 8); for (;;) { guint32 length; guint32 code; if (!gst_byte_reader_get_uint32_be (&reader, &length)) goto beach; if (!gst_byte_reader_get_uint32_le (&reader, &code)) goto beach; GST_TRACE_OBJECT (parse, "%" GST_FOURCC_FORMAT " chunk, %u bytes", GST_FOURCC_ARGS (code), length); if (code == GST_MAKE_FOURCC ('I', 'H', 'D', 'R')) { if (!gst_byte_reader_get_uint32_be (&reader, &width)) goto beach; if (!gst_byte_reader_get_uint32_be (&reader, &height)) goto beach; length -= 8; } else if (code == GST_MAKE_FOURCC ('I', 'D', 'A', 'T')) { gst_base_parse_set_min_frame_size (parse, gst_byte_reader_get_pos (&reader) + 4 + length + 12); } if (!gst_byte_reader_skip (&reader, length + 4)) goto beach; if (code == GST_MAKE_FOURCC ('I', 'E', 'N', 'D')) { /* the start code and at least 2 empty frames (IHDR and IEND) */ gst_base_parse_set_min_frame_size (parse, 8 + 12 + 12); if (pngparse->width != width || pngparse->height != height) { GstCaps *caps, *sink_caps; pngparse->height = height; pngparse->width = width; caps = gst_caps_new_simple ("image/png", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (pngparse)); if (sink_caps) { GstStructure *st; gint fr_num, fr_denom; st = gst_caps_get_structure (sink_caps, 0); if (st && gst_structure_get_fraction (st, "framerate", &fr_num, &fr_denom)) { gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, fr_num, fr_denom, NULL); } else { GST_WARNING_OBJECT (pngparse, "No framerate set"); } gst_caps_unref (sink_caps); } if (!gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps)) ret = GST_FLOW_NOT_NEGOTIATED; gst_caps_unref (caps); if (ret != GST_FLOW_OK) goto beach; } gst_buffer_unmap (frame->buffer, &map); return gst_base_parse_finish_frame (parse, frame, gst_byte_reader_get_pos (&reader)); } } beach: gst_buffer_unmap (frame->buffer, &map); return ret; }
static void gst_png_parse_init (GstPngParse * pngparse) { GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (pngparse)); GST_PAD_SET_ACCEPT_TEMPLATE (GST_BASE_PARSE_SINK_PAD (pngparse)); }
static void gst_h263_parse_init (GstH263Parse * h263parse) { GST_PAD_SET_ACCEPT_INTERSECT (GST_BASE_PARSE_SINK_PAD (h263parse)); }