avcodec/hapdec: use the common texturedsp decode function

Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
Marton Balint 2022-03-19 21:01:41 +01:00
parent 30fdcd2e12
commit b3074ac9f4
2 changed files with 28 additions and 93 deletions

View File

@ -72,23 +72,18 @@ typedef struct HapContext {
HapChunk *chunks;
int *chunk_results; /* Results from threaded operations */
int tex_rat; /* Compression ratio */
int tex_rat2; /* Compression ratio of the second texture */
const uint8_t *tex_data; /* Compressed texture */
uint8_t *tex_buf; /* Buffer for compressed texture */
size_t tex_size; /* Size of the compressed texture */
size_t max_snappy; /* Maximum compressed size for snappy buffer */
int slice_count; /* Number of slices for threaded operations */
int texture_count; /* 2 for HAQA, 1 for other version */
int texture_section_size; /* size of the part of the texture section (for HAPQA) */
int uncompress_pix_size; /* nb of byte / pixel for the target picture */
/* Pointer to the selected compress or decompress function */
/* Pointer to the selected compress function (encoder only) */
int (*tex_fun)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block);
int (*tex_fun2)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block);
TextureDSPThreadContext dec[2];
} HapContext;
/*

View File

@ -247,60 +247,6 @@ static int decompress_chunks_thread(AVCodecContext *avctx, void *arg,
return 0;
}
static int decompress_texture_thread_internal(AVCodecContext *avctx, void *arg,
int slice, int thread_nb, int texture_num)
{
HapContext *ctx = avctx->priv_data;
AVFrame *frame = arg;
const uint8_t *d = ctx->tex_data;
int w_block = avctx->coded_width / TEXTURE_BLOCK_W;
int h_block = avctx->coded_height / TEXTURE_BLOCK_H;
int x, y;
int start_slice, end_slice;
int base_blocks_per_slice = h_block / ctx->slice_count;
int remainder_blocks = h_block % ctx->slice_count;
/* When the frame height (in blocks) doesn't divide evenly between the
* number of slices, spread the remaining blocks evenly between the first
* operations */
start_slice = slice * base_blocks_per_slice;
/* Add any extra blocks (one per slice) that have been added before this slice */
start_slice += FFMIN(slice, remainder_blocks);
end_slice = start_slice + base_blocks_per_slice;
/* Add an extra block if there are still remainder blocks to be accounted for */
if (slice < remainder_blocks)
end_slice++;
for (y = start_slice; y < end_slice; y++) {
uint8_t *p = frame->data[0] + y * frame->linesize[0] * TEXTURE_BLOCK_H;
int off = y * w_block;
for (x = 0; x < w_block; x++) {
if (texture_num == 0) {
ctx->tex_fun(p + x * 4 * ctx->uncompress_pix_size, frame->linesize[0],
d + (off + x) * ctx->tex_rat);
} else {
ctx->tex_fun2(p + x * 4 * ctx->uncompress_pix_size, frame->linesize[0],
d + (off + x) * ctx->tex_rat2);
}
}
}
return 0;
}
static int decompress_texture_thread(AVCodecContext *avctx, void *arg,
int slice, int thread_nb)
{
return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 0);
}
static int decompress_texture2_thread(AVCodecContext *avctx, void *arg,
int slice, int thread_nb)
{
return decompress_texture_thread_internal(avctx, arg, slice, thread_nb, 1);
}
static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
int *got_frame, AVPacket *avpkt)
{
@ -309,12 +255,9 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
int section_size;
enum HapSectionType section_type;
int start_texture_section = 0;
int tex_rat[2] = {0, 0};
bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size);
tex_rat[0] = ctx->tex_rat;
/* check for multi texture header */
if (ctx->texture_count == 2) {
ret = ff_hap_parse_section_header(&ctx->gbc, &section_size, &section_type);
@ -325,7 +268,6 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
return AVERROR_INVALIDDATA;
}
start_texture_section = 4;
tex_rat[1] = ctx->tex_rat2;
}
/* Get the output frame ready to receive data */
@ -343,7 +285,7 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
if (ctx->tex_size != (avctx->coded_width / TEXTURE_BLOCK_W)
*(avctx->coded_height / TEXTURE_BLOCK_H)
*tex_rat[t]) {
*ctx->dec[t].tex_ratio) {
av_log(avctx, AV_LOG_ERROR, "uncompressed size mismatches\n");
return AVERROR_INVALIDDATA;
}
@ -354,11 +296,11 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
if (hap_can_use_tex_in_place(ctx)) {
int tex_size;
/* Only DXTC texture compression in a contiguous block */
ctx->tex_data = ctx->gbc.buffer;
ctx->dec[t].tex_data.in = ctx->gbc.buffer;
tex_size = FFMIN(ctx->texture_section_size, bytestream2_get_bytes_left(&ctx->gbc));
if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W)
*(avctx->coded_height / TEXTURE_BLOCK_H)
*tex_rat[t]) {
*ctx->dec[t].tex_ratio) {
av_log(avctx, AV_LOG_ERROR, "Insufficient data\n");
return AVERROR_INVALIDDATA;
}
@ -376,15 +318,12 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
return ctx->chunk_results[i];
}
ctx->tex_data = ctx->tex_buf;
ctx->dec[t].tex_data.in = ctx->tex_buf;
}
/* Use the decompress function on the texture, one block per thread */
if (t == 0){
avctx->execute2(avctx, decompress_texture_thread, frame, NULL, ctx->slice_count);
} else{
avctx->execute2(avctx, decompress_texture2_thread, frame, NULL, ctx->slice_count);
}
ctx->dec[t].frame_data.out = frame->data[0];
ctx->dec[t].stride = frame->linesize[0];
avctx->execute2(avctx, ff_texturedsp_decompress_thread, &ctx->dec[t], NULL, ctx->dec[t].slice_count);
}
/* Frame is ready to be output */
@ -414,40 +353,44 @@ static av_cold int hap_init(AVCodecContext *avctx)
ff_texturedsp_init(&ctx->dxtc);
ctx->texture_count = 1;
ctx->uncompress_pix_size = 4;
ctx->dec[0].raw_ratio = 16;
ctx->dec[0].slice_count = av_clip(avctx->thread_count, 1,
avctx->coded_height / TEXTURE_BLOCK_H);
switch (avctx->codec_tag) {
case MKTAG('H','a','p','1'):
texture_name = "DXT1";
ctx->tex_rat = 8;
ctx->tex_fun = ctx->dxtc.dxt1_block;
ctx->dec[0].tex_ratio = 8;
ctx->dec[0].tex_funct = ctx->dxtc.dxt1_block;
avctx->pix_fmt = AV_PIX_FMT_RGB0;
break;
case MKTAG('H','a','p','5'):
texture_name = "DXT5";
ctx->tex_rat = 16;
ctx->tex_fun = ctx->dxtc.dxt5_block;
ctx->dec[0].tex_ratio = 16;
ctx->dec[0].tex_funct = ctx->dxtc.dxt5_block;
avctx->pix_fmt = AV_PIX_FMT_RGBA;
break;
case MKTAG('H','a','p','Y'):
texture_name = "DXT5-YCoCg-scaled";
ctx->tex_rat = 16;
ctx->tex_fun = ctx->dxtc.dxt5ys_block;
ctx->dec[0].tex_ratio = 16;
ctx->dec[0].tex_funct = ctx->dxtc.dxt5ys_block;
avctx->pix_fmt = AV_PIX_FMT_RGB0;
break;
case MKTAG('H','a','p','A'):
texture_name = "RGTC1";
ctx->tex_rat = 8;
ctx->tex_fun = ctx->dxtc.rgtc1u_gray_block;
ctx->dec[0].tex_ratio = 8;
ctx->dec[0].tex_funct = ctx->dxtc.rgtc1u_gray_block;
ctx->dec[0].raw_ratio = 4;
avctx->pix_fmt = AV_PIX_FMT_GRAY8;
ctx->uncompress_pix_size = 1;
break;
case MKTAG('H','a','p','M'):
texture_name = "DXT5-YCoCg-scaled / RGTC1";
ctx->tex_rat = 16;
ctx->tex_rat2 = 8;
ctx->tex_fun = ctx->dxtc.dxt5ys_block;
ctx->tex_fun2 = ctx->dxtc.rgtc1u_alpha_block;
ctx->dec[0].tex_ratio = 16;
ctx->dec[1].tex_ratio = 8;
ctx->dec[0].tex_funct = ctx->dxtc.dxt5ys_block;
ctx->dec[1].tex_funct = ctx->dxtc.rgtc1u_alpha_block;
ctx->dec[1].raw_ratio = 16;
ctx->dec[1].slice_count = ctx->dec[0].slice_count;
avctx->pix_fmt = AV_PIX_FMT_RGBA;
ctx->texture_count = 2;
break;
@ -457,9 +400,6 @@ static av_cold int hap_init(AVCodecContext *avctx)
av_log(avctx, AV_LOG_DEBUG, "%s texture\n", texture_name);
ctx->slice_count = av_clip(avctx->thread_count, 1,
avctx->coded_height / TEXTURE_BLOCK_H);
return 0;
}