avcodec/utvideodec: add vlc multi support
Faster decoding, by average 50% faster overall.
This commit is contained in:
parent
8b7391cb5f
commit
da888b790a
@ -81,6 +81,7 @@ typedef struct UtvideoContext {
|
||||
ptrdiff_t slice_stride;
|
||||
uint8_t *slice_bits, *slice_buffer[4];
|
||||
int slice_bits_size;
|
||||
void *buffer;
|
||||
|
||||
const uint8_t *packed_stream[4][256];
|
||||
size_t packed_stream_size[4][256];
|
||||
|
@ -46,7 +46,7 @@ typedef struct HuffEntry {
|
||||
} HuffEntry;
|
||||
|
||||
static int build_huff(UtvideoContext *c, const uint8_t *src, VLC *vlc,
|
||||
int *fsym, unsigned nb_elems)
|
||||
VLC_MULTI *multi, int *fsym, unsigned nb_elems)
|
||||
{
|
||||
int i;
|
||||
HuffEntry he[1024];
|
||||
@ -82,11 +82,35 @@ static int build_huff(UtvideoContext *c, const uint8_t *src, VLC *vlc,
|
||||
he[--codes_count[bits[i]]] = (HuffEntry) { bits[i], i };
|
||||
|
||||
#define VLC_BITS 11
|
||||
return ff_init_vlc_from_lengths(vlc, VLC_BITS, codes_count[0],
|
||||
return ff_init_vlc_multi_from_lengths(vlc, multi, VLC_BITS, nb_elems, codes_count[0],
|
||||
&he[0].len, sizeof(*he),
|
||||
&he[0].sym, sizeof(*he), 2, 0, 0, c->avctx);
|
||||
}
|
||||
|
||||
#define READ_PLANE(b, end) \
|
||||
{ \
|
||||
buf = !use_pred ? dest : c->buffer; \
|
||||
i = 0; \
|
||||
for (; CACHED_BITSTREAM_READER && i < width-end && get_bits_left(&gb) > 0;) {\
|
||||
ret = get_vlc_multi(&gb, (uint8_t *)buf + i * b, multi.table, \
|
||||
vlc.table, VLC_BITS, 3); \
|
||||
if (ret > 0) \
|
||||
i += ret; \
|
||||
if (ret <= 0) \
|
||||
goto fail; \
|
||||
} \
|
||||
for (; i < width && get_bits_left(&gb) > 0; i++) \
|
||||
buf[i] = get_vlc2(&gb, vlc.table, VLC_BITS, 3); \
|
||||
if (use_pred) { \
|
||||
if (b == 2) \
|
||||
c->llviddsp.add_left_pred_int16((uint16_t *)dest, (const uint16_t *)buf, 0x3ff, width, prev); \
|
||||
else \
|
||||
c->llviddsp.add_left_pred((uint8_t *)dest, (const uint8_t *)buf, width, prev); \
|
||||
} \
|
||||
prev = dest[width-1]; \
|
||||
dest += stride; \
|
||||
}
|
||||
|
||||
static int decode_plane10(UtvideoContext *c, int plane_no,
|
||||
uint16_t *dst, ptrdiff_t stride,
|
||||
int width, int height,
|
||||
@ -95,11 +119,12 @@ static int decode_plane10(UtvideoContext *c, int plane_no,
|
||||
{
|
||||
int i, j, slice, pix, ret;
|
||||
int sstart, send;
|
||||
VLC_MULTI multi;
|
||||
VLC vlc;
|
||||
GetBitContext gb;
|
||||
int prev, fsym;
|
||||
|
||||
if ((ret = build_huff(c, huff, &vlc, &fsym, 1024)) < 0) {
|
||||
if ((ret = build_huff(c, huff, &vlc, &multi, &fsym, 1024)) < 0) {
|
||||
av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
|
||||
return ret;
|
||||
}
|
||||
@ -131,7 +156,7 @@ static int decode_plane10(UtvideoContext *c, int plane_no,
|
||||
|
||||
send = 0;
|
||||
for (slice = 0; slice < c->slices; slice++) {
|
||||
uint16_t *dest;
|
||||
uint16_t *dest, *buf;
|
||||
int slice_data_start, slice_data_end, slice_size;
|
||||
|
||||
sstart = send;
|
||||
@ -156,37 +181,20 @@ static int decode_plane10(UtvideoContext *c, int plane_no,
|
||||
init_get_bits(&gb, c->slice_bits, slice_size * 8);
|
||||
|
||||
prev = 0x200;
|
||||
for (j = sstart; j < send; j++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);
|
||||
if (pix < 0) {
|
||||
av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
|
||||
goto fail;
|
||||
}
|
||||
if (use_pred) {
|
||||
prev += pix;
|
||||
prev &= 0x3FF;
|
||||
pix = prev;
|
||||
}
|
||||
dest[i] = pix;
|
||||
}
|
||||
dest += stride;
|
||||
if (get_bits_left(&gb) < 0) {
|
||||
av_log(c->avctx, AV_LOG_ERROR,
|
||||
"Slice decoding ran out of bits\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
for (j = sstart; j < send; j++)
|
||||
READ_PLANE(2, 3)
|
||||
if (get_bits_left(&gb) > 32)
|
||||
av_log(c->avctx, AV_LOG_WARNING,
|
||||
"%d bits left after decoding slice\n", get_bits_left(&gb));
|
||||
}
|
||||
|
||||
ff_free_vlc(&vlc);
|
||||
ff_free_vlc_multi(&multi);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
ff_free_vlc(&vlc);
|
||||
ff_free_vlc_multi(&multi);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
@ -207,6 +215,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
|
||||
{
|
||||
int i, j, slice, pix;
|
||||
int sstart, send;
|
||||
VLC_MULTI multi;
|
||||
VLC vlc;
|
||||
GetBitContext gb;
|
||||
int ret, prev, fsym;
|
||||
@ -259,7 +268,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (build_huff(c, src, &vlc, &fsym, 256)) {
|
||||
if (build_huff(c, src, &vlc, &multi, &fsym, 256)) {
|
||||
av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
@ -292,7 +301,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
|
||||
|
||||
send = 0;
|
||||
for (slice = 0; slice < c->slices; slice++) {
|
||||
uint8_t *dest;
|
||||
uint8_t *dest, *buf;
|
||||
int slice_data_start, slice_data_end, slice_size;
|
||||
|
||||
sstart = send;
|
||||
@ -317,36 +326,20 @@ static int decode_plane(UtvideoContext *c, int plane_no,
|
||||
init_get_bits(&gb, c->slice_bits, slice_size * 8);
|
||||
|
||||
prev = 0x80;
|
||||
for (j = sstart; j < send; j++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3);
|
||||
if (pix < 0) {
|
||||
av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n");
|
||||
goto fail;
|
||||
}
|
||||
if (use_pred) {
|
||||
prev += pix;
|
||||
pix = prev;
|
||||
}
|
||||
dest[i] = pix;
|
||||
}
|
||||
if (get_bits_left(&gb) < 0) {
|
||||
av_log(c->avctx, AV_LOG_ERROR,
|
||||
"Slice decoding ran out of bits\n");
|
||||
goto fail;
|
||||
}
|
||||
dest += stride;
|
||||
}
|
||||
for (j = sstart; j < send; j++)
|
||||
READ_PLANE(1, 5)
|
||||
if (get_bits_left(&gb) > 32)
|
||||
av_log(c->avctx, AV_LOG_WARNING,
|
||||
"%d bits left after decoding slice\n", get_bits_left(&gb));
|
||||
}
|
||||
|
||||
ff_free_vlc(&vlc);
|
||||
ff_free_vlc_multi(&multi);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
ff_free_vlc(&vlc);
|
||||
ff_free_vlc_multi(&multi);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
@ -992,6 +985,10 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
c->buffer = av_calloc(avctx->width, c->pro?2:1);
|
||||
if (!c->buffer)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &h_shift, &v_shift);
|
||||
if ((avctx->width & ((1<<h_shift)-1)) ||
|
||||
(avctx->height & ((1<<v_shift)-1))) {
|
||||
@ -1047,6 +1044,7 @@ static av_cold int decode_end(AVCodecContext *avctx)
|
||||
UtvideoContext * const c = avctx->priv_data;
|
||||
|
||||
av_freep(&c->slice_bits);
|
||||
av_freep(&c->buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user