summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_dec/libvdpau/Makefile.am8
-rw-r--r--src/video_dec/libvdpau/alterh264_bits_reader.h127
-rw-r--r--src/video_dec/libvdpau/alterh264_decode.c2448
-rw-r--r--src/video_dec/libvdpau/alterh264_decode.h339
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 */