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
nouveau_vp3_fill_picparm_mpeg12_bsp(struct nouveau_vp3_decoder * dec,struct pipe_mpeg12_picture_desc * desc,char * map)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
nouveau_vp3_fill_picparm_mpeg4_bsp(struct nouveau_vp3_decoder * dec,struct pipe_mpeg4_picture_desc * desc,char * map)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
nouveau_vp3_fill_picparm_vc1_bsp(struct nouveau_vp3_decoder * dec,struct pipe_vc1_picture_desc * d,char * map)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
nouveau_vp3_fill_picparm_h264_bsp(struct nouveau_vp3_decoder * dec,struct pipe_h264_picture_desc * d,char * map)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
strparm_bsp(struct nouveau_vp3_decoder * dec)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
nouveau_vp3_bsp_begin(struct nouveau_vp3_decoder * dec)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
nouveau_vp3_bsp_next(struct nouveau_vp3_decoder * dec,unsigned num_buffers,const void * const * data,const unsigned * num_bytes)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
nouveau_vp3_bsp_end(struct nouveau_vp3_decoder * dec,union pipe_desc desc)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