2 * Copyright (c) 2002 The FFmpeg Project
4 * This file is part of FFmpeg.
6 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "mpegvideo.h"
24 #include "msmpeg4data.h"
25 #include "simple_idct.h"
29 av_cold
void ff_wmv2_common_init(Wmv2Context
*w
)
31 MpegEncContext
*const s
= &w
->s
;
33 ff_blockdsp_init(&s
->bdsp
, s
->avctx
);
34 ff_wmv2dsp_init(&w
->wdsp
);
35 s
->idsp
.perm_type
= w
->wdsp
.idct_perm
;
36 ff_init_scantable_permutation(s
->idsp
.idct_permutation
,
38 ff_init_scantable(s
->idsp
.idct_permutation
, &w
->abt_scantable
[0],
40 ff_init_scantable(s
->idsp
.idct_permutation
, &w
->abt_scantable
[1],
42 ff_init_scantable(s
->idsp
.idct_permutation
, &s
->intra_scantable
,
43 ff_wmv1_scantable
[1]);
44 ff_init_scantable(s
->idsp
.idct_permutation
, &s
->intra_h_scantable
,
45 ff_wmv1_scantable
[2]);
46 ff_init_scantable(s
->idsp
.idct_permutation
, &s
->intra_v_scantable
,
47 ff_wmv1_scantable
[3]);
48 ff_init_scantable(s
->idsp
.idct_permutation
, &s
->inter_scantable
,
49 ff_wmv1_scantable
[0]);
50 s
->idsp
.idct_put
= w
->wdsp
.idct_put
;
51 s
->idsp
.idct_add
= w
->wdsp
.idct_add
;
55 static void wmv2_add_block(Wmv2Context
*w
, int16_t *block1
,
56 uint8_t *dst
, int stride
, int n
)
58 MpegEncContext
*const s
= &w
->s
;
60 if (s
->block_last_index
[n
] >= 0) {
61 switch (w
->abt_type_table
[n
]) {
63 w
->wdsp
.idct_add(dst
, stride
, block1
);
66 ff_simple_idct84_add(dst
, stride
, block1
);
67 ff_simple_idct84_add(dst
+ 4 * stride
, stride
, w
->abt_block2
[n
]);
68 s
->bdsp
.clear_block(w
->abt_block2
[n
]);
71 ff_simple_idct48_add(dst
, stride
, block1
);
72 ff_simple_idct48_add(dst
+ 4, stride
, w
->abt_block2
[n
]);
73 s
->bdsp
.clear_block(w
->abt_block2
[n
]);
76 av_log(s
->avctx
, AV_LOG_ERROR
, "internal error in WMV2 abt\n");
81 void ff_wmv2_add_mb(MpegEncContext
*s
, int16_t block1
[6][64],
82 uint8_t *dest_y
, uint8_t *dest_cb
, uint8_t *dest_cr
)
84 Wmv2Context
*const w
= (Wmv2Context
*) s
;
86 wmv2_add_block(w
, block1
[0], dest_y
, s
->linesize
, 0);
87 wmv2_add_block(w
, block1
[1], dest_y
+ 8, s
->linesize
, 1);
88 wmv2_add_block(w
, block1
[2], dest_y
+ 8 * s
->linesize
, s
->linesize
, 2);
89 wmv2_add_block(w
, block1
[3], dest_y
+ 8 + 8 * s
->linesize
, s
->linesize
, 3);
91 if (s
->flags
& CODEC_FLAG_GRAY
)
94 wmv2_add_block(w
, block1
[4], dest_cb
, s
->uvlinesize
, 4);
95 wmv2_add_block(w
, block1
[5], dest_cr
, s
->uvlinesize
, 5);
98 void ff_mspel_motion(MpegEncContext
*s
, uint8_t *dest_y
,
99 uint8_t *dest_cb
, uint8_t *dest_cr
,
100 uint8_t **ref_picture
, op_pixels_func (*pix_op
)[4],
101 int motion_x
, int motion_y
, int h
)
103 Wmv2Context
*const w
= (Wmv2Context
*) s
;
105 int dxy
, mx
, my
, src_x
, src_y
, v_edge_pos
;
106 ptrdiff_t offset
, linesize
, uvlinesize
;
109 dxy
= ((motion_y
& 1) << 1) | (motion_x
& 1);
110 dxy
= 2 * dxy
+ w
->hshift
;
111 src_x
= s
->mb_x
* 16 + (motion_x
>> 1);
112 src_y
= s
->mb_y
* 16 + (motion_y
>> 1);
114 /* WARNING: do no forget half pels */
115 v_edge_pos
= s
->v_edge_pos
;
116 src_x
= av_clip(src_x
, -16, s
->width
);
117 src_y
= av_clip(src_y
, -16, s
->height
);
119 if (src_x
<= -16 || src_x
>= s
->width
)
121 if (src_y
<= -16 || src_y
>= s
->height
)
124 linesize
= s
->linesize
;
125 uvlinesize
= s
->uvlinesize
;
126 ptr
= ref_picture
[0] + (src_y
* linesize
) + src_x
;
128 if (src_x
< 1 || src_y
< 1 || src_x
+ 17 >= s
->h_edge_pos
||
129 src_y
+ h
+ 1 >= v_edge_pos
) {
130 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
- 1 - s
->linesize
,
131 s
->linesize
, s
->linesize
, 19, 19,
132 src_x
- 1, src_y
- 1,
133 s
->h_edge_pos
, s
->v_edge_pos
);
134 ptr
= s
->edge_emu_buffer
+ 1 + s
->linesize
;
138 w
->wdsp
.put_mspel_pixels_tab
[dxy
](dest_y
, ptr
, linesize
);
139 w
->wdsp
.put_mspel_pixels_tab
[dxy
](dest_y
+ 8, ptr
+ 8, linesize
);
140 w
->wdsp
.put_mspel_pixels_tab
[dxy
](dest_y
+ 8 * linesize
, ptr
+ 8 * linesize
, linesize
);
141 w
->wdsp
.put_mspel_pixels_tab
[dxy
](dest_y
+ 8 + 8 * linesize
, ptr
+ 8 + 8 * linesize
, linesize
);
143 if (s
->flags
& CODEC_FLAG_GRAY
)
147 if ((motion_x
& 3) != 0)
149 if ((motion_y
& 3) != 0)
154 src_x
= s
->mb_x
* 8 + mx
;
155 src_y
= s
->mb_y
* 8 + my
;
156 src_x
= av_clip(src_x
, -8, s
->width
>> 1);
157 if (src_x
== (s
->width
>> 1))
159 src_y
= av_clip(src_y
, -8, s
->height
>> 1);
160 if (src_y
== (s
->height
>> 1))
162 offset
= (src_y
* uvlinesize
) + src_x
;
163 ptr
= ref_picture
[1] + offset
;
165 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
166 s
->uvlinesize
, s
->uvlinesize
,
169 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
170 ptr
= s
->edge_emu_buffer
;
172 pix_op
[1][dxy
](dest_cb
, ptr
, uvlinesize
, h
>> 1);
174 ptr
= ref_picture
[2] + offset
;
176 s
->vdsp
.emulated_edge_mc(s
->edge_emu_buffer
, ptr
,
177 s
->uvlinesize
, s
->uvlinesize
,
180 s
->h_edge_pos
>> 1, s
->v_edge_pos
>> 1);
181 ptr
= s
->edge_emu_buffer
;
183 pix_op
[1][dxy
](dest_cr
, ptr
, uvlinesize
, h
>> 1);