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_video.h>
35 #include "vl_mpeg12_decoder.h"
36 #include "vl_defines.h"
38 #define SCALE_FACTOR_16_TO_9 (32768.0f / 256.0f)
40 static const unsigned const_empty_block_mask_420
[3][2][2] = {
41 { { 0x20, 0x10 }, { 0x08, 0x04 } },
42 { { 0x02, 0x02 }, { 0x02, 0x02 } },
43 { { 0x01, 0x01 }, { 0x01, 0x01 } }
47 map_buffers(struct vl_mpeg12_decoder
*ctx
, struct vl_mpeg12_buffer
*buffer
)
49 struct pipe_sampler_view
**sampler_views
;
50 struct pipe_resource
*tex
;
53 assert(ctx
&& buffer
);
55 if (ctx
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
56 sampler_views
= buffer
->idct_source
->get_sampler_views(buffer
->idct_source
);
58 sampler_views
= buffer
->mc_source
->get_sampler_views(buffer
->mc_source
);
59 assert(sampler_views
);
61 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
62 tex
= sampler_views
[i
]->texture
;
64 struct pipe_box rect
=
72 buffer
->tex_transfer
[i
] = ctx
->pipe
->get_transfer
75 0, PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
79 buffer
->texels
[i
] = ctx
->pipe
->transfer_map(ctx
->pipe
, buffer
->tex_transfer
[i
]);
84 upload_block(struct vl_mpeg12_buffer
*buffer
, unsigned plane
, unsigned x
, unsigned y
, short *block
)
94 tex_pitch
= buffer
->tex_transfer
[plane
]->stride
/ sizeof(short);
95 texels
= buffer
->texels
[plane
] + y
* tex_pitch
* BLOCK_HEIGHT
+ x
* BLOCK_WIDTH
;
97 for (i
= 0; i
< BLOCK_HEIGHT
; ++i
)
98 memcpy(texels
+ i
* tex_pitch
, block
+ i
* BLOCK_WIDTH
, BLOCK_WIDTH
* sizeof(short));
102 upload_buffer(struct vl_mpeg12_decoder
*ctx
,
103 struct vl_mpeg12_buffer
*buffer
,
104 struct pipe_mpeg12_macroblock
*mb
)
115 for (y
= 0; y
< 2; ++y
) {
116 for (x
= 0; x
< 2; ++x
, ++tb
) {
117 if (mb
->cbp
& (*ctx
->empty_block_mask
)[0][y
][x
]) {
118 upload_block(buffer
, 0, mb
->mbx
* 2 + x
, mb
->mby
* 2 + y
, blocks
);
119 blocks
+= BLOCK_WIDTH
* BLOCK_HEIGHT
;
124 /* TODO: Implement 422, 444 */
125 assert(ctx
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
127 for (tb
= 1; tb
< 3; ++tb
) {
128 if (mb
->cbp
& (*ctx
->empty_block_mask
)[tb
][0][0]) {
129 upload_block(buffer
, tb
, mb
->mbx
, mb
->mby
, blocks
);
130 blocks
+= BLOCK_WIDTH
* BLOCK_HEIGHT
;
136 unmap_buffers(struct vl_mpeg12_decoder
*ctx
, struct vl_mpeg12_buffer
*buffer
)
140 assert(ctx
&& buffer
);
142 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
143 ctx
->pipe
->transfer_unmap(ctx
->pipe
, buffer
->tex_transfer
[i
]);
144 ctx
->pipe
->transfer_destroy(ctx
->pipe
, buffer
->tex_transfer
[i
]);
149 vl_mpeg12_buffer_destroy(struct pipe_video_decode_buffer
*buffer
)
151 struct vl_mpeg12_buffer
*buf
= (struct vl_mpeg12_buffer
*)buffer
;
152 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)buf
->base
.decoder
;
155 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
156 buf
->idct_source
->destroy(buf
->idct_source
);
157 buf
->idct_intermediate
->destroy(buf
->idct_intermediate
);
158 vl_idct_cleanup_buffer(&dec
->idct_y
, &buf
->idct
[0]);
159 vl_idct_cleanup_buffer(&dec
->idct_c
, &buf
->idct
[1]);
160 vl_idct_cleanup_buffer(&dec
->idct_c
, &buf
->idct
[2]);
162 buf
->mc_source
->destroy(buf
->mc_source
);
163 vl_vb_cleanup(&buf
->vertex_stream
);
164 vl_mpeg12_mc_cleanup_buffer(&buf
->mc
[0]);
165 vl_mpeg12_mc_cleanup_buffer(&buf
->mc
[1]);
166 vl_mpeg12_mc_cleanup_buffer(&buf
->mc
[2]);
172 vl_mpeg12_buffer_map(struct pipe_video_decode_buffer
*buffer
)
174 struct vl_mpeg12_buffer
*buf
= (struct vl_mpeg12_buffer
*)buffer
;
175 struct vl_mpeg12_decoder
*dec
;
178 dec
= (struct vl_mpeg12_decoder
*)buf
->base
.decoder
;
181 vl_vb_map(&buf
->vertex_stream
, dec
->pipe
);
182 map_buffers(dec
, buf
);
186 vl_mpeg12_buffer_add_macroblocks(struct pipe_video_decode_buffer
*buffer
,
187 unsigned num_macroblocks
,
188 struct pipe_macroblock
*macroblocks
)
190 struct pipe_mpeg12_macroblock
*mb
= (struct pipe_mpeg12_macroblock
*)macroblocks
;
191 struct vl_mpeg12_buffer
*buf
= (struct vl_mpeg12_buffer
*)buffer
;
192 struct vl_mpeg12_decoder
*dec
;
197 dec
= (struct vl_mpeg12_decoder
*)buf
->base
.decoder
;
200 assert(num_macroblocks
);
202 assert(macroblocks
->codec
== PIPE_VIDEO_CODEC_MPEG12
);
204 for ( i
= 0; i
< num_macroblocks
; ++i
) {
205 vl_vb_add_block(&buf
->vertex_stream
, &mb
[i
], dec
->empty_block_mask
);
206 upload_buffer(dec
, buf
, &mb
[i
]);
211 vl_mpeg12_buffer_unmap(struct pipe_video_decode_buffer
*buffer
)
213 struct vl_mpeg12_buffer
*buf
= (struct vl_mpeg12_buffer
*)buffer
;
214 struct vl_mpeg12_decoder
*dec
;
217 dec
= (struct vl_mpeg12_decoder
*)buf
->base
.decoder
;
220 vl_vb_unmap(&buf
->vertex_stream
, dec
->pipe
);
221 unmap_buffers(dec
, buf
);
225 vl_mpeg12_destroy(struct pipe_video_decoder
*decoder
)
227 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
231 /* Asserted in softpipe_delete_fs_state() for some reason */
232 dec
->pipe
->bind_vs_state(dec
->pipe
, NULL
);
233 dec
->pipe
->bind_fs_state(dec
->pipe
, NULL
);
235 dec
->pipe
->delete_blend_state(dec
->pipe
, dec
->blend
);
236 dec
->pipe
->delete_rasterizer_state(dec
->pipe
, dec
->rast
);
237 dec
->pipe
->delete_depth_stencil_alpha_state(dec
->pipe
, dec
->dsa
);
239 vl_mpeg12_mc_renderer_cleanup(&dec
->mc
);
240 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
241 vl_idct_cleanup(&dec
->idct_y
);
242 vl_idct_cleanup(&dec
->idct_c
);
244 dec
->pipe
->delete_vertex_elements_state(dec
->pipe
, dec
->ves
[0]);
245 dec
->pipe
->delete_vertex_elements_state(dec
->pipe
, dec
->ves
[1]);
246 dec
->pipe
->delete_vertex_elements_state(dec
->pipe
, dec
->ves
[2]);
247 pipe_resource_reference(&dec
->quads
.buffer
, NULL
);
252 static struct pipe_video_decode_buffer
*
253 vl_mpeg12_create_buffer(struct pipe_video_decoder
*decoder
)
255 const enum pipe_format idct_source_formats
[3] = {
256 PIPE_FORMAT_R16G16B16A16_SNORM
,
257 PIPE_FORMAT_R16G16B16A16_SNORM
,
258 PIPE_FORMAT_R16G16B16A16_SNORM
261 const enum pipe_format mc_source_formats
[3] = {
262 PIPE_FORMAT_R16_SNORM
,
263 PIPE_FORMAT_R16_SNORM
,
264 PIPE_FORMAT_R16_SNORM
267 struct vl_mpeg12_decoder
*dec
= (struct vl_mpeg12_decoder
*)decoder
;
268 struct vl_mpeg12_buffer
*buffer
;
270 struct pipe_sampler_view
**idct_source_sv
, **idct_intermediate_sv
, **mc_source_sv
;
271 struct pipe_surface
**idct_surfaces
;
275 buffer
= CALLOC_STRUCT(vl_mpeg12_buffer
);
279 buffer
->base
.decoder
= decoder
;
280 buffer
->base
.destroy
= vl_mpeg12_buffer_destroy
;
281 buffer
->base
.map
= vl_mpeg12_buffer_map
;
282 buffer
->base
.add_macroblocks
= vl_mpeg12_buffer_add_macroblocks
;
283 buffer
->base
.unmap
= vl_mpeg12_buffer_unmap
;
285 buffer
->vertex_bufs
.individual
.quad
.stride
= dec
->quads
.stride
;
286 buffer
->vertex_bufs
.individual
.quad
.buffer_offset
= dec
->quads
.buffer_offset
;
287 pipe_resource_reference(&buffer
->vertex_bufs
.individual
.quad
.buffer
, dec
->quads
.buffer
);
289 buffer
->vertex_bufs
.individual
.stream
= vl_vb_init(&buffer
->vertex_stream
, dec
->pipe
,
290 dec
->base
.width
/ MACROBLOCK_WIDTH
*
291 dec
->base
.height
/ MACROBLOCK_HEIGHT
);
292 if (!buffer
->vertex_bufs
.individual
.stream
.buffer
)
293 goto error_vertex_stream
;
295 buffer
->mc_source
= vl_video_buffer_init(dec
->base
.context
, dec
->pipe
,
296 dec
->base
.width
, dec
->base
.height
, 1,
297 dec
->base
.chroma_format
, 3,
301 if (!buffer
->mc_source
)
302 goto error_mc_source
;
304 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
305 buffer
->idct_source
= vl_video_buffer_init(dec
->base
.context
, dec
->pipe
,
306 dec
->base
.width
/ 4, dec
->base
.height
, 1,
307 dec
->base
.chroma_format
, 3,
310 if (!buffer
->idct_source
)
311 goto error_idct_source
;
313 buffer
->idct_intermediate
= vl_video_buffer_init(dec
->base
.context
, dec
->pipe
,
314 dec
->base
.width
/ 4, dec
->base
.height
/ 4, 4,
315 dec
->base
.chroma_format
, 3,
319 if (!buffer
->idct_intermediate
)
320 goto error_idct_intermediate
;
322 idct_source_sv
= buffer
->idct_source
->get_sampler_views(buffer
->idct_source
);
324 goto error_idct_source_sv
;
326 idct_intermediate_sv
= buffer
->idct_intermediate
->get_sampler_views(buffer
->idct_intermediate
);
327 if (!idct_intermediate_sv
)
328 goto error_idct_intermediate_sv
;
330 idct_surfaces
= buffer
->mc_source
->get_surfaces(buffer
->mc_source
);
332 goto error_idct_surfaces
;
334 if (!vl_idct_init_buffer(&dec
->idct_y
, &buffer
->idct
[0],
336 idct_intermediate_sv
[0],
340 if (!vl_idct_init_buffer(&dec
->idct_c
, &buffer
->idct
[1],
342 idct_intermediate_sv
[1],
346 if (!vl_idct_init_buffer(&dec
->idct_c
, &buffer
->idct
[2],
348 idct_intermediate_sv
[2],
353 mc_source_sv
= buffer
->mc_source
->get_sampler_views(buffer
->mc_source
);
355 goto error_mc_source_sv
;
357 if(!vl_mpeg12_mc_init_buffer(&dec
->mc
, &buffer
->mc
[0], mc_source_sv
[0]))
360 if(!vl_mpeg12_mc_init_buffer(&dec
->mc
, &buffer
->mc
[1], mc_source_sv
[1]))
363 if(!vl_mpeg12_mc_init_buffer(&dec
->mc
, &buffer
->mc
[2], mc_source_sv
[2]))
366 return &buffer
->base
;
369 vl_mpeg12_mc_cleanup_buffer(&buffer
->mc
[1]);
372 vl_mpeg12_mc_cleanup_buffer(&buffer
->mc
[0]);
376 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
377 vl_idct_cleanup_buffer(&dec
->idct_c
, &buffer
->idct
[2]);
380 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
381 vl_idct_cleanup_buffer(&dec
->idct_c
, &buffer
->idct
[1]);
384 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
385 vl_idct_cleanup_buffer(&dec
->idct_y
, &buffer
->idct
[0]);
389 error_idct_intermediate_sv
:
390 error_idct_source_sv
:
391 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
392 buffer
->idct_intermediate
->destroy(buffer
->idct_intermediate
);
394 error_idct_intermediate
:
395 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
396 buffer
->idct_source
->destroy(buffer
->idct_source
);
399 buffer
->mc_source
->destroy(buffer
->mc_source
);
402 vl_vb_cleanup(&buffer
->vertex_stream
);
410 vl_mpeg12_decoder_flush_buffer(struct pipe_video_decode_buffer
*buffer
,
411 struct pipe_video_buffer
*refs
[2],
412 struct pipe_video_buffer
*dst
,
413 struct pipe_fence_handle
**fence
)
415 struct vl_mpeg12_buffer
*buf
= (struct vl_mpeg12_buffer
*)buffer
;
416 struct vl_mpeg12_decoder
*dec
;
418 struct pipe_sampler_view
**sv_past
;
419 struct pipe_sampler_view
**sv_future
;
420 struct pipe_surface
**surfaces
;
422 struct pipe_sampler_view
*sv_refs
[2];
423 unsigned ne_start
, ne_num
, e_start
, e_num
;
428 dec
= (struct vl_mpeg12_decoder
*)buf
->base
.decoder
;
431 sv_past
= refs
[0] ? refs
[0]->get_sampler_views(refs
[0]) : NULL
;
432 sv_future
= refs
[1] ? refs
[1]->get_sampler_views(refs
[1]) : NULL
;
434 surfaces
= dst
->get_surfaces(dst
);
436 vl_vb_restart(&buf
->vertex_stream
, &ne_start
, &ne_num
, &e_start
, &e_num
);
438 dec
->pipe
->set_vertex_buffers(dec
->pipe
, 2, buf
->vertex_bufs
.all
);
439 dec
->pipe
->bind_blend_state(dec
->pipe
, dec
->blend
);
441 for (i
= 0; i
< VL_MAX_PLANES
; ++i
) {
442 dec
->pipe
->bind_vertex_elements_state(dec
->pipe
, dec
->ves
[i
]);
444 if (dec
->base
.entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
445 vl_idct_flush(i
== 0 ? &dec
->idct_y
: &dec
->idct_c
, &buf
->idct
[i
], ne_num
);
447 sv_refs
[0] = sv_past
? sv_past
[i
] : NULL
;
448 sv_refs
[1] = sv_future
? sv_future
[i
] : NULL
;
450 vl_mpeg12_mc_renderer_flush(&dec
->mc
, &buf
->mc
[i
], surfaces
[i
], sv_refs
,
451 ne_start
, ne_num
, e_start
, e_num
, fence
);
456 vl_mpeg12_decoder_clear_buffer(struct pipe_video_decode_buffer
*buffer
)
458 struct vl_mpeg12_buffer
*buf
= (struct vl_mpeg12_buffer
*)buffer
;
459 unsigned ne_start
, ne_num
, e_start
, e_num
;
463 vl_vb_restart(&buf
->vertex_stream
, &ne_start
, &ne_num
, &e_start
, &e_num
);
467 init_pipe_state(struct vl_mpeg12_decoder
*dec
)
469 struct pipe_rasterizer_state rast
;
470 struct pipe_blend_state blend
;
471 struct pipe_depth_stencil_alpha_state dsa
;
476 memset(&rast
, 0, sizeof rast
);
478 rast
.flatshade_first
= 0;
479 rast
.light_twoside
= 0;
481 rast
.cull_face
= PIPE_FACE_NONE
;
482 rast
.fill_back
= PIPE_POLYGON_MODE_FILL
;
483 rast
.fill_front
= PIPE_POLYGON_MODE_FILL
;
484 rast
.offset_point
= 0;
485 rast
.offset_line
= 0;
487 rast
.poly_smooth
= 0;
488 rast
.poly_stipple_enable
= 0;
489 rast
.sprite_coord_enable
= 0;
490 rast
.point_size_per_vertex
= 0;
491 rast
.multisample
= 0;
492 rast
.line_smooth
= 0;
493 rast
.line_stipple_enable
= 0;
494 rast
.line_stipple_factor
= 0;
495 rast
.line_stipple_pattern
= 0;
496 rast
.line_last_pixel
= 0;
498 rast
.point_smooth
= 0;
499 rast
.point_quad_rasterization
= 0;
500 rast
.point_size_per_vertex
= 1;
501 rast
.offset_units
= 1;
502 rast
.offset_scale
= 1;
503 rast
.gl_rasterization_rules
= 1;
505 dec
->rast
= dec
->pipe
->create_rasterizer_state(dec
->pipe
, &rast
);
506 dec
->pipe
->bind_rasterizer_state(dec
->pipe
, dec
->rast
);
508 memset(&blend
, 0, sizeof blend
);
510 blend
.independent_blend_enable
= 0;
511 blend
.rt
[0].blend_enable
= 0;
512 blend
.rt
[0].rgb_func
= PIPE_BLEND_ADD
;
513 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
514 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ONE
;
515 blend
.rt
[0].alpha_func
= PIPE_BLEND_ADD
;
516 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
517 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ONE
;
518 blend
.logicop_enable
= 0;
519 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
520 /* Needed to allow color writes to FB, even if blending disabled */
521 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
523 dec
->blend
= dec
->pipe
->create_blend_state(dec
->pipe
, &blend
);
525 memset(&dsa
, 0, sizeof dsa
);
526 dsa
.depth
.enabled
= 0;
527 dsa
.depth
.writemask
= 0;
528 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
529 for (i
= 0; i
< 2; ++i
) {
530 dsa
.stencil
[i
].enabled
= 0;
531 dsa
.stencil
[i
].func
= PIPE_FUNC_ALWAYS
;
532 dsa
.stencil
[i
].fail_op
= PIPE_STENCIL_OP_KEEP
;
533 dsa
.stencil
[i
].zpass_op
= PIPE_STENCIL_OP_KEEP
;
534 dsa
.stencil
[i
].zfail_op
= PIPE_STENCIL_OP_KEEP
;
535 dsa
.stencil
[i
].valuemask
= 0;
536 dsa
.stencil
[i
].writemask
= 0;
538 dsa
.alpha
.enabled
= 0;
539 dsa
.alpha
.func
= PIPE_FUNC_ALWAYS
;
540 dsa
.alpha
.ref_value
= 0;
541 dec
->dsa
= dec
->pipe
->create_depth_stencil_alpha_state(dec
->pipe
, &dsa
);
542 dec
->pipe
->bind_depth_stencil_alpha_state(dec
->pipe
, dec
->dsa
);
548 init_idct(struct vl_mpeg12_decoder
*dec
, unsigned buffer_width
, unsigned buffer_height
)
550 unsigned chroma_width
, chroma_height
, chroma_blocks_x
, chroma_blocks_y
;
551 struct pipe_sampler_view
*idct_matrix
;
553 if (!(idct_matrix
= vl_idct_upload_matrix(dec
->pipe
, sqrt(SCALE_FACTOR_16_TO_9
))))
554 goto error_idct_matrix
;
556 if (!vl_idct_init(&dec
->idct_y
, dec
->pipe
, buffer_width
, buffer_height
,
560 if (dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
) {
561 chroma_width
= buffer_width
/ 2;
562 chroma_height
= buffer_height
/ 2;
565 } else if (dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_422
) {
566 chroma_width
= buffer_width
;
567 chroma_height
= buffer_height
/ 2;
571 chroma_width
= buffer_width
;
572 chroma_height
= buffer_height
;
577 if(!vl_idct_init(&dec
->idct_c
, dec
->pipe
, chroma_width
, chroma_height
,
578 chroma_blocks_x
, chroma_blocks_y
, idct_matrix
))
581 pipe_sampler_view_reference(&idct_matrix
, NULL
);
585 vl_idct_cleanup(&dec
->idct_y
);
588 pipe_sampler_view_reference(&idct_matrix
, NULL
);
594 struct pipe_video_decoder
*
595 vl_create_mpeg12_decoder(struct pipe_video_context
*context
,
596 struct pipe_context
*pipe
,
597 enum pipe_video_profile profile
,
598 enum pipe_video_entrypoint entrypoint
,
599 enum pipe_video_chroma_format chroma_format
,
600 unsigned width
, unsigned height
)
602 struct vl_mpeg12_decoder
*dec
;
605 assert(u_reduce_video_profile(profile
) == PIPE_VIDEO_CODEC_MPEG12
);
607 dec
= CALLOC_STRUCT(vl_mpeg12_decoder
);
612 dec
->base
.context
= context
;
613 dec
->base
.profile
= profile
;
614 dec
->base
.entrypoint
= entrypoint
;
615 dec
->base
.chroma_format
= chroma_format
;
616 dec
->base
.width
= width
;
617 dec
->base
.height
= height
;
619 dec
->base
.destroy
= vl_mpeg12_destroy
;
620 dec
->base
.create_buffer
= vl_mpeg12_create_buffer
;
621 dec
->base
.flush_buffer
= vl_mpeg12_decoder_flush_buffer
;
622 dec
->base
.clear_buffer
= vl_mpeg12_decoder_clear_buffer
;
626 dec
->quads
= vl_vb_upload_quads(dec
->pipe
, 2, 2);
627 for (i
= 0; i
< VL_MAX_PLANES
; ++i
)
628 dec
->ves
[i
] = vl_vb_get_elems_state(dec
->pipe
, i
);
630 dec
->base
.width
= align(width
, MACROBLOCK_WIDTH
);
631 dec
->base
.height
= align(height
, MACROBLOCK_HEIGHT
);
633 /* TODO: Implement 422, 444 */
634 assert(dec
->base
.chroma_format
== PIPE_VIDEO_CHROMA_FORMAT_420
);
635 dec
->empty_block_mask
= &const_empty_block_mask_420
;
637 if (entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
)
638 if (!init_idct(dec
, dec
->base
.width
, dec
->base
.height
))
641 if (!vl_mpeg12_mc_renderer_init(&dec
->mc
, dec
->pipe
, dec
->base
.width
, dec
->base
.height
,
642 entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
? 1.0f
: SCALE_FACTOR_16_TO_9
))
645 if (!init_pipe_state(dec
))
646 goto error_pipe_state
;
651 vl_mpeg12_mc_renderer_cleanup(&dec
->mc
);
654 if (entrypoint
<= PIPE_VIDEO_ENTRYPOINT_IDCT
) {
655 vl_idct_cleanup(&dec
->idct_y
);
656 vl_idct_cleanup(&dec
->idct_c
);