1 #include "tr_public.h"
2 #include "tr_dump.h"
3 #include "tr_dump_state.h"
4 #include "tr_texture.h"
5 #include "u_inlines.h"
6 #include "u_video.h"
7 #include "tr_video.h"
8 #include "pipe/p_video_codec.h"
9 #include "pipe/p_video_enums.h"
10 #include "util/macros.h"
11 #include "util/u_memory.h"
12 #include "vl/vl_defines.h"
13
14 static void
trace_video_codec_destroy(struct pipe_video_codec * _codec)15 trace_video_codec_destroy(struct pipe_video_codec *_codec)
16 {
17 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
18 struct pipe_video_codec *video_codec = tr_vcodec->video_codec;
19
20 trace_dump_call_begin("pipe_video_codec", "destroy");
21 trace_dump_arg(ptr, video_codec);
22 trace_dump_call_end();
23
24 video_codec->destroy(video_codec);
25
26 ralloc_free(tr_vcodec);
27 }
28
29 static void
unwrap_refrence_frames_in_place(struct pipe_video_buffer ** refrence_frames,unsigned max_num_refrence_frame)30 unwrap_refrence_frames_in_place(struct pipe_video_buffer **refrence_frames, unsigned max_num_refrence_frame)
31 {
32 for (unsigned i=0; i < max_num_refrence_frame; i++) {
33 if (refrence_frames[i]) {
34 struct trace_video_buffer *tr_buffer = trace_video_buffer(refrence_frames[i]);
35 refrence_frames[i] = tr_buffer->video_buffer;
36 }
37 }
38 }
39
40 static bool
unwrap_refrence_frames(struct pipe_picture_desc ** picture)41 unwrap_refrence_frames(struct pipe_picture_desc **picture)
42 {
43 // only decode pictures use video buffers for refrences
44 if ((*picture)->entry_point != PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
45 return false;
46 switch (u_reduce_video_profile((*picture)->profile)) {
47 case PIPE_VIDEO_FORMAT_MPEG12: {
48 struct pipe_mpeg12_picture_desc *copied = mem_dup(*picture, sizeof(struct pipe_mpeg12_picture_desc));
49 assert(copied);
50 unwrap_refrence_frames_in_place(copied->ref, ARRAY_SIZE(copied->ref));
51 *picture = (struct pipe_picture_desc*)copied;
52 return true;
53 }
54 case PIPE_VIDEO_FORMAT_MPEG4: {
55 struct pipe_mpeg4_picture_desc *copied = mem_dup(*picture, sizeof(struct pipe_mpeg4_picture_desc));
56 assert(copied);
57 unwrap_refrence_frames_in_place(copied->ref, ARRAY_SIZE(copied->ref));
58 *picture = (struct pipe_picture_desc*)copied;
59 return true;
60 }
61 case PIPE_VIDEO_FORMAT_VC1:{
62 struct pipe_vc1_picture_desc *copied = mem_dup(*picture, sizeof(struct pipe_vc1_picture_desc));
63 assert(copied);
64 unwrap_refrence_frames_in_place(copied->ref, ARRAY_SIZE(copied->ref));
65 *picture = (struct pipe_picture_desc*)copied;
66 return true;
67 }
68 case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
69 struct pipe_h264_picture_desc *copied = mem_dup(*picture, sizeof(struct pipe_h264_picture_desc));
70 assert(copied);
71 unwrap_refrence_frames_in_place(copied->ref, ARRAY_SIZE(copied->ref));
72 *picture = (struct pipe_picture_desc*)copied;
73 return true;
74 }
75 case PIPE_VIDEO_FORMAT_HEVC:{
76 struct pipe_h265_picture_desc *copied = mem_dup(*picture, sizeof(struct pipe_h265_picture_desc));
77 assert(copied);
78 unwrap_refrence_frames_in_place(copied->ref, ARRAY_SIZE(copied->ref));
79 *picture = (struct pipe_picture_desc*)copied;
80 return true;
81 }
82 case PIPE_VIDEO_FORMAT_JPEG:
83 return false;
84 case PIPE_VIDEO_FORMAT_VP9:{
85 struct pipe_vp9_picture_desc *copied = mem_dup(*picture, sizeof(struct pipe_vp9_picture_desc));
86 assert(copied);
87 unwrap_refrence_frames_in_place(copied->ref, ARRAY_SIZE(copied->ref));
88 *picture = (struct pipe_picture_desc*)copied;
89 return true;
90 }
91 case PIPE_VIDEO_FORMAT_AV1:{
92 struct pipe_av1_picture_desc *copied = mem_dup(*picture, sizeof(struct pipe_av1_picture_desc));
93 assert(copied);
94 unwrap_refrence_frames_in_place(copied->ref, ARRAY_SIZE(copied->ref));
95 unwrap_refrence_frames_in_place(&copied->film_grain_target, 1);
96 *picture = (struct pipe_picture_desc*)copied;
97 return true;
98 }
99 case PIPE_VIDEO_FORMAT_UNKNOWN:
100 default:
101 unreachable("unknown video format");
102 }
103 }
104
105 static void
trace_video_codec_begin_frame(struct pipe_video_codec * _codec,struct pipe_video_buffer * _target,struct pipe_picture_desc * picture)106 trace_video_codec_begin_frame(struct pipe_video_codec *_codec,
107 struct pipe_video_buffer *_target,
108 struct pipe_picture_desc *picture)
109 {
110 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
111 struct pipe_video_codec *codec = tr_vcodec->video_codec;
112 struct trace_video_buffer *tr_target = trace_video_buffer(_target);
113 struct pipe_video_buffer *target = tr_target->video_buffer;
114
115 trace_dump_call_begin("pipe_video_codec", "begin_frame");
116 trace_dump_arg(ptr, codec);
117 trace_dump_arg(ptr, target);
118 trace_dump_arg(pipe_picture_desc, picture);
119 trace_dump_call_end();
120
121 bool copied = unwrap_refrence_frames(&picture);
122 codec->begin_frame(codec, target, picture);
123 if (copied)
124 FREE(picture);
125 }
126
127 static void
trace_video_codec_decode_macroblock(struct pipe_video_codec * _codec,struct pipe_video_buffer * _target,struct pipe_picture_desc * picture,const struct pipe_macroblock * macroblocks,unsigned num_macroblocks)128 trace_video_codec_decode_macroblock(struct pipe_video_codec *_codec,
129 struct pipe_video_buffer *_target,
130 struct pipe_picture_desc *picture,
131 const struct pipe_macroblock *macroblocks,
132 unsigned num_macroblocks)
133 {
134 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
135 struct pipe_video_codec *codec = tr_vcodec->video_codec;
136 struct trace_video_buffer *tr_target = trace_video_buffer(_target);
137 struct pipe_video_buffer *target = tr_target->video_buffer;
138
139 trace_dump_call_begin("pipe_video_codec", "decode_macroblock");
140 trace_dump_arg(ptr, codec);
141 trace_dump_arg(ptr, target);
142 trace_dump_arg(pipe_picture_desc, picture);
143 // TODO: how to dump pipe_macroblocks? It's only a single pointer,
144 // but each struct has codec dependent size, so can't use generic trace_dump_arg_array
145 trace_dump_arg(ptr, macroblocks);
146 trace_dump_arg(uint, num_macroblocks);
147 trace_dump_call_end();
148
149 bool copied = unwrap_refrence_frames(&picture);
150 codec->decode_macroblock(codec, target, picture, macroblocks, num_macroblocks);
151 if (copied)
152 FREE(picture);
153 }
154
155 static void
trace_video_codec_decode_bitstream(struct pipe_video_codec * _codec,struct pipe_video_buffer * _target,struct pipe_picture_desc * picture,unsigned num_buffers,const void * const * buffers,const unsigned * sizes)156 trace_video_codec_decode_bitstream(struct pipe_video_codec *_codec,
157 struct pipe_video_buffer *_target,
158 struct pipe_picture_desc *picture,
159 unsigned num_buffers,
160 const void * const *buffers,
161 const unsigned *sizes)
162 {
163 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
164 struct pipe_video_codec *codec = tr_vcodec->video_codec;
165 struct trace_video_buffer *tr_target = trace_video_buffer(_target);
166 struct pipe_video_buffer *target = tr_target->video_buffer;
167
168 trace_dump_call_begin("pipe_video_codec", "decode_bitstream");
169 trace_dump_arg(ptr, codec);
170 trace_dump_arg(ptr, target);
171 trace_dump_arg(pipe_picture_desc, picture);
172
173 trace_dump_arg(uint, num_buffers);
174 trace_dump_arg_array(ptr, buffers, num_buffers);
175 trace_dump_arg_array(uint, sizes, num_buffers);
176 trace_dump_call_end();
177
178 bool copied = unwrap_refrence_frames(&picture);
179 codec->decode_bitstream(codec, target, picture, num_buffers, buffers, sizes);
180 if (copied)
181 FREE(picture);
182 }
183
184 static void
trace_video_codec_encode_bitstream(struct pipe_video_codec * _codec,struct pipe_video_buffer * _source,struct pipe_resource * destination,void ** feedback)185 trace_video_codec_encode_bitstream(struct pipe_video_codec *_codec,
186 struct pipe_video_buffer *_source,
187 struct pipe_resource *destination,
188 void **feedback)
189 {
190 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
191 struct pipe_video_codec *codec = tr_vcodec->video_codec;
192 struct trace_video_buffer *tr_source = trace_video_buffer(_source);
193 struct pipe_video_buffer *source = tr_source->video_buffer;
194
195 trace_dump_call_begin("pipe_video_codec", "encode_bitstream");
196 trace_dump_arg(ptr, codec);
197 trace_dump_arg(ptr, source);
198 trace_dump_arg(ptr, destination);
199 trace_dump_arg(ptr, feedback);
200 trace_dump_call_end();
201
202 codec->encode_bitstream(codec, source, destination, feedback);
203 }
204
205 static int
trace_video_codec_process_frame(struct pipe_video_codec * _codec,struct pipe_video_buffer * _source,const struct pipe_vpp_desc * process_properties)206 trace_video_codec_process_frame(struct pipe_video_codec *_codec,
207 struct pipe_video_buffer *_source,
208 const struct pipe_vpp_desc *process_properties)
209 {
210 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
211 struct pipe_video_codec *codec = tr_vcodec->video_codec;
212 struct trace_video_buffer *tr_source = trace_video_buffer(_source);
213 struct pipe_video_buffer *source = tr_source->video_buffer;
214
215 trace_dump_call_begin("pipe_video_codec", "process_frame");
216 trace_dump_arg(ptr, codec);
217 trace_dump_arg(ptr, source);
218 trace_dump_arg(pipe_vpp_desc, process_properties);
219 trace_dump_call_end();
220
221 codec->process_frame(codec, source, process_properties);
222 return 0;
223 }
224
225 static int
trace_video_codec_end_frame(struct pipe_video_codec * _codec,struct pipe_video_buffer * _target,struct pipe_picture_desc * picture)226 trace_video_codec_end_frame(struct pipe_video_codec *_codec,
227 struct pipe_video_buffer *_target,
228 struct pipe_picture_desc *picture)
229 {
230 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
231 struct pipe_video_codec *codec = tr_vcodec->video_codec;
232 struct trace_video_buffer *tr_target = trace_video_buffer(_target);
233 struct pipe_video_buffer *target = tr_target->video_buffer;
234
235 trace_dump_call_begin("pipe_video_codec", "end_frame");
236 trace_dump_arg(ptr, codec);
237 trace_dump_arg(ptr, target);
238 trace_dump_arg(pipe_picture_desc, picture);
239 trace_dump_call_end();
240
241 bool copied = unwrap_refrence_frames(&picture);
242 codec->end_frame(codec, target, picture);
243 if (copied)
244 FREE(picture);
245 return 0;
246 }
247
248 static void
trace_video_codec_flush(struct pipe_video_codec * _codec)249 trace_video_codec_flush(struct pipe_video_codec *_codec)
250 {
251 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
252 struct pipe_video_codec *codec = tr_vcodec->video_codec;
253
254 trace_dump_call_begin("pipe_video_codec", "flush");
255 trace_dump_arg(ptr, codec);
256 trace_dump_call_end();
257
258 codec->flush(codec);
259 }
260
261 static void
trace_video_codec_get_feedback(struct pipe_video_codec * _codec,void * feedback,unsigned * size,struct pipe_enc_feedback_metadata * metadata)262 trace_video_codec_get_feedback(struct pipe_video_codec *_codec,
263 void *feedback,
264 unsigned *size,
265 struct pipe_enc_feedback_metadata* metadata)
266 {
267 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
268 struct pipe_video_codec *codec = tr_vcodec->video_codec;
269
270 trace_dump_call_begin("pipe_video_codec", "get_feedback");
271 trace_dump_arg(ptr, codec);
272 trace_dump_arg(ptr, feedback);
273 trace_dump_arg(ptr, size);
274 trace_dump_call_end();
275
276 codec->get_feedback(codec, feedback, size, metadata);
277 }
278
279 static int
trace_video_codec_fence_wait(struct pipe_video_codec * _codec,struct pipe_fence_handle * fence,uint64_t timeout)280 trace_video_codec_fence_wait(struct pipe_video_codec *_codec,
281 struct pipe_fence_handle *fence,
282 uint64_t timeout)
283 {
284 struct trace_video_codec *tr_vcodec = trace_video_codec(_codec);
285 struct pipe_video_codec *codec = tr_vcodec->video_codec;
286
287 trace_dump_call_begin("pipe_video_codec", "fence_wait");
288 trace_dump_arg(ptr, codec);
289 trace_dump_arg(ptr, fence);
290 trace_dump_arg(uint, timeout);
291
292 int ret = codec->fence_wait(codec, fence, timeout);
293
294 trace_dump_ret(int, ret);
295 trace_dump_call_end();
296
297 return ret;
298 }
299
300 struct pipe_video_codec *
trace_video_codec_create(struct trace_context * tr_ctx,struct pipe_video_codec * video_codec)301 trace_video_codec_create(struct trace_context *tr_ctx,
302 struct pipe_video_codec *video_codec)
303 {
304 struct trace_video_codec *tr_vcodec;
305
306 if (!video_codec)
307 goto error1;
308
309 if (!trace_enabled())
310 goto error1;
311
312 tr_vcodec = rzalloc(NULL, struct trace_video_codec);
313 if (!tr_vcodec)
314 goto error1;
315
316 memcpy(&tr_vcodec->base, video_codec, sizeof(struct pipe_video_codec));
317 tr_vcodec->base.context = &tr_ctx->base;
318
319 #define TR_VC_INIT(_member) \
320 tr_vcodec->base . _member = video_codec -> _member ? trace_video_codec_ ## _member : NULL
321
322 TR_VC_INIT(destroy);
323 TR_VC_INIT(begin_frame);
324 TR_VC_INIT(decode_macroblock);
325 TR_VC_INIT(decode_bitstream);
326 TR_VC_INIT(encode_bitstream);
327 TR_VC_INIT(process_frame);
328 TR_VC_INIT(end_frame);
329 TR_VC_INIT(flush);
330 TR_VC_INIT(get_feedback);
331 TR_VC_INIT(fence_wait);
332
333 #undef TR_VC_INIT
334
335 tr_vcodec->video_codec = video_codec;
336
337 return &tr_vcodec->base;
338
339 error1:
340 return video_codec;
341 }
342
343
344 static void
trace_video_buffer_destroy(struct pipe_video_buffer * _buffer)345 trace_video_buffer_destroy(struct pipe_video_buffer *_buffer)
346 {
347 struct trace_video_buffer *tr_vbuffer = trace_video_buffer(_buffer);
348 struct pipe_video_buffer *video_buffer = tr_vbuffer->video_buffer;
349
350 trace_dump_call_begin("pipe_video_buffer", "destroy");
351 trace_dump_arg(ptr, video_buffer);
352 trace_dump_call_end();
353
354 for (int i=0; i < VL_NUM_COMPONENTS; i++) {
355 pipe_sampler_view_reference(&tr_vbuffer->sampler_view_planes[i], NULL);
356 pipe_sampler_view_reference(&tr_vbuffer->sampler_view_components[i], NULL);
357 }
358 for (int i=0; i < VL_MAX_SURFACES; i++) {
359 pipe_surface_reference(&tr_vbuffer->surfaces[i], NULL);
360 }
361 video_buffer->destroy(video_buffer);
362
363 ralloc_free(tr_vbuffer);
364 }
365
366 static void
trace_video_buffer_get_resources(struct pipe_video_buffer * _buffer,struct pipe_resource ** resources)367 trace_video_buffer_get_resources(struct pipe_video_buffer *_buffer, struct pipe_resource **resources)
368 {
369 struct trace_video_buffer *tr_vbuffer = trace_video_buffer(_buffer);
370 struct pipe_video_buffer *buffer = tr_vbuffer->video_buffer;
371
372 trace_dump_call_begin("pipe_video_buffer", "get_resources");
373 trace_dump_arg(ptr, buffer);
374
375 buffer->get_resources(buffer, resources);
376
377 // TODO: A `trace_dump_ret_arg` style of function would be more appropriate
378 trace_dump_arg_array(ptr, resources, VL_NUM_COMPONENTS);
379 trace_dump_call_end();
380 }
381
382 static struct pipe_sampler_view **
trace_video_buffer_get_sampler_view_planes(struct pipe_video_buffer * _buffer)383 trace_video_buffer_get_sampler_view_planes(struct pipe_video_buffer *_buffer)
384 {
385 struct trace_context *tr_ctx = trace_context(_buffer->context);
386 struct trace_video_buffer *tr_vbuffer = trace_video_buffer(_buffer);
387 struct pipe_video_buffer *buffer = tr_vbuffer->video_buffer;
388
389 trace_dump_call_begin("pipe_video_buffer", "get_sampler_view_planes");
390 trace_dump_arg(ptr, buffer);
391
392 struct pipe_sampler_view **view_planes = buffer->get_sampler_view_planes(buffer);
393
394 trace_dump_ret_array(ptr, view_planes, VL_NUM_COMPONENTS);
395 trace_dump_call_end();
396
397 for (int i=0; i < VL_NUM_COMPONENTS; i++) {
398 if (!view_planes || !view_planes[i]) {
399 pipe_sampler_view_reference(&tr_vbuffer->sampler_view_planes[i], NULL);
400 } else if (tr_vbuffer->sampler_view_planes[i] == NULL || (trace_sampler_view(tr_vbuffer->sampler_view_planes[i])->sampler_view != view_planes[i])) {
401 pipe_sampler_view_reference(&tr_vbuffer->sampler_view_planes[i], trace_sampler_view_create(tr_ctx, view_planes[i]->texture, view_planes[i]));
402 }
403 }
404
405 return view_planes ? tr_vbuffer->sampler_view_planes : NULL;
406 }
407
408 static struct pipe_sampler_view **
trace_video_buffer_get_sampler_view_components(struct pipe_video_buffer * _buffer)409 trace_video_buffer_get_sampler_view_components(struct pipe_video_buffer *_buffer)
410 {
411 struct trace_context *tr_ctx = trace_context(_buffer->context);
412 struct trace_video_buffer *tr_vbuffer = trace_video_buffer(_buffer);
413 struct pipe_video_buffer *buffer = tr_vbuffer->video_buffer;
414
415 trace_dump_call_begin("pipe_video_buffer", "get_sampler_view_components");
416 trace_dump_arg(ptr, buffer);
417
418 struct pipe_sampler_view **view_components = buffer->get_sampler_view_components(buffer);
419
420 trace_dump_ret_array(ptr, view_components, VL_NUM_COMPONENTS);
421 trace_dump_call_end();
422
423 for (int i=0; i < VL_NUM_COMPONENTS; i++) {
424 if (!view_components || !view_components[i]) {
425 pipe_sampler_view_reference(&tr_vbuffer->sampler_view_components[i], NULL);
426 } else if (tr_vbuffer->sampler_view_components[i] == NULL || (trace_sampler_view(tr_vbuffer->sampler_view_components[i])->sampler_view != view_components[i])) {
427 pipe_sampler_view_reference(&tr_vbuffer->sampler_view_components[i], trace_sampler_view_create(tr_ctx, view_components[i]->texture, view_components[i]));
428 }
429 }
430
431 return view_components ? tr_vbuffer->sampler_view_components : NULL;
432 }
433
434 static struct pipe_surface **
trace_video_buffer_get_surfaces(struct pipe_video_buffer * _buffer)435 trace_video_buffer_get_surfaces(struct pipe_video_buffer *_buffer)
436 {
437 struct trace_context *tr_ctx = trace_context(_buffer->context);
438 struct trace_video_buffer *tr_vbuffer = trace_video_buffer(_buffer);
439 struct pipe_video_buffer *buffer = tr_vbuffer->video_buffer;
440
441 trace_dump_call_begin("pipe_video_buffer", "get_surfaces");
442 trace_dump_arg(ptr, buffer);
443
444 struct pipe_surface **surfaces = buffer->get_surfaces(buffer);
445
446 trace_dump_ret_array(ptr, surfaces, VL_MAX_SURFACES);
447 trace_dump_call_end();
448
449 for (int i=0; i < VL_MAX_SURFACES; i++) {
450 if (!surfaces || !surfaces[i]) {
451 pipe_surface_reference(&tr_vbuffer->surfaces[i], NULL);
452 } else if (tr_vbuffer->surfaces[i] == NULL || (trace_surface(tr_vbuffer->surfaces[i])->surface != surfaces[i])){
453 pipe_surface_reference(&tr_vbuffer->surfaces[i], trace_surf_create(tr_ctx, surfaces[i]->texture, surfaces[i]));
454 }
455 }
456
457 return surfaces ? tr_vbuffer->surfaces : NULL;
458 }
459
460
461 struct pipe_video_buffer *
trace_video_buffer_create(struct trace_context * tr_ctx,struct pipe_video_buffer * video_buffer)462 trace_video_buffer_create(struct trace_context *tr_ctx,
463 struct pipe_video_buffer *video_buffer)
464 {
465 struct trace_video_buffer *tr_vbuffer;
466
467 if (!video_buffer)
468 goto error1;
469
470 if (!trace_enabled())
471 goto error1;
472
473 tr_vbuffer = rzalloc(NULL, struct trace_video_buffer);
474 if (!tr_vbuffer)
475 goto error1;
476
477 memcpy(&tr_vbuffer->base, video_buffer, sizeof(struct pipe_video_buffer));
478 tr_vbuffer->base.context = &tr_ctx->base;
479
480 #define TR_VB_INIT(_member) \
481 tr_vbuffer->base . _member = video_buffer -> _member ? trace_video_buffer_ ## _member : NULL
482
483 TR_VB_INIT(destroy);
484 TR_VB_INIT(get_resources);
485 TR_VB_INIT(get_sampler_view_planes);
486 TR_VB_INIT(get_sampler_view_components);
487 TR_VB_INIT(get_surfaces);
488
489 #undef TR_VB_INIT
490
491 tr_vbuffer->video_buffer = video_buffer;
492
493 return &tr_vbuffer->base;
494
495 error1:
496 return video_buffer;
497 }
498