1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-11-26 19:01:44 +02:00

avcodec/huffyuv: Split HYuvContext into decoder and encoder context

While the share of elements used by both is quite big, the amount
of code shared between the decoders and encoders is negligible.
Therefore one can easily split the context if one wants to.
The reasons for doing so are that the non-shared elements
are non-negligible: The stats array which is only used by
the encoder takes 524288B of 868904B (on x64); similarly,
pix_bgr_map which is only used by the decoder takes 16KiB.
Furthermore, using a shared context also entails inclusions
of unneeded headers like put_bits.h for the decoder and get_bits.h
for the encoder (and all of these and much more for huffyuv.c).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt 2022-10-01 23:36:09 +02:00
parent 83a8b9fac7
commit 566280c3f4
6 changed files with 138 additions and 114 deletions

View File

@ -30,10 +30,11 @@
#include <stdint.h>
#include "libavutil/attributes.h"
#include "libavutil/error.h"
#include "libavutil/log.h"
#include "libavutil/mem.h"
#include "avcodec.h"
#include "bswapdsp.h"
#include "huffyuv.h"
int ff_huffyuv_generate_bits_table(uint32_t *dst, const uint8_t *len_table, int n)
@ -55,25 +56,25 @@ int ff_huffyuv_generate_bits_table(uint32_t *dst, const uint8_t *len_table, int
return 0;
}
av_cold int ff_huffyuv_alloc_temp(HYuvContext *s, int width)
av_cold int ff_huffyuv_alloc_temp(uint8_t *temp[3], uint16_t *temp16[3], int width)
{
int i;
for (i=0; i<3; i++) {
s->temp[i] = av_malloc(4 * width + 16);
if (!s->temp[i])
temp[i] = av_malloc(4 * width + 16);
if (!temp[i])
return AVERROR(ENOMEM);
s->temp16[i] = (uint16_t*)s->temp[i];
temp16[i] = (uint16_t*)temp[i];
}
return 0;
}
av_cold void ff_huffyuv_common_end(HYuvContext *s)
av_cold void ff_huffyuv_common_end(uint8_t *temp[3], uint16_t *temp16[3])
{
int i;
for(i = 0; i < 3; i++) {
av_freep(&s->temp[i]);
s->temp16[i] = NULL;
av_freep(&temp[i]);
temp16[i] = NULL;
}
}

View File

@ -31,16 +31,19 @@
#include <stdint.h>
#include "avcodec.h"
#include "bswapdsp.h"
#include "get_bits.h"
#include "huffyuvdsp.h"
#include "huffyuvencdsp.h"
#include "put_bits.h"
#include "lossless_videodsp.h"
#include "lossless_videoencdsp.h"
#include "config.h"
#define VLC_BITS 12
#if HAVE_BIGENDIAN
#define B 3
#define G 2
#define R 1
#define A 0
#else
#define B 0
#define G 1
#define R 2
#define A 3
#endif
#define MAX_BITS 16
#define MAX_N (1<<MAX_BITS)
@ -52,49 +55,8 @@ typedef enum Predictor {
MEDIAN,
} Predictor;
typedef struct HYuvContext {
AVClass *class;
AVCodecContext *avctx;
Predictor predictor;
GetBitContext gb;
PutBitContext pb;
int interlaced;
int decorrelate;
int bitstream_bpp;
int version;
int yuy2; //use yuy2 instead of 422P
int bgr32; //use bgr32 instead of bgr24
int bps;
int n; // 1<<bps
int vlc_n; // number of vlc codes (FFMIN(1<<bps, MAX_VLC_N))
int alpha;
int chroma;
int yuv;
int chroma_h_shift;
int chroma_v_shift;
int flags;
int context;
int picture_number;
int last_slice_end;
uint8_t *temp[3];
uint16_t *temp16[3]; ///< identical to temp but 16bit type
uint64_t stats[4][MAX_VLC_N];
uint8_t len[4][MAX_VLC_N];
uint32_t bits[4][MAX_VLC_N];
uint32_t pix_bgr_map[1<<VLC_BITS];
VLC vlc[8]; //Y,U,V,A,YY,YU,YV,AA
uint8_t *bitstream_buffer;
unsigned int bitstream_buffer_size;
BswapDSPContext bdsp;
HuffYUVDSPContext hdsp;
HuffYUVEncDSPContext hencdsp;
LLVidDSPContext llviddsp;
LLVidEncDSPContext llvidencdsp;
int non_determ; // non-deterministic, multi-threaded encoder allowed
} HYuvContext;
void ff_huffyuv_common_end(HYuvContext *s);
int ff_huffyuv_alloc_temp(HYuvContext *s, int width);
void ff_huffyuv_common_end(uint8_t *temp[3], uint16_t *temp16[3]);
int ff_huffyuv_alloc_temp(uint8_t *temp[3], uint16_t *temp16[3], int width);
int ff_huffyuv_generate_bits_table(uint32_t *dst, const uint8_t *len_table, int n);
#endif /* AVCODEC_HUFFYUV_H */

