You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	avcodec/ffv1: template functions to allow data types different from int16_t
This is required for >= 16bit RGB support I tried it without templates but its too much duplicated code Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
		| @@ -158,37 +158,6 @@ static av_always_inline int fold(int diff, int bits) | ||||
|     return diff; | ||||
| } | ||||
|  | ||||
| static inline int predict(int16_t *src, int16_t *last) | ||||
| { | ||||
|     const int LT = last[-1]; | ||||
|     const int T  = last[0]; | ||||
|     const int L  = src[-1]; | ||||
|  | ||||
|     return mid_pred(L, L + T - LT, T); | ||||
| } | ||||
|  | ||||
| static inline int get_context(PlaneContext *p, int16_t *src, | ||||
|                               int16_t *last, int16_t *last2) | ||||
| { | ||||
|     const int LT = last[-1]; | ||||
|     const int T  = last[0]; | ||||
|     const int RT = last[1]; | ||||
|     const int L  = src[-1]; | ||||
|  | ||||
|     if (p->quant_table[3][127]) { | ||||
|         const int TT = last2[0]; | ||||
|         const int LL = src[-2]; | ||||
|         return p->quant_table[0][(L - LT) & 0xFF] + | ||||
|                p->quant_table[1][(LT - T) & 0xFF] + | ||||
|                p->quant_table[2][(T - RT) & 0xFF] + | ||||
|                p->quant_table[3][(LL - L) & 0xFF] + | ||||
|                p->quant_table[4][(TT - T) & 0xFF]; | ||||
|     } else | ||||
|         return p->quant_table[0][(L - LT) & 0xFF] + | ||||
|                p->quant_table[1][(LT - T) & 0xFF] + | ||||
|                p->quant_table[2][(T - RT) & 0xFF]; | ||||
| } | ||||
|  | ||||
| static inline void update_vlc_state(VlcState *const state, const int v) | ||||
| { | ||||
|     int drift = state->drift; | ||||
| @@ -223,4 +192,10 @@ static inline void update_vlc_state(VlcState *const state, const int v) | ||||
|     state->count = count; | ||||
| } | ||||
|  | ||||
| #define TYPE int16_t | ||||
| #define RENAME(name) name | ||||
| #include "ffv1_template.c" | ||||
| #undef TYPE | ||||
| #undef RENAME | ||||
|  | ||||
| #endif /* AVCODEC_FFV1_H */ | ||||
|   | ||||
							
								
								
									
										53
									
								
								libavcodec/ffv1_template.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								libavcodec/ffv1_template.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|  * FFV1 codec | ||||
