Line |
Branch |
Exec |
Source |
1 |
|
|
/* |
2 |
|
|
* SpeedHQ encoder |
3 |
|
|
* Copyright (c) 2000, 2001 Fabrice Bellard |
4 |
|
|
* Copyright (c) 2003 Alex Beregszaszi |
5 |
|
|
* Copyright (c) 2003-2004 Michael Niedermayer |
6 |
|
|
* Copyright (c) 2020 FFmpeg |
7 |
|
|
* |
8 |
|
|
* This file is part of FFmpeg. |
9 |
|
|
* |
10 |
|
|
* FFmpeg is free software; you can redistribute it and/or |
11 |
|
|
* modify it under the terms of the GNU Lesser General Public |
12 |
|
|
* License as published by the Free Software Foundation; either |
13 |
|
|
* version 2.1 of the License, or (at your option) any later version. |
14 |
|
|
* |
15 |
|
|
* FFmpeg is distributed in the hope that it will be useful, |
16 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 |
|
|
* Lesser General Public License for more details. |
19 |
|
|
* |
20 |
|
|
* You should have received a copy of the GNU Lesser General Public |
21 |
|
|
* License along with FFmpeg; if not, write to the Free Software |
22 |
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
23 |
|
|
*/ |
24 |
|
|
|
25 |
|
|
/** |
26 |
|
|
* @file |
27 |
|
|
* SpeedHQ encoder. |
28 |
|
|
*/ |
29 |
|
|
|
30 |
|
|
#include "config_components.h" |
31 |
|
|
|
32 |
|
|
#include "libavutil/thread.h" |
33 |
|
|
|
34 |
|
|
#include "avcodec.h" |
35 |
|
|
#include "codec_internal.h" |
36 |
|
|
#include "mpeg12data.h" |
37 |
|
|
#include "mpeg12enc.h" |
38 |
|
|
#include "mpegvideo.h" |
39 |
|
|
#include "mpegvideoenc.h" |
40 |
|
|
#include "speedhqenc.h" |
41 |
|
|
|
42 |
|
|
extern RLTable ff_rl_speedhq; |
43 |
|
|
static uint8_t speedhq_static_rl_table_store[2][2*MAX_RUN + MAX_LEVEL + 3]; |
44 |
|
|
|
45 |
|
|
/* Exactly the same as MPEG-2, except little-endian. */ |
46 |
|
|
static const uint16_t mpeg12_vlc_dc_lum_code_reversed[12] = { |
47 |
|
|
0x1, 0x0, 0x2, 0x5, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF |
48 |
|
|
}; |
49 |
|
|
static const uint16_t mpeg12_vlc_dc_chroma_code_reversed[12] = { |
50 |
|
|
0x0, 0x2, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF |
51 |
|
|
}; |
52 |
|
|
|
53 |
|
|
/* simple include everything table for dc, first byte is bits |
54 |
|
|
* number next 3 are code */ |
55 |
|
|
static uint32_t speedhq_lum_dc_uni[512]; |
56 |
|
|
static uint32_t speedhq_chr_dc_uni[512]; |
57 |
|
|
|
58 |
|
|
static uint8_t uni_speedhq_ac_vlc_len[64 * 64 * 2]; |
59 |
|
|
|
60 |
|
|
typedef struct SpeedHQEncContext { |
61 |
|
|
MpegEncContext m; |
62 |
|
|
|
63 |
|
|
int slice_start; |
64 |
|
|
} SpeedHQEncContext; |
65 |
|
|
|
66 |
|
✗ |
static av_cold void speedhq_init_static_data(void) |
67 |
|
|
{ |
68 |
|
✗ |
ff_rl_init(&ff_rl_speedhq, speedhq_static_rl_table_store); |
69 |
|
|
|
70 |
|
|
/* build unified dc encoding tables */ |
71 |
|
✗ |
for (int i = -255; i < 256; i++) { |
72 |
|
|
int adiff, index; |
73 |
|
|
int bits, code; |
74 |
|
✗ |
int diff = i; |
75 |
|
|
|
76 |
|
✗ |
adiff = FFABS(diff); |
77 |
|
✗ |
if (diff < 0) |
78 |
|
✗ |
diff--; |
79 |
|
✗ |
index = av_log2(2 * adiff); |
80 |
|
|
|
81 |
|
✗ |
bits = ff_mpeg12_vlc_dc_lum_bits[index] + index; |
82 |
|
✗ |
code = mpeg12_vlc_dc_lum_code_reversed[index] + |
83 |
|
✗ |
(av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_lum_bits[index]); |
84 |
|
✗ |
speedhq_lum_dc_uni[i + 255] = bits + (code << 8); |
85 |
|
|
|
86 |
|
✗ |
bits = ff_mpeg12_vlc_dc_chroma_bits[index] + index; |
87 |
|
✗ |
code = mpeg12_vlc_dc_chroma_code_reversed[index] + |
88 |
|
✗ |
(av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_chroma_bits[index]); |
89 |
|
✗ |
speedhq_chr_dc_uni[i + 255] = bits + (code << 8); |
90 |
|
|
} |
91 |
|
|
|
92 |
|
✗ |
ff_mpeg1_init_uni_ac_vlc(&ff_rl_speedhq, uni_speedhq_ac_vlc_len); |
93 |
|
|
} |
94 |
|
|
|
95 |
|
✗ |
av_cold int ff_speedhq_encode_init(MpegEncContext *s) |
96 |
|
|
{ |
97 |
|
|
static AVOnce init_static_once = AV_ONCE_INIT; |
98 |
|
|
|
99 |
|
✗ |
if (s->width > 65500 || s->height > 65500) { |
100 |
|
✗ |
av_log(s, AV_LOG_ERROR, "SpeedHQ does not support resolutions above 65500x65500\n"); |
101 |
|
✗ |
return AVERROR(EINVAL); |
102 |
|
|
} |
103 |
|
|
|
104 |
|
✗ |
s->min_qcoeff = -2048; |
105 |
|
✗ |
s->max_qcoeff = 2047; |
106 |
|
|
|
107 |
|
✗ |
ff_thread_once(&init_static_once, speedhq_init_static_data); |
108 |
|
|
|
109 |
|
✗ |
s->intra_ac_vlc_length = |
110 |
|
✗ |
s->intra_ac_vlc_last_length = |
111 |
|
✗ |
s->intra_chroma_ac_vlc_length = |
112 |
|
✗ |
s->intra_chroma_ac_vlc_last_length = uni_speedhq_ac_vlc_len; |
113 |
|
|
|
114 |
|
✗ |
switch (s->avctx->pix_fmt) { |
115 |
|
✗ |
case AV_PIX_FMT_YUV420P: |
116 |
|
✗ |
s->avctx->codec_tag = MKTAG('S','H','Q','0'); |
117 |
|
✗ |
break; |
118 |
|
✗ |
case AV_PIX_FMT_YUV422P: |
119 |
|
✗ |
s->avctx->codec_tag = MKTAG('S','H','Q','2'); |
120 |
|
✗ |
break; |
121 |
|
✗ |
case AV_PIX_FMT_YUV444P: |
122 |
|
✗ |
s->avctx->codec_tag = MKTAG('S','H','Q','4'); |
123 |
|
✗ |
break; |
124 |
|
✗ |
default: |
125 |
|
✗ |
av_assert0(0); |
126 |
|
|
} |
127 |
|
|
|
128 |
|
✗ |
return 0; |
129 |
|
|
} |
130 |
|
|
|
131 |
|
✗ |
void ff_speedhq_encode_picture_header(MpegEncContext *s) |
132 |
|
|
{ |
133 |
|
✗ |
SpeedHQEncContext *ctx = (SpeedHQEncContext*)s; |
134 |
|
|
|
135 |
|
✗ |
put_bits_le(&s->pb, 8, 100 - s->qscale * 2); /* FIXME why doubled */ |
136 |
|
✗ |
put_bits_le(&s->pb, 24, 4); /* no second field */ |
137 |
|
|
|
138 |
|
✗ |
ctx->slice_start = 4; |
139 |
|
|
/* length of first slice, will be filled out later */ |
140 |
|
✗ |
put_bits_le(&s->pb, 24, 0); |
141 |
|
|
} |
142 |
|
|
|
143 |
|
✗ |
void ff_speedhq_end_slice(MpegEncContext *s) |
144 |
|
|
{ |
145 |
|
✗ |
SpeedHQEncContext *ctx = (SpeedHQEncContext*)s; |
146 |
|
|
int slice_len; |
147 |
|
|
|
148 |
|
✗ |
flush_put_bits_le(&s->pb); |
149 |
|
✗ |
slice_len = put_bytes_output(&s->pb) - ctx->slice_start; |
150 |
|
✗ |
AV_WL24(s->pb.buf + ctx->slice_start, slice_len); |
151 |
|
|
|
152 |
|
|
/* length of next slice, will be filled out later */ |
153 |
|
✗ |
ctx->slice_start = put_bytes_output(&s->pb); |
154 |
|
✗ |
put_bits_le(&s->pb, 24, 0); |
155 |
|
|
} |
156 |
|
|
|
157 |
|
✗ |
static inline void encode_dc(PutBitContext *pb, int diff, int component) |
158 |
|
|
{ |
159 |
|
✗ |
unsigned int diff_u = diff + 255; |
160 |
|
✗ |
if (diff_u >= 511) { |
161 |
|
|
int index; |
162 |
|
|
|
163 |
|
✗ |
if (diff < 0) { |
164 |
|
✗ |
index = av_log2_16bit(-2 * diff); |
165 |
|
✗ |
diff--; |
166 |
|
|
} else { |
167 |
|
✗ |
index = av_log2_16bit(2 * diff); |
168 |
|
|
} |
169 |
|
✗ |
if (component == 0) |
170 |
|
✗ |
put_bits_le(pb, |
171 |
|
✗ |
ff_mpeg12_vlc_dc_lum_bits[index] + index, |
172 |
|
✗ |
mpeg12_vlc_dc_lum_code_reversed[index] + |
173 |
|
✗ |
(av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_lum_bits[index])); |
174 |
|
|
else |
175 |
|
✗ |
put_bits_le(pb, |
176 |
|
✗ |
ff_mpeg12_vlc_dc_chroma_bits[index] + index, |
177 |
|
✗ |
mpeg12_vlc_dc_chroma_code_reversed[index] + |
178 |
|
✗ |
(av_mod_uintp2(diff, index) << ff_mpeg12_vlc_dc_chroma_bits[index])); |
179 |
|
|
} else { |
180 |
|
✗ |
if (component == 0) |
181 |
|
✗ |
put_bits_le(pb, |
182 |
|
✗ |
speedhq_lum_dc_uni[diff + 255] & 0xFF, |
183 |
|
✗ |
speedhq_lum_dc_uni[diff + 255] >> 8); |
184 |
|
|
else |
185 |
|
✗ |
put_bits_le(pb, |
186 |
|
✗ |
speedhq_chr_dc_uni[diff + 255] & 0xFF, |
187 |
|
✗ |
speedhq_chr_dc_uni[diff + 255] >> 8); |
188 |
|
|
} |
189 |
|
|
} |
190 |
|
|
|
191 |
|
✗ |
static void encode_block(MpegEncContext *s, int16_t *block, int n) |
192 |
|
|
{ |
193 |
|
|
int alevel, level, last_non_zero, dc, i, j, run, last_index, sign; |
194 |
|
|
int code; |
195 |
|
|
int component, val; |
196 |
|
|
|
197 |
|
|
/* DC coef */ |
198 |
|
✗ |
component = (n <= 3 ? 0 : (n&1) + 1); |
199 |
|
✗ |
dc = block[0]; /* overflow is impossible */ |
200 |
|
✗ |
val = s->last_dc[component] - dc; /* opposite of most codecs */ |
201 |
|
✗ |
encode_dc(&s->pb, val, component); |
202 |
|
✗ |
s->last_dc[component] = dc; |
203 |
|
|
|
204 |
|
|
/* now quantify & encode AC coefs */ |
205 |
|
✗ |
last_non_zero = 0; |
206 |
|
✗ |
last_index = s->block_last_index[n]; |
207 |
|
|
|
208 |
|
✗ |
for (i = 1; i <= last_index; i++) { |
209 |
|
✗ |
j = s->intra_scantable.permutated[i]; |
210 |
|
✗ |
level = block[j]; |
211 |
|
|
|
212 |
|
|
/* encode using VLC */ |
213 |
|
✗ |
if (level != 0) { |
214 |
|
✗ |
run = i - last_non_zero - 1; |
215 |
|
|
|
216 |
|
✗ |
alevel = level; |
217 |
|
✗ |
MASK_ABS(sign, alevel); |
218 |
|
✗ |
sign &= 1; |
219 |
|
|
|
220 |
|
✗ |
if (alevel <= ff_rl_speedhq.max_level[0][run]) { |
221 |
|
✗ |
code = ff_rl_speedhq.index_run[0][run] + alevel - 1; |
222 |
|
|
/* store the VLC & sign at once */ |
223 |
|
✗ |
put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[code][1] + 1, |
224 |
|
✗ |
ff_rl_speedhq.table_vlc[code][0] + (sign << ff_rl_speedhq.table_vlc[code][1])); |
225 |
|
|
} else { |
226 |
|
|
/* escape seems to be pretty rare <5% so I do not optimize it; |
227 |
|
|
* the values correspond to ff_rl_speedhq.table_vlc[121] */ |
228 |
|
✗ |
put_bits_le(&s->pb, 6, 32); |
229 |
|
|
/* escape: only clip in this case */ |
230 |
|
✗ |
put_bits_le(&s->pb, 6, run); |
231 |
|
✗ |
put_bits_le(&s->pb, 12, level + 2048); |
232 |
|
|
} |
233 |
|
✗ |
last_non_zero = i; |
234 |
|
|
} |
235 |
|
|
} |
236 |
|
|
/* end of block; the values correspond to ff_rl_speedhq.table_vlc[122] */ |
237 |
|
✗ |
put_bits_le(&s->pb, 4, 6); |
238 |
|
|
} |
239 |
|
|
|
240 |
|
✗ |
void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]) |
241 |
|
|
{ |
242 |
|
|
int i; |
243 |
|
✗ |
for(i=0;i<6;i++) { |
244 |
|
✗ |
encode_block(s, block[i], i); |
245 |
|
|
} |
246 |
|
✗ |
if (s->chroma_format == CHROMA_444) { |
247 |
|
✗ |
encode_block(s, block[8], 8); |
248 |
|
✗ |
encode_block(s, block[9], 9); |
249 |
|
|
|
250 |
|
✗ |
encode_block(s, block[6], 6); |
251 |
|
✗ |
encode_block(s, block[7], 7); |
252 |
|
|
|
253 |
|
✗ |
encode_block(s, block[10], 10); |
254 |
|
✗ |
encode_block(s, block[11], 11); |
255 |
|
✗ |
} else if (s->chroma_format == CHROMA_422) { |
256 |
|
✗ |
encode_block(s, block[6], 6); |
257 |
|
✗ |
encode_block(s, block[7], 7); |
258 |
|
|
} |
259 |
|
|
|
260 |
|
✗ |
s->i_tex_bits += get_bits_diff(s); |
261 |
|
|
} |
262 |
|
|
|
263 |
|
✗ |
static int ff_speedhq_mb_rows_in_slice(int slice_num, int mb_height) |
264 |
|
|
{ |
265 |
|
✗ |
return mb_height / 4 + (slice_num < (mb_height % 4)); |
266 |
|
|
} |
267 |
|
|
|
268 |
|
✗ |
int ff_speedhq_mb_y_order_to_mb(int mb_y_order, int mb_height, int *first_in_slice) |
269 |
|
|
{ |
270 |
|
✗ |
int slice_num = 0; |
271 |
|
✗ |
while (mb_y_order >= ff_speedhq_mb_rows_in_slice(slice_num, mb_height)) { |
272 |
|
✗ |
mb_y_order -= ff_speedhq_mb_rows_in_slice(slice_num, mb_height); |
273 |
|
✗ |
slice_num++; |
274 |
|
|
} |
275 |
|
✗ |
*first_in_slice = (mb_y_order == 0); |
276 |
|
✗ |
return mb_y_order * 4 + slice_num; |
277 |
|
|
} |
278 |
|
|
|
279 |
|
|
#if CONFIG_SPEEDHQ_ENCODER |
280 |
|
|
const FFCodec ff_speedhq_encoder = { |
281 |
|
|
.p.name = "speedhq", |
282 |
|
|
.p.long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), |
283 |
|
|
.p.type = AVMEDIA_TYPE_VIDEO, |
284 |
|
|
.p.id = AV_CODEC_ID_SPEEDHQ, |
285 |
|
|
.p.priv_class = &ff_mpv_enc_class, |
286 |
|
|
.priv_data_size = sizeof(SpeedHQEncContext), |
287 |
|
|
.init = ff_mpv_encode_init, |
288 |
|
|
FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), |
289 |
|
|
.close = ff_mpv_encode_end, |
290 |
|
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, |
291 |
|
|
.p.pix_fmts = (const enum AVPixelFormat[]) { |
292 |
|
|
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, |
293 |
|
|
AV_PIX_FMT_NONE |
294 |
|
|
}, |
295 |
|
|
}; |
296 |
|
|
#endif |
297 |
|
|
|