avcodec/hapdec: use the common texturedsp decode function
Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
parent
30fdcd2e12
commit
b3074ac9f4
@ -72,23 +72,18 @@ typedef struct HapContext {
|
|||||||
HapChunk *chunks;
|
HapChunk *chunks;
|
||||||
int *chunk_results; /* Results from threaded operations */
|
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 */
|
uint8_t *tex_buf; /* Buffer for compressed texture */
|
||||||
size_t tex_size; /* Size of the compressed texture */
|
size_t tex_size; /* Size of the compressed texture */
|
||||||
|
|
||||||
size_t max_snappy; /* Maximum compressed size for snappy buffer */
|
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_count; /* 2 for HAQA, 1 for other version */
|
||||||
int texture_section_size; /* size of the part of the texture section (for HAPQA) */
|
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_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;
|
} HapContext;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -247,60 +247,6 @@ static int decompress_chunks_thread(AVCodecContext *avctx, void *arg,
|
|||||||
return 0;
|
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,
|
static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
|
||||||
int *got_frame, AVPacket *avpkt)
|
int *got_frame, AVPacket *avpkt)
|
||||||
{
|
{
|
||||||
@ -309,12 +255,9 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
|
|||||||
int section_size;
|
int section_size;
|
||||||
enum HapSectionType section_type;
|
enum HapSectionType section_type;
|
||||||
int start_texture_section = 0;
|
int start_texture_section = 0;
|
||||||
int tex_rat[2] = {0, 0};
|
|
||||||
|
|
||||||
bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size);
|
bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size);
|
||||||
|
|
||||||
tex_rat[0] = ctx->tex_rat;
|
|
||||||
|
|
||||||
/* check for multi texture header */
|
/* check for multi texture header */
|
||||||
if (ctx->texture_count == 2) {
|
if (ctx->texture_count == 2) {
|
||||||
ret = ff_hap_parse_section_header(&ctx->gbc, §ion_size, §ion_type);
|
ret = ff_hap_parse_section_header(&ctx->gbc, §ion_size, §ion_type);
|
||||||
@ -325,7 +268,6 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
start_texture_section = 4;
|
start_texture_section = 4;
|
||||||
tex_rat[1] = ctx->tex_rat2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the output frame ready to receive data */
|
/* 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)
|
if (ctx->tex_size != (avctx->coded_width / TEXTURE_BLOCK_W)
|
||||||
*(avctx->coded_height / TEXTURE_BLOCK_H)
|
*(avctx->coded_height / TEXTURE_BLOCK_H)
|
||||||
*tex_rat[t]) {
|
*ctx->dec[t].tex_ratio) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "uncompressed size mismatches\n");
|
av_log(avctx, AV_LOG_ERROR, "uncompressed size mismatches\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
@ -354,11 +296,11 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
|
|||||||
if (hap_can_use_tex_in_place(ctx)) {
|
if (hap_can_use_tex_in_place(ctx)) {
|
||||||
int tex_size;
|
int tex_size;
|
||||||
/* Only DXTC texture compression in a contiguous block */
|
/* 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));
|
tex_size = FFMIN(ctx->texture_section_size, bytestream2_get_bytes_left(&ctx->gbc));
|
||||||
if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W)
|
if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W)
|
||||||
*(avctx->coded_height / TEXTURE_BLOCK_H)
|
*(avctx->coded_height / TEXTURE_BLOCK_H)
|
||||||
*tex_rat[t]) {
|
*ctx->dec[t].tex_ratio) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Insufficient data\n");
|
av_log(avctx, AV_LOG_ERROR, "Insufficient data\n");
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
@ -376,15 +318,12 @@ static int hap_decode(AVCodecContext *avctx, AVFrame *frame,
|
|||||||
return ctx->chunk_results[i];
|
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 */
|
ctx->dec[t].frame_data.out = frame->data[0];
|
||||||
if (t == 0){
|
ctx->dec[t].stride = frame->linesize[0];
|
||||||
avctx->execute2(avctx, decompress_texture_thread, frame, NULL, ctx->slice_count);
|
avctx->execute2(avctx, ff_texturedsp_decompress_thread, &ctx->dec[t], NULL, ctx->dec[t].slice_count);
|
||||||
} else{
|
|
||||||
avctx->execute2(avctx, decompress_texture2_thread, frame, NULL, ctx->slice_count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Frame is ready to be output */
|
/* Frame is ready to be output */
|
||||||
@ -414,40 +353,44 @@ static av_cold int hap_init(AVCodecContext *avctx)
|
|||||||
ff_texturedsp_init(&ctx->dxtc);
|
ff_texturedsp_init(&ctx->dxtc);
|
||||||
|
|
||||||
ctx->texture_count = 1;
|
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) {
|
switch (avctx->codec_tag) {
|
||||||
case MKTAG('H','a','p','1'):
|
case MKTAG('H','a','p','1'):
|
||||||
texture_name = "DXT1";
|
texture_name = "DXT1";
|
||||||
ctx->tex_rat = 8;
|
ctx->dec[0].tex_ratio = 8;
|
||||||
ctx->tex_fun = ctx->dxtc.dxt1_block;
|
ctx->dec[0].tex_funct = ctx->dxtc.dxt1_block;
|
||||||
avctx->pix_fmt = AV_PIX_FMT_RGB0;
|
avctx->pix_fmt = AV_PIX_FMT_RGB0;
|
||||||
break;
|
break;
|
||||||
case MKTAG('H','a','p','5'):
|
case MKTAG('H','a','p','5'):
|
||||||
texture_name = "DXT5";
|
texture_name = "DXT5";
|
||||||
ctx->tex_rat = 16;
|
ctx->dec[0].tex_ratio = 16;
|
||||||
ctx->tex_fun = ctx->dxtc.dxt5_block;
|
ctx->dec[0].tex_funct = ctx->dxtc.dxt5_block;
|
||||||
avctx->pix_fmt = AV_PIX_FMT_RGBA;
|
avctx->pix_fmt = AV_PIX_FMT_RGBA;
|
||||||
break;
|
break;
|
||||||
case MKTAG('H','a','p','Y'):
|
case MKTAG('H','a','p','Y'):
|
||||||
texture_name = "DXT5-YCoCg-scaled";
|
texture_name = "DXT5-YCoCg-scaled";
|
||||||
ctx->tex_rat = 16;
|
ctx->dec[0].tex_ratio = 16;
|
||||||
ctx->tex_fun = ctx->dxtc.dxt5ys_block;
|
ctx->dec[0].tex_funct = ctx->dxtc.dxt5ys_block;
|
||||||
avctx->pix_fmt = AV_PIX_FMT_RGB0;
|
avctx->pix_fmt = AV_PIX_FMT_RGB0;
|
||||||
break;
|
break;
|
||||||
case MKTAG('H','a','p','A'):
|
case MKTAG('H','a','p','A'):
|
||||||
texture_name = "RGTC1";
|
texture_name = "RGTC1";
|
||||||
ctx->tex_rat = 8;
|
ctx->dec[0].tex_ratio = 8;
|
||||||
ctx->tex_fun = ctx->dxtc.rgtc1u_gray_block;
|
ctx->dec[0].tex_funct = ctx->dxtc.rgtc1u_gray_block;
|
||||||
|
ctx->dec[0].raw_ratio = 4;
|
||||||
avctx->pix_fmt = AV_PIX_FMT_GRAY8;
|
avctx->pix_fmt = AV_PIX_FMT_GRAY8;
|
||||||
ctx->uncompress_pix_size = 1;
|
|
||||||
break;
|
break;
|
||||||
case MKTAG('H','a','p','M'):
|
case MKTAG('H','a','p','M'):
|
||||||
texture_name = "DXT5-YCoCg-scaled / RGTC1";
|
texture_name = "DXT5-YCoCg-scaled / RGTC1";
|
||||||
ctx->tex_rat = 16;
|
ctx->dec[0].tex_ratio = 16;
|
||||||
ctx->tex_rat2 = 8;
|
ctx->dec[1].tex_ratio = 8;
|
||||||
ctx->tex_fun = ctx->dxtc.dxt5ys_block;
|
ctx->dec[0].tex_funct = ctx->dxtc.dxt5ys_block;
|
||||||
ctx->tex_fun2 = ctx->dxtc.rgtc1u_alpha_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;
|
avctx->pix_fmt = AV_PIX_FMT_RGBA;
|
||||||
ctx->texture_count = 2;
|
ctx->texture_count = 2;
|
||||||
break;
|
break;
|
||||||
@ -457,9 +400,6 @@ static av_cold int hap_init(AVCodecContext *avctx)
|
|||||||
|
|
||||||
av_log(avctx, AV_LOG_DEBUG, "%s texture\n", texture_name);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user