static gboolean gst_vdp_h264_dec_set_sink_caps (GstBaseVideoDecoder * base_video_decoder, GstCaps * caps) { GstVdpH264Dec *h264_dec; GstStructure *structure; const GValue *value; h264_dec = GST_VDP_H264_DEC (base_video_decoder); structure = gst_caps_get_structure (caps, 0); /* packetized video has a codec_data */ if ((value = gst_structure_get_value (structure, "codec_data"))) { GstBuffer *buf; GstBitReader reader; guint8 version; guint8 n_sps, n_pps; gint i; GST_DEBUG_OBJECT (h264_dec, "have packetized h264"); h264_dec->packetized = TRUE; buf = gst_value_get_buffer (value); GST_MEMDUMP ("avcC:", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); /* parse the avcC data */ if (GST_BUFFER_SIZE (buf) < 7) { GST_ERROR_OBJECT (h264_dec, "avcC size %u < 7", GST_BUFFER_SIZE (buf)); return FALSE; } gst_bit_reader_init_from_buffer (&reader, buf); READ_UINT8 (&reader, version, 8); if (version != 1) return FALSE; SKIP (&reader, 30); READ_UINT8 (&reader, h264_dec->nal_length_size, 2); h264_dec->nal_length_size += 1; GST_DEBUG_OBJECT (h264_dec, "nal length %u", h264_dec->nal_length_size); SKIP (&reader, 3); READ_UINT8 (&reader, n_sps, 5); for (i = 0; i < n_sps; i++) { guint16 sps_length; guint8 *data; READ_UINT16 (&reader, sps_length, 16); sps_length -= 1; SKIP (&reader, 8); data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8; if (!gst_h264_parser_parse_sequence (h264_dec->parser, data, sps_length)) return FALSE; SKIP (&reader, sps_length * 8); } READ_UINT8 (&reader, n_pps, 8); for (i = 0; i < n_pps; i++) { guint16 pps_length; guint8 *data; READ_UINT16 (&reader, pps_length, 16); pps_length -= 1; SKIP (&reader, 8); data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8; if (!gst_h264_parser_parse_picture (h264_dec->parser, data, pps_length)) return FALSE; SKIP (&reader, pps_length * 8); } } return TRUE; }
static GstFlowReturn gst_vdp_h264_dec_parse_data (GstBaseVideoDecoder * base_video_decoder, GstBuffer * buf, gboolean at_eos, GstVideoFrame * frame) { GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder); GstBitReader reader; GstNalUnit nal_unit; guint8 forbidden_zero_bit; guint8 *data; guint size; gint i; GstFlowReturn ret = GST_FLOW_OK; GST_MEMDUMP ("data", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); gst_bit_reader_init_from_buffer (&reader, buf); if (gst_bit_reader_get_remaining (&reader) < h264_dec->nal_length_size * 8 + 7) goto invalid_packet; /* skip nal_length or sync code */ gst_bit_reader_skip_unchecked (&reader, h264_dec->nal_length_size * 8); forbidden_zero_bit = gst_bit_reader_get_bits_uint8_unchecked (&reader, 1); if (forbidden_zero_bit != 0) { GST_WARNING ("forbidden_zero_bit != 0"); return GST_FLOW_ERROR; } nal_unit.ref_idc = gst_bit_reader_get_bits_uint16_unchecked (&reader, 2); GST_DEBUG ("nal_ref_idc: %u", nal_unit.ref_idc); /* read nal_unit_type */ nal_unit.type = gst_bit_reader_get_bits_uint16_unchecked (&reader, 5); GST_DEBUG ("nal_unit_type: %u", nal_unit.type); if (nal_unit.type == 14 || nal_unit.type == 20) { if (!gst_bit_reader_skip (&reader, 24)) goto invalid_packet; } nal_unit.IdrPicFlag = (nal_unit.type == 5 ? 1 : 0); data = GST_BUFFER_DATA (buf) + gst_bit_reader_get_pos (&reader) / 8; size = gst_bit_reader_get_remaining (&reader) / 8; i = size - 1; while ((gint) size > 0 && data[i] == 0x00) { size--; i--; } if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_H264_FRAME_GOT_PRIMARY)) { if (nal_unit.type == GST_NAL_SPS || nal_unit.type == GST_NAL_PPS || nal_unit.type == GST_NAL_SEI || nal_unit.type == GST_NAL_AU_DELIMITER || (nal_unit.type >= 14 && nal_unit.type <= 18)) ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, &frame); } if (nal_unit.type >= GST_NAL_SLICE && nal_unit.type <= GST_NAL_SLICE_IDR) { GstH264Slice slice; if (!gst_h264_parser_parse_slice_header (h264_dec->parser, &slice, data, size, nal_unit)) goto invalid_packet; if (slice.redundant_pic_cnt == 0) { if (GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_H264_FRAME_GOT_PRIMARY)) { GstH264Slice *p_slice; guint8 pic_order_cnt_type, p_pic_order_cnt_type; gboolean finish_frame = FALSE; p_slice = &(GST_H264_FRAME_CAST (frame)->slice_hdr); pic_order_cnt_type = slice.picture->sequence->pic_order_cnt_type; p_pic_order_cnt_type = p_slice->picture->sequence->pic_order_cnt_type; if (slice.frame_num != p_slice->frame_num) finish_frame = TRUE; else if (slice.picture != p_slice->picture) finish_frame = TRUE; else if (slice.bottom_field_flag != p_slice->bottom_field_flag) finish_frame = TRUE; else if (nal_unit.ref_idc != p_slice->nal_unit.ref_idc && (nal_unit.ref_idc == 0 || p_slice->nal_unit.ref_idc == 0)) finish_frame = TRUE; else if ((pic_order_cnt_type == 0 && p_pic_order_cnt_type == 0) && (slice.pic_order_cnt_lsb != p_slice->pic_order_cnt_lsb || slice.delta_pic_order_cnt_bottom != p_slice->delta_pic_order_cnt_bottom)) finish_frame = TRUE; else if ((p_pic_order_cnt_type == 1 && p_pic_order_cnt_type == 1) && (slice.delta_pic_order_cnt[0] != p_slice->delta_pic_order_cnt[0] || slice.delta_pic_order_cnt[1] != p_slice->delta_pic_order_cnt[1])) finish_frame = TRUE; if (finish_frame) ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, &frame); } if (!GST_VIDEO_FRAME_FLAG_IS_SET (frame, GST_H264_FRAME_GOT_PRIMARY)) { if (GST_H264_IS_I_SLICE (slice.type) || GST_H264_IS_SI_SLICE (slice.type)) GST_VIDEO_FRAME_FLAG_SET (frame, GST_VIDEO_FRAME_FLAG_KEYFRAME); GST_H264_FRAME_CAST (frame)->slice_hdr = slice; GST_VIDEO_FRAME_FLAG_SET (frame, GST_H264_FRAME_GOT_PRIMARY); } } gst_h264_frame_add_slice ((GstH264Frame *) frame, buf); } if (nal_unit.type == GST_NAL_SPS) { if (!gst_h264_parser_parse_sequence (h264_dec->parser, data, size)) goto invalid_packet; } if (nal_unit.type == GST_NAL_PPS) { if (!gst_h264_parser_parse_picture (h264_dec->parser, data, size)) goto invalid_packet; } gst_buffer_unref (buf); return ret; invalid_packet: GST_WARNING ("Invalid packet size!"); gst_buffer_unref (buf); return GST_FLOW_OK; }
/** * gst_mpeg4_parse_video_plane_with_short_header: * @shorthdr: The #GstMpeg4VideoPlaneShortHdr to parse * @data: The data to parse * @size: The size of the @data to parse */ GstMpeg4ParseResult gst_mpeg4_parse_video_plane_short_header (GstMpeg4VideoPlaneShortHdr * shorthdr, const guint8 * data, gsize size) { guint8 zero_bits; GstBitReader br = GST_BIT_READER_INIT (data, size); g_return_val_if_fail (shorthdr != NULL, GST_MPEG4_PARSER_ERROR); if (gst_bit_reader_get_remaining (&br) < 48) goto failed; if (gst_bit_reader_get_bits_uint32_unchecked (&br, 22) != 0x20) goto failed; shorthdr->temporal_reference = gst_bit_reader_get_bits_uint8_unchecked (&br, 8); CHECK_MARKER (&br); zero_bits = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); if (zero_bits != 0x00) goto failed; shorthdr->split_screen_indicator = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); shorthdr->document_camera_indicator = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); shorthdr->full_picture_freeze_release = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); shorthdr->source_format = gst_bit_reader_get_bits_uint8_unchecked (&br, 3); /* Set parameters/Table 6-25 */ switch (shorthdr->source_format) { case 0x01: shorthdr->vop_width = 128; shorthdr->vop_height = 96; shorthdr->num_macroblocks_in_gob = 8; shorthdr->num_gobs_in_vop = 6; break; case 0x02: shorthdr->vop_width = 176; shorthdr->vop_height = 144; shorthdr->num_macroblocks_in_gob = 11; shorthdr->num_gobs_in_vop = 9; break; case 0x03: shorthdr->vop_width = 352; shorthdr->vop_height = 288; shorthdr->num_macroblocks_in_gob = 22; shorthdr->num_gobs_in_vop = 18; break; case 0x04: shorthdr->vop_width = 704; shorthdr->vop_height = 576; shorthdr->num_macroblocks_in_gob = 88; shorthdr->num_gobs_in_vop = 18; break; case 0x05: shorthdr->vop_width = 1408; shorthdr->vop_height = 1152; shorthdr->num_macroblocks_in_gob = 352; shorthdr->num_gobs_in_vop = 18; break; default: shorthdr->vop_width = 0; shorthdr->vop_height = 0; shorthdr->num_macroblocks_in_gob = 0; shorthdr->num_gobs_in_vop = 0; } shorthdr->picture_coding_type = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); zero_bits = gst_bit_reader_get_bits_uint8_unchecked (&br, 4); if (zero_bits != 0x00) goto failed; shorthdr->vop_quant = gst_bit_reader_get_bits_uint8_unchecked (&br, 5); zero_bits = gst_bit_reader_get_bits_uint8_unchecked (&br, 1); if (zero_bits != 0x00) goto failed; do { READ_UINT8 (&br, shorthdr->pei, 1); if (shorthdr->pei == 1) READ_UINT8 (&br, shorthdr->psupp, 8); } while (shorthdr->pei == 1); shorthdr->size = gst_bit_reader_get_pos (&br); return GST_MPEG4_PARSER_OK; failed: GST_WARNING ("Could not parse the Plane short header"); return GST_MPEG4_PARSER_ERROR; }
/** * 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; }