2 * Copyright (c) 2002 The Libav Project
4 * This file is part of Libav.
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "mpegvideo.h"
23 #include "msmpeg4data.h"
24 #include "simple_idct.h"
28 av_cold
void ff_wmv2_common_init(Wmv2Context
* w
){
29 MpegEncContext
* const s
= &w
->s
;
31 ff_wmv2dsp_init(&w
->wdsp
);
32 s
->dsp
.idct_permutation_type
= w
->wdsp
.idct_perm
;
33 ff_init_scantable_permutation(s
->dsp
.idct_permutation
,
35 ff_init_scantable(s
->dsp
.idct_permutation
, &w
->abt_scantable
[0],
37 ff_init_scantable(s
->dsp
.idct_permutation
, &w
->abt_scantable
[1],
39 ff_init_scantable(s
->dsp
.idct_permutation
, &s
->intra_scantable
,
40 ff_wmv1_scantable
[1]);
41 ff_init_scantable(s
->dsp
.idct_permutation
, &s
->intra_h_scantable
,
42 ff_wmv1_scantable
[2]);
43 ff_init_scantable(s
->dsp
.idct_permutation
, &s
->intra_v_scantable
,
44 ff_wmv1_scantable
[3]);
45 ff_init_scantable(s
->dsp
.idct_permutation
, &s
->inter_scantable
,
46 ff_wmv1_scantable
[0]);
47 s
->dsp
.idct_put
= w
->wdsp
.idct_put
;
48 s
->dsp
.idct_add
= w
->wdsp
.idct_add
;
52 static void wmv2_add_block(Wmv2Context
*w
, int16_t *block1
, uint8_t *dst
, int stride
, int n
){
53 MpegEncContext
* const s
= &w
->s
;
55 if (s
->block_last_index
[n
] >= 0) {
56 switch(w
->abt_type_table
[n
]){
58 w
->wdsp
.idct_add(dst
, stride
, block1
);
61 ff_simple_idct84_add(dst
, stride
, block1
);
62 ff_simple_idct84_add(dst
+ 4*stride
, stride
, w
->abt_block2
[n
]);
63 s
->dsp
.clear_block(w
->abt_block2
[n
]);
66 ff_simple_idct48_add(dst
, stride
, block1
);
67 ff_simple_idct48_add(dst
+ 4 , stride
, w
->abt_block2
[n
]);
68 s
->dsp
.clear_block(w
->abt_block2
[n
]);
71 av_log(s
->avctx
, AV_LOG_ERROR
, "internal error in WMV2 abt\n");
76 void ff_wmv2_add_mb(MpegEncContext
*s
, int16_t block1
[6][64], uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
){
77 Wmv2Context
* const w
= (Wmv2Context
*)s
;
79 wmv2_add_block(w
, block1
[0], dest_y
, s
->linesize
, 0);
80 wmv2_add_block(w
, block1
[1], dest_y
+ 8 , s
->linesize
, 1);
81 wmv2_add_block(w
, block1
[2], dest_y
+ 8*s
->linesize
, s
->linesize
, 2);
82 wmv2_add_block(w
, block1
[3], dest_y
+ 8 + 8*s
->linesize
, s
->linesize
, 3);
84 if(s
->flags
&CODEC_FLAG_GRAY
) return;
86 wmv2_add_block(w
, block1
[4], dest_cb
, s
->uvlinesize
, 4);
87 wmv2_add_block(w
, block1
[5], dest_cr
, s
->uvlinesize
, 5);
90 void ff_mspel_motion(MpegEncContext
*s
,
91 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
,
92 uint8_t **ref_picture
, op_pixels_func (*pix_op
)[4],
93 int motion_x
, int motion_y
, int h
)
95 Wmv2Context
* const w
= (Wmv2Context
*)s
;
97 int dxy
, offset
, mx
, my
, src_x
, src_y
, v_edge_pos
, linesize
, uvlinesize
;
100 dxy
= ((motion_y
& 1) << 1) | (motion_x
& 1);
101 dxy
= 2*dxy
+ w
->hshift
;
102 src_x
= s
->mb_x
* 16 + (motion_x
>> 1);
103 src_y
= s
->mb_y
* 16 + (motion_y
>> 1);
105 /* WARNING: do no forget half pels */
106 v_edge_pos
= s
->v_edge_pos
;
107 src_x
= av_clip(src_x
, -16, s
->width
);
108 src_y
= av_clip(src_y
, -16, s
->height
);
110 if(src_x
<=-16 || src_x
>= s
->width
)
112 if(src_y
<=-16 || src_y
>= s
->height
)
115 linesize
= s
->linesize
;
116 uvlinesize
= s
->uvlinesize
;
117 ptr
= ref_picture
[0] + (src_y
* linesize
) + src_x
;
119 if(s
->flags
&CODEC_FLAG_EMU_EDGE
){
120 if(src_x
<1 || src_y
<1 || src_x
+ 17 >= s
->h_edge_pos
121 || src_y
+ h
+1 >= v_edge_pos
){
122 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
- 1 - s
->linesize
, s
->linesize
, 19, 19,
123 src_x
-1, src_y
-1, s
->h_edge_pos
, s
->v_edge_pos
);
124 ptr
= s
->edge_emu_buffer
+ 1 + s
->linesize
;
129 s
->dsp
.put_mspel_pixels_tab
[dxy
](dest_y
, ptr
, linesize
);
130 s
->dsp
.put_mspel_pixels_tab
[dxy
](dest_y
+8 , ptr
+8 , linesize
);
131 s
->dsp
.put_mspel_pixels_tab
[dxy
](dest_y
+8*linesize
, ptr
+8*linesize
, linesize
);
132 s
->dsp
.put_mspel_pixels_tab
[dxy
](dest_y
+8+8*linesize
, ptr
+8+8*linesize
, linesize
);
134 if(s
->flags
&CODEC_FLAG_GRAY
) return;
136 if (s
->out_format
== FMT_H263
) {
138 if ((motion_x
& 3) != 0)
140 if ((motion_y
& 3) != 0)
147 dxy
= ((my
& 1) << 1) | (mx
& 1);
152 src_x
= s
->mb_x
* 8 + mx
;
153 src_y
= s
->mb_y
* 8 + my
;
154 src_x
= av_clip(src_x
, -8, s
->width
>> 1);
155 if (src_x
== (s
->width
>> 1))
157 src_y
= av_clip(src_y
, -8, s
->height
>> 1);
158 if (src_y
== (s
->height
>> 1))
160 offset
= (src_y
* uvlinesize
) + src_x
;
161 ptr
= ref_picture
[1] + offset
;
163 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
, s
->uvlinesize
, 9, 9,
164 src_x
, src_y
, s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
165 ptr
= s
->edge_emu_buffer
;
167 pix_op
[1][dxy
](dest_cb
, ptr
, uvlinesize
, h
>> 1);
169 ptr
= ref_picture
[2] + offset
;
171 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
, s
->uvlinesize
, 9, 9,
172 src_x
, src_y
, s
->h_edge_pos
>>1, s
->v_edge_pos
>>1);
173 ptr
= s
->edge_emu_buffer
;
175 pix_op
[1][dxy
](dest_cr
, ptr
, uvlinesize
, h
>> 1);