static gboolean gst_vdp_mpeg_dec_handle_picture_coding (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer, GstVideoFrame * frame) { MPEGPictureExt pic_ext; VdpPictureInfoMPEG1Or2 *info; gint fields; info = &mpeg_dec->vdp_info; if (!mpeg_util_parse_picture_coding_extension (&pic_ext, buffer)) return FALSE; memcpy (&mpeg_dec->vdp_info.f_code, &pic_ext.f_code, 4); info->intra_dc_precision = pic_ext.intra_dc_precision; info->picture_structure = pic_ext.picture_structure; info->top_field_first = pic_ext.top_field_first; info->frame_pred_frame_dct = pic_ext.frame_pred_frame_dct; info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; info->q_scale_type = pic_ext.q_scale_type; info->intra_vlc_format = pic_ext.intra_vlc_format; info->alternate_scan = pic_ext.alternate_scan; fields = 2; if (pic_ext.picture_structure == 3) { if (mpeg_dec->stream_info.interlaced) { if (pic_ext.progressive_frame == 0) fields = 2; if (pic_ext.progressive_frame == 0 && pic_ext.repeat_first_field == 0) fields = 2; if (pic_ext.progressive_frame == 1 && pic_ext.repeat_first_field == 1) fields = 3; } else { if (pic_ext.repeat_first_field == 0) fields = 2; if (pic_ext.repeat_first_field == 1 && pic_ext.top_field_first == 0) fields = 4; if (pic_ext.repeat_first_field == 1 && pic_ext.top_field_first == 1) fields = 6; } } else fields = 1; frame->n_fields = fields; if (pic_ext.top_field_first) GST_VIDEO_FRAME_FLAG_SET (frame, GST_VIDEO_FRAME_FLAG_TFF); 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; }