radeon/uvd: try to fix VC-1 decoding
authorGrigori Goronzy <greg@chown.ath.cx>
Wed, 9 Oct 2013 00:23:48 +0000 (02:23 +0200)
committerChristian König <christian.koenig@amd.com>
Wed, 9 Oct 2013 11:02:40 +0000 (13:02 +0200)
The DPB size calculations seem to be off; there is various random
corruption happening, even with advanced profile. Always assuming
a minimum number of references appears to fix it, similarly to
H.264. This might overallocate the DPB.  Also clean up the SPS/PPS
field setup so that it matches VC-1 specifications better.

With these changes, all advanced profile VC-1 files I could get my
hand on work fine.

Reviewed-by: Christian König <christian.koenig@amd.com>
src/gallium/drivers/radeon/radeon_uvd.c

index 34650d4d19bd77eaf617ab4543958e7a16d952d3..da92ace57ba32e4ca952686f19c34b77ee5f27f1 100644 (file)
@@ -56,6 +56,7 @@
 
 #define NUM_MPEG2_REFS 6
 #define NUM_H264_REFS 17
+#define NUM_VC1_REFS 5
 
 /* UVD buffer representation */
 struct ruvd_buffer
@@ -304,6 +305,9 @@ static unsigned calc_dpb_size(const struct pipe_video_codec *templ)
                break;
 
        case PIPE_VIDEO_FORMAT_VC1:
+               // the firmware seems to allways assume a minimum of ref frames
+               max_references = MAX2(NUM_VC1_REFS, max_references);
+
                // reference picture buffer
                dpb_size = image_size * max_references;
 
@@ -431,60 +435,62 @@ static struct ruvd_vc1 get_vc1_msg(struct pipe_vc1_picture_desc *pic)
        struct ruvd_vc1 result;
 
        memset(&result, 0, sizeof(result));
+
        switch(pic->base.profile) {
        case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
                result.profile = RUVD_VC1_PROFILE_SIMPLE;
+               result.level = 1;
                break;
 
        case PIPE_VIDEO_PROFILE_VC1_MAIN:
                result.profile = RUVD_VC1_PROFILE_MAIN;
+               result.level = 2;
                break;
-               
+
        case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
                result.profile = RUVD_VC1_PROFILE_ADVANCED;
+               result.level = 4;
                break;
+
        default:
                assert(0);
        }
 
-       if (pic->base.profile == PIPE_VIDEO_PROFILE_VC1_ADVANCED) {
-               result.level = 0;
-
-               result.sps_info_flags |= pic->postprocflag << 7;
-               result.sps_info_flags |= pic->pulldown << 6;
-               result.sps_info_flags |= pic->interlace << 5;
-               result.sps_info_flags |= pic->tfcntrflag << 4;
-               result.sps_info_flags |= pic->psf << 1;
-
-               result.pps_info_flags |= pic->panscan_flag << 7;
-               result.pps_info_flags |= pic->refdist_flag << 6;
-               result.pps_info_flags |= pic->extended_dmv << 8;
-               result.pps_info_flags |= pic->range_mapy_flag << 31;
-               result.pps_info_flags |= pic->range_mapy << 28;
-               result.pps_info_flags |= pic->range_mapuv_flag << 27;
-               result.pps_info_flags |= pic->range_mapuv << 24;
+       /* fields common for all profiles */
+       result.sps_info_flags |= pic->postprocflag << 7;
+       result.sps_info_flags |= pic->pulldown << 6;
+       result.sps_info_flags |= pic->interlace << 5;
+       result.sps_info_flags |= pic->tfcntrflag << 4;
+       result.sps_info_flags |= pic->finterpflag << 3;
+       result.sps_info_flags |= pic->psf << 1;
+
+       result.pps_info_flags |= pic->range_mapy_flag << 31;
+       result.pps_info_flags |= pic->range_mapy << 28;
+       result.pps_info_flags |= pic->range_mapuv_flag << 27;
+       result.pps_info_flags |= pic->range_mapuv << 24;
+       result.pps_info_flags |= pic->multires << 21;
+       result.pps_info_flags |= pic->maxbframes << 16;
+       result.pps_info_flags |= pic->overlap << 11;
+       result.pps_info_flags |= pic->quantizer << 9;
+       result.pps_info_flags |= pic->panscan_flag << 7;
+       result.pps_info_flags |= pic->refdist_flag << 6;
+       result.pps_info_flags |= pic->vstransform << 0;
 
-       } else {
-               result.level = 0;
-               result.pps_info_flags |= pic->multires << 21;
+       /* some fields only apply to main/advanced profile */
+       if (pic->base.profile != PIPE_VIDEO_PROFILE_VC1_SIMPLE) {
                result.pps_info_flags |= pic->syncmarker << 20;
                result.pps_info_flags |= pic->rangered << 19;
-               result.pps_info_flags |= pic->maxbframes << 16;
+               result.pps_info_flags |= pic->loopfilter << 5;
+               result.pps_info_flags |= pic->fastuvmc << 4;
+               result.pps_info_flags |= pic->extended_mv << 3;
+               result.pps_info_flags |= pic->extended_dmv << 8;
+               result.pps_info_flags |= pic->dquant << 1;
        }
 
-       result.sps_info_flags |= pic->finterpflag << 3;
-       //(((unsigned int)(pPicParams->advance.reserved1))        << SPS_INFO_VC1_RESERVED_SHIFT)
-
-       result.pps_info_flags |= pic->loopfilter << 5;
-       result.pps_info_flags |= pic->fastuvmc << 4;
-       result.pps_info_flags |= pic->extended_mv << 3;
-       result.pps_info_flags |= pic->dquant << 1;
-       result.pps_info_flags |= pic->vstransform << 0;
-       result.pps_info_flags |= pic->overlap << 11;
-       result.pps_info_flags |= pic->quantizer << 9;
-
+       result.chroma_format = 1;
 
 #if 0
+//(((unsigned int)(pPicParams->advance.reserved1))        << SPS_INFO_VC1_RESERVED_SHIFT)
 uint32_t       slice_count
 uint8_t        picture_type
 uint8_t        frame_coding_mode
@@ -492,7 +498,6 @@ uint8_t     deblockEnable
 uint8_t        pquant
 #endif
 
-        result.chroma_format  = 1;
        return result;
 }