summaryrefslogtreecommitdiffstats
path: root/libavcodec/hapenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/hapenc.c')
-rw-r--r--libavcodec/hapenc.c83
1 files changed, 58 insertions, 25 deletions
diff --git a/libavcodec/hapenc.c b/libavcodec/hapenc.c
index bf2ccaa..3a1bc87 100644
--- a/libavcodec/hapenc.c
+++ b/libavcodec/hapenc.c
@@ -3,20 +3,20 @@
* Copyright (C) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
* Copyright (C) 2015 Tom Butterworth <bangnoise@gmail.com>
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -52,12 +52,14 @@ enum HapHeaderLength {
HAP_HDR_LONG = 8,
};
-static void compress_texture(AVCodecContext *avctx, const AVFrame *f)
+static int compress_texture(AVCodecContext *avctx, uint8_t *out, int out_length, const AVFrame *f)
{
HapContext *ctx = avctx->priv_data;
- uint8_t *out = ctx->tex_buf;
int i, j;
+ if (ctx->tex_size > out_length)
+ return AVERROR_BUFFER_TOO_SMALL;
+
for (j = 0; j < avctx->height; j += 4) {
for (i = 0; i < avctx->width; i += 4) {
uint8_t *p = f->data[0] + i * 4 + j * f->linesize[0];
@@ -65,6 +67,8 @@ static void compress_texture(AVCodecContext *avctx, const AVFrame *f)
out += step;
}
}
+
+ return 0;
}
/* section_length does not include the header */
@@ -118,7 +122,7 @@ static int hap_compress_frame(AVCodecContext *avctx, uint8_t *dst)
/* If there is no gain from snappy, just use the raw texture. */
if (chunk->compressed_size >= chunk->uncompressed_size) {
av_log(avctx, AV_LOG_VERBOSE,
- "Snappy buffer bigger than uncompressed (%zu >= %zu bytes).\n",
+ "Snappy buffer bigger than uncompressed (%"SIZE_SPECIFIER" >= %"SIZE_SPECIFIER" bytes).\n",
chunk->compressed_size, chunk->uncompressed_size);
memcpy(chunk_dst, chunk_src, chunk->uncompressed_size);
chunk->compressor = HAP_COMP_NONE;
@@ -196,17 +200,29 @@ static int hap_encode(AVCodecContext *avctx, AVPacket *pkt,
int pktsize = FFMAX(ctx->tex_size, ctx->max_snappy * ctx->chunk_count) + header_length;
/* Allocate maximum size packet, shrink later. */
- ret = ff_alloc_packet(pkt, pktsize);
+ ret = ff_alloc_packet2(avctx, pkt, pktsize, header_length);
if (ret < 0)
return ret;
- /* DXTC compression. */
- compress_texture(avctx, frame);
+ 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;
- /* 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;
+ 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. */
hap_write_frame_header(ctx, pkt->data, final_data_size + header_length);
@@ -267,10 +283,30 @@ static av_cold int hap_init(AVCodecContext *avctx)
ctx->tex_size = FFALIGN(avctx->width, TEXTURE_BLOCK_W) *
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) {
av_log(avctx, AV_LOG_INFO, "%d chunks requested but %d used.\n",
@@ -280,12 +316,6 @@ static av_cold int hap_init(AVCodecContext *avctx)
if (ret != 0)
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;
}
@@ -306,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_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, },
+ { "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 },
};
@@ -318,7 +351,7 @@ static const AVClass hapenc_class = {
AVCodec ff_hap_encoder = {
.name = "hap",
- .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap encoder"),
+ .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_HAP,
.priv_data_size = sizeof(HapContext),
OpenPOWER on IntegriCloud