/** * gst_amr_parse_sink_setcaps: * @sinkpad: GstPad * @caps: GstCaps * * Returns: TRUE on success. */ static gboolean gst_amr_parse_sink_setcaps (GstBaseParse * parse, GstCaps * caps) { GstAmrParse *amrparse; GstStructure *structure; const gchar *name; amrparse = GST_AMR_PARSE (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_rate (GST_BASE_PARSE (amrparse), 50, 1, 2, 2); gst_amr_parse_set_src_caps (amrparse); return TRUE; }
static GstFlowReturn gst_amr_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstAmrParse *amrparse = GST_AMR_PARSE (parse); if (!amrparse->sent_codec_tag) { GstTagList *taglist; GstCaps *caps; /* codec tag */ caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse)); if (G_UNLIKELY (caps == NULL)) { if (GST_PAD_IS_FLUSHING (GST_BASE_PARSE_SRC_PAD (parse))) { GST_INFO_OBJECT (parse, "Src pad is flushing"); return GST_FLOW_FLUSHING; } else { GST_INFO_OBJECT (parse, "Src pad is not negotiated!"); return GST_FLOW_NOT_NEGOTIATED; } } taglist = gst_tag_list_new_empty (); gst_pb_utils_add_codec_description_to_tag_list (taglist, GST_TAG_AUDIO_CODEC, caps); gst_caps_unref (caps); gst_base_parse_merge_tags (parse, taglist, GST_TAG_MERGE_REPLACE); gst_tag_list_unref (taglist); /* also signals the end of first-frame processing */ amrparse->sent_codec_tag = TRUE; } return GST_FLOW_OK; }
/** * gst_amr_parse_stop: * @parse: #GstBaseParse. * * Implementation of "stop" vmethod in #GstBaseParse class. * * Returns: TRUE on success. */ static gboolean gst_amr_parse_stop (GstBaseParse * parse) { GstAmrParse *amrparse; amrparse = GST_AMR_PARSE (parse); GST_DEBUG ("stop"); amrparse->need_header = TRUE; amrparse->header = 0; return TRUE; }
/** * gst_amr_parse_start: * @parse: #GstBaseParse. * * Implementation of "start" vmethod in #GstBaseParse class. * * Returns: TRUE on success. */ static gboolean gst_amr_parse_start (GstBaseParse * parse) { GstAmrParse *amrparse; amrparse = GST_AMR_PARSE (parse); GST_DEBUG ("start"); amrparse->need_header = TRUE; amrparse->header = 0; amrparse->sent_codec_tag = FALSE; return TRUE; }
/** * gst_amr_parse_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_amr_parse_check_valid_frame (GstBaseParse * parse, GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { GstBuffer *buffer; const guint8 *data; gint fsize, mode, dsize; GstAmrParse *amrparse; amrparse = GST_AMR_PARSE (parse); buffer = frame->buffer; 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_amr_parse_parse_header (amrparse, data, skipsize)) { amrparse->need_header = FALSE; gst_base_parse_set_frame_rate (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 (fsize && (!GST_BASE_PARSE_LOST_SYNC (parse) || GST_BASE_PARSE_DRAINING (parse) || (dsize > fsize && (data[fsize] & 0x83) == 0))) { *framesize = fsize; return TRUE; } }
/** * gst_amr_parse_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. */ static GstFlowReturn gst_amr_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame, gint * skipsize) { GstBuffer *buffer; GstMapInfo map; gint fsize = 0, mode, dsize; GstAmrParse *amrparse; GstFlowReturn ret = GST_FLOW_OK; gboolean found = FALSE; amrparse = GST_AMR_PARSE (parse); buffer = frame->buffer; gst_buffer_map (buffer, &map, GST_MAP_READ); dsize = map.size; GST_LOG ("buffer: %d bytes", dsize); if (amrparse->need_header) { if (dsize >= AMR_MIME_HEADER_SIZE && gst_amr_parse_parse_header (amrparse, map.data, skipsize)) { amrparse->need_header = FALSE; gst_base_parse_set_frame_rate (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. */ goto done; } *skipsize = 1; /* Does this look like a possible frame header candidate? */ if ((map.data[0] & 0x83) == 0) { /* Yep. Retrieve the frame size */ mode = (map.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 (fsize) { *skipsize = 0; /* in sync, no further check */ if (!GST_BASE_PARSE_LOST_SYNC (parse)) { found = TRUE; } else if (dsize > fsize) { /* enough data, check for next sync */ if ((map.data[fsize] & 0x83) == 0) found = TRUE; } else if (GST_BASE_PARSE_DRAINING (parse)) { /* not enough, but draining, so ok */ found = TRUE; } } }