From 322d1ff9460b7eeedc78d2c07d2195b785be2f3f Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 17 Jun 2010 15:20:51 +0200 Subject: vdpauh264dec: now works for simple streams --- sys/vdpau/h264/gsth264dpb.c | 45 ++++++++++++++++------- sys/vdpau/h264/gsth264parser.c | 83 ++++++++++++++++++++++++------------------ sys/vdpau/h264/gstvdph264dec.c | 32 ++++++++++++---- 3 files changed, 104 insertions(+), 56 deletions(-) (limited to 'sys/vdpau') diff --git a/sys/vdpau/h264/gsth264dpb.c b/sys/vdpau/h264/gsth264dpb.c index 85f3c3056..a2d695686 100644 --- a/sys/vdpau/h264/gsth264dpb.c +++ b/sys/vdpau/h264/gsth264dpb.c @@ -48,8 +48,8 @@ gst_h264_dpb_fill_reference_frames (GstH264DPB * dpb, GstVdpH264Frame *frame = frames[i]; reference_frames[i].surface = - GST_VDP_VIDEO_BUFFER (GST_VIDEO_FRAME_CAST (frame)->src_buffer)-> - surface; + GST_VDP_VIDEO_BUFFER (GST_VIDEO_FRAME_CAST (frame)-> + src_buffer)->surface; reference_frames[i].is_long_term = frame->is_long_term; reference_frames[i].top_is_reference = frame->is_reference; @@ -58,6 +58,26 @@ gst_h264_dpb_fill_reference_frames (GstH264DPB * dpb, reference_frames[i].field_order_cnt[1] = frame->poc; reference_frames[i].frame_idx = frame->frame_num; } + + for (i = dpb->n_frames; i < 16; i++) { + reference_frames[i].surface = VDP_INVALID_HANDLE; + reference_frames[i].top_is_reference = VDP_FALSE; + reference_frames[i].bottom_is_reference = VDP_FALSE; + } +} + +static void +gst_h264_dpb_remove (GstH264DPB * dpb, guint idx) +{ + GstVdpH264Frame **frames; + guint i; + + frames = dpb->frames; + gst_video_frame_unref (GST_VIDEO_FRAME_CAST (frames[idx])); + dpb->n_frames--; + + for (i = idx; i < dpb->n_frames; i++) + frames[i] = frames[i + 1]; } static void @@ -67,18 +87,10 @@ gst_h264_dpb_output (GstH264DPB * dpb, guint idx) gst_video_frame_ref (GST_VIDEO_FRAME_CAST (frame)); dpb->output (dpb, frame); + frame->output_needed = FALSE; - if (!frame->is_reference) { - GstVdpH264Frame **frames; - guint i; - - gst_video_frame_unref (GST_VIDEO_FRAME_CAST (frame)); - dpb->n_frames--; - - frames = dpb->frames; - for (i = idx; i < dpb->n_frames; i++) - frames[i] = frames[i + 1]; - } + if (!frame->is_reference) + gst_h264_dpb_remove (dpb, idx); } static gboolean @@ -153,6 +165,8 @@ gst_h264_dpb_flush (GstH264DPB * dpb, gboolean output) GstVideoFrame **frames; guint i; + GST_DEBUG ("flush"); + if (output) while (gst_h264_dpb_bump (dpb, G_MAXUINT)); @@ -171,6 +185,9 @@ gst_h264_dpb_mark_sliding (GstH264DPB * dpb) guint i; gint mark_idx; + if (dpb->n_frames != dpb->max_frames) + return; + frames = dpb->frames; for (i = 0; i < dpb->n_frames; i++) { if (frames[i]->is_reference && !frames[i]->is_long_term) { @@ -187,6 +204,8 @@ gst_h264_dpb_mark_sliding (GstH264DPB * dpb) } frames[mark_idx]->is_reference = FALSE; + if (!frames[mark_idx]->output_needed) + gst_h264_dpb_remove (dpb, mark_idx); } } diff --git a/sys/vdpau/h264/gsth264parser.c b/sys/vdpau/h264/gsth264parser.c index 1614c2d59..6d442d8d3 100644 --- a/sys/vdpau/h264/gsth264parser.c +++ b/sys/vdpau/h264/gsth264parser.c @@ -255,45 +255,46 @@ gst_h264_parser_parse_scaling_list (GstNalReader * reader, const guint8 fallback_8x8_inter[64], const guint8 fallback_8x8_intra[64], guint32 chroma_format_idc) { - gint i; - guint8 seq_scaling_list_present_flag[12] = { 0, }; + guint i; GST_WARNING ("parsing scaling lists"); - for (i = 0; i < ((chroma_format_idc) != 3) ? 8 : 12; i++) { - READ_UINT8 (reader, seq_scaling_list_present_flag[i], 1); - } - for (i = 0; i < 12; i++) { gboolean use_default = FALSE; - if (seq_scaling_list_present_flag[i]) { - guint8 *scaling_list; - guint size; - guint j; - guint8 last_scale, next_scale; - - if (i <= 5) { - scaling_list = scaling_lists_4x4[i]; - size = 16; - } else { - scaling_list = scaling_lists_8x8[i]; - size = 64; - } - - last_scale = 8; - next_scale = 8; - for (j = 0; j < size; j++) { - if (next_scale != 0) { - gint32 delta_scale; + if (i < ((chroma_format_idc != 3) ? 8 : 12)) { + guint8 scaling_list_present_flag; + + READ_UINT8 (reader, scaling_list_present_flag, 1); + if (scaling_list_present_flag) { + guint8 *scaling_list; + guint size; + guint j; + guint8 last_scale, next_scale; + + if (i <= 5) { + scaling_list = scaling_lists_4x4[i]; + size = 16; + } else { + scaling_list = scaling_lists_8x8[i - 6]; + size = 64; + } - READ_SE (reader, delta_scale); - next_scale = (last_scale + delta_scale + 256) % 256; - use_default = (j == 0 && next_scale == 0); + last_scale = 8; + next_scale = 8; + for (j = 0; j < size; j++) { + if (next_scale != 0) { + gint32 delta_scale; + + READ_SE (reader, delta_scale); + next_scale = (last_scale + delta_scale + 256) % 256; + use_default = (j == 0 && next_scale == 0); + } + scaling_list[j] = (next_scale == 0) ? last_scale : next_scale; + last_scale = scaling_list[j]; } - scaling_list[j] = (next_scale == 0) ? last_scale : next_scale; - last_scale = scaling_list[j]; - } + } else + use_default = TRUE; } else use_default = TRUE; @@ -396,8 +397,8 @@ gst_h264_parser_parse_sequence (GstH264Parser * parser, guint8 * data, if (seq->profile_idc == 100 || seq->profile_idc == 110 || seq->profile_idc == 122 || seq->profile_idc == 244 || - seq->profile_idc == 244 || seq->profile_idc == 44 || - seq->profile_idc == 83 || seq->profile_idc == 86) { + seq->profile_idc == 44 || seq->profile_idc == 83 || + seq->profile_idc == 86) { READ_UE_ALLOWED (&reader, seq->chroma_format_idc, 0, 3); if (seq->chroma_format_idc == 3) READ_UINT8 (&reader, seq->separate_colour_plane_flag, 1); @@ -497,8 +498,18 @@ gst_h264_parser_more_data (GstNalReader * reader) if (!gst_nal_reader_peek_bits_uint8 (reader, &rbsp_stop_one_bit, 1)) return FALSE; - if (rbsp_stop_one_bit == 1) - return FALSE; + if (rbsp_stop_one_bit == 1) { + guint8 zero_bits; + + if (remaining == 1) + return FALSE; + + if (!gst_nal_reader_peek_bits_uint8 (reader, &zero_bits, remaining)) + return FALSE; + + if ((zero_bits - (1 << (remaining - 1))) == 0) + return FALSE; + } } return TRUE; @@ -754,7 +765,7 @@ gst_h264_slice_parse_dec_ref_pic_marking (GstH264Slice * slice, m = &slice->dec_ref_pic_marking; - if (slice->nal_unit.IdrPicFlag == 0) { + if (slice->nal_unit.IdrPicFlag) { READ_UINT8 (reader, m->no_output_of_prior_pics_flag, 1); READ_UINT8 (reader, m->long_term_reference_flag, 1); } else { diff --git a/sys/vdpau/h264/gstvdph264dec.c b/sys/vdpau/h264/gstvdph264dec.c index 222971444..93071fb21 100644 --- a/sys/vdpau/h264/gstvdph264dec.c +++ b/sys/vdpau/h264/gstvdph264dec.c @@ -183,9 +183,13 @@ gst_vdp_h264_dec_shape_output (GstBaseVideoDecoder * base_video_decoder, static void gst_vdp_h264_dec_output (GstH264DPB * dpb, GstVdpH264Frame * h264_frame) { + GstBaseVideoDecoder *base_video_decoder; + GST_DEBUG ("poc: %d", h264_frame->poc); - gst_video_frame_unref (GST_VIDEO_FRAME_CAST (h264_frame)); + base_video_decoder = g_object_get_data (G_OBJECT (dpb), "decoder"); + gst_base_video_decoder_finish_frame (base_video_decoder, + GST_VIDEO_FRAME_CAST (h264_frame)); } static guint @@ -230,7 +234,9 @@ gst_vdp_h264_dec_init_frame_info (GstVdpH264Dec * h264_dec, h264_frame->poc = gst_vdp_h264_dec_calculate_poc (h264_dec, slice); + h264_frame->output_needed = TRUE; h264_frame->is_long_term = FALSE; + h264_frame->frame_num = slice->frame_num; /* is reference */ if (slice->nal_unit.ref_idc == 0) @@ -266,14 +272,16 @@ gst_vdp_h264_dec_idr (GstVdpH264Dec * h264_dec, GstVdpH264Frame * h264_frame) seq = slice->picture->sequence; if (seq != h264_dec->sequence) { + GstFlowReturn ret; GstVdpDevice *device; gst_base_video_decoder_update_src_caps (GST_BASE_VIDEO_DECODER (h264_dec)); - device = gst_vdp_video_src_pad_get_device - (GST_VDP_VIDEO_SRC_PAD (GST_BASE_VIDEO_DECODER_SRC_PAD (h264_dec))); + ret = gst_vdp_video_src_pad_get_device + (GST_VDP_VIDEO_SRC_PAD (GST_BASE_VIDEO_DECODER_SRC_PAD (h264_dec)), + &device, NULL); - if (device) { + if (ret == GST_FLOW_OK) { GstVideoState *state; VdpDecoderProfile profile; VdpStatus status; @@ -344,6 +352,7 @@ gst_vdp_h264_dec_fill_info (GstVdpH264Dec * h264_dec, info.field_order_cnt[1] = h264_frame->poc; info.is_reference = h264_frame->is_reference; + info.frame_num = slice->frame_num; info.field_pic_flag = slice->field_pic_flag; info.bottom_field_flag = slice->bottom_field_flag; @@ -374,8 +383,13 @@ gst_vdp_h264_dec_fill_info (GstVdpH264Dec * h264_dec, pic->deblocking_filter_control_present_flag; info.redundant_pic_cnt_present_flag = pic->redundant_pic_cnt_present_flag; - memcpy (&info.scaling_lists_4x4, &pic->scaling_lists_4x4, 96); - memcpy (&info.scaling_lists_8x8, &pic->scaling_lists_8x8, 128); + if (pic->scaling_matrix_present_flag) { + memcpy (&info.scaling_lists_4x4, &pic->scaling_lists_4x4, 96); + memcpy (&info.scaling_lists_8x8, &pic->scaling_lists_8x8, 128); + } else { + memcpy (&info.scaling_lists_4x4, &seq->scaling_lists_4x4, 96); + memcpy (&info.scaling_lists_8x8, &seq->scaling_lists_8x8, 128); + } gst_h264_dpb_fill_reference_frames (h264_dec->dpb, info.referenceFrames); @@ -652,6 +666,7 @@ gst_vdp_h264_dec_parse_data (GstBaseVideoDecoder * base_video_decoder, 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; @@ -811,6 +826,7 @@ gst_vdp_h264_dec_start (GstBaseVideoDecoder * base_video_decoder) h264_dec->parser = g_object_new (GST_TYPE_H264_PARSER, NULL); h264_dec->dpb = g_object_new (GST_TYPE_H264_DPB, NULL); + g_object_set_data (G_OBJECT (h264_dec->dpb), "decoder", h264_dec); h264_dec->dpb->output = gst_vdp_h264_dec_output; return TRUE; @@ -822,6 +838,7 @@ gst_vdp_h264_dec_stop (GstBaseVideoDecoder * base_video_decoder) GstVdpH264Dec *h264_dec = GST_VDP_H264_DEC (base_video_decoder); GstVdpVideoSrcPad *vdp_pad; + GstFlowReturn ret; GstVdpDevice *device; g_object_unref (h264_dec->parser); @@ -831,7 +848,8 @@ gst_vdp_h264_dec_stop (GstBaseVideoDecoder * base_video_decoder) GST_VDP_VIDEO_SRC_PAD (GST_BASE_VIDEO_DECODER_SRC_PAD (base_video_decoder)); - if ((device = gst_vdp_video_src_pad_get_device (vdp_pad))) { + ret = gst_vdp_video_src_pad_get_device (vdp_pad, &device, NULL); + if (ret == GST_FLOW_OK) { if (h264_dec->decoder != VDP_INVALID_HANDLE) device->vdp_decoder_destroy (h264_dec->decoder); -- cgit v1.2.3