diff options
-rw-r--r-- | src/video_dec/libvdpau/Makefile.am | 8 | ||||
-rw-r--r-- | src/video_dec/libvdpau/alterh264_bits_reader.h | 127 | ||||
-rw-r--r-- | src/video_dec/libvdpau/alterh264_decode.c | 2448 | ||||
-rw-r--r-- | src/video_dec/libvdpau/alterh264_decode.h | 339 |
4 files changed, 2921 insertions, 1 deletions
diff --git a/src/video_dec/libvdpau/Makefile.am b/src/video_dec/libvdpau/Makefile.am index 89821fca9..d5ffef8de 100644 --- a/src/video_dec/libvdpau/Makefile.am +++ b/src/video_dec/libvdpau/Makefile.am @@ -10,6 +10,8 @@ if ENABLE_VDPAU vdpau_h264_module = xineplug_decode_vdpau_h264.la VDPAU_CFLAGS += -D_ISOC99_SOURCE +vdpau_h264_alter_module = xineplug_decode_vdpau_h264_alter.la + vdpau_mpeg12_module = xineplug_decode_vdpau_mpeg12.la vdpau_vc1_module = xineplug_decode_vdpau_vc1.la @@ -17,7 +19,11 @@ vdpau_vc1_module = xineplug_decode_vdpau_vc1.la vdpau_mpeg4_module = xineplug_decode_vdpau_mpeg4.la endif -xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) $(vdpau_vc1_module) $(vdpau_mpeg4_module) +xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_h264_alter_module) $(vdpau_mpeg12_module) $(vdpau_vc1_module) $(vdpau_mpeg4_module) + +xineplug_decode_vdpau_h264_alter_la_SOURCES = alterh264_decode.c +xineplug_decode_vdpau_h264_alter_la_CFLAGS = $(AM_CFLAGS) +xineplug_decode_vdpau_h264_alter_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c cpb.c h264_parser.c vdpau_h264.c xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) -fno-strict-aliasing diff --git a/src/video_dec/libvdpau/alterh264_bits_reader.h b/src/video_dec/libvdpau/alterh264_bits_reader.h new file mode 100644 index 000000000..47a26aca1 --- /dev/null +++ b/src/video_dec/libvdpau/alterh264_bits_reader.h @@ -0,0 +1,127 @@ +/* kate: tab-indent on; indent-width 4; mixedindent off; indent-mode cstyle; remove-trailing-space on; */ +#ifndef ALTERH264_BITS_READER_H +#define ALTERH264_BITS_READER_H +#include <sys/types.h> +#include <inttypes.h> +#include <stdio.h> + + + +typedef struct { + uint8_t *buffer, *start; + int offbits, length, oflow; +} bits_reader_t; + + + +static void +bits_reader_set (bits_reader_t * br, uint8_t * buf, int len) +{ + br->buffer = br->start = buf; + br->offbits = 0; + br->length = len; + br->oflow = 0; +} + + + +static inline uint32_t +more_rbsp_data (bits_reader_t * br) +{ + uint8_t val[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + uint8_t *buf = br->start + br->length; + int bit; + + while (--buf >= br->buffer) + { + for (bit = 7; bit > -1; bit--) + if (*buf & val[bit]) + return ((buf - br->buffer) * 8) - br->offbits + bit; + } + return 0; +} + + + +static inline uint8_t +bits_reader_shift (bits_reader_t * br) +{ + br->offbits = 0; + if ((br->buffer + 1) > (br->start + br->length - 1)) + { + br->oflow = 1; + //printf("!!!!! buffer overflow !!!!!\n"); + return 0; + } + ++br->buffer; + if ((*(br->buffer) == 3) && ((br->buffer - br->start) > 2) + && (*(br->buffer - 2) == 0) && (*(br->buffer - 1) == 0)) + { + if ((br->buffer + 1) > (br->start + br->length - 1)) + { + br->oflow = 1; + //printf("!!!!! buffer overflow !!!!!\n"); + return 0; + } + ++br->buffer; + } + return 1; +} + + + +static inline uint32_t +read_bits (bits_reader_t * br, int nbits) +{ + uint8_t val[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + uint32_t res = 0; + + while (nbits) + { + res = (res << 1) + ((*br->buffer & val[br->offbits]) ? 1 : 0); + --nbits; + ++br->offbits; + if (br->offbits > 7) + if (!bits_reader_shift (br)) + return 1; + } + return res; +} + + + +static inline void +skip_bits (bits_reader_t * br, int nbits) +{ + while (nbits) + { + --nbits; + ++br->offbits; + if (br->offbits > 7) + bits_reader_shift (br); + } +} + + + +static inline uint32_t +read_exp_ue (bits_reader_t * br) +{ + int leading = -1; + uint8_t b; + + for (b = 0; !b; leading++) + b = read_bits (br, 1); + + return (1 << leading) - 1 + read_bits (br, leading); +} + + + +static inline int32_t +read_exp_se (bits_reader_t * br) +{ + uint32_t res = read_exp_ue (br); + return (res & 0x01) ? (res + 1) / 2 : -(res / 2); +} +#endif /* ALTERH264_BITS_READER_H */ diff --git a/src/video_dec/libvdpau/alterh264_decode.c b/src/video_dec/libvdpau/alterh264_decode.c new file mode 100644 index 000000000..f11162f3e --- /dev/null +++ b/src/video_dec/libvdpau/alterh264_decode.c @@ -0,0 +1,2448 @@ +/* kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle; remove-trailing-space on; + * Copyright (C) 2008 the xine project + * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr> + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * alterh264_decode.c, a H264 video stream parser using VDPAU hardware decoder + * + */ + +#include "alterh264_decode.h" + + +#define MAX_DPB_SIZE 16 +#define MIN_BUFFER_SIZE 10000 +#define MAX_BUFFER_SIZE 3145728 + +#define NAL_UNSPECIFIED 0 +#define NAL_SLICE_NO_IDR 1 +#define NAL_SLICE_IDR 5 +#define NAL_SEI 6 +#define NAL_SEQUENCE 7 +#define NAL_PICTURE 8 +#define NAL_ACCES 9 +#define NAL_END_SEQUENCE 10 +#define NAL_END_STREAM 11 +#define NAL_SEQUENCE_EXT 13 + +#define SLICE_TYPE_P 0 +#define SLICE_TYPE_B 1 +#define SLICE_TYPE_I 2 +#define SLICE_TYPE_SP 3 +#define SLICE_TYPE_SI 4 + +#define START_IDR_FLAG 1000 + +#define MAX_POC 2147483647 + +#define DPB_DRAW_CLEAR 1 +#define DPB_DRAW_REFS 2 +#define DPB_DRAW_CURRENT 3 + +//#define MAKE_DAT /*do NOT define this, unless you know what you do */ +#ifdef MAKE_DAT +static int nframes; +static FILE *outfile; +#endif + + +/*-------- DPB -------------------------------------------*/ +static void +dpb_print (sequence_t * sequence) +{ + int i; + dpb_frame_t *frame; + uint32_t sf; + + for (i = 0; i < MAX_DPB_SIZE; i++) + { + frame = sequence->dpb[i]; + if (!frame->used) + break; + vo_frame_t *vo = (vo_frame_t *) frame->videoSurface; + vdpau_accel_t *accel; + if (vo) + accel = (vdpau_accel_t *) vo->accel_data; + sf = (vo) ? accel->surface : -1; + fprintf (stderr, + "{ i:%d u:%d c:%d pn:%d-%d ir:%d-%d tpoc:%d bpoc:%d sf:%u }\n", + i, frame->used, frame->completed, frame->PicNum[0], + frame->PicNum[1], frame->is_reference[0], frame->is_reference[1], + frame->TopFieldOrderCnt, frame->BottomFieldOrderCnt, sf); + } +} + + + +static void +dpb_clear_all_pts (sequence_t * sequence) +{ + int i; + + for (i = 0; i < MAX_DPB_SIZE; i++) + { + if (!sequence->dpb[i]->used) + break; + sequence->dpb[i]->pts = 0; + } + sequence->cur_pic.pts = 0; + sequence->cur_pic.drop_pts = 1; +} + + +static void +dpb_reset (sequence_t * sequence) +{ + int i; + + for (i = 0; i < MAX_DPB_SIZE; i++) + { + if (sequence->dpb[i]->videoSurface) + sequence->dpb[i]->videoSurface->free (sequence->dpb[i]->videoSurface); + memset (sequence->dpb[i], 0, sizeof (dpb_frame_t)); + } + if (sequence->cur_pic.videoSurface && !sequence->cur_pic.is_reference[0] + && !sequence->cur_pic.is_reference[1]) + { + //fprintf(stderr, "freeing cur_pic\n"); + sequence->cur_pic.videoSurface->free (sequence->cur_pic.videoSurface); + } +} + + + +static void +dpb_remove (sequence_t * sequence, int index) +{ + lprintf ("|||||||||||||||||||||||||||||||||||||||| dbp_remove\n"); + int i; + + dpb_frame_t *frame = sequence->dpb[index]; + if (frame->videoSurface) + frame->videoSurface->free (frame->videoSurface); + memset (frame, 0, sizeof (dpb_frame_t)); + for (i = index; i < (MAX_DPB_SIZE - 1); i++) + { + sequence->dpb[i] = sequence->dpb[i + 1]; + if (!sequence->dpb[i]->used) + { + sequence->dpb[i + 1] = frame; + break; + } + } + if (i == (MAX_DPB_SIZE - 1)) + sequence->dpb[i] = frame; +} + + + +static dpb_frame_t * +dpb_get_prev_ref (sequence_t * sequence) +{ + int i = MAX_DPB_SIZE - 1; + + while (i > -1) + { + if (sequence->dpb[i]->used) + return sequence->dpb[i]; + --i; + } + + return NULL; +} + + + +static void +dpb_draw_frames (vdpau_h264_alter_decoder_t * this_gen, int32_t curpoc, + int draw_mode) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + int i, index = 0; + int32_t poc, tpoc; + dpb_frame_t *frame; + + while (index > -1) + { + index = -1; + poc = curpoc; + for (i = 0; i < MAX_DPB_SIZE; i++) + { + frame = seq->dpb[i]; + if (!frame->used) + break; + tpoc = + (frame->TopFieldOrderCnt > + frame->BottomFieldOrderCnt) ? frame->TopFieldOrderCnt : frame-> + BottomFieldOrderCnt; + if (!frame->videoSurface->drawn && (tpoc <= poc)) + { + poc = tpoc; + index = i; + } + } + if ((index > -1) && (poc <= curpoc)) + { + //fprintf(stderr,"|||||||||||||||||||||||||||||||||||||||| dpb_draw_frame = %d\n", poc); + frame = seq->dpb[index]; + frame->videoSurface->pts = frame->pts; + //fprintf(stderr,"H264 PTS = %llu\n", frame->pts); + frame->videoSurface->top_field_first = frame->top_field_first; + frame->videoSurface->draw (frame->videoSurface, this_gen->stream); + frame->videoSurface->drawn++; + if ((draw_mode != DPB_DRAW_CLEAR) && !frame->is_reference[0] + && !frame->is_reference[1]) + dpb_remove (seq, index); + } + else + index = -1; + } + + if (draw_mode == DPB_DRAW_CURRENT) + { + //fprintf(stderr,"|||||||||||||||||||||||||||||||||||||||| dpb_draw_frame = %d\n", curpoc); + frame = &seq->cur_pic; + frame->videoSurface->pts = frame->pts; + //fprintf(stderr,"H264 PTS = %llu\n", frame->pts); + frame->videoSurface->top_field_first = frame->top_field_first; + frame->videoSurface->draw (frame->videoSurface, this_gen->stream); + frame->videoSurface->free (frame->videoSurface); + } + else if (draw_mode == DPB_DRAW_CLEAR) + dpb_reset (seq); +} + + + +static dpb_frame_t * +dpb_get_PicNum (sequence_t * sequence, int32_t pic_num, int *index) +{ + dpb_frame_t *frame; + int i = 0; + + for (i = 0; i < MAX_DPB_SIZE; i++) + { + frame = sequence->dpb[i]; + if (!frame->used) + break; + if ((frame->PicNum[0] == pic_num) || (frame->PicNum[1] == pic_num)) + { + *index = i; + return frame; + } + } + return 0; +} + + + +static void +dpb_mmc1 (vdpau_h264_alter_decoder_t * this_gen, int32_t picnum) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + int index; + + lprintf ("dpb_mmc1\n"); + + dpb_frame_t *frame = dpb_get_PicNum (seq, picnum, &index); + + if (frame) + { + frame->is_reference[0] = frame->is_reference[1] = 0; + if (frame->videoSurface->drawn) + dpb_remove (seq, index); + else + dpb_draw_frames (this_gen, + (frame->TopFieldOrderCnt > + frame->BottomFieldOrderCnt) ? frame-> + TopFieldOrderCnt : frame->BottomFieldOrderCnt, + DPB_DRAW_REFS); + } +} + + + +static void +dbp_append (vdpau_h264_alter_decoder_t * this_gen, int second_field) +{ + sequence_t *sequence = (sequence_t *) & this_gen->sequence; + int i, index = 0, refs = 0; + int32_t fnw = MAX_POC; + slice_param_t *sl = &sequence->slice_param; + pic_param_t *pic = sequence->pic_param[sl->pic_parameter_set_id]; + seq_param_t *sp = sequence->seq_param[pic->seq_parameter_set_id]; + dpb_frame_t *tmp = 0, *cur_pic = &sequence->cur_pic; + int max = sp->num_ref_frames ? sp->num_ref_frames : 1; + max = (max > MAX_DPB_SIZE) ? MAX_DPB_SIZE : max; + + vo_frame_t *vo = (vo_frame_t *) cur_pic->videoSurface; + vdpau_accel_t *accel = (vdpau_accel_t *) vo->accel_data; + lprintf + ("|||||||||||||||||||||||||||||||||||||||| dbp_append surface = %d\n", + accel->surface); + + if (second_field) + { + tmp = dpb_get_prev_ref (sequence); + if (tmp) + { + memcpy (tmp, cur_pic, sizeof (dpb_frame_t)); + cur_pic->videoSurface = NULL; + } + else + fprintf (stderr, "OOPS, no frame to store the second field ?!\n"); + return; + } + + for (i = 0; i < MAX_DPB_SIZE; i++) + { + if (!sequence->dpb[i]->used) + break; + if (sequence->dpb[i]->FrameNumWrap < fnw) + { + fnw = sequence->dpb[i]->FrameNumWrap; + index = i; + } + refs++; + } + + if (refs >= max) + { + lprintf ("sliding window\n"); + tmp = sequence->dpb[index], + tmp->is_reference[0] = tmp->is_reference[1] = 0; + if (tmp->videoSurface->drawn) + dpb_remove (sequence, index); + else + dpb_draw_frames (this_gen, + (tmp->TopFieldOrderCnt > + tmp->BottomFieldOrderCnt) ? tmp-> + TopFieldOrderCnt : tmp->BottomFieldOrderCnt, + DPB_DRAW_REFS); + + for (i = 0; i < MAX_DPB_SIZE; i++) + { + if (!sequence->dpb[i]->used) + break; + } + } + + if (i < MAX_DPB_SIZE) + { + memcpy (sequence->dpb[i], cur_pic, sizeof (dpb_frame_t)); + if (!cur_pic->field_pic_flag) + cur_pic->videoSurface = NULL; + } +} + +/*--------------------------------------------------------*/ + + + +static void +reset_slices (sequence_t * sequence) +{ + sequence->slices_count = 0; + sequence->slice_mode = 0; +} + + + +static void +reset_sequence (sequence_t * sequence) +{ + sequence->prevFrameNum = 0; + sequence->prevFrameNumOffset = 0; + sequence->prevMMC5 = 0; + + sequence->startup_frame = 0; + sequence->reset = 0; + sequence->chroma = 0; + sequence->pic_pts = 0; + sequence->bufpos = 0; + sequence->bufseek = 0; + sequence->start = -1; + reset_slices (sequence); + dpb_reset (sequence); + memset (&sequence->cur_pic, 0, sizeof (dpb_frame_t)); + sequence->reset = VO_NEW_SEQUENCE_FLAG; + sequence->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; +} + + + +static void +set_ratio (sequence_t * seq, seq_param_t * sp) +{ + if (seq->mode_frame && seq->ratio) + return; + if (!seq->coded_height) + seq->coded_height = 1; + seq->ratio = (double) seq->coded_width / (double) seq->coded_height; + if (sp->vui.aspect_ratio_info) + { + switch (sp->vui.aspect_ratio_idc) + { + case ASPECT_1_1: + seq->ratio = 1 * seq->ratio; + break; + case ASPECT_12_11: + seq->ratio *= 12.0 / 11.0; + break; + case ASPECT_10_11: + seq->ratio *= 10.0 / 11.0; + break; + case ASPECT_16_11: + seq->ratio *= 16.0 / 11.0; + break; + case ASPECT_40_33: + seq->ratio *= 40.0 / 33.0; + break; + case ASPECT_24_11: + seq->ratio *= 24.0 / 11.0; + break; + case ASPECT_20_11: + seq->ratio *= 20.0 / 11.0; + break; + case ASPECT_32_11: + seq->ratio *= 32.0 / 11.0; + break; + case ASPECT_80_33: + seq->ratio *= 80.0 / 33.0; + break; + case ASPECT_18_11: + seq->ratio *= 18.0 / 11.0; + break; + case ASPECT_15_11: + seq->ratio *= 15.0 / 11.0; + break; + case ASPECT_64_33: + seq->ratio *= 64.0 / 33.0; + break; + case ASPECT_160_99: + seq->ratio *= 160.0 / 99.0; + break; + case ASPECT_4_3: + seq->ratio *= 4.0 / 3.0; + break; + case ASPECT_3_2: + seq->ratio *= 3.0 / 2.0; + break; + case ASPECT_2_1: + seq->ratio *= 2.0 / 1.0; + break; + case ASPECT_EXTENDED_SAR: + if (sp->vui.sar_height) + seq->ratio *= (double) sp->vui.sar_width / sp->vui.sar_height; + break; + } + } +} + + + +static void +parse_scaling_list (bits_reader_t * br, uint8_t * scaling_list, int len, + int index) +{ + int last_scale = 8; + int next_scale = 8; + int32_t delta_scale; + uint8_t use_default_scaling_matrix_flag = 0; + int i; + + const uint8_t *zigzag = (len == 64) ? zigzag_8x8 : zigzag_4x4; + + for (i = 0; i < len; i++) + { + if (next_scale != 0) + { + delta_scale = read_exp_se (br); + next_scale = (last_scale + delta_scale + 256) % 256; + if (i == 0 && next_scale == 0) + { + use_default_scaling_matrix_flag = 1; + break; + } + } + scaling_list[zigzag[i]] = last_scale = + (next_scale == 0) ? last_scale : next_scale; + } + + if (use_default_scaling_matrix_flag) + { + switch (index) + { + case 0: + case 1: + case 2: + { + for (i = 0; i < sizeof (default_4x4_intra); i++) + scaling_list[zigzag_4x4[i]] = default_4x4_intra[i]; + break; + } + case 3: + case 4: + case 5: + { + for (i = 0; i < sizeof (default_4x4_inter); i++) + scaling_list[zigzag_4x4[i]] = default_4x4_inter[i]; + break; + } + case 6: + { + for (i = 0; i < sizeof (default_8x8_intra); i++) + scaling_list[zigzag_8x8[i]] = default_8x8_intra[i]; + break; + } + case 7: + { + for (i = 0; i < sizeof (default_8x8_inter); i++) + scaling_list[zigzag_8x8[i]] = default_8x8_inter[i]; + break; + } + } + } +} + + + +static void +scaling_list_fallback_A (uint8_t * scaling_lists_4x4, + uint8_t * scaling_lists_8x8, int i) +{ + int j; + switch (i) + { + case 0: + { + for (j = 0; j < sizeof (default_4x4_intra); j++) + scaling_lists_4x4[(i * 16) + zigzag_4x4[j]] = default_4x4_intra[j]; + break; + } + case 3: + { + for (j = 0; j < sizeof (default_4x4_inter); j++) + scaling_lists_4x4[(i * 16) + zigzag_4x4[j]] = default_4x4_inter[j]; + break; + } + case 1: + case 2: + case 4: + case 5: + memcpy (&scaling_lists_4x4[i * 16], &scaling_lists_4x4[(i - 1) * 16], + 6 * 16); + break; + case 6: + { + for (j = 0; j < sizeof (default_8x8_intra); j++) + scaling_lists_8x8[(i - 6) * 64 + zigzag_8x8[j]] = + default_8x8_intra[j]; + break; + } + case 7: + { + for (j = 0; j < sizeof (default_8x8_inter); j++) + scaling_lists_8x8[(i - 6) * 64 + zigzag_8x8[j]] = + default_8x8_inter[j]; + break; + } + + } +} + + + +static void +scaling_list_fallback_B (seq_param_t * sp, pic_param_t * pic, int i) +{ + switch (i) + { + case 0: + case 3: + memcpy (pic->scaling_lists_4x4[i], sp->scaling_lists_4x4[i], + sizeof (pic->scaling_lists_4x4[i])); + break; + case 1: + case 2: + case 4: + case 5: + memcpy (pic->scaling_lists_4x4[i], pic->scaling_lists_4x4[i - 1], + sizeof (pic->scaling_lists_4x4[i])); + break; + case 6: + case 7: + memcpy (pic->scaling_lists_8x8[i - 6], sp->scaling_lists_8x8[i - 6], + sizeof (pic->scaling_lists_8x8[i - 6])); + break; + } +} + + + +static void +vui_parameters (sequence_t * seq, vui_param_t * vui) +{ + bits_reader_t *br = &seq->br; + + vui->aspect_ratio_info = read_bits (br, 1); + lprintf ("aspect_ratio_info_present_flag = %d\n", vui->aspect_ratio_info); + if (vui->aspect_ratio_info) + { + vui->aspect_ratio_idc = read_bits (br, 8); + lprintf ("aspect_ratio_idc = %d\n", vui->aspect_ratio_idc); + if (vui->aspect_ratio_idc == 255) + { + vui->sar_width = read_bits (br, 16); + lprintf ("sar_width = %d\n", vui->sar_width); + vui->sar_height = read_bits (br, 16); + lprintf ("sar_height = %d\n", vui->sar_height); + } + } + if (read_bits (br, 1)) /* overscan_info_present_flag */ + skip_bits (br, 1); /* overscan_appropriate_falg */ + if (read_bits (br, 1)) + { /* video_signal_type_present_flag */ + skip_bits (br, 3); /*video_format */ + skip_bits (br, 1); /*video_full_range_flag */ + vui->colour_desc = read_bits (br, 1); + lprintf ("colour_desc = %d\n", vui->colour_desc); + if (vui->colour_desc) + { + vui->colour_primaries = read_bits (br, 8); + lprintf ("colour_primaries = %d\n", vui->colour_primaries); + skip_bits (br, 8); /* transfer_characteristics */ + skip_bits (br, 8); /* matrix_coefficients */ + switch (vui->colour_primaries) + { + case 1: + seq->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709; + break; + case 6: + case 7: + seq->color_standard = VDP_COLOR_STANDARD_SMPTE_240M; + break; + } + } + } + if (read_bits (br, 1)) + { /* chroma_loc_info_present_flag */ + read_exp_ue (br); /* chroma_sample_loc_type_top_field */ + read_exp_ue (br); /* chroma_sample_loc_type_bottom_field */ + } + vui->timing_info = read_bits (br, 1); + lprintf ("timing_info = %d\n", vui->timing_info); + if (vui->timing_info) + { + vui->num_units_in_tick = read_bits (br, 32); + lprintf ("num_units_in_tick = %u\n", vui->num_units_in_tick); + vui->time_scale = read_bits (br, 32); + lprintf ("time_scale = %u\n", vui->time_scale); + if (vui->time_scale > 0) + seq->video_step = + 180000. * (double) vui->num_units_in_tick / (double) vui->time_scale; + } +} + + + +static void +seq_parameter_set_data (vdpau_h264_alter_decoder_t * this_gen) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + seq_param_t *sp; + int i; + + uint8_t profile_idc = read_bits (&seq->br, 8); + lprintf ("profile_idc = %d\n", profile_idc); + uint8_t constraint_set0_flag = read_bits (&seq->br, 1); + lprintf ("constraint_set0_flag = %d\n", constraint_set0_flag); + uint8_t constraint_set1_flag = read_bits (&seq->br, 1); + lprintf ("constraint_set1_flag = %d\n", constraint_set1_flag); + uint8_t constraint_set2_flag = read_bits (&seq->br, 1); + lprintf ("constraint_set2_flag = %d\n", constraint_set2_flag); + uint8_t constraint_set3_flag = read_bits (&seq->br, 1); + lprintf ("constraint_set3_flag = %d\n", constraint_set3_flag); + skip_bits (&seq->br, 4); + uint8_t level_idc = read_bits (&seq->br, 8); + lprintf ("level_idc = %d\n", level_idc); + + uint8_t seq_parameter_set_id = read_exp_ue (&seq->br); + lprintf ("seq_parameter_set_id = %d\n", seq_parameter_set_id); + if (seq_parameter_set_id > 31) + { + lprintf ("OOPS : seq_parameter_set_id > 31 !!\n"); + return; + } + + if (!seq->seq_param[seq_parameter_set_id]) + seq->seq_param[seq_parameter_set_id] = + (seq_param_t *) calloc (1, sizeof (seq_param_t)); + if (!seq->seq_param[seq_parameter_set_id]) + { + lprintf ("OOPS : can't allocate SPS %d !!\n", seq_parameter_set_id); + return; + } + + sp = seq->seq_param[seq_parameter_set_id]; + sp->profile_idc = profile_idc; + switch (profile_idc) + { + case 100: + seq->profile = VDP_DECODER_PROFILE_H264_HIGH; + break; + case 77: + seq->profile = VDP_DECODER_PROFILE_H264_MAIN; + break; + case 66: /* nvidia's vdpau doesn't suppot baseline, force main */ + default: + seq->profile = VDP_DECODER_PROFILE_H264_MAIN; + } + sp->constraint_set0_flag = constraint_set0_flag; + sp->constraint_set1_flag = constraint_set1_flag; + sp->constraint_set2_flag = constraint_set2_flag; + sp->constraint_set3_flag = constraint_set3_flag; + sp->level_idc = level_idc; + + memset (&sp->scaling_lists_4x4, 16, sizeof (sp->scaling_lists_4x4)); + memset (&sp->scaling_lists_8x8, 16, sizeof (sp->scaling_lists_8x8)); + + sp->chroma_format_idc = 1; + sp->separate_colour_plane_flag = 0; + if (sp->profile_idc == 100 || sp->profile_idc == 110 + || sp->profile_idc == 122 || sp->profile_idc == 244 + || sp->profile_idc == 44 || sp->profile_idc == 83 + || sp->profile_idc == 86) + { + sp->chroma_format_idc = read_exp_ue (&seq->br); + lprintf ("chroma_format_idc = %u\n", sp->chroma_format_idc); + if (sp->chroma_format_idc == 3) + { + sp->separate_colour_plane_flag = read_bits (&seq->br, 1); + lprintf ("separate_colour_plane_flag = %d\n", + sp->separate_colour_plane_flag); + } + sp->bit_depth_luma_minus8 = read_exp_ue (&seq->br); + lprintf ("bit_depth_luma_minus8 = %u\n", sp->bit_depth_luma_minus8); + sp->bit_depth_chroma_minus8 = read_exp_ue (&seq->br); + lprintf ("bit_depth_chroma_minus8 = %u\n", sp->bit_depth_chroma_minus8); + sp->qpprime_y_zero_transform_bypass_flag = read_bits (&seq->br, 1); + lprintf ("qpprime_y_zero_transform_bypass_flag = %u\n", + sp->qpprime_y_zero_transform_bypass_flag); + sp->seq_scaling_matrix_present_flag = read_bits (&seq->br, 1); + lprintf ("seq_scaling_matrix_present_flag = %u\n", + sp->seq_scaling_matrix_present_flag); + if (sp->seq_scaling_matrix_present_flag) + { + for (i = 0; i < 8; i++) + { + int scaling_flag = read_bits (&seq->br, 1); + if (scaling_flag) + { + if (i < 6) + parse_scaling_list (&seq->br, &sp->scaling_lists_4x4[i][0], 16, + i); + else + parse_scaling_list (&seq->br, &sp->scaling_lists_8x8[i - 6][0], + 64, i); + } + else + scaling_list_fallback_A ((uint8_t *) sp->scaling_lists_4x4, + (uint8_t *) sp->scaling_lists_8x8, i); + } + } + } + sp->log2_max_frame_num_minus4 = read_exp_ue (&seq->br); + lprintf ("log2_max_frame_num_minus4 = %u\n", sp->log2_max_frame_num_minus4); + sp->pic_order_cnt_type = read_exp_ue (&seq->br); + lprintf ("pic_order_cnt_type = %u\n", sp->pic_order_cnt_type); + if (sp->pic_order_cnt_type == 0) + { + sp->log2_max_pic_order_cnt_lsb_minus4 = read_exp_ue (&seq->br); + lprintf ("log2_max_pic_order_cnt_lsb_minus4 = %u\n", + sp->log2_max_pic_order_cnt_lsb_minus4); + } + else if (sp->pic_order_cnt_type == 1) + { + sp->delta_pic_order_always_zero_flag = read_bits (&seq->br, 1); + lprintf ("delta_pic_order_always_zero_flag = %u\n", + sp->delta_pic_order_always_zero_flag); + sp->offset_for_non_ref_pic = read_exp_se (&seq->br); + lprintf ("offset_for_non_ref_pic = %d\n", sp->offset_for_non_ref_pic); + sp->offset_for_top_to_bottom_field = read_exp_se (&seq->br); + lprintf ("offset_for_top_to_bottom_field = %d\n", + sp->offset_for_top_to_bottom_field); + sp->num_ref_frames_in_pic_order_cnt_cycle = read_exp_ue (&seq->br); + lprintf ("num_ref_frames_in_pic_order_cnt_cycle = %u\n", + sp->num_ref_frames_in_pic_order_cnt_cycle); + for (i = 0; i < sp->num_ref_frames_in_pic_order_cnt_cycle; i++) + { + sp->offset_for_ref_frame[i] = read_exp_se (&seq->br); + lprintf ("offset_for_ref_frame[%d] = %d\n", i, + sp->offset_for_ref_frame[i]); + } + } + sp->num_ref_frames = read_exp_ue (&seq->br); + if (sp->num_ref_frames > 16) + sp->num_ref_frames = 16; + lprintf ("num_ref_frames = %u\n", sp->num_ref_frames); + sp->gaps_in_frame_num_value_allowed_flag = read_bits (&seq->br, 1); + lprintf ("gaps_in_frame_num_value_allowed_flag = %u\n", + sp->gaps_in_frame_num_value_allowed_flag); + sp->pic_width_in_mbs_minus1 = read_exp_ue (&seq->br); + lprintf ("pic_width_in_mbs_minus1 = %u\n", sp->pic_width_in_mbs_minus1); + sp->pic_height_in_map_units_minus1 = read_exp_ue (&seq->br); + lprintf ("pic_height_in_map_units_minus1 = %u\n", + sp->pic_height_in_map_units_minus1); + sp->frame_mbs_only_flag = read_bits (&seq->br, 1); + lprintf ("frame_mbs_only_flag = %u\n", sp->frame_mbs_only_flag); + + seq->coded_width = (sp->pic_width_in_mbs_minus1 + 1) * 16; + seq->coded_height = + (2 - sp->frame_mbs_only_flag) * (sp->pic_height_in_map_units_minus1 + + 1) * 16; + + if (!sp->frame_mbs_only_flag) + { + sp->mb_adaptive_frame_field_flag = read_bits (&seq->br, 1); + lprintf ("mb_adaptive_frame_field_flag = %u\n", + sp->mb_adaptive_frame_field_flag); + } + sp->direct_8x8_inference_flag = read_bits (&seq->br, 1); + lprintf ("direct_8x8_inference_flag = %u\n", sp->direct_8x8_inference_flag); + sp->frame_cropping_flag = read_bits (&seq->br, 1); + lprintf ("frame_cropping_flag = %u\n", sp->frame_cropping_flag); + if (sp->frame_cropping_flag) + { + sp->frame_crop_left_offset = read_exp_ue (&seq->br); + lprintf ("frame_crop_left_offset = %u\n", sp->frame_crop_left_offset); + sp->frame_crop_right_offset = read_exp_ue (&seq->br); + lprintf ("frame_crop_right_offset = %u\n", sp->frame_crop_right_offset); + sp->frame_crop_top_offset = read_exp_ue (&seq->br); + lprintf ("frame_crop_top_offset = %u\n", sp->frame_crop_top_offset); + sp->frame_crop_bottom_offset = read_exp_ue (&seq->br); + lprintf ("frame_crop_bottom_offset = %u\n", sp->frame_crop_bottom_offset); + seq->coded_height -= + (2 - sp->frame_mbs_only_flag) * 2 * sp->frame_crop_bottom_offset; + } + if (seq->coded_height == 1088) + seq->coded_height = 1080; + sp->vui_parameters_present_flag = read_bits (&seq->br, 1); + lprintf ("vui_parameters_present_flag = %u\n", + sp->vui_parameters_present_flag); + if (sp->vui_parameters_present_flag) + vui_parameters (seq, &sp->vui); + set_ratio (seq, sp); +} + + + +static void +pic_parameter_set (vdpau_h264_alter_decoder_t * this_gen) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + pic_param_t *pic; + seq_param_t *sp; + int i; + + uint8_t pic_parameter_set_id = read_exp_ue (&seq->br); + lprintf ("pic_parameter_set_id = %u\n", pic_parameter_set_id); + if (!seq->pic_param[pic_parameter_set_id]) + seq->pic_param[pic_parameter_set_id] = + (pic_param_t *) calloc (1, sizeof (pic_param_t)); + if (!seq->pic_param[pic_parameter_set_id]) + { + lprintf ("OOPS : can't allocate PPS %d !!\n", pic_parameter_set_id); + return; + } + pic = seq->pic_param[pic_parameter_set_id]; + + uint8_t seq_parameter_set_id = read_exp_ue (&seq->br); + lprintf ("seq_parameter_set_id = %u\n", seq_parameter_set_id); + if (seq_parameter_set_id > 31) + { + lprintf ("OOPS : referenced SPS (%d) does not exist !!\n", + seq_parameter_set_id); + return; + } + if (!seq->seq_param[seq_parameter_set_id]) + { + lprintf ("OOPS : referenced SPS (%d) does not exist !!\n", + seq_parameter_set_id); + return; + } + + pic->seq_parameter_set_id = seq_parameter_set_id; + sp = seq->seq_param[pic->seq_parameter_set_id]; + pic->entropy_coding_mode_flag = read_bits (&seq->br, 1); + lprintf ("entropy_coding_mode_flag = %u\n", pic->entropy_coding_mode_flag); + pic->pic_order_present_flag = read_bits (&seq->br, 1); + lprintf ("pic_order_present_flag = %u\n", pic->pic_order_present_flag); + uint8_t num_slice_groups_minus1 = read_exp_ue (&seq->br); + lprintf ("num_slice_groups_minus1 = %u\n", num_slice_groups_minus1); + if (num_slice_groups_minus1 > 0) + { + uint8_t slice_group_map_type = read_exp_ue (&seq->br); + lprintf ("slice_group_map_type = %u\n", slice_group_map_type); + if (!slice_group_map_type) + { + for (i = 0; i < num_slice_groups_minus1; i++) + read_exp_ue (&seq->br); + } + else if (slice_group_map_type == 2) + { + for (i = 0; i < num_slice_groups_minus1; i++) + { + read_exp_ue (&seq->br); + read_exp_ue (&seq->br); + } + } + else if (slice_group_map_type == 3 || slice_group_map_type == 4 + || slice_group_map_type == 5) + { + read_bits (&seq->br, 1); + read_exp_ue (&seq->br); + } + else if (slice_group_map_type == 6) + { + read_exp_ue (&seq->br); + } + } + pic->num_ref_idx_l0_active_minus1 = read_exp_ue (&seq->br); + lprintf ("num_ref_idx_l0_active_minus1 = %u\n", + pic->num_ref_idx_l0_active_minus1); + pic->num_ref_idx_l1_active_minus1 = read_exp_ue (&seq->br); + lprintf ("num_ref_idx_l1_active_minus1 = %u\n", + pic->num_ref_idx_l1_active_minus1); + pic->weighted_pred_flag = read_bits (&seq->br, 1); + lprintf ("weighted_pred_flag = %u\n", pic->weighted_pred_flag); + pic->weighted_bipred_idc = read_bits (&seq->br, 2); + lprintf ("weighted_bipred_idc = %u\n", pic->weighted_bipred_idc); + pic->pic_init_qp_minus26 = read_exp_se (&seq->br); + lprintf ("pic_init_qp_minus26 = %d\n", pic->pic_init_qp_minus26); + pic->pic_init_qs_minus26 = read_exp_se (&seq->br); + lprintf ("pic_init_qs_minus26 = %d\n", pic->pic_init_qs_minus26); + pic->chroma_qp_index_offset = read_exp_se (&seq->br); + lprintf ("chroma_qp_index_offset = %d\n", pic->chroma_qp_index_offset); + pic->deblocking_filter_control_present_flag = read_bits (&seq->br, 1); + lprintf ("deblocking_filter_control_present_flag = %u\n", + pic->deblocking_filter_control_present_flag); + pic->constrained_intra_pred_flag = read_bits (&seq->br, 1); + lprintf ("constrained_intra_pred_flag = %u\n", + pic->constrained_intra_pred_flag); + pic->redundant_pic_cnt_present_flag = read_bits (&seq->br, 1); + lprintf ("redundant_pic_cnt_present_flag = %u\n", + pic->redundant_pic_cnt_present_flag); + + uint32_t more = more_rbsp_data (&seq->br); + lprintf ("more bits = %u (buflen = %d) (still = %d)\n", more, + seq->br.length, seq->br.start + seq->br.length - seq->br.buffer); + if (more) + { + pic->transform_8x8_mode_flag = read_bits (&seq->br, 1); + lprintf ("transform_8x8_mode_flag = %u\n", pic->transform_8x8_mode_flag); + pic->pic_scaling_matrix_present_flag = read_bits (&seq->br, 1); + lprintf ("pic_scaling_matrix_present_flag = %u\n", + pic->pic_scaling_matrix_present_flag); + if (pic->pic_scaling_matrix_present_flag) + { + for (i = 0; i < 8; i++) + { + if (i < 6 || pic->transform_8x8_mode_flag) + pic->pic_scaling_list_present_flag[i] = read_bits (&seq->br, 1); + else + pic->pic_scaling_list_present_flag[i] = 0; + + if (pic->pic_scaling_list_present_flag[i]) + { + if (i < 6) + parse_scaling_list (&seq->br, &pic->scaling_lists_4x4[i][0], 16, + i); + else + parse_scaling_list (&seq->br, &pic->scaling_lists_8x8[i - 6][0], + 64, i); + } + else + { + if (!sp->seq_scaling_matrix_present_flag) + scaling_list_fallback_A ((uint8_t *) pic->scaling_lists_4x4, + (uint8_t *) pic->scaling_lists_8x8, i); + else + scaling_list_fallback_B (sp, pic, i); + } + } + } + pic->second_chroma_qp_index_offset = read_exp_se (&seq->br); + lprintf ("second_chroma_qp_index_offset = %d\n", + pic->second_chroma_qp_index_offset); + } + else + { + pic->transform_8x8_mode_flag = 0; + pic->pic_scaling_matrix_present_flag = 0; + pic->second_chroma_qp_index_offset = pic->chroma_qp_index_offset; + } +} + + + +static void +pred_weight_table (vdpau_h264_alter_decoder_t * this_gen, uint8_t slice_type, + uint8_t ChromaArrayType, uint8_t l0, uint8_t l1) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + int i; + + read_exp_ue (&seq->br); + if (ChromaArrayType) + read_exp_ue (&seq->br); + for (i = 0; i <= l0; i++) + { + if (read_bits (&seq->br, 1)) + { + read_exp_se (&seq->br); + read_exp_se (&seq->br); + } + if (ChromaArrayType && read_bits (&seq->br, 1)) + { + read_exp_se (&seq->br); + read_exp_se (&seq->br); + read_exp_se (&seq->br); + read_exp_se (&seq->br); + } + } + if (slice_type == SLICE_TYPE_B) + { + for (i = 0; i <= l1; i++) + { + if (read_bits (&seq->br, 1)) + { + read_exp_se (&seq->br); + read_exp_se (&seq->br); + } + if (ChromaArrayType) + { + if (read_bits (&seq->br, 1)) + { + read_exp_se (&seq->br); + read_exp_se (&seq->br); + read_exp_se (&seq->br); + read_exp_se (&seq->br); + } + } + } + } +} + + + +static void +ref_pic_list_reordering (vdpau_h264_alter_decoder_t * this_gen) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + slice_param_t *sl = &seq->slice_param; + + if ((sl->slice_type != SLICE_TYPE_I) && (sl->slice_type != SLICE_TYPE_SI)) + { + if (read_bits (&seq->br, 1)) + { + uint32_t tmp, diff; + do + { + tmp = read_exp_ue (&seq->br); + if (tmp == 0 || tmp == 1) + diff = read_exp_ue (&seq->br); + else if (tmp == 2) + diff = read_exp_ue (&seq->br); + } + while (tmp != 3 && !seq->br.oflow); + } + } + if (sl->slice_type == SLICE_TYPE_B) + { + if (read_bits (&seq->br, 1)) + { + uint32_t tmp2, diff2; + do + { + tmp2 = read_exp_ue (&seq->br); + if (tmp2 == 0 || tmp2 == 1) + diff2 = read_exp_ue (&seq->br); + else if (tmp2 == 2) + diff2 = read_exp_ue (&seq->br); + } + while (tmp2 != 3 && !seq->br.oflow); + } + } +} + + + +static void +dec_ref_pic_marking (vdpau_h264_alter_decoder_t * this_gen, uint8_t idr) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + int32_t pic_num; + + if (idr) + { + uint8_t no_output_of_prior_pics_flag = read_bits (&seq->br, 1); + lprintf ("no_output_of_prior_pics_flag = %u\n", + no_output_of_prior_pics_flag); + uint8_t long_term_reference_flag = read_bits (&seq->br, 1); + lprintf ("long_term_reference_flag = %u\n", long_term_reference_flag); + } + else + { + uint8_t adaptive_ref_pic_marking_mode_flag = read_bits (&seq->br, 1); + lprintf ("adaptive_ref_pic_marking_mode_flag = %u\n", + adaptive_ref_pic_marking_mode_flag); + if (!adaptive_ref_pic_marking_mode_flag) + { + if (seq->cur_pic.field_pic_flag + && (seq->cur_pic.completed == PICTURE_DONE) + && (seq->cur_pic.is_reference[0] || seq->cur_pic.is_reference[1])) + { + seq->cur_pic.is_reference[0] = seq->cur_pic.is_reference[1] = + SHORT_TERM_REF; + lprintf ("short_ref marking\n"); + } + // sliding window is always performed in dpb_append() + } + else + { + uint8_t memory_management_control_operation; + do + { + memory_management_control_operation = read_exp_ue (&seq->br); + lprintf ("memory_management_control_operation = %u\n", + memory_management_control_operation); + if (memory_management_control_operation == 1 + || memory_management_control_operation == 3) + { + uint32_t difference_of_pic_nums_minus1 = read_exp_ue (&seq->br); + lprintf ("difference_of_pic_nums_minus1 = %u\n", + difference_of_pic_nums_minus1); + pic_num = + seq->cur_pic.PicNum[0] - (difference_of_pic_nums_minus1 + 1); + dpb_mmc1 (this_gen, pic_num); + } + if (memory_management_control_operation == 2) + { + uint32_t long_term_pic_num = read_exp_ue (&seq->br); + lprintf ("long_term_pic_num = %u\n", long_term_pic_num); + } + if (memory_management_control_operation == 3 + || memory_management_control_operation == 6) + { + uint32_t long_term_frame_idx = read_exp_ue (&seq->br); + lprintf ("long_term_frame_idx = %u\n", long_term_frame_idx); + } + if (memory_management_control_operation == 4) + { + uint32_t max_long_term_frame_idx_plus1 = read_exp_ue (&seq->br); + lprintf ("max_long_term_frame_idx_plus1 = %u\n", + max_long_term_frame_idx_plus1); + } + } + while (memory_management_control_operation && !seq->br.oflow); + } + } +} + + + +static void +slice_header (vdpau_h264_alter_decoder_t * this_gen, uint8_t nal_ref_idc, + uint8_t nal_unit_type) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + slice_param_t *sl = &seq->slice_param; + pic_param_t *pic; + seq_param_t *sp; + + sl->nal_ref_idc = nal_ref_idc; + sl->nal_unit_type = nal_unit_type; + + read_exp_ue (&seq->br); /* first_mb_in_slice */ + sl->slice_type = read_exp_ue (&seq->br) % 5; + lprintf ("slice_type = %u\n", sl->slice_type); + sl->pic_parameter_set_id = read_exp_ue (&seq->br); + lprintf ("pic_parameter_set_id = %u\n", sl->pic_parameter_set_id); + if (!seq->pic_param[sl->pic_parameter_set_id]) + { + lprintf ("OOPS : referenced PPS (%d) does not exist !!\n", + sl->pic_parameter_set_id); + seq->cur_pic.missing_header = 1; + return; + } + pic = seq->pic_param[sl->pic_parameter_set_id]; + if (!seq->seq_param[pic->seq_parameter_set_id]) + { + lprintf ("OOPS : referenced SPS (%d) does not exist !!\n", + pic->seq_parameter_set_id); + seq->cur_pic.missing_header = 1; + return; + } + + if (!seq->startup_frame && (sl->slice_type == SLICE_TYPE_I) + && !seq->cur_pic.completed) + seq->startup_frame = 1; + + sp = seq->seq_param[pic->seq_parameter_set_id]; + if (sp->separate_colour_plane_flag) + read_bits (&seq->br, 2); /* colour_plane_id */ + sl->frame_num = read_bits (&seq->br, sp->log2_max_frame_num_minus4 + 4); + lprintf ("frame_num = %u\n", sl->frame_num); + sl->MaxFrameNum = 1 << (sp->log2_max_frame_num_minus4 + 4); + + sl->field_pic_flag = sl->bottom_field_flag = + sl->delta_pic_order_cnt_bottom = 0; + sl->delta_pic_order_cnt[0] = sl->delta_pic_order_cnt[1] = 0; + + if (!sp->frame_mbs_only_flag) + { + sl->field_pic_flag = read_bits (&seq->br, 1); + lprintf ("field_pic_flag = %u\n", sl->field_pic_flag); + if (sl->field_pic_flag) + { + sl->bottom_field_flag = read_bits (&seq->br, 1); + lprintf ("bottom_field_flag = %u\n", sl->bottom_field_flag); + } + } + if (nal_unit_type == NAL_SLICE_IDR) + { + sl->idr_pic_id = read_exp_ue (&seq->br); + lprintf ("idr_pic_id = %u\n", sl->idr_pic_id); + } + if (sp->pic_order_cnt_type == 0) + { + sl->pic_order_cnt_lsb = + read_bits (&seq->br, sp->log2_max_pic_order_cnt_lsb_minus4 + 4); + lprintf ("pic_order_cnt_lsb = %u\n", sl->pic_order_cnt_lsb); + if (pic->pic_order_present_flag && !sl->field_pic_flag) + { + sl->delta_pic_order_cnt_bottom = read_exp_se (&seq->br); + lprintf ("delta_pic_order_cnt_bottom = %d\n", + sl->delta_pic_order_cnt_bottom); + } + } + if (sp->pic_order_cnt_type == 1 && !sp->delta_pic_order_always_zero_flag) + { + sl->delta_pic_order_cnt[0] = read_exp_se (&seq->br); + lprintf ("delta_pic_order_cnt[0] = %d\n", sl->delta_pic_order_cnt[0]); + if (pic->pic_order_present_flag && !sl->field_pic_flag) + { + sl->delta_pic_order_cnt[1] = read_exp_se (&seq->br); + lprintf ("delta_pic_order_cnt[1] = %d\n", sl->delta_pic_order_cnt[1]); + } + } + if (pic->redundant_pic_cnt_present_flag) + { + sl->redundant_pic_cnt = read_exp_ue (&seq->br); + lprintf ("redundant_pic_cnt = %u\n", sl->redundant_pic_cnt); + } + if (sl->slice_type == SLICE_TYPE_B) + skip_bits (&seq->br, 1); /* direct_spatial_mv_pred_flag */ + + sl->num_ref_idx_l0_active_minus1 = pic->num_ref_idx_l0_active_minus1; + sl->num_ref_idx_l1_active_minus1 = pic->num_ref_idx_l1_active_minus1; + + if (sl->slice_type == SLICE_TYPE_P || sl->slice_type == SLICE_TYPE_SP + || sl->slice_type == SLICE_TYPE_B) + { + if (read_bits (&seq->br, 1)) + { + lprintf ("num_ref_idx_active_override_flag = 1\n"); + sl->num_ref_idx_l0_active_minus1 = read_exp_ue (&seq->br); + if (sl->slice_type == SLICE_TYPE_B) + sl->num_ref_idx_l1_active_minus1 = read_exp_ue (&seq->br); + lprintf ("num_ref_idx_l0_active_minus1 = %u\n", + sl->num_ref_idx_l0_active_minus1); + lprintf ("num_ref_idx_l1_active_minus1 = %u\n", + sl->num_ref_idx_l1_active_minus1); + } + } +} + + + +static void +slice_header_post (vdpau_h264_alter_decoder_t * this_gen) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + slice_param_t *sl = &seq->slice_param; + + if (!sl->nal_ref_idc) + return; + + pic_param_t *pic = seq->pic_param[sl->pic_parameter_set_id]; + seq_param_t *sp = seq->seq_param[pic->seq_parameter_set_id]; + + if ((pic->weighted_pred_flag + && ((sl->slice_type == SLICE_TYPE_P) + || (sl->slice_type == SLICE_TYPE_SP))) + || ((pic->weighted_bipred_idc == 1) + && (sl->slice_type == SLICE_TYPE_B))) + { + uint8_t chroma = + (sp->separate_colour_plane_flag) ? 0 : sp->chroma_format_idc; + pred_weight_table (this_gen, sl->slice_type, chroma, + sl->num_ref_idx_l0_active_minus1, + sl->num_ref_idx_l1_active_minus1); + } + + dec_ref_pic_marking (this_gen, (sl->nal_unit_type == 5) ? 1 : 0); +} + + + +static void +decode_poc (vdpau_h264_alter_decoder_t * this_gen) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + slice_param_t *sl = &seq->slice_param; + pic_param_t *pic = seq->pic_param[sl->pic_parameter_set_id]; + seq_param_t *sp = seq->seq_param[pic->seq_parameter_set_id]; + int parity = sl->bottom_field_flag ? 1 : 0; + + seq->cur_pic.used = 1; + seq->cur_pic.FrameNum = sl->frame_num; + seq->cur_pic.is_reference[parity] = sl->nal_ref_idc; + seq->cur_pic.field_pic_flag = sl->field_pic_flag; + + if (sl->field_pic_flag) + { + if (!seq->cur_pic.completed) + seq->cur_pic.top_field_first = !parity; + seq->cur_pic.completed |= + (parity ? PICTURE_BOTTOM_DONE : PICTURE_TOP_DONE); + } + else + { + seq->cur_pic.is_reference[!parity] = seq->cur_pic.is_reference[parity]; + seq->cur_pic.completed = PICTURE_DONE; + } + + if (sp->pic_order_cnt_type == 0) + { + dpb_frame_t *prev_pic = dpb_get_prev_ref (seq); + int32_t prevPicOrderCntMsb, prevPicOrderCntLsb; + uint32_t MaxPicOrderCntLsb = + 1 << (sp->log2_max_pic_order_cnt_lsb_minus4 + 4); + + seq->cur_pic.pic_order_cnt_lsb = sl->pic_order_cnt_lsb; + seq->cur_pic.top_field_first = + (sl->delta_pic_order_cnt_bottom < 0) ? 0 : 1; + + if (!prev_pic) + { + seq->cur_pic.PicOrderCntMsb = seq->cur_pic.TopFieldOrderCnt = + seq->cur_pic.BottomFieldOrderCnt = 0; + return; + } + if (sl->nal_unit_type == NAL_SLICE_IDR) + prevPicOrderCntMsb = prevPicOrderCntLsb = 0; + else if (prev_pic->mmc5) + { + if (!sl->bottom_field_flag) + { + prevPicOrderCntMsb = 0; + prevPicOrderCntLsb = prev_pic->TopFieldOrderCnt; + } + else + prevPicOrderCntMsb = prevPicOrderCntLsb = 0; + } + else + { + prevPicOrderCntMsb = prev_pic->PicOrderCntMsb; + prevPicOrderCntLsb = prev_pic->pic_order_cnt_lsb; + } + + if ((sl->pic_order_cnt_lsb < prevPicOrderCntLsb) + && ((prevPicOrderCntLsb - sl->pic_order_cnt_lsb) >= + (MaxPicOrderCntLsb / 2))) + seq->cur_pic.PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; + else if ((sl->pic_order_cnt_lsb > prevPicOrderCntLsb) + && ((sl->pic_order_cnt_lsb - prevPicOrderCntLsb) > + (MaxPicOrderCntLsb / 2))) + seq->cur_pic.PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; + else + seq->cur_pic.PicOrderCntMsb = prevPicOrderCntMsb; + + if (!sl->field_pic_flag) + { + seq->cur_pic.TopFieldOrderCnt = + seq->cur_pic.PicOrderCntMsb + sl->pic_order_cnt_lsb; + seq->cur_pic.BottomFieldOrderCnt = + seq->cur_pic.TopFieldOrderCnt + sl->delta_pic_order_cnt_bottom; + } + else + { + if (sl->bottom_field_flag) + seq->cur_pic.BottomFieldOrderCnt = + seq->cur_pic.PicOrderCntMsb + sl->pic_order_cnt_lsb; + else + seq->cur_pic.TopFieldOrderCnt = + seq->cur_pic.PicOrderCntMsb + sl->pic_order_cnt_lsb; + } + } + else + { + int16_t FrameNumOffset, prevFrameNumOffset; + uint16_t MaxFrameNum = 1 << (sp->log2_max_frame_num_minus4 + 4); + + if (sl->nal_unit_type == NAL_SLICE_IDR) + { + FrameNumOffset = 0; + } + else + { + if (seq->prevMMC5) + prevFrameNumOffset = 0; + else + prevFrameNumOffset = seq->prevFrameNumOffset; + + if (seq->prevFrameNum > sl->frame_num) + FrameNumOffset = prevFrameNumOffset + MaxFrameNum; + else + FrameNumOffset = prevFrameNumOffset; + } + + if (sp->pic_order_cnt_type == 1) + { + int16_t absFrameNum = 0, picOrderCntCycleCnt = + 0, frameNumInPicOrderCntCycle = 0, expectedDeltaPerPicOrderCntCycle = + 0, expectedPicOrderCnt = 0; + int i; + if (sp->num_ref_frames_in_pic_order_cnt_cycle) + absFrameNum = FrameNumOffset + sl->frame_num; + if (!sl->nal_ref_idc && (absFrameNum > 0)) + --absFrameNum; + + for (i = 0; i < sp->num_ref_frames_in_pic_order_cnt_cycle; i++) + expectedDeltaPerPicOrderCntCycle += sp->offset_for_ref_frame[i]; + + if (absFrameNum > 0) + { + picOrderCntCycleCnt = + (absFrameNum - 1) / sp->num_ref_frames_in_pic_order_cnt_cycle; + frameNumInPicOrderCntCycle = + (absFrameNum - 1) % sp->num_ref_frames_in_pic_order_cnt_cycle; + expectedPicOrderCnt = + picOrderCntCycleCnt * expectedDeltaPerPicOrderCntCycle; + for (i = 0; i < frameNumInPicOrderCntCycle; i++) + expectedPicOrderCnt += sp->offset_for_ref_frame[i]; + } + if (!sl->nal_ref_idc) + expectedPicOrderCnt += sp->offset_for_non_ref_pic; + + if (!sl->field_pic_flag) + { + seq->cur_pic.TopFieldOrderCnt = + expectedPicOrderCnt + sl->delta_pic_order_cnt[0]; + seq->cur_pic.BottomFieldOrderCnt = + seq->cur_pic.TopFieldOrderCnt + sp->offset_for_top_to_bottom_field + + sl->delta_pic_order_cnt[1]; + } + else if (!sl->bottom_field_flag) + seq->cur_pic.TopFieldOrderCnt = + expectedPicOrderCnt + sl->delta_pic_order_cnt[0]; + else + seq->cur_pic.BottomFieldOrderCnt = + expectedPicOrderCnt + sp->offset_for_top_to_bottom_field + + sl->delta_pic_order_cnt[1]; + } + else + { + int32_t tmpPicOrderCnt; + if (sl->nal_unit_type == NAL_SLICE_IDR) + tmpPicOrderCnt = 0; + else if (!sl->nal_ref_idc) + tmpPicOrderCnt = 2 * (FrameNumOffset + sl->frame_num) - 1; + else + tmpPicOrderCnt = 2 * (FrameNumOffset + sl->frame_num); + + if (!sl->field_pic_flag) + seq->cur_pic.TopFieldOrderCnt = seq->cur_pic.BottomFieldOrderCnt = + tmpPicOrderCnt; + else if (sl->bottom_field_flag) + seq->cur_pic.BottomFieldOrderCnt = tmpPicOrderCnt; + else + seq->cur_pic.TopFieldOrderCnt = tmpPicOrderCnt; + } + seq->prevFrameNum = seq->cur_pic.FrameNum; + seq->prevFrameNumOffset = FrameNumOffset; + } + + if (seq->cur_pic.completed < PICTURE_DONE) + { + if (sl->bottom_field_flag) + seq->cur_pic.TopFieldOrderCnt = seq->cur_pic.BottomFieldOrderCnt; + else + seq->cur_pic.BottomFieldOrderCnt = seq->cur_pic.TopFieldOrderCnt; + } +} + + + +static void +decode_picnum (vdpau_h264_alter_decoder_t * this_gen) +{ + sequence_t *seq = (sequence_t *) & this_gen->sequence; + slice_param_t *sl = &seq->slice_param; + dpb_frame_t *frame; + int i = 0; + + int parity = sl->bottom_field_flag ? 1 : 0; + + if (!seq->cur_pic.field_pic_flag) + seq->cur_pic.PicNum[0] = seq->cur_pic.FrameNum; + else + seq->cur_pic.PicNum[parity] = 2 * seq->cur_pic.FrameNum + 1; + + while (i < MAX_DPB_SIZE) + { + frame = seq->dpb[i]; + if (!frame->used) + break; + if (frame->FrameNum > seq->cur_pic.FrameNum) + frame->FrameNumWrap = frame->FrameNum - sl->MaxFrameNum; + else + frame->FrameNumWrap = frame->FrameNum; + + if (!sl->field_pic_flag) + { + frame->PicNum[0] = frame->PicNum[1] = frame->FrameNumWrap; + } + else + { + frame->PicNum[0] = 2 * frame->FrameNumWrap + (parity ? 0 : 1); + frame->PicNum[1] = 2 * frame->FrameNumWrap + (parity ? 1 : 0); + } + ++i; + } +} + + + +static int +check_ref_list (vdpau_h264_alter_decoder_t * this_gen) +{ + int i, j, bad_frame = 0; + dpb_frame_t *frame; + sequence_t *seq = (sequence_t *) & this_gen->sequence; + slice_param_t *sl = &seq->slice_param; + pic_param_t *pic = seq->pic_param[sl->pic_parameter_set_id]; + seq_param_t *sp = seq->seq_param[pic->seq_parameter_set_id]; + int prefs = 0; + int brefs = 0; + int poc, curpoc; + + //int fps = (double)sp->vui.time_scale / (double)sp->vui.num_units_in_tick / ( 2 - sl->field_pic_flag ); + int fps = (1 + sl->field_pic_flag) * 2 * sp->num_ref_frames; + + if (seq->startup_frame >= fps) + return 0; + + curpoc = + (seq->cur_pic.TopFieldOrderCnt > + seq->cur_pic.BottomFieldOrderCnt) ? seq->cur_pic.TopFieldOrderCnt : seq-> + cur_pic.BottomFieldOrderCnt; + + for (i = 15; i > -1; i--) + { + frame = seq->dpb[i]; + if (!frame->used) + continue; + poc = + (frame->TopFieldOrderCnt > + frame->BottomFieldOrderCnt) ? frame->TopFieldOrderCnt : frame-> + BottomFieldOrderCnt; + if (seq->cur_pic.field_pic_flag) + { + if (!frame->videoSurface->bad_frame) + { + for (j = 0; j < 2; j++) + { + if (frame->is_reference[j]) + { + if (poc <= curpoc) + ++prefs; + else + ++brefs; + } + } + } + } + else + { + if (!frame->videoSurface->bad_frame) + { + if (poc <= curpoc) + ++prefs; + else + ++brefs; + } + } + } + + if (sl->slice_type != SLICE_TYPE_I) + { + if (prefs < (sl->num_ref_idx_l0_active_minus1 + 1)) + bad_frame = 1; + if (sl->slice_type == SLICE_TYPE_B) + { + if (brefs < (sl->num_ref_idx_l1_active_minus1 + 1)) + bad_frame = 1; + } + } + + if (bad_frame) + fprintf (stderr, + "******** Missing refframes, dropping. nrf=%d lo=%d prefs=%d l1=%d brefs=%d type=%d (%d fps)\n", + sp->num_ref_frames, sl->num_ref_idx_l0_active_minus1 + 1, prefs, + sl->num_ref_idx_l1_active_minus1 + 1, brefs, sl->slice_type, + fps); + //else + //fprintf(stderr,"******** GOOD ! nrf=%d lo=%d prefs=%d l1=%d brefs=%d type=%d (%d fps)\n", sp->num_ref_frames, sl->num_ref_idx_l0_active_minus1 + 1, prefs, sl->num_ref_idx_l1_active_minus1 + 1, brefs, sl->slice_type, fps ); + + if (seq->cur_pic.is_reference[0] || seq->cur_pic.is_reference[1]) + ++seq->startup_frame; + + return bad_frame; +} + + + +static void +decode_render (vdpau_h264_alter_decoder_t * vd, int bad_frame) +{ + int i, j; + VdpPictureInfoH264 info; + seq_param_t *sp; + pic_param_t *pic; + slice_param_t *sl; + sequence_t *seq = (sequence_t *) & vd->sequence; + vo_frame_t *img; + + if (!seq->cur_pic.field_pic_flag || (seq->cur_pic.completed < PICTURE_DONE)) + { + img = + vd->stream->video_out->get_frame (vd->stream->video_out, + seq->coded_width, seq->coded_height, + seq->ratio, XINE_IMGFMT_VDPAU, + VO_BOTH_FIELDS | seq->chroma | seq-> + reset); + seq->reset = 0; + img->drawn = 0; + } + else + img = seq->cur_pic.videoSurface; + + if (!img) + { /* should not happen */ + fprintf (stderr, + "vdpau_h264_alter : !!!!!!!!!!!!!!!!!!!!!! No vo_frame_t !!!!!!!!!!!!!!!!!!!!!!!\n"); + return; + } + + vdpau_accel_t *accel = (vdpau_accel_t *) img->accel_data; + if (!seq->accel_vdpau) + seq->accel_vdpau = accel; + + if (seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr)) + vd->decoder = VDP_INVALID_HANDLE; + + sl = &vd->sequence.slice_param; + pic = vd->sequence.pic_param[sl->pic_parameter_set_id]; + sp = vd->sequence.seq_param[pic->seq_parameter_set_id]; + + VdpStatus st; + if (vd->decoder == VDP_INVALID_HANDLE || vd->decoder_profile != seq->profile + || vd->decoder_width != seq->coded_width + || vd->decoder_height != seq->coded_height) + { + if (vd->decoder != VDP_INVALID_HANDLE) + { + accel->vdp_decoder_destroy (vd->decoder); + vd->decoder = VDP_INVALID_HANDLE; + } + st = + accel->vdp_decoder_create (accel->vdp_device, seq->profile, + seq->coded_width, seq->coded_height, + sp->num_ref_frames, &vd->decoder); + if (st != VDP_STATUS_OK) + fprintf (stderr, "vdpau_h264_alter : failed to create decoder !! %s\n", + accel->vdp_get_error_string (st)); + else + { + vd->decoder_profile = seq->profile; + vd->decoder_width = seq->coded_width; + vd->decoder_height = seq->coded_height; + seq->vdp_runtime_nr = seq->accel_vdpau->vdp_runtime_nr; + } + } + + info.slice_count = seq->slices_count; + info.field_order_cnt[0] = seq->cur_pic.TopFieldOrderCnt; + info.field_order_cnt[1] = seq->cur_pic.BottomFieldOrderCnt; + info.is_reference = sl->nal_ref_idc ? VDP_TRUE : VDP_FALSE; + info.frame_num = sl->frame_num; + info.field_pic_flag = sl->field_pic_flag; + info.bottom_field_flag = sl->bottom_field_flag; + info.num_ref_frames = sp->num_ref_frames; + info.mb_adaptive_frame_field_flag = sp->mb_adaptive_frame_field_flag + && !sl->field_pic_flag; + info.constrained_intra_pred_flag = pic->constrained_intra_pred_flag; + info.weighted_pred_flag = pic->weighted_pred_flag; + info.weighted_bipred_idc = pic->weighted_bipred_idc; + info.frame_mbs_only_flag = sp->frame_mbs_only_flag; + info.transform_8x8_mode_flag = pic->transform_8x8_mode_flag; + info.chroma_qp_index_offset = pic->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.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.log2_max_frame_num_minus4 = sp->log2_max_frame_num_minus4; + info.pic_order_cnt_type = sp->pic_order_cnt_type; + info.log2_max_pic_order_cnt_lsb_minus4 = + sp->log2_max_pic_order_cnt_lsb_minus4; + info.delta_pic_order_always_zero_flag = + sp->delta_pic_order_always_zero_flag; + info.direct_8x8_inference_flag = sp->direct_8x8_inference_flag; + info.entropy_coding_mode_flag = pic->entropy_coding_mode_flag; + info.pic_order_present_flag = pic->pic_order_present_flag; + info.deblocking_filter_control_present_flag = + pic->deblocking_filter_control_present_flag; + info.redundant_pic_cnt_present_flag = pic->redundant_pic_cnt_present_flag; + + if (!pic->pic_scaling_matrix_present_flag) + { + xine_fast_memcpy (info.scaling_lists_4x4, sp->scaling_lists_4x4, + sizeof (info.scaling_lists_4x4)); + xine_fast_memcpy (info.scaling_lists_8x8, sp->scaling_lists_8x8, + sizeof (info.scaling_lists_8x8)); + } + else + { + xine_fast_memcpy (info.scaling_lists_4x4, pic->scaling_lists_4x4, + sizeof (info.scaling_lists_4x4)); + xine_fast_memcpy (info.scaling_lists_8x8, pic->scaling_lists_8x8, + sizeof (info.scaling_lists_8x8)); + } + + j = 0; + for (i = (MAX_DPB_SIZE - 1); i > -1; i--) + { + if (!seq->dpb[i]->used) + continue; + vdpau_accel_t *accel = + (vdpau_accel_t *) seq->dpb[i]->videoSurface->accel_data; + info.referenceFrames[j].surface = accel->surface; + info.referenceFrames[j].is_long_term = 0; + info.referenceFrames[j].frame_idx = seq->dpb[i]->FrameNum; + info.referenceFrames[j].top_is_reference = + seq->dpb[i]->is_reference[0] ? VDP_TRUE : VDP_FALSE; + info.referenceFrames[j].bottom_is_reference = + seq->dpb[i]->is_reference[1] ? VDP_TRUE : VDP_FALSE; + info.referenceFrames[j].field_order_cnt[0] = + seq->dpb[i]->TopFieldOrderCnt; + info.referenceFrames[j].field_order_cnt[1] = + seq->dpb[i]->BottomFieldOrderCnt; + ++j; + } + for (; j < MAX_DPB_SIZE; j++) + { + info.referenceFrames[j].surface = VDP_INVALID_HANDLE; + info.referenceFrames[j].is_long_term = 0; + info.referenceFrames[j].frame_idx = 0; + info.referenceFrames[j].top_is_reference = 0; + info.referenceFrames[j].bottom_is_reference = 0; + info.referenceFrames[j].field_order_cnt[0] = 0; + info.referenceFrames[j].field_order_cnt[1] = 0; + } + + uint8_t sc[3] = { 0, 0, 1 }; + VdpBitstreamBuffer vbits[seq->slices_count * 2]; + for (i = 0; i < seq->slices_count; i++) + { + vbits[i * 2].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbits[i * 2].bitstream = sc; + vbits[i * 2].bitstream_bytes = 3; + vbits[(i * 2) + 1].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbits[(i * 2) + 1].bitstream = seq->buf + seq->slices[i].buf_offset; + vbits[(i * 2) + 1].bitstream_bytes = seq->slices[i].len; + } + st = + accel->vdp_decoder_render (vd->decoder, accel->surface, + (VdpPictureInfo *) & info, + seq->slices_count * 2, vbits); + if (st != VDP_STATUS_OK) + lprintf ("**********************DECODING failed! - surface = %d - %s\n", + accel->surface, accel->vdp_get_error_string (st)); + else + lprintf ("**********************DECODING success! - surface = %d\n", + accel->surface); + + if ((seq->ratio != seq->reported_ratio) + || (seq->coded_width != seq->reported_coded_width) + || (seq->coded_height != seq->reported_coded_height) + || (seq->video_step != seq->reported_video_step)) + { + seq->reported_ratio = seq->ratio; + seq->reported_coded_width = seq->coded_width; + seq->reported_coded_height = seq->coded_height; + seq->reported_video_step = seq->video_step; + _x_stream_info_set (vd->stream, XINE_STREAM_INFO_VIDEO_WIDTH, + seq->coded_width); + _x_stream_info_set (vd->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, + seq->coded_height); + _x_stream_info_set (vd->stream, XINE_STREAM_INFO_VIDEO_RATIO, + ((double) 10000 * seq->ratio)); + _x_stream_info_set (vd->stream, XINE_STREAM_INFO_FRAME_DURATION, + seq->video_step); + _x_meta_info_set_utf8 (vd->stream, XINE_META_INFO_VIDEOCODEC, + "H264/AVC (vdpau_alter)"); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = vd->stream; + event.data = &data; + event.data_length = sizeof (data); + data.width = seq->coded_width; + data.height = seq->coded_height; + data.aspect = seq->ratio; + xine_event_send (vd->stream, &event); + } + + accel->color_standard = seq->color_standard; + + if (seq->cur_pic.completed == PICTURE_DONE) + { + seq->cur_pic.pts = seq->pic_pts; + seq->pic_pts = 0; + } + if (seq->cur_pic.drop_pts) + seq->cur_pic.pts = 0; + if (sp->frame_mbs_only_flag) + img->progressive_frame = -1; + img->bad_frame = bad_frame; + img->duration = seq->video_step; + seq->cur_pic.videoSurface = img; +} + + + +static void +decode_picture (vdpau_h264_alter_decoder_t * decoder) +{ + if (decoder->sequence.cur_pic.missing_header + || !decoder->sequence.startup_frame) + { + memset (&decoder->sequence.cur_pic, 0, sizeof (dpb_frame_t)); + lprintf ("MISSING_HEADER or !startup_frame\n\n"); + return; + } + + slice_param_t *sl = &decoder->sequence.slice_param; + dpb_frame_t *cur_pic = &decoder->sequence.cur_pic; + + if (cur_pic->completed && cur_pic->field_pic_flag) + { + int wrong_field = 0; + if ((sl->frame_num != cur_pic->FrameNum) + || (sl->bottom_field_flag + && (cur_pic->completed == PICTURE_BOTTOM_DONE)) + || (!sl->bottom_field_flag + && (cur_pic->completed == PICTURE_TOP_DONE)) + || !sl->field_pic_flag) + { + wrong_field = 1; + } + if (wrong_field) + { + fprintf (stderr, "vdpau_h264_alter : Wrong field, skipping.\n"); + memset (cur_pic, 0, sizeof (dpb_frame_t)); + dpb_reset (&decoder->sequence); + cur_pic->missing_header = 1; + decoder->sequence.startup_frame = 0; + return; + } + } + + /* picture decoding */ + decode_poc (decoder); + lprintf ("TopFieldOrderCnt = %d - BottomFieldOrderCnt = %d\n", + cur_pic->TopFieldOrderCnt, cur_pic->BottomFieldOrderCnt); + if (sl->nal_unit_type == 5) + { + dpb_draw_frames (decoder, MAX_POC, DPB_DRAW_CLEAR); + decoder->sequence.startup_frame = START_IDR_FLAG; + } + decode_picnum (decoder); + ref_pic_list_reordering (decoder); + lprintf ("............................. slices_count = %d\n", + decoder->sequence.slices_count); + + decode_render (decoder, check_ref_list (decoder)); + + /* dec_ref_pic_marking */ + slice_header_post (decoder); + + if (!cur_pic->is_reference[0] && !cur_pic->is_reference[1]) + { + if (cur_pic->completed == PICTURE_DONE) + { + dpb_draw_frames (decoder, + (cur_pic->TopFieldOrderCnt > + cur_pic->BottomFieldOrderCnt) ? cur_pic-> + TopFieldOrderCnt : cur_pic->BottomFieldOrderCnt, + DPB_DRAW_CURRENT); + } + } + else + { + if (decoder->sequence. + seq_param[decoder->sequence.pic_param[sl->pic_parameter_set_id]-> + seq_parameter_set_id]->pic_order_cnt_type == 2) + dpb_draw_frames (decoder, + (cur_pic->TopFieldOrderCnt > + cur_pic->BottomFieldOrderCnt) ? cur_pic-> + TopFieldOrderCnt : cur_pic->BottomFieldOrderCnt, + DPB_DRAW_REFS); + + if (!sl->field_pic_flag || cur_pic->completed < PICTURE_DONE) + dbp_append (decoder, 0); + else + dbp_append (decoder, 1); + } + + if (cur_pic->completed == PICTURE_DONE) + memset (cur_pic, 0, sizeof (dpb_frame_t)); + + + lprintf + ("\n___________________________________________________________________________________________\n\n"); +} + + + +static int +parse_startcodes (vdpau_h264_alter_decoder_t * this_gen, uint8_t * buf, + uint32_t len) +{ + sequence_t *sequence = (sequence_t *) & this_gen->sequence; + bits_reader_set (&sequence->br, buf, len); + int ret = 0; + + skip_bits (&sequence->br, 1); /* forbidden_zero_bit */ + uint8_t nal_ref_idc = read_bits (&sequence->br, 2); + uint8_t nal_unit_type = read_bits (&sequence->br, 5); + lprintf ("NAL size = %d, nal_ref_idc = %d, nal_unit_type = %d\n", len, + nal_ref_idc, nal_unit_type); + + switch (nal_unit_type) + { + case NAL_END_SEQUENCE: + break; + case NAL_SEQUENCE: + seq_parameter_set_data (this_gen); + break; + case NAL_PICTURE: + pic_parameter_set (this_gen); + break; + case NAL_SLICE_IDR: + slice_header (this_gen, nal_ref_idc, nal_unit_type); + sequence->slices[sequence->slices_count].buf_offset = buf - sequence->buf; + sequence->slices[sequence->slices_count].len = len; + ++sequence->slices_count; + sequence->slice_mode = NAL_SLICE_IDR; + break; + case NAL_SLICE_NO_IDR: + slice_header (this_gen, nal_ref_idc, nal_unit_type); + sequence->slices[sequence->slices_count].buf_offset = buf - sequence->buf; + sequence->slices[sequence->slices_count].len = len; + ++sequence->slices_count; + sequence->slice_mode = NAL_SLICE_NO_IDR; + break; + } + + return ret; +} + + + +static void +parse_codec_private (vdpau_h264_alter_decoder_t * this_gen, uint8_t * buf, + uint32_t len) +{ + sequence_t *sequence = (sequence_t *) & this_gen->sequence; + bits_reader_set (&sequence->br, buf, len); + uint8_t *buffer = buf; + int i; + + lprintf ("parse_codec_private\n"); + + sequence->mode_frame = 1; + + // reserved + skip_bits (&sequence->br, 8); + skip_bits (&sequence->br, 8); /* profile_idc */ + skip_bits (&sequence->br, 8); + skip_bits (&sequence->br, 8); /* level_idc */ + skip_bits (&sequence->br, 6); + + sequence->frame_header_size = read_bits (&sequence->br, 2) + 1; + //sequence->frame_header_size = 3; + skip_bits (&sequence->br, 3); + uint8_t count = read_bits (&sequence->br, 5); + buffer += 6; + for (i = 0; i < count; i++) + { + bits_reader_set (&sequence->br, buffer, len - (buffer - buf)); + uint16_t sps_size = read_bits (&sequence->br, 16); + skip_bits (&sequence->br, 8); + seq_parameter_set_data (this_gen); + buffer += sps_size + 2; + } + count = buffer[0]; + ++buffer; + for (i = 0; i < count; i++) + { + bits_reader_set (&sequence->br, buffer, len - (buffer - buf)); + uint16_t pps_size = read_bits (&sequence->br, 16); + skip_bits (&sequence->br, 8); + pic_parameter_set (this_gen); + buffer += pps_size + 2; + } +} + + + +static void +flush_buffer (sequence_t * seq) +{ + if ((seq->bufpos - seq->bufseek) >= seq->bufseek) + { + seq->bufsize = (seq->bufpos - seq->bufseek) + MIN_BUFFER_SIZE; + lprintf ("buffer too short, have to allocate a new one.\n"); + uint8_t *tmp = (uint8_t *) malloc (seq->bufsize); + xine_fast_memcpy (tmp, seq->buf + seq->bufseek, + seq->bufpos - seq->bufseek); + free (seq->buf); + seq->buf = tmp; + } + else + xine_fast_memcpy (seq->buf, seq->buf + seq->bufseek, + seq->bufpos - seq->bufseek); + + seq->bufpos -= seq->bufseek; + seq->start = -1; + seq->bufseek = 0; + reset_slices (seq); +} + + + +/* + * This function receives a buffer of data from the demuxer layer and + * figures out how to handle it based on its header flags. + */ +static void +vdpau_h264_alter_decode_data (video_decoder_t * this_gen, buf_element_t * buf) +{ + vdpau_h264_alter_decoder_t *this = (vdpau_h264_alter_decoder_t *) this_gen; + sequence_t *seq = (sequence_t *) & this->sequence; + +#ifdef MAKE_DAT + fwrite (buf->content, 1, buf->size, outfile); +#endif + + if (buf->decoder_flags & BUF_FLAG_FRAMERATE) + { + lprintf ("BUF_FLAG_FRAMERATE\n"); + seq->video_step = buf->decoder_info[0]; + } + + if (buf->decoder_flags & BUF_FLAG_ASPECT) + { + lprintf ("BUF_FLAG_ASPECT\n"); + seq->ratio = + (double) buf->decoder_info[1] / (double) buf->decoder_info[2]; + } + + if (buf->decoder_flags & BUF_FLAG_STDHEADER) + { + lprintf ("BUF_FLAG_STDHEADER\n"); + seq->flag_header = 1; + xine_bmiheader *bih = (xine_bmiheader *) buf->content; + seq->coded_width = bih->biWidth; + seq->coded_height = bih->biHeight; + uint8_t *codec_private = buf->content + sizeof (xine_bmiheader); + uint32_t codec_private_len = bih->biSize - sizeof (xine_bmiheader); + if (codec_private_len > 0) + parse_codec_private (this, codec_private, codec_private_len); + return; + } + + if (buf->decoder_flags & BUF_FLAG_SPECIAL) + { + if (buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG) + { + lprintf ("BUF_SPECIAL_DECODER_CONFIG\n"); + seq->flag_header = 1; + uint8_t *codec_private = buf->decoder_info_ptr[2]; + uint32_t codec_private_len = buf->decoder_info[2]; + if (codec_private_len > 0) + parse_codec_private (this, codec_private, codec_private_len); + } + return; + } + + if (!buf->size) + return; + + int size = seq->bufpos + buf->size; + if (seq->bufsize < size) + { + if (seq->bufsize > MAX_BUFFER_SIZE) + { + fprintf (stderr, + "vdpau_h264_alter : sorry, can't accumulate so much data, broken stream?\n"); + reset_sequence (seq); + return; + } + seq->bufsize = size + MIN_BUFFER_SIZE; + seq->buf = (uint8_t *) realloc (seq->buf, seq->bufsize); + lprintf ("realloc new size = %d\n", seq->bufsize); + } + xine_fast_memcpy (seq->buf + seq->bufpos, buf->content, buf->size); + seq->bufpos += buf->size; + + if (buf->decoder_flags & BUF_FLAG_FRAME_START) + seq->pic_pts = buf->pts; + + int frame_end = buf->decoder_flags & BUF_FLAG_FRAME_END; + + if (seq->mode_frame) + { + if (!seq->pic_pts) + seq->pic_pts = buf->pts; + if (frame_end) + { + if (buf->pts) + seq->pic_pts = buf->pts; + lprintf ("frame_end && seq->mode_frame\n"); + int fhs; + uint8_t tb; + uint32_t j = 0; + while (j < seq->bufpos) + { + uint32_t s = 0; + for (fhs = 0; fhs < seq->frame_header_size; fhs++) + s |= seq->buf[j + fhs] << (8 * (seq->frame_header_size - 1 - fhs)); + tb = *(seq->buf + j + seq->frame_header_size) & 0x1F; + if (seq->slice_mode && (tb != seq->slice_mode)) + { + decode_picture (this); + reset_slices (seq); + } + parse_startcodes (this, seq->buf + j + seq->frame_header_size, s); + j += seq->frame_header_size + s; + } + if (seq->slice_mode) + { + decode_picture (this); + reset_slices (seq); + } + seq->bufpos = 0; + } + return; + } + + while (seq->bufseek <= seq->bufpos - 4) + { + uint8_t *buffer = seq->buf + seq->bufseek; + if (buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 1) + { + if (seq->start < 0) + { + seq->start = seq->bufseek; + uint8_t tb = buffer[3] & 0x1F; + if (((tb == NAL_SLICE_NO_IDR) || (tb == NAL_SLICE_IDR)) + && !seq->pic_pts) + seq->pic_pts = buf->pts; + if (seq->slice_mode && (tb != seq->slice_mode)) + { + decode_picture (this); + flush_buffer (seq); + } + if ((tb & 0x1F) == NAL_END_SEQUENCE) + { + dpb_print (seq); + dpb_draw_frames (this, MAX_POC, DPB_DRAW_CLEAR); + lprintf ("NAL_END_SEQUENCE\n"); + dpb_print (seq); + } + } + else + { + parse_startcodes (this, seq->buf + seq->start + 3, + seq->bufseek - seq->start - 3); + seq->start = -1; + --seq->bufseek; + } + } + ++seq->bufseek; + } + + if (frame_end && seq->flag_header && (seq->start > -1) + && (seq->bufseek > seq->start)) + { + lprintf ("frame_end && seq->start\n"); + seq->bufseek = seq->bufpos; + parse_startcodes (this, seq->buf + seq->start + 3, + seq->bufseek - seq->start - 3); + if (seq->slice_mode) + decode_picture (this); + flush_buffer (seq); + } +} + + +/* + * This function is called when xine needs to flush the system. + */ +static void +vdpau_h264_alter_flush (video_decoder_t * this_gen) +{ + vdpau_h264_alter_decoder_t *this = (vdpau_h264_alter_decoder_t *) this_gen; + + printf ("vdpau_h264_alter_flush\n"); + dpb_draw_frames (this, MAX_POC, DPB_DRAW_REFS); +} + + +/* + * This function resets the video decoder. + */ +static void +vdpau_h264_alter_reset (video_decoder_t * this_gen) +{ + vdpau_h264_alter_decoder_t *this = (vdpau_h264_alter_decoder_t *) this_gen; + + lprintf ("vdpau_h264_alter_reset\n"); + reset_sequence (&this->sequence); +} + + +/* + * The decoder should forget any stored pts values here. + */ +static void +vdpau_h264_alter_discontinuity (video_decoder_t * this_gen) +{ + vdpau_h264_alter_decoder_t *this = (vdpau_h264_alter_decoder_t *) this_gen; + printf ("vdpau_h264_alter_discontinuity\n"); + + dpb_clear_all_pts (&this->sequence); + this->sequence.reset = VO_NEW_SEQUENCE_FLAG; +} + + +/* + * This function frees the video decoder instance allocated to the decoder. + */ +static void +vdpau_h264_alter_dispose (video_decoder_t * this_gen) +{ + + vdpau_h264_alter_decoder_t *this = (vdpau_h264_alter_decoder_t *) this_gen; + + lprintf ("vdpau_h264_alter_dispose\n"); + + if ((this->decoder != VDP_INVALID_HANDLE) && this->sequence.accel_vdpau) + { + this->sequence.accel_vdpau->vdp_decoder_destroy (this->decoder); + this->decoder = VDP_INVALID_HANDLE; + } + reset_sequence (&this->sequence); + + int i; + for (i = 0; i < MAX_DPB_SIZE; i++) + free (this->sequence.dpb[i]); + for (i = 0; i < 32; i++) + if (this->sequence.seq_param[i]) + free (this->sequence.seq_param[i]); + for (i = 0; i < 255; i++) + if (this->sequence.pic_param[i]) + free (this->sequence.pic_param[i]); + + this->stream->video_out->close (this->stream->video_out, this->stream); + + free (this->sequence.buf); + free (this_gen); +} + + +/* + * This function allocates, initializes, and returns a private video + * decoder structure. + */ +static video_decoder_t * +open_plugin (video_decoder_class_t * class_gen, xine_stream_t * stream) +{ + + vdpau_h264_alter_decoder_t *this; + + /* the videoout must be vdpau-capable to support this decoder */ + if (! + (stream->video_driver-> + get_capabilities (stream->video_driver) & VO_CAP_VDPAU_H264)) + return NULL; + + /* now check if vdpau has free decoder resource */ + vo_frame_t *img = + stream->video_out->get_frame (stream->video_out, 1920, 1080, 1, + XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + vdpau_accel_t *accel = (vdpau_accel_t *) img->accel_data; + int runtime_nr = accel->vdp_runtime_nr; + img->free (img); + VdpDecoder decoder; + VdpStatus st = + accel->vdp_decoder_create (accel->vdp_device, + VDP_DECODER_PROFILE_H264_MAIN, 1920, 1080, 16, + &decoder); + if (st != VDP_STATUS_OK) + { + fprintf (stderr, "can't create vdpau decoder!\n"); + return NULL; + } + + accel->vdp_decoder_destroy (decoder); + + this = + (vdpau_h264_alter_decoder_t *) calloc (1, + sizeof + (vdpau_h264_alter_decoder_t)); + + this->video_decoder.decode_data = vdpau_h264_alter_decode_data; + this->video_decoder.flush = vdpau_h264_alter_flush; + this->video_decoder.reset = vdpau_h264_alter_reset; + this->video_decoder.discontinuity = vdpau_h264_alter_discontinuity; + this->video_decoder.dispose = vdpau_h264_alter_dispose; + + this->stream = stream; + this->class = (vdpau_h264_alter_class_t *) class_gen; + + int i; + for (i = 0; i < 16; i++) + this->sequence.dpb[i] = (dpb_frame_t *) calloc (1, sizeof (dpb_frame_t)); + this->sequence.bufsize = MIN_BUFFER_SIZE; + this->sequence.buf = (uint8_t *) malloc (this->sequence.bufsize); + this->sequence.vdp_runtime_nr = runtime_nr; + this->sequence.reset = VO_NEW_SEQUENCE_FLAG; + this->sequence.reset = VO_NEW_SEQUENCE_FLAG; + this->sequence.ratio = 0.0; + this->sequence.video_step = 3600; + this->sequence.coded_width = 1280; + this->sequence.coded_height = 720; + this->sequence.reported_ratio = 0.0; + this->sequence.reported_video_step = 0; + this->sequence.reported_coded_width = 0; + this->sequence.reported_coded_height = 0; + this->sequence.frame_header_size = 4; + this->sequence.flag_header = 0; + this->sequence.mode_frame = 0; + reset_sequence (&this->sequence); + + this->decoder = VDP_INVALID_HANDLE; + this->sequence.accel_vdpau = NULL; + + (stream->video_out->open) (stream->video_out, stream); + +#ifdef MAKE_DAT + outfile = fopen ("/tmp/h264.dat", "w"); + nframes = 0; +#endif + + return &this->video_decoder; +} + + +/* + * This function allocates a private video decoder class and initializes + * the class's member functions. + */ +static void * +init_plugin (xine_t * xine, void *data) +{ + + vdpau_h264_alter_class_t *this; + + this = + (vdpau_h264_alter_class_t *) calloc (1, + sizeof (vdpau_h264_alter_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.identifier = "vdpau_h264_alter"; + this->decoder_class.description = + N_ + ("vdpau_h264_alter: H264 decoder plugin using VDPAU hardware decoding.\n" + "Must be used along with video_out_vdpau."); + this->decoder_class.dispose = default_video_decoder_class_dispose; + + return this; +} + + +/* + * This is a list of all of the internal xine video buffer types that + * this decoder is able to handle. Check src/xine-engine/buffer.h for a + * list of valid buffer types (and add a new one if the one you need does + * not exist). Terminate the list with a 0. + */ +static const uint32_t video_types[] = { + BUF_VIDEO_H264, + 0 +}; + + +/* + * This data structure combines the list of supported xine buffer types and + * the priority that the plugin should be given with respect to other + * plugins that handle the same buffer type. A plugin with priority (n+1) + * will be used instead of a plugin with priority (n). + */ +static const decoder_info_t dec_info_video = { + video_types, /* supported types */ + 9 /* priority */ +}; + + +/* + * The plugin catalog entry. This is the only information that this plugin + * will export to the public. + */ +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* { type, API, "name", version, special_info, init_function } */ + {PLUGIN_VIDEO_DECODER, 19, "vdpau_h264_alter", XINE_VERSION_CODE, + &dec_info_video, init_plugin}, + {PLUGIN_NONE, 0, "", 0, NULL, NULL} +}; diff --git a/src/video_dec/libvdpau/alterh264_decode.h b/src/video_dec/libvdpau/alterh264_decode.h new file mode 100644 index 000000000..88f5e638f --- /dev/null +++ b/src/video_dec/libvdpau/alterh264_decode.h @@ -0,0 +1,339 @@ +/* kate: tab-indent on; indent-width 4; mixedindent off; indent-mode cstyle; remove-trailing-space on; */ +#ifndef ALTERH264_DECODE_H +#define ALTERH264_DECODE_H + +//#define LOG +#define LOG_MODULE "vdpau_h264" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> + +#include <xine/xine_internal.h> +#include <xine/video_out.h> +#include <xine/buffer.h> +#include <xine/xineutils.h> +#include "accel_vdpau.h" +#include <vdpau/vdpau.h> + +#include "alterh264_bits_reader.h" + + + +enum aspect_ratio +{ + ASPECT_UNSPECIFIED = 0, + ASPECT_1_1, + ASPECT_12_11, + ASPECT_10_11, + ASPECT_16_11, + ASPECT_40_33, + ASPECT_24_11, + ASPECT_20_11, + ASPECT_32_11, + ASPECT_80_33, + ASPECT_18_11, + ASPECT_15_11, + ASPECT_64_33, + ASPECT_160_99, + ASPECT_4_3, + ASPECT_3_2, + ASPECT_2_1, + ASPECT_RESERVED, + ASPECT_EXTENDED_SAR = 255 +}; + + + +static const uint8_t zigzag_4x4[16] = { + 0, 1, 4, 8, + 5, 2, 3, 6, + 9, 12, 13, 10, + 7, 11, 14, 15 +}; + +static const uint8_t zigzag_8x8[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + +static const uint8_t default_4x4_intra[16] = { + 6, 13, 13, 20, + 20, 20, 28, 28, + 28, 28, 32, 32, + 32, 37, 37, 42 +}; + +static const uint8_t default_4x4_inter[16] = { + 10, 14, 14, 20, + 20, 20, 24, 24, + 24, 24, 27, 27, + 27, 30, 30, 34 +}; + +static const uint8_t default_8x8_intra[64] = { + 6, 10, 10, 13, 11, 13, 16, 16, + 16, 16, 18, 18, 18, 18, 18, 23, + 23, 23, 23, 23, 23, 25, 25, 25, + 25, 25, 25, 25, 27, 27, 27, 27, + 27, 27, 27, 27, 29, 29, 29, 29, + 29, 29, 29, 31, 31, 31, 31, 31, + 31, 33, 33, 33, 33, 33, 36, 36, + 36, 36, 38, 38, 38, 40, 40, 42 +}; + +static const uint8_t default_8x8_inter[64] = { + 9, 13, 13, 15, 13, 15, 17, 17, + 17, 17, 19, 19, 19, 19, 19, 21, + 21, 21, 21, 21, 21, 22, 22, 22, + 22, 22, 22, 22, 24, 24, 24, 24, + 24, 24, 24, 24, 25, 25, 25, 25, + 25, 25, 25, 27, 27, 27, 27, 27, + 27, 28, 28, 28, 28, 28, 30, 30, + 30, 30, 32, 32, 32, 33, 33, 35 +}; + + + +typedef struct +{ + uint8_t aspect_ratio_info; + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + uint8_t colour_desc; + uint8_t colour_primaries; + uint8_t timing_info; + uint32_t num_units_in_tick; + uint32_t time_scale; +} vui_param_t; + + + +typedef struct +{ + uint8_t profile_idc; + uint8_t level_idc; + uint8_t seq_parameter_set_id; + uint8_t constraint_set0_flag; + uint8_t constraint_set1_flag; + uint8_t constraint_set2_flag; + uint8_t constraint_set3_flag; + uint8_t chroma_format_idc; + uint8_t separate_colour_plane_flag; + uint8_t bit_depth_luma_minus8; + uint8_t bit_depth_chroma_minus8; + uint8_t qpprime_y_zero_transform_bypass_flag; + uint8_t seq_scaling_matrix_present_flag; + uint8_t scaling_lists_4x4[6][16]; + uint8_t scaling_lists_8x8[2][64]; + uint8_t log2_max_frame_num_minus4; + uint8_t pic_order_cnt_type; + uint8_t log2_max_pic_order_cnt_lsb_minus4; + uint8_t delta_pic_order_always_zero_flag; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint8_t num_ref_frames_in_pic_order_cnt_cycle; + int32_t offset_for_ref_frame[256]; + uint8_t num_ref_frames; + uint8_t gaps_in_frame_num_value_allowed_flag; + uint8_t pic_width_in_mbs_minus1; + uint8_t pic_height_in_map_units_minus1; + uint8_t frame_mbs_only_flag; + uint8_t mb_adaptive_frame_field_flag; + uint8_t direct_8x8_inference_flag; + uint8_t frame_cropping_flag; + uint16_t frame_crop_left_offset; + uint16_t frame_crop_right_offset; + uint16_t frame_crop_top_offset; + uint16_t frame_crop_bottom_offset; + uint8_t vui_parameters_present_flag; + vui_param_t vui; +} seq_param_t; + + + +typedef struct +{ + uint8_t pic_parameter_set_id; + uint8_t seq_parameter_set_id; + uint8_t entropy_coding_mode_flag; + uint8_t pic_order_present_flag; + /*uint8_t num_slice_groups_minus1; + uint8_t slice_group_map_type; + uint16_t run_length_minus1[64]; + uint16_t top_left[64]; + uint16_t bottom_right[64]; + uint8_t slice_group_change_direction_flag; + uint16_t slice_group_change_rate_minus1; + uint16_t pic_size_in_map_units_minus1; + uint8_t slice_group_id[64]; */ + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_idc; + int8_t pic_init_qp_minus26; + int8_t pic_init_qs_minus26; + int8_t chroma_qp_index_offset; + uint8_t deblocking_filter_control_present_flag; + uint8_t constrained_intra_pred_flag; + uint8_t redundant_pic_cnt_present_flag; + uint8_t transform_8x8_mode_flag; + uint8_t pic_scaling_matrix_present_flag; + uint8_t pic_scaling_list_present_flag[8]; + uint8_t scaling_lists_4x4[6][16]; + uint8_t scaling_lists_8x8[2][64]; + int8_t second_chroma_qp_index_offset; +} pic_param_t; + + + +typedef struct +{ + uint8_t nal_ref_idc; + uint8_t nal_unit_type; + uint8_t slice_type; + uint8_t pic_parameter_set_id; + uint16_t frame_num; + uint32_t MaxFrameNum; + uint8_t field_pic_flag; + uint8_t bottom_field_flag; + uint16_t idr_pic_id; + uint16_t pic_order_cnt_lsb; + int32_t delta_pic_order_cnt_bottom; + int32_t delta_pic_order_cnt[2]; + uint8_t redundant_pic_cnt; + uint8_t num_ref_idx_l0_active_minus1; + uint8_t num_ref_idx_l1_active_minus1; +} slice_param_t; + + +#define PICTURE_TOP_DONE 1 +#define PICTURE_BOTTOM_DONE 2 +#define PICTURE_DONE 3 + +#define SHORT_TERM_REF 1 +#define LONG_TERM_REF 2 + +typedef struct +{ + uint8_t used; + uint8_t missing_header; + int64_t pts; + uint8_t drop_pts; + uint8_t completed; + uint8_t top_field_first; + uint16_t FrameNum; + int32_t FrameNumWrap; + int32_t PicNum[2]; /* 0:top, 1:bottom */ + uint8_t is_reference[2]; /* 0:top, 1:bottom, short or long term */ + uint8_t field_pic_flag; + int32_t PicOrderCntMsb; + int32_t TopFieldOrderCnt; + int32_t BottomFieldOrderCnt; + uint16_t pic_order_cnt_lsb; + uint8_t mmc5; + + vo_frame_t *videoSurface; +} dpb_frame_t; + + + +typedef struct +{ + uint32_t buf_offset; + uint32_t len; +} slice_t; + + + +typedef struct +{ + uint32_t coded_width; + uint32_t reported_coded_width; + uint32_t coded_height; + uint32_t reported_coded_height; + uint64_t video_step; /* frame duration in pts units */ + uint64_t reported_video_step; /* frame duration in pts units */ + double ratio; + double reported_ratio; + + slice_t slices[68]; + int slices_count; + int slice_mode; + + seq_param_t *seq_param[32]; + pic_param_t *pic_param[256]; + slice_param_t slice_param; + + dpb_frame_t *dpb[16]; + dpb_frame_t cur_pic; + uint16_t prevFrameNum; + uint16_t prevFrameNumOffset; + uint8_t prevMMC5; + + VdpColorStandard color_standard; + int chroma; + int top_field_first; + VdpDecoderProfile profile; + + uint8_t *buf; /* accumulate data */ + int bufseek; + uint32_t bufsize; + uint32_t bufpos; + int start; + + int64_t pic_pts; + + bits_reader_t br; + + int vdp_runtime_nr; + vdpau_accel_t *accel_vdpau; + + int reset; + int startup_frame; + + uint8_t mode_frame; + uint8_t flag_header; + uint32_t frame_header_size; + +} sequence_t; + + + +typedef struct +{ + video_decoder_class_t decoder_class; +} vdpau_h264_alter_class_t; + + + +typedef struct vdpau_mpeg12_decoder_s +{ + video_decoder_t video_decoder; /* parent video decoder structure */ + + vdpau_h264_alter_class_t *class; + xine_stream_t *stream; + + sequence_t sequence; + + VdpDecoder decoder; + VdpDecoderProfile decoder_profile; + uint32_t decoder_width; + uint32_t decoder_height; + +} vdpau_h264_alter_decoder_t; + +#endif /* ALTERH264_DECODE_H */ |