#include "huffyuvencdsp.h"
#include "internal.h"
#include "put_bits.h"
+#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
static inline void diff_bytes(HYuvContext *s, uint8_t *dst,
return 0;
}
-static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
+static int encode_plane_bitstream(HYuvContext *s, int width, int plane)
{
- int i;
+ int i, count = width/2;
if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < count * s->bps / 2) {
av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return -1;
}
+#define LOADEND\
+ int y0 = s->temp[0][width-1];
+#define LOADEND_14\
+ int y0 = s->temp16[0][width-1] & mask;
+#define LOADEND_16\
+ int y0 = s->temp16[0][width-1];
+#define STATEND\
+ s->stats[plane][y0]++;
+#define STATEND_16\
+ s->stats[plane][y0>>2]++;
+#define WRITEEND\
+ put_bits(&s->pb, s->len[plane][y0], s->bits[plane][y0]);
+#define WRITEEND_16\
+ put_bits(&s->pb, s->len[plane][y0>>2], s->bits[plane][y0>>2]);\
+ put_bits(&s->pb, 2, y0&3);
+
#define LOAD2\
int y0 = s->temp[0][2 * i];\
int y1 = s->temp[0][2 * i + 1];
put_bits(&s->pb, s->len[plane][y1>>2], s->bits[plane][y1>>2]);\
put_bits(&s->pb, 2, y1&3);
- count /= 2;
-
if (s->bps <= 8) {
if (s->flags & CODEC_FLAG_PASS1) {
for (i = 0; i < count; i++) {
LOAD2;
STAT2;
}
+ if (width&1) {
+ LOADEND;
+ STATEND;
+ }
}
if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)
return 0;
STAT2;
WRITE2;
}
+ if (width&1) {
+ LOADEND;
+ STATEND;
+ WRITEEND;
+ }
} else {
for (i = 0; i < count; i++) {
LOAD2;
WRITE2;
}
+ if (width&1) {
+ LOADEND;
+ WRITEEND;
+ }
}
} else if (s->bps <= 14) {
int mask = s->n - 1;
LOAD2_14;
STAT2;
}
+ if (width&1) {
+ LOADEND_14;
+ STATEND;
+ }
}
if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)
return 0;
STAT2;
WRITE2;
}
+ if (width&1) {
+ LOADEND_14;
+ STATEND;
+ WRITEEND;
+ }
} else {
for (i = 0; i < count; i++) {
LOAD2_14;
WRITE2;
}
+ if (width&1) {
+ LOADEND_14;
+ WRITEEND;
+ }
}
} else {
if (s->flags & CODEC_FLAG_PASS1) {
LOAD2_16;
STAT2_16;
}
+ if (width&1) {
+ LOADEND_16;
+ STATEND_16;
+ }
}
if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)
return 0;
STAT2_16;
WRITE2_16;
}
+ if (width&1) {
+ LOADEND_16;
+ STATEND_16;
+ WRITEEND_16;
+ }
} else {
for (i = 0; i < count; i++) {
LOAD2_16;
WRITE2_16;
}
+ if (width&1) {
+ LOADEND_16;
+ WRITEEND_16;
+ }
}
}
#undef LOAD2
return 0;
}
+static const AVOption options[] = {
+ { "non_deterministic", "Allow multithreading for e.g. context=1 at the expense of determinism",
+ offsetof(HYuvContext, non_determ), AV_OPT_TYPE_INT, { .i64 = 1 },
+ 0, 1, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM },
+ { NULL },
+};
+
+static const AVClass normal_class = {
+ .class_name = "huffyuv",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static const AVClass ff_class = {
+ .class_name = "ffvhuff",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVCodec ff_huffyuv_encoder = {
.name = "huffyuv",
.long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"),
.encode2 = encode_frame,
.close = encode_end,
.capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
+ .priv_class = &normal_class,
.pix_fmts = (const enum AVPixelFormat[]){
AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24,
AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE
.encode2 = encode_frame,
.close = encode_end,
.capabilities = CODEC_CAP_FRAME_THREADS | CODEC_CAP_INTRA_ONLY,
+ .priv_class = &ff_class,
.pix_fmts = (const enum AVPixelFormat[]){
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV411P,
AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P,