FFmpeg
Loading...
Searching...
No Matches
asvenc.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2003 Michael Niedermayer
3 *
4 * This file is part of FFmpeg.
5 *
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.
10 *
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.
15 *
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
19 */
20
21/**
22 * @file
23 * ASUS V1/V2 encoder.
24 */
25
26#include "config_components.h"
27
30#include "libavutil/mem.h"
32
33#include "aandcttab.h"
34#include "asv.h"
35#include "avcodec.h"
36#include "codec_internal.h"
37#include "encode.h"
38#include "fdctdsp.h"
39#include "mpeg12data.h"
40#include "pixblockdsp.h"
41#include "put_bits.h"
42
43typedef struct ASVEncContext {
45
47
48 void (*get_pixels)(int16_t *restrict block,
49 const uint8_t *pixels,
50 ptrdiff_t stride);
51
54 DECLARE_ALIGNED(32, int16_t, block)[6][64];
57
58enum {
59 ASV1_MAX_BLOCK_SIZE = 8 + 10 * FFMAX(2 /* skip */, 5 /* ccp */ + 4 * 11 /* level */) + 5,
61 ASV2_MAX_BLOCK_SIZE = 4 + 8 + 16 * (6 /* ccp */ + 4 * 13 /* level */),
64};
65
66static inline void asv1_put_level(PutBitContext *pb, int level)
67{
68 unsigned int index = level + 3;
69 unsigned n, code;
70
71 if (index <= 6) {
72 n = ff_asv_level_tab[index][1];
74 } else {
75 n = 3 + 8;
76 code = (0 /* Escape code */ << 8) | (level & 0xFF);
77 }
78 put_bits(pb, n, code);
79}
80
81static inline void asv2_put_level(ASVEncContext *a, PutBitContext *pb, int level)
82{
83 unsigned int index = level + 31;
84 unsigned n, code;
85
86 if (index <= 62) {
89 } else {
91 av_log(a->c.avctx, AV_LOG_WARNING, "Clipping level %d, increase qscale\n", level);
93 }
94 n = 5 + 8;
95 code = (level & 0xFF) << 5 | /* Escape code */ 0;
96 }
97 put_bits_le(pb, n, code);
98}
99
100static inline void asv1_encode_block(ASVEncContext *a, int16_t block[64])
101{
102 put_bits(&a->pb, 8, (block[0] + 32) >> 6);
103 block[0] = 0;
104
105 for (unsigned i = 0, nc_bits = 0, nc_val = 0; i < 10; i++) {
106 const int index = ff_asv_scantab[4 * i];
107 int ccp = 0;
108
109 if ((block[index + 0] = (block[index + 0] *
110 a->q_intra_matrix[index + 0] + (1 << 15)) >> 16))
111 ccp |= 8;
112 if ((block[index + 8] = (block[index + 8] *
113 a->q_intra_matrix[index + 8] + (1 << 15)) >> 16))
114 ccp |= 4;
115 if ((block[index + 1] = (block[index + 1] *
116 a->q_intra_matrix[index + 1] + (1 << 15)) >> 16))
117 ccp |= 2;
118 if ((block[index + 9] = (block[index + 9] *
119 a->q_intra_matrix[index + 9] + (1 << 15)) >> 16))
120 ccp |= 1;
121
122 if (ccp) {
123 put_bits(&a->pb, nc_bits + ff_asv_ccp_tab[ccp][1],
124 nc_val << ff_asv_ccp_tab[ccp][1] /* Skip */ |
125 ff_asv_ccp_tab[ccp][0]);
126 nc_bits = 0;
127 nc_val = 0;
128
129 if (ccp & 8)
130 asv1_put_level(&a->pb, block[index + 0]);
131 if (ccp & 4)
132 asv1_put_level(&a->pb, block[index + 8]);
133 if (ccp & 2)
134 asv1_put_level(&a->pb, block[index + 1]);
135 if (ccp & 1)
136 asv1_put_level(&a->pb, block[index + 9]);
137 } else {
138 nc_bits += 2;
139 nc_val = (nc_val << 2) | 2;
140 }
141 }
142 put_bits(&a->pb, 5, 0xF); /* End of block */
143}
144
145static inline void asv2_encode_block(ASVEncContext *a, int16_t block[64])
146{
147 int i;
148 int count = 0;
149
150 for (count = 63; count > 3; count--) {
151 const int index = ff_asv_scantab[count];
152 if ((block[index] * a->q_intra_matrix[index] + (1 << 15)) >> 16)
153 break;
154 }
155
156 count >>= 2;
157
158 put_bits_le(&a->pb, 4 + 8, count /* 4 bits */ |
159 (/* DC */(block[0] + 32) >> 6) << 4);
160 block[0] = 0;
161
162 for (i = 0; i <= count; i++) {
163 const int index = ff_asv_scantab[4 * i];
164 int ccp = 0;
165
166 if ((block[index + 0] = (block[index + 0] *
167 a->q_intra_matrix[index + 0] + (1 << 15)) >> 16))
168 ccp |= 8;
169 if ((block[index + 8] = (block[index + 8] *
170 a->q_intra_matrix[index + 8] + (1 << 15)) >> 16))
171 ccp |= 4;
172 if ((block[index + 1] = (block[index + 1] *
173 a->q_intra_matrix[index + 1] + (1 << 15)) >> 16))
174 ccp |= 2;
175 if ((block[index + 9] = (block[index + 9] *
176 a->q_intra_matrix[index + 9] + (1 << 15)) >> 16))
177 ccp |= 1;
178
179 av_assert2(i || ccp < 8);
180 if (i)
181 put_bits_le(&a->pb, ff_asv_ac_ccp_tab[ccp][1], ff_asv_ac_ccp_tab[ccp][0]);
182 else
183 put_bits_le(&a->pb, ff_asv_dc_ccp_tab[ccp][1], ff_asv_dc_ccp_tab[ccp][0]);
184
185 if (ccp) {
186 if (ccp & 8)
187 asv2_put_level(a, &a->pb, block[index + 0]);
188 if (ccp & 4)
189 asv2_put_level(a, &a->pb, block[index + 8]);
190 if (ccp & 2)
191 asv2_put_level(a, &a->pb, block[index + 1]);
192 if (ccp & 1)
193 asv2_put_level(a, &a->pb, block[index + 9]);
194 }
195 }
196}
197
198static inline int encode_mb(ASVEncContext *a, int16_t block[6][64])
199{
200 int i;
201
203
204 if (a->c.avctx->codec_id == AV_CODEC_ID_ASV1) {
205 for (i = 0; i < 6; i++)
207 } else {
208 for (i = 0; i < 6; i++) {
210 }
211 }
212 return 0;
213}
214
215static inline void dct_get(ASVEncContext *a, const AVFrame *frame,
216 int mb_x, int mb_y)
217{
218 int16_t (*block)[64] = a->block;
219 int linesize = frame->linesize[0];
220 int i;
221
222 const uint8_t *ptr_y = frame->data[0] + (mb_y * 16 * linesize) + mb_x * 16;
223 const uint8_t *ptr_cb = frame->data[1] + (mb_y * 8 * frame->linesize[1]) + mb_x * 8;
224 const uint8_t *ptr_cr = frame->data[2] + (mb_y * 8 * frame->linesize[2]) + mb_x * 8;
225
226 a->get_pixels(block[0], ptr_y, linesize);
227 a->get_pixels(block[1], ptr_y + 8, linesize);
228 a->get_pixels(block[2], ptr_y + 8 * linesize, linesize);
229 a->get_pixels(block[3], ptr_y + 8 * linesize + 8, linesize);
230 for (i = 0; i < 4; i++)
231 a->fdsp.fdct(block[i]);
232
233 if (!(a->c.avctx->flags & AV_CODEC_FLAG_GRAY)) {
234 a->get_pixels(block[4], ptr_cb, frame->linesize[1]);
235 a->get_pixels(block[5], ptr_cr, frame->linesize[2]);
236 for (i = 4; i < 6; i++)
237 a->fdsp.fdct(block[i]);
238 }
239}
240
241static void handle_partial_mb(ASVEncContext *a, const uint8_t *const data[3],
242 const int linesizes[3],
243 int valid_width, int valid_height)
244{
245 const int nb_blocks = a->c.avctx->flags & AV_CODEC_FLAG_GRAY ? 4 : 6;
246 static const struct Descriptor {
247 uint8_t x_offset, y_offset;
248 uint8_t component, subsampling;
249 } block_descriptor[] = {
250 { 0, 0, 0, 0 }, { 8, 0, 0, 0 }, { 0, 8, 0, 0 }, { 8, 8, 0, 0 },
251 { 0, 0, 1, 1 }, { 0, 0, 2, 1 },
252 };
253
254 for (int i = 0; i < nb_blocks; ++i) {
255 const struct Descriptor *const desc = block_descriptor + i;
256 int width_avail = AV_CEIL_RSHIFT(valid_width, desc->subsampling) - desc->x_offset;
257 int height_avail = AV_CEIL_RSHIFT(valid_height, desc->subsampling) - desc->y_offset;
258
259 if (width_avail <= 0 || height_avail <= 0) {
260 // This block is outside of the visible part; don't replicate pixels,
261 // just zero the block, so that only the dc value will be coded.
262 memset(a->block[i], 0, sizeof(a->block[i]));
263 continue;
264 }
265 width_avail = FFMIN(width_avail, 8);
266 height_avail = FFMIN(height_avail, 8);
267
268 ptrdiff_t linesize = linesizes[desc->component];
269 const uint8_t *src = data[desc->component] + desc->y_offset * linesize + desc->x_offset;
270 int16_t *block = a->block[i];
271
272 for (int h = 0;; block += 8, src += linesize) {
273 int16_t last;
274 for (int w = 0; w < width_avail; ++w)
275 last = block[w] = src[w];
276 for (int w = width_avail; w < 8; ++w)
277 block[w] = last;
278 if (++h == height_avail)
279 break;
280 }
281 const int16_t *const last_row = block;
282 for (int h = height_avail; h < 8; ++h) {
283 block += 8;
284 AV_COPY128(block, last_row);
285 }
286
287 a->fdsp.fdct(a->block[i]);
288 }
289
290 encode_mb(a, a->block);
291}
292
294 const AVFrame *pict, int *got_packet)
295{
296 ASVEncContext *const a = avctx->priv_data;
297 const ASVCommonContext *const c = &a->c;
298 int size, ret;
299
300 ret = ff_alloc_packet(avctx, pkt, c->mb_height * c->mb_width * MAX_MB_SIZE + 3);
301 if (ret < 0)
302 return ret;
303
305 ((uintptr_t)pict->data[0] & 7 || pict->linesize[0] & 7 ||
306 (uintptr_t)pict->data[1] & 7 || pict->linesize[1] & 7 ||
307 (uintptr_t)pict->data[2] & 7 || pict->linesize[2] & 7))
308 a->get_pixels = a->pdsp.get_pixels_unaligned;
309 else
310 a->get_pixels = a->pdsp.get_pixels;
311
312 init_put_bits(&a->pb, pkt->data, pkt->size);
313
314 for (int mb_y = 0; mb_y < c->mb_height2; mb_y++) {
315 for (int mb_x = 0; mb_x < c->mb_width2; mb_x++) {
316 dct_get(a, pict, mb_x, mb_y);
317 encode_mb(a, a->block);
318 }
319 }
320
321 if (avctx->width & 15) {
322 const uint8_t *src[3] = {
323 pict->data[0] + c->mb_width2 * 16,
324 pict->data[1] + c->mb_width2 * 8,
325 pict->data[2] + c->mb_width2 * 8,
326 };
327 int available_width = avctx->width & 15;
328
329 for (int mb_y = 0; mb_y < c->mb_height2; mb_y++) {
330 handle_partial_mb(a, src, pict->linesize, available_width, 16);
331 src[0] += 16 * pict->linesize[0];
332 src[1] += 8 * pict->linesize[1];
333 src[2] += 8 * pict->linesize[2];
334 }
335 }
336
337 if (avctx->height & 15) {
338 const uint8_t *src[3] = {
339 pict->data[0] + c->mb_height2 * 16 * pict->linesize[0],
340 pict->data[1] + c->mb_height2 * 8 * pict->linesize[1],
341 pict->data[2] + c->mb_height2 * 8 * pict->linesize[2],
342 };
343 int available_height = avctx->height & 15;
344
345 for (int remaining = avctx->width;; remaining -= 16) {
346 handle_partial_mb(a, src, pict->linesize, remaining, available_height);
347 if (remaining <= 16)
348 break;
349 src[0] += 16;
350 src[1] += 8;
351 src[2] += 8;
352 }
353 }
354
355 if (avctx->codec_id == AV_CODEC_ID_ASV1)
356 flush_put_bits(&a->pb);
357 else
358 flush_put_bits_le(&a->pb);
359 AV_WN32(put_bits_ptr(&a->pb), 0);
360 size = (put_bytes_output(&a->pb) + 3) / 4;
361
362 if (avctx->codec_id == AV_CODEC_ID_ASV1) {
363 c->bbdsp.bswap_buf((uint32_t *) pkt->data,
364 (uint32_t *) pkt->data, size);
365 }
366
367 pkt->size = size * 4;
368 *got_packet = 1;
369
370 return 0;
371}
372
374{
375 ASVEncContext *const a = avctx->priv_data;
376 int i;
377 const int scale = avctx->codec_id == AV_CODEC_ID_ASV1 ? 1 : 2;
378 int inv_qscale;
379
380 ff_asv_common_init(avctx);
381 ff_fdctdsp_init(&a->fdsp, avctx);
382 ff_pixblockdsp_init(&a->pdsp, 8);
383
384 if (avctx->global_quality <= 0)
385 avctx->global_quality = 4 * FF_QUALITY_SCALE;
386
387 inv_qscale = (32 * scale * FF_QUALITY_SCALE +
388 avctx->global_quality / 2) / avctx->global_quality;
389
390 avctx->extradata = av_mallocz(8);
391 if (!avctx->extradata)
392 return AVERROR(ENOMEM);
393 avctx->extradata_size = 8;
394 AV_WL32A(avctx->extradata, inv_qscale);
395 AV_WL32A(avctx->extradata + 4, MKTAG('A', 'S', 'U', 'S'));
396
397 for (i = 0; i < 64; i++) {
398 if (a->fdsp.fdct == ff_fdct_ifast) {
400 a->q_intra_matrix[i] = (((int64_t)inv_qscale << 30) + q / 2) / q;
401 } else {
402 int q = 32 * scale * ff_mpeg1_default_intra_matrix[i];
403 a->q_intra_matrix[i] = ((inv_qscale << 16) + q / 2) / q;
404 }
405 }
406
407 return 0;
408}
409
410#if CONFIG_ASV1_ENCODER
411const FFCodec ff_asv1_encoder = {
412 .p.name = "asv1",
413 CODEC_LONG_NAME("ASUS V1"),
414 .p.type = AVMEDIA_TYPE_VIDEO,
415 .p.id = AV_CODEC_ID_ASV1,
417 .priv_data_size = sizeof(ASVEncContext),
418 .init = encode_init,
421 .color_ranges = AVCOL_RANGE_MPEG,
422};
423#endif
424
425#if CONFIG_ASV2_ENCODER
426const FFCodec ff_asv2_encoder = {
427 .p.name = "asv2",
428 CODEC_LONG_NAME("ASUS V2"),
429 .p.type = AVMEDIA_TYPE_VIDEO,
430 .p.id = AV_CODEC_ID_ASV2,
432 .priv_data_size = sizeof(ASVEncContext),
433 .init = encode_init,
436 .color_ranges = AVCOL_RANGE_MPEG,
437};
438#endif
const uint16_t ff_aanscales[64]
Definition aandcttab.c:26
AAN (Arai, Agui and Nakajima) (I)DCT tables.
const FFCodec ff_asv1_encoder
const FFCodec ff_asv2_encoder
const uint8_t ff_asv_level_tab[7][2]
Definition asv.c:53
const uint8_t ff_asv_dc_ccp_tab[8][2]
Definition asv.c:57
const uint8_t ff_asv_scantab[64]
Definition asv.c:34
const uint8_t ff_asv_ac_ccp_tab[16][2]
Definition asv.c:62
const uint16_t ff_asv2_level_tab[63][2]
Definition asv.c:69
av_cold void ff_asv_common_init(AVCodecContext *avctx)
Definition asv.c:91
const uint8_t ff_asv_ccp_tab[17][2]
Definition asv.c:45
ASUS V1/V2 encoder/decoder common data.
static void asv1_put_level(PutBitContext *pb, int level)
Definition asvenc.c:66
static void dct_get(ASVEncContext *a, const AVFrame *frame, int mb_x, int mb_y)
Definition asvenc.c:215
static int encode_mb(ASVEncContext *a, int16_t block[6][64])
Definition asvenc.c:198
static void asv2_encode_block(ASVEncContext *a, int16_t block[64])
Definition asvenc.c:145
static av_cold int encode_init(AVCodecContext *avctx)
Definition asvenc.c:373
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet)
Definition asvenc.c:293
static void asv2_put_level(ASVEncContext *a, PutBitContext *pb, int level)
Definition asvenc.c:81
static void handle_partial_mb(ASVEncContext *a, const uint8_t *const data[3], const int linesizes[3], int valid_width, int valid_height)
Definition asvenc.c:241
static void asv1_encode_block(ASVEncContext *a, int16_t block[64])
Definition asvenc.c:100
@ ASV1_MAX_MB_SIZE
Definition asvenc.c:60
@ ASV1_MAX_BLOCK_SIZE
Definition asvenc.c:59
@ ASV2_MAX_MB_SIZE
Definition asvenc.c:62
@ MAX_MB_SIZE
Definition asvenc.c:63
@ ASV2_MAX_BLOCK_SIZE
Definition asvenc.c:61
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
Libavcodec external API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define CODEC_PIXFMTS(...)
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
#define av_clip_int8
Definition common.h:109
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
long long int64_t
Definition coverity.c:34
static int16_t block[64]
Definition dct.c:125
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size)
Check AVPacket size and allocate data.
Definition encode.c:62
void ff_fdct_ifast(int16_t *data)
Definition jfdctfst.c:207
static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame, AVPacket *pkt)
Definition ffmpeg_enc.c:694
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
Definition codec.h:147
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
#define AV_CODEC_FLAG_GRAY
Only decode/encode grayscale.
Definition avcodec.h:302
@ AV_CODEC_ID_ASV1
Definition codec_id.h:81
@ AV_CODEC_ID_ASV2
Definition codec_id.h:82
#define FF_QUALITY_SCALE
Definition avutil.h:229
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
int index
Definition gxfenc.c:90
int a
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition intra.c:278
#define AV_WN32(p, v)
#define AV_COPY128(d, s)
#define AV_WL32A(p, v)
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition j2kenc.c:154
av_cold void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx)
Definition fdctdsp.c:25
av_cold void ff_pixblockdsp_init(PixblockDSPContext *c, int bits_per_raw_sample)
Definition pixblockdsp.c:87
Macro definitions for various function/variable attributes.
#define av_cold
Definition attributes.h:117
const char * desc
Definition libsvtav1.c:83
uint8_t w
Definition llvidencdsp.c:39
#define FFMIN(a, b)
Definition macros.h:49
#define MKTAG(a, b, c, d)
Definition macros.h:55
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
#define DECLARE_ALIGNED(n, t, v)
Declare a variable that is aligned in memory.
const uint16_t ff_mpeg1_default_intra_matrix[256]
Definition mpeg12data.c:31
MPEG-1/2 tables.
const char data[16]
Definition mxf.c:149
@ Descriptor
Definition mxf.h:40
#define PIXBLOCKDSP_8BPP_GET_PIXELS_SUPPORTS_UNALIGNED
Definition pixblockdsp.h:25
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition pixfmt.h:766
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
bitstream writer API
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition put_bits.h:62
static void put_bits_le(PutBitContext *s, int n, BitBuf value)
Definition put_bits.h:263
static void flush_put_bits_le(PutBitContext *s)
Definition put_bits.h:174
static uint8_t * put_bits_ptr(PutBitContext *s)
Return the pointer to the byte where the bitstream writer will put the next bit.
Definition put_bits.h:402
static int put_bytes_left(const PutBitContext *s, int round_up)
Definition put_bits.h:145
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition put_bits.h:153
static int put_bytes_output(const PutBitContext *s)
Definition put_bits.h:99
const uint8_t * code
Definition spdifenc.c:433
PutBitContext pb
Definition asvenc.c:46
void(* get_pixels)(int16_t *restrict block, const uint8_t *pixels, ptrdiff_t stride)
Definition asvenc.c:48
ASVCommonContext c
Definition asvenc.c:44
FDCTDSPContext fdsp
Definition asvenc.c:53
int16_t block[6][64]
Definition asvenc.c:54
PixblockDSPContext pdsp
Definition asvenc.c:52
int q_intra_matrix[64]
Definition asvenc.c:55
main external API structure.
Definition avcodec.h:443
int width
picture width / height.
Definition avcodec.h:604
int global_quality
Global quality for codecs which cannot change it per frame.
Definition avcodec.h:1235
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition avcodec.h:526
enum AVCodecID codec_id
Definition avcodec.h:453
int extradata_size
Definition avcodec.h:527
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
This structure stores compressed data.
Definition packet.h:580
uint8_t level
Definition svq3.c:208
#define stride
#define av_mallocz(s)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
int size
static double c[64]