/** As certs_cell_cert_parse(), but do not allocate the output object. */ static ssize_t certs_cell_cert_parse_into(certs_cell_cert_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u8 cert_type */ CHECK_REMAINING(1, truncated); obj->cert_type = (trunnel_get_uint8(ptr)); remaining -= 1; ptr += 1; /* Parse u16 cert_len */ CHECK_REMAINING(2, truncated); obj->cert_len = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; /* Parse u8 body[cert_len] */ CHECK_REMAINING(obj->cert_len, truncated); TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->body, obj->cert_len, {}); obj->body.n_ = obj->cert_len; memcpy(obj->body.elts_, ptr, obj->cert_len); ptr += obj->cert_len; remaining -= obj->cert_len; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; trunnel_alloc_failed: return -1; }
/** As trn_cell_introduce1_parse(), but do not allocate the output * object. */ static ssize_t trn_cell_introduce1_parse_into(trn_cell_introduce1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u8 legacy_key_id[TRUNNEL_SHA1_LEN] */ CHECK_REMAINING(TRUNNEL_SHA1_LEN, truncated); memcpy(obj->legacy_key_id, ptr, TRUNNEL_SHA1_LEN); remaining -= TRUNNEL_SHA1_LEN; ptr += TRUNNEL_SHA1_LEN; /* Parse u8 auth_key_type IN [0, 1, 2] */ CHECK_REMAINING(1, truncated); obj->auth_key_type = (trunnel_get_uint8(ptr)); remaining -= 1; ptr += 1; if (! (obj->auth_key_type == 0 || obj->auth_key_type == 1 || obj->auth_key_type == 2)) goto fail; /* Parse u16 auth_key_len */ CHECK_REMAINING(2, truncated); obj->auth_key_len = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; /* Parse u8 auth_key[auth_key_len] */ CHECK_REMAINING(obj->auth_key_len, truncated); TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->auth_key, obj->auth_key_len, {}); obj->auth_key.n_ = obj->auth_key_len; if (obj->auth_key_len) memcpy(obj->auth_key.elts_, ptr, obj->auth_key_len); ptr += obj->auth_key_len; remaining -= obj->auth_key_len; /* Parse struct trn_cell_extension extensions */ result = trn_cell_extension_parse(&obj->extensions, ptr, remaining); if (result < 0) goto relay_fail; trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; /* Parse u8 encrypted[] */ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->encrypted, remaining, {}); obj->encrypted.n_ = remaining; if (remaining) memcpy(obj->encrypted.elts_, ptr, remaining); ptr += remaining; remaining -= remaining; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; relay_fail: trunnel_assert(result < 0); return result; trunnel_alloc_failed: return -1; fail: result = -1; return result; }
/** As trn_cell_introduce_ack_parse(), but do not allocate the output * object. */ static ssize_t trn_cell_introduce_ack_parse_into(trn_cell_introduce_ack_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u16 status IN [0, 1, 2] */ CHECK_REMAINING(2, truncated); obj->status = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; if (! (obj->status == 0 || obj->status == 1 || obj->status == 2)) goto fail; /* Parse struct trn_cell_extension extensions */ result = trn_cell_extension_parse(&obj->extensions, ptr, remaining); if (result < 0) goto relay_fail; trunnel_assert((size_t)result <= remaining); remaining -= result; ptr += result; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; relay_fail: trunnel_assert(result < 0); return result; fail: result = -1; return result; }
/** As trn_cell_rendezvous1_parse(), but do not allocate the output * object. */ static ssize_t trn_cell_rendezvous1_parse_into(trn_cell_rendezvous1_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u8 rendezvous_cookie[TRUNNEL_REND_COOKIE_LEN] */ CHECK_REMAINING(TRUNNEL_REND_COOKIE_LEN, truncated); memcpy(obj->rendezvous_cookie, ptr, TRUNNEL_REND_COOKIE_LEN); remaining -= TRUNNEL_REND_COOKIE_LEN; ptr += TRUNNEL_REND_COOKIE_LEN; /* Parse u8 handshake_info[] */ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->handshake_info, remaining, {}); obj->handshake_info.n_ = remaining; if (remaining) memcpy(obj->handshake_info.elts_, ptr, remaining); ptr += remaining; remaining -= remaining; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; trunnel_alloc_failed: return -1; }
/** * gst_mpeg4_parse_group_of_vop: * @gov: The #GstMpeg4GroupOfVOP structure to fill * @data: The data to parse * @size: The size of the @data to parse * * Parses @data containing the group of video object plane packet, and fills * the @gov structure. * * Returns: a #GstMpeg4ParseResult */ GstMpeg4ParseResult gst_mpeg4_parse_group_of_vop (GstMpeg4GroupOfVOP * gov, const guint8 * data, gsize size) { guint8 gov_start_code; GstBitReader br = GST_BIT_READER_INIT (data, size); g_return_val_if_fail (gov != NULL, GST_MPEG4_PARSER_ERROR); READ_UINT8 (&br, gov_start_code, 8); if (gov_start_code != GST_MPEG4_GROUP_OF_VOP) goto wrong_start_code; CHECK_REMAINING (&br, 65); gov->hours = gst_bit_reader_get_bits_uint8_unchecked (&br, 5); gov->minutes = gst_bit_reader_get_bits_uint8_unchecked (&br, 6); /* marker bit */ MARKER_UNCHECKED (&br); gov->seconds = gst_bit_reader_get_bits_uint8_unchecked (&br, 6); gov->closed = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); gov->broken_link = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); return GST_MPEG4_PARSER_OK; failed: GST_WARNING ("failed parsing \"Group of Video Object Plane\""); return GST_MPEG4_PARSER_ERROR; wrong_start_code: GST_WARNING ("got buffer with wrong start code"); goto failed; }
/** As rsa_ed_crosscert_parse(), but do not allocate the output * object. */ static ssize_t rsa_ed_crosscert_parse_into(rsa_ed_crosscert_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u8 ed_key[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->ed_key, ptr, 32); remaining -= 32; ptr += 32; /* Parse u32 expiration */ CHECK_REMAINING(4, truncated); obj->expiration = trunnel_ntohl(trunnel_get_uint32(ptr)); remaining -= 4; ptr += 4; obj->end_of_signed = ptr; /* Parse u8 sig_len */ CHECK_REMAINING(1, truncated); obj->sig_len = (trunnel_get_uint8(ptr)); remaining -= 1; ptr += 1; /* Parse u8 sig[sig_len] */ CHECK_REMAINING(obj->sig_len, truncated); TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, obj->sig_len, {}); obj->sig.n_ = obj->sig_len; if (obj->sig_len) memcpy(obj->sig.elts_, ptr, obj->sig_len); ptr += obj->sig_len; remaining -= obj->sig_len; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; trunnel_alloc_failed: return -1; }
/** As auth_challenge_cell_parse(), but do not allocate the output * object. */ static ssize_t auth_challenge_cell_parse_into(auth_challenge_cell_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u8 challenge[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->challenge, ptr, 32); remaining -= 32; ptr += 32; /* Parse u16 n_methods */ CHECK_REMAINING(2, truncated); obj->n_methods = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; /* Parse u16 methods[n_methods] */ TRUNNEL_DYNARRAY_EXPAND(uint16_t, &obj->methods, obj->n_methods, {}); { uint16_t elt; unsigned idx; for (idx = 0; idx < obj->n_methods; ++idx) { CHECK_REMAINING(2, truncated); elt = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; TRUNNEL_DYNARRAY_ADD(uint16_t, &obj->methods, elt, {}); } } trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; trunnel_alloc_failed: return -1; }
/** As trn_cell_rendezvous2_parse(), but do not allocate the output * object. */ static ssize_t trn_cell_rendezvous2_parse_into(trn_cell_rendezvous2_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u8 handshake_info[TRUNNEL_HANDSHAKE_INFO_LEN] */ CHECK_REMAINING(TRUNNEL_HANDSHAKE_INFO_LEN, truncated); memcpy(obj->handshake_info, ptr, TRUNNEL_HANDSHAKE_INFO_LEN); remaining -= TRUNNEL_HANDSHAKE_INFO_LEN; ptr += TRUNNEL_HANDSHAKE_INFO_LEN; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; }
/** As auth1_parse(), but do not allocate the output object. */ static ssize_t auth1_parse_into(auth1_t *obj, const uint8_t *input, const size_t len_in, const auth_ctx_t *auth_ctx_ctx) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; if (auth_ctx_ctx == NULL) return -1; /* Parse u8 type[8] */ CHECK_REMAINING(8, truncated); memcpy(obj->type, ptr, 8); remaining -= 8; ptr += 8; /* Parse u8 cid[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->cid, ptr, 32); remaining -= 32; ptr += 32; /* Parse u8 sid[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->sid, ptr, 32); remaining -= 32; ptr += 32; /* Parse union u1[auth_ctx.is_ed] */ switch (auth_ctx_ctx->is_ed) { case 0: break; case 1: /* Parse u8 u1_cid_ed[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->u1_cid_ed, ptr, 32); remaining -= 32; ptr += 32; /* Parse u8 u1_sid_ed[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->u1_sid_ed, ptr, 32); remaining -= 32; ptr += 32; break; default: goto fail; break; } /* Parse u8 slog[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->slog, ptr, 32); remaining -= 32; ptr += 32; /* Parse u8 clog[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->clog, ptr, 32); remaining -= 32; ptr += 32; /* Parse u8 scert[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->scert, ptr, 32); remaining -= 32; ptr += 32; /* Parse u8 tlssecrets[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->tlssecrets, ptr, 32); remaining -= 32; ptr += 32; obj->end_of_fixed_part = ptr; /* Parse u8 rand[24] */ CHECK_REMAINING(24, truncated); memcpy(obj->rand, ptr, 24); remaining -= 24; ptr += 24; obj->end_of_signed = ptr; /* Parse u8 sig[] */ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, remaining, {}); obj->sig.n_ = remaining; memcpy(obj->sig.elts_, ptr, remaining); ptr += remaining; remaining -= remaining; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; trunnel_alloc_failed: return -1; fail: result = -1; return result; }
/** * gst_mpeg4_parse_video_object_layer: * @vol: The #GstMpeg4VideoObjectLayer structure to fill * @vo: The #GstMpeg4VisualObject currently being parsed or %NULL * @data: The data to parse * @size: The size of the @data to parse * * Parses @data containing the video object layer packet, and fills * the @vol structure. * * Returns: a #GstMpeg4ParseResult */ GstMpeg4ParseResult gst_mpeg4_parse_video_object_layer (GstMpeg4VideoObjectLayer * vol, GstMpeg4VisualObject * vo, const guint8 * data, gsize size) { guint8 video_object_layer_start_code; /* Used for enums types */ guint8 tmp; GstBitReader br = GST_BIT_READER_INIT (data, size); g_return_val_if_fail (vol != NULL, GST_MPEG4_PARSER_ERROR); GST_DEBUG ("Parsing video object layer"); READ_UINT8 (&br, video_object_layer_start_code, 8); if (!(video_object_layer_start_code >= GST_MPEG4_VIDEO_LAYER_FIRST && video_object_layer_start_code <= GST_MPEG4_VIDEO_LAYER_LAST)) goto wrong_start_code; /* set default values */ if (vo) { vol->verid = vo->verid; vol->priority = vo->priority; } else { vol->verid = 1; vol->priority = 0; } vol->low_delay = FALSE; vol->chroma_format = 1; vol->vbv_parameters = FALSE; vol->quant_precision = 5; vol->bits_per_pixel = 8; vol->quarter_sample = FALSE; vol->newpred_enable = FALSE; vol->interlaced = 0; vol->width = 0; vol->height = 0; READ_UINT8 (&br, vol->random_accessible_vol, 1); READ_UINT8 (&br, vol->video_object_type_indication, 8); READ_UINT8 (&br, vol->is_object_layer_identifier, 1); if (vol->is_object_layer_identifier) { READ_UINT8 (&br, vol->verid, 4); READ_UINT8 (&br, vol->priority, 3); } READ_UINT8 (&br, tmp, 4); vol->aspect_ratio_info = tmp; if (vol->aspect_ratio_info != GST_MPEG4_EXTENDED_PAR) { mpeg4_util_par_from_info (vol->aspect_ratio_info, &vol->par_width, &vol->par_height); } else { gint v; READ_UINT8 (&br, vol->par_width, 8); v = vol->par_width; CHECK_ALLOWED (v, 1, 255); READ_UINT8 (&br, vol->par_height, 8); v = vol->par_height; CHECK_ALLOWED (v, 1, 255); } GST_DEBUG ("Pixel aspect ratio %d/%d", vol->par_width, vol->par_width); READ_UINT8 (&br, vol->control_parameters, 1); if (vol->control_parameters) { guint8 chroma_format; READ_UINT8 (&br, chroma_format, 2); vol->chroma_format = chroma_format; READ_UINT8 (&br, vol->low_delay, 1); READ_UINT8 (&br, vol->vbv_parameters, 1); if (vol->vbv_parameters) { CHECK_REMAINING (&br, 79); vol->first_half_bitrate = gst_bit_reader_get_bits_uint16_unchecked (&br, 15); MARKER_UNCHECKED (&br); vol->latter_half_bitrate = gst_bit_reader_get_bits_uint16_unchecked (&br, 15); MARKER_UNCHECKED (&br); vol->bit_rate = (vol->first_half_bitrate << 15) | vol->latter_half_bitrate; vol->first_half_vbv_buffer_size = gst_bit_reader_get_bits_uint16_unchecked (&br, 15); MARKER_UNCHECKED (&br); vol->latter_half_vbv_buffer_size = gst_bit_reader_get_bits_uint8_unchecked (&br, 3); vol->vbv_buffer_size = (vol->first_half_vbv_buffer_size << 15) | vol->latter_half_vbv_buffer_size; vol->first_half_vbv_occupancy = gst_bit_reader_get_bits_uint16_unchecked (&br, 11); MARKER_UNCHECKED (&br); vol->latter_half_vbv_occupancy = gst_bit_reader_get_bits_uint16_unchecked (&br, 15); MARKER_UNCHECKED (&br); } } READ_UINT8 (&br, tmp, 2); vol->shape = tmp; if (vol->shape == GST_MPEG4_GRAYSCALE) { /* TODO support grayscale shapes, for now we just pass */ /* Something the standard starts to define... */ GST_WARNING ("Grayscale shaped not supported"); goto failed; } if (vol->shape == GST_MPEG4_GRAYSCALE && vol->verid != 0x01) READ_UINT8 (&br, vol->shape_extension, 4); CHECK_REMAINING (&br, 19); MARKER_UNCHECKED (&br); vol->vop_time_increment_resolution = gst_bit_reader_get_bits_uint16_unchecked (&br, 16); if (vol->vop_time_increment_resolution < 1) { GST_WARNING ("value not in allowed range. value: %d, range %d-%d", vol->vop_time_increment_resolution, 1, G_MAXUINT16); goto failed; } vol->vop_time_increment_bits = g_bit_storage (vol->vop_time_increment_resolution); MARKER_UNCHECKED (&br); vol->fixed_vop_rate = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); if (vol->fixed_vop_rate) READ_UINT16 (&br, vol->fixed_vop_time_increment, vol->vop_time_increment_bits); if (vol->shape != GST_MPEG4_BINARY_ONLY) { if (vol->shape == GST_MPEG4_RECTANGULAR) { CHECK_REMAINING (&br, 29); MARKER_UNCHECKED (&br); vol->width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vol->height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); } READ_UINT8 (&br, vol->interlaced, 1); READ_UINT8 (&br, vol->obmc_disable, 1); if (vol->verid == 0x1) READ_UINT8 (&br, tmp, 1); else READ_UINT8 (&br, tmp, 2); vol->sprite_enable = tmp; if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC || vol->sprite_enable == GST_MPEG4_SPRITE_GMG) { if (vol->sprite_enable == GST_MPEG4_SPRITE_GMG) CHECK_REMAINING (&br, 9); else { CHECK_REMAINING (&br, 65); vol->sprite_width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vol->sprite_height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vol->sprite_left_coordinate = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vol->sprite_top_coordinate = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); } vol->no_of_sprite_warping_points = gst_bit_reader_get_bits_uint8_unchecked (&br, 6); vol->sprite_warping_accuracy = gst_bit_reader_get_bits_uint8_unchecked (&br, 2); vol->sprite_brightness_change = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); if (vol->sprite_enable != GST_MPEG4_SPRITE_GMG) vol->low_latency_sprite_enable = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); } if (vol->verid != 0x1 && vol->shape != GST_MPEG4_RECTANGULAR) READ_UINT8 (&br, vol->sadct_disable, 1); READ_UINT8 (&br, vol->not_8_bit, 1); if (vol->not_8_bit) { READ_UINT8 (&br, vol->quant_precision, 4); CHECK_ALLOWED (vol->quant_precision, 3, 9); READ_UINT8 (&br, vol->bits_per_pixel, 4); CHECK_ALLOWED (vol->bits_per_pixel, 4, 12); } if (vol->shape == GST_MPEG4_GRAYSCALE) { /* We don't actually support it */ READ_UINT8 (&br, vol->no_gray_quant_update, 1); READ_UINT8 (&br, vol->composition_method, 1); READ_UINT8 (&br, vol->linear_composition, 1); } READ_UINT8 (&br, vol->quant_type, 1); if (vol->quant_type) { if (!parse_quant (&br, vol->intra_quant_mat, default_intra_quant_mat, &vol->load_intra_quant_mat)) goto failed; if (!parse_quant (&br, vol->non_intra_quant_mat, default_non_intra_quant_mat, &vol->load_non_intra_quant_mat)) goto failed; if (vol->shape == GST_MPEG4_GRAYSCALE) { /* Something the standard starts to define... */ GST_WARNING ("Grayscale shaped not supported"); goto failed; } } else { memset (&vol->intra_quant_mat, 0, 64); memset (&vol->non_intra_quant_mat, 0, 64); } if (vol->verid != 0x1) READ_UINT8 (&br, vol->quarter_sample, 1); READ_UINT8 (&br, vol->complexity_estimation_disable, 1); if (!vol->complexity_estimation_disable) { guint8 estimation_method; guint8 estimation_disable; /* skip unneeded properties */ READ_UINT8 (&br, estimation_method, 2); if (estimation_method < 2) { READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 6); READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 4); CHECK_MARKER (&br); READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 4); READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 6); CHECK_MARKER (&br); if (estimation_method == 1) { READ_UINT8 (&br, estimation_disable, 1); if (!estimation_disable) SKIP (&br, 2); } } } READ_UINT8 (&br, vol->resync_marker_disable, 1); READ_UINT8 (&br, vol->data_partitioned, 1); if (vol->data_partitioned) READ_UINT8 (&br, vol->reversible_vlc, 1); if (vol->verid != 0x01) { READ_UINT8 (&br, vol->newpred_enable, 1); if (vol->newpred_enable) /* requested_upstream_message_type and newpred_segment_type */ SKIP (&br, 3); READ_UINT8 (&br, vol->reduced_resolution_vop_enable, 1); } READ_UINT8 (&br, vol->scalability, 1); if (vol->scalability) { SKIP (&br, 26); /* Few not needed props */ READ_UINT8 (&br, vol->enhancement_type, 1); } /* More unused infos */ } else if (vol->verid != 0x01) { GST_WARNING ("Binary only shapes not fully supported"); goto failed; } /* ... */ return GST_MPEG4_PARSER_OK; failed: GST_WARNING ("failed parsing \"Video Object Layer\""); return GST_MPEG4_PARSER_ERROR; wrong_start_code: GST_WARNING ("got buffer with wrong start code"); goto failed; }
/** * gst_mpeg4_parse_video_packet_header: * @videopackethdr: The #GstMpeg4VideoPacketHdr structure to fill * @vol: The last parsed #GstMpeg4VideoObjectLayer, will be updated * with the informations found during the parsing * @vop: The last parsed #GstMpeg4VideoObjectPlane, will be updated * with the informations found during the parsing * @sprite_trajectory: A #GstMpeg4SpriteTrajectory to fill or %NULL * with the informations found during the parsing * @data: The data to parse, should be set after the resync marker. * @size: The size of the data to parse * * Parsers @data containing the video packet header * and fills the @videopackethdr structure */ GstMpeg4ParseResult gst_mpeg4_parse_video_packet_header (GstMpeg4VideoPacketHdr * videopackethdr, GstMpeg4VideoObjectLayer * vol, GstMpeg4VideoObjectPlane * vop, GstMpeg4SpriteTrajectory * sprite_trajectory, const guint8 * data, gsize size) { guint8 markersize; GstBitReader br = GST_BIT_READER_INIT (data, size); g_return_val_if_fail (videopackethdr != NULL, GST_MPEG4_PARSER_ERROR); g_return_val_if_fail (vol != NULL, GST_MPEG4_PARSER_ERROR); markersize = compute_resync_marker_size (vop, NULL, NULL); CHECK_REMAINING (&br, markersize); if (gst_bit_reader_get_bits_uint32_unchecked (&br, markersize) != 0x01) goto failed; if (vol->shape != GST_MPEG4_RECTANGULAR) { READ_UINT8 (&br, videopackethdr->header_extension_code, 1); if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC && vop->coding_type == GST_MPEG4_I_VOP) { CHECK_REMAINING (&br, 56); U_READ_UINT16 (&br, vop->width, 13); CHECK_MARKER (&br); U_READ_UINT16 (&br, vop->height, 13); CHECK_MARKER (&br); U_READ_UINT16 (&br, vop->horizontal_mc_spatial_ref, 13); CHECK_MARKER (&br); U_READ_UINT16 (&br, vop->vertical_mc_spatial_ref, 13); CHECK_MARKER (&br); /* Update macroblock infirmations */ vop->mb_height = (vop->height + 15) / 16; vop->mb_width = (vop->width + 15) / 16; vop->mb_num = vop->mb_height * vop->mb_width; } } READ_UINT16 (&br, videopackethdr->macroblock_number, g_bit_storage (vop->mb_num - 1)); if (vol->shape != GST_MPEG4_BINARY_ONLY) READ_UINT16 (&br, videopackethdr->quant_scale, vol->quant_precision); if (vol->shape == GST_MPEG4_RECTANGULAR) READ_UINT8 (&br, videopackethdr->header_extension_code, 1); if (videopackethdr->header_extension_code) { guint timeincr = 0; guint8 bit = 0, coding_type; do { READ_UINT8 (&br, bit, 1); timeincr++; } while (bit); vol->vop_time_increment_bits = timeincr; CHECK_MARKER (&br); READ_UINT16 (&br, vop->time_increment, timeincr); CHECK_MARKER (&br); READ_UINT8 (&br, coding_type, 2); vop->coding_type = coding_type; if (vol->shape != GST_MPEG4_RECTANGULAR) { READ_UINT8 (&br, vop->change_conv_ratio_disable, 1); if (vop->coding_type != GST_MPEG4_I_VOP) READ_UINT8 (&br, vop->shape_coding_type, 1); } if (vol->shape != GST_MPEG4_BINARY_ONLY) { READ_UINT8 (&br, vop->intra_dc_vlc_thr, 3); if (sprite_trajectory && vol->sprite_enable == GST_MPEG4_SPRITE_GMG && vop->coding_type == GST_MPEG4_S_VOP && vol->no_of_sprite_warping_points > 0) { parse_sprite_trajectory (&br, sprite_trajectory, vol->no_of_sprite_warping_points); } if (vol->reduced_resolution_vop_enable && vol->shape == GST_MPEG4_RECTANGULAR && (vop->coding_type == GST_MPEG4_P_VOP || vop->coding_type == GST_MPEG4_I_VOP)) READ_UINT8 (&br, vop->reduced_resolution, 1); if (vop->coding_type != GST_MPEG4_I_VOP) { READ_UINT8 (&br, vop->fcode_forward, 3); CHECK_ALLOWED (vop->fcode_forward, 1, 7); } if (vop->coding_type == GST_MPEG4_B_VOP) { READ_UINT8 (&br, vop->fcode_backward, 3); CHECK_ALLOWED (vop->fcode_backward, 1, 7); } } } if (vol->newpred_enable) { guint16 nbbits = vol->vop_time_increment_bits + 3 < 15 ? vop->time_increment + 3 : 15; READ_UINT16 (&br, vop->id, nbbits); READ_UINT8 (&br, vop->id_for_prediction_indication, 1); if (vop->id_for_prediction_indication) { /* Would be nice if the standard actually told us... */ READ_UINT16 (&br, vop->id, nbbits); CHECK_MARKER (&br); } } videopackethdr->size = gst_bit_reader_get_pos (&br); failed: GST_DEBUG ("Failed to parse video packet header"); return GST_MPEG4_PARSER_NO_PACKET; }
/** * gst_mpeg4_parse_video_object_plane: * @vop: The #GstMpeg4VideoObjectPlane currently being parsed * @sprite_trajectory: A #GstMpeg4SpriteTrajectory to fill or %NULL * @vol: The #GstMpeg4VideoObjectLayer structure to fill * @data: The data to parse * @size: The size of the @data to parse * * Parses @data containing the video object plane packet, and fills the @vol * structure. * * Returns: a #GstMpeg4ParseResult */ GstMpeg4ParseResult gst_mpeg4_parse_video_object_plane (GstMpeg4VideoObjectPlane * vop, GstMpeg4SpriteTrajectory * sprite_trajectory, GstMpeg4VideoObjectLayer * vol, const guint8 * data, gsize size) { guint8 vop_start_code, coding_type, modulo_time_base; GstBitReader br = GST_BIT_READER_INIT (data, size); g_return_val_if_fail (vop != NULL, GST_MPEG4_PARSER_ERROR); if (vol->shape == GST_MPEG4_BINARY_ONLY) { /* TODO: implement binary only shapes */ GST_WARNING ("Binary only shapes not supported"); goto failed; } READ_UINT8 (&br, vop_start_code, 8); if (vop_start_code != GST_MPEG4_VIDEO_OBJ_PLANE) goto wrong_start_code; /* set default values */ vop->modulo_time_base = 0; vop->rounding_type = 0; vop->top_field_first = 1; vop->alternate_vertical_scan_flag = 0; vop->fcode_forward = 1; vop->fcode_backward = 1; /* Compute macroblock informations */ if (vol->interlaced) vop->mb_height = (2 * (vol->height + 31) / 32); else vop->mb_height = (vol->height + 15) / 16; vop->mb_width = (vol->width + 15) / 16; vop->mb_num = vop->mb_height * vop->mb_width; READ_UINT8 (&br, coding_type, 2); vop->coding_type = coding_type; READ_UINT8 (&br, modulo_time_base, 1); while (modulo_time_base) { vop->modulo_time_base++; READ_UINT8 (&br, modulo_time_base, 1); } CHECK_REMAINING (&br, vol->vop_time_increment_bits + 3); MARKER_UNCHECKED (&br); vop->time_increment = gst_bit_reader_get_bits_uint16_unchecked (&br, vol->vop_time_increment_bits); MARKER_UNCHECKED (&br); vop->coded = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); if (!vop->coded) return GST_MPEG4_PARSER_OK; if (vol->newpred_enable) { guint16 nbbits = vop->time_increment + 3 < 15 ? vop->time_increment + 3 : 15; READ_UINT16 (&br, vop->id, nbbits); READ_UINT8 (&br, vop->id_for_prediction_indication, 1); if (vop->id_for_prediction_indication) { /* Would be nice if the standard actually told us... */ READ_UINT16 (&br, vop->id, nbbits); CHECK_MARKER (&br); } } if (vol->shape != GST_MPEG4_BINARY_ONLY && (vop->coding_type == GST_MPEG4_P_VOP || (vop->coding_type == GST_MPEG4_S_VOP && vol->sprite_enable == GST_MPEG4_SPRITE_GMG))) READ_UINT8 (&br, vop->rounding_type, 1); if ((vol->reduced_resolution_vop_enable) && (vol->shape == GST_MPEG4_RECTANGULAR || (vop->coding_type = GST_MPEG4_P_VOP || vop->coding_type == GST_MPEG4_I_VOP))) READ_UINT8 (&br, vop->reduced_resolution, 1); if (vol->shape != GST_MPEG4_RECTANGULAR) { if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC && vop->coding_type == GST_MPEG4_I_VOP) { CHECK_REMAINING (&br, 55); vop->width = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vop->height = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vop->horizontal_mc_spatial_ref = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); vop->vertical_mc_spatial_ref = gst_bit_reader_get_bits_uint16_unchecked (&br, 13); MARKER_UNCHECKED (&br); /* Recompute the Macroblock informations * accordingly to the new values */ if (vol->interlaced) vop->mb_height = (2 * (vol->height + 31) / 32); else vop->mb_height = (vol->height + 15) / 16; vop->mb_width = (vol->width + 15) / 16; vop->mb_num = vop->mb_height * vop->mb_width; } if ((vol->shape != GST_MPEG4_BINARY_ONLY) && vol->scalability && vol->enhancement_type) READ_UINT8 (&br, vop->background_composition, 1); READ_UINT8 (&br, vop->change_conv_ratio_disable, 1); READ_UINT8 (&br, vop->constant_alpha, 1); if (vop->constant_alpha) READ_UINT8 (&br, vop->constant_alpha_value, 1); } if (vol->shape != GST_MPEG4_BINARY_ONLY) { if (!vol->complexity_estimation_disable) { GST_WARNING ("Complexity estimation not supported"); goto failed; } READ_UINT8 (&br, vop->intra_dc_vlc_thr, 3); if (vol->interlaced) { READ_UINT8 (&br, vop->top_field_first, 1); READ_UINT8 (&br, vop->alternate_vertical_scan_flag, 1); } } if ((vol->sprite_enable == GST_MPEG4_SPRITE_STATIC || vol->sprite_enable == GST_MPEG4_SPRITE_GMG) && vop->coding_type == GST_MPEG4_S_VOP) { /* only if @sprite_trajectory is not NULL we parse it */ if (sprite_trajectory && vol->no_of_sprite_warping_points) parse_sprite_trajectory (&br, sprite_trajectory, vol->no_of_sprite_warping_points); if (vol->sprite_brightness_change) { GST_WARNING ("sprite_brightness_change not supported"); goto failed; } if (vol->sprite_enable == GST_MPEG4_SPRITE_STATIC) { GST_WARNING ("sprite enable static not supported"); goto failed; } } if (vol->shape != GST_MPEG4_BINARY_ONLY) { READ_UINT16 (&br, vop->quant, vol->quant_precision); if (vol->shape == GST_MPEG4_GRAYSCALE) { /* TODO implement grayscale support */ GST_WARNING ("Grayscale shapes no supported"); /* TODO implement me */ goto failed; } if (vop->coding_type != GST_MPEG4_I_VOP) { READ_UINT8 (&br, vop->fcode_forward, 3); CHECK_ALLOWED (vop->fcode_forward, 1, 7); } if (vop->coding_type == GST_MPEG4_B_VOP) { READ_UINT8 (&br, vop->fcode_backward, 3); CHECK_ALLOWED (vop->fcode_backward, 1, 7); } } if (!vol->scalability) { if (vol->shape != GST_MPEG4_RECTANGULAR) READ_UINT8 (&br, vop->shape_coding_type, 1); } else { if (vol->enhancement_type) { READ_UINT8 (&br, vop->load_backward_shape, 1); if (vop->load_backward_shape) { GST_WARNING ("Load backward shape not supported"); goto failed; } READ_UINT8 (&br, vop->ref_select_code, 2); } } vop->size = gst_bit_reader_get_pos (&br); /* More things to possibly parse ... */ return GST_MPEG4_PARSER_OK; failed: GST_WARNING ("failed parsing \"Video Object Plane\""); return GST_MPEG4_PARSER_ERROR; wrong_start_code: GST_WARNING ("got buffer with wrong start code"); goto failed; }
/** As pwbox_encoded_parse(), but do not allocate the output object. */ static ssize_t pwbox_encoded_parse_into(pwbox_encoded_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u32 fixedbytes0 IN [PWBOX0_CONST0] */ CHECK_REMAINING(4, truncated); obj->fixedbytes0 = trunnel_ntohl(trunnel_get_uint32(ptr)); remaining -= 4; ptr += 4; if (! (obj->fixedbytes0 == PWBOX0_CONST0)) goto fail; /* Parse u32 fixedbytes1 IN [PWBOX0_CONST1] */ CHECK_REMAINING(4, truncated); obj->fixedbytes1 = trunnel_ntohl(trunnel_get_uint32(ptr)); remaining -= 4; ptr += 4; if (! (obj->fixedbytes1 == PWBOX0_CONST1)) goto fail; /* Parse u8 header_len */ CHECK_REMAINING(1, truncated); obj->header_len = (trunnel_get_uint8(ptr)); remaining -= 1; ptr += 1; /* Parse u8 skey_header[header_len] */ CHECK_REMAINING(obj->header_len, truncated); TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->skey_header, obj->header_len, {}); obj->skey_header.n_ = obj->header_len; memcpy(obj->skey_header.elts_, ptr, obj->header_len); ptr += obj->header_len; remaining -= obj->header_len; /* Parse u8 iv[16] */ CHECK_REMAINING(16, truncated); memcpy(obj->iv, ptr, 16); remaining -= 16; ptr += 16; { size_t remaining_after; CHECK_REMAINING(32, truncated); remaining_after = 32; remaining = remaining - 32; /* Parse u8 data[] */ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->data, remaining, {}); obj->data.n_ = remaining; memcpy(obj->data.elts_, ptr, remaining); ptr += remaining; remaining -= remaining; if (remaining != 0) goto fail; remaining = remaining_after; } /* Parse u8 hmac[32] */ CHECK_REMAINING(32, truncated); memcpy(obj->hmac, ptr, 32); remaining -= 32; ptr += 32; trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; trunnel_alloc_failed: return -1; fail: result = -1; return result; }
/** As ed25519_cert_extension_parse(), but do not allocate the output * object. */ static ssize_t ed25519_cert_extension_parse_into(ed25519_cert_extension_t *obj, const uint8_t *input, const size_t len_in) { const uint8_t *ptr = input; size_t remaining = len_in; ssize_t result = 0; (void)result; /* Parse u16 ext_length */ CHECK_REMAINING(2, truncated); obj->ext_length = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; /* Parse u8 ext_type */ CHECK_REMAINING(1, truncated); obj->ext_type = (trunnel_get_uint8(ptr)); remaining -= 1; ptr += 1; /* Parse u8 ext_flags */ CHECK_REMAINING(1, truncated); obj->ext_flags = (trunnel_get_uint8(ptr)); remaining -= 1; ptr += 1; { size_t remaining_after; CHECK_REMAINING(obj->ext_length, truncated); remaining_after = remaining - obj->ext_length; remaining = obj->ext_length; /* Parse union un[ext_type] */ switch (obj->ext_type) { case CERTEXT_SIGNED_WITH_KEY: /* Parse u8 un_signing_key[32] */ CHECK_REMAINING(32, fail); memcpy(obj->un_signing_key, ptr, 32); remaining -= 32; ptr += 32; break; default: /* Parse u8 un_unparsed[] */ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->un_unparsed, remaining, {}); obj->un_unparsed.n_ = remaining; memcpy(obj->un_unparsed.elts_, ptr, remaining); ptr += remaining; remaining -= remaining; break; } if (remaining != 0) goto fail; remaining = remaining_after; } trunnel_assert(ptr + remaining == input + len_in); return len_in - remaining; truncated: return -2; trunnel_alloc_failed: return -1; fail: result = -1; return result; }