EXPORT_C #endif gboolean gst_bit_reader_skip (GstBitReader * reader, guint nbits) { g_return_val_if_fail (reader != NULL, FALSE); if (gst_bit_reader_get_remaining (reader) < nbits) return FALSE; reader->bit += nbits; reader->byte += reader->bit / 8; reader->bit = reader->bit % 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; }
static GstFlowReturn gst_vdp_mpeg_dec_parse_data (GstBaseVideoDecoder * base_video_decoder, GstBuffer * buf, gboolean at_eos, GstVideoFrame * frame) { GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (base_video_decoder); GstVdpMpegFrame *mpeg_frame; GstFlowReturn ret = GST_FLOW_OK; GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); guint8 start_code; if (gst_bit_reader_get_remaining (&b_reader) < 8 * 3 + 8) return GST_FLOW_ERROR; /* skip sync_code */ gst_bit_reader_skip_unchecked (&b_reader, 8 * 3); /* start_code */ start_code = gst_bit_reader_get_bits_uint8_unchecked (&b_reader, 8); mpeg_frame = GST_VDP_MPEG_FRAME_CAST (frame); if (start_code >= MPEG_PACKET_SLICE_MIN && start_code <= MPEG_PACKET_SLICE_MAX) { GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); gst_vdp_mpeg_frame_add_slice (mpeg_frame, buf); goto done; } switch (start_code) { case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); if (mpeg_dec->prev_packet != -1) ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, (GstVideoFrame **) & mpeg_frame); mpeg_frame->seq = buf; break; case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); if (mpeg_dec->prev_packet != MPEG_PACKET_SEQUENCE && mpeg_dec->prev_packet != MPEG_PACKET_GOP) ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, (GstVideoFrame **) & mpeg_frame); mpeg_frame->pic = buf; break; case MPEG_PACKET_GOP: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); if (mpeg_dec->prev_packet != MPEG_PACKET_SEQUENCE) ret = gst_base_video_decoder_have_frame (base_video_decoder, FALSE, (GstVideoFrame **) & mpeg_frame); mpeg_frame->gop = buf; break; case MPEG_PACKET_EXTENSION: { guint8 ext_code; /* ext_code */ if (!gst_bit_reader_get_bits_uint8 (&b_reader, &ext_code, 4)) { ret = GST_FLOW_ERROR; gst_buffer_unref (buf); goto done; } GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION: %d", ext_code); switch (ext_code) { case MPEG_PACKET_EXT_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_SEQUENCE"); mpeg_frame->seq_ext = buf; /* so that we don't finish the frame if we get a MPEG_PACKET_PICTURE * or MPEG_PACKET_GOP after this */ start_code = MPEG_PACKET_SEQUENCE; break; case MPEG_PACKET_EXT_SEQUENCE_DISPLAY: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_SEQUENCE_DISPLAY"); /* so that we don't finish the frame if we get a MPEG_PACKET_PICTURE * or MPEG_PACKET_GOP after this */ start_code = MPEG_PACKET_SEQUENCE; break; case MPEG_PACKET_EXT_PICTURE_CODING: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_PICTURE_CODING"); mpeg_frame->pic_ext = buf; break; case MPEG_PACKET_EXT_QUANT_MATRIX: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); mpeg_frame->qm_ext = buf; break; default: gst_buffer_unref (buf); } break; } default: gst_buffer_unref (buf); } if (at_eos && mpeg_frame->slices) ret = gst_base_video_decoder_have_frame (base_video_decoder, TRUE, NULL); done: mpeg_dec->prev_packet = start_code; return ret; }
/** * 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; }