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_buffer(void *buffer
)
389 struct vl_mpeg12_buffer
*buf
= buffer
;
393 cleanup_zscan_buffer(buf
);
394 cleanup_idct_buffer(buf
);
395 cleanup_mc_buffer(buf
);
396 vl_vb_cleanup(&buf
->vertex_stream
);
402 vl_mpeg12_destroy(struct pipe_video_decoder
*decoder
)
404 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
409 /* Asserted in softpipe_delete_fs_state() for some reason */
410 dec
->base
.context
->bind_vs_state(dec
->base
.context
, NULL
);
411 dec
->base
.context
->bind_fs_state(dec
->base
.context
, NULL
);
413 dec
->base
.context
->delete_depth_stencil_alpha_state(dec
->base
.context
, dec
->dsa
);
414 dec
->base
.context
->delete_sampler_state(dec
->base
.context
, dec
->sampler_ycbcr
);
416 vl_mc_cleanup(&dec
->mc_y
);
417 vl_mc_cleanup(&dec
->mc_c
);
418 dec
->mc_source
->destroy(dec
->mc_source
);
420 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
421 vl_idct_cleanup(&dec
->idct_y
);
422 vl_idct_cleanup(&dec
->idct_c
);
423 dec
->idct_source
->destroy(dec
->idct_source
);
426 vl_zscan_cleanup(&dec
->zscan_y
);
427 vl_zscan_cleanup(&dec
->zscan_c
);
429 dec
->base
.context
->delete_vertex_elements_state(dec
->base
.context
, dec
->ves_ycbcr
);
430 dec
->base
.context
->delete_vertex_elements_state(dec
->base
.context
, dec
->ves_mv
);
432 pipe_resource_reference(&dec
->quads
.buffer
, NULL
);
433 pipe_resource_reference(&dec
->pos
.buffer
, NULL
);
435 pipe_sampler_view_reference(&dec
->zscan_linear
, NULL
);
436 pipe_sampler_view_reference(&dec
->zscan_normal
, NULL
);
437 pipe_sampler_view_reference(&dec
->zscan_alternate
, NULL
);
439 for (i
= 0; i
< 4; ++i
)
440 if (dec
->dec_buffers
[i
])
441 vl_mpeg12_destroy_buffer(dec
->dec_buffers
[i
]);
446 static struct vl_mpeg12_buffer
*
447 vl_mpeg12_get_decode_buffer(struct vl_mpeg12_decoder
*dec
)
449 struct vl_mpeg12_buffer
*buffer
;
453 buffer
= vl_video_buffer_get_associated_data(dec
->target
, &dec
->base
);
457 buffer
= dec
->dec_buffers
[dec
->current_buffer
];
461 buffer
= CALLOC_STRUCT(vl_mpeg12_buffer
);
465 if (!vl_vb_init(&buffer
->vertex_stream
, dec
->base
.context
,
466 dec
->base
.width
/ MACROBLOCK_WIDTH
,
467 dec
->base
.height
/ MACROBLOCK_HEIGHT
))
468 goto error_vertex_buffer
;
470 if (!init_mc_buffer(dec
, buffer
))
473 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
474 if (!init_idct_buffer(dec
, buffer
))
477 if (!init_zscan_buffer(dec
, buffer
))
480 if (dec
->base
.entrypoint
== PIPE_VIDEO_ENTRYPOINT_BITSTREAM
)
481 vl_mpg12_bs_init(&buffer
->bs
, &dec
->base
);
483 if (dec
->expect_chunked_decode
)
484 vl_video_buffer_set_associated_data(dec
->target
, &dec
->base
,
485 buffer
, vl_mpeg12_destroy_buffer
);
487 dec
->dec_buffers
[dec
->current_buffer
] = buffer
;
492 cleanup_idct_buffer(buffer
);
495 cleanup_mc_buffer(buffer
);
498 vl_vb_cleanup(&buffer
->vertex_stream
);
506 vl_mpeg12_set_picture_parameters(struct pipe_video_decoder
*decoder
,
507 struct pipe_picture_desc
*picture
)
509 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
510 struct pipe_mpeg12_picture_desc
*pic
= (struct pipe_mpeg12_picture_desc
*)picture
;
514 dec
->picture_desc
= *pic
;
518 vl_mpeg12_set_quant_matrix(struct pipe_video_decoder
*decoder
,
519 const struct pipe_quant_matrix
*matrix
)
521 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
522 const struct pipe_mpeg12_quant_matrix
*m
= (const struct pipe_mpeg12_quant_matrix
*)matrix
;
525 assert(matrix
->codec
== PIPE_VIDEO_CODEC_MPEG12
);
527 memcpy(dec
->intra_matrix
, m
->intra_matrix
, 64);
528 memcpy(dec
->non_intra_matrix
, m
->non_intra_matrix
, 64);
532 vl_mpeg12_set_decode_target(struct pipe_video_decoder
*decoder
,
533 struct pipe_video_buffer
*target
)
535 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
536 struct pipe_surface
**surfaces
;
541 dec
->target
= target
;
542 surfaces
= target
->get_surfaces(target
);
543 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
544 pipe_surface_reference(&dec
->target_surfaces
[i
], surfaces
[i
]);
548 vl_mpeg12_set_reference_frames(struct pipe_video_decoder
*decoder
,
549 struct pipe_video_buffer
**ref_frames
,
550 unsigned num_ref_frames
)
552 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
553 struct pipe_sampler_view
**sv
;
557 assert(num_ref_frames
<= VL_MAX_REF_FRAMES
);
559 for (i
= 0; i
< num_ref_frames
; ++i
) {
560 sv
= ref_frames
[i
]->get_sampler_view_planes(ref_frames
[i
]);
561 for (j
= 0; j
< VL_MAX_PLANES
; ++j
)
562 pipe_sampler_view_reference(&dec
->ref_frames
[i
][j
], sv
[j
]);
565 for (; i
< VL_MAX_REF_FRAMES
; ++i
)
566 for (j
= 0; j
< VL_MAX_PLANES
; ++j
)
567 pipe_sampler_view_reference(&dec
->ref_frames
[i
][j
], NULL
);
571 vl_mpeg12_begin_frame(struct pipe_video_decoder
*decoder
)
573 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
574 struct vl_mpeg12_buffer
*buf
;
576 struct pipe_resource
*tex
;
577 struct pipe_box rect
= { 0, 0, 0, 1, 1, 1 };
581 assert(dec
&& dec
->target
);
583 buf
= vl_mpeg12_get_decode_buffer(dec
);
586 if (dec
->base
.entrypoint
== PIPE_VIDEO_ENTRYPOINT_BITSTREAM
)
587 dec
->intra_matrix
[0] = 1 << (7 - dec
->picture_desc
.intra_dc_precision
);
589 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
590 struct vl_zscan
*zscan
= i
== 0 ? &dec
->zscan_y
: &dec
->zscan_c
;
591 vl_zscan_upload_quant(zscan
, &buf
->zscan
[i
], dec
->intra_matrix
, true);
592 vl_zscan_upload_quant(zscan
, &buf
->zscan
[i
], dec
->non_intra_matrix
, false);
595 vl_vb_map(&buf
->vertex_stream
, dec
->base
.context
);
597 tex
= buf
->zscan_source
->texture
;
598 rect
.width
= tex
->width0
;
599 rect
.height
= tex
->height0
;
601 buf
->tex_transfer
= dec
->base
.context
->get_transfer
603 dec
->base
.context
, tex
,
604 0, PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD_RANGE
,
609 buf
->texels
= dec
->base
.context
->transfer_map(dec
->base
.context
, buf
->tex_transfer
);
611 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
612 buf
->ycbcr_stream
[i
] = vl_vb_get_ycbcr_stream(&buf
->vertex_stream
, i
);
613 buf
->num_ycbcr_blocks
[i
] = 0;
616 for (i
= 0; i
< VL_MAX_REF_FRAMES
; ++i
)
617 buf
->mv_stream
[i
] = vl_vb_get_mv_stream(&buf
->vertex_stream
, i
);
619 if (dec
->base
.entrypoint
== PIPE_VIDEO_ENTRYPOINT_BITSTREAM
) {
620 vl_mpg12_bs_set_picture_desc(&buf
->bs
, &dec
->picture_desc
);
624 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
625 vl_zscan_set_layout(&buf
->zscan
[i
], dec
->zscan_linear
);
630 vl_mpeg12_decode_macroblock(struct pipe_video_decoder
*decoder
,
631 const struct pipe_macroblock
*macroblocks
,
632 unsigned num_macroblocks
)
634 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
635 const struct pipe_mpeg12_macroblock
*mb
= (const struct pipe_mpeg12_macroblock
*)macroblocks
;
636 struct vl_mpeg12_buffer
*buf
;
638 unsigned i
, j
, mv_weights
[2];
640 assert(dec
&& dec
->target
);
641 assert(macroblocks
&& macroblocks
->codec
== PIPE_VIDEO_CODEC_MPEG12
);
643 buf
= vl_mpeg12_get_decode_buffer(dec
);
646 for (; num_macroblocks
> 0; --num_macroblocks
) {
647 unsigned mb_addr
= mb
->y
* dec
->width_in_macroblocks
+ mb
->x
;
649 if (mb
->macroblock_type
& (PIPE_MPEG12_MB_TYPE_PATTERN
| PIPE_MPEG12_MB_TYPE_INTRA
))
650 UploadYcbcrBlocks(dec
, buf
, mb
);
652 MacroBlockTypeToPipeWeights(mb
, mv_weights
);
654 for (i
= 0; i
< 2; ++i
) {
655 if (!dec
->ref_frames
[i
][0]) continue;
657 buf
->mv_stream
[i
][mb_addr
] = MotionVectorToPipe
660 i
? PIPE_MPEG12_FS_FIRST_BACKWARD
: PIPE_MPEG12_FS_FIRST_FORWARD
,
665 /* see section 7.6.6 of the spec */
666 if (mb
->num_skipped_macroblocks
> 0) {
667 struct vl_motionvector skipped_mv
[2];
669 if (dec
->ref_frames
[0][0] && !dec
->ref_frames
[1][0]) {
670 skipped_mv
[0].top
.x
= skipped_mv
[0].top
.y
= 0;
671 skipped_mv
[0].top
.weight
= PIPE_VIDEO_MV_WEIGHT_MAX
;
673 skipped_mv
[0] = buf
->mv_stream
[0][mb_addr
];
674 skipped_mv
[1] = buf
->mv_stream
[1][mb_addr
];
676 skipped_mv
[0].top
.field_select
= PIPE_VIDEO_FRAME
;
677 skipped_mv
[1].top
.field_select
= PIPE_VIDEO_FRAME
;
679 skipped_mv
[0].bottom
= skipped_mv
[0].top
;
680 skipped_mv
[1].bottom
= skipped_mv
[1].top
;
683 for (i
= 0; i
< mb
->num_skipped_macroblocks
; ++i
, ++mb_addr
) {
684 for (j
= 0; j
< 2; ++j
) {
685 if (!dec
->ref_frames
[j
][0]) continue;
686 buf
->mv_stream
[j
][mb_addr
] = skipped_mv
[j
];
697 vl_mpeg12_decode_bitstream(struct pipe_video_decoder
*decoder
,
698 unsigned num_buffers
,
699 const void * const *buffers
,
700 const unsigned *sizes
)
702 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
703 struct vl_mpeg12_buffer
*buf
;
707 assert(dec
&& dec
->target
);
709 buf
= vl_mpeg12_get_decode_buffer(dec
);
712 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
713 vl_zscan_set_layout(&buf
->zscan
[i
], dec
->picture_desc
.alternate_scan
?
714 dec
->zscan_alternate
: dec
->zscan_normal
);
716 vl_mpg12_bs_decode(&buf
->bs
, num_buffers
, buffers
, sizes
);
720 vl_mpeg12_end_frame(struct pipe_video_decoder
*decoder
)
722 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
723 struct pipe_sampler_view
**mc_source_sv
;
724 struct pipe_vertex_buffer vb
[3];
725 struct vl_mpeg12_buffer
*buf
;
727 unsigned i
, j
, component
;
728 unsigned nr_components
;
730 assert(dec
&& dec
->target
);
732 buf
= vl_mpeg12_get_decode_buffer(dec
);
734 vl_vb_unmap(&buf
->vertex_stream
, dec
->base
.context
);
736 dec
->base
.context
->transfer_unmap(dec
->base
.context
, buf
->tex_transfer
);
737 dec
->base
.context
->transfer_destroy(dec
->base
.context
, buf
->tex_transfer
);
742 dec
->base
.context
->bind_vertex_elements_state(dec
->base
.context
, dec
->ves_mv
);
743 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
744 if (!dec
->target_surfaces
[i
]) continue;
746 vl_mc_set_surface(&buf
->mc
[i
], dec
->target_surfaces
[i
]);
748 for (j
= 0; j
< VL_MAX_REF_FRAMES
; ++j
) {
749 if (!dec
->ref_frames
[j
][i
]) continue;
751 vb
[2] = vl_vb_get_mv(&buf
->vertex_stream
, j
);;
752 dec
->base
.context
->set_vertex_buffers(dec
->base
.context
, 3, vb
);
754 vl_mc_render_ref(i
? &dec
->mc_c
: &dec
->mc_y
, &buf
->mc
[i
], dec
->ref_frames
[j
][i
]);
758 dec
->base
.context
->bind_vertex_elements_state(dec
->base
.context
, dec
->ves_ycbcr
);
759 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
760 if (!buf
->num_ycbcr_blocks
[i
]) continue;
762 vb
[1] = vl_vb_get_ycbcr(&buf
->vertex_stream
, i
);
763 dec
->base
.context
->set_vertex_buffers(dec
->base
.context
, 2, vb
);
765 vl_zscan_render(i
? &dec
->zscan_c
: & dec
->zscan_y
, &buf
->zscan
[i
] , buf
->num_ycbcr_blocks
[i
]);
767 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
768 vl_idct_flush(i
? &dec
->idct_c
: &dec
->idct_y
, &buf
->idct
[i
], buf
->num_ycbcr_blocks
[i
]);
771 mc_source_sv
= dec
->mc_source
->get_sampler_view_planes(dec
->mc_source
);
772 for (i
= 0, component
= 0; i
< VL_MAX_PLANES
; ++i
) {
773 if (!dec
->target_surfaces
[i
]) continue;
775 nr_components
= util_format_get_nr_components(dec
->target_surfaces
[i
]->texture
->format
);
776 for (j
= 0; j
< nr_components
; ++j
, ++component
) {
777 if (!buf
->num_ycbcr_blocks
[i
]) continue;
779 vb
[1] = vl_vb_get_ycbcr(&buf
->vertex_stream
, component
);
780 dec
->base
.context
->set_vertex_buffers(dec
->base
.context
, 2, vb
);
782 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
783 vl_idct_prepare_stage2(i
? &dec
->idct_c
: &dec
->idct_y
, &buf
->idct
[component
]);
785 dec
->base
.context
->set_fragment_sampler_views(dec
->base
.context
, 1, &mc_source_sv
[component
]);
786 dec
->base
.context
->bind_fragment_sampler_states(dec
->base
.context
, 1, &dec
->sampler_ycbcr
);
788 vl_mc_render_ycbcr(i
? &dec
->mc_c
: &dec
->mc_y
, &buf
->mc
[i
], j
, buf
->num_ycbcr_blocks
[component
]);
791 ++dec
->current_buffer
;
792 dec
->current_buffer
%= 4;
796 vl_mpeg12_flush(struct pipe_video_decoder
*decoder
)
800 //Noop, for shaders it is much faster to flush everything in end_frame
804 init_pipe_state(struct vl_mpeg12_decoder
*dec
)
806 struct pipe_depth_stencil_alpha_state dsa
;
807 struct pipe_sampler_state sampler
;
812 memset(&dsa
, 0, sizeof dsa
);
813 dsa
.depth
.enabled
= 0;
814 dsa
.depth
.writemask
= 0;
815 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
816 for (i
= 0; i
< 2; ++i
) {
817 dsa
.stencil
[i
].enabled
= 0;
818 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
819 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
820 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
821 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
822 dsa
.stencil
[i
].valuemask
= 0;
823 dsa
.stencil
[i
].writemask
= 0;
825 dsa
.alpha
.enabled
= 0;
826 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
827 dsa
.alpha
.ref_value
= 0;
828 dec
->dsa
= dec
->base
.context
->create_depth_stencil_alpha_state(dec
->base
.context
, &dsa
);
829 dec
->base
.context
->bind_depth_stencil_alpha_state(dec
->base
.context
, dec
->dsa
);
831 memset(&sampler
, 0, sizeof(sampler
));
832 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
833 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
834 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
835 sampler
.min_img_filter
= PIPE_TEX_FILTER_NEAREST
;
836 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
837 sampler
.mag_img_filter
= PIPE_TEX_FILTER_NEAREST
;
838 sampler
.compare_mode
= PIPE_TEX_COMPARE_NONE
;
839 sampler
.compare_func
= PIPE_FUNC_ALWAYS
;
840 sampler
.normalized_coords
= 1;
841 dec
->sampler_ycbcr
= dec
->base
.context
->create_sampler_state(dec
->base
.context
, &sampler
);
842 if (!dec
->sampler_ycbcr
)
848 static const struct format_config
*
849 find_format_config(struct vl_mpeg12_decoder
*dec
, const struct format_config configs
[], unsigned num_configs
)
851 struct pipe_screen
*screen
;
856 screen
= dec
->base
.context
->screen
;
858 for (i
= 0; i
< num_configs
; ++i
) {
859 if (!screen
->is_format_supported(screen
, configs
[i
].zscan_source_format
, PIPE_TEXTURE_2D
,
860 1, PIPE_BIND_SAMPLER_VIEW
))
863 if (configs
[i
].idct_source_format
!= PIPE_FORMAT_NONE
) {
864 if (!screen
->is_format_supported(screen
, configs
[i
].idct_source_format
, PIPE_TEXTURE_2D
,
865 1, PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
))
868 if (!screen
->is_format_supported(screen
, configs
[i
].mc_source_format
, PIPE_TEXTURE_3D
,
869 1, PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
))
872 if (!screen
->is_format_supported(screen
, configs
[i
].mc_source_format
, PIPE_TEXTURE_2D
,
873 1, PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
))
883 init_zscan(struct vl_mpeg12_decoder
*dec
, const struct format_config
* format_config
)
885 unsigned num_channels
;
889 dec
->zscan_source_format
= format_config
->zscan_source_format
;
890 dec
->zscan_linear
= vl_zscan_layout(dec
->base
.context
, vl_zscan_linear
, dec
->blocks_per_line
);
891 dec
->zscan_normal
= vl_zscan_layout(dec
->base
.context
, vl_zscan_normal
, dec
->blocks_per_line
);
892 dec
->zscan_alternate
= vl_zscan_layout(dec
->base
.context
, vl_zscan_alternate
, dec
->blocks_per_line
);
894 num_channels
= dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
? 4 : 1;
896 if (!vl_zscan_init(&dec
->zscan_y
, dec
->base
.context
, dec
->base
.width
, dec
->base
.height
,
897 dec
->blocks_per_line
, dec
->num_blocks
, num_channels
))
900 if (!vl_zscan_init(&dec
->zscan_c
, dec
->base
.context
, dec
->chroma_width
, dec
->chroma_height
,
901 dec
->blocks_per_line
, dec
->num_blocks
, num_channels
))
908 init_idct(struct vl_mpeg12_decoder
*dec
, const struct format_config
* format_config
)
910 unsigned nr_of_idct_render_targets
, max_inst
;
911 enum pipe_format formats
[3];
913 struct pipe_sampler_view
*matrix
= NULL
;
915 nr_of_idct_render_targets
= dec
->base
.context
->screen
->get_param
917 dec
->base
.context
->screen
, PIPE_CAP_MAX_RENDER_TARGETS
920 max_inst
= dec
->base
.context
->screen
->get_shader_param
922 dec
->base
.context
->screen
, PIPE_SHADER_FRAGMENT
, PIPE_SHADER_CAP_MAX_INSTRUCTIONS
925 // Just assume we need 32 inst per render target, not 100% true, but should work in most cases
926 if (nr_of_idct_render_targets
>= 4 && max_inst
>= 32*4)
927 // more than 4 render targets usually doesn't makes any seens
928 nr_of_idct_render_targets
= 4;
930 nr_of_idct_render_targets
= 1;
932 formats
[0] = formats
[1] = formats
[2] = format_config
->idct_source_format
;
933 dec
->idct_source
= vl_video_buffer_create_ex
935 dec
->base
.context
, dec
->base
.width
/ 4, dec
->base
.height
, 1,
936 dec
->base
.chroma_format
, formats
, PIPE_USAGE_STATIC
939 if (!dec
->idct_source
)
940 goto error_idct_source
;
942 formats
[0] = formats
[1] = formats
[2] = format_config
->mc_source_format
;
943 dec
->mc_source
= vl_video_buffer_create_ex
945 dec
->base
.context
, dec
->base
.width
/ nr_of_idct_render_targets
,
946 dec
->base
.height
/ 4, nr_of_idct_render_targets
,
947 dec
->base
.chroma_format
, formats
, PIPE_USAGE_STATIC
951 goto error_mc_source
;
953 if (!(matrix
= vl_idct_upload_matrix(dec
->base
.context
, format_config
->idct_scale
)))
956 if (!vl_idct_init(&dec
->idct_y
, dec
->base
.context
, dec
->base
.width
, dec
->base
.height
,
957 nr_of_idct_render_targets
, matrix
, matrix
))
960 if(!vl_idct_init(&dec
->idct_c
, dec
->base
.context
, dec
->chroma_width
, dec
->chroma_height
,
961 nr_of_idct_render_targets
, matrix
, matrix
))
964 pipe_sampler_view_reference(&matrix
, NULL
);
969 vl_idct_cleanup(&dec
->idct_y
);
972 pipe_sampler_view_reference(&matrix
, NULL
);
975 dec
->mc_source
->destroy(dec
->mc_source
);
978 dec
->idct_source
->destroy(dec
->idct_source
);
985 init_mc_source_widthout_idct(struct vl_mpeg12_decoder
*dec
, const struct format_config
* format_config
)
987 enum pipe_format formats
[3];
989 formats
[0] = formats
[1] = formats
[2] = format_config
->mc_source_format
;
990 dec
->mc_source
= vl_video_buffer_create_ex
992 dec
->base
.context
, dec
->base
.width
, dec
->base
.height
, 1,
993 dec
->base
.chroma_format
, formats
, PIPE_USAGE_STATIC
996 return dec
->mc_source
!= NULL
;
1000 mc_vert_shader_callback(void *priv
, struct vl_mc
*mc
,
1001 struct ureg_program
*shader
,
1002 unsigned first_output
,
1003 struct ureg_dst tex
)
1005 struct vl_mpeg12_decoder
*dec
= priv
;
1006 struct ureg_dst o_vtex
;
1011 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
1012 struct vl_idct
*idct
= mc
== &dec
->mc_y
? &dec
->idct_y
: &dec
->idct_c
;
1013 vl_idct_stage2_vert_shader(idct
, shader
, first_output
, tex
);
1015 o_vtex
= ureg_DECL_output(shader
, TGSI_SEMANTIC_GENERIC
, first_output
);
1016 ureg_MOV(shader
, ureg_writemask(o_vtex
, TGSI_WRITEMASK_XY
), ureg_src(tex
));
1021 mc_frag_shader_callback(void *priv
, struct vl_mc
*mc
,
1022 struct ureg_program
*shader
,
1023 unsigned first_input
,
1024 struct ureg_dst dst
)
1026 struct vl_mpeg12_decoder
*dec
= priv
;
1027 struct ureg_src src
, sampler
;
1032 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
1033 struct vl_idct
*idct
= mc
== &dec
->mc_y
? &dec
->idct_y
: &dec
->idct_c
;
1034 vl_idct_stage2_frag_shader(idct
, shader
, first_input
, dst
);
1036 src
= ureg_DECL_fs_input(shader
, TGSI_SEMANTIC_GENERIC
, first_input
, TGSI_INTERPOLATE_LINEAR
);
1037 sampler
= ureg_DECL_sampler(shader
, 0);
1038 ureg_TEX(shader
, dst
, TGSI_TEXTURE_2D
, src
, sampler
);
1042 struct pipe_video_decoder
*
1043 vl_create_mpeg12_decoder(struct pipe_context
*context
,
1044 enum pipe_video_profile profile
,
1045 enum pipe_video_entrypoint entrypoint
,
1046 enum pipe_video_chroma_format chroma_format
,
1047 unsigned width
, unsigned height
, unsigned max_references
,
1048 bool expect_chunked_decode
)
1050 const unsigned block_size_pixels
= BLOCK_WIDTH
* BLOCK_HEIGHT
;
1051 const struct format_config
*format_config
;
1052 struct vl_mpeg12_decoder
*dec
;
1054 assert(u_reduce_video_profile(profile
) == PIPE_VIDEO_CODEC_MPEG12
);
1056 dec
= CALLOC_STRUCT(vl_mpeg12_decoder
);
1061 dec
->base
.context
= context
;
1062 dec
->base
.profile
= profile
;
1063 dec
->base
.entrypoint
= entrypoint
;
1064 dec
->base
.chroma_format
= chroma_format
;
1065 dec
->base
.width
= width
;
1066 dec
->base
.height
= height
;
1067 dec
->base
.max_references
= max_references
;
1069 dec
->base
.destroy
= vl_mpeg12_destroy
;
1070 dec
->base
.set_picture_parameters
= vl_mpeg12_set_picture_parameters
;
1071 dec
->base
.set_quant_matrix
= vl_mpeg12_set_quant_matrix
;
1072 dec
->base
.set_decode_target
= vl_mpeg12_set_decode_target
;
1073 dec
->base
.set_reference_frames
= vl_mpeg12_set_reference_frames
;
1074 dec
->base
.begin_frame
= vl_mpeg12_begin_frame
;
1075 dec
->base
.decode_macroblock
= vl_mpeg12_decode_macroblock
;
1076 dec
->base
.decode_bitstream
= vl_mpeg12_decode_bitstream
;
1077 dec
->base
.end_frame
= vl_mpeg12_end_frame
;
1078 dec
->base
.flush
= vl_mpeg12_flush
;
1080 dec
->blocks_per_line
= MAX2(util_next_power_of_two(dec
->base
.width
) / block_size_pixels
, 4);
1081 dec
->num_blocks
= (dec
->base
.width
* dec
->base
.height
) / block_size_pixels
;
1082 dec
->width_in_macroblocks
= align(dec
->base
.width
, MACROBLOCK_WIDTH
) / MACROBLOCK_WIDTH
;
1083 dec
->expect_chunked_decode
= expect_chunked_decode
;
1085 /* TODO: Implement 422, 444 */
1086 assert(dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
1088 if (dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
1089 dec
->chroma_width
= dec
->base
.width
/ 2;
1090 dec
->chroma_height
= dec
->base
.height
/ 2;
1091 dec
->num_blocks
= dec
->num_blocks
* 2;
1092 } else if (dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_422
) {
1093 dec
->chroma_width
= dec
->base
.width
;
1094 dec
->chroma_height
= dec
->base
.height
/ 2;
1095 dec
->num_blocks
= dec
->num_blocks
* 2 + dec
->num_blocks
;
1097 dec
->chroma_width
= dec
->base
.width
;
1098 dec
->chroma_height
= dec
->base
.height
;
1099 dec
->num_blocks
= dec
->num_blocks
* 3;
1102 dec
->quads
= vl_vb_upload_quads(dec
->base
.context
);
1103 dec
->pos
= vl_vb_upload_pos(
1105 dec
->base
.width
/ MACROBLOCK_WIDTH
,
1106 dec
->base
.height
/ MACROBLOCK_HEIGHT
1109 dec
->ves_ycbcr
= vl_vb_get_ves_ycbcr(dec
->base
.context
);
1110 dec
->ves_mv
= vl_vb_get_ves_mv(dec
->base
.context
);
1112 switch (entrypoint
) {
1113 case PIPE_VIDEO_ENTRYPOINT_BITSTREAM
:
1114 format_config
= find_format_config(dec
, bitstream_format_config
, num_bitstream_format_configs
);
1117 case PIPE_VIDEO_ENTRYPOINT_IDCT
:
1118 format_config
= find_format_config(dec
, idct_format_config
, num_idct_format_configs
);
1121 case PIPE_VIDEO_ENTRYPOINT_MC
:
1122 format_config
= find_format_config(dec
, mc_format_config
, num_mc_format_configs
);
1131 if (!format_config
) {
1136 if (!init_zscan(dec
, format_config
))
1139 if (entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
1140 if (!init_idct(dec
, format_config
))
1143 if (!init_mc_source_widthout_idct(dec
, format_config
))
1147 if (!vl_mc_init(&dec
->mc_y
, dec
->base
.context
, dec
->base
.width
, dec
->base
.height
,
1148 MACROBLOCK_HEIGHT
, format_config
->mc_scale
,
1149 mc_vert_shader_callback
, mc_frag_shader_callback
, dec
))
1153 if (!vl_mc_init(&dec
->mc_c
, dec
->base
.context
, dec
->base
.width
, dec
->base
.height
,
1154 BLOCK_HEIGHT
, format_config
->mc_scale
,
1155 mc_vert_shader_callback
, mc_frag_shader_callback
, dec
))
1158 if (!init_pipe_state(dec
))
1159 goto error_pipe_state
;
1161 memset(dec
->intra_matrix
, 0x10, 64);
1162 memset(dec
->non_intra_matrix
, 0x10, 64);
1167 vl_mc_cleanup(&dec
->mc_c
);
1170 vl_mc_cleanup(&dec
->mc_y
);
1173 if (entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
1174 vl_idct_cleanup(&dec
->idct_y
);
1175 vl_idct_cleanup(&dec
->idct_c
);
1176 dec
->idct_source
->destroy(dec
->idct_source
);
1178 dec
->mc_source
->destroy(dec
->mc_source
);
1181 vl_zscan_cleanup(&dec
->zscan_y
);
1182 vl_zscan_cleanup(&dec
->zscan_c
);