aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec/huffyuvenc.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-01-13 01:14:05 +0100
committerMichael Niedermayer <michaelni@gmx.at>2014-01-16 16:59:15 +0100
commitb53aab1a5819abe7c65b5f645e09559bb42db793 (patch)
treeef402d37750932538e0b090cc3d0b964a51cbfc8 /libavcodec/huffyuvenc.c
parent6c004e8aada00d96f5c38e50c9770efb1eaaaa59 (diff)
downloadffmpeg-b53aab1a5819abe7c65b5f645e09559bb42db793.tar.gz
libavcodec/huffyuv: >8 bit support
This adds only yuv420p10, others are trivial to add after this commit and will be added in a subsequent commit. Currently the implementation is not optimized, optimizations will be added later Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/huffyuvenc.c')
-rw-r--r--libavcodec/huffyuvenc.c124
1 files changed, 95 insertions, 29 deletions
diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c
index bd633a2fed..55e0b1e398 100644
--- a/libavcodec/huffyuvenc.c
+++ b/libavcodec/huffyuvenc.c
@@ -19,6 +19,8 @@
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * yuva, gray, 4:4:4, 4:1:1, 4:1:0 and >8 bit per sample support sponsored by NOA
*/
/**
@@ -33,25 +35,58 @@
#include "put_bits.h"
#include "libavutil/pixdesc.h"
+static inline void diff_bytes(HYuvContext *s, uint8_t *dst,
+ const uint8_t *src0, const uint8_t *src1, int w)
+{
+ int i;
+ if (s->bps <= 8) {
+ s->dsp.diff_bytes(dst, src0, src1, w);
+ } else {
+ const uint16_t *src016 = (const uint16_t *)src0;
+ const uint16_t *src116 = (const uint16_t *)src1;
+ uint16_t *dst16 = ( uint16_t *)dst;
+
+ for (i = 0; i < w; i++) {
+ dst16[i] = src016[i] - src116[i];
+ }
+
+ //FIXME optimize
+ }
+}
+
static inline int sub_left_prediction(HYuvContext *s, uint8_t *dst,
const uint8_t *src, int w, int left)
{
int i;
- if (w < 32) {
- for (i = 0; i < w; i++) {
- const int temp = src[i];
- dst[i] = temp - left;
- left = temp;
+ if (s->bps <= 8) {
+ if (w < 32) {
+ for (i = 0; i < w; i++) {
+ const int temp = src[i];
+ dst[i] = temp - left;
+ left = temp;
+ }
+ return left;
+ } else {
+ for (i = 0; i < 16; i++) {
+ const int temp = src[i];
+ dst[i] = temp - left;
+ left = temp;
+ }
+ s->dsp.diff_bytes(dst + 16, src + 16, src + 15, w - 16);
+ return src[w-1];
}
- return left;
} else {
- for (i = 0; i < 16; i++) {
- const int temp = src[i];
- dst[i] = temp - left;
+ const uint16_t *src16 = (const uint16_t *)src;
+ uint16_t *dst16 = ( uint16_t *)dst;
+
+ for (i = 0; i < w; i++) {
+ const int temp = src16[i];
+ dst16[i] = temp - left;
left = temp;
}
- s->dsp.diff_bytes(dst + 16, src + 16, src + 15, w - 16);
- return src[w-1];
+ return left;
+
+ //FIXME optimize
}
}
@@ -122,15 +157,16 @@ static int store_table(HYuvContext *s, const uint8_t *len, uint8_t *buf)
{
int i;
int index = 0;
+ int n = s->n;
- for (i = 0; i < 256;) {
+ for (i = 0; i < n;) {
int val = len[i];
int repeat = 0;
- for (; i < 256 && len[i] == val && repeat < 255; i++)
+ for (; i < n && len[i] == val && repeat < 255; i++)
repeat++;
- av_assert0(val < 32 && val >0 && repeat<256 && repeat>0);
+ av_assert0(val < 32 && val >0 && repeat < 256 && repeat>0);
if (repeat > 7) {
buf[index++] = val;
buf[index++] = repeat;
@@ -152,10 +188,10 @@ static int store_huffman_tables(HYuvContext *s, uint8_t *buf)
count = 1 + s->alpha + 2*s->chroma;
for (i = 0; i < count; i++) {
- if ((ret = ff_huff_gen_len_table(s->len[i], s->stats[i], 256)) < 0)
+ if ((ret = ff_huff_gen_len_table(s->len[i], s->stats[i], s->n)) < 0)
return ret;
- if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i]) < 0) {
+ if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->n) < 0) {
return -1;
}
@@ -173,8 +209,8 @@ static av_cold int encode_init(AVCodecContext *avctx)
ff_huffyuv_common_init(avctx);
- avctx->extradata = av_mallocz(1024*30); // 256*3+4 == 772
- avctx->stats_out = av_mallocz(1024*30); // 21*256*3(%llu ) + 3(\n) + 1(0) = 16132
+ avctx->extradata = av_mallocz(3*MAX_N + 4);
+ avctx->stats_out = av_mallocz(21*MAX_N*3 + 4); // 21*256*3(%llu ) + 3(\n) + 1(0) = 16132
if (!avctx->extradata || !avctx->stats_out) {
av_freep(&avctx->stats_out);
return AVERROR(ENOMEM);
@@ -216,6 +252,7 @@ static av_cold int encode_init(AVCodecContext *avctx)
case AV_PIX_FMT_YUVA422P:
case AV_PIX_FMT_GBRAP:
case AV_PIX_FMT_GRAY8A:
+ case AV_PIX_FMT_YUV420P10:
s->version = 3;
break;
case AV_PIX_FMT_RGB32:
@@ -301,14 +338,14 @@ static av_cold int encode_init(AVCodecContext *avctx)
char *p = avctx->stats_in;
for (i = 0; i < 4; i++)
- for (j = 0; j < 256; j++)
+ for (j = 0; j < s->n; j++)
s->stats[i][j] = 1;
for (;;) {
for (i = 0; i < 4; i++) {
char *next;
- for (j = 0; j < 256; j++) {
+ for (j = 0; j < s->n; j++) {
s->stats[i][j] += strtol(p, &next, 0);
if (next == p) return -1;
p = next;
@@ -318,8 +355,8 @@ static av_cold int encode_init(AVCodecContext *avctx)
}
} else {
for (i = 0; i < 4; i++)
- for (j = 0; j < 256; j++) {
- int d = FFMIN(j, 256 - j);
+ for (j = 0; j < s->n; j++) {
+ int d = FFMIN(j, s->n - j);
s->stats[i][j] = 100000000 / (d + 1);
}
@@ -333,14 +370,14 @@ static av_cold int encode_init(AVCodecContext *avctx)
if (s->context) {
for (i = 0; i < 4; i++) {
int pels = s->width * s->height / (i ? 40 : 10);
- for (j = 0; j < 256; j++) {
- int d = FFMIN(j, 256 - j);
+ for (j = 0; j < s->n; j++) {
+ int d = FFMIN(j, s->n - j);
s->stats[i][j] = pels/(d + 1);
}
}
} else {
for (i = 0; i < 4; i++)
- for (j = 0; j < 256; j++)
+ for (j = 0; j < s->n; j++)
s->stats[i][j]= 0;
}
@@ -412,7 +449,7 @@ static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
{
int i;
- if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < 4 * count) {
+ 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;
}
@@ -420,6 +457,9 @@ static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
#define LOAD2\
int y0 = s->temp[0][2 * i];\
int y1 = s->temp[0][2 * i + 1];
+#define LOAD2_16\
+ int y0 = s->temp16[0][2 * i] & mask;\
+ int y1 = s->temp16[0][2 * i + 1] & mask;
#define STAT2\
s->stats[plane][y0]++;\
s->stats[plane][y1]++;
@@ -429,6 +469,7 @@ static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
count /= 2;
+ if (s->bps <= 8) {
if (s->flags & CODEC_FLAG_PASS1) {
for (i = 0; i < count; i++) {
LOAD2;
@@ -450,6 +491,30 @@ static int encode_plane_bitstream(HYuvContext *s, int count, int plane)
WRITE2;
}
}
+ } else {
+ int mask = s->n - 1;
+ if (s->flags & CODEC_FLAG_PASS1) {
+ for (i = 0; i < count; i++) {
+ LOAD2_16;
+ STAT2;
+ }
+ }
+ if (s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)
+ return 0;
+
+ if (s->context) {
+ for (i = 0; i < count; i++) {
+ LOAD2_16;
+ STAT2;
+ WRITE2;
+ }
+ } else {
+ for (i = 0; i < count; i++) {
+ LOAD2_16;
+ WRITE2;
+ }
+ }
+ }
#undef LOAD2
#undef STAT2
#undef WRITE2
@@ -574,7 +639,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
return size;
for (i = 0; i < 4; i++)
- for (j = 0; j < 256; j++)
+ for (j = 0; j < s->n; j++)
s->stats[i][j] >>= 1;
}
@@ -784,7 +849,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
uint8_t *dst = p->data[plane] + p->linesize[plane] * y;
if (s->predictor == PLANE && s->interlaced < y) {
- s->dsp.diff_bytes(s->temp[1], dst, dst - fake_stride, w);
+ diff_bytes(s, s->temp[1], dst, dst - fake_stride, w);
left = sub_left_prediction(s, s->temp[0], s->temp[1], w , left);
} else {
@@ -810,7 +875,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
char *p = avctx->stats_out;
char *end = p + 1024*30;
for (i = 0; i < 4; i++) {
- for (j = 0; j < 256; j++) {
+ for (j = 0; j < s->n; j++) {
snprintf(p, end-p, "%"PRIu64" ", s->stats[i][j]);
p += strlen(p);
s->stats[i][j]= 0;
@@ -883,6 +948,7 @@ AVCodec ff_ffvhuff_encoder = {
AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
AV_PIX_FMT_GBRAP,
AV_PIX_FMT_GRAY8A,
+ AV_PIX_FMT_YUV420P10,
AV_PIX_FMT_RGB24,
AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE
},