X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmjpegenc_common.c;h=83a9e95766829f9b70ced1f667422c15e9c657ad;hb=f0ecbb13cf1cf706a1350dad657219dc7b3c131e;hp=7a6fe7468fec98db3af09a39f599e47ae341edb8;hpb=d8ffdefbdce16948c9b3c84df62171a7d58c8253;p=ffmpeg diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 7a6fe7468fe..83a9e957668 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -33,8 +33,35 @@ #include "put_bits.h" #include "mjpegenc.h" #include "mjpegenc_common.h" +#include "mjpegenc_huffman.h" #include "mjpeg.h" +av_cold void ff_init_uni_ac_vlc(const uint8_t huff_size_ac[256], uint8_t *uni_ac_vlc_len) +{ + int i; + + for (i = 0; i < 128; i++) { + int level = i - 64; + int run; + if (!level) + continue; + for (run = 0; run < 64; run++) { + int len, code, nbits; + int alevel = FFABS(level); + + len = (run >> 4) * huff_size_ac[0xf0]; + + nbits= av_log2_16bit(alevel) + 1; + code = ((15&run) << 4) | nbits; + + len += huff_size_ac[code] + nbits; + + uni_ac_vlc_len[UNI_AC_ENC_INDEX(run, i)] = len; + // We ignore EOB as its just a constant which does not change generally + } + } +} + /* table_class: 0 = DC coef, 1 = AC coefs */ static int put_huffman_table(PutBitContext *p, int table_class, int table_id, const uint8_t *bits_table, const uint8_t *value_table) @@ -104,15 +131,30 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, ptr = put_bits_ptr(p); put_bits(p, 16, 0); /* patched later */ size = 2; - size += put_huffman_table(p, 0, 0, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); - size += put_huffman_table(p, 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); - - size += put_huffman_table(p, 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); - size += put_huffman_table(p, 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + + // Only MJPEG can have a variable Huffman variable. All other + // formats use the default Huffman table. + if (s->out_format == FMT_MJPEG && s->huffman == HUFFMAN_TABLE_OPTIMAL) { + size += put_huffman_table(p, 0, 0, s->mjpeg_ctx->bits_dc_luminance, + s->mjpeg_ctx->val_dc_luminance); + size += put_huffman_table(p, 0, 1, s->mjpeg_ctx->bits_dc_chrominance, + s->mjpeg_ctx->val_dc_chrominance); + + size += put_huffman_table(p, 1, 0, s->mjpeg_ctx->bits_ac_luminance, + s->mjpeg_ctx->val_ac_luminance); + size += put_huffman_table(p, 1, 1, s->mjpeg_ctx->bits_ac_chrominance, + s->mjpeg_ctx->val_ac_chrominance); + } else { + size += put_huffman_table(p, 0, 0, avpriv_mjpeg_bits_dc_luminance, + avpriv_mjpeg_val_dc); + size += put_huffman_table(p, 0, 1, avpriv_mjpeg_bits_dc_chrominance, + avpriv_mjpeg_val_dc); + + size += put_huffman_table(p, 1, 0, avpriv_mjpeg_bits_ac_luminance, + avpriv_mjpeg_val_ac_luminance); + size += put_huffman_table(p, 1, 1, avpriv_mjpeg_bits_ac_chrominance, + avpriv_mjpeg_val_ac_chrominance); + } AV_WB16(ptr, size); } @@ -372,14 +414,106 @@ void ff_mjpeg_escape_FF(PutBitContext *pb, int start) } } +/** + * Builds all 4 optimal Huffman tables. + * + * Uses the data stored in the JPEG buffer to compute the tables. + * Stores the Huffman tables in the bits_* and val_* arrays in the MJpegContext. + * + * @param m MJpegContext containing the JPEG buffer. + */ +static void ff_mjpeg_build_optimal_huffman(MJpegContext *m) +{ + int i, table_id, code; + + MJpegEncHuffmanContext dc_luminance_ctx; + MJpegEncHuffmanContext dc_chrominance_ctx; + MJpegEncHuffmanContext ac_luminance_ctx; + MJpegEncHuffmanContext ac_chrominance_ctx; + MJpegEncHuffmanContext *ctx[4] = {&dc_luminance_ctx, + &dc_chrominance_ctx, + &ac_luminance_ctx, + &ac_chrominance_ctx}; + for (i = 0; i < 4; i++) { + ff_mjpeg_encode_huffman_init(ctx[i]); + } + for (i = 0; i < m->huff_ncode; i++) { + table_id = m->huff_buffer[i].table_id; + code = m->huff_buffer[i].code; + + ff_mjpeg_encode_huffman_increment(ctx[table_id], code); + } + + ff_mjpeg_encode_huffman_close(&dc_luminance_ctx, + m->bits_dc_luminance, + m->val_dc_luminance, 12); + ff_mjpeg_encode_huffman_close(&dc_chrominance_ctx, + m->bits_dc_chrominance, + m->val_dc_chrominance, 12); + ff_mjpeg_encode_huffman_close(&ac_luminance_ctx, + m->bits_ac_luminance, + m->val_ac_luminance, 256); + ff_mjpeg_encode_huffman_close(&ac_chrominance_ctx, + m->bits_ac_chrominance, + m->val_ac_chrominance, 256); + + ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, + m->huff_code_dc_luminance, + m->bits_dc_luminance, + m->val_dc_luminance); + ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, + m->huff_code_dc_chrominance, + m->bits_dc_chrominance, + m->val_dc_chrominance); + ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, + m->huff_code_ac_luminance, + m->bits_ac_luminance, + m->val_ac_luminance); + ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, + m->huff_code_ac_chrominance, + m->bits_ac_chrominance, + m->val_ac_chrominance); +} + +/** + * Writes the complete JPEG frame when optimal huffman tables are enabled, + * otherwise writes the stuffing. + * + * Header + values + stuffing. + * + * @param s The MpegEncContext. + * @return int Error code, 0 if successful. + */ int ff_mjpeg_encode_stuffing(MpegEncContext *s) { int i; PutBitContext *pbc = &s->pb; int mb_y = s->mb_y - !s->mb_x; + int ret; + MJpegContext *m; + + m = s->mjpeg_ctx; + + if (s->huffman == HUFFMAN_TABLE_OPTIMAL) { + ff_mjpeg_build_optimal_huffman(m); + + // Replace the VLCs with the optimal ones. + // The default ones may be used for trellis during quantization. + ff_init_uni_ac_vlc(m->huff_size_ac_luminance, m->uni_ac_vlc_len); + ff_init_uni_ac_vlc(m->huff_size_ac_chrominance, m->uni_chroma_ac_vlc_len); + s->intra_ac_vlc_length = + s->intra_ac_vlc_last_length = m->uni_ac_vlc_len; + s->intra_chroma_ac_vlc_length = + s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len; + + ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, + s->pred, s->intra_matrix, s->chroma_intra_matrix); + ff_mjpeg_encode_picture_frame(s); + } + + ret = ff_mpv_reallocate_putbitbuffer(s, put_bits_count(&s->pb) / 8 + 100, + put_bits_count(&s->pb) / 4 + 1000); - int ret = ff_mpv_reallocate_putbitbuffer(s, put_bits_count(&s->pb) / 8 + 100, - put_bits_count(&s->pb) / 4 + 1000); if (ret < 0) { av_log(s->avctx, AV_LOG_ERROR, "Buffer reallocation failed\n"); goto fail;