static gboolean gst_h263_parse_sink_event (GstBaseParse * parse, GstEvent * event) { GstH263Parse *h263parse; gboolean res = FALSE; h263parse = GST_H263_PARSE (parse); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_TAG: { GstTagList *taglist; gst_event_parse_tag (event, &taglist); if (gst_tag_list_get_uint (taglist, GST_TAG_BITRATE, &h263parse->bitrate)) GST_DEBUG_OBJECT (h263parse, "got bitrate tag: %u", h263parse->bitrate); break; } default: break; } return res; }
static GstFlowReturn gst_h263_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstH263Parse *h263parse = GST_H263_PARSE (parse); if (!h263parse->sent_codec_tag) { GstTagList *taglist; GstCaps *caps; taglist = gst_tag_list_new_empty (); /* codec tag */ caps = gst_pad_get_current_caps (GST_BASE_PARSE_SRC_PAD (parse)); gst_pb_utils_add_codec_description_to_tag_list (taglist, GST_TAG_VIDEO_CODEC, caps); gst_caps_unref (caps); gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (h263parse), gst_event_new_tag (taglist)); /* also signals the end of first-frame processing */ h263parse->sent_codec_tag = TRUE; } return GST_FLOW_OK; }
static gboolean gst_h263_parse_start (GstBaseParse * parse) { GstH263Parse *h263parse = GST_H263_PARSE (parse); GST_DEBUG_OBJECT (h263parse, "start"); h263parse->bitrate = 0; h263parse->profile = -1; h263parse->level = -1; h263parse->state = PARSING; gst_base_parse_set_min_frame_size (parse, 4); return TRUE; }
static GstFlowReturn gst_h263_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstH263Parse *h263parse; GstBuffer *buffer; GstFlowReturn res; H263Params params = { 0, }; h263parse = GST_H263_PARSE (parse); buffer = frame->buffer; res = gst_h263_parse_get_params (¶ms, buffer, TRUE, &h263parse->state); if (res != GST_FLOW_OK) goto out; if (h263parse->state == PASSTHROUGH || h263parse->state == PARSING) { /* There's a feature we don't support, or we didn't have enough data to * parse the header, which should not be possible. Either way, go into * passthrough mode and let downstream handle it if it can. */ GST_WARNING ("Couldn't parse header - setting passthrough mode"); gst_base_parse_set_passthrough (parse, TRUE); goto out; } /* h263parse->state is now GOT_HEADER */ gst_buffer_set_caps (buffer, GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (h263parse)))); if (gst_h263_parse_is_delta_unit (¶ms)) GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); else GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); out: return res; }
static gboolean gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { GstH263Parse *h263parse; GstBuffer *buffer; guint psc_pos, next_psc_pos; h263parse = GST_H263_PARSE (parse); buffer = frame->buffer; if (GST_BUFFER_SIZE (buffer) < 3) return FALSE; psc_pos = find_psc (buffer, 0); if (psc_pos == -1) { /* PSC not found, need more data */ if (GST_BUFFER_SIZE (buffer) > 3) psc_pos = GST_BUFFER_SIZE (buffer) - 3; else psc_pos = 0; goto more; } /* Found the start of the frame, now try to find the end */ next_psc_pos = psc_pos + 3; next_psc_pos = find_psc (buffer, next_psc_pos); if (next_psc_pos == -1) { if (GST_BASE_PARSE_DRAINING (parse)) /* FLUSH/EOS, it's okay if we can't find the next frame */ next_psc_pos = GST_BUFFER_SIZE (buffer); else goto more; } /* We should now have a complete frame */ /* If this is the first frame, parse and set srcpad caps */ if (h263parse->state == PARSING) { H263Params params = { 0, }; GstFlowReturn res; res = gst_h263_parse_get_params (¶ms, buffer, FALSE, &h263parse->state); if (res != GST_FLOW_OK || h263parse->state != GOT_HEADER) { GST_WARNING ("Couldn't parse header - setting passthrough mode"); gst_base_parse_set_passthrough (parse, TRUE); } else { /* Set srcpad caps since we now have sufficient information to do so */ gst_h263_parse_set_src_caps (h263parse, ¶ms); gst_base_parse_set_passthrough (parse, FALSE); } } *skipsize = psc_pos; *framesize = next_psc_pos - psc_pos; /* XXX: After getting a keyframe, should we adjust min_frame_size to * something smaller so we don't end up collecting too many non-keyframes? */ GST_DEBUG_OBJECT (h263parse, "found a frame of size %d at pos %d", *framesize, *skipsize); return TRUE; more: /* ask for best next available */ *framesize = G_MAXUINT; *skipsize = psc_pos; return FALSE; }
static GstFlowReturn gst_h263_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame, gint * skipsize) { GstH263Parse *h263parse; GstBuffer *buffer; guint psc_pos, next_psc_pos; gsize size; H263Params params = { 0, }; GstFlowReturn res = GST_FLOW_OK; h263parse = GST_H263_PARSE (parse); buffer = frame->buffer; size = gst_buffer_get_size (buffer); if (size < 3) { *skipsize = 1; return GST_FLOW_OK; } psc_pos = find_psc (buffer, 0); if (psc_pos == -1) { /* PSC not found, need more data */ if (size > 3) psc_pos = size - 3; else psc_pos = 0; goto more; } /* need to skip */ if (psc_pos > 0) goto more; /* Found the start of the frame, now try to find the end */ next_psc_pos = psc_pos + 3; next_psc_pos = find_psc (buffer, next_psc_pos); if (next_psc_pos == -1) { if (GST_BASE_PARSE_DRAINING (parse)) /* FLUSH/EOS, it's okay if we can't find the next frame */ next_psc_pos = size; else goto more; } /* We should now have a complete frame */ /* If this is the first frame, parse and set srcpad caps */ if (h263parse->state == PARSING) { res = gst_h263_parse_get_params (¶ms, buffer, FALSE, &h263parse->state); if (res != GST_FLOW_OK || h263parse->state != GOT_HEADER) { GST_WARNING ("Couldn't parse header - setting passthrough mode"); gst_base_parse_set_passthrough (parse, TRUE); } else { /* Set srcpad caps since we now have sufficient information to do so */ gst_h263_parse_set_src_caps (h263parse, ¶ms); gst_base_parse_set_passthrough (parse, FALSE); } memset (¶ms, 0, sizeof (params)); } /* XXX: After getting a keyframe, should we adjust min_frame_size to * something smaller so we don't end up collecting too many non-keyframes? */ GST_DEBUG_OBJECT (h263parse, "found a frame of size %u at pos %u", next_psc_pos, psc_pos); res = gst_h263_parse_get_params (¶ms, buffer, TRUE, &h263parse->state); if (res != GST_FLOW_OK) goto more; if (h263parse->state == PASSTHROUGH || h263parse->state == PARSING) { /* There's a feature we don't support, or we didn't have enough data to * parse the header, which should not be possible. Either way, go into * passthrough mode and let downstream handle it if it can. */ GST_WARNING ("Couldn't parse header - setting passthrough mode"); gst_base_parse_set_passthrough (parse, TRUE); goto more; } if (gst_h263_parse_is_delta_unit (¶ms)) GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); else GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); return gst_base_parse_finish_frame (parse, frame, next_psc_pos); more: *skipsize = psc_pos; return res; }