31#include <astcenc/astcenc.h>
45#define ASTC_MAGIC 0x5CA1AB13
46#define ASTC_HEADER_SIZE 16
47#define ASTC_BLOCK_BYTES 16
53 struct astcenc_config
cfg;
54 struct astcenc_context *
ctx;
70 enum astcenc_profile prf;
71 unsigned int flags = 0;
72 enum astcenc_error err;
78 if (
s->profile >= 0) {
79 prf = (
enum astcenc_profile)
s->profile;
84 prf = ASTCENC_PRF_LDR_SRGB;
87 prf = ASTCENC_PRF_LDR;
90 prf = ASTCENC_PRF_HDR_RGB_LDR_A;
93 prf = ASTCENC_PRF_HDR;
97 "Unsupported ASTC encoding profile %d.\n", avctx->
profile);
112 if (prf == ASTCENC_PRF_LDR || prf == ASTCENC_PRF_LDR_SRGB) {
113 prf = ASTCENC_PRF_HDR_RGB_LDR_A;
115 "Float/half input: auto-promoted profile to HDR_RGB_LDR_A.\n");
117 }
else if (prf == ASTCENC_PRF_HDR || prf == ASTCENC_PRF_HDR_RGB_LDR_A) {
119 "HDR profile selected but input is 8-bit; use float/half "
120 "input (e.g. -pix_fmt rgbaf16) for HDR.\n");
123 s->profile = (int)prf;
128 case ASTCENC_PRF_LDR_SRGB:
131 case ASTCENC_PRF_LDR:
134 case ASTCENC_PRF_HDR_RGB_LDR_A:
137 case ASTCENC_PRF_HDR:
146 avctx->
width > 0xFFFFFF || avctx->
height > 0xFFFFFF) {
158 if (sscanf(
s->block_size_str,
"%dx%dx%d%n", &
s->block_x, &
s->block_y,
159 &
s->block_z, &consumed) != 3) {
162 sscanf(
s->block_size_str,
"%dx%d%n", &
s->block_x, &
s->block_y,
165 if (!consumed ||
s->block_size_str[consumed]) {
167 "(expected e.g. 8x8 or 6x6x6).\n",
s->block_size_str);
172 flags |= ASTCENC_FLG_USE_PERCEPTUAL;
174 flags |= ASTCENC_FLG_USE_ALPHA_WEIGHT;
176 err = astcenc_config_init(prf,
s->block_x,
s->block_y,
s->block_z,
178 if (err != ASTCENC_SUCCESS) {
180 astcenc_get_error_string(err));
188 s->block_x =
s->cfg.block_x;
189 s->block_y =
s->cfg.block_y;
190 s->block_z =
s->cfg.block_z;
192 err = astcenc_context_alloc(&
s->cfg, 1, &
s->ctx,
NULL);
193 if (err != ASTCENC_SUCCESS) {
195 astcenc_get_error_string(err));
219 h[4] = (uint8_t)
s->block_x;
220 h[5] = (uint8_t)
s->block_y;
221 h[6] = (uint8_t)
s->block_z;
234 const int w =
frame->width;
235 const int h =
frame->height;
236 const int bx =
s->block_x;
237 const int by =
s->block_y;
238 size_t blocks_x, blocks_y, block_count,
out_size;
242 "Frame size %dx%d does not match configured %dx%d.\n",
247 blocks_x = (
w - 1) / bx + 1;
248 blocks_y = (
h - 1) / by + 1;
249 if (
av_size_mult(blocks_x, blocks_y, &block_count) < 0 ||
254 struct astcenc_swizzle swz = {
255 ASTCENC_SWZ_R, ASTCENC_SWZ_G, ASTCENC_SWZ_B, ASTCENC_SWZ_A
261 struct astcenc_image
img;
262 enum astcenc_error err;
270 enum astcenc_type
type;
272 switch (
frame->format) {
273 case AV_PIX_FMT_RGBA:
type = ASTCENC_TYPE_U8; elem = 1; planar = 0; const_alpha = 0;
break;
284 size_t row_bytes, buf_size;
291 if (!planar && !const_alpha &&
frame->linesize[0] == (
int)row_bytes) {
292 packed =
frame->data[0];
301 for (
int y = 0; y <
h; y++) {
302 const float *
g = (
const float *)(
frame->data[0] + (
size_t)y *
frame->linesize[0]);
303 const float *
b = (
const float *)(
frame->data[1] + (
size_t)y *
frame->linesize[1]);
304 const float *
r = (
const float *)(
frame->data[2] + (
size_t)y *
frame->linesize[2]);
305 const float *
a = (
const float *)(
frame->data[3] + (
size_t)y *
frame->linesize[3]);
306 float *
dst = (
float *)(buf + (
size_t)y * row_bytes);
307 for (
int x = 0; x <
w; x++) {
308 dst[4*x+0] =
r[x];
dst[4*x+1] =
g[x];
309 dst[4*x+2] =
b[x];
dst[4*x+3] =
a[x];
312 }
else if (const_alpha) {
313 for (
int y = 0; y <
h; y++) {
314 const uint8_t *
src =
frame->data[0] + (size_t)y *
frame->linesize[0];
315 uint8_t *
dst = buf + (size_t)y * row_bytes;
316 for (
int x = 0; x <
w; x++) {
318 dst[4*x+2] =
src[3*x+2];
dst[4*x+3] = 255;
323 for (
int y = 0; y <
h; y++)
324 memcpy(buf + (
size_t)y * row_bytes,
325 frame->data[0] + (
size_t)y *
frame->linesize[0], row_bytes);
333 data_ptrs[0] = packed;
334 img.data = data_ptrs;
340 err = astcenc_compress_image(
s->ctx, &
img, &swz,
pkt->data,
pkt->size, 0);
341 if (err != ASTCENC_SUCCESS) {
343 astcenc_get_error_string(err));
360 astcenc_context_free(
s->ctx);
366#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
367#define OFFSET(x) offsetof(LibAstcEncContext, x)
370 {
"block_size",
"ASTC block size WxH[xD] (e.g. 4x4, 8x8, 6x6x6)",
OFFSET(block_size_str),
372 {
"quality",
"Compression quality 0..100 (0=fastest, 100=exhaustive)",
374 {
"profile",
"Color profile (overrides AVCodecContext.profile)",
376 {
"ldr",
"Linear LDR", 0,
AV_OPT_TYPE_CONST, { .i64 = ASTCENC_PRF_LDR }, 0, 0,
VE, .unit =
"profile" },
377 {
"ldr-srgb",
"sRGB LDR", 0,
AV_OPT_TYPE_CONST, { .i64 = ASTCENC_PRF_LDR_SRGB }, 0, 0,
VE, .unit =
"profile" },
378 {
"hdr-ldr-a",
"HDR RGB, LDR alpha", 0,
AV_OPT_TYPE_CONST, { .i64 = ASTCENC_PRF_HDR_RGB_LDR_A }, 0, 0,
VE, .unit =
"profile" },
379 {
"hdr",
"HDR", 0,
AV_OPT_TYPE_CONST, { .i64 = ASTCENC_PRF_HDR }, 0, 0,
VE, .unit =
"profile" },
380 {
"perceptual",
"Use perceptual (PSNR-weighted) error metric",
OFFSET(
perceptual),
382 {
"alpha_weight",
"Enable alpha weighting",
OFFSET(alpha_weight),
388 .class_name =
"libastcenc",
395 .p.name =
"libastcenc",
396 CODEC_LONG_NAME(
"ASTC (Adaptive Scalable Texture Compression) image using astc-encoder"),
404 .p.wrapper_name =
"libastcenc",
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
const FFCodec ff_libastcenc_encoder
Libavcodec external API header.
#define flags(name, subs,...)
static IPT perceptual(const CmsCtx *ctx, IPT ipt)
#define CODEC_PIXFMTS(...)
#define FF_CODEC_CAP_NOT_INIT_THREADSAFE
The codec is not known to be init-threadsafe (i.e.
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
#define AV_PROFILE_UNKNOWN
#define AV_PROFILE_ASTC_LDR
Linear LDR.
#define AV_PROFILE_ASTC_HDR
HDR RGB and alpha.
#define AV_PROFILE_ASTC_HDR_RGB_LDR_A
HDR RGB with LDR alpha.
#define AV_PROFILE_ASTC_LDR_SRGB
sRGB LDR.
int(* init)(AVBSFContext *ctx)
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
int av_size_mult(size_t a, size_t b, size_t *r)
Multiply two size_t values checking for overflow.
#define LIBAVUTIL_VERSION_INT
static av_cold int libastcenc_init(AVCodecContext *avctx)
static av_cold int libastcenc_close(AVCodecContext *avctx)
static const AVClass libastcenc_class
static int libastcenc_encode(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Memory handling functions.
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
#define AV_PIX_FMT_RGBAF32
#define AV_PIX_FMT_RGBAF16
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
#define AV_PIX_FMT_GBRAPF32
const AVProfile ff_astc_profiles[]
Describe the class of an AVClass context structure.
main external API structure.
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
int width
picture width / height.
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
This structure describes decoded (raw) audio or video data.
This structure stores compressed data.
struct astcenc_config cfg
struct astcenc_context * ctx
static const uint8_t quality[]