vdpauh264dec: improve further

This commit is contained in:
Carl-Anton Ingmarsson 2010-06-22 14:17:28 +02:00
parent 322d1ff946
commit 3ea3a084e4
6 changed files with 301 additions and 93 deletions

View file

@ -24,7 +24,8 @@
enum enum
{ {
PROP_0, PROP_0,
PROP_NUM_REF_FRAMES PROP_NUM_REF_FRAMES,
PROP_MAX_LONGTERM_IDX
}; };
GST_DEBUG_CATEGORY_STATIC (h264dpb_debug); GST_DEBUG_CATEGORY_STATIC (h264dpb_debug);
@ -48,15 +49,15 @@ gst_h264_dpb_fill_reference_frames (GstH264DPB * dpb,
GstVdpH264Frame *frame = frames[i]; GstVdpH264Frame *frame = frames[i];
reference_frames[i].surface = reference_frames[i].surface =
GST_VDP_VIDEO_BUFFER (GST_VIDEO_FRAME_CAST (frame)-> GST_VDP_VIDEO_BUFFER (GST_VIDEO_FRAME_CAST (frame)->src_buffer)->
src_buffer)->surface; surface;
reference_frames[i].is_long_term = frame->is_long_term; reference_frames[i].is_long_term = frame->is_long_term;
reference_frames[i].top_is_reference = frame->is_reference; reference_frames[i].top_is_reference = frame->is_reference;
reference_frames[i].bottom_is_reference = frame->is_reference; reference_frames[i].bottom_is_reference = frame->is_reference;
reference_frames[i].field_order_cnt[0] = frame->poc; reference_frames[i].field_order_cnt[0] = frame->poc;
reference_frames[i].field_order_cnt[1] = frame->poc; reference_frames[i].field_order_cnt[1] = frame->poc;
reference_frames[i].frame_idx = frame->frame_num; reference_frames[i].frame_idx = frame->frame_idx;
} }
for (i = dpb->n_frames; i < 16; i++) { for (i = dpb->n_frames; i < 16; i++) {
@ -134,8 +135,11 @@ gst_h264_dpb_add (GstH264DPB * dpb, GstVdpH264Frame * h264_frame)
frames = dpb->frames; frames = dpb->frames;
if (h264_frame->is_reference) { if (h264_frame->is_reference && h264_frame->is_long_term &&
(h264_frame->frame_idx > dpb->max_longterm_frame_idx))
h264_frame->is_reference = FALSE;
if (h264_frame->is_reference) {
while (dpb->n_frames == dpb->max_frames) { while (dpb->n_frames == dpb->max_frames) {
if (!gst_h264_dpb_bump (dpb, G_MAXUINT)) { if (!gst_h264_dpb_bump (dpb, G_MAXUINT)) {
GST_ERROR_OBJECT (dpb, "Couldn't make room in DPB"); GST_ERROR_OBJECT (dpb, "Couldn't make room in DPB");
@ -146,14 +150,8 @@ gst_h264_dpb_add (GstH264DPB * dpb, GstVdpH264Frame * h264_frame)
} }
else { else {
if (dpb->n_frames == dpb->max_frames) { while (gst_h264_dpb_bump (dpb, h264_frame->poc));
while (gst_h264_dpb_bump (dpb, h264_frame->poc)); dpb->output (dpb, h264_frame);
dpb->output (dpb, h264_frame);
}
else
dpb->frames[dpb->n_frames++] = h264_frame;
} }
return TRUE; return TRUE;
@ -183,7 +181,7 @@ gst_h264_dpb_mark_sliding (GstH264DPB * dpb)
{ {
GstVdpH264Frame **frames; GstVdpH264Frame **frames;
guint i; guint i;
gint mark_idx; gint mark_idx = -1;
if (dpb->n_frames != dpb->max_frames) if (dpb->n_frames != dpb->max_frames)
return; return;
@ -199,7 +197,7 @@ gst_h264_dpb_mark_sliding (GstH264DPB * dpb)
if (mark_idx != -1) { if (mark_idx != -1) {
for (i = mark_idx; i < dpb->n_frames; i++) { for (i = mark_idx; i < dpb->n_frames; i++) {
if (frames[i]->is_reference && !frames[i]->is_long_term && if (frames[i]->is_reference && !frames[i]->is_long_term &&
frames[i]->frame_num < frames[mark_idx]->frame_num) frames[i]->frame_idx < frames[mark_idx]->frame_idx)
mark_idx = i; mark_idx = i;
} }
@ -209,6 +207,94 @@ gst_h264_dpb_mark_sliding (GstH264DPB * dpb)
} }
} }
void
gst_h264_dpb_mark_long_term (GstH264DPB * dpb, guint16 pic_num,
guint16 long_term_frame_idx)
{
GstVdpH264Frame **frames;
guint i;
gint mark_idx = -1;
frames = dpb->frames;
for (i = 0; i < dpb->n_frames; i++) {
if (frames[i]->is_reference && !frames[i]->is_long_term &&
frames[i]->frame_idx == pic_num) {
mark_idx = i;
break;
}
}
if (mark_idx != -1) {
frames[mark_idx]->is_long_term = TRUE;
frames[mark_idx]->frame_idx = long_term_frame_idx;
}
}
void
gst_h264_dpb_mark_short_term_unused (GstH264DPB * dpb, guint16 pic_num)
{
GstVdpH264Frame **frames;
guint i;
gint mark_idx = -1;
frames = dpb->frames;
for (i = 0; i < dpb->n_frames; i++) {
if (frames[i]->is_reference && !frames[i]->is_long_term &&
frames[i]->frame_idx == pic_num) {
mark_idx = i;
break;
}
}
if (mark_idx != -1) {
frames[mark_idx]->is_reference = FALSE;
if (!frames[mark_idx]->output_needed)
gst_h264_dpb_remove (dpb, mark_idx);
}
}
void
gst_h264_dpb_mark_long_term_unused (GstH264DPB * dpb, guint16 long_term_pic_num)
{
GstVdpH264Frame **frames;
guint i;
gint mark_idx = -1;
frames = dpb->frames;
for (i = 0; i < dpb->n_frames; i++) {
if (frames[i]->is_reference && frames[i]->is_long_term &&
frames[i]->frame_idx == long_term_pic_num) {
mark_idx = i;
break;
}
}
if (mark_idx != -1) {
frames[mark_idx]->is_reference = FALSE;
if (!frames[mark_idx]->output_needed)
gst_h264_dpb_remove (dpb, mark_idx);
}
}
void
gst_h264_dpb_mark_all_unused (GstH264DPB * dpb)
{
GstVdpH264Frame **frames;
guint i;
frames = dpb->frames;
for (i = 0; i < dpb->n_frames; i++) {
frames[i]->is_reference = FALSE;
if (!frames[i]->output_needed) {
gst_h264_dpb_remove (dpb, i);
i--;
}
}
}
/* GObject vmethod implementations */ /* GObject vmethod implementations */
static void static void
gst_h264_dpb_get_property (GObject * object, guint property_id, gst_h264_dpb_get_property (GObject * object, guint property_id,
@ -220,6 +306,9 @@ gst_h264_dpb_get_property (GObject * object, guint property_id,
case PROP_NUM_REF_FRAMES: case PROP_NUM_REF_FRAMES:
g_value_set_uint (value, dpb->max_frames); g_value_set_uint (value, dpb->max_frames);
break; break;
case PROP_MAX_LONGTERM_IDX:
g_value_set_int (value, dpb->max_longterm_frame_idx);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break; break;
@ -244,6 +333,27 @@ gst_h264_dpb_set_property (GObject * object, guint property_id,
break; break;
} }
case PROP_MAX_LONGTERM_IDX:
{
GstVdpH264Frame **frames;
guint i;
dpb->max_longterm_frame_idx = g_value_get_int (value);
frames = dpb->frames;
for (i = dpb->n_frames; i < dpb->n_frames; i++) {
if (frames[i]->is_reference && frames[i]->is_long_term &&
frames[i]->frame_idx > dpb->max_longterm_frame_idx) {
frames[i]->is_reference = FALSE;
if (!frames[i]->output_needed) {
gst_h264_dpb_remove (dpb, i);
i--;
}
}
}
break;
}
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break; break;
@ -262,6 +372,7 @@ static void
gst_h264_dpb_init (GstH264DPB * dpb) gst_h264_dpb_init (GstH264DPB * dpb)
{ {
dpb->n_frames = 0; dpb->n_frames = 0;
dpb->max_longterm_frame_idx = -1;
dpb->max_frames = MAX_DPB_SIZE; dpb->max_frames = MAX_DPB_SIZE;
} }
@ -279,4 +390,9 @@ gst_h264_dpb_class_init (GstH264DPBClass * klass)
"How many reference frames the DPB should hold ", "How many reference frames the DPB should hold ",
0, 16, 16, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 0, 16, 16, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_MAX_LONGTERM_IDX,
g_param_spec_int ("max-longterm-frame-idx", "MaxLongTermFrameIDX",
"Maximum long-term frame index",
-1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
} }

View file

@ -50,6 +50,7 @@ struct _GstH264DPB
guint n_frames; guint n_frames;
guint max_frames; guint max_frames;
gint max_longterm_frame_idx;
void (*output) (GstH264DPB *dpb, GstVdpH264Frame *h264_frame); void (*output) (GstH264DPB *dpb, GstVdpH264Frame *h264_frame);
}; };
@ -67,6 +68,11 @@ void gst_h264_dpb_flush (GstH264DPB *dpb, gboolean output);
void gst_h264_dpb_mark_sliding (GstH264DPB *dpb); void gst_h264_dpb_mark_sliding (GstH264DPB *dpb);
void gst_h264_dpb_mark_long_term_unused (GstH264DPB *dpb, guint16 long_term_pic_num);
void gst_h264_dpb_mark_short_term_unused (GstH264DPB *dpb, guint16 pic_num);
void gst_h264_dpb_mark_all_unused (GstH264DPB *dpb);
void gst_h264_dpb_mark_long_term (GstH264DPB *dpb, guint16 pic_num, guint16 long_term_frame_idx);
GType gst_h264_dpb_get_type (void) G_GNUC_CONST; GType gst_h264_dpb_get_type (void) G_GNUC_CONST;
G_END_DECLS G_END_DECLS

View file

@ -257,7 +257,7 @@ gst_h264_parser_parse_scaling_list (GstNalReader * reader,
{ {
guint i; guint i;
GST_WARNING ("parsing scaling lists"); GST_DEBUG ("parsing scaling lists");
for (i = 0; i < 12; i++) { for (i = 0; i < 12; i++) {
gboolean use_default = FALSE; gboolean use_default = FALSE;
@ -460,6 +460,12 @@ gst_h264_parser_parse_sequence (GstH264Parser * parser, guint8 * data,
goto error; goto error;
} }
/* calculate ChromaArrayType */
if (seq->separate_colour_plane_flag)
seq->ChromaArrayType = 0;
else
seq->ChromaArrayType = seq->chroma_format_idc;
GST_DEBUG ("adding sequence parameter set with id: %d to hash table", GST_DEBUG ("adding sequence parameter set with id: %d to hash table",
seq->id); seq->id);
g_hash_table_replace (parser->sequences, &seq->id, seq); g_hash_table_replace (parser->sequences, &seq->id, seq);
@ -523,6 +529,7 @@ gst_h264_parser_parse_picture (GstH264Parser * parser, guint8 * data,
GstH264Picture *pic; GstH264Picture *pic;
gint seq_parameter_set_id; gint seq_parameter_set_id;
GstH264Sequence *seq; GstH264Sequence *seq;
guint8 pic_scaling_matrix_present_flag;
g_return_val_if_fail (GST_IS_H264_PARSER (parser), NULL); g_return_val_if_fail (GST_IS_H264_PARSER (parser), NULL);
g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail (data != NULL, NULL);
@ -557,27 +564,28 @@ gst_h264_parser_parse_picture (GstH264Parser * parser, guint8 * data,
for (i = 0; i <= pic->num_slice_groups_minus1; i++) for (i = 0; i <= pic->num_slice_groups_minus1; i++)
READ_UE (&reader, pic->run_length_minus1[i]); READ_UE (&reader, pic->run_length_minus1[i]);
} else if (pic->slice_group_map_type == 2) {
gint i;
for (i = 0; i <= pic->num_slice_groups_minus1; i++) {
READ_UE (&reader, pic->top_left[i]);
READ_UE (&reader, pic->bottom_right[i]);
}
} else if (pic->slice_group_map_type >= 3 && pic->slice_group_map_type <= 5) {
READ_UINT8 (&reader, pic->slice_group_change_direction_flag, 1);
READ_UE (&reader, pic->slice_group_change_rate_minus1);
} else if (pic->slice_group_map_type == 6) {
gint bits;
gint i;
READ_UE (&reader, pic->pic_size_in_map_units_minus1);
bits = ceil (log2 (pic->num_slice_groups_minus1 + 1));
pic->slice_group_id =
g_new (guint8, pic->pic_size_in_map_units_minus1 + 1);
for (i = 0; i <= pic->pic_size_in_map_units_minus1; i++)
READ_UINT8 (&reader, pic->slice_group_id[i], bits);
} }
} else if (pic->slice_group_map_type == 2) {
gint i;
for (i = 0; i <= pic->num_slice_groups_minus1; i++) {
READ_UE (&reader, pic->top_left[i]);
READ_UE (&reader, pic->bottom_right[i]);
}
} else if (pic->slice_group_map_type >= 3 && pic->slice_group_map_type <= 5) {
READ_UINT8 (&reader, pic->slice_group_change_direction_flag, 1);
READ_UE (&reader, pic->slice_group_change_rate_minus1);
} else if (pic->slice_group_map_type == 6) {
gint bits;
gint i;
READ_UE (&reader, pic->pic_size_in_map_units_minus1);
bits = ceil (log2 (pic->num_slice_groups_minus1 + 1));
pic->slice_group_id = g_new (guint8, pic->pic_size_in_map_units_minus1 + 1);
for (i = 0; i <= pic->pic_size_in_map_units_minus1; i++)
READ_UINT8 (&reader, pic->slice_group_id[i], bits);
} }
READ_UE_ALLOWED (&reader, pic->num_ref_idx_l0_active_minus1, 0, 31); READ_UE_ALLOWED (&reader, pic->num_ref_idx_l0_active_minus1, 0, 31);
@ -597,8 +605,8 @@ gst_h264_parser_parse_picture (GstH264Parser * parser, guint8 * data,
READ_UINT8 (&reader, pic->transform_8x8_mode_flag, 1); READ_UINT8 (&reader, pic->transform_8x8_mode_flag, 1);
READ_UINT8 (&reader, pic->scaling_matrix_present_flag, 1); READ_UINT8 (&reader, pic_scaling_matrix_present_flag, 1);
if (pic->scaling_matrix_present_flag) { if (pic_scaling_matrix_present_flag) {
if (seq->scaling_matrix_present_flag) { if (seq->scaling_matrix_present_flag) {
if (!gst_h264_parser_parse_scaling_list (&reader, if (!gst_h264_parser_parse_scaling_list (&reader,
pic->scaling_lists_4x4, pic->scaling_lists_8x8, pic->scaling_lists_4x4, pic->scaling_lists_8x8,
@ -613,6 +621,9 @@ gst_h264_parser_parse_picture (GstH264Parser * parser, guint8 * data,
default_8x8_inter, default_8x8_intra, seq->chroma_format_idc)) default_8x8_inter, default_8x8_intra, seq->chroma_format_idc))
goto error; goto error;
} }
} else {
memcpy (&pic->scaling_lists_4x4, &seq->scaling_lists_4x4, 96);
memcpy (&pic->scaling_lists_8x8, &seq->scaling_lists_8x8, 384);
} }
READ_SE_ALLOWED (&reader, pic->second_chroma_qp_index_offset, -12, 12); READ_SE_ALLOWED (&reader, pic->second_chroma_qp_index_offset, -12, 12);
@ -653,7 +664,7 @@ gst_h264_slice_parse_pred_weight_table (GstH264Slice * slice,
memset (p->chroma_offset_l0, 0, 64); memset (p->chroma_offset_l0, 0, 64);
} }
for (i = 0; i <= pic->num_ref_idx_l0_active_minus1; i++) { for (i = 0; i <= slice->num_ref_idx_l0_active_minus1; i++) {
guint8 luma_weight_l0_flag; guint8 luma_weight_l0_flag;
READ_UINT8 (reader, luma_weight_l0_flag, 1); READ_UINT8 (reader, luma_weight_l0_flag, 1);
@ -666,15 +677,17 @@ gst_h264_slice_parse_pred_weight_table (GstH264Slice * slice,
gint j; gint j;
READ_UINT8 (reader, chroma_weight_l0_flag, 1); READ_UINT8 (reader, chroma_weight_l0_flag, 1);
for (j = 0; j <= 2; j++) { if (chroma_weight_l0_flag) {
READ_SE_ALLOWED (reader, p->chroma_weight_l0[i][j], -128, 127); for (j = 0; j < 2; j++) {
READ_SE_ALLOWED (reader, p->chroma_offset_l0[i][j], -128, 127); READ_SE_ALLOWED (reader, p->chroma_weight_l0[i][j], -128, 127);
READ_SE_ALLOWED (reader, p->chroma_offset_l0[i][j], -128, 127);
}
} }
} }
} }
if (GST_H264_IS_B_SLICE (slice->type)) { if (GST_H264_IS_B_SLICE (slice->type)) {
for (i = 0; i <= pic->num_ref_idx_l1_active_minus1; i++) { for (i = 0; i <= slice->num_ref_idx_l1_active_minus1; i++) {
guint8 luma_weight_l1_flag; guint8 luma_weight_l1_flag;
READ_UINT8 (reader, luma_weight_l1_flag, 1); READ_UINT8 (reader, luma_weight_l1_flag, 1);
@ -687,9 +700,11 @@ gst_h264_slice_parse_pred_weight_table (GstH264Slice * slice,
gint j; gint j;
READ_UINT8 (reader, chroma_weight_l1_flag, 1); READ_UINT8 (reader, chroma_weight_l1_flag, 1);
for (j = 0; j <= 2; j++) { if (chroma_weight_l1_flag) {
READ_SE_ALLOWED (reader, p->chroma_weight_l1[i][j], -128, 127); for (j = 0; j < 2; j++) {
READ_SE_ALLOWED (reader, p->chroma_offset_l1[i][j], -128, 127); READ_SE_ALLOWED (reader, p->chroma_weight_l1[i][j], -128, 127);
READ_SE_ALLOWED (reader, p->chroma_offset_l1[i][j], -128, 127);
}
} }
} }
} }
@ -740,7 +755,7 @@ gst_h264_slice_parse_ref_pic_list_reordering (GstH264Slice * slice,
if (reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) { if (reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) {
guint32 abs_diff_num_minus1; guint32 abs_diff_num_minus1;
READ_UE (reader, abs_diff_num_minus1); READ_UE (reader, abs_diff_num_minus1);
} else if (reordering_of_pic_nums_idc == 3) { } else if (reordering_of_pic_nums_idc == 2) {
guint32 long_term_pic_num; guint32 long_term_pic_num;
READ_UE (reader, long_term_pic_num); READ_UE (reader, long_term_pic_num);
@ -772,32 +787,39 @@ gst_h264_slice_parse_dec_ref_pic_marking (GstH264Slice * slice,
READ_UINT8 (reader, m->adaptive_ref_pic_marking_mode_flag, 1); READ_UINT8 (reader, m->adaptive_ref_pic_marking_mode_flag, 1);
if (m->adaptive_ref_pic_marking_mode_flag) { if (m->adaptive_ref_pic_marking_mode_flag) {
guint8 memory_management_control_operation; guint8 memory_management_control_operation;
guint i = 0;
do { m->n_ref_pic_marking = 0;
while (1) {
READ_UE_ALLOWED (reader, memory_management_control_operation, 0, 6); READ_UE_ALLOWED (reader, memory_management_control_operation, 0, 6);
m->ref_pic_marking[i].memory_management_control_operation = if (memory_management_control_operation == 0)
break;
m->ref_pic_marking[m->n_ref_pic_marking].
memory_management_control_operation =
memory_management_control_operation; memory_management_control_operation;
if (memory_management_control_operation == 1 || if (memory_management_control_operation == 1 ||
memory_management_control_operation == 3) memory_management_control_operation == 3)
READ_UE (reader, m->ref_pic_marking[i].difference_of_pic_nums_minus1); READ_UE (reader,
m->ref_pic_marking[m->n_ref_pic_marking].
difference_of_pic_nums_minus1);
if (memory_management_control_operation == 2) if (memory_management_control_operation == 2)
READ_UE (reader, m->ref_pic_marking[i].long_term_pic_num); READ_UE (reader,
m->ref_pic_marking[m->n_ref_pic_marking].long_term_pic_num);
if (memory_management_control_operation == 3 || if (memory_management_control_operation == 3 ||
memory_management_control_operation == 6) memory_management_control_operation == 6)
READ_UE (reader, m->ref_pic_marking[i].long_term_frame_idx); READ_UE (reader,
m->ref_pic_marking[m->n_ref_pic_marking].long_term_frame_idx);
if (memory_management_control_operation == 4) if (memory_management_control_operation == 4)
READ_UE (reader, m->ref_pic_marking[i].max_long_term_frame_idx_plus1); READ_UE (reader,
m->ref_pic_marking[m->n_ref_pic_marking].
max_long_term_frame_idx_plus1);
i++; m->n_ref_pic_marking++;
} }
while (memory_management_control_operation != 0);
m->n_ref_pic_marking = i;
} }
} }

View file

@ -71,6 +71,7 @@ typedef struct _GstH264Sequence GstH264Sequence;
typedef struct _GstH264Picture GstH264Picture; typedef struct _GstH264Picture GstH264Picture;
typedef struct _GstH264DecRefPicMarking GstH264DecRefPicMarking; typedef struct _GstH264DecRefPicMarking GstH264DecRefPicMarking;
typedef struct _GstH264RefPicMarking GstH264RefPicMarking;
typedef struct _GstH264PredWeightTable GstH264PredWeightTable; typedef struct _GstH264PredWeightTable GstH264PredWeightTable;
typedef struct _GstH264Slice GstH264Slice; typedef struct _GstH264Slice GstH264Slice;
@ -239,33 +240,30 @@ struct _GstH264Picture
guint8 transform_8x8_mode_flag; guint8 transform_8x8_mode_flag;
guint8 scaling_matrix_present_flag;
/* if scaling_matrix_present_flag == 1 */
guint8 scaling_lists_4x4[6][16]; guint8 scaling_lists_4x4[6][16];
guint8 scaling_lists_8x8[6][64]; guint8 scaling_lists_8x8[6][64];
guint8 second_chroma_qp_index_offset; guint8 second_chroma_qp_index_offset;
}; };
struct _GstH264RefPicMarking
{
guint8 memory_management_control_operation;
guint32 difference_of_pic_nums_minus1;
guint32 long_term_pic_num;
guint32 long_term_frame_idx;
guint32 max_long_term_frame_idx_plus1;
};
struct _GstH264DecRefPicMarking struct _GstH264DecRefPicMarking
{ {
/* if slice->nal_unit.IdrPicFlag */ /* if slice->nal_unit.IdrPicFlag */
guint8 no_output_of_prior_pics_flag; guint8 no_output_of_prior_pics_flag;
guint8 long_term_reference_flag; guint8 long_term_reference_flag;
/* else */
guint8 adaptive_ref_pic_marking_mode_flag; guint8 adaptive_ref_pic_marking_mode_flag;
GstH264RefPicMarking ref_pic_marking[10];
struct {
guint8 memory_management_control_operation;
union {
guint32 difference_of_pic_nums_minus1;
guint32 long_term_pic_num;
guint32 long_term_frame_idx;
guint32 max_long_term_frame_idx_plus1;
};
} ref_pic_marking[10];
guint8 n_ref_pic_marking; guint8 n_ref_pic_marking;
}; };

View file

@ -236,20 +236,33 @@ gst_vdp_h264_dec_init_frame_info (GstVdpH264Dec * h264_dec,
h264_frame->output_needed = TRUE; h264_frame->output_needed = TRUE;
h264_frame->is_long_term = FALSE; h264_frame->is_long_term = FALSE;
h264_frame->frame_num = slice->frame_num; h264_frame->frame_idx = slice->frame_num;
/* is reference */ /* is reference */
if (slice->nal_unit.ref_idc == 0) if (slice->nal_unit.ref_idc == 0)
h264_frame->is_reference = FALSE; h264_frame->is_reference = FALSE;
else if (slice->nal_unit.IdrPicFlag) { else if (slice->nal_unit.IdrPicFlag) {
h264_frame->is_reference = TRUE; h264_frame->is_reference = TRUE;
h264_frame->is_long_term = if (slice->dec_ref_pic_marking.long_term_reference_flag) {
slice->dec_ref_pic_marking.long_term_reference_flag; h264_frame->is_long_term = TRUE;
h264_frame->frame_idx = 0;
}
} else { } else {
if (slice->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) h264_frame->is_reference = TRUE;
GST_ERROR ("FIXME: implement adaptive ref pic marking");
else if (slice->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) {
h264_frame->is_reference = TRUE; GstH264RefPicMarking *marking;
guint i;
marking = slice->dec_ref_pic_marking.ref_pic_marking;
for (i = 0; i < slice->dec_ref_pic_marking.n_ref_pic_marking; i++) {
if (marking[i].memory_management_control_operation == 6) {
h264_frame->is_long_term = TRUE;
h264_frame->frame_idx = marking[i].long_term_frame_idx;
break;
}
}
}
} }
} }
@ -269,6 +282,10 @@ gst_vdp_h264_dec_idr (GstVdpH264Dec * h264_dec, GstVdpH264Frame * h264_frame)
else else
gst_h264_dpb_flush (h264_dec->dpb, TRUE); gst_h264_dpb_flush (h264_dec->dpb, TRUE);
if (slice->dec_ref_pic_marking.long_term_reference_flag)
g_object_set (h264_dec->dpb, "max-longterm-frame-idx", 0, NULL);
else
g_object_set (h264_dec->dpb, "max-longterm-frame-idx", -1, NULL);
seq = slice->picture->sequence; seq = slice->picture->sequence;
if (seq != h264_dec->sequence) { if (seq != h264_dec->sequence) {
@ -356,6 +373,8 @@ gst_vdp_h264_dec_fill_info (GstVdpH264Dec * h264_dec,
info.field_pic_flag = slice->field_pic_flag; info.field_pic_flag = slice->field_pic_flag;
info.bottom_field_flag = slice->bottom_field_flag; info.bottom_field_flag = slice->bottom_field_flag;
info.num_ref_idx_l0_active_minus1 = slice->num_ref_idx_l0_active_minus1;
info.num_ref_idx_l1_active_minus1 = slice->num_ref_idx_l1_active_minus1;
info.num_ref_frames = seq->num_ref_frames; info.num_ref_frames = seq->num_ref_frames;
info.frame_mbs_only_flag = seq->frame_mbs_only_flag; info.frame_mbs_only_flag = seq->frame_mbs_only_flag;
@ -375,21 +394,14 @@ gst_vdp_h264_dec_fill_info (GstVdpH264Dec * h264_dec,
info.chroma_qp_index_offset = pic->chroma_qp_index_offset; info.chroma_qp_index_offset = pic->chroma_qp_index_offset;
info.second_chroma_qp_index_offset = pic->second_chroma_qp_index_offset; info.second_chroma_qp_index_offset = pic->second_chroma_qp_index_offset;
info.pic_init_qp_minus26 = pic->pic_init_qp_minus26; info.pic_init_qp_minus26 = pic->pic_init_qp_minus26;
info.num_ref_idx_l0_active_minus1 = pic->num_ref_idx_l0_active_minus1;
info.num_ref_idx_l1_active_minus1 = pic->num_ref_idx_l1_active_minus1;
info.entropy_coding_mode_flag = pic->entropy_coding_mode_flag; info.entropy_coding_mode_flag = pic->entropy_coding_mode_flag;
info.pic_order_present_flag = pic->pic_order_present_flag; info.pic_order_present_flag = pic->pic_order_present_flag;
info.deblocking_filter_control_present_flag = info.deblocking_filter_control_present_flag =
pic->deblocking_filter_control_present_flag; pic->deblocking_filter_control_present_flag;
info.redundant_pic_cnt_present_flag = pic->redundant_pic_cnt_present_flag; info.redundant_pic_cnt_present_flag = pic->redundant_pic_cnt_present_flag;
if (pic->scaling_matrix_present_flag) { memcpy (&info.scaling_lists_4x4, &pic->scaling_lists_4x4, 96);
memcpy (&info.scaling_lists_4x4, &pic->scaling_lists_4x4, 96); memcpy (&info.scaling_lists_8x8, &pic->scaling_lists_8x8, 128);
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); gst_h264_dpb_fill_reference_frames (h264_dec->dpb, info.referenceFrames);
@ -490,6 +502,8 @@ gst_vdp_h264_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder,
return GST_FLOW_OK; return GST_FLOW_OK;
} }
gst_vdp_h264_dec_init_frame_info (h264_dec, h264_frame); gst_vdp_h264_dec_init_frame_info (h264_dec, h264_frame);
@ -515,14 +529,66 @@ gst_vdp_h264_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder,
frame->src_buffer = GST_BUFFER_CAST (outbuf); frame->src_buffer = GST_BUFFER_CAST (outbuf);
/* DPB handling */ /* DPB handling */
if (slice->nal_unit.ref_idc != 0 && !slice->nal_unit.IdrPicFlag) { if (slice->nal_unit.ref_idc != 0 && !slice->nal_unit.IdrPicFlag) {
if (slice->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) if (slice->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) {
GST_ERROR ("FIXME: implement adaptive ref pic marking"); GstH264RefPicMarking *marking;
else guint i;
marking = slice->dec_ref_pic_marking.ref_pic_marking;
for (i = 0; i < slice->dec_ref_pic_marking.n_ref_pic_marking; i++) {
switch (marking[i].memory_management_control_operation) {
case 1:
{
guint16 pic_num;
pic_num = slice->frame_num -
(marking[i].difference_of_pic_nums_minus1 + 1);
gst_h264_dpb_mark_short_term_unused (h264_dec->dpb, pic_num);
break;
}
case 2:
{
gst_h264_dpb_mark_long_term_unused (h264_dec->dpb,
marking[i].long_term_pic_num);
break;
}
case 3:
{
guint16 pic_num;
pic_num = slice->frame_num -
(marking[i].difference_of_pic_nums_minus1 + 1);
gst_h264_dpb_mark_long_term (h264_dec->dpb, pic_num,
marking[i].long_term_frame_idx);
break;
}
case 4:
{
g_object_set (h264_dec->dpb, "max-longterm-frame-idx",
marking[i].max_long_term_frame_idx_plus1 - 1, NULL);
break;
}
case 5:
{
gst_h264_dpb_mark_all_unused (h264_dec->dpb);
g_object_set (h264_dec->dpb, "max-longterm-frame-idx", -1, NULL);
break;
}
default:
break;
}
}
} else
gst_h264_dpb_mark_sliding (h264_dec->dpb); gst_h264_dpb_mark_sliding (h264_dec->dpb);
} }
gst_h264_dpb_add (h264_dec->dpb, h264_frame); gst_h264_dpb_add (h264_dec->dpb, h264_frame);
return GST_FLOW_OK; return GST_FLOW_OK;

View file

@ -45,7 +45,7 @@ struct _GstVdpH264Frame
GPtrArray *slices; GPtrArray *slices;
guint poc; guint poc;
guint16 frame_num; guint16 frame_idx;
gboolean is_reference; gboolean is_reference;
gboolean is_long_term; gboolean is_long_term;
gboolean output_needed; gboolean output_needed;