1 /* 2 * Copyright 2011-2013 Maarten Lankhorst 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #include "nouveau_vp3_video.h" 24 25 struct strparm_bsp { 26 uint32_t w0[4]; // bits 0-23 length, bits 24-31 addr_hi 27 uint32_t w1[4]; // bit 8-24 addr_lo 28 uint32_t unk20; // should be idx * 0x8000000, bitstream offset 29 uint32_t do_crypto_crap; // set to 0 30 }; 31 32 struct mpeg12_picparm_bsp { 33 uint16_t width; 34 uint16_t height; 35 uint8_t picture_structure; 36 uint8_t picture_coding_type; 37 uint8_t intra_dc_precision; 38 uint8_t frame_pred_frame_dct; 39 uint8_t concealment_motion_vectors; 40 uint8_t intra_vlc_format; 41 uint16_t pad; 42 uint8_t f_code[2][2]; 43 }; 44 45 struct mpeg4_picparm_bsp { 46 uint16_t width; 47 uint16_t height; 48 uint8_t vop_time_increment_size; 49 uint8_t interlaced; 50 uint8_t resync_marker_disable; 51 }; 52 53 struct vc1_picparm_bsp { 54 uint16_t width; 55 uint16_t height; 56 uint8_t profile; // 04 0 simple, 1 main, 2 advanced 57 uint8_t postprocflag; // 05 58 uint8_t pulldown; // 06 59 uint8_t interlaced; // 07 60 uint8_t tfcntrflag; // 08 61 uint8_t finterpflag; // 09 62 uint8_t psf; // 0a 63 uint8_t pad; // 0b 64 uint8_t multires; // 0c 65 uint8_t syncmarker; // 0d 66 uint8_t rangered; // 0e 67 uint8_t maxbframes; // 0f 68 uint8_t dquant; // 10 69 uint8_t panscan_flag; // 11 70 uint8_t refdist_flag; // 12 71 uint8_t quantizer; // 13 72 uint8_t extended_mv; // 14 73 uint8_t extended_dmv; // 15 74 uint8_t overlap; // 16 75 uint8_t vstransform; // 17 76 }; 77 78 struct h264_picparm_bsp { 79 // 00 80 uint32_t unk00; 81 // 04 82 uint32_t log2_max_frame_num_minus4; // 04 checked 83 uint32_t pic_order_cnt_type; // 08 checked 84 uint32_t log2_max_pic_order_cnt_lsb_minus4; // 0c checked 85 uint32_t delta_pic_order_always_zero_flag; // 10, or unknown 86 87 uint32_t frame_mbs_only_flag; // 14, always 1? 88 uint32_t direct_8x8_inference_flag; // 18, always 1? 89 uint32_t width_mb; // 1c checked 90 uint32_t height_mb; // 20 checked 91 // 24 92 //struct picparm2 93 uint32_t entropy_coding_mode_flag; // 00, checked 94 uint32_t pic_order_present_flag; // 04 checked 95 uint32_t unk; // 08 seems to be 0? 96 uint32_t pad1; // 0c seems to be 0? 97 uint32_t pad2; // 10 always 0 ? 98 uint32_t num_ref_idx_l0_active_minus1; // 14 always 0? 99 uint32_t num_ref_idx_l1_active_minus1; // 18 always 0? 100 uint32_t weighted_pred_flag; // 1c checked 101 uint32_t weighted_bipred_idc; // 20 checked 102 uint32_t pic_init_qp_minus26; // 24 checked 103 uint32_t deblocking_filter_control_present_flag; // 28 always 1? 104 uint32_t redundant_pic_cnt_present_flag; // 2c always 0? 105 uint32_t transform_8x8_mode_flag; // 30 checked 106 uint32_t mb_adaptive_frame_field_flag; // 34 checked-ish 107 uint8_t field_pic_flag; // 38 checked 108 uint8_t bottom_field_flag; // 39 checked 109 uint8_t real_pad[0x1b]; // XX why? 110 }; 111 112 static uint32_t 113 nouveau_vp3_fill_picparm_mpeg12_bsp(struct nouveau_vp3_decoder *dec, 114 struct pipe_mpeg12_picture_desc *desc, 115 char *map) 116 { 117 struct mpeg12_picparm_bsp *pic_bsp = (struct mpeg12_picparm_bsp *)map; 118 int i; 119 pic_bsp->width = dec->base.width; 120 pic_bsp->height = dec->base.height; 121 pic_bsp->picture_structure = desc->picture_structure; 122 pic_bsp->picture_coding_type = desc->picture_coding_type; 123 pic_bsp->intra_dc_precision = desc->intra_dc_precision; 124 pic_bsp->frame_pred_frame_dct = desc->frame_pred_frame_dct; 125 pic_bsp->concealment_motion_vectors = desc->concealment_motion_vectors; 126 pic_bsp->intra_vlc_format = desc->intra_vlc_format; 127 pic_bsp->pad = 0; 128 for (i = 0; i < 4; ++i) 129 pic_bsp->f_code[i/2][i%2] = desc->f_code[i/2][i%2] + 1; // FU 130 131 return (desc->num_slices << 4) | (dec->base.profile != PIPE_VIDEO_PROFILE_MPEG1); 132 } 133 134 static uint32_t 135 nouveau_vp3_fill_picparm_mpeg4_bsp(struct nouveau_vp3_decoder *dec, 136 struct pipe_mpeg4_picture_desc *desc, 137 char *map) 138 { 139 struct mpeg4_picparm_bsp *pic_bsp = (struct mpeg4_picparm_bsp *)map; 140 uint32_t t, bits = 0; 141 pic_bsp->width = dec->base.width; 142 pic_bsp->height = dec->base.height; 143 assert(desc->vop_time_increment_resolution > 0); 144 145 t = desc->vop_time_increment_resolution - 1; 146 while (t) { 147 bits++; 148 t /= 2; 149 } 150 if (!bits) 151 bits = 1; 152 t = desc->vop_time_increment_resolution - 1; 153 pic_bsp->vop_time_increment_size = bits; 154 pic_bsp->interlaced = desc->interlaced; 155 pic_bsp->resync_marker_disable = desc->resync_marker_disable; 156 return 4; 157 } 158 159 static uint32_t 160 nouveau_vp3_fill_picparm_vc1_bsp(struct nouveau_vp3_decoder *dec, 161 struct pipe_vc1_picture_desc *d, 162 char *map) 163 { 164 struct vc1_picparm_bsp *vc = (struct vc1_picparm_bsp *)map; 165 uint32_t caps = (d->slice_count << 4)&0xfff0; 166 vc->width = dec->base.width; 167 vc->height = dec->base.height; 168 vc->profile = dec->base.profile - PIPE_VIDEO_PROFILE_VC1_SIMPLE; // 04 169 vc->postprocflag = d->postprocflag; 170 vc->pulldown = d->pulldown; 171 vc->interlaced = d->interlace; 172 vc->tfcntrflag = d->tfcntrflag; // 08 173 vc->finterpflag = d->finterpflag; 174 vc->psf = d->psf; 175 vc->pad = 0; 176 vc->multires = d->multires; // 0c 177 vc->syncmarker = d->syncmarker; 178 vc->rangered = d->rangered; 179 vc->maxbframes = d->maxbframes; 180 vc->dquant = d->dquant; // 10 181 vc->panscan_flag = d->panscan_flag; 182 vc->refdist_flag = d->refdist_flag; 183 vc->quantizer = d->quantizer; 184 vc->extended_mv = d->extended_mv; // 14 185 vc->extended_dmv = d->extended_dmv; 186 vc->overlap = d->overlap; 187 vc->vstransform = d->vstransform; 188 return caps | 2; 189 } 190 191 static uint32_t 192 nouveau_vp3_fill_picparm_h264_bsp(struct nouveau_vp3_decoder *dec, 193 struct pipe_h264_picture_desc *d, 194 char *map) 195 { 196 struct h264_picparm_bsp stub_h = {}, *h = &stub_h; 197 uint32_t caps = (d->slice_count << 4)&0xfff0; 198 199 assert(!(d->slice_count & ~0xfff)); 200 if (d->slice_count & 0x1000) 201 caps |= 1 << 20; 202 203 assert(offsetof(struct h264_picparm_bsp, bottom_field_flag) == (0x39 + 0x24)); 204 h->unk00 = 1; 205 h->pad1 = h->pad2 = 0; 206 h->unk = 0; 207 h->log2_max_frame_num_minus4 = d->pps->sps->log2_max_frame_num_minus4; 208 h->frame_mbs_only_flag = d->pps->sps->frame_mbs_only_flag; 209 h->direct_8x8_inference_flag = d->pps->sps->direct_8x8_inference_flag; 210 h->width_mb = mb(dec->base.width); 211 h->height_mb = mb(dec->base.height); 212 h->entropy_coding_mode_flag = d->pps->entropy_coding_mode_flag; 213 h->pic_order_present_flag = d->pps->bottom_field_pic_order_in_frame_present_flag; 214 h->pic_order_cnt_type = d->pps->sps->pic_order_cnt_type; 215 h->log2_max_pic_order_cnt_lsb_minus4 = d->pps->sps->log2_max_pic_order_cnt_lsb_minus4; 216 h->delta_pic_order_always_zero_flag = d->pps->sps->delta_pic_order_always_zero_flag; 217 h->num_ref_idx_l0_active_minus1 = d->num_ref_idx_l0_active_minus1; 218 h->num_ref_idx_l1_active_minus1 = d->num_ref_idx_l1_active_minus1; 219 h->weighted_pred_flag = d->pps->weighted_pred_flag; 220 h->weighted_bipred_idc = d->pps->weighted_bipred_idc; 221 h->pic_init_qp_minus26 = d->pps->pic_init_qp_minus26; 222 h->deblocking_filter_control_present_flag = d->pps->deblocking_filter_control_present_flag; 223 h->redundant_pic_cnt_present_flag = d->pps->redundant_pic_cnt_present_flag; 224 h->transform_8x8_mode_flag = d->pps->transform_8x8_mode_flag; 225 h->mb_adaptive_frame_field_flag = d->pps->sps->mb_adaptive_frame_field_flag; 226 h->field_pic_flag = d->field_pic_flag; 227 h->bottom_field_flag = d->bottom_field_flag; 228 memset(h->real_pad, 0, sizeof(h->real_pad)); 229 *(struct h264_picparm_bsp *)map = *h; 230 return caps | 3; 231 } 232 233 static inline struct strparm_bsp *strparm_bsp(struct nouveau_vp3_decoder *dec) 234 { 235 unsigned comm_seq = dec->fence_seq; 236 struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; 237 return (struct strparm_bsp *)(bsp_bo->map + 0x100); 238 } 239 240 void 241 nouveau_vp3_bsp_begin(struct nouveau_vp3_decoder *dec) 242 { 243 struct strparm_bsp *str_bsp = strparm_bsp(dec); 244 245 dec->bsp_ptr = (void *)str_bsp; 246 memset(str_bsp, 0, 0x80); 247 dec->bsp_ptr += 0x100; 248 /* Reserved for picparm_vp */ 249 dec->bsp_ptr += 0x300; 250 /* Reserved for comm */ 251 #if !NOUVEAU_VP3_DEBUG_FENCE 252 memset(dec->bsp_ptr, 0, 0x200); 253 #endif 254 dec->bsp_ptr += 0x200; 255 } 256 257 void 258 nouveau_vp3_bsp_next(struct nouveau_vp3_decoder *dec, unsigned num_buffers, 259 const void *const *data, const unsigned *num_bytes) 260 { 261 #ifndef NDEBUG 262 unsigned comm_seq = dec->fence_seq; 263 struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; 264 #endif 265 struct strparm_bsp *str_bsp = strparm_bsp(dec); 266 int i; 267 268 for (i = 0; i < num_buffers; ++i) { 269 #ifndef NDEBUG 270 assert(bsp_bo->size >= str_bsp->w0[0] + num_bytes[i]); 271 #endif 272 memcpy(dec->bsp_ptr, data[i], num_bytes[i]); 273 dec->bsp_ptr += num_bytes[i]; 274 str_bsp->w0[0] += num_bytes[i]; 275 } 276 } 277 278 uint32_t 279 nouveau_vp3_bsp_end(struct nouveau_vp3_decoder *dec, union pipe_desc desc) 280 { 281 enum pipe_video_format codec = u_reduce_video_profile(dec->base.profile); 282 unsigned comm_seq = dec->fence_seq; 283 struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH]; 284 uint32_t endmarker, caps; 285 struct strparm_bsp *str_bsp = strparm_bsp(dec); 286 char *bsp = bsp_bo->map; 287 /* 288 * 0x000..0x100: picparm_bsp 289 * 0x200..0x500: picparm_vp 290 * 0x500..0x700: comm 291 * 0x700..onward: raw bitstream 292 */ 293 294 switch (codec){ 295 case PIPE_VIDEO_FORMAT_MPEG12: 296 endmarker = 0xb7010000; 297 caps = nouveau_vp3_fill_picparm_mpeg12_bsp(dec, desc.mpeg12, bsp); 298 break; 299 case PIPE_VIDEO_FORMAT_MPEG4: 300 endmarker = 0xb1010000; 301 caps = nouveau_vp3_fill_picparm_mpeg4_bsp(dec, desc.mpeg4, bsp); 302 break; 303 case PIPE_VIDEO_FORMAT_VC1: { 304 endmarker = 0x0a010000; 305 caps = nouveau_vp3_fill_picparm_vc1_bsp(dec, desc.vc1, bsp); 306 break; 307 } 308 case PIPE_VIDEO_FORMAT_MPEG4_AVC: { 309 endmarker = 0x0b010000; 310 caps = nouveau_vp3_fill_picparm_h264_bsp(dec, desc.h264, bsp); 311 break; 312 } 313 default: assert(0); return -1; 314 } 315 316 caps |= 0 << 16; // reset struct comm if flag is set 317 caps |= 1 << 17; // enable watchdog 318 caps |= 0 << 18; // do not report error to VP, so it can continue decoding what we have 319 caps |= 0 << 19; // if enabled, use crypto crap? 320 321 str_bsp = strparm_bsp(dec); 322 str_bsp->w1[0] = 0x1; 323 324 /* Append end sequence */ 325 *(uint32_t *)dec->bsp_ptr = endmarker; 326 dec->bsp_ptr += 4; 327 *(uint32_t *)dec->bsp_ptr = 0x00000000; 328 dec->bsp_ptr += 4; 329 *(uint32_t *)dec->bsp_ptr = endmarker; 330 dec->bsp_ptr += 4; 331 *(uint32_t *)dec->bsp_ptr = 0x00000000; 332 str_bsp->w0[0] += 16; 333 334 dec->bsp_ptr = NULL; 335 336 return caps; 337 } 338