Commit 2a293ec7 authored by Steinar H. Gunderson's avatar Steinar H. Gunderson Committed by Paul B Mahol

avcodec: add Newtek SpeedHQ decoder

This decoder can decode all existing SpeedHQ formats (SHQ0–5, 7, and 9),
including correct decoding of the alpha channel.

1080p is decoded in 142 fps on one core of my i7-4600U (2.1 GHz Haswell),
about evenly split between bitstream reader and IDCT. There is currently
no attempt at slice or frame threading, even though the format trivially
supports both.

NewTek very helpfully provided a full set of SHQ samples, as well as
source code for an SHQ2 encoder (not included) and assistance with
understanding some details of the format.
parent eaff1aa0
......@@ -13,6 +13,7 @@ version <next>:
- 24.0 floating point pcm decoder
- Apple Pixlet decoder
- QDMC audio decoder
- NewTek SpeedHQ decoder
version 3.2:
- libopenmpt demuxer
......
......@@ -521,6 +521,7 @@ OBJS-$(CONFIG_SOL_DPCM_DECODER) += dpcm.o
OBJS-$(CONFIG_SONIC_DECODER) += sonic.o
OBJS-$(CONFIG_SONIC_ENCODER) += sonic.o
OBJS-$(CONFIG_SONIC_LS_ENCODER) += sonic.o
OBJS-$(CONFIG_SPEEDHQ_DECODER) += speedhq.o simple_idct.o
OBJS-$(CONFIG_SP5X_DECODER) += sp5xdec.o
OBJS-$(CONFIG_SRT_DECODER) += srtdec.o ass.o htmlsubtitles.o
OBJS-$(CONFIG_SRT_ENCODER) += srtenc.o ass_split.o
......
......@@ -316,6 +316,7 @@ void avcodec_register_all(void)
REGISTER_DECODER(SMVJPEG, smvjpeg);
REGISTER_ENCDEC (SNOW, snow);
REGISTER_DECODER(SP5X, sp5x);
REGISTER_DECODER(SPEEDHQ, speedhq);
REGISTER_ENCDEC (SUNRAST, sunrast);
REGISTER_ENCDEC (SVQ1, svq1);
REGISTER_DECODER(SVQ3, svq3);
......
......@@ -413,6 +413,7 @@ enum AVCodecID {
AV_CODEC_ID_YLC,
AV_CODEC_ID_PSD,
AV_CODEC_ID_PIXLET,
AV_CODEC_ID_SPEEDHQ,
/* various PCM "codecs" */
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
......
......@@ -1290,6 +1290,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
.long_name = NULL_IF_CONFIG_SMALL("Screenpresso"),
.props = AV_CODEC_PROP_LOSSLESS,
},
{
.id = AV_CODEC_ID_SPEEDHQ,
.type = AVMEDIA_TYPE_VIDEO,
.name = "speedhq",
.long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"),
.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
},
{
.id = AV_CODEC_ID_WRAPPED_AVFRAME,
.type = AVMEDIA_TYPE_VIDEO,
......
......@@ -229,6 +229,20 @@ static inline int get_xbits(GetBitContext *s, int n)
return (NEG_USR32(sign ^ cache, n) ^ sign) - sign;
}
static inline int get_xbits_le(GetBitContext *s, int n)
{
register int sign;
register int32_t cache;
OPEN_READER(re, s);
av_assert2(n>0 && n<=25);
UPDATE_CACHE_LE(re, s);
cache = GET_CACHE(re, s);
sign = sign_extend(~cache, n) >> 31;
LAST_SKIP_BITS(re, s, n);
CLOSE_READER(re, s);
return (zero_extend(sign ^ cache, n) ^ sign) - sign;
}
static inline int get_sbits(GetBitContext *s, int n)
{
register int tmp;
......
......@@ -67,20 +67,13 @@ static const uint8_t table_mb_btype[11][2] = {
{ 2, 5 }, // 0x1E MB_QUANT|MB_FOR|MB_BACK|MB_PAT
};
#define INIT_2D_VLC_RL(rl, static_size)\
{\
static RL_VLC_ELEM rl_vlc_table[static_size];\
rl.rl_vlc[0] = rl_vlc_table;\
init_2d_vlc_rl(&rl, static_size);\
}
static av_cold void init_2d_vlc_rl(RLTable *rl, unsigned static_size)
av_cold void ff_init_2d_vlc_rl(RLTable *rl, unsigned static_size, int flags)
{
int i;
VLC_TYPE table[680][2] = {{0}};
VLC vlc = { .table = table, .table_allocated = static_size };
av_assert0(static_size <= FF_ARRAY_ELEMS(table));
init_vlc(&vlc, TEX_VLC_BITS, rl->n + 2, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC);
init_vlc(&vlc, TEX_VLC_BITS, rl->n + 2, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC | flags);
for (i = 0; i < vlc.table_size; i++) {
int code = vlc.table[i][0];
......@@ -173,8 +166,8 @@ av_cold void ff_mpeg12_init_vlcs(void)
ff_rl_init(&ff_rl_mpeg1, ff_mpeg12_static_rl_table_store[0]);
ff_rl_init(&ff_rl_mpeg2, ff_mpeg12_static_rl_table_store[1]);
INIT_2D_VLC_RL(ff_rl_mpeg1, 680);
INIT_2D_VLC_RL(ff_rl_mpeg2, 674);
INIT_2D_VLC_RL(ff_rl_mpeg1, 680, 0);
INIT_2D_VLC_RL(ff_rl_mpeg2, 674, 0);
}
}
......
......@@ -29,6 +29,15 @@ extern uint8_t ff_mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3];
void ff_mpeg12_common_init(MpegEncContext *s);
#define INIT_2D_VLC_RL(rl, static_size, flags)\
{\
static RL_VLC_ELEM rl_vlc_table[static_size];\
rl.rl_vlc[0] = rl_vlc_table;\
ff_init_2d_vlc_rl(&rl, static_size, flags);\
}
void ff_init_2d_vlc_rl(RLTable *rl, unsigned static_size, int flags);
static inline int decode_dc(GetBitContext *gb, int component)
{
int code, diff;
......
This diff is collapsed.
......@@ -28,8 +28,8 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 57
#define LIBAVCODEC_VERSION_MINOR 71
#define LIBAVCODEC_VERSION_MICRO 101
#define LIBAVCODEC_VERSION_MINOR 72
#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
......
......@@ -62,4 +62,13 @@ void ff_free_vlc(VLC *vlc);
init_vlc(vlc, bits, a, b, c, d, e, f, g, INIT_VLC_USE_NEW_STATIC); \
} while (0)
#define INIT_LE_VLC_STATIC(vlc, bits, a, b, c, d, e, f, g, static_size) \
do { \
static VLC_TYPE table[static_size][2]; \
(vlc)->table = table; \
(vlc)->table_allocated = static_size; \
init_vlc(vlc, bits, a, b, c, d, e, f, g, \
INIT_VLC_USE_NEW_STATIC | INIT_VLC_LE); \
} while (0)
#endif /* AVCODEC_VLC_H */
......@@ -440,6 +440,14 @@ const AVCodecTag ff_codec_bmp_tags[] = {
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'G', '0') },
{ AV_CODEC_ID_MAGICYUV, MKTAG('M', '0', 'Y', '2') },
{ AV_CODEC_ID_YLC, MKTAG('Y', 'L', 'C', '0') },
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '0') },
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '1') },
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '2') },
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '3') },
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '4') },
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '5') },
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '7') },
{ AV_CODEC_ID_SPEEDHQ, MKTAG('S', 'H', 'Q', '9') },
{ AV_CODEC_ID_NONE, 0 }
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment