|
|
@@ -204,15 +204,25 @@ static int hap_encode(AVCodecContext *avctx, AVPacket *pkt, |
|
|
if (ret < 0) |
|
|
if (ret < 0) |
|
|
return ret; |
|
|
return ret; |
|
|
|
|
|
|
|
|
/* DXTC compression. */ |
|
|
|
|
|
ret = compress_texture(avctx, ctx->tex_buf, ctx->tex_size, frame); |
|
|
|
|
|
if (ret < 0) |
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
|
|
/* Compress (using Snappy) the frame */ |
|
|
|
|
|
final_data_size = hap_compress_frame(avctx, pkt->data + header_length); |
|
|
|
|
|
if (final_data_size < 0) |
|
|
|
|
|
return final_data_size; |
|
|
|
|
|
|
|
|
if (ctx->opt_compressor == HAP_COMP_NONE) { |
|
|
|
|
|
/* DXTC compression directly to the packet buffer. */ |
|
|
|
|
|
ret = compress_texture(avctx, pkt->data + header_length, pkt->size - header_length, frame); |
|
|
|
|
|
if (ret < 0) |
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
|
|
ctx->chunks[0].compressor = HAP_COMP_NONE; |
|
|
|
|
|
final_data_size = ctx->tex_size; |
|
|
|
|
|
} else { |
|
|
|
|
|
/* DXTC compression. */ |
|
|
|
|
|
ret = compress_texture(avctx, ctx->tex_buf, ctx->tex_size, frame); |
|
|
|
|
|
if (ret < 0) |
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|
|
|
/* Compress (using Snappy) the frame */ |
|
|
|
|
|
final_data_size = hap_compress_frame(avctx, pkt->data + header_length); |
|
|
|
|
|
if (final_data_size < 0) |
|
|
|
|
|
return final_data_size; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/* Write header at the start. */ |
|
|
/* Write header at the start. */ |
|
|
hap_write_frame_header(ctx, pkt->data, final_data_size + header_length); |
|
|
hap_write_frame_header(ctx, pkt->data, final_data_size + header_length); |
|
|
@@ -273,10 +283,30 @@ static av_cold int hap_init(AVCodecContext *avctx) |
|
|
ctx->tex_size = FFALIGN(avctx->width, TEXTURE_BLOCK_W) * |
|
|
ctx->tex_size = FFALIGN(avctx->width, TEXTURE_BLOCK_W) * |
|
|
FFALIGN(avctx->height, TEXTURE_BLOCK_H) * 4 / ratio; |
|
|
FFALIGN(avctx->height, TEXTURE_BLOCK_H) * 4 / ratio; |
|
|
|
|
|
|
|
|
/* Round the chunk count to divide evenly on DXT block edges */ |
|
|
|
|
|
corrected_chunk_count = av_clip(ctx->opt_chunk_count, 1, HAP_MAX_CHUNKS); |
|
|
|
|
|
while ((ctx->tex_size / (64 / ratio)) % corrected_chunk_count != 0) { |
|
|
|
|
|
corrected_chunk_count--; |
|
|
|
|
|
|
|
|
switch (ctx->opt_compressor) { |
|
|
|
|
|
case HAP_COMP_NONE: |
|
|
|
|
|
/* No benefit chunking uncompressed data */ |
|
|
|
|
|
corrected_chunk_count = 1; |
|
|
|
|
|
|
|
|
|
|
|
ctx->max_snappy = ctx->tex_size; |
|
|
|
|
|
ctx->tex_buf = NULL; |
|
|
|
|
|
break; |
|
|
|
|
|
case HAP_COMP_SNAPPY: |
|
|
|
|
|
/* Round the chunk count to divide evenly on DXT block edges */ |
|
|
|
|
|
corrected_chunk_count = av_clip(ctx->opt_chunk_count, 1, HAP_MAX_CHUNKS); |
|
|
|
|
|
while ((ctx->tex_size / (64 / ratio)) % corrected_chunk_count != 0) { |
|
|
|
|
|
corrected_chunk_count--; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ctx->max_snappy = snappy_max_compressed_length(ctx->tex_size / corrected_chunk_count); |
|
|
|
|
|
ctx->tex_buf = av_malloc(ctx->tex_size); |
|
|
|
|
|
if (!ctx->tex_buf) { |
|
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid compresor %02X\n", ctx->opt_compressor); |
|
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
} |
|
|
} |
|
|
if (corrected_chunk_count != ctx->opt_chunk_count) { |
|
|
if (corrected_chunk_count != ctx->opt_chunk_count) { |
|
|
av_log(avctx, AV_LOG_INFO, "%d chunks requested but %d used.\n", |
|
|
av_log(avctx, AV_LOG_INFO, "%d chunks requested but %d used.\n", |
|
|
@@ -286,12 +316,6 @@ static av_cold int hap_init(AVCodecContext *avctx) |
|
|
if (ret != 0) |
|
|
if (ret != 0) |
|
|
return ret; |
|
|
return ret; |
|
|
|
|
|
|
|
|
ctx->max_snappy = snappy_max_compressed_length(ctx->tex_size / corrected_chunk_count); |
|
|
|
|
|
|
|
|
|
|
|
ctx->tex_buf = av_malloc(ctx->tex_size); |
|
|
|
|
|
if (!ctx->tex_buf) |
|
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -312,6 +336,9 @@ static const AVOption options[] = { |
|
|
{ "hap_alpha", "Hap Alpha (DXT5 textures)", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_FMT_RGBADXT5 }, 0, 0, FLAGS, "format" }, |
|
|
{ "hap_alpha", "Hap Alpha (DXT5 textures)", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_FMT_RGBADXT5 }, 0, 0, FLAGS, "format" }, |
|
|
{ "hap_q", "Hap Q (DXT5-YCoCg textures)", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_FMT_YCOCGDXT5 }, 0, 0, FLAGS, "format" }, |
|
|
{ "hap_q", "Hap Q (DXT5-YCoCg textures)", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_FMT_YCOCGDXT5 }, 0, 0, FLAGS, "format" }, |
|
|
{ "chunks", "chunk count", OFFSET(opt_chunk_count), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, HAP_MAX_CHUNKS, FLAGS, }, |
|
|
{ "chunks", "chunk count", OFFSET(opt_chunk_count), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, HAP_MAX_CHUNKS, FLAGS, }, |
|
|
|
|
|
{ "compressor", "second-stage compressor", OFFSET(opt_compressor), AV_OPT_TYPE_INT, { .i64 = HAP_COMP_SNAPPY }, HAP_COMP_NONE, HAP_COMP_SNAPPY, FLAGS, "compressor" }, |
|
|
|
|
|
{ "none", "None", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_COMP_NONE }, 0, 0, FLAGS, "compressor" }, |
|
|
|
|
|
{ "snappy", "Snappy", 0, AV_OPT_TYPE_CONST, { .i64 = HAP_COMP_SNAPPY }, 0, 0, FLAGS, "compressor" }, |
|
|
{ NULL }, |
|
|
{ NULL }, |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|