View File

@ -35,6 +35,7 @@
#include "config_components.h"
#include "avcodec.h"
#include "bswapdsp.h"
#include "codec_internal.h"
#include "get_bits.h"
#include "huffyuv.h"
@ -44,6 +45,43 @@
#include "libavutil/imgutils.h"
#include "libavutil/pixdesc.h"
#define VLC_BITS 12
typedef struct HYuvDecContext {
GetBitContext gb;
Predictor predictor;
int interlaced;
int decorrelate;
int bitstream_bpp;
int version;
int yuy2; //use yuy2 instead of 422P
int bgr32; //use bgr32 instead of bgr24
int bps;
int n; // 1<<bps
int vlc_n; // number of vlc codes (FFMIN(1<<bps, MAX_VLC_N))
int alpha;
int chroma;
int yuv;
int chroma_h_shift;
int chroma_v_shift;
int flags;
int context;
int last_slice_end;
uint8_t *temp[3];
uint16_t *temp16[3]; ///< identical to temp but 16bit type
uint8_t len[4][MAX_VLC_N];
uint32_t bits[4][MAX_VLC_N];
uint32_t pix_bgr_map[1<<VLC_BITS];
VLC vlc[8]; //Y,U,V,A,YY,YU,YV,AA
uint8_t *bitstream_buffer;
unsigned int bitstream_buffer_size;
BswapDSPContext bdsp;
HuffYUVDSPContext hdsp;
LLVidDSPContext llviddsp;
} HYuvDecContext;
#define classic_shift_luma_table_size 42
static const unsigned char classic_shift_luma[classic_shift_luma_table_size + AV_INPUT_BUFFER_PADDING_SIZE] = {
34, 36, 35, 69, 135, 232, 9, 16, 10, 24, 11, 23, 12, 16, 13, 10,
@ -118,7 +156,7 @@ static int read_len_table(uint8_t *dst, GetBitContext *gb, int n)
return 0;
}
static int generate_joint_tables(HYuvContext *s)
static int generate_joint_tables(HYuvDecContext *s)
{
int ret;
uint16_t *symbols = av_mallocz(5 << VLC_BITS);
@ -208,7 +246,7 @@ out:
return ret;
}
static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length)
static int read_huffman_tables(HYuvDecContext *s, const uint8_t *src, int length)
{
GetBitContext gb;
int i, ret;
@ -237,7 +275,7 @@ static int read_huffman_tables(HYuvContext *s, const uint8_t *src, int length)
return (get_bits_count(&gb) + 7) / 8;
}
static int read_old_huffman_tables(HYuvContext *s)
static int read_old_huffman_tables(HYuvDecContext *s)
{
GetBitContext gb;
int i, ret;
@ -279,10 +317,10 @@ static int read_old_huffman_tables(HYuvContext *s)
static av_cold int decode_end(AVCodecContext *avctx)
{
HYuvContext *s = avctx->priv_data;
HYuvDecContext *s = avctx->priv_data;
int i;
ff_huffyuv_common_end(s);
ff_huffyuv_common_end(s->temp, s->temp16);
av_freep(&s->bitstream_buffer);
for (i = 0; i < 8; i++)
@ -293,7 +331,7 @@ static av_cold int decode_end(AVCodecContext *avctx)
static av_cold int decode_init(AVCodecContext *avctx)
{
HYuvContext *s = avctx->priv_data;
HYuvDecContext *s = avctx->priv_data;
int ret;
ret = av_image_check_size(avctx->width, avctx->height, 0, avctx);
@ -559,7 +597,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
return AVERROR_INVALIDDATA;
}
if ((ret = ff_huffyuv_alloc_temp(s, avctx->width)) < 0)
if ((ret = ff_huffyuv_alloc_temp(s->temp, s->temp16, avctx->width)) < 0)
return ret;
return 0;
@ -618,7 +656,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
GET_VLC_DUAL(dst0, dst1, re, &s->gb, s->vlc[4+plane1].table, \
s->vlc[0].table, s->vlc[plane1].table, VLC_BITS, 3, OP8bits)
static void decode_422_bitstream(HYuvContext *s, int count)
static void decode_422_bitstream(HYuvDecContext *s, int count)
{
int i, icount;
OPEN_READER(re, &s->gb);
@ -662,7 +700,7 @@ static void decode_422_bitstream(HYuvContext *s, int count)
dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;\
dst1 += get_bits(&s->gb, 2);\
}
static void decode_plane_bitstream(HYuvContext *s, int width, int plane)
static void decode_plane_bitstream(HYuvDecContext *s, int width, int plane)
{
int i, count = width/2;
@ -723,7 +761,7 @@ static void decode_plane_bitstream(HYuvContext *s, int width, int plane)
}
}
static void decode_gray_bitstream(HYuvContext *s, int count)
static void decode_gray_bitstream(HYuvDecContext *s, int count)
{
int i;
OPEN_READER(re, &s->gb);
@ -741,7 +779,7 @@ static void decode_gray_bitstream(HYuvContext *s, int count)
CLOSE_READER(re, &s->gb);
}
static av_always_inline void decode_bgr_1(HYuvContext *s, int count,
static av_always_inline void decode_bgr_1(HYuvDecContext *s, int count,
int decorrelate, int alpha)
{
int i;
@ -799,7 +837,7 @@ static av_always_inline void decode_bgr_1(HYuvContext *s, int count,
CLOSE_READER(re, &s->gb);
}
static void decode_bgr_bitstream(HYuvContext *s, int count)
static void decode_bgr_bitstream(HYuvDecContext *s, int count)
{
if (s->decorrelate) {
if (s->bitstream_bpp == 24)
@ -814,7 +852,7 @@ static void decode_bgr_bitstream(HYuvContext *s, int count)
}
}
static void draw_slice(HYuvContext *s, AVCodecContext *avctx, AVFrame *frame, int y)
static void draw_slice(HYuvDecContext *s, AVCodecContext *avctx, AVFrame *frame, int y)
{
int h, cy, i;
int offset[AV_NUM_DATA_POINTERS];
@ -842,7 +880,7 @@ static void draw_slice(HYuvContext *s, AVCodecContext *avctx, AVFrame *frame, in
s->last_slice_end = y + h;
}
static int left_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, int w, int acc)
static int left_prediction(HYuvDecContext *s, uint8_t *dst, const uint8_t *src, int w, int acc)
{
if (s->bps <= 8) {
return s->llviddsp.add_left_pred(dst, src, w, acc);
@ -851,7 +889,7 @@ static int left_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, int
}
}
static void add_bytes(HYuvContext *s, uint8_t *dst, uint8_t *src, int w)
static void add_bytes(HYuvDecContext *s, uint8_t *dst, uint8_t *src, int w)
{
if (s->bps <= 8) {
s->llviddsp.add_bytes(dst, src, w);
@ -860,7 +898,7 @@ static void add_bytes(HYuvContext *s, uint8_t *dst, uint8_t *src, int w)
}
}
static void add_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src, const uint8_t *diff, int w, int *left, int *left_top)
static void add_median_prediction(HYuvDecContext *s, uint8_t *dst, const uint8_t *src, const uint8_t *diff, int w, int *left, int *left_top)
{
if (s->bps <= 8) {
s->llviddsp.add_median_pred(dst, src, diff, w, left, left_top);
@ -872,7 +910,7 @@ static void add_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *s
static int decode_slice(AVCodecContext *avctx, AVFrame *p, int height,
int buf_size, int y_offset, int table_size)
{
HYuvContext *s = avctx->priv_data;
HYuvDecContext *s = avctx->priv_data;
int fake_ystride, fake_ustride, fake_vstride;
const int width = avctx->width;
const int width2 = avctx->width >> 1;
@ -1185,7 +1223,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p,
{
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
HYuvContext *s = avctx->priv_data;
HYuvDecContext *s = avctx->priv_data;
const int width = avctx->width;
const int height = avctx->height;
int slice, table_size = 0, ret, nb_slices;
@ -1268,7 +1306,7 @@ const FFCodec ff_huffyuv_decoder = {
CODEC_LONG_NAME("Huffyuv / HuffYUV"),
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_HUFFYUV,
.priv_data_size = sizeof(HYuvContext),
.priv_data_size = sizeof(HYuvDecContext),
.init = decode_init,
.close = decode_end,
FF_CODEC_DECODE_CB(decode_frame),
@ -1283,7 +1321,7 @@ const FFCodec ff_ffvhuff_decoder = {
CODEC_LONG_NAME("Huffyuv FFmpeg variant"),
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_FFVHUFF,
.priv_data_size = sizeof(HYuvContext),
.priv_data_size = sizeof(HYuvDecContext),
.init = decode_init,
.close = decode_end,
FF_CODEC_DECODE_CB(decode_frame),
@ -1299,7 +1337,7 @@ const FFCodec ff_hymt_decoder = {
CODEC_LONG_NAME("HuffYUV MT"),
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_HYMT,
.priv_data_size = sizeof(HYuvContext),
.priv_data_size = sizeof(HYuvDecContext),
.init = decode_init,
.close = decode_end,
FF_CODEC_DECODE_CB(decode_frame),

View File

@ -21,6 +21,7 @@
#include "config.h"
#include "libavutil/attributes.h"
#include "mathops.h"
#include "huffyuv.h"
#include "huffyuvdsp.h"
// 0x00010001 or 0x0001000100010001 or whatever, depending on the cpu's native arithmetic size

View File

@ -21,19 +21,6 @@
#include <stdint.h>
#include "libavutil/pixfmt.h"
#include "config.h"
#if HAVE_BIGENDIAN
#define B 3
#define G 2
#define R 1
#define A 0
#else
#define B 0
#define G 1
#define R 2
#define A 3
#endif
typedef struct HuffYUVDSPContext {
void (*add_int16)(uint16_t *dst/*align 16*/, const uint16_t *src/*align 16*/,

View File

@ -31,6 +31,7 @@
#include "config_components.h"
#include "avcodec.h"
#include "bswapdsp.h"
#include "codec_internal.h"
#include "encode.h"
#include "huffyuv.h"
@ -41,7 +42,39 @@
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
static inline void diff_bytes(HYuvContext *s, uint8_t *dst,
typedef struct HYuvEncContext {
AVClass *class;
AVCodecContext *avctx;
PutBitContext pb;
Predictor predictor;
int interlaced;
int decorrelate;
int bitstream_bpp;
int version;
int bps;
int n; // 1<<bps
int vlc_n; // number of vlc codes (FFMIN(1<<bps, MAX_VLC_N))
int alpha;
int chroma;
int yuv;
int chroma_h_shift;
int chroma_v_shift;
int flags;
int context;
int picture_number;
uint8_t *temp[3];
uint16_t *temp16[3]; ///< identical to temp but 16bit type
uint64_t stats[4][MAX_VLC_N];
uint8_t len[4][MAX_VLC_N];
uint32_t bits[4][MAX_VLC_N];
BswapDSPContext bdsp;
HuffYUVEncDSPContext hencdsp;
LLVidEncDSPContext llvidencdsp;
int non_determ; // non-deterministic, multi-threaded encoder allowed
} HYuvEncContext;
static inline void diff_bytes(HYuvEncContext *s, uint8_t *dst,
const uint8_t *src0, const uint8_t *src1, int w)
{
if (s->bps <= 8) {
@ -51,7 +84,7 @@ static inline void diff_bytes(HYuvContext *s, uint8_t *dst,
}
}
static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst,
static inline int sub_left_prediction(HYuvEncContext *s, uint8_t *dst,
const uint8_t *src, int w, int left)
{
int i;
@ -82,7 +115,7 @@ static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst,
}
}
static inline void sub_left_prediction_bgr32(HYuvContext *s, uint8_t *dst,
static inline void sub_left_prediction_bgr32(HYuvEncContext *s, uint8_t *dst,
const uint8_t *src, int w,
int *red, int *green, int *blue,
int *alpha)
@ -118,7 +151,7 @@ static inline void sub_left_prediction_bgr32(HYuvContext *s, uint8_t *dst,
*alpha = src[(w - 1) * 4 + A];
}
static inline void sub_left_prediction_rgb24(HYuvContext *s, uint8_t *dst,
static inline void sub_left_prediction_rgb24(HYuvEncContext *s, uint8_t *dst,
const uint8_t *src, int w,
int *red, int *green, int *blue)
{
@ -146,7 +179,9 @@ static inline void sub_left_prediction_rgb24(HYuvContext *s, uint8_t *dst,
*blue = src[(w - 1) * 3 + 2];
}
static void sub_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *src1, const uint8_t *src2, int w, int *left, int *left_top)
static void sub_median_prediction(HYuvEncContext *s, uint8_t *dst,
const uint8_t *src1, const uint8_t *src2,
int w, int *left, int *left_top)
{
if (s->bps <= 8) {
s->llvidencdsp.sub_median_pred(dst, src1, src2, w , left, left_top);
@ -155,7 +190,7 @@ static void sub_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *s
}
}
static int store_table(HYuvContext *s, const uint8_t *len, uint8_t *buf)
static int store_table(HYuvEncContext *s, const uint8_t *len, uint8_t *buf)
{
int i;
int index = 0;
@ -180,7 +215,7 @@ static int store_table(HYuvContext *s, const uint8_t *len, uint8_t *buf)
return index;
}
static int store_huffman_tables(HYuvContext *s, uint8_t *buf)
static int store_huffman_tables(HYuvEncContext *s, uint8_t *buf)
{
int i, ret;
int size = 0;
@ -204,7 +239,7 @@ static int store_huffman_tables(HYuvContext *s, uint8_t *buf)
static av_cold int encode_init(AVCodecContext *avctx)
{
HYuvContext *s = avctx->priv_data;
HYuvEncContext *s = avctx->priv_data;
int i, j;
int ret;
const AVPixFmtDescriptor *desc;
@ -393,7 +428,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
s->stats[i][j]= 0;
}
ret = ff_huffyuv_alloc_temp(s, avctx->width);
ret = ff_huffyuv_alloc_temp(s->temp, s->temp16, avctx->width);
if (ret < 0)
return ret;
@ -401,7 +436,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
return 0;
}
static int encode_422_bitstream(HYuvContext *s, int offset, int count)
static int encode_422_bitstream(HYuvEncContext *s, int offset, int count)
{
int i;
const uint8_t *y = s->temp[0] + offset;
@ -456,7 +491,7 @@ static int encode_422_bitstream(HYuvContext *s, int offset, int count)
return 0;
}
static int encode_plane_bitstream(HYuvContext *s, int width, int plane)
static int encode_plane_bitstream(HYuvEncContext *s, int width, int plane)
{
int i, count = width/2;
@ -618,7 +653,7 @@ static int encode_plane_bitstream(HYuvContext *s, int width, int plane)
return 0;
}
static int encode_gray_bitstream(HYuvContext *s, int count)
static int encode_gray_bitstream(HYuvEncContext *s, int count)
{
int i;
@ -663,7 +698,7 @@ static int encode_gray_bitstream(HYuvContext *s, int count)
return 0;
}
static inline int encode_bgra_bitstream(HYuvContext *s, int count, int planes)
static inline int encode_bgra_bitstream(HYuvEncContext *s, int count, int planes)
{
int i;
@ -716,7 +751,7 @@ static inline int encode_bgra_bitstream(HYuvContext *s, int count, int planes)
static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
const AVFrame *pict, int *got_packet)
{
HYuvContext *s = avctx->priv_data;
HYuvEncContext *s = avctx->priv_data;
const int width = avctx->width;
const int width2 = avctx->width >> 1;
const int height = avctx->height;
@ -996,16 +1031,16 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
static av_cold int encode_end(AVCodecContext *avctx)
{
HYuvContext *s = avctx->priv_data;
HYuvEncContext *s = avctx->priv_data;
ff_huffyuv_common_end(s);
ff_huffyuv_common_end(s->temp, s->temp16);
av_freep(&avctx->stats_out);
return 0;
}
#define OFFSET(x) offsetof(HYuvContext, x)
#define OFFSET(x) offsetof(HYuvEncContext, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
#define COMMON_OPTIONS \
@ -1048,7 +1083,7 @@ const FFCodec ff_huffyuv_encoder = {
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_HUFFYUV,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
.priv_data_size = sizeof(HYuvContext),
.priv_data_size = sizeof(HYuvEncContext),
.init = encode_init,
FF_CODEC_ENCODE_CB(encode_frame),
.close = encode_end,
@ -1067,7 +1102,7 @@ const FFCodec ff_ffvhuff_encoder = {
.p.type = AVMEDIA_TYPE_VIDEO,
.p.id = AV_CODEC_ID_FFVHUFF,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
.priv_data_size = sizeof(HYuvContext),
.priv_data_size = sizeof(HYuvEncContext),
.init = encode_init,
FF_CODEC_ENCODE_CB(encode_frame),
.close = encode_end,