|  * | ||||
|  * Copyright (c) 2003-2013 Michael Niedermayer <michaelni@gmx.at> | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * 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 | ||||
|  */ | ||||
|  | ||||
| static inline int RENAME(predict)(TYPE *src, TYPE *last) | ||||
| { | ||||
|     const int LT = last[-1]; | ||||
|     const int T  = last[0]; | ||||
|     const int L  = src[-1]; | ||||
|  | ||||
|     return mid_pred(L, L + T - LT, T); | ||||
| } | ||||
|  | ||||
| static inline int RENAME(get_context)(PlaneContext *p, TYPE *src, | ||||
|                                       TYPE *last, TYPE *last2) | ||||
| { | ||||
|     const int LT = last[-1]; | ||||
|     const int T  = last[0]; | ||||
|     const int RT = last[1]; | ||||
|     const int L  = src[-1]; | ||||
|  | ||||
|     if (p->quant_table[3][127]) { | ||||
|         const int TT = last2[0]; | ||||
|         const int LL = src[-2]; | ||||
|         return p->quant_table[0][(L - LT) & 0xFF] + | ||||
|                p->quant_table[1][(LT - T) & 0xFF] + | ||||
|                p->quant_table[2][(T - RT) & 0xFF] + | ||||
|                p->quant_table[3][(LL - L) & 0xFF] + | ||||
|                p->quant_table[4][(TT - T) & 0xFF]; | ||||
|     } else | ||||
|         return p->quant_table[0][(L - LT) & 0xFF] + | ||||
|                p->quant_table[1][(LT - T) & 0xFF] + | ||||
|                p->quant_table[2][(T - RT) & 0xFF]; | ||||
| } | ||||
|  | ||||
| @@ -97,88 +97,12 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state, | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| static av_always_inline void decode_line(FFV1Context *s, int w, | ||||
|                                          int16_t *sample[2], | ||||
|                                          int plane_index, int bits) | ||||
| { | ||||
|     PlaneContext *const p = &s->plane[plane_index]; | ||||
|     RangeCoder *const c   = &s->c; | ||||
|     int x; | ||||
|     int run_count = 0; | ||||
|     int run_mode  = 0; | ||||
|     int run_index = s->run_index; | ||||
| #define TYPE int16_t | ||||
| #define RENAME(name) name | ||||
| #include "ffv1dec_template.c" | ||||
| #undef TYPE | ||||
| #undef RENAME | ||||
|  | ||||
|     if (s->slice_coding_mode == 1) { | ||||
|         int i; | ||||
|         for (x = 0; x < w; x++) { | ||||
|             int v = 0; | ||||
|             for (i=0; i<bits; i++) { | ||||
|                 uint8_t state = 128; | ||||
|                 v += v + get_rac(c, &state); | ||||
|             } | ||||
|             sample[1][x] = v; | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     for (x = 0; x < w; x++) { | ||||
|         int diff, context, sign; | ||||
|  | ||||
|         context = get_context(p, sample[1] + x, sample[0] + x, sample[1] + x); | ||||
|         if (context < 0) { | ||||
|             context = -context; | ||||
|             sign    = 1; | ||||
|         } else | ||||
|             sign = 0; | ||||
|  | ||||
|         av_assert2(context < p->context_count); | ||||
|  | ||||
|         if (s->ac != AC_GOLOMB_RICE) { | ||||
|             diff = get_symbol_inline(c, p->state[context], 1); | ||||
|         } else { | ||||
|             if (context == 0 && run_mode == 0) | ||||
|                 run_mode = 1; | ||||
|  | ||||
|             if (run_mode) { | ||||
|                 if (run_count == 0 && run_mode == 1) { | ||||
|                     if (get_bits1(&s->gb)) { | ||||
|                         run_count = 1 << ff_log2_run[run_index]; | ||||
|                         if (x + run_count <= w) | ||||
|                             run_index++; | ||||
|                     } else { | ||||
|                         if (ff_log2_run[run_index]) | ||||
|                             run_count = get_bits(&s->gb, ff_log2_run[run_index]); | ||||
|                         else | ||||
|                             run_count = 0; | ||||
|                         if (run_index) | ||||
|                             run_index--; | ||||
|                         run_mode = 2; | ||||
|                     } | ||||
|                 } | ||||
|                 run_count--; | ||||
|                 if (run_count < 0) { | ||||
|                     run_mode  = 0; | ||||
|                     run_count = 0; | ||||
|                     diff      = get_vlc_symbol(&s->gb, &p->vlc_state[context], | ||||
|                                                bits); | ||||
|                     if (diff >= 0) | ||||
|                         diff++; | ||||
|                 } else | ||||
|                     diff = 0; | ||||
|             } else | ||||
|                 diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], bits); | ||||
|  | ||||
|             ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", | ||||
|                     run_count, run_index, run_mode, x, get_bits_count(&s->gb)); | ||||
|         } | ||||
|  | ||||
|         if (sign) | ||||
|             diff = -diff; | ||||
|  | ||||
|         sample[1][x] = av_mod_uintp2(predict(sample[1] + x, sample[0] + x) + diff, bits); | ||||
|     } | ||||
|     s->run_index = run_index; | ||||
| } | ||||
|  | ||||
| static void decode_plane(FFV1Context *s, uint8_t *src, | ||||
|                          int w, int h, int stride, int plane_index, | ||||
| @@ -223,62 +147,6 @@ static void decode_plane(FFV1Context *s, uint8_t *src, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void decode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]) | ||||
| { | ||||
|     int x, y, p; | ||||
|     int16_t *sample[4][2]; | ||||
|     int lbd    = s->avctx->bits_per_raw_sample <= 8; | ||||
|     int bits   = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8; | ||||
|     int offset = 1 << bits; | ||||
|  | ||||
|     for (x = 0; x < 4; x++) { | ||||
|         sample[x][0] = s->sample_buffer +  x * 2      * (w + 6) + 3; | ||||
|         sample[x][1] = s->sample_buffer + (x * 2 + 1) * (w + 6) + 3; | ||||
|     } | ||||
|  | ||||
|     s->run_index = 0; | ||||
|  | ||||
|     memset(s->sample_buffer, 0, 8 * (w + 6) * sizeof(*s->sample_buffer)); | ||||
|  | ||||
|     for (y = 0; y < h; y++) { | ||||
|         for (p = 0; p < 3 + s->transparency; p++) { | ||||
|             int16_t *temp = sample[p][0]; // FIXME: try a normal buffer | ||||
|  | ||||
|             sample[p][0] = sample[p][1]; | ||||
|             sample[p][1] = temp; | ||||
|  | ||||
|             sample[p][1][-1]= sample[p][0][0  ]; | ||||
|             sample[p][0][ w]= sample[p][0][w-1]; | ||||
|             if (lbd && s->slice_coding_mode == 0) | ||||
|                 decode_line(s, w, sample[p], (p + 1)/2, 9); | ||||
|             else | ||||
|                 decode_line(s, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1)); | ||||
|         } | ||||
|         for (x = 0; x < w; x++) { | ||||
|             int g = sample[0][1][x]; | ||||
|             int b = sample[1][1][x]; | ||||
|             int r = sample[2][1][x]; | ||||
|             int a = sample[3][1][x]; | ||||
|  | ||||
|             if (s->slice_coding_mode != 1) { | ||||
|                 b -= offset; | ||||
|                 r -= offset; | ||||
|                 g -= (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2; | ||||
|                 b += g; | ||||
|                 r += g; | ||||
|             } | ||||
|  | ||||
|             if (lbd) | ||||
|                 *((uint32_t*)(src[0] + x*4 + stride[0]*y)) = b + (g<<8) + (r<<16) + (a<<24); | ||||
|             else { | ||||
|                 *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b; | ||||
|                 *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g; | ||||
|                 *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int decode_slice_header(FFV1Context *f, FFV1Context *fs) | ||||
| { | ||||
|     RangeCoder *c = &fs->c; | ||||
|   | ||||
							
								
								
									
										160
									
								
								libavcodec/ffv1dec_template.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								libavcodec/ffv1dec_template.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,160 @@ | ||||
| /* | ||||
|  * FFV1 decoder template | ||||
|  * | ||||
|  * Copyright (c) 2003-2016 Michael Niedermayer <michaelni@gmx.at> | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * 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 | ||||
|  */ | ||||
|  | ||||
| static av_always_inline void RENAME(decode_line)(FFV1Context *s, int w, | ||||
|                                                  TYPE *sample[2], | ||||
|                                                  int plane_index, int bits) | ||||
| { | ||||
|     PlaneContext *const p = &s->plane[plane_index]; | ||||
|     RangeCoder *const c   = &s->c; | ||||
|     int x; | ||||
|     int run_count = 0; | ||||
|     int run_mode  = 0; | ||||
|     int run_index = s->run_index; | ||||
|  | ||||
|     if (s->slice_coding_mode == 1) { | ||||
|         int i; | ||||
|         for (x = 0; x < w; x++) { | ||||
|             int v = 0; | ||||
|             for (i=0; i<bits; i++) { | ||||
|                 uint8_t state = 128; | ||||
|                 v += v + get_rac(c, &state); | ||||
|             } | ||||
|             sample[1][x] = v; | ||||
|         } | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     for (x = 0; x < w; x++) { | ||||
|         int diff, context, sign; | ||||
|  | ||||
|         context = RENAME(get_context)(p, sample[1] + x, sample[0] + x, sample[1] + x); | ||||
|         if (context < 0) { | ||||
|             context = -context; | ||||
|             sign    = 1; | ||||
|         } else | ||||
|             sign = 0; | ||||
|  | ||||
|         av_assert2(context < p->context_count); | ||||
|  | ||||
|         if (s->ac != AC_GOLOMB_RICE) { | ||||
|             diff = get_symbol_inline(c, p->state[context], 1); | ||||
|         } else { | ||||
|             if (context == 0 && run_mode == 0) | ||||
|                 run_mode = 1; | ||||
|  | ||||
|             if (run_mode) { | ||||
|                 if (run_count == 0 && run_mode == 1) { | ||||
|                     if (get_bits1(&s->gb)) { | ||||
|                         run_count = 1 << ff_log2_run[run_index]; | ||||
|                         if (x + run_count <= w) | ||||
|                             run_index++; | ||||
|                     } else { | ||||
|                         if (ff_log2_run[run_index]) | ||||
|                             run_count = get_bits(&s->gb, ff_log2_run[run_index]); | ||||
|                         else | ||||
|                             run_count = 0; | ||||
|                         if (run_index) | ||||
|                             run_index--; | ||||
|                         run_mode = 2; | ||||
|                     } | ||||
|                 } | ||||
|                 run_count--; | ||||
|                 if (run_count < 0) { | ||||
|                     run_mode  = 0; | ||||
|                     run_count = 0; | ||||
|                     diff      = get_vlc_symbol(&s->gb, &p->vlc_state[context], | ||||
|                                                bits); | ||||
|                     if (diff >= 0) | ||||
|                         diff++; | ||||
|                 } else | ||||
|                     diff = 0; | ||||
|             } else | ||||
|                 diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], bits); | ||||
|  | ||||
|             ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", | ||||
|                     run_count, run_index, run_mode, x, get_bits_count(&s->gb)); | ||||
|         } | ||||
|  | ||||
|         if (sign) | ||||
|             diff = -diff; | ||||
|  | ||||
|         sample[1][x] = av_mod_uintp2(RENAME(predict)(sample[1] + x, sample[0] + x) + diff, bits); | ||||
|     } | ||||
|     s->run_index = run_index; | ||||
| } | ||||
|  | ||||
| static void RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[3], int w, int h, int stride[3]) | ||||
| { | ||||
|     int x, y, p; | ||||
|     TYPE *sample[4][2]; | ||||
|     int lbd    = s->avctx->bits_per_raw_sample <= 8; | ||||
|     int bits   = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8; | ||||
|     int offset = 1 << bits; | ||||
|  | ||||
|     for (x = 0; x < 4; x++) { | ||||
|         sample[x][0] = RENAME(s->sample_buffer) +  x * 2      * (w + 6) + 3; | ||||
|         sample[x][1] = RENAME(s->sample_buffer) + (x * 2 + 1) * (w + 6) + 3; | ||||
|     } | ||||
|  | ||||
|     s->run_index = 0; | ||||
|  | ||||
|     memset(RENAME(s->sample_buffer), 0, 8 * (w + 6) * sizeof(*RENAME(s->sample_buffer))); | ||||
|  | ||||
|     for (y = 0; y < h; y++) { | ||||
|         for (p = 0; p < 3 + s->transparency; p++) { | ||||
|             TYPE *temp = sample[p][0]; // FIXME: try a normal buffer | ||||
|  | ||||
|             sample[p][0] = sample[p][1]; | ||||
|             sample[p][1] = temp; | ||||
|  | ||||
|             sample[p][1][-1]= sample[p][0][0  ]; | ||||
|             sample[p][0][ w]= sample[p][0][w-1]; | ||||
|             if (lbd && s->slice_coding_mode == 0) | ||||
|                 RENAME(decode_line)(s, w, sample[p], (p + 1)/2, 9); | ||||
|             else | ||||
|                 RENAME(decode_line)(s, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1)); | ||||
|         } | ||||
|         for (x = 0; x < w; x++) { | ||||
|             int g = sample[0][1][x]; | ||||
|             int b = sample[1][1][x]; | ||||
|             int r = sample[2][1][x]; | ||||
|             int a = sample[3][1][x]; | ||||
|  | ||||
|             if (s->slice_coding_mode != 1) { | ||||
|                 b -= offset; | ||||
|                 r -= offset; | ||||
|                 g -= (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2; | ||||
|                 b += g; | ||||
|                 r += g; | ||||
|             } | ||||
|  | ||||
|             if (lbd) | ||||
|                 *((uint32_t*)(src[0] + x*4 + stride[0]*y)) = b + (g<<8) + (r<<16) + (a<<24); | ||||
|             else { | ||||
|                 *((uint16_t*)(src[0] + x*2 + stride[0]*y)) = b; | ||||
|                 *((uint16_t*)(src[1] + x*2 + stride[1]*y)) = g; | ||||
|                 *((uint16_t*)(src[2] + x*2 + stride[2]*y)) = r; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -268,107 +268,12 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state, | ||||
|     update_vlc_state(state, v); | ||||
| } | ||||
|  | ||||
| static av_always_inline int encode_line(FFV1Context *s, int w, | ||||
|                                         int16_t *sample[3], | ||||
|                                         int plane_index, int bits) | ||||
| { | ||||
|     PlaneContext *const p = &s->plane[plane_index]; | ||||
|     RangeCoder *const c   = &s->c; | ||||
|     int x; | ||||
|     int run_index = s->run_index; | ||||
|     int run_count = 0; | ||||
|     int run_mode  = 0; | ||||
| #define TYPE int16_t | ||||
| #define RENAME(name) name | ||||
| #include "ffv1enc_template.c" | ||||
| #undef TYPE | ||||
| #undef RENAME | ||||
|  | ||||
|     if (s->ac != AC_GOLOMB_RICE) { | ||||
|         if (c->bytestream_end - c->bytestream < w * 35) { | ||||
|             av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); | ||||
|             return AVERROR_INVALIDDATA; | ||||
|         } | ||||
|     } else { | ||||
|         if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < w * 4) { | ||||
|             av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); | ||||
|             return AVERROR_INVALIDDATA; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (s->slice_coding_mode == 1) { | ||||
|         for (x = 0; x < w; x++) { | ||||
|             int i; | ||||
|             int v = sample[0][x]; | ||||
|             for (i = bits-1; i>=0; i--) { | ||||
|                 uint8_t state = 128; | ||||
|                 put_rac(c, &state, (v>>i) & 1); | ||||
|             } | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     for (x = 0; x < w; x++) { | ||||
|         int diff, context; | ||||
|  | ||||
|         context = get_context(p, sample[0] + x, sample[1] + x, sample[2] + x); | ||||
|         diff    = sample[0][x] - predict(sample[0] + x, sample[1] + x); | ||||
|  | ||||
|         if (context < 0) { | ||||
|             context = -context; | ||||
|             diff    = -diff; | ||||
|         } | ||||
|  | ||||
|         diff = fold(diff, bits); | ||||
|  | ||||
|         if (s->ac != AC_GOLOMB_RICE) { | ||||
|             if (s->flags & AV_CODEC_FLAG_PASS1) { | ||||
|                 put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat, | ||||
|                                   s->rc_stat2[p->quant_table_index][context]); | ||||
|             } else { | ||||
|                 put_symbol_inline(c, p->state[context], diff, 1, NULL, NULL); | ||||
|             } | ||||
|         } else { | ||||
|             if (context == 0) | ||||
|                 run_mode = 1; | ||||
|  | ||||
|             if (run_mode) { | ||||
|                 if (diff) { | ||||
|                     while (run_count >= 1 << ff_log2_run[run_index]) { | ||||
|                         run_count -= 1 << ff_log2_run[run_index]; | ||||
|                         run_index++; | ||||
|                         put_bits(&s->pb, 1, 1); | ||||
|                     } | ||||
|  | ||||
|                     put_bits(&s->pb, 1 + ff_log2_run[run_index], run_count); | ||||
|                     if (run_index) | ||||
|                         run_index--; | ||||
|                     run_count = 0; | ||||
|                     run_mode  = 0; | ||||
|                     if (diff > 0) | ||||
|                         diff--; | ||||
|                 } else { | ||||
|                     run_count++; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", | ||||
|                     run_count, run_index, run_mode, x, | ||||
|                     (int)put_bits_count(&s->pb)); | ||||
|  | ||||
|             if (run_mode == 0) | ||||
|                 put_vlc_symbol(&s->pb, &p->vlc_state[context], diff, bits); | ||||
|         } | ||||
|     } | ||||
|     if (run_mode) { | ||||
|         while (run_count >= 1 << ff_log2_run[run_index]) { | ||||
|             run_count -= 1 << ff_log2_run[run_index]; | ||||
|             run_index++; | ||||
|             put_bits(&s->pb, 1, 1); | ||||
|         } | ||||
|  | ||||
|         if (run_count) | ||||
|             put_bits(&s->pb, 1, 1); | ||||
|     } | ||||
|     s->run_index = run_index; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int encode_plane(FFV1Context *s, uint8_t *src, int w, int h, | ||||
|                          int stride, int plane_index, int pixel_stride) | ||||
| @@ -410,68 +315,6 @@ static int encode_plane(FFV1Context *s, uint8_t *src, int w, int h, | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int encode_rgb_frame(FFV1Context *s, const uint8_t *src[3], | ||||
|                              int w, int h, const int stride[3]) | ||||
| { | ||||
|     int x, y, p, i; | ||||
|     const int ring_size = s->context_model ? 3 : 2; | ||||
|     int16_t *sample[4][3]; | ||||
|     int lbd    = s->bits_per_raw_sample <= 8; | ||||
|     int bits   = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8; | ||||
|     int offset = 1 << bits; | ||||
|  | ||||
|     s->run_index = 0; | ||||
|  | ||||
|     memset(s->sample_buffer, 0, ring_size * MAX_PLANES * | ||||
|                                 (w + 6) * sizeof(*s->sample_buffer)); | ||||
|  | ||||
|     for (y = 0; y < h; y++) { | ||||
|         for (i = 0; i < ring_size; i++) | ||||
|             for (p = 0; p < MAX_PLANES; p++) | ||||
|                 sample[p][i]= s->sample_buffer + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3; | ||||
|  | ||||
|         for (x = 0; x < w; x++) { | ||||
|             int b, g, r, av_uninit(a); | ||||
|             if (lbd) { | ||||
|                 unsigned v = *((const uint32_t*)(src[0] + x*4 + stride[0]*y)); | ||||
|                 b =  v        & 0xFF; | ||||
|                 g = (v >>  8) & 0xFF; | ||||
|                 r = (v >> 16) & 0xFF; | ||||
|                 a =  v >> 24; | ||||
|             } else { | ||||
|                 b = *((const uint16_t *)(src[0] + x*2 + stride[0]*y)); | ||||
|                 g = *((const uint16_t *)(src[1] + x*2 + stride[1]*y)); | ||||
|                 r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y)); | ||||
|             } | ||||
|  | ||||
|             if (s->slice_coding_mode != 1) { | ||||
|                 b -= g; | ||||
|                 r -= g; | ||||
|                 g += (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2; | ||||
|                 b += offset; | ||||
|                 r += offset; | ||||
|             } | ||||
|  | ||||
|             sample[0][0][x] = g; | ||||
|             sample[1][0][x] = b; | ||||
|             sample[2][0][x] = r; | ||||
|             sample[3][0][x] = a; | ||||
|         } | ||||
|         for (p = 0; p < 3 + s->transparency; p++) { | ||||
|             int ret; | ||||
|             sample[p][0][-1] = sample[p][1][0  ]; | ||||
|             sample[p][1][ w] = sample[p][1][w-1]; | ||||
|             if (lbd && s->slice_coding_mode == 0) | ||||
|                 ret = encode_line(s, w, sample[p], (p + 1) / 2, 9); | ||||
|             else | ||||
|                 ret = encode_line(s, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1)); | ||||
|             if (ret < 0) | ||||
|                 return ret; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static void write_quant_table(RangeCoder *c, int16_t *quant_table) | ||||
| { | ||||
|     int last = 0; | ||||
|   | ||||
							
								
								
									
										186
									
								
								libavcodec/ffv1enc_template.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								libavcodec/ffv1enc_template.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,186 @@ | ||||
| /* | ||||
|  * FFV1 encoder template | ||||
|  * | ||||
|  * Copyright (c) 2003-2016 Michael Niedermayer <michaelni@gmx.at> | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
|  * FFmpeg is free software; you can redistribute it and/or | ||||
|  * modify it under the terms of the GNU Lesser General Public | ||||
|  * License as published by the Free Software Foundation; either | ||||
|  * version 2.1 of the License, or (at your option) any later version. | ||||
|  * | ||||
|  * FFmpeg is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|  * Lesser General Public License for more details. | ||||
|  * | ||||
|  * 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 | ||||
|  */ | ||||
|  | ||||
| static av_always_inline int RENAME(encode_line)(FFV1Context *s, int w, | ||||
|                                                 TYPE *sample[3], | ||||
|                                                 int plane_index, int bits) | ||||
| { | ||||
|     PlaneContext *const p = &s->plane[plane_index]; | ||||
|     RangeCoder *const c   = &s->c; | ||||
|     int x; | ||||
|     int run_index = s->run_index; | ||||
|     int run_count = 0; | ||||
|     int run_mode  = 0; | ||||
|  | ||||
|     if (s->ac != AC_GOLOMB_RICE) { | ||||
|         if (c->bytestream_end - c->bytestream < w * 35) { | ||||
|             av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); | ||||
|             return AVERROR_INVALIDDATA; | ||||
|         } | ||||
|     } else { | ||||
|         if (s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb) >> 3) < w * 4) { | ||||
|             av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); | ||||
|             return AVERROR_INVALIDDATA; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (s->slice_coding_mode == 1) { | ||||
|         for (x = 0; x < w; x++) { | ||||
|             int i; | ||||
|             int v = sample[0][x]; | ||||
|             for (i = bits-1; i>=0; i--) { | ||||
|                 uint8_t state = 128; | ||||
|                 put_rac(c, &state, (v>>i) & 1); | ||||
|             } | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     for (x = 0; x < w; x++) { | ||||
|         int diff, context; | ||||
|  | ||||
|         context = RENAME(get_context)(p, sample[0] + x, sample[1] + x, sample[2] + x); | ||||
|         diff    = sample[0][x] - RENAME(predict)(sample[0] + x, sample[1] + x); | ||||
|  | ||||
|         if (context < 0) { | ||||
|             context = -context; | ||||
|             diff    = -diff; | ||||
|         } | ||||
|  | ||||
|         diff = fold(diff, bits); | ||||
|  | ||||
|         if (s->ac != AC_GOLOMB_RICE) { | ||||
|             if (s->flags & AV_CODEC_FLAG_PASS1) { | ||||
|                 put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat, | ||||
|                                   s->rc_stat2[p->quant_table_index][context]); | ||||
|             } else { | ||||
|                 put_symbol_inline(c, p->state[context], diff, 1, NULL, NULL); | ||||
|             } | ||||
|         } else { | ||||
|             if (context == 0) | ||||
|                 run_mode = 1; | ||||
|  | ||||
|             if (run_mode) { | ||||
|                 if (diff) { | ||||
|                     while (run_count >= 1 << ff_log2_run[run_index]) { | ||||
|                         run_count -= 1 << ff_log2_run[run_index]; | ||||
|                         run_index++; | ||||
|                         put_bits(&s->pb, 1, 1); | ||||
|                     } | ||||
|  | ||||
|                     put_bits(&s->pb, 1 + ff_log2_run[run_index], run_count); | ||||
|                     if (run_index) | ||||
|                         run_index--; | ||||
|                     run_count = 0; | ||||
|                     run_mode  = 0; | ||||
|                     if (diff > 0) | ||||
|                         diff--; | ||||
|                 } else { | ||||
|                     run_count++; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n", | ||||
|                     run_count, run_index, run_mode, x, | ||||
|                     (int)put_bits_count(&s->pb)); | ||||
|  | ||||
|             if (run_mode == 0) | ||||
|                 put_vlc_symbol(&s->pb, &p->vlc_state[context], diff, bits); | ||||
|         } | ||||
|     } | ||||
|     if (run_mode) { | ||||
|         while (run_count >= 1 << ff_log2_run[run_index]) { | ||||
|             run_count -= 1 << ff_log2_run[run_index]; | ||||
|             run_index++; | ||||
|             put_bits(&s->pb, 1, 1); | ||||
|         } | ||||
|  | ||||
|         if (run_count) | ||||
|             put_bits(&s->pb, 1, 1); | ||||
|     } | ||||
|     s->run_index = run_index; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[3], | ||||
|                                     int w, int h, const int stride[3]) | ||||
| { | ||||
|     int x, y, p, i; | ||||
|     const int ring_size = s->context_model ? 3 : 2; | ||||
|     TYPE *sample[4][3]; | ||||
|     int lbd    = s->bits_per_raw_sample <= 8; | ||||
|     int bits   = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8; | ||||
|     int offset = 1 << bits; | ||||
|  | ||||
|     s->run_index = 0; | ||||
|  | ||||
|     memset(RENAME(s->sample_buffer), 0, ring_size * MAX_PLANES * | ||||
|            (w + 6) * sizeof(*RENAME(s->sample_buffer))); | ||||
|  | ||||
|     for (y = 0; y < h; y++) { | ||||
|         for (i = 0; i < ring_size; i++) | ||||
|             for (p = 0; p < MAX_PLANES; p++) | ||||
|                 sample[p][i]= RENAME(s->sample_buffer) + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3; | ||||
|  | ||||
|         for (x = 0; x < w; x++) { | ||||
|             int b, g, r, av_uninit(a); | ||||
|             if (lbd) { | ||||
|                 unsigned v = *((const uint32_t*)(src[0] + x*4 + stride[0]*y)); | ||||
|                 b =  v        & 0xFF; | ||||
|                 g = (v >>  8) & 0xFF; | ||||
|                 r = (v >> 16) & 0xFF; | ||||
|                 a =  v >> 24; | ||||
|             } else { | ||||
|                 b = *((const uint16_t *)(src[0] + x*2 + stride[0]*y)); | ||||
|                 g = *((const uint16_t *)(src[1] + x*2 + stride[1]*y)); | ||||
|                 r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y)); | ||||
|             } | ||||
|  | ||||
|             if (s->slice_coding_mode != 1) { | ||||
|                 b -= g; | ||||
|                 r -= g; | ||||
|                 g += (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2; | ||||
|                 b += offset; | ||||
|                 r += offset; | ||||
|             } | ||||
|  | ||||
|             sample[0][0][x] = g; | ||||
|             sample[1][0][x] = b; | ||||
|             sample[2][0][x] = r; | ||||
|             sample[3][0][x] = a; | ||||
|         } | ||||
|         for (p = 0; p < 3 + s->transparency; p++) { | ||||
|             int ret; | ||||
|             sample[p][0][-1] = sample[p][1][0  ]; | ||||
|             sample[p][1][ w] = sample[p][1][w-1]; | ||||
|             if (lbd && s->slice_coding_mode == 0) | ||||
|                 ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, 9); | ||||
|             else | ||||
|                 ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1)); | ||||
|             if (ret < 0) | ||||
|                 return ret; | ||||
|         } | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user