You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	avcodec/ffv1: Store slices*planes with the minimum bits needed after remap
This also means that if a plane*slice has only 1 color nothing is stored after the remap table This also corrects the RCT offset to the exact value after remap not a fixed 65536 Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
		| @@ -219,6 +219,43 @@ void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1SliceContext *sc) | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ff_ffv1_compute_bits_per_plane(const FFV1Context *f, FFV1SliceContext *sc, int bits[4], int *offset, int mask[4], int bits_per_raw_sample) | ||||
| { | ||||
|     // to simplify we use the remap_count as the symbol range in each plane | ||||
|     if (!sc->remap) { | ||||
|         sc->remap_count[0] = | ||||
|         sc->remap_count[1] = | ||||
|         sc->remap_count[2] = | ||||
|         sc->remap_count[3] = 1 << (bits_per_raw_sample > 0 ? bits_per_raw_sample : 8); | ||||
|     } | ||||
|  | ||||
|     if (sc->remap) | ||||
|         av_assert0(bits_per_raw_sample > 8); //breaks with lbd, needs review if added | ||||
|  | ||||
|     //bits with no RCT | ||||
|     for (int p=0; p<3+f->transparency; p++) { | ||||
|         bits[p] = av_ceil_log2(sc->remap_count[p]); | ||||
|         if (mask) | ||||
|             mask[p] = (1<<bits[p]) - 1; | ||||
|     } | ||||
|  | ||||
|     //RCT | ||||
|     if (sc->slice_coding_mode == 0) { | ||||
|         *offset = sc->remap_count[0]; | ||||
|  | ||||
|         bits[0] = av_ceil_log2(FFMAX3(sc->remap_count[0], sc->remap_count[1], sc->remap_count[2])); | ||||
|         bits[1] = av_ceil_log2(sc->remap_count[0] + sc->remap_count[1]); | ||||
|         bits[2] = av_ceil_log2(sc->remap_count[0] + sc->remap_count[2]); | ||||
|  | ||||
|         //old version coded a bit more than needed | ||||
|         if (f->combined_version < 0x40008) { | ||||
|             bits[0]++; | ||||
|             if(f->transparency) | ||||
|                 bits[3]++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| int ff_ffv1_get_symbol(RangeCoder *c, uint8_t *state, int is_signed) | ||||
| { | ||||
|     return get_symbol_inline(c, state, is_signed); | ||||
|   | ||||
| @@ -106,6 +106,7 @@ typedef struct FFV1SliceContext { | ||||
|             uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2]; | ||||
|         }; | ||||
|     }; | ||||
|     int remap_count[4]; | ||||
|  | ||||
|     uint16_t   *bitmap  [4]; //float encode | ||||
|     uint16_t   *fltmap  [4]; //halffloat encode & decode | ||||
| @@ -199,6 +200,7 @@ int ff_ffv1_parse_header(FFV1Context *f, RangeCoder *c, uint8_t *state); | ||||
| int ff_ffv1_read_extra_header(FFV1Context *f); | ||||
| int ff_ffv1_read_quant_tables(RangeCoder *c, | ||||
|                               int16_t quant_table[MAX_CONTEXT_INPUTS][256]); | ||||
| void ff_ffv1_compute_bits_per_plane(const FFV1Context *f, FFV1SliceContext *sc, int bits[4], int offset[1], int mask[4], int bits_per_raw_sample); | ||||
| int ff_ffv1_get_symbol(RangeCoder *c, uint8_t *state, int is_signed); | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -99,6 +99,16 @@ static int decode_plane(FFV1Context *f, FFV1SliceContext *sc, | ||||
| { | ||||
|     int x, y; | ||||
|     int16_t *sample[2]; | ||||
|     int bits; | ||||
|     unsigned mask; | ||||
|  | ||||
|     if (sc->remap) { | ||||
|         bits = av_ceil_log2(sc->remap_count[remap_index]); | ||||
|         mask = (1<<bits)-1; | ||||
|     } else { | ||||
|         bits = f->avctx->bits_per_raw_sample; | ||||
|     } | ||||
|  | ||||
|     sample[0] = sc->sample_buffer + 3; | ||||
|     sample[1] = sc->sample_buffer + w + 6 + 3; | ||||
|  | ||||
| @@ -125,18 +135,18 @@ static int decode_plane(FFV1Context *f, FFV1SliceContext *sc, | ||||
|             for (x = 0; x < w; x++) | ||||
|                 src[x*pixel_stride + stride * y] = sample[1][x]; | ||||
|         } else { | ||||
|             int ret = decode_line(f, sc, gb, w, sample, plane_index, f->avctx->bits_per_raw_sample, ac); | ||||
|             int ret = decode_line(f, sc, gb, w, sample, plane_index, bits, ac); | ||||
|             if (ret < 0) | ||||
|                 return ret; | ||||
|  | ||||
|             if (sc->remap) { | ||||
|                 if (f->packed_at_lsb || f->avctx->bits_per_raw_sample == 16) { | ||||
|                     for (x = 0; x < w; x++) { | ||||
|                         ((uint16_t*)(src + stride*y))[x*pixel_stride] = sc->fltmap[remap_index][sample[1][x] & 0xFFFF]; | ||||
|                         ((uint16_t*)(src + stride*y))[x*pixel_stride] = sc->fltmap[remap_index][sample[1][x] & mask]; | ||||
|                     } | ||||
|                 } else { | ||||
|                     for (x = 0; x < w; x++) { | ||||
|                         int v = sc->fltmap[remap_index][sample[1][x] & 0xFFFF]; | ||||
|                         int v = sc->fltmap[remap_index][sample[1][x] & mask]; | ||||
|                         ((uint16_t*)(src + stride*y))[x*pixel_stride] = v << (16 - f->avctx->bits_per_raw_sample) | v >> (2 * f->avctx->bits_per_raw_sample - 16); | ||||
|                     } | ||||
|                 } | ||||
| @@ -337,6 +347,7 @@ static int decode_remap(FFV1Context *f, FFV1SliceContext *sc) | ||||
|             } | ||||
|             lu ^= !run; | ||||
|         } | ||||
|         sc->remap_count[p] = j; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|   | ||||
| @@ -36,6 +36,12 @@ RENAME(decode_line)(FFV1Context *f, FFV1SliceContext *sc, | ||||
|     int run_mode  = 0; | ||||
|     int run_index = sc->run_index; | ||||
|  | ||||
|     if (bits == 0) { | ||||
|         for (x = 0; x < w; x++) | ||||
|             sample[1][x] = 0; | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if (is_input_end(c, gb, ac)) | ||||
|         return AVERROR_INVALIDDATA; | ||||
|  | ||||
| @@ -138,10 +144,12 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc, | ||||
|     int x, y, p; | ||||
|     TYPE *sample[4][2]; | ||||
|     int lbd    = f->avctx->bits_per_raw_sample <= 8; | ||||
|     int bits   = f->avctx->bits_per_raw_sample > 0 ? FFMIN(f->avctx->bits_per_raw_sample, 16) : 8; | ||||
|     int offset = 1 << bits; | ||||
|     int bits[4], offset; | ||||
|     int transparency = f->transparency; | ||||
|     int ac = f->ac; | ||||
|     unsigned mask[4]; | ||||
|  | ||||
|     ff_ffv1_compute_bits_per_plane(f, sc, bits, &offset, mask, f->avctx->bits_per_raw_sample); | ||||
|  | ||||
|     if (sc->slice_coding_mode == 1) | ||||
|         ac = 1; | ||||
| @@ -165,10 +173,10 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc, | ||||
|  | ||||
|             sample[p][1][-1]= sample[p][0][0  ]; | ||||
|             sample[p][0][ w]= sample[p][0][w-1]; | ||||
|             if (lbd && sc->slice_coding_mode == 0) | ||||
|             if (bits[p] == 9) | ||||
|                 ret = RENAME(decode_line)(f, sc, gb, w, sample[p], (p + 1)/2, 9, ac); | ||||
|             else | ||||
|                 ret = RENAME(decode_line)(f, sc, gb, w, sample[p], (p + 1)/2, bits + (sc->slice_coding_mode != 1), ac); | ||||
|                 ret = RENAME(decode_line)(f, sc, gb, w, sample[p], (p + 1)/2, bits[p], ac); | ||||
|             if (ret < 0) | ||||
|                 return ret; | ||||
|         } | ||||
| @@ -187,17 +195,17 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc, | ||||
|             } | ||||
|             if (sc->remap) { | ||||
|                 if (f->avctx->bits_per_raw_sample == 32) { | ||||
|                     g = sc->fltmap32[0][g & 0xFFFF]; | ||||
|                     b = sc->fltmap32[1][b & 0xFFFF]; | ||||
|                     r = sc->fltmap32[2][r & 0xFFFF]; | ||||
|                     g = sc->fltmap32[0][g & mask[0]]; | ||||
|                     b = sc->fltmap32[1][b & mask[1]]; | ||||
|                     r = sc->fltmap32[2][r & mask[2]]; | ||||
|                     if (transparency) | ||||
|                         a = sc->fltmap32[3][a & 0xFFFF]; | ||||
|                         a = sc->fltmap32[3][a & mask[3]]; | ||||
|                 } else { | ||||
|                     g = sc->fltmap[0][g & 0xFFFF]; | ||||
|                     b = sc->fltmap[1][b & 0xFFFF]; | ||||
|                     r = sc->fltmap[2][r & 0xFFFF]; | ||||
|                     g = sc->fltmap[0][g & mask[0]]; | ||||
|                     b = sc->fltmap[1][b & mask[1]]; | ||||
|                     r = sc->fltmap[2][r & mask[2]]; | ||||
|                     if (transparency) | ||||
|                         a = sc->fltmap[3][a & 0xFFFF]; | ||||
|                         a = sc->fltmap[3][a & mask[3]]; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -433,7 +433,7 @@ static void set_micro_version(FFV1Context *f) | ||||
|         if (f->version == 3) { | ||||
|             f->micro_version = 4; | ||||
|         } else if (f->version == 4) { | ||||
|             f->micro_version = 7; | ||||
|             f->micro_version = 8; | ||||
|         } else | ||||
|             av_assert0(0); | ||||
|  | ||||
| @@ -1216,6 +1216,7 @@ static void encode_histogram_remap(FFV1Context *f, FFV1SliceContext *sc) | ||||
|         } | ||||
|         if (run) | ||||
|             put_symbol(&sc->c, state[lu], run, 0); | ||||
|         sc->remap_count[p] = j; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1370,7 +1371,8 @@ static int encode_float32_remap_segment(FFV1SliceContext *sc, | ||||
|                     mul[ current_mul_index ] *= -1; | ||||
|                     put_symbol_inline(&rc, state[0][2], mul[ current_mul_index ], 0, NULL, NULL); | ||||
|                 } | ||||
|                 compact_index ++; | ||||
|                 if (i < pixel_num) | ||||
|                     compact_index ++; | ||||
|             } | ||||
|         } | ||||
|         if (!run || run1final) | ||||
| @@ -1380,6 +1382,8 @@ static int encode_float32_remap_segment(FFV1SliceContext *sc, | ||||
|  | ||||
|     if (update) { | ||||
|         sc->c = rc; | ||||
|         av_assert0(compact_index <= 65535); | ||||
|         sc->remap_count[p] = compact_index + 1; | ||||
|     } | ||||
|     return get_rac_count(&rc); | ||||
| } | ||||
| @@ -1492,10 +1496,11 @@ static int encode_float32_rgb_frame(FFV1Context *f, FFV1SliceContext *sc, | ||||
|     const int ring_size = f->context_model ? 3 : 2; | ||||
|     int32_t *sample[4][3]; | ||||
|     const int pass1 = !!(f->avctx->flags & AV_CODEC_FLAG_PASS1); | ||||
|     int bits   = 16;  //TODO explain this in the specifciation, we have 32bits in but really encode max 16 | ||||
|     int offset = 1 << bits; | ||||
|     int bits[4], offset; | ||||
|     int transparency = f->transparency; | ||||
|  | ||||
|     ff_ffv1_compute_bits_per_plane(f, sc, bits, &offset, NULL, f->bits_per_raw_sample); | ||||
|  | ||||
|     sc->run_index = 0; | ||||
|  | ||||
|     memset(RENAME(sc->sample_buffer), 0, ring_size * MAX_PLANES * | ||||
| @@ -1532,7 +1537,7 @@ static int encode_float32_rgb_frame(FFV1Context *f, FFV1SliceContext *sc, | ||||
|             sample[p][0][-1] = sample[p][1][0  ]; | ||||
|             sample[p][1][ w] = sample[p][1][w-1]; | ||||
|             ret = encode_line32(f, sc, f->avctx, w, sample[p], (p + 1) / 2, | ||||
|                                 bits + (sc->slice_coding_mode != 1), ac, pass1); | ||||
|                                 bits[p], ac, pass1); | ||||
|             if (ret < 0) | ||||
|                 return ret; | ||||
|         } | ||||
|   | ||||
| @@ -35,6 +35,9 @@ RENAME(encode_line)(FFV1Context *f, FFV1SliceContext *sc, | ||||
|     int run_count = 0; | ||||
|     int run_mode  = 0; | ||||
|  | ||||
|     if (bits == 0) | ||||
|         return 0; | ||||
|  | ||||
|     if (ac != AC_GOLOMB_RICE) { | ||||
|         if (c->bytestream_end - c->bytestream < w * 35) { | ||||
|             av_log(logctx, AV_LOG_ERROR, "encoded Range Coder frame too large\n"); | ||||
| @@ -172,11 +175,12 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc, | ||||
|     const int pass1 = !!(f->avctx->flags & AV_CODEC_FLAG_PASS1); | ||||
|     int lbd    = f->bits_per_raw_sample <= 8; | ||||
|     int packed = !src[1]; | ||||
|     int bits   = f->bits_per_raw_sample > 0 ? f->bits_per_raw_sample : 8; | ||||
|     int offset = 1 << bits; | ||||
|     int bits[4], offset; | ||||
|     int transparency = f->transparency; | ||||
|     int packed_size = (3 + transparency)*2; | ||||
|  | ||||
|     ff_ffv1_compute_bits_per_plane(f, sc, bits, &offset, NULL, f->bits_per_raw_sample); | ||||
|  | ||||
|     sc->run_index = 0; | ||||
|  | ||||
|     memset(RENAME(sc->sample_buffer), 0, ring_size * MAX_PLANES * | ||||
| @@ -239,11 +243,11 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc, | ||||
|             int ret; | ||||
|             sample[p][0][-1] = sample[p][1][0  ]; | ||||
|             sample[p][1][ w] = sample[p][1][w-1]; | ||||
|             if (lbd && sc->slice_coding_mode == 0) | ||||
|             if (bits[p] == 9) | ||||
|                 ret = RENAME(encode_line)(f, sc, f->avctx, w, sample[p], (p + 1) / 2, 9, ac, pass1); | ||||
|             else | ||||
|                 ret = RENAME(encode_line)(f, sc, f->avctx, w, sample[p], (p + 1) / 2, | ||||
|                                           bits + (sc->slice_coding_mode != 1), ac, pass1); | ||||
|                                           bits[p], ac, pass1); | ||||
|             if (ret < 0) | ||||
|                 return ret; | ||||
|         } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user