vdpauh264dec: now works for simple streams

This commit is contained in:
Carl-Anton Ingmarsson 2010-06-17 15:20:51 +02:00
parent 80749da166
commit 322d1ff946
3 changed files with 103 additions and 55 deletions

View file

@ -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);
}
}

View file

@ -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 < ((chroma_format_idc != 3) ? 8 : 12)) {
guint8 scaling_list_present_flag;
if (i <= 5) {
scaling_list = scaling_lists_4x4[i];
size = 16;
} else {
scaling_list = scaling_lists_8x8[i];
size = 64;
}
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;
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);
if (i <= 5) {
scaling_list = scaling_lists_4x4[i];
size = 16;
} else {
scaling_list = scaling_lists_8x8[i - 6];
size = 64;
}
scaling_list[j] = (next_scale == 0) ? last_scale : next_scale;
last_scale = scaling_list[j];
}
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];
}
} 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 {

View file

@ -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);