/** * gst_h263_parse: * @packet: The #GstMpeg4Packet to fill * @offset: offset from which to start the parsing * @data: The data to parse * @size: The size of the @data to parse * * Parses @data and fills @packet with the information of the next packet * found. * * Note that the type of the packet is meaningless in this case. * * Returns: a #GstMpeg4ParseResult */ GstMpeg4ParseResult gst_h263_parse (GstMpeg4Packet * packet, const guint8 * data, guint offset, gsize size) { gint off1, off2; GstByteReader br; gst_byte_reader_init (&br, data + offset, size - offset); g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR); if (size - offset < 3) { GST_DEBUG ("Can't parse, buffer is to small size %" G_GSIZE_FORMAT " at offset %d", size, offset); return GST_MPEG4_PARSER_ERROR; } off1 = find_psc (&br); if (off1 == -1) { GST_DEBUG ("No start code prefix in this buffer"); return GST_MPEG4_PARSER_NO_PACKET; } packet->offset = off1 + offset; packet->data = data; gst_byte_reader_skip_unchecked (&br, 3); off2 = find_psc (&br); if (off2 == -1) { GST_DEBUG ("Packet start %d, No end found", off1); packet->size = G_MAXUINT; return GST_MPEG4_PARSER_NO_PACKET_END; } packet->size = (gsize) off2 - off1; GST_DEBUG ("Complete packet found at: %d, Size: %" G_GSIZE_FORMAT, packet->offset, packet->size); return GST_MPEG4_PARSER_OK; }
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; }