/** * gst_mpeg4_next_resync: * @packet: The #GstMpeg4Packet to fill * @vop: The previously parsed #GstMpeg4VideoObjectPlane * @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 resync packet * found. * * Returns: a #GstMpeg4ParseResult */ static GstMpeg4ParseResult gst_mpeg4_next_resync (GstMpeg4Packet * packet, const GstMpeg4VideoObjectPlane * vop, const guint8 * data, gsize size, gboolean first_resync_marker) { guint markersize = 0, off1, off2; guint32 mask = 0xff, pattern = 0xff; GstByteReader br; gst_byte_reader_init (&br, data, size); g_return_val_if_fail (packet != NULL, GST_MPEG4_PARSER_ERROR); g_return_val_if_fail (vop != NULL, GST_MPEG4_PARSER_ERROR); markersize = compute_resync_marker_size (vop, &pattern, &mask); if (first_resync_marker) { off1 = 0; } else { off1 = gst_byte_reader_masked_scan_uint32 (&br, mask, pattern, 0, size); } if (off1 == -1) return GST_MPEG4_PARSER_NO_PACKET; GST_DEBUG ("Resync code found at %i", off1); packet->offset = off1; packet->type = GST_MPEG4_RESYNC; packet->marker_size = markersize; off2 = gst_byte_reader_masked_scan_uint32 (&br, mask, pattern, off1 + 2, size - off1 - 2); if (off2 == -1) return GST_MPEG4_PARSER_NO_PACKET_END; packet->size = off2 - off1; return GST_MPEG4_PARSER_OK; }
/** * mpeg4_next_resync: * @packet: The #Mpeg4Packet to fill * @vop: The previously parsed #Mpeg4VideoObjectPlane * @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 resync packet * found. * * Returns: a #Mpeg4ParseResult */ static Mpeg4ParseResult mpeg4_next_resync (Mpeg4Packet * packet, const Mpeg4VideoObjectPlane * vop, const uint8_t * data, size_t size, bool first_resync_marker) { uint32_t markersize = 0, off1, off2; uint32_t mask = 0xff, pattern = 0xff; ByteReader br; byte_reader_init (&br, data, size); g_return_val_if_fail (packet != NULL, MPEG4_PARSER_ERROR); g_return_val_if_fail (vop != NULL, MPEG4_PARSER_ERROR); markersize = compute_resync_marker_size (vop, &pattern, &mask); if (first_resync_marker) { off1 = 0; } else { off1 = byte_reader_masked_scan_uint32 (&br, mask, pattern, 0, size); } if (off1 == -1) return MPEG4_PARSER_NO_PACKET; DEBUG ("Resync code found at %i", off1); packet->offset = off1; packet->type = MPEG4_RESYNC; packet->marker_size = markersize; off2 = byte_reader_masked_scan_uint32 (&br, mask, pattern, off1 + 2, size - off1 - 2); if (off2 == -1) return MPEG4_PARSER_NO_PACKET_END; packet->size = off2 - off1; return MPEG4_PARSER_OK; }
/** * 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; }