From b53aab1a5819abe7c65b5f645e09559bb42db793 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 13 Jan 2014 01:14:05 +0100 Subject: 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 --- libavcodec/huffyuvenc.c | 124 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 95 insertions(+), 29 deletions(-) (limited to 'libavcodec/huffyuvenc.c') 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 }, -- cgit v1.2.3