/** * gst_amrparse_sink_setcaps: * @sinkpad: GstPad * @caps: GstCaps * * Returns: TRUE on success. */ static gboolean gst_amrparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps) { GstAmrParse *amrparse; GstStructure *structure; const gchar *name; amrparse = GST_AMRPARSE (parse); structure = gst_caps_get_structure (caps, 0); name = gst_structure_get_name (structure); GST_DEBUG_OBJECT (amrparse, "setcaps: %s", name); if (!strncmp (name, "audio/x-amr-wb-sh", 17)) { amrparse->block_size = block_size_wb; amrparse->wide = 1; } else if (!strncmp (name, "audio/x-amr-nb-sh", 17)) { amrparse->block_size = block_size_nb; amrparse->wide = 0; } else { GST_WARNING ("Unknown caps"); return FALSE; } amrparse->need_header = FALSE; gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2); gst_amrparse_set_src_caps (amrparse); return TRUE; }
/** * gst_amrparse_check_valid_frame: * @parse: #GstBaseParse. * @buffer: #GstBuffer. * @framesize: Output variable where the found frame size is put. * @skipsize: Output variable which tells how much data needs to be skipped * until a frame header is found. * * Implementation of "check_valid_frame" vmethod in #GstBaseParse class. * * Returns: TRUE if the given data contains valid frame. */ gboolean gst_amrparse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, guint * framesize, gint * skipsize) { const guint8 *data; gint fsize, mode, dsize; GstAmrParse *amrparse; amrparse = GST_AMRPARSE (parse); data = GST_BUFFER_DATA (buffer); dsize = GST_BUFFER_SIZE (buffer); GST_LOG ("buffer: %d bytes", dsize); if (amrparse->need_header) { if (dsize >= AMR_MIME_HEADER_SIZE && gst_amrparse_parse_header (amrparse, data, skipsize)) { amrparse->need_header = FALSE; gst_base_parse_set_frame_props (GST_BASE_PARSE (amrparse), 50, 1, 2, 2); } else { GST_WARNING ("media doesn't look like a AMR format"); } /* We return FALSE, so this frame won't get pushed forward. Instead, the "skip" value is set, so next time we will receive a valid frame. */ return FALSE; } /* Does this look like a possible frame header candidate? */ if ((data[0] & 0x83) == 0) { /* Yep. Retrieve the frame size */ mode = (data[0] >> 3) & 0x0F; fsize = amrparse->block_size[mode] + 1; /* +1 for the header byte */ /* We recognize this data as a valid frame when: * - We are in sync. There is no need for extra checks then * - We are in EOS. There might not be enough data to check next frame * - Sync is lost, but the following data after this frame seem * to contain a valid header as well (and there is enough data to * perform this check) */ if (gst_base_parse_get_sync (parse) || gst_base_parse_get_drain (parse) || (dsize >= fsize && (data[fsize] & 0x83) == 0)) { *framesize = fsize; return TRUE; } }
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); }