1 /**************************************************************************
3 * Copyright 2009 Younes Manton.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
31 #include "util/u_memory.h"
32 #include "util/u_rect.h"
33 #include "util/u_sampler.h"
34 #include "util/u_video.h"
36 #include "vl_mpeg12_decoder.h"
37 #include "vl_defines.h"
39 #define SCALE_FACTOR_SNORM (32768.0f / 256.0f)
40 #define SCALE_FACTOR_SSCALED (1.0f / 256.0f)
42 struct format_config
{
43 enum pipe_format zscan_source_format
;
44 enum pipe_format idct_source_format
;
45 enum pipe_format mc_source_format
;
51 static const struct format_config bitstream_format_config
[] = {
52 // { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SSCALED },
53 // { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, 1.0f, SCALE_FACTOR_SSCALED },
54 { PIPE_FORMAT_R16_SNORM
, PIPE_FORMAT_R16G16B16A16_SNORM
, PIPE_FORMAT_R16G16B16A16_FLOAT
, 1.0f
, SCALE_FACTOR_SNORM
},
55 { PIPE_FORMAT_R16_SNORM
, PIPE_FORMAT_R16G16B16A16_SNORM
, PIPE_FORMAT_R16G16B16A16_SNORM
, 1.0f
, SCALE_FACTOR_SNORM
}
58 static const unsigned num_bitstream_format_configs
=
59 sizeof(bitstream_format_config
) / sizeof(struct format_config
);
61 static const struct format_config idct_format_config
[] = {
62 // { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SSCALED },
63 // { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, 1.0f, SCALE_FACTOR_SSCALED },
64 { PIPE_FORMAT_R16_SNORM
, PIPE_FORMAT_R16G16B16A16_SNORM
, PIPE_FORMAT_R16G16B16A16_FLOAT
, 1.0f
, SCALE_FACTOR_SNORM
},
65 { PIPE_FORMAT_R16_SNORM
, PIPE_FORMAT_R16G16B16A16_SNORM
, PIPE_FORMAT_R16G16B16A16_SNORM
, 1.0f
, SCALE_FACTOR_SNORM
}
68 static const unsigned num_idct_format_configs
=
69 sizeof(idct_format_config
) / sizeof(struct format_config
);
71 static const struct format_config mc_format_config
[] = {
72 //{ PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_NONE, PIPE_FORMAT_R16_SSCALED, 0.0f, SCALE_FACTOR_SSCALED },
73 { PIPE_FORMAT_R16_SNORM
, PIPE_FORMAT_NONE
, PIPE_FORMAT_R16_SNORM
, 0.0f
, SCALE_FACTOR_SNORM
}
76 static const unsigned num_mc_format_configs
=
77 sizeof(mc_format_config
) / sizeof(struct format_config
);
79 static const unsigned const_empty_block_mask_420
[3][2][2] = {
80 { { 0x20, 0x10 }, { 0x08, 0x04 } },
81 { { 0x02, 0x02 }, { 0x02, 0x02 } },
82 { { 0x01, 0x01 }, { 0x01, 0x01 } }
86 init_zscan_buffer(struct vl_mpeg12_decoder
*dec
, struct vl_mpeg12_buffer
*buffer
)
88 struct pipe_resource
*res
, res_tmpl
;
89 struct pipe_sampler_view sv_tmpl
;
90 struct pipe_surface
**destination
;
94 assert(dec
&& buffer
);
96 memset(&res_tmpl
, 0, sizeof(res_tmpl
));
97 res_tmpl
.target
= PIPE_TEXTURE_2D
;
98 res_tmpl
.format
= dec
->zscan_source_format
;
99 res_tmpl
.width0
= dec
->blocks_per_line
* BLOCK_WIDTH
* BLOCK_HEIGHT
;
100 res_tmpl
.height0
= align(dec
->num_blocks
, dec
->blocks_per_line
) / dec
->blocks_per_line
;
102 res_tmpl
.array_size
= 1;
103 res_tmpl
.usage
= PIPE_USAGE_STREAM
;
104 res_tmpl
.bind
= PIPE_BIND_SAMPLER_VIEW
;
106 res
= dec
->base
.context
->screen
->resource_create(dec
->base
.context
->screen
, &res_tmpl
);
111 memset(&sv_tmpl
, 0, sizeof(sv_tmpl
));
112 u_sampler_view_default_template(&sv_tmpl
, res
, res
->format
);
113 sv_tmpl
.swizzle_r
= sv_tmpl
.swizzle_g
= sv_tmpl
.swizzle_b
= sv_tmpl
.swizzle_a
= PIPE_SWIZZLE_RED
;
114 buffer
->zscan_source
= dec
->base
.context
->create_sampler_view(dec
->base
.context
, res
, &sv_tmpl
);
115 pipe_resource_reference(&res
, NULL
);
116 if (!buffer
->zscan_source
)
119 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
120 destination
= dec
->idct_source
->get_surfaces(dec
->idct_source
);
122 destination
= dec
->mc_source
->get_surfaces(dec
->mc_source
);
127 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
128 if (!vl_zscan_init_buffer(i
== 0 ? &dec
->zscan_y
: &dec
->zscan_c
,
129 &buffer
->zscan
[i
], buffer
->zscan_source
, destination
[i
]))
136 vl_zscan_cleanup_buffer(&buffer
->zscan
[i
- 1]);
140 pipe_sampler_view_reference(&buffer
->zscan_source
, NULL
);
147 cleanup_zscan_buffer(struct vl_mpeg12_buffer
*buffer
)
153 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
154 vl_zscan_cleanup_buffer(&buffer
->zscan
[i
]);
156 pipe_sampler_view_reference(&buffer
->zscan_source
, NULL
);
160 init_idct_buffer(struct vl_mpeg12_decoder
*dec
, struct vl_mpeg12_buffer
*buffer
)
162 struct pipe_sampler_view
**idct_source_sv
, **mc_source_sv
;
166 assert(dec
&& buffer
);
168 idct_source_sv
= dec
->idct_source
->get_sampler_view_planes(dec
->idct_source
);
170 goto error_source_sv
;
172 mc_source_sv
= dec
->mc_source
->get_sampler_view_planes(dec
->mc_source
);
174 goto error_mc_source_sv
;
176 for (i
= 0; i
< 3; ++i
)
177 if (!vl_idct_init_buffer(i
== 0 ? &dec
->idct_y
: &dec
->idct_c
,
178 &buffer
->idct
[i
], idct_source_sv
[i
],
186 vl_idct_cleanup_buffer(&buffer
->idct
[i
- 1]);
194 cleanup_idct_buffer(struct vl_mpeg12_buffer
*buf
)
200 for (i
= 0; i
< 3; ++i
)
201 vl_idct_cleanup_buffer(&buf
->idct
[0]);
205 init_mc_buffer(struct vl_mpeg12_decoder
*dec
, struct vl_mpeg12_buffer
*buf
)
209 if(!vl_mc_init_buffer(&dec
->mc_y
, &buf
->mc
[0]))
212 if(!vl_mc_init_buffer(&dec
->mc_c
, &buf
->mc
[1]))
215 if(!vl_mc_init_buffer(&dec
->mc_c
, &buf
->mc
[2]))
221 vl_mc_cleanup_buffer(&buf
->mc
[1]);
224 vl_mc_cleanup_buffer(&buf
->mc
[0]);
231 cleanup_mc_buffer(struct vl_mpeg12_buffer
*buf
)
237 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
238 vl_mc_cleanup_buffer(&buf
->mc
[i
]);
242 MacroBlockTypeToPipeWeights(const struct pipe_mpeg12_macroblock
*mb
, unsigned weights
[2])
246 switch (mb
->macroblock_type
& (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
| PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
)) {
247 case PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
:
248 weights
[0] = PIPE_VIDEO_MV_WEIGHT_MAX
;
249 weights
[1] = PIPE_VIDEO_MV_WEIGHT_MIN
;
252 case (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
| PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
):
253 weights
[0] = PIPE_VIDEO_MV_WEIGHT_HALF
;
254 weights
[1] = PIPE_VIDEO_MV_WEIGHT_HALF
;
257 case PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
:
258 weights
[0] = PIPE_VIDEO_MV_WEIGHT_MIN
;
259 weights
[1] = PIPE_VIDEO_MV_WEIGHT_MAX
;
263 if (mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
) {
264 weights
[0] = PIPE_VIDEO_MV_WEIGHT_MIN
;
265 weights
[1] = PIPE_VIDEO_MV_WEIGHT_MIN
;
267 /* no motion vector, but also not intra mb ->
268 just copy the old frame content */
269 weights
[0] = PIPE_VIDEO_MV_WEIGHT_MAX
;
270 weights
[1] = PIPE_VIDEO_MV_WEIGHT_MIN
;
276 static INLINE
struct vl_motionvector
277 MotionVectorToPipe(const struct pipe_mpeg12_macroblock
*mb
, unsigned vector
,
278 unsigned field_select_mask
, unsigned weight
)
280 struct vl_motionvector mv
;
284 if (mb
->macroblock_type
& (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
| PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
)) {
285 switch (mb
->macroblock_modes
.bits
.frame_motion_type
) {
286 case PIPE_MPEG12_MO_TYPE_FRAME
:
287 mv
.top
.x
= mb
->PMV
[0][vector
][0];
288 mv
.top
.y
= mb
->PMV
[0][vector
][1];
289 mv
.top
.field_select
= PIPE_VIDEO_FRAME
;
290 mv
.top
.weight
= weight
;
292 mv
.bottom
.x
= mb
->PMV
[0][vector
][0];
293 mv
.bottom
.y
= mb
->PMV
[0][vector
][1];
294 mv
.bottom
.weight
= weight
;
295 mv
.bottom
.field_select
= PIPE_VIDEO_FRAME
;
298 case PIPE_MPEG12_MO_TYPE_FIELD
:
299 mv
.top
.x
= mb
->PMV
[0][vector
][0];
300 mv
.top
.y
= mb
->PMV
[0][vector
][1];
301 mv
.top
.field_select
= (mb
->motion_vertical_field_select
& field_select_mask
) ?
302 PIPE_VIDEO_BOTTOM_FIELD
: PIPE_VIDEO_TOP_FIELD
;
303 mv
.top
.weight
= weight
;
305 mv
.bottom
.x
= mb
->PMV
[1][vector
][0];
306 mv
.bottom
.y
= mb
->PMV
[1][vector
][1];
307 mv
.bottom
.field_select
= (mb
->motion_vertical_field_select
& (field_select_mask
<< 2)) ?
308 PIPE_VIDEO_BOTTOM_FIELD
: PIPE_VIDEO_TOP_FIELD
;
309 mv
.bottom
.weight
= weight
;
312 default: // TODO: Support DUALPRIME and 16x8
316 mv
.top
.x
= mv
.top
.y
= 0;
317 mv
.top
.field_select
= PIPE_VIDEO_FRAME
;
318 mv
.top
.weight
= weight
;
320 mv
.bottom
.x
= mv
.bottom
.y
= 0;
321 mv
.bottom
.field_select
= PIPE_VIDEO_FRAME
;
322 mv
.bottom
.weight
= weight
;
328 UploadYcbcrBlocks(struct vl_mpeg12_decoder
*dec
,
329 struct vl_mpeg12_buffer
*buf
,
330 const struct pipe_mpeg12_macroblock
*mb
)
333 unsigned tb
, x
, y
, num_blocks
= 0;
338 if (!mb
->coded_block_pattern
)
341 intra
= mb
->macroblock_type
& PIPE_MPEG12_MB_TYPE_INTRA
? 1 : 0;
343 for (y
= 0; y
< 2; ++y
) {
344 for (x
= 0; x
< 2; ++x
) {
345 if (mb
->coded_block_pattern
& const_empty_block_mask_420
[0][y
][x
]) {
347 struct vl_ycbcr_block
*stream
= buf
->ycbcr_stream
[0];
348 stream
->x
= mb
->x
* 2 + x
;
349 stream
->y
= mb
->y
* 2 + y
;
350 stream
->intra
= intra
;
351 stream
->coding
= mb
->macroblock_modes
.bits
.dct_type
;
352 stream
->block_num
= buf
->block_num
++;
354 buf
->num_ycbcr_blocks
[0]++;
355 buf
->ycbcr_stream
[0]++;
362 /* TODO: Implement 422, 444 */
363 //assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
365 for (tb
= 1; tb
< 3; ++tb
) {
366 if (mb
->coded_block_pattern
& const_empty_block_mask_420
[tb
][0][0]) {
368 struct vl_ycbcr_block
*stream
= buf
->ycbcr_stream
[tb
];
371 stream
->intra
= intra
;
373 stream
->block_num
= buf
->block_num
++;
375 buf
->num_ycbcr_blocks
[tb
]++;
376 buf
->ycbcr_stream
[tb
]++;
382 memcpy(buf
->texels
, mb
->blocks
, 64 * sizeof(short) * num_blocks
);
383 buf
->texels
+= 64 * num_blocks
;
387 vl_mpeg12_destroy(struct pipe_video_decoder
*decoder
)
389 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
393 /* Asserted in softpipe_delete_fs_state() for some reason */
394 dec
->base
.context
->bind_vs_state(dec
->base
.context
, NULL
);
395 dec
->base
.context
->bind_fs_state(dec
->base
.context
, NULL
);
397 dec
->base
.context
->delete_depth_stencil_alpha_state(dec
->base
.context
, dec
->dsa
);
398 dec
->base
.context
->delete_sampler_state(dec
->base
.context
, dec
->sampler_ycbcr
);
400 vl_mc_cleanup(&dec
->mc_y
);
401 vl_mc_cleanup(&dec
->mc_c
);
402 dec
->mc_source
->destroy(dec
->mc_source
);
404 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
405 vl_idct_cleanup(&dec
->idct_y
);
406 vl_idct_cleanup(&dec
->idct_c
);
407 dec
->idct_source
->destroy(dec
->idct_source
);
410 vl_zscan_cleanup(&dec
->zscan_y
);
411 vl_zscan_cleanup(&dec
->zscan_c
);
413 dec
->base
.context
->delete_vertex_elements_state(dec
->base
.context
, dec
->ves_ycbcr
);
414 dec
->base
.context
->delete_vertex_elements_state(dec
->base
.context
, dec
->ves_mv
);
416 pipe_resource_reference(&dec
->quads
.buffer
, NULL
);
417 pipe_resource_reference(&dec
->pos
.buffer
, NULL
);
419 pipe_sampler_view_reference(&dec
->zscan_linear
, NULL
);
420 pipe_sampler_view_reference(&dec
->zscan_normal
, NULL
);
421 pipe_sampler_view_reference(&dec
->zscan_alternate
, NULL
);
427 vl_mpeg12_create_buffer(struct pipe_video_decoder
*decoder
)
429 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
430 struct vl_mpeg12_buffer
*buffer
;
434 buffer
= CALLOC_STRUCT(vl_mpeg12_buffer
);
438 if (!vl_vb_init(&buffer
->vertex_stream
, dec
->base
.context
,
439 dec
->base
.width
/ MACROBLOCK_WIDTH
,
440 dec
->base
.height
/ MACROBLOCK_HEIGHT
))
441 goto error_vertex_buffer
;
443 if (!init_mc_buffer(dec
, buffer
))
446 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
447 if (!init_idct_buffer(dec
, buffer
))
450 if (!init_zscan_buffer(dec
, buffer
))
453 if (dec
->base
.entrypoint
== PIPE_VIDEO_ENTRYPOINT_BITSTREAM
)
454 vl_mpg12_bs_init(&buffer
->bs
, decoder
);
459 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
460 cleanup_idct_buffer(buffer
);
463 cleanup_mc_buffer(buffer
);
466 vl_vb_cleanup(&buffer
->vertex_stream
);
474 vl_mpeg12_destroy_buffer(struct pipe_video_decoder
*decoder
, void *buffer
)
476 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
477 struct vl_mpeg12_buffer
*buf
= buffer
;
481 cleanup_zscan_buffer(buf
);
483 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
484 cleanup_idct_buffer(buf
);
486 cleanup_mc_buffer(buf
);
488 vl_vb_cleanup(&buf
->vertex_stream
);
494 vl_mpeg12_set_decode_buffer(struct pipe_video_decoder
*decoder
, void *buffer
)
496 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
498 assert(dec
&& buffer
);
500 dec
->current_buffer
= buffer
;
504 vl_mpeg12_set_picture_parameters(struct pipe_video_decoder
*decoder
,
505 struct pipe_picture_desc
*picture
)
507 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
508 struct pipe_mpeg12_picture_desc
*pic
= (struct pipe_mpeg12_picture_desc
*)picture
;
512 dec
->picture_desc
= *pic
;
516 vl_mpeg12_set_quant_matrix(struct pipe_video_decoder
*decoder
,
517 const struct pipe_quant_matrix
*matrix
)
519 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
520 const struct pipe_mpeg12_quant_matrix
*m
= (const struct pipe_mpeg12_quant_matrix
*)matrix
;
523 assert(matrix
->codec
== PIPE_VIDEO_CODEC_MPEG12
);
525 memcpy(dec
->intra_matrix
, m
->intra_matrix
, 64);
526 memcpy(dec
->non_intra_matrix
, m
->non_intra_matrix
, 64);
530 vl_mpeg12_set_decode_target(struct pipe_video_decoder
*decoder
,
531 struct pipe_video_buffer
*target
)
533 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
534 struct pipe_surface
**surfaces
;
539 surfaces
= target
->get_surfaces(target
);
540 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
541 pipe_surface_reference(&dec
->target_surfaces
[i
], surfaces
[i
]);
545 vl_mpeg12_set_reference_frames(struct pipe_video_decoder
*decoder
,
546 struct pipe_video_buffer
**ref_frames
,
547 unsigned num_ref_frames
)
549 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
550 struct pipe_sampler_view
**sv
;
554 assert(num_ref_frames
<= VL_MAX_REF_FRAMES
);
556 for (i
= 0; i
< num_ref_frames
; ++i
) {
557 sv
= ref_frames
[i
]->get_sampler_view_planes(ref_frames
[i
]);
558 for (j
= 0; j
< VL_MAX_PLANES
; ++j
)
559 pipe_sampler_view_reference(&dec
->ref_frames
[i
][j
], sv
[j
]);
562 for (; i
< VL_MAX_REF_FRAMES
; ++i
)
563 for (j
= 0; j
< VL_MAX_PLANES
; ++j
)
564 pipe_sampler_view_reference(&dec
->ref_frames
[i
][j
], NULL
);
568 vl_mpeg12_begin_frame(struct pipe_video_decoder
*decoder
)
570 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
571 struct vl_mpeg12_buffer
*buf
;
573 struct pipe_resource
*tex
;
574 struct pipe_box rect
= { 0, 0, 0, 1, 1, 1 };
580 buf
= dec
->current_buffer
;
583 if (dec
->base
.entrypoint
== PIPE_VIDEO_ENTRYPOINT_BITSTREAM
)
584 dec
->intra_matrix
[0] = 1 << (7 - dec
->picture_desc
.intra_dc_precision
);
586 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
587 struct vl_zscan
*zscan
= i
== 0 ? &dec
->zscan_y
: &dec
->zscan_c
;
588 vl_zscan_upload_quant(zscan
, &buf
->zscan
[i
], dec
->intra_matrix
, true);
589 vl_zscan_upload_quant(zscan
, &buf
->zscan
[i
], dec
->non_intra_matrix
, false);
592 vl_vb_map(&buf
->vertex_stream
, dec
->base
.context
);
594 tex
= buf
->zscan_source
->texture
;
595 rect
.width
= tex
->width0
;
596 rect
.height
= tex
->height0
;
598 buf
->tex_transfer
= dec
->base
.context
->get_transfer
600 dec
->base
.context
, tex
,
601 0, PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
606 buf
->texels
= dec
->base
.context
->transfer_map(dec
->base
.context
, buf
->tex_transfer
);
608 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
609 buf
->ycbcr_stream
[i
] = vl_vb_get_ycbcr_stream(&buf
->vertex_stream
, i
);
610 buf
->num_ycbcr_blocks
[i
] = 0;
613 for (i
= 0; i
< VL_MAX_REF_FRAMES
; ++i
)
614 buf
->mv_stream
[i
] = vl_vb_get_mv_stream(&buf
->vertex_stream
, i
);
616 if (dec
->base
.entrypoint
== PIPE_VIDEO_ENTRYPOINT_BITSTREAM
) {
617 vl_mpg12_bs_set_picture_desc(&buf
->bs
, &dec
->picture_desc
);
621 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
622 vl_zscan_set_layout(&buf
->zscan
[i
], dec
->zscan_linear
);
627 vl_mpeg12_decode_macroblock(struct pipe_video_decoder
*decoder
,
628 const struct pipe_macroblock
*macroblocks
,
629 unsigned num_macroblocks
)
631 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
632 const struct pipe_mpeg12_macroblock
*mb
= (const struct pipe_mpeg12_macroblock
*)macroblocks
;
633 struct vl_mpeg12_buffer
*buf
;
635 unsigned i
, j
, mv_weights
[2];
637 assert(dec
&& dec
->current_buffer
);
638 assert(macroblocks
&& macroblocks
->codec
== PIPE_VIDEO_CODEC_MPEG12
);
640 buf
= dec
->current_buffer
;
643 for (; num_macroblocks
> 0; --num_macroblocks
) {
644 unsigned mb_addr
= mb
->y
* dec
->width_in_macroblocks
+ mb
->x
;
646 if (mb
->macroblock_type
& (PIPE_MPEG12_MB_TYPE_PATTERN
| PIPE_MPEG12_MB_TYPE_INTRA
))
647 UploadYcbcrBlocks(dec
, buf
, mb
);
649 MacroBlockTypeToPipeWeights(mb
, mv_weights
);
651 for (i
= 0; i
< 2; ++i
) {
652 if (!dec
->ref_frames
[i
][0]) continue;
654 buf
->mv_stream
[i
][mb_addr
] = MotionVectorToPipe
657 i
? PIPE_MPEG12_FS_FIRST_BACKWARD
: PIPE_MPEG12_FS_FIRST_FORWARD
,
662 /* see section 7.6.6 of the spec */
663 if (mb
->num_skipped_macroblocks
> 0) {
664 struct vl_motionvector skipped_mv
[2];
666 if (dec
->ref_frames
[0][0] && !dec
->ref_frames
[1][0]) {
667 skipped_mv
[0].top
.x
= skipped_mv
[0].top
.y
= 0;
668 skipped_mv
[0].top
.weight
= PIPE_VIDEO_MV_WEIGHT_MAX
;
670 skipped_mv
[0] = buf
->mv_stream
[0][mb_addr
];
671 skipped_mv
[1] = buf
->mv_stream
[1][mb_addr
];
673 skipped_mv
[0].top
.field_select
= PIPE_VIDEO_FRAME
;
674 skipped_mv
[1].top
.field_select
= PIPE_VIDEO_FRAME
;
676 skipped_mv
[0].bottom
= skipped_mv
[0].top
;
677 skipped_mv
[1].bottom
= skipped_mv
[1].top
;
680 for (i
= 0; i
< mb
->num_skipped_macroblocks
; ++i
, ++mb_addr
) {
681 for (j
= 0; j
< 2; ++j
) {
682 if (!dec
->ref_frames
[j
][0]) continue;
683 buf
->mv_stream
[j
][mb_addr
] = skipped_mv
[j
];
694 vl_mpeg12_decode_bitstream(struct pipe_video_decoder
*decoder
,
695 unsigned num_buffers
,
696 const void * const *buffers
,
697 const unsigned *sizes
)
699 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
700 struct vl_mpeg12_buffer
*buf
;
704 assert(dec
&& dec
->current_buffer
);
706 buf
= dec
->current_buffer
;
709 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
710 vl_zscan_set_layout(&buf
->zscan
[i
], dec
->picture_desc
.alternate_scan
?
711 dec
->zscan_alternate
: dec
->zscan_normal
);
713 vl_mpg12_bs_decode(&buf
->bs
, num_buffers
, buffers
, sizes
);
717 vl_mpeg12_end_frame(struct pipe_video_decoder
*decoder
)
719 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
720 struct pipe_sampler_view
**mc_source_sv
;
721 struct pipe_vertex_buffer vb
[3];
722 struct vl_mpeg12_buffer
*buf
;
724 unsigned i
, j
, component
;
725 unsigned nr_components
;
727 assert(dec
&& dec
->current_buffer
);
729 buf
= dec
->current_buffer
;
731 vl_vb_unmap(&buf
->vertex_stream
, dec
->base
.context
);
733 dec
->base
.context
->transfer_unmap(dec
->base
.context
, buf
->tex_transfer
);
734 dec
->base
.context
->transfer_destroy(dec
->base
.context
, buf
->tex_transfer
);
739 dec
->base
.context
->bind_vertex_elements_state(dec
->base
.context
, dec
->ves_mv
);
740 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
741 if (!dec
->target_surfaces
[i
]) continue;
743 vl_mc_set_surface(&buf
->mc
[i
], dec
->target_surfaces
[i
]);
745 for (j
= 0; j
< VL_MAX_REF_FRAMES
; ++j
) {
746 if (!dec
->ref_frames
[j
][i
]) continue;
748 vb
[2] = vl_vb_get_mv(&buf
->vertex_stream
, j
);;
749 dec
->base
.context
->set_vertex_buffers(dec
->base
.context
, 3, vb
);
751 vl_mc_render_ref(i
? &dec
->mc_c
: &dec
->mc_y
, &buf
->mc
[i
], dec
->ref_frames
[j
][i
]);
755 dec
->base
.context
->bind_vertex_elements_state(dec
->base
.context
, dec
->ves_ycbcr
);
756 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
757 if (!buf
->num_ycbcr_blocks
[i
]) continue;
759 vb
[1] = vl_vb_get_ycbcr(&buf
->vertex_stream
, i
);
760 dec
->base
.context
->set_vertex_buffers(dec
->base
.context
, 2, vb
);
762 vl_zscan_render(i
? &dec
->zscan_c
: & dec
->zscan_y
, &buf
->zscan
[i
] , buf
->num_ycbcr_blocks
[i
]);
764 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
765 vl_idct_flush(i
? &dec
->idct_c
: &dec
->idct_y
, &buf
->idct
[i
], buf
->num_ycbcr_blocks
[i
]);
768 mc_source_sv
= dec
->mc_source
->get_sampler_view_planes(dec
->mc_source
);
769 for (i
= 0, component
= 0; i
< VL_MAX_PLANES
; ++i
) {
770 if (!dec
->target_surfaces
[i
]) continue;
772 nr_components
= util_format_get_nr_components(dec
->target_surfaces
[i
]->texture
->format
);
773 for (j
= 0; j
< nr_components
; ++j
, ++component
) {
774 if (!buf
->num_ycbcr_blocks
[i
]) continue;
776 vb
[1] = vl_vb_get_ycbcr(&buf
->vertex_stream
, component
);
777 dec
->base
.context
->set_vertex_buffers(dec
->base
.context
, 2, vb
);
779 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
780 vl_idct_prepare_stage2(i
? &dec
->idct_c
: &dec
->idct_y
, &buf
->idct
[component
]);
782 dec
->base
.context
->set_fragment_sampler_views(dec
->base
.context
, 1, &mc_source_sv
[component
]);
783 dec
->base
.context
->bind_fragment_sampler_states(dec
->base
.context
, 1, &dec
->sampler_ycbcr
);
785 vl_mc_render_ycbcr(i
? &dec
->mc_c
: &dec
->mc_y
, &buf
->mc
[i
], j
, buf
->num_ycbcr_blocks
[component
]);
791 vl_mpeg12_flush(struct pipe_video_decoder
*decoder
)
795 //Noop, for shaders it is much faster to flush everything in end_frame
799 init_pipe_state(struct vl_mpeg12_decoder
*dec
)
801 struct pipe_depth_stencil_alpha_state dsa
;
802 struct pipe_sampler_state sampler
;
807 memset(&dsa
, 0, sizeof dsa
);
808 dsa
.depth
.enabled
= 0;
809 dsa
.depth
.writemask
= 0;
810 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
811 for (i
= 0; i
< 2; ++i
) {
812 dsa
.stencil
[i
].enabled
= 0;
813 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
814 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
815 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
816 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
817 dsa
.stencil
[i
].valuemask
= 0;
818 dsa
.stencil
[i
].writemask
= 0;
820 dsa
.alpha
.enabled
= 0;
821 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
822 dsa
.alpha
.ref_value
= 0;
823 dec
->dsa
= dec
->base
.context
->create_depth_stencil_alpha_state(dec
->base
.context
, &dsa
);
824 dec
->base
.context
->bind_depth_stencil_alpha_state(dec
->base
.context
, dec
->dsa
);
826 memset(&sampler
, 0, sizeof(sampler
));
827 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
828 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
829 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
830 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
831 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
832 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
833 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
834 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
835 sampler
.normalized_coords
= 1;
836 dec
->sampler_ycbcr
= dec
->base
.context
->create_sampler_state(dec
->base
.context
, &sampler
);
837 if (!dec
->sampler_ycbcr
)
843 static const struct format_config
*
844 find_format_config(struct vl_mpeg12_decoder
*dec
, const struct format_config configs
[], unsigned num_configs
)
846 struct pipe_screen
*screen
;
851 screen
= dec
->base
.context
->screen
;
853 for (i
= 0; i
< num_configs
; ++i
) {
854 if (!screen
->is_format_supported(screen
, configs
[i
].zscan_source_format
, PIPE_TEXTURE_2D
,
855 1, PIPE_BIND_SAMPLER_VIEW
))
858 if (configs
[i
].idct_source_format
!= PIPE_FORMAT_NONE
) {
859 if (!screen
->is_format_supported(screen
, configs
[i
].idct_source_format
, PIPE_TEXTURE_2D
,
860 1, PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
))
863 if (!screen
->is_format_supported(screen
, configs
[i
].mc_source_format
, PIPE_TEXTURE_3D
,
864 1, PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
))
867 if (!screen
->is_format_supported(screen
, configs
[i
].mc_source_format
, PIPE_TEXTURE_2D
,
868 1, PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
))
878 init_zscan(struct vl_mpeg12_decoder
*dec
, const struct format_config
* format_config
)
880 unsigned num_channels
;
884 dec
->zscan_source_format
= format_config
->zscan_source_format
;
885 dec
->zscan_linear
= vl_zscan_layout(dec
->base
.context
, vl_zscan_linear
, dec
->blocks_per_line
);
886 dec
->zscan_normal
= vl_zscan_layout(dec
->base
.context
, vl_zscan_normal
, dec
->blocks_per_line
);
887 dec
->zscan_alternate
= vl_zscan_layout(dec
->base
.context
, vl_zscan_alternate
, dec
->blocks_per_line
);
889 num_channels
= dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
? 4 : 1;
891 if (!vl_zscan_init(&dec
->zscan_y
, dec
->base
.context
, dec
->base
.width
, dec
->base
.height
,
892 dec
->blocks_per_line
, dec
->num_blocks
, num_channels
))
895 if (!vl_zscan_init(&dec
->zscan_c
, dec
->base
.context
, dec
->chroma_width
, dec
->chroma_height
,
896 dec
->blocks_per_line
, dec
->num_blocks
, num_channels
))
903 init_idct(struct vl_mpeg12_decoder
*dec
, const struct format_config
* format_config
)
905 unsigned nr_of_idct_render_targets
, max_inst
;
906 enum pipe_format formats
[3];
908 struct pipe_sampler_view
*matrix
= NULL
;
910 nr_of_idct_render_targets
= dec
->base
.context
->screen
->get_param
912 dec
->base
.context
->screen
, PIPE_CAP_MAX_RENDER_TARGETS
915 max_inst
= dec
->base
.context
->screen
->get_shader_param
917 dec
->base
.context
->screen
, PIPE_SHADER_FRAGMENT
, PIPE_SHADER_CAP_MAX_INSTRUCTIONS
920 // Just assume we need 32 inst per render target, not 100% true, but should work in most cases
921 if (nr_of_idct_render_targets
>= 4 && max_inst
>= 32*4)
922 // more than 4 render targets usually doesn't makes any seens
923 nr_of_idct_render_targets
= 4;
925 nr_of_idct_render_targets
= 1;
927 formats
[0] = formats
[1] = formats
[2] = format_config
->idct_source_format
;
928 dec
->idct_source
= vl_video_buffer_create_ex
930 dec
->base
.context
, dec
->base
.width
/ 4, dec
->base
.height
, 1,
931 dec
->base
.chroma_format
, formats
, PIPE_USAGE_STATIC
934 if (!dec
->idct_source
)
935 goto error_idct_source
;
937 formats
[0] = formats
[1] = formats
[2] = format_config
->mc_source_format
;
938 dec
->mc_source
= vl_video_buffer_create_ex
940 dec
->base
.context
, dec
->base
.width
/ nr_of_idct_render_targets
,
941 dec
->base
.height
/ 4, nr_of_idct_render_targets
,
942 dec
->base
.chroma_format
, formats
, PIPE_USAGE_STATIC
946 goto error_mc_source
;
948 if (!(matrix
= vl_idct_upload_matrix(dec
->base
.context
, format_config
->idct_scale
)))
951 if (!vl_idct_init(&dec
->idct_y
, dec
->base
.context
, dec
->base
.width
, dec
->base
.height
,
952 nr_of_idct_render_targets
, matrix
, matrix
))
955 if(!vl_idct_init(&dec
->idct_c
, dec
->base
.context
, dec
->chroma_width
, dec
->chroma_height
,
956 nr_of_idct_render_targets
, matrix
, matrix
))
959 pipe_sampler_view_reference(&matrix
, NULL
);
964 vl_idct_cleanup(&dec
->idct_y
);
967 pipe_sampler_view_reference(&matrix
, NULL
);
970 dec
->mc_source
->destroy(dec
->mc_source
);
973 dec
->idct_source
->destroy(dec
->idct_source
);
980 init_mc_source_widthout_idct(struct vl_mpeg12_decoder
*dec
, const struct format_config
* format_config
)
982 enum pipe_format formats
[3];
984 formats
[0] = formats
[1] = formats
[2] = format_config
->mc_source_format
;
985 dec
->mc_source
= vl_video_buffer_create_ex
987 dec
->base
.context
, dec
->base
.width
, dec
->base
.height
, 1,
988 dec
->base
.chroma_format
, formats
, PIPE_USAGE_STATIC
991 return dec
->mc_source
!= NULL
;
995 mc_vert_shader_callback(void *priv
, struct vl_mc
*mc
,
996 struct ureg_program
*shader
,
997 unsigned first_output
,
1000 struct vl_mpeg12_decoder
*dec
= priv
;
1001 struct ureg_dst o_vtex
;
1006 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
1007 struct vl_idct
*idct
= mc
== &dec
->mc_y
? &dec
->idct_y
: &dec
->idct_c
;
1008 vl_idct_stage2_vert_shader(idct
, shader
, first_output
, tex
);
1010 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, first_output
);
1011 ureg_MOV(shader
, ureg_writemask(o_vtex
, TGSI_WRITEMASK_XY
), ureg_src(tex
));
1016 mc_frag_shader_callback(void *priv
, struct vl_mc
*mc
,
1017 struct ureg_program
*shader
,
1018 unsigned first_input
,
1019 struct ureg_dst dst
)
1021 struct vl_mpeg12_decoder
*dec
= priv
;
1022 struct ureg_src src
, sampler
;
1027 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
1028 struct vl_idct
*idct
= mc
== &dec
->mc_y
? &dec
->idct_y
: &dec
->idct_c
;
1029 vl_idct_stage2_frag_shader(idct
, shader
, first_input
, dst
);
1031 src
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, first_input
, TGSI_INTERPOLATE_LINEAR
);
1032 sampler
= ureg_DECL_sampler(shader
, 0);
1033 ureg_TEX(shader
, dst
, TGSI_TEXTURE_2D
, src
, sampler
);
1037 struct pipe_video_decoder
*
1038 vl_create_mpeg12_decoder(struct pipe_context
*context
,
1039 enum pipe_video_profile profile
,
1040 enum pipe_video_entrypoint entrypoint
,
1041 enum pipe_video_chroma_format chroma_format
,
1042 unsigned width
, unsigned height
, unsigned max_references
)
1044 const unsigned block_size_pixels
= BLOCK_WIDTH
* BLOCK_HEIGHT
;
1045 const struct format_config
*format_config
;
1046 struct vl_mpeg12_decoder
*dec
;
1048 assert(u_reduce_video_profile(profile
) == PIPE_VIDEO_CODEC_MPEG12
);
1050 dec
= CALLOC_STRUCT(vl_mpeg12_decoder
);
1055 dec
->base
.context
= context
;
1056 dec
->base
.profile
= profile
;
1057 dec
->base
.entrypoint
= entrypoint
;
1058 dec
->base
.chroma_format
= chroma_format
;
1059 dec
->base
.width
= width
;
1060 dec
->base
.height
= height
;
1061 dec
->base
.max_references
= max_references
;
1063 dec
->base
.destroy
= vl_mpeg12_destroy
;
1064 dec
->base
.create_buffer
= vl_mpeg12_create_buffer
;
1065 dec
->base
.destroy_buffer
= vl_mpeg12_destroy_buffer
;
1066 dec
->base
.set_decode_buffer
= vl_mpeg12_set_decode_buffer
;
1067 dec
->base
.set_picture_parameters
= vl_mpeg12_set_picture_parameters
;
1068 dec
->base
.set_quant_matrix
= vl_mpeg12_set_quant_matrix
;
1069 dec
->base
.set_decode_target
= vl_mpeg12_set_decode_target
;
1070 dec
->base
.set_reference_frames
= vl_mpeg12_set_reference_frames
;
1071 dec
->base
.begin_frame
= vl_mpeg12_begin_frame
;
1072 dec
->base
.decode_macroblock
= vl_mpeg12_decode_macroblock
;
1073 dec
->base
.decode_bitstream
= vl_mpeg12_decode_bitstream
;
1074 dec
->base
.end_frame
= vl_mpeg12_end_frame
;
1075 dec
->base
.flush
= vl_mpeg12_flush
;
1077 dec
->blocks_per_line
= MAX2(util_next_power_of_two(dec
->base
.width
) / block_size_pixels
, 4);
1078 dec
->num_blocks
= (dec
->base
.width
* dec
->base
.height
) / block_size_pixels
;
1079 dec
->width_in_macroblocks
= align(dec
->base
.width
, MACROBLOCK_WIDTH
) / MACROBLOCK_WIDTH
;
1081 /* TODO: Implement 422, 444 */
1082 assert(dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
1084 if (dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
1085 dec
->chroma_width
= dec
->base
.width
/ 2;
1086 dec
->chroma_height
= dec
->base
.height
/ 2;
1087 dec
->num_blocks
= dec
->num_blocks
* 2;
1088 } else if (dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_422
) {
1089 dec
->chroma_width
= dec
->base
.width
;
1090 dec
->chroma_height
= dec
->base
.height
/ 2;
1091 dec
->num_blocks
= dec
->num_blocks
* 2 + dec
->num_blocks
;
1093 dec
->chroma_width
= dec
->base
.width
;
1094 dec
->chroma_height
= dec
->base
.height
;
1095 dec
->num_blocks
= dec
->num_blocks
* 3;
1098 dec
->quads
= vl_vb_upload_quads(dec
->base
.context
);
1099 dec
->pos
= vl_vb_upload_pos(
1101 dec
->base
.width
/ MACROBLOCK_WIDTH
,
1102 dec
->base
.height
/ MACROBLOCK_HEIGHT
1105 dec
->ves_ycbcr
= vl_vb_get_ves_ycbcr(dec
->base
.context
);
1106 dec
->ves_mv
= vl_vb_get_ves_mv(dec
->base
.context
);
1108 switch (entrypoint
) {
1109 case PIPE_VIDEO_ENTRYPOINT_BITSTREAM
:
1110 format_config
= find_format_config(dec
, bitstream_format_config
, num_bitstream_format_configs
);
1113 case PIPE_VIDEO_ENTRYPOINT_IDCT
:
1114 format_config
= find_format_config(dec
, idct_format_config
, num_idct_format_configs
);
1117 case PIPE_VIDEO_ENTRYPOINT_MC
:
1118 format_config
= find_format_config(dec
, mc_format_config
, num_mc_format_configs
);
1127 if (!format_config
) {
1132 if (!init_zscan(dec
, format_config
))
1135 if (entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
1136 if (!init_idct(dec
, format_config
))
1139 if (!init_mc_source_widthout_idct(dec
, format_config
))
1143 if (!vl_mc_init(&dec
->mc_y
, dec
->base
.context
, dec
->base
.width
, dec
->base
.height
,
1144 MACROBLOCK_HEIGHT
, format_config
->mc_scale
,
1145 mc_vert_shader_callback
, mc_frag_shader_callback
, dec
))
1149 if (!vl_mc_init(&dec
->mc_c
, dec
->base
.context
, dec
->base
.width
, dec
->base
.height
,
1150 BLOCK_HEIGHT
, format_config
->mc_scale
,
1151 mc_vert_shader_callback
, mc_frag_shader_callback
, dec
))
1154 if (!init_pipe_state(dec
))
1155 goto error_pipe_state
;
1157 memset(dec
->intra_matrix
, 0x10, 64);
1158 memset(dec
->non_intra_matrix
, 0x10, 64);
1163 vl_mc_cleanup(&dec
->mc_c
);
1166 vl_mc_cleanup(&dec
->mc_y
);
1169 if (entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
1170 vl_idct_cleanup(&dec
->idct_y
);
1171 vl_idct_cleanup(&dec
->idct_c
);
1172 dec
->idct_source
->destroy(dec
->idct_source
);
1174 dec
->mc_source
->destroy(dec
->mc_source
);
1177 vl_zscan_cleanup(&dec
->zscan_y
);
1178 vl_zscan_cleanup(&dec
->zscan_c
);