2003-06-09 05:24:51 +03:00
/*
* FFV1 codec for libavcodec
*
* Copyright ( c ) 2003 Michael Niedermayer < michaelni @ gmx . at >
*
2006-10-07 18:30:46 +03:00
* This file is part of FFmpeg .
*
* FFmpeg is free software ; you can redistribute it and / or
2003-06-09 05:24:51 +03:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
2006-10-07 18:30:46 +03:00
* version 2.1 of the License , or ( at your option ) any later version .
2003-06-09 05:24:51 +03:00
*
2006-10-07 18:30:46 +03:00
* FFmpeg is distributed in the hope that it will be useful ,
2003-06-09 05:24:51 +03:00
* 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
2006-10-07 18:30:46 +03:00
* License along with FFmpeg ; if not , write to the Free Software
2006-01-13 00:43:26 +02:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2003-06-09 05:24:51 +03:00
*/
2005-12-17 20:14:38 +02:00
2003-06-09 05:24:51 +03:00
/**
2010-04-20 17:45:34 +03:00
* @ file
2010-03-22 16:26:17 +02:00
* FF Video Codec 1 ( a lossless codec )
2003-06-09 05:24:51 +03:00
*/
# include "avcodec.h"
2012-03-22 06:22:49 +03:00
# include "internal.h"
2009-04-13 19:20:26 +03:00
# include "get_bits.h"
2009-04-12 11:35:26 +03:00
# include "put_bits.h"
2003-06-09 05:24:51 +03:00
# include "dsputil.h"
2004-10-31 12:08:50 +02:00
# include "rangecoder.h"
2003-06-14 00:31:28 +03:00
# include "golomb.h"
2009-01-19 00:57:40 +02:00
# include "mathops.h"
2012-02-14 08:39:03 +03:00
# include "libavutil/pixdesc.h"
2010-10-15 01:03:32 +03:00
# include "libavutil/avassert.h"
2012-04-20 15:47:24 +03:00
# include "libavutil/crc.h"
2012-04-30 16:00:10 +03:00
# include "libavutil/opt.h"
2003-06-09 05:24:51 +03:00
2012-04-16 12:51:17 +03:00
# ifdef __INTEL_COMPILER
# undef av_flatten
# define av_flatten
# endif
2003-06-09 05:24:51 +03:00
# define MAX_PLANES 4
2003-06-10 02:55:16 +03:00
# define CONTEXT_SIZE 32
2010-10-11 00:04:45 +03:00
# define MAX_QUANT_TABLES 8
2010-10-19 20:26:27 +03:00
# define MAX_CONTEXT_INPUTS 5
2010-10-11 00:04:45 +03:00
2011-04-01 13:46:36 +03:00
extern const uint8_t ff_log2_run [ 41 ] ;
2008-06-26 19:39:21 +03:00
2009-04-24 07:10:32 +03:00
static const int8_t quant5_10bit [ 256 ] = {
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 ,
- 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 0 , - 0 , - 0 , - 0 , - 0 , - 0 , - 0 , - 0 , - 0 , - 0 ,
} ;
2003-06-14 00:31:28 +03:00
static const int8_t quant5 [ 256 ] = {
0 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2003-06-09 05:24:51 +03:00
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2003-06-14 00:31:28 +03:00
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 1 , - 1 , - 1 ,
} ;
2011-07-03 03:52:37 +03:00
2009-04-24 07:10:32 +03:00
static const int8_t quant9_10bit [ 256 ] = {
0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 ,
3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ,
3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
- 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 ,
- 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 ,
- 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 ,
- 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 ,
- 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 ,
- 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 ,
- 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 , - 2 ,
- 2 , - 2 , - 2 , - 2 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 1 , - 0 , - 0 , - 0 , - 0 ,
} ;
2003-06-14 00:31:28 +03:00
static const int8_t quant11 [ 256 ] = {
0 , 1 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 ,
4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ,
4 , 4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
- 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 ,
- 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 ,
- 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 ,
- 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 ,
- 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 ,
- 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 5 , - 4 , - 4 ,
- 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 , - 4 ,
- 4 , - 4 , - 4 , - 4 , - 4 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 3 , - 2 , - 2 , - 2 , - 1 ,
} ;
2003-06-09 05:24:51 +03:00
2010-04-01 21:51:08 +03:00
static const uint8_t ver2_state [ 256 ] = {
0 , 10 , 10 , 10 , 10 , 16 , 16 , 16 , 28 , 16 , 16 , 29 , 42 , 49 , 20 , 49 ,
59 , 25 , 26 , 26 , 27 , 31 , 33 , 33 , 33 , 34 , 34 , 37 , 67 , 38 , 39 , 39 ,
40 , 40 , 41 , 79 , 43 , 44 , 45 , 45 , 48 , 48 , 64 , 50 , 51 , 52 , 88 , 52 ,
53 , 74 , 55 , 57 , 58 , 58 , 74 , 60 , 101 , 61 , 62 , 84 , 66 , 66 , 68 , 69 ,
87 , 82 , 71 , 97 , 73 , 73 , 82 , 75 , 111 , 77 , 94 , 78 , 87 , 81 , 83 , 97 ,
85 , 83 , 94 , 86 , 99 , 89 , 90 , 99 , 111 , 92 , 93 , 134 , 95 , 98 , 105 , 98 ,
105 , 110 , 102 , 108 , 102 , 118 , 103 , 106 , 106 , 113 , 109 , 112 , 114 , 112 , 116 , 125 ,
115 , 116 , 117 , 117 , 126 , 119 , 125 , 121 , 121 , 123 , 145 , 124 , 126 , 131 , 127 , 129 ,
165 , 130 , 132 , 138 , 133 , 135 , 145 , 136 , 137 , 139 , 146 , 141 , 143 , 142 , 144 , 148 ,
147 , 155 , 151 , 149 , 151 , 150 , 152 , 157 , 153 , 154 , 156 , 168 , 158 , 162 , 161 , 160 ,
172 , 163 , 169 , 164 , 166 , 184 , 167 , 170 , 177 , 174 , 171 , 173 , 182 , 176 , 180 , 178 ,
175 , 189 , 179 , 181 , 186 , 183 , 192 , 185 , 200 , 187 , 191 , 188 , 190 , 197 , 193 , 196 ,
197 , 194 , 195 , 196 , 198 , 202 , 199 , 201 , 210 , 203 , 207 , 204 , 205 , 206 , 208 , 214 ,
209 , 211 , 221 , 212 , 213 , 215 , 224 , 216 , 217 , 218 , 219 , 220 , 222 , 228 , 223 , 225 ,
226 , 224 , 227 , 229 , 240 , 230 , 231 , 232 , 233 , 234 , 235 , 236 , 238 , 239 , 237 , 242 ,
241 , 243 , 242 , 244 , 245 , 246 , 247 , 248 , 249 , 250 , 251 , 252 , 252 , 253 , 254 , 255 ,
} ;
2003-06-14 00:31:28 +03:00
typedef struct VlcState {
int16_t drift ;
uint16_t error_sum ;
int8_t bias ;
uint8_t count ;
} VlcState ;
2003-06-09 05:24:51 +03:00
typedef struct PlaneContext {
2010-10-19 20:26:27 +03:00
int16_t quant_table [ MAX_CONTEXT_INPUTS ] [ 256 ] ;
2010-10-26 04:59:03 +03:00
int quant_table_index ;
2003-06-09 05:24:51 +03:00
int context_count ;
2003-06-10 02:55:16 +03:00
uint8_t ( * state ) [ CONTEXT_SIZE ] ;
2003-06-14 00:31:28 +03:00
VlcState * vlc_state ;
2003-06-09 05:24:51 +03:00
uint8_t interlace_bit_state [ 2 ] ;
} PlaneContext ;
2010-10-15 01:03:32 +03:00
# define MAX_SLICES 256
2003-06-09 05:24:51 +03:00
typedef struct FFV1Context {
2012-04-30 18:55:36 +03:00
AVClass * class ;
2003-06-09 05:24:51 +03:00
AVCodecContext * avctx ;
2004-10-31 12:08:50 +02:00
RangeCoder c ;
2003-06-14 00:31:28 +03:00
GetBitContext gb ;
PutBitContext pb ;
2010-10-24 15:31:09 +03:00
uint64_t rc_stat [ 256 ] [ 2 ] ;
2010-10-27 02:01:07 +03:00
uint64_t ( * rc_stat2 [ MAX_QUANT_TABLES ] ) [ 32 ] [ 2 ] ;
2003-06-09 05:24:51 +03:00
int version ;
2012-04-08 15:20:17 +03:00
int minor_version ;
2003-06-09 05:24:51 +03:00
int width , height ;
int chroma_h_shift , chroma_v_shift ;
2012-02-06 21:23:44 +03:00
int chroma_planes ;
2011-11-28 19:38:04 +03:00
int transparency ;
2003-06-09 05:24:51 +03:00
int flags ;
int picture_number ;
AVFrame picture ;
int plane_count ;
2009-08-27 00:25:43 +03:00
int ac ; ///< 1=range coder <-> 0=golomb rice
2012-04-24 23:54:50 +03:00
int ac_byte_count ; ///< number of bytes used for AC coding
2003-06-09 05:24:51 +03:00
PlaneContext plane [ MAX_PLANES ] ;
2010-10-19 20:26:27 +03:00
int16_t quant_table [ MAX_CONTEXT_INPUTS ] [ 256 ] ;
int16_t quant_tables [ MAX_QUANT_TABLES ] [ MAX_CONTEXT_INPUTS ] [ 256 ] ;
2010-10-11 00:04:45 +03:00
int context_count [ MAX_QUANT_TABLES ] ;
2010-04-01 21:51:08 +03:00
uint8_t state_transition [ 256 ] ;
2010-10-27 02:01:11 +03:00
uint8_t ( * initial_states [ MAX_QUANT_TABLES ] ) [ 32 ] ;
2003-11-01 19:38:25 +02:00
int run_index ;
int colorspace ;
2011-04-29 17:08:20 +03:00
int16_t * sample_buffer ;
2010-10-28 15:15:44 +03:00
int gob_count ;
2011-05-08 19:51:55 +03:00
int packed_at_lsb ;
2012-04-20 16:08:28 +03:00
int ec ;
2012-04-22 14:56:07 +03:00
int key_frame_ok ;
2005-12-17 20:14:38 +02:00
2010-10-11 00:04:45 +03:00
int quant_table_count ;
2005-12-17 20:14:38 +02:00
DSPContext dsp ;
2010-10-15 01:03:32 +03:00
struct FFV1Context * slice_context [ MAX_SLICES ] ;
int slice_count ;
int num_v_slices ;
int num_h_slices ;
int slice_width ;
int slice_height ;
int slice_x ;
int slice_y ;
2012-02-12 01:45:04 +03:00
int bits_per_raw_sample ;
2003-06-09 05:24:51 +03:00
} FFV1Context ;
2006-12-08 02:35:08 +02:00
static av_always_inline int fold ( int diff , int bits ) {
2003-11-01 19:38:25 +02:00
if ( bits = = 8 )
diff = ( int8_t ) diff ;
else {
diff + = 1 < < ( bits - 1 ) ;
diff & = ( 1 < < bits ) - 1 ;
diff - = 1 < < ( bits - 1 ) ;
}
return diff ;
}
2011-04-29 17:08:20 +03:00
static inline int predict ( int16_t * src , int16_t * last )
{
2003-06-14 00:31:28 +03:00
const int LT = last [ - 1 ] ;
const int T = last [ 0 ] ;
const int L = src [ - 1 ] ;
2003-06-09 05:24:51 +03:00
2003-07-13 01:15:11 +03:00
return mid_pred ( L , L + T - LT , T ) ;
2003-06-09 05:24:51 +03:00
}
2011-04-29 17:08:20 +03:00
static inline int get_context ( PlaneContext * p , int16_t * src ,
int16_t * last , int16_t * last2 )
{
2003-06-14 00:31:28 +03:00
const int LT = last [ - 1 ] ;
const int T = last [ 0 ] ;
const int RT = last [ 1 ] ;
const int L = src [ - 1 ] ;
2010-10-15 01:03:41 +03:00
if ( p - > quant_table [ 3 ] [ 127 ] ) {
2003-06-14 00:31:28 +03:00
const int TT = last2 [ 0 ] ;
const int LL = src [ - 2 ] ;
2010-10-15 01:03:41 +03:00
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 ] ;
2003-06-14 00:31:28 +03:00
} else
2010-10-15 01:03:41 +03:00
return p - > quant_table [ 0 ] [ ( L - LT ) & 0xFF ] + p - > quant_table [ 1 ] [ ( LT - T ) & 0xFF ] + p - > quant_table [ 2 ] [ ( T - RT ) & 0xFF ] ;
2003-06-09 05:24:51 +03:00
}
2003-06-10 02:55:16 +03:00
2010-10-28 15:15:47 +03:00
static void find_best_state ( uint8_t best_state [ 256 ] [ 256 ] , const uint8_t one_state [ 256 ] ) {
int i , j , k , m ;
double l2tab [ 256 ] ;
for ( i = 1 ; i < 256 ; i + + )
l2tab [ i ] = log2 ( i / 256.0 ) ;
for ( i = 0 ; i < 256 ; i + + ) {
double best_len [ 256 ] ;
double p = i / 256.0 ;
for ( j = 0 ; j < 256 ; j + + )
best_len [ j ] = 1 < < 30 ;
for ( j = FFMAX ( i - 10 , 1 ) ; j < FFMIN ( i + 11 , 256 ) ; j + + ) {
double occ [ 256 ] = { 0 } ;
double len = 0 ;
occ [ j ] = 1.0 ;
for ( k = 0 ; k < 256 ; k + + ) {
double newocc [ 256 ] = { 0 } ;
for ( m = 0 ; m < 256 ; m + + ) {
if ( occ [ m ] ) {
len - = occ [ m ] * ( p * l2tab [ m ]
+ ( 1 - p ) * l2tab [ 256 - m ] ) ;
}
}
if ( len < best_len [ k ] ) {
best_len [ k ] = len ;
best_state [ i ] [ k ] = j ;
}
for ( m = 0 ; m < 256 ; m + + ) {
if ( occ [ m ] ) {
newocc [ one_state [ m ] ] + = occ [ m ] * p ;
newocc [ 256 - one_state [ 256 - m ] ] + = occ [ m ] * ( 1 - p ) ;
}
}
memcpy ( occ , newocc , sizeof ( occ ) ) ;
}
}
}
}
2010-10-27 02:01:07 +03:00
static av_always_inline av_flatten void put_symbol_inline ( RangeCoder * c , uint8_t * state , int v , int is_signed , uint64_t rc_stat [ 256 ] [ 2 ] , uint64_t rc_stat2 [ 32 ] [ 2 ] ) {
2003-06-09 05:24:51 +03:00
int i ;
2010-10-24 15:31:09 +03:00
# define put_rac(C,S,B) \
do { \
2010-10-27 02:00:49 +03:00
if ( rc_stat ) { \
2010-10-24 15:31:09 +03:00
rc_stat [ * ( S ) ] [ B ] + + ; \
2010-10-27 02:01:07 +03:00
rc_stat2 [ ( S ) - state ] [ B ] + + ; \
2010-10-27 02:00:49 +03:00
} \
2010-10-24 15:31:09 +03:00
put_rac ( C , S , B ) ; \
} while ( 0 )
2003-06-09 05:24:51 +03:00
if ( v ) {
2006-10-12 02:17:58 +03:00
const int a = FFABS ( v ) ;
2003-06-09 05:24:51 +03:00
const int e = av_log2 ( a ) ;
2004-10-31 12:08:50 +02:00
put_rac ( c , state + 0 , 0 ) ;
2009-04-24 07:10:32 +03:00
if ( e < = 9 ) {
2009-04-24 16:38:28 +03:00
for ( i = 0 ; i < e ; i + + ) {
put_rac ( c , state + 1 + i , 1 ) ; //1..10
}
put_rac ( c , state + 1 + i , 0 ) ;
2003-07-02 13:45:04 +03:00
2009-04-24 16:38:28 +03:00
for ( i = e - 1 ; i > = 0 ; i - - ) {
put_rac ( c , state + 22 + i , ( a > > i ) & 1 ) ; //22..31
}
2004-10-31 14:22:00 +02:00
2009-04-24 16:38:28 +03:00
if ( is_signed )
put_rac ( c , state + 11 + e , v < 0 ) ; //11..21
2009-04-24 07:10:32 +03:00
} else {
for ( i = 0 ; i < e ; i + + ) {
put_rac ( c , state + 1 + FFMIN ( i , 9 ) , 1 ) ; //1..10
}
put_rac ( c , state + 1 + 9 , 0 ) ;
for ( i = e - 1 ; i > = 0 ; i - - ) {
put_rac ( c , state + 22 + FFMIN ( i , 9 ) , ( a > > i ) & 1 ) ; //22..31
}
if ( is_signed )
put_rac ( c , state + 11 + 10 , v < 0 ) ; //11..21
}
2003-06-09 05:24:51 +03:00
} else {
2004-10-31 12:08:50 +02:00
put_rac ( c , state + 0 , 1 ) ;
2003-06-09 05:24:51 +03:00
}
2010-10-24 15:31:09 +03:00
# undef put_rac
2003-06-09 05:24:51 +03:00
}
2012-03-31 00:34:22 +03:00
static av_noinline void put_symbol ( RangeCoder * c , uint8_t * state , int v , int is_signed ) {
2010-10-27 02:01:07 +03:00
put_symbol_inline ( c , state , v , is_signed , NULL , NULL ) ;
2009-04-24 04:50:09 +03:00
}
2009-04-24 07:10:32 +03:00
static inline av_flatten int get_symbol_inline ( RangeCoder * c , uint8_t * state , int is_signed ) {
2004-10-31 12:08:50 +02:00
if ( get_rac ( c , state + 0 ) )
2003-06-09 05:24:51 +03:00
return 0 ;
else {
2004-10-31 14:22:00 +02:00
int i , e , a ;
e = 0 ;
2009-04-24 07:10:32 +03:00
while ( get_rac ( c , state + 1 + FFMIN ( e , 9 ) ) ) { //1..10
2004-10-31 14:22:00 +02:00
e + + ;
}
2003-06-09 05:24:51 +03:00
2004-10-31 14:22:00 +02:00
a = 1 ;
for ( i = e - 1 ; i > = 0 ; i - - ) {
2009-04-24 07:10:32 +03:00
a + = a + get_rac ( c , state + 22 + FFMIN ( i , 9 ) ) ; //22..31
2003-07-02 13:45:04 +03:00
}
2004-10-31 14:22:00 +02:00
2009-04-24 07:10:32 +03:00
e = - ( is_signed & & get_rac ( c , state + 11 + FFMIN ( e , 10 ) ) ) ; //11..21
2009-04-24 03:26:49 +03:00
return ( a ^ e ) - e ;
2003-06-09 05:24:51 +03:00
}
}
2003-06-14 00:31:28 +03:00
2012-03-31 00:34:22 +03:00
static av_noinline int get_symbol ( RangeCoder * c , uint8_t * state , int is_signed ) {
2009-04-24 04:50:09 +03:00
return get_symbol_inline ( c , state , is_signed ) ;
}
2003-06-14 00:31:28 +03:00
static inline void update_vlc_state ( VlcState * const state , const int v ) {
int drift = state - > drift ;
int count = state - > count ;
2006-10-12 02:17:58 +03:00
state - > error_sum + = FFABS ( v ) ;
2003-06-14 00:31:28 +03:00
drift + = v ;
if ( count = = 128 ) { //FIXME variable
count > > = 1 ;
drift > > = 1 ;
state - > error_sum > > = 1 ;
}
count + + ;
if ( drift < = - count ) {
if ( state - > bias > - 128 ) state - > bias - - ;
2005-12-17 20:14:38 +02:00
2003-06-14 00:31:28 +03:00
drift + = count ;
if ( drift < = - count )
drift = - count + 1 ;
} else if ( drift > 0 ) {
if ( state - > bias < 127 ) state - > bias + + ;
2005-12-17 20:14:38 +02:00
2003-06-14 00:31:28 +03:00
drift - = count ;
2005-12-17 20:14:38 +02:00
if ( drift > 0 )
2003-06-14 00:31:28 +03:00
drift = 0 ;
}
state - > drift = drift ;
state - > count = count ;
}
2003-11-01 19:38:25 +02:00
static inline void put_vlc_symbol ( PutBitContext * pb , VlcState * const state , int v , int bits ) {
2003-06-14 00:31:28 +03:00
int i , k , code ;
//printf("final: %d ", v);
2003-11-01 19:38:25 +02:00
v = fold ( v - state - > bias , bits ) ;
2003-06-14 00:31:28 +03:00
i = state - > count ;
k = 0 ;
while ( i < state - > error_sum ) { //FIXME optimize
k + + ;
i + = i ;
}
2003-07-13 14:06:45 +03:00
assert ( k < = 8 ) ;
2003-06-14 00:31:28 +03:00
#if 0 // JPEG LS
if ( k = = 0 & & 2 * state - > drift < = - state - > count ) code = v ^ ( - 1 ) ;
else code = v ;
# else
code = v ^ ( ( 2 * state - > drift + state - > count ) > > 31 ) ;
# endif
2005-12-17 20:14:38 +02:00
2003-06-14 00:31:28 +03:00
//printf("v:%d/%d bias:%d error:%d drift:%d count:%d k:%d\n", v, code, state->bias, state->error_sum, state->drift, state->count, k);
2004-09-10 22:40:55 +03:00
set_sr_golomb ( pb , code , k , 12 , bits ) ;
2003-06-14 00:31:28 +03:00
update_vlc_state ( state , v ) ;
}
2003-11-01 19:38:25 +02:00
static inline int get_vlc_symbol ( GetBitContext * gb , VlcState * const state , int bits ) {
2003-06-14 00:31:28 +03:00
int k , i , v , ret ;
i = state - > count ;
k = 0 ;
while ( i < state - > error_sum ) { //FIXME optimize
k + + ;
i + = i ;
}
2003-07-13 14:06:45 +03:00
assert ( k < = 8 ) ;
2004-09-10 22:40:55 +03:00
v = get_sr_golomb ( gb , k , 12 , bits ) ;
2003-06-14 00:31:28 +03:00
//printf("v:%d bias:%d error:%d drift:%d count:%d k:%d", v, state->bias, state->error_sum, state->drift, state->count, k);
2003-07-13 14:06:45 +03:00
2003-06-14 00:31:28 +03:00
#if 0 // JPEG LS
if ( k = = 0 & & 2 * state - > drift < = - state - > count ) v ^ = ( - 1 ) ;
# else
v ^ = ( ( 2 * state - > drift + state - > count ) > > 31 ) ;
2003-06-09 05:24:51 +03:00
# endif
2003-11-01 19:38:25 +02:00
ret = fold ( v + state - > bias , bits ) ;
2005-12-17 20:14:38 +02:00
2003-06-14 00:31:28 +03:00
update_vlc_state ( state , v ) ;
//printf("final: %d\n", ret);
return ret ;
}
2009-01-14 01:44:16 +02:00
# if CONFIG_FFV1_ENCODER
2011-04-29 17:08:20 +03:00
static av_always_inline int encode_line ( FFV1Context * s , int w ,
2012-04-13 03:11:03 +03:00
int16_t * sample [ 3 ] ,
2011-04-29 17:08:20 +03:00
int plane_index , int bits )
{
2003-11-01 19:38:25 +02:00
PlaneContext * const p = & s - > plane [ plane_index ] ;
2004-10-31 12:08:50 +02:00
RangeCoder * const c = & s - > c ;
2003-11-01 19:38:25 +02:00
int x ;
int run_index = s - > run_index ;
int run_count = 0 ;
int run_mode = 0 ;
2005-01-12 02:16:25 +02:00
if ( s - > ac ) {
if ( c - > bytestream_end - c - > bytestream < w * 20 ) {
av_log ( s - > avctx , AV_LOG_ERROR , " encoded frame too large \n " ) ;
return - 1 ;
}
} 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 - 1 ;
}
}
2003-11-01 19:38:25 +02:00
for ( x = 0 ; x < w ; x + + ) {
int diff , context ;
2005-12-17 20:14:38 +02:00
2010-10-15 01:03:41 +03:00
context = get_context ( p , sample [ 0 ] + x , sample [ 1 ] + x , sample [ 2 ] + x ) ;
2004-05-02 22:18:20 +03:00
diff = sample [ 0 ] [ x ] - predict ( sample [ 0 ] + x , sample [ 1 ] + x ) ;
2003-06-14 00:31:28 +03:00
2003-11-01 19:38:25 +02:00
if ( context < 0 ) {
context = - context ;
diff = - diff ;
}
diff = fold ( diff , bits ) ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
if ( s - > ac ) {
2010-10-27 02:00:49 +03:00
if ( s - > flags & CODEC_FLAG_PASS1 ) {
2010-10-27 02:01:07 +03:00
put_symbol_inline ( c , p - > state [ context ] , diff , 1 , s - > rc_stat , s - > rc_stat2 [ p - > quant_table_index ] [ context ] ) ;
2010-10-27 02:00:49 +03:00
} else {
2010-10-27 02:01:07 +03:00
put_symbol_inline ( c , p - > state [ context ] , diff , 1 , NULL , NULL ) ;
2010-10-27 02:00:49 +03:00
}
2003-11-01 19:38:25 +02:00
} else {
if ( context = = 0 ) run_mode = 1 ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
if ( run_mode ) {
if ( diff ) {
2008-06-26 19:39:21 +03:00
while ( run_count > = 1 < < ff_log2_run [ run_index ] ) {
run_count - = 1 < < ff_log2_run [ run_index ] ;
2003-11-01 19:38:25 +02:00
run_index + + ;
put_bits ( & s - > pb , 1 , 1 ) ;
}
2005-12-17 20:14:38 +02:00
2008-06-26 19:39:21 +03:00
put_bits ( & s - > pb , 1 + ff_log2_run [ run_index ] , run_count ) ;
2003-11-01 19:38:25 +02:00
if ( run_index ) run_index - - ;
run_count = 0 ;
run_mode = 0 ;
if ( diff > 0 ) diff - - ;
} else {
run_count + + ;
}
}
2005-12-17 20:14:38 +02:00
2004-02-06 17:27:31 +02:00
// printf("count:%d index:%d, mode:%d, x:%d y:%d pos:%d\n", run_count, run_index, run_mode, x, y, (int)put_bits_count(&s->pb));
2003-11-01 19:38:25 +02:00
if ( run_mode = = 0 )
put_vlc_symbol ( & s - > pb , & p - > vlc_state [ context ] , diff , bits ) ;
}
}
if ( run_mode ) {
2008-06-26 19:39:21 +03:00
while ( run_count > = 1 < < ff_log2_run [ run_index ] ) {
run_count - = 1 < < ff_log2_run [ run_index ] ;
2003-11-01 19:38:25 +02:00
run_index + + ;
put_bits ( & s - > pb , 1 , 1 ) ;
}
if ( run_count )
put_bits ( & s - > pb , 1 , 1 ) ;
}
s - > run_index = run_index ;
2005-12-17 20:14:38 +02:00
2005-01-12 02:16:25 +02:00
return 0 ;
2003-11-01 19:38:25 +02:00
}
2003-06-14 00:31:28 +03:00
2003-06-09 05:24:51 +03:00
static void encode_plane ( FFV1Context * s , uint8_t * src , int w , int h , int stride , int plane_index ) {
2004-05-02 22:18:20 +03:00
int x , y , i ;
2004-08-03 04:07:19 +03:00
const int ring_size = s - > avctx - > context_model ? 3 : 2 ;
2011-04-29 17:08:20 +03:00
int16_t * sample [ 3 ] ;
2003-11-01 19:38:25 +02:00
s - > run_index = 0 ;
2005-12-17 20:14:38 +02:00
2010-06-26 18:53:25 +03:00
memset ( s - > sample_buffer , 0 , ring_size * ( w + 6 ) * sizeof ( * s - > sample_buffer ) ) ;
2005-12-17 20:14:38 +02:00
2003-06-09 05:24:51 +03:00
for ( y = 0 ; y < h ; y + + ) {
2004-05-02 22:18:20 +03:00
for ( i = 0 ; i < ring_size ; i + + )
2010-06-26 18:53:25 +03:00
sample [ i ] = s - > sample_buffer + ( w + 6 ) * ( ( h + i - y ) % ring_size ) + 3 ;
2005-12-17 20:14:38 +02:00
2004-05-02 22:18:20 +03:00
sample [ 0 ] [ - 1 ] = sample [ 1 ] [ 0 ] ;
sample [ 1 ] [ w ] = sample [ 1 ] [ w - 1 ] ;
2003-11-01 19:38:25 +02:00
//{START_TIMER
2012-02-12 01:45:04 +03:00
if ( s - > bits_per_raw_sample < = 8 ) {
2009-04-24 16:38:28 +03:00
for ( x = 0 ; x < w ; x + + ) {
sample [ 0 ] [ x ] = src [ x + stride * y ] ;
}
encode_line ( s , w , sample , plane_index , 8 ) ;
2009-04-24 07:10:32 +03:00
} else {
2011-05-08 19:51:55 +03:00
if ( s - > packed_at_lsb ) {
for ( x = 0 ; x < w ; x + + ) {
sample [ 0 ] [ x ] = ( ( uint16_t * ) ( src + stride * y ) ) [ x ] ;
}
} else {
for ( x = 0 ; x < w ; x + + ) {
2012-02-12 01:45:04 +03:00
sample [ 0 ] [ x ] = ( ( uint16_t * ) ( src + stride * y ) ) [ x ] > > ( 16 - s - > bits_per_raw_sample ) ;
2011-05-08 19:51:55 +03:00
}
2009-04-24 07:10:32 +03:00
}
2012-02-12 01:45:04 +03:00
encode_line ( s , w , sample , plane_index , s - > bits_per_raw_sample ) ;
2009-04-24 07:10:32 +03:00
}
2003-11-01 19:38:25 +02:00
//STOP_TIMER("encode line")}
}
}
2003-06-09 05:24:51 +03:00
2003-11-01 19:38:25 +02:00
static void encode_rgb_frame ( FFV1Context * s , uint32_t * src , int w , int h , int stride ) {
2004-05-02 22:18:20 +03:00
int x , y , p , i ;
2004-08-03 04:07:19 +03:00
const int ring_size = s - > avctx - > context_model ? 3 : 2 ;
2011-11-28 19:38:04 +03:00
int16_t * sample [ 4 ] [ 3 ] ;
2003-11-01 19:38:25 +02:00
s - > run_index = 0 ;
2005-12-17 20:14:38 +02:00
2011-11-28 19:38:04 +03:00
memset ( s - > sample_buffer , 0 , ring_size * 4 * ( w + 6 ) * sizeof ( * s - > sample_buffer ) ) ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
for ( y = 0 ; y < h ; y + + ) {
2004-05-02 22:18:20 +03:00
for ( i = 0 ; i < ring_size ; i + + )
2011-11-28 19:38:04 +03:00
for ( p = 0 ; p < 4 ; p + + )
2010-06-26 18:53:25 +03:00
sample [ p ] [ i ] = s - > sample_buffer + p * ring_size * ( w + 6 ) + ( ( h + i - y ) % ring_size ) * ( w + 6 ) + 3 ;
2004-05-02 22:18:20 +03:00
2003-06-09 05:24:51 +03:00
for ( x = 0 ; x < w ; x + + ) {
2011-11-28 19:38:04 +03:00
unsigned v = src [ x + stride * y ] ;
2003-11-01 19:38:25 +02:00
int b = v & 0xFF ;
int g = ( v > > 8 ) & 0xFF ;
int r = ( v > > 16 ) & 0xFF ;
2011-11-28 19:38:04 +03:00
int a = v > > 24 ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
b - = g ;
r - = g ;
g + = ( b + r ) > > 2 ;
b + = 0x100 ;
r + = 0x100 ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
// assert(g>=0 && b>=0 && r>=0);
// assert(g<256 && b<512 && r<512);
sample [ 0 ] [ 0 ] [ x ] = g ;
sample [ 1 ] [ 0 ] [ x ] = b ;
sample [ 2 ] [ 0 ] [ x ] = r ;
2011-11-28 19:38:04 +03:00
sample [ 3 ] [ 0 ] [ x ] = a ;
2003-06-14 00:31:28 +03:00
}
2011-11-28 19:39:25 +03:00
for ( p = 0 ; p < 3 + s - > transparency ; p + + ) {
2004-05-02 22:18:20 +03:00
sample [ p ] [ 0 ] [ - 1 ] = sample [ p ] [ 1 ] [ 0 ] ;
sample [ p ] [ 1 ] [ w ] = sample [ p ] [ 1 ] [ w - 1 ] ;
2011-11-28 19:38:04 +03:00
encode_line ( s , w , sample [ p ] , ( p + 1 ) / 2 , 9 ) ;
2003-06-09 05:24:51 +03:00
}
}
}
2004-10-31 12:08:50 +02:00
static void write_quant_table ( RangeCoder * c , int16_t * quant_table ) {
2003-06-09 05:24:51 +03:00
int last = 0 ;
int i ;
2004-10-31 12:08:50 +02:00
uint8_t state [ CONTEXT_SIZE ] ;
memset ( state , 128 , sizeof ( state ) ) ;
2003-06-09 05:24:51 +03:00
2003-06-14 00:31:28 +03:00
for ( i = 1 ; i < 128 ; i + + ) {
2003-06-09 05:24:51 +03:00
if ( quant_table [ i ] ! = quant_table [ i - 1 ] ) {
2004-10-31 14:22:00 +02:00
put_symbol ( c , state , i - last - 1 , 0 ) ;
2003-06-09 05:24:51 +03:00
last = i ;
}
}
2004-10-31 14:22:00 +02:00
put_symbol ( c , state , i - last - 1 , 0 ) ;
2003-06-09 05:24:51 +03:00
}
2010-10-19 20:26:27 +03:00
static void write_quant_tables ( RangeCoder * c , int16_t quant_table [ MAX_CONTEXT_INPUTS ] [ 256 ] ) {
2010-10-11 00:04:34 +03:00
int i ;
for ( i = 0 ; i < 5 ; i + + )
write_quant_table ( c , quant_table [ i ] ) ;
}
2003-06-09 05:24:51 +03:00
static void write_header ( FFV1Context * f ) {
2004-10-31 12:08:50 +02:00
uint8_t state [ CONTEXT_SIZE ] ;
2010-10-15 05:05:06 +03:00
int i , j ;
2010-10-15 01:03:32 +03:00
RangeCoder * const c = & f - > slice_context [ 0 ] - > c ;
2003-06-09 05:24:51 +03:00
2004-10-31 12:08:50 +02:00
memset ( state , 128 , sizeof ( state ) ) ;
2005-12-17 20:14:38 +02:00
2010-10-11 00:04:41 +03:00
if ( f - > version < 2 ) {
2010-10-15 01:10:50 +03:00
put_symbol ( c , state , f - > version , 0 ) ;
put_symbol ( c , state , f - > ac , 0 ) ;
if ( f - > ac > 1 ) {
for ( i = 1 ; i < 256 ; i + + ) {
2010-10-24 15:31:00 +03:00
put_symbol ( c , state , f - > state_transition [ i ] - c - > one_state [ i ] , 1 ) ;
2010-10-15 01:10:50 +03:00
}
2010-04-01 21:51:08 +03:00
}
2010-10-15 01:10:50 +03:00
put_symbol ( c , state , f - > colorspace , 0 ) ; //YUV cs type
if ( f - > version > 0 )
2012-02-12 01:45:04 +03:00
put_symbol ( c , state , f - > bits_per_raw_sample , 0 ) ;
2012-02-06 21:23:44 +03:00
put_rac ( c , state , f - > chroma_planes ) ;
2012-02-02 20:49:10 +03:00
put_symbol ( c , state , f - > chroma_h_shift , 0 ) ;
put_symbol ( c , state , f - > chroma_v_shift , 0 ) ;
2011-11-28 19:38:04 +03:00
put_rac ( c , state , f - > transparency ) ;
2010-10-15 01:10:50 +03:00
write_quant_tables ( c , f - > quant_table ) ;
2012-04-25 16:01:32 +03:00
} else if ( f - > version < 3 ) {
2010-10-15 05:05:06 +03:00
put_symbol ( c , state , f - > slice_count , 0 ) ;
for ( i = 0 ; i < f - > slice_count ; i + + ) {
FFV1Context * fs = f - > slice_context [ i ] ;
put_symbol ( c , state , ( fs - > slice_x + 1 ) * f - > num_h_slices / f - > width , 0 ) ;
put_symbol ( c , state , ( fs - > slice_y + 1 ) * f - > num_v_slices / f - > height , 0 ) ;
put_symbol ( c , state , ( fs - > slice_width + 1 ) * f - > num_h_slices / f - > width - 1 , 0 ) ;
put_symbol ( c , state , ( fs - > slice_height + 1 ) * f - > num_v_slices / f - > height - 1 , 0 ) ;
2010-10-26 04:59:03 +03:00
for ( j = 0 ; j < f - > plane_count ; j + + ) {
put_symbol ( c , state , f - > plane [ j ] . quant_table_index , 0 ) ;
av_assert0 ( f - > plane [ j ] . quant_table_index = = f - > avctx - > context_model ) ;
}
2010-10-15 05:05:06 +03:00
}
2010-10-11 00:04:41 +03:00
}
2003-06-09 05:24:51 +03:00
}
2008-09-03 15:33:21 +03:00
# endif /* CONFIG_FFV1_ENCODER */
2003-06-09 05:24:51 +03:00
2008-03-21 05:11:20 +02:00
static av_cold int common_init ( AVCodecContext * avctx ) {
2003-06-09 05:24:51 +03:00
FFV1Context * s = avctx - > priv_data ;
s - > avctx = avctx ;
s - > flags = avctx - > flags ;
2005-12-17 20:14:38 +02:00
2011-05-08 20:26:22 +03:00
avcodec_get_frame_defaults ( & s - > picture ) ;
2012-02-15 13:06:44 +03:00
ff_dsputil_init ( & s - > dsp , avctx ) ;
2005-12-17 20:14:38 +02:00
2009-04-17 17:59:04 +03:00
s - > width = avctx - > width ;
s - > height = avctx - > height ;
2005-12-17 20:14:38 +02:00
2009-04-17 17:59:04 +03:00
assert ( s - > width & & s - > height ) ;
2010-10-15 01:03:32 +03:00
//defaults
s - > num_h_slices = 1 ;
s - > num_v_slices = 1 ;
2003-06-09 05:24:51 +03:00
2010-06-26 18:53:25 +03:00
2003-06-09 05:24:51 +03:00
return 0 ;
}
2012-04-20 15:50:07 +03:00
static int init_slice_state ( FFV1Context * f , FFV1Context * fs ) {
int j ;
2010-10-15 01:03:32 +03:00
2011-11-28 19:38:04 +03:00
fs - > plane_count = f - > plane_count ;
fs - > transparency = f - > transparency ;
2010-10-15 01:03:32 +03:00
for ( j = 0 ; j < f - > plane_count ; j + + ) {
PlaneContext * const p = & fs - > plane [ j ] ;
if ( fs - > ac ) {
if ( ! p - > state ) p - > state = av_malloc ( CONTEXT_SIZE * p - > context_count * sizeof ( uint8_t ) ) ;
if ( ! p - > state )
return AVERROR ( ENOMEM ) ;
} else {
if ( ! p - > vlc_state ) p - > vlc_state = av_malloc ( p - > context_count * sizeof ( VlcState ) ) ;
if ( ! p - > vlc_state )
return AVERROR ( ENOMEM ) ;
}
}
if ( fs - > ac > 1 ) {
//FIXME only redo if state_transition changed
for ( j = 1 ; j < 256 ; j + + ) {
2012-05-23 13:04:10 +03:00
fs - > c . one_state [ j ] = f - > state_transition [ j ] ;
2010-10-15 01:03:32 +03:00
fs - > c . zero_state [ 256 - j ] = 256 - fs - > c . one_state [ j ] ;
}
}
return 0 ;
}
2012-04-20 15:50:07 +03:00
static int init_slices_state ( FFV1Context * f ) {
int i ;
for ( i = 0 ; i < f - > slice_count ; i + + ) {
FFV1Context * fs = f - > slice_context [ i ] ;
if ( init_slice_state ( f , fs ) < 0 )
return - 1 ;
}
return 0 ;
}
2010-10-15 01:03:32 +03:00
static av_cold int init_slice_contexts ( FFV1Context * f ) {
int i ;
f - > slice_count = f - > num_h_slices * f - > num_v_slices ;
for ( i = 0 ; i < f - > slice_count ; i + + ) {
FFV1Context * fs = av_mallocz ( sizeof ( * fs ) ) ;
int sx = i % f - > num_h_slices ;
int sy = i / f - > num_h_slices ;
int sxs = f - > avctx - > width * sx / f - > num_h_slices ;
int sxe = f - > avctx - > width * ( sx + 1 ) / f - > num_h_slices ;
int sys = f - > avctx - > height * sy / f - > num_v_slices ;
int sye = f - > avctx - > height * ( sy + 1 ) / f - > num_v_slices ;
f - > slice_context [ i ] = fs ;
memcpy ( fs , f , sizeof ( * fs ) ) ;
2010-10-27 02:01:17 +03:00
memset ( fs - > rc_stat2 , 0 , sizeof ( fs - > rc_stat2 ) ) ;
2010-10-15 01:03:32 +03:00
fs - > slice_width = sxe - sxs ;
fs - > slice_height = sye - sys ;
fs - > slice_x = sxs ;
fs - > slice_y = sys ;
2011-11-28 19:38:04 +03:00
fs - > sample_buffer = av_malloc ( 3 * 4 * ( fs - > width + 6 ) * sizeof ( * fs - > sample_buffer ) ) ;
2010-10-15 01:03:32 +03:00
if ( ! fs - > sample_buffer )
return AVERROR ( ENOMEM ) ;
}
return 0 ;
}
2010-10-27 02:01:11 +03:00
static int allocate_initial_states ( FFV1Context * f ) {
int i ;
for ( i = 0 ; i < f - > quant_table_count ; i + + ) {
f - > initial_states [ i ] = av_malloc ( f - > context_count [ i ] * sizeof ( * f - > initial_states [ i ] ) ) ;
if ( ! f - > initial_states [ i ] )
return AVERROR ( ENOMEM ) ;
memset ( f - > initial_states [ i ] , 128 , f - > context_count [ i ] * sizeof ( * f - > initial_states [ i ] ) ) ;
}
return 0 ;
}
2010-10-17 00:31:16 +03:00
# if CONFIG_FFV1_ENCODER
static int write_extra_header ( FFV1Context * f ) {
RangeCoder * const c = & f - > c ;
uint8_t state [ CONTEXT_SIZE ] ;
2010-10-27 02:01:14 +03:00
int i , j , k ;
uint8_t state2 [ 32 ] [ CONTEXT_SIZE ] ;
2012-04-20 15:47:24 +03:00
unsigned v ;
2010-10-27 02:01:14 +03:00
memset ( state2 , 128 , sizeof ( state2 ) ) ;
2010-10-17 00:31:16 +03:00
memset ( state , 128 , sizeof ( state ) ) ;
2010-10-27 02:01:14 +03:00
f - > avctx - > extradata = av_malloc ( f - > avctx - > extradata_size = 10000 + ( 11 * 11 * 5 * 5 * 5 + 11 * 11 * 11 ) * 32 ) ;
2010-10-17 00:31:16 +03:00
ff_init_range_encoder ( c , f - > avctx - > extradata , f - > avctx - > extradata_size ) ;
ff_build_rac_states ( c , 0.05 * ( 1LL < < 32 ) , 256 - 8 ) ;
put_symbol ( c , state , f - > version , 0 ) ;
2012-04-08 15:20:17 +03:00
if ( f - > version > 2 )
put_symbol ( c , state , f - > minor_version , 0 ) ;
2010-10-17 00:31:16 +03:00
put_symbol ( c , state , f - > ac , 0 ) ;
if ( f - > ac > 1 ) {
for ( i = 1 ; i < 256 ; i + + ) {
2010-10-24 15:31:00 +03:00
put_symbol ( c , state , f - > state_transition [ i ] - c - > one_state [ i ] , 1 ) ;
2010-10-17 00:31:16 +03:00
}
}
put_symbol ( c , state , f - > colorspace , 0 ) ; //YUV cs type
2012-02-12 01:45:04 +03:00
put_symbol ( c , state , f - > bits_per_raw_sample , 0 ) ;
2012-02-06 21:23:44 +03:00
put_rac ( c , state , f - > chroma_planes ) ;
2012-02-02 20:49:10 +03:00
put_symbol ( c , state , f - > chroma_h_shift , 0 ) ;
put_symbol ( c , state , f - > chroma_v_shift , 0 ) ;
2011-11-28 19:38:04 +03:00
put_rac ( c , state , f - > transparency ) ;
2010-10-17 00:31:16 +03:00
put_symbol ( c , state , f - > num_h_slices - 1 , 0 ) ;
put_symbol ( c , state , f - > num_v_slices - 1 , 0 ) ;
put_symbol ( c , state , f - > quant_table_count , 0 ) ;
for ( i = 0 ; i < f - > quant_table_count ; i + + )
write_quant_tables ( c , f - > quant_tables [ i ] ) ;
2010-10-27 02:01:14 +03:00
for ( i = 0 ; i < f - > quant_table_count ; i + + ) {
for ( j = 0 ; j < f - > context_count [ i ] * CONTEXT_SIZE ; j + + )
if ( f - > initial_states [ i ] & & f - > initial_states [ i ] [ 0 ] [ j ] ! = 128 )
break ;
if ( j < f - > context_count [ i ] * CONTEXT_SIZE ) {
put_rac ( c , state , 1 ) ;
for ( j = 0 ; j < f - > context_count [ i ] ; j + + ) {
for ( k = 0 ; k < CONTEXT_SIZE ; k + + ) {
int pred = j ? f - > initial_states [ i ] [ j - 1 ] [ k ] : 128 ;
put_symbol ( c , state2 [ k ] , ( int8_t ) ( f - > initial_states [ i ] [ j ] [ k ] - pred ) , 1 ) ;
}
}
} else {
put_rac ( c , state , 0 ) ;
}
}
2012-04-20 16:08:28 +03:00
if ( f - > version > 2 ) {
put_symbol ( c , state , f - > ec , 0 ) ;
}
2010-10-17 00:31:16 +03:00
f - > avctx - > extradata_size = ff_rac_terminate ( c ) ;
2012-04-20 15:47:24 +03:00
v = av_crc ( av_crc_get_table ( AV_CRC_32_IEEE ) , 0 , f - > avctx - > extradata , f - > avctx - > extradata_size ) ;
AV_WL32 ( f - > avctx - > extradata + f - > avctx - > extradata_size , v ) ;
f - > avctx - > extradata_size + = 4 ;
2010-10-17 00:31:16 +03:00
return 0 ;
}
2010-10-24 19:55:42 +03:00
static int sort_stt ( FFV1Context * s , uint8_t stt [ 256 ] ) {
int i , i2 , changed , print = 0 ;
do {
changed = 0 ;
for ( i = 12 ; i < 244 ; i + + ) {
for ( i2 = i + 1 ; i2 < 245 & & i2 < i + 4 ; i2 + + ) {
# define COST(old, new) \
s - > rc_stat [ old ] [ 0 ] * - log2 ( ( 256 - ( new ) ) / 256.0 ) \
+ s - > rc_stat [ old ] [ 1 ] * - log2 ( ( new ) / 256.0 )
# define COST2(old, new) \
COST ( old , new ) \
+ COST ( 256 - ( old ) , 256 - ( new ) )
double size0 = COST2 ( i , i ) + COST2 ( i2 , i2 ) ;
double sizeX = COST2 ( i , i2 ) + COST2 ( i2 , i ) ;
if ( sizeX < size0 & & i ! = 128 & & i2 ! = 128 ) {
int j ;
FFSWAP ( int , stt [ i ] , stt [ i2 ] ) ;
FFSWAP ( int , s - > rc_stat [ i ] [ 0 ] , s - > rc_stat [ i2 ] [ 0 ] ) ;
FFSWAP ( int , s - > rc_stat [ i ] [ 1 ] , s - > rc_stat [ i2 ] [ 1 ] ) ;
if ( i ! = 256 - i2 ) {
FFSWAP ( int , stt [ 256 - i ] , stt [ 256 - i2 ] ) ;
FFSWAP ( int , s - > rc_stat [ 256 - i ] [ 0 ] , s - > rc_stat [ 256 - i2 ] [ 0 ] ) ;
FFSWAP ( int , s - > rc_stat [ 256 - i ] [ 1 ] , s - > rc_stat [ 256 - i2 ] [ 1 ] ) ;
}
for ( j = 1 ; j < 256 ; j + + ) {
if ( stt [ j ] = = i ) stt [ j ] = i2 ;
else if ( stt [ j ] = = i2 ) stt [ j ] = i ;
if ( i ! = 256 - i2 ) {
if ( stt [ 256 - j ] = = 256 - i ) stt [ 256 - j ] = 256 - i2 ;
else if ( stt [ 256 - j ] = = 256 - i2 ) stt [ 256 - j ] = 256 - i ;
}
}
print = changed = 1 ;
}
}
}
} while ( changed ) ;
return print ;
}
2008-03-21 05:11:20 +02:00
static av_cold int encode_init ( AVCodecContext * avctx )
2003-06-09 05:24:51 +03:00
{
FFV1Context * s = avctx - > priv_data ;
2010-10-27 02:01:17 +03:00
int i , j , k , m ;
2003-06-09 05:24:51 +03:00
common_init ( avctx ) ;
2005-12-17 20:14:38 +02:00
2003-06-09 05:24:51 +03:00
s - > version = 0 ;
2012-04-08 17:46:36 +03:00
if ( ( avctx - > flags & ( CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2 ) ) | | avctx - > slices > 1 )
s - > version = FFMAX ( s - > version , 2 ) ;
2012-04-25 00:05:16 +03:00
if ( avctx - > level = = 3 ) {
s - > version = 3 ;
2012-04-30 16:00:10 +03:00
}
if ( s - > ec < 0 ) {
s - > ec = ( s - > version > = 3 ) ;
2012-04-25 00:05:16 +03:00
}
2012-04-08 17:46:36 +03:00
if ( s - > version > = 2 & & avctx - > strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL ) {
av_log ( avctx , AV_LOG_ERROR , " Version 2 needed for requested features but version 2 is experimental and not enabled \n " ) ;
return - 1 ;
}
2010-04-01 21:51:08 +03:00
s - > ac = avctx - > coder_type ? 2 : 0 ;
2005-12-17 20:14:38 +02:00
2010-10-24 15:31:00 +03:00
if ( s - > ac > 1 )
for ( i = 1 ; i < 256 ; i + + )
s - > state_transition [ i ] = ver2_state [ i ] ;
2011-11-28 19:38:04 +03:00
s - > plane_count = 3 ;
2003-06-09 05:24:51 +03:00
switch ( avctx - > pix_fmt ) {
2012-03-07 02:16:39 +03:00
case PIX_FMT_YUV444P9 :
case PIX_FMT_YUV422P9 :
2011-05-12 18:46:02 +03:00
case PIX_FMT_YUV420P9 :
2012-02-12 01:45:04 +03:00
if ( ! avctx - > bits_per_raw_sample )
s - > bits_per_raw_sample = 9 ;
2012-03-07 02:16:40 +03:00
case PIX_FMT_YUV444P10 :
2011-05-08 19:51:55 +03:00
case PIX_FMT_YUV420P10 :
case PIX_FMT_YUV422P10 :
s - > packed_at_lsb = 1 ;
2012-02-12 01:45:04 +03:00
if ( ! avctx - > bits_per_raw_sample & & ! s - > bits_per_raw_sample )
s - > bits_per_raw_sample = 10 ;
2012-02-06 21:23:44 +03:00
case PIX_FMT_GRAY16 :
2009-04-24 07:10:32 +03:00
case PIX_FMT_YUV444P16 :
case PIX_FMT_YUV422P16 :
case PIX_FMT_YUV420P16 :
2012-02-12 01:45:04 +03:00
if ( ! avctx - > bits_per_raw_sample & & ! s - > bits_per_raw_sample ) {
s - > bits_per_raw_sample = 16 ;
} else if ( ! s - > bits_per_raw_sample ) {
s - > bits_per_raw_sample = avctx - > bits_per_raw_sample ;
}
if ( s - > bits_per_raw_sample < = 8 ) {
2009-08-14 19:41:21 +03:00
av_log ( avctx , AV_LOG_ERROR , " bits_per_raw_sample invalid \n " ) ;
2009-04-24 07:10:32 +03:00
return - 1 ;
}
2010-03-22 23:12:31 +02:00
if ( ! s - > ac ) {
av_log ( avctx , AV_LOG_ERROR , " bits_per_raw_sample of more than 8 needs -coder 1 currently \n " ) ;
return - 1 ;
}
2010-10-11 00:04:38 +03:00
s - > version = FFMAX ( s - > version , 1 ) ;
2012-02-14 08:39:03 +03:00
case PIX_FMT_GRAY8 :
2003-06-09 05:24:51 +03:00
case PIX_FMT_YUV444P :
2012-02-01 04:54:17 +03:00
case PIX_FMT_YUV440P :
2003-06-09 05:24:51 +03:00
case PIX_FMT_YUV422P :
case PIX_FMT_YUV420P :
case PIX_FMT_YUV411P :
case PIX_FMT_YUV410P :
2012-02-14 08:39:03 +03:00
s - > chroma_planes = av_pix_fmt_descriptors [ avctx - > pix_fmt ] . nb_components < 3 ? 0 : 1 ;
2003-11-01 19:38:25 +02:00
s - > colorspace = 0 ;
break ;
2012-01-31 23:21:34 +03:00
case PIX_FMT_YUVA444P :
2012-05-08 09:49:36 +03:00
case PIX_FMT_YUVA422P :
2012-01-31 23:18:21 +03:00
case PIX_FMT_YUVA420P :
2012-02-06 21:23:44 +03:00
s - > chroma_planes = 1 ;
2012-01-31 23:18:21 +03:00
s - > colorspace = 0 ;
s - > transparency = 1 ;
break ;
2007-02-07 03:48:09 +02:00
case PIX_FMT_RGB32 :
2003-11-01 19:38:25 +02:00
s - > colorspace = 1 ;
2011-11-28 19:38:04 +03:00
s - > transparency = 1 ;
2003-06-09 05:24:51 +03:00
break ;
2011-11-28 19:39:25 +03:00
case PIX_FMT_0RGB32 :
s - > colorspace = 1 ;
break ;
2003-06-09 05:24:51 +03:00
default :
2003-11-03 15:26:22 +02:00
av_log ( avctx , AV_LOG_ERROR , " format not supported \n " ) ;
2003-06-09 05:24:51 +03:00
return - 1 ;
}
2012-02-15 21:34:08 +03:00
if ( s - > transparency ) {
av_log ( avctx , AV_LOG_WARNING , " Storing alpha plane, this will require a recent FFV1 decoder to playback! \n " ) ;
}
2012-03-20 02:29:34 +03:00
if ( avctx - > context_model > 1U ) {
av_log ( avctx , AV_LOG_ERROR , " Invalid context model %d, valid values are 0 and 1 \n " , avctx - > context_model ) ;
return AVERROR ( EINVAL ) ;
}
2012-02-15 21:34:08 +03:00
2012-02-12 01:42:58 +03:00
for ( i = 0 ; i < 256 ; i + + ) {
s - > quant_table_count = 2 ;
2012-02-12 01:45:04 +03:00
if ( s - > bits_per_raw_sample < = 8 ) {
2012-02-12 01:42:58 +03:00
s - > quant_tables [ 0 ] [ 0 ] [ i ] = quant11 [ i ] ;
s - > quant_tables [ 0 ] [ 1 ] [ i ] = 11 * quant11 [ i ] ;
s - > quant_tables [ 0 ] [ 2 ] [ i ] = 11 * 11 * quant11 [ i ] ;
s - > quant_tables [ 1 ] [ 0 ] [ i ] = quant11 [ i ] ;
s - > quant_tables [ 1 ] [ 1 ] [ i ] = 11 * quant11 [ i ] ;
s - > quant_tables [ 1 ] [ 2 ] [ i ] = 11 * 11 * quant5 [ i ] ;
s - > quant_tables [ 1 ] [ 3 ] [ i ] = 5 * 11 * 11 * quant5 [ i ] ;
s - > quant_tables [ 1 ] [ 4 ] [ i ] = 5 * 5 * 11 * 11 * quant5 [ i ] ;
} else {
s - > quant_tables [ 0 ] [ 0 ] [ i ] = quant9_10bit [ i ] ;
s - > quant_tables [ 0 ] [ 1 ] [ i ] = 11 * quant9_10bit [ i ] ;
s - > quant_tables [ 0 ] [ 2 ] [ i ] = 11 * 11 * quant9_10bit [ i ] ;
s - > quant_tables [ 1 ] [ 0 ] [ i ] = quant9_10bit [ i ] ;
s - > quant_tables [ 1 ] [ 1 ] [ i ] = 11 * quant9_10bit [ i ] ;
s - > quant_tables [ 1 ] [ 2 ] [ i ] = 11 * 11 * quant5_10bit [ i ] ;
s - > quant_tables [ 1 ] [ 3 ] [ i ] = 5 * 11 * 11 * quant5_10bit [ i ] ;
s - > quant_tables [ 1 ] [ 4 ] [ i ] = 5 * 5 * 11 * 11 * quant5_10bit [ i ] ;
}
}
s - > context_count [ 0 ] = ( 11 * 11 * 11 + 1 ) / 2 ;
s - > context_count [ 1 ] = ( 11 * 11 * 5 * 5 * 5 + 1 ) / 2 ;
memcpy ( s - > quant_table , s - > quant_tables [ avctx - > context_model ] , sizeof ( s - > quant_table ) ) ;
for ( i = 0 ; i < s - > plane_count ; i + + ) {
PlaneContext * const p = & s - > plane [ i ] ;
memcpy ( p - > quant_table , s - > quant_table , sizeof ( p - > quant_table ) ) ;
p - > quant_table_index = avctx - > context_model ;
p - > context_count = s - > context_count [ p - > quant_table_index ] ;
}
if ( allocate_initial_states ( s ) < 0 )
return AVERROR ( ENOMEM ) ;
avctx - > coded_frame = & s - > picture ;
2011-11-28 19:38:04 +03:00
if ( ! s - > transparency )
s - > plane_count = 2 ;
2003-11-01 19:38:25 +02:00
avcodec_get_chroma_sub_sample ( avctx - > pix_fmt , & s - > chroma_h_shift , & s - > chroma_v_shift ) ;
2003-06-09 05:24:51 +03:00
s - > picture_number = 0 ;
2005-12-17 20:14:38 +02:00
2010-10-27 02:01:17 +03:00
if ( avctx - > flags & ( CODEC_FLAG_PASS1 | CODEC_FLAG_PASS2 ) ) {
for ( i = 0 ; i < s - > quant_table_count ; i + + ) {
s - > rc_stat2 [ i ] = av_mallocz ( s - > context_count [ i ] * sizeof ( * s - > rc_stat2 [ i ] ) ) ;
if ( ! s - > rc_stat2 [ i ] )
return AVERROR ( ENOMEM ) ;
}
}
2010-10-24 15:31:09 +03:00
if ( avctx - > stats_in ) {
char * p = avctx - > stats_in ;
2010-10-28 15:15:47 +03:00
uint8_t best_state [ 256 ] [ 256 ] ;
2010-10-28 15:15:44 +03:00
int gob_count = 0 ;
2010-10-28 15:15:40 +03:00
char * next ;
2010-10-24 15:31:09 +03:00
2010-10-27 02:01:17 +03:00
av_assert0 ( s - > version > = 2 ) ;
2010-10-24 15:31:09 +03:00
for ( ; ; ) {
for ( j = 0 ; j < 256 ; j + + ) {
for ( i = 0 ; i < 2 ; i + + ) {
s - > rc_stat [ j ] [ i ] = strtol ( p , & next , 0 ) ;
if ( next = = p ) {
av_log ( avctx , AV_LOG_ERROR , " 2Pass file invalid at %d %d [%s] \n " , j , i , p ) ;
return - 1 ;
}
p = next ;
}
}
2010-10-27 02:01:17 +03:00
for ( i = 0 ; i < s - > quant_table_count ; i + + ) {
for ( j = 0 ; j < s - > context_count [ i ] ; j + + ) {
for ( k = 0 ; k < 32 ; k + + ) {
for ( m = 0 ; m < 2 ; m + + ) {
s - > rc_stat2 [ i ] [ j ] [ k ] [ m ] = strtol ( p , & next , 0 ) ;
if ( next = = p ) {
av_log ( avctx , AV_LOG_ERROR , " 2Pass file invalid at %d %d %d %d [%s] \n " , i , j , k , m , p ) ;
return - 1 ;
}
p = next ;
}
}
}
}
2010-10-28 15:15:44 +03:00
gob_count = strtol ( p , & next , 0 ) ;
if ( next = = p | | gob_count < 0 ) {
av_log ( avctx , AV_LOG_ERROR , " 2Pass file invalid \n " ) ;
return - 1 ;
}
p = next ;
2010-10-24 15:31:09 +03:00
while ( * p = = ' \n ' | | * p = = ' ' ) p + + ;
if ( p [ 0 ] = = 0 ) break ;
}
2010-10-24 19:55:42 +03:00
sort_stt ( s , s - > state_transition ) ;
2010-10-27 02:01:17 +03:00
2010-10-28 15:15:47 +03:00
find_best_state ( best_state , s - > state_transition ) ;
2010-10-27 02:01:17 +03:00
for ( i = 0 ; i < s - > quant_table_count ; i + + ) {
for ( j = 0 ; j < s - > context_count [ i ] ; j + + ) {
for ( k = 0 ; k < 32 ; k + + ) {
2010-10-28 15:15:47 +03:00
double p = 128 ;
2010-10-27 02:01:17 +03:00
if ( s - > rc_stat2 [ i ] [ j ] [ k ] [ 0 ] + s - > rc_stat2 [ i ] [ j ] [ k ] [ 1 ] ) {
2010-10-28 15:15:47 +03:00
p = 256.0 * s - > rc_stat2 [ i ] [ j ] [ k ] [ 1 ] / ( s - > rc_stat2 [ i ] [ j ] [ k ] [ 0 ] + s - > rc_stat2 [ i ] [ j ] [ k ] [ 1 ] ) ;
2010-10-27 02:01:17 +03:00
}
2010-10-28 15:15:47 +03:00
s - > initial_states [ i ] [ j ] [ k ] = best_state [ av_clip ( round ( p ) , 1 , 255 ) ] [ av_clip ( ( s - > rc_stat2 [ i ] [ j ] [ k ] [ 0 ] + s - > rc_stat2 [ i ] [ j ] [ k ] [ 1 ] ) / gob_count , 0 , 255 ) ] ;
2010-10-27 02:01:17 +03:00
}
}
}
2010-10-24 15:31:09 +03:00
}
2010-10-15 01:03:32 +03:00
if ( s - > version > 1 ) {
2012-04-08 18:03:38 +03:00
for ( s - > num_v_slices = 2 ; s - > num_v_slices < 9 ; s - > num_v_slices + + ) {
for ( s - > num_h_slices = s - > num_v_slices ; s - > num_h_slices < 2 * s - > num_v_slices ; s - > num_h_slices + + ) {
if ( avctx - > slices = = s - > num_h_slices * s - > num_v_slices & & avctx - > slices < = 64 )
goto slices_ok ;
}
}
2012-04-26 05:35:30 +03:00
av_log ( avctx , AV_LOG_ERROR , " Unsupported number %d of slices requested, please specify a supported number with -slices (ex:4,6,9,12,16, ...) \n " , avctx - > slices ) ;
2012-04-08 18:03:38 +03:00
return - 1 ;
slices_ok :
2010-10-11 00:04:41 +03:00
write_extra_header ( s ) ;
2010-10-15 01:03:32 +03:00
}
if ( init_slice_contexts ( s ) < 0 )
return - 1 ;
2012-04-20 15:50:07 +03:00
if ( init_slices_state ( s ) < 0 )
2010-10-15 01:03:32 +03:00
return - 1 ;
2010-10-11 00:04:41 +03:00
2010-10-27 02:01:17 +03:00
# define STATS_OUT_SIZE 1024*1024*6
2010-10-27 02:01:07 +03:00
if ( avctx - > flags & CODEC_FLAG_PASS1 ) {
2010-12-12 04:54:21 +02:00
avctx - > stats_out = av_mallocz ( STATS_OUT_SIZE ) ;
2010-10-27 02:01:07 +03:00
for ( i = 0 ; i < s - > quant_table_count ; i + + ) {
for ( j = 0 ; j < s - > slice_count ; j + + ) {
FFV1Context * sf = s - > slice_context [ j ] ;
av_assert0 ( ! sf - > rc_stat2 [ i ] ) ;
sf - > rc_stat2 [ i ] = av_mallocz ( s - > context_count [ i ] * sizeof ( * sf - > rc_stat2 [ i ] ) ) ;
if ( ! sf - > rc_stat2 [ i ] )
return AVERROR ( ENOMEM ) ;
}
}
}
2010-10-24 15:31:09 +03:00
2003-06-09 05:24:51 +03:00
return 0 ;
}
2008-09-03 15:33:21 +03:00
# endif /* CONFIG_FFV1_ENCODER */
2003-06-09 05:24:51 +03:00
2012-04-20 15:51:42 +03:00
static void clear_slice_state ( FFV1Context * f , FFV1Context * fs ) {
int i , j ;
2003-06-09 05:24:51 +03:00
2010-10-15 01:10:50 +03:00
for ( i = 0 ; i < f - > plane_count ; i + + ) {
PlaneContext * p = & fs - > plane [ i ] ;
2003-06-09 05:24:51 +03:00
2010-10-15 01:10:50 +03:00
p - > interlace_bit_state [ 0 ] = 128 ;
p - > interlace_bit_state [ 1 ] = 128 ;
2005-12-17 20:14:38 +02:00
2010-10-27 02:01:04 +03:00
if ( fs - > ac ) {
2010-10-27 02:01:11 +03:00
if ( f - > initial_states [ p - > quant_table_index ] ) {
memcpy ( p - > state , f - > initial_states [ p - > quant_table_index ] , CONTEXT_SIZE * p - > context_count ) ;
} else
2010-10-27 02:01:04 +03:00
memset ( p - > state , 128 , CONTEXT_SIZE * p - > context_count ) ;
} else {
2012-02-02 20:49:10 +03:00
for ( j = 0 ; j < p - > context_count ; j + + ) {
2010-10-15 01:10:50 +03:00
p - > vlc_state [ j ] . drift = 0 ;
p - > vlc_state [ j ] . error_sum = 4 ; //FFMAX((RANGE + 32)/64, 2);
p - > vlc_state [ j ] . bias = 0 ;
p - > vlc_state [ j ] . count = 1 ;
2012-02-02 20:49:10 +03:00
}
2003-06-14 00:31:28 +03:00
}
2003-06-10 02:55:16 +03:00
}
2012-04-20 15:51:42 +03:00
}
2009-01-14 01:44:16 +02:00
# if CONFIG_FFV1_ENCODER
2012-04-20 16:05:36 +03:00
static void encode_slice_header ( FFV1Context * f , FFV1Context * fs ) {
RangeCoder * c = & fs - > c ;
uint8_t state [ CONTEXT_SIZE ] ;
int j ;
memset ( state , 128 , sizeof ( state ) ) ;
put_symbol ( c , state , ( fs - > slice_x + 1 ) * f - > num_h_slices / f - > width , 0 ) ;
put_symbol ( c , state , ( fs - > slice_y + 1 ) * f - > num_v_slices / f - > height , 0 ) ;
put_symbol ( c , state , ( fs - > slice_width + 1 ) * f - > num_h_slices / f - > width - 1 , 0 ) ;
put_symbol ( c , state , ( fs - > slice_height + 1 ) * f - > num_v_slices / f - > height - 1 , 0 ) ;
for ( j = 0 ; j < f - > plane_count ; j + + ) {
put_symbol ( c , state , f - > plane [ j ] . quant_table_index , 0 ) ;
av_assert0 ( f - > plane [ j ] . quant_table_index = = f - > avctx - > context_model ) ;
}
if ( ! f - > picture . interlaced_frame ) put_symbol ( c , state , 3 , 0 ) ;
else put_symbol ( c , state , 1 + ! f - > picture . top_field_first , 0 ) ;
put_symbol ( c , state , f - > picture . sample_aspect_ratio . num , 0 ) ;
put_symbol ( c , state , f - > picture . sample_aspect_ratio . den , 0 ) ;
}
2010-10-15 01:03:32 +03:00
static int encode_slice ( AVCodecContext * c , void * arg ) {
FFV1Context * fs = * ( void * * ) arg ;
FFV1Context * f = fs - > avctx - > priv_data ;
int width = fs - > slice_width ;
int height = fs - > slice_height ;
int x = fs - > slice_x ;
int y = fs - > slice_y ;
AVFrame * const p = & f - > picture ;
2012-02-12 01:45:04 +03:00
const int ps = ( f - > bits_per_raw_sample > 8 ) + 1 ;
2010-10-15 01:03:32 +03:00
2012-04-25 19:02:43 +03:00
if ( p - > key_frame )
clear_slice_state ( f , fs ) ;
2012-04-20 16:05:36 +03:00
if ( f - > version > 2 ) {
encode_slice_header ( f , fs ) ;
}
2012-04-24 23:54:50 +03:00
if ( ! fs - > ac ) {
fs - > ac_byte_count = f - > version > 2 | | ( ! x & & ! y ) ? ff_rac_terminate ( & fs - > c ) : 0 ;
init_put_bits ( & fs - > pb , fs - > c . bytestream_start + fs - > ac_byte_count , fs - > c . bytestream_end - fs - > c . bytestream_start - fs - > ac_byte_count ) ;
}
2012-04-20 16:05:36 +03:00
2010-10-15 01:03:32 +03:00
if ( f - > colorspace = = 0 ) {
const int chroma_width = - ( ( - width ) > > f - > chroma_h_shift ) ;
const int chroma_height = - ( ( - height ) > > f - > chroma_v_shift ) ;
const int cx = x > > f - > chroma_h_shift ;
const int cy = y > > f - > chroma_v_shift ;
2011-05-26 02:55:12 +03:00
encode_plane ( fs , p - > data [ 0 ] + ps * x + y * p - > linesize [ 0 ] , width , height , p - > linesize [ 0 ] , 0 ) ;
2010-10-15 01:03:32 +03:00
2012-02-06 21:23:44 +03:00
if ( f - > chroma_planes ) {
encode_plane ( fs , p - > data [ 1 ] + ps * cx + cy * p - > linesize [ 1 ] , chroma_width , chroma_height , p - > linesize [ 1 ] , 1 ) ;
encode_plane ( fs , p - > data [ 2 ] + ps * cx + cy * p - > linesize [ 2 ] , chroma_width , chroma_height , p - > linesize [ 2 ] , 1 ) ;
}
2012-01-31 23:18:21 +03:00
if ( fs - > transparency )
encode_plane ( fs , p - > data [ 3 ] + ps * x + y * p - > linesize [ 3 ] , width , height , p - > linesize [ 3 ] , 2 ) ;
2010-10-15 01:03:32 +03:00
} else {
2011-05-26 02:55:12 +03:00
encode_rgb_frame ( fs , ( uint32_t * ) ( p - > data [ 0 ] ) + ps * x + y * ( p - > linesize [ 0 ] / 4 ) , width , height , p - > linesize [ 0 ] / 4 ) ;
2010-10-15 01:03:32 +03:00
}
emms_c ( ) ;
return 0 ;
}
2012-02-12 11:32:40 +03:00
static int encode_frame ( AVCodecContext * avctx , AVPacket * pkt ,
const AVFrame * pict , int * got_packet )
{
2003-06-09 05:24:51 +03:00
FFV1Context * f = avctx - > priv_data ;
2010-10-15 01:03:32 +03:00
RangeCoder * const c = & f - > slice_context [ 0 ] - > c ;
2003-06-09 05:24:51 +03:00
AVFrame * const p = & f - > picture ;
2003-06-14 00:31:28 +03:00
int used_count = 0 ;
2004-10-31 12:08:50 +02:00
uint8_t keystate = 128 ;
2010-10-15 01:03:32 +03:00
uint8_t * buf_p ;
2012-02-12 11:32:40 +03:00
int i , ret ;
2012-03-22 06:22:49 +03:00
if ( ( ret = ff_alloc_packet2 ( avctx , pkt , avctx - > width * avctx - > height * ( ( 8 * 2 + 1 + 1 ) * 4 ) / 8
2012-03-22 23:22:39 +03:00
+ FF_MIN_BUFFER_SIZE ) ) < 0 )
2012-02-12 11:32:40 +03:00
return ret ;
2004-10-31 12:08:50 +02:00
2012-02-12 11:32:40 +03:00
ff_init_range_encoder ( c , pkt - > data , pkt - > size ) ;
2004-10-31 12:08:50 +02:00
ff_build_rac_states ( c , 0.05 * ( 1LL < < 32 ) , 256 - 8 ) ;
2003-06-09 05:24:51 +03:00
* p = * pict ;
2011-04-28 02:40:44 +03:00
p - > pict_type = AV_PICTURE_TYPE_I ;
2005-12-17 20:14:38 +02:00
2003-06-09 05:24:51 +03:00
if ( avctx - > gop_size = = 0 | | f - > picture_number % avctx - > gop_size = = 0 ) {
2004-10-31 12:08:50 +02:00
put_rac ( c , & keystate , 1 ) ;
2003-06-09 05:24:51 +03:00
p - > key_frame = 1 ;
2010-10-28 15:15:44 +03:00
f - > gob_count + + ;
2003-06-09 05:24:51 +03:00
write_header ( f ) ;
} else {
2004-10-31 12:08:50 +02:00
put_rac ( c , & keystate , 0 ) ;
2003-06-09 05:24:51 +03:00
p - > key_frame = 0 ;
}
2012-04-24 23:54:50 +03:00
if ( f - > ac > 1 ) {
2010-04-01 21:51:08 +03:00
int i ;
for ( i = 1 ; i < 256 ; i + + ) {
c - > one_state [ i ] = f - > state_transition [ i ] ;
c - > zero_state [ 256 - i ] = 256 - c - > one_state [ i ] ;
}
2003-06-14 00:31:28 +03:00
}
2005-12-17 20:14:38 +02:00
2010-10-15 01:03:32 +03:00
for ( i = 1 ; i < f - > slice_count ; i + + ) {
FFV1Context * fs = f - > slice_context [ i ] ;
2012-02-12 11:32:40 +03:00
uint8_t * start = pkt - > data + ( pkt - > size - used_count ) * i / f - > slice_count ;
int len = pkt - > size / f - > slice_count ;
2003-06-09 05:24:51 +03:00
2012-04-24 23:54:50 +03:00
ff_init_range_encoder ( & fs - > c , start , len ) ;
2003-06-09 05:24:51 +03:00
}
2010-10-15 01:03:32 +03:00
avctx - > execute ( avctx , encode_slice , & f - > slice_context [ 0 ] , NULL , f - > slice_count , sizeof ( void * ) ) ;
2005-12-17 20:14:38 +02:00
2012-02-12 11:32:40 +03:00
buf_p = pkt - > data ;
2010-10-15 01:03:32 +03:00
for ( i = 0 ; i < f - > slice_count ; i + + ) {
FFV1Context * fs = f - > slice_context [ i ] ;
int bytes ;
2003-06-09 05:24:51 +03:00
2010-10-15 01:03:32 +03:00
if ( fs - > ac ) {
uint8_t state = 128 ;
put_rac ( & fs - > c , & state , 0 ) ;
bytes = ff_rac_terminate ( & fs - > c ) ;
} else {
flush_put_bits ( & fs - > pb ) ; //nicer padding FIXME
2012-04-24 23:54:50 +03:00
bytes = fs - > ac_byte_count + ( put_bits_count ( & fs - > pb ) + 7 ) / 8 ;
2010-10-15 01:03:32 +03:00
}
2012-04-25 15:59:15 +03:00
if ( i > 0 | | f - > version > 2 ) {
2012-02-12 11:32:40 +03:00
av_assert0 ( bytes < pkt - > size / f - > slice_count ) ;
2012-04-25 00:28:37 +03:00
memmove ( buf_p , fs - > c . bytestream_start , bytes ) ;
2010-10-15 01:03:32 +03:00
av_assert0 ( bytes < ( 1 < < 24 ) ) ;
AV_WB24 ( buf_p + bytes , bytes ) ;
bytes + = 3 ;
}
2012-04-20 16:08:28 +03:00
if ( f - > ec ) {
2012-04-25 13:05:06 +03:00
unsigned v ;
buf_p [ bytes + + ] = 0 ;
v = av_crc ( av_crc_get_table ( AV_CRC_32_IEEE ) , 0 , buf_p , bytes ) ;
2012-04-20 16:08:28 +03:00
AV_WL32 ( buf_p + bytes , v ) ; bytes + = 4 ;
}
2010-10-15 01:03:32 +03:00
buf_p + = bytes ;
2003-06-14 00:31:28 +03:00
}
2010-10-15 01:03:32 +03:00
2010-10-24 15:31:09 +03:00
if ( ( avctx - > flags & CODEC_FLAG_PASS1 ) & & ( f - > picture_number & 31 ) = = 0 ) {
2010-10-27 02:01:17 +03:00
int j , k , m ;
2010-10-24 15:31:09 +03:00
char * p = avctx - > stats_out ;
2010-10-27 02:00:57 +03:00
char * end = p + STATS_OUT_SIZE ;
2010-10-24 15:31:09 +03:00
memset ( f - > rc_stat , 0 , sizeof ( f - > rc_stat ) ) ;
2010-10-27 02:01:17 +03:00
for ( i = 0 ; i < f - > quant_table_count ; i + + )
memset ( f - > rc_stat2 [ i ] , 0 , f - > context_count [ i ] * sizeof ( * f - > rc_stat2 [ i ] ) ) ;
2010-10-24 15:31:09 +03:00
for ( j = 0 ; j < f - > slice_count ; j + + ) {
FFV1Context * fs = f - > slice_context [ j ] ;
for ( i = 0 ; i < 256 ; i + + ) {
f - > rc_stat [ i ] [ 0 ] + = fs - > rc_stat [ i ] [ 0 ] ;
f - > rc_stat [ i ] [ 1 ] + = fs - > rc_stat [ i ] [ 1 ] ;
}
2010-10-27 02:01:17 +03:00
for ( i = 0 ; i < f - > quant_table_count ; i + + ) {
for ( k = 0 ; k < f - > context_count [ i ] ; k + + ) {
for ( m = 0 ; m < 32 ; m + + ) {
f - > rc_stat2 [ i ] [ k ] [ m ] [ 0 ] + = fs - > rc_stat2 [ i ] [ k ] [ m ] [ 0 ] ;
f - > rc_stat2 [ i ] [ k ] [ m ] [ 1 ] + = fs - > rc_stat2 [ i ] [ k ] [ m ] [ 1 ] ;
}
}
}
2010-10-24 15:31:09 +03:00
}
for ( j = 0 ; j < 256 ; j + + ) {
snprintf ( p , end - p , " % " PRIu64 " % " PRIu64 " " , f - > rc_stat [ j ] [ 0 ] , f - > rc_stat [ j ] [ 1 ] ) ;
p + = strlen ( p ) ;
}
snprintf ( p , end - p , " \n " ) ;
2010-10-27 02:01:17 +03:00
for ( i = 0 ; i < f - > quant_table_count ; i + + ) {
for ( j = 0 ; j < f - > context_count [ i ] ; j + + ) {
for ( m = 0 ; m < 32 ; m + + ) {
snprintf ( p , end - p , " % " PRIu64 " % " PRIu64 " " , f - > rc_stat2 [ i ] [ j ] [ m ] [ 0 ] , f - > rc_stat2 [ i ] [ j ] [ m ] [ 1 ] ) ;
p + = strlen ( p ) ;
}
}
}
2010-10-28 15:15:44 +03:00
snprintf ( p , end - p , " %d \n " , f - > gob_count ) ;
2010-10-27 02:01:00 +03:00
} else if ( avctx - > flags & CODEC_FLAG_PASS1 )
2010-10-24 15:31:09 +03:00
avctx - > stats_out [ 0 ] = ' \0 ' ;
2010-10-15 01:03:32 +03:00
f - > picture_number + + ;
2012-02-12 11:32:40 +03:00
pkt - > size = buf_p - pkt - > data ;
pkt - > flags | = AV_PKT_FLAG_KEY * p - > key_frame ;
* got_packet = 1 ;
return 0 ;
2003-06-09 05:24:51 +03:00
}
2008-09-03 15:33:21 +03:00
# endif /* CONFIG_FFV1_ENCODER */
2003-06-09 05:24:51 +03:00
2008-03-21 05:11:20 +02:00
static av_cold int common_end ( AVCodecContext * avctx ) {
2006-04-29 02:16:42 +03:00
FFV1Context * s = avctx - > priv_data ;
2010-10-15 01:03:32 +03:00
int i , j ;
2003-06-09 05:24:51 +03:00
2010-11-05 00:45:46 +02:00
if ( avctx - > codec - > decode & & s - > picture . data [ 0 ] )
avctx - > release_buffer ( avctx , & s - > picture ) ;
2010-10-15 01:03:32 +03:00
for ( j = 0 ; j < s - > slice_count ; j + + ) {
FFV1Context * fs = s - > slice_context [ j ] ;
2010-10-15 01:10:50 +03:00
for ( i = 0 ; i < s - > plane_count ; i + + ) {
PlaneContext * p = & fs - > plane [ i ] ;
2003-06-09 05:24:51 +03:00
2010-10-15 01:10:50 +03:00
av_freep ( & p - > state ) ;
av_freep ( & p - > vlc_state ) ;
}
2010-10-15 01:03:32 +03:00
av_freep ( & fs - > sample_buffer ) ;
}
2010-06-26 18:53:25 +03:00
2010-10-24 15:31:09 +03:00
av_freep ( & avctx - > stats_out ) ;
2010-10-27 02:01:07 +03:00
for ( j = 0 ; j < s - > quant_table_count ; j + + ) {
2010-10-27 02:01:11 +03:00
av_freep ( & s - > initial_states [ j ] ) ;
2010-10-27 02:01:07 +03:00
for ( i = 0 ; i < s - > slice_count ; i + + ) {
FFV1Context * sf = s - > slice_context [ i ] ;
av_freep ( & sf - > rc_stat2 [ j ] ) ;
}
2010-10-27 02:01:17 +03:00
av_freep ( & s - > rc_stat2 [ j ] ) ;
2010-10-27 02:01:07 +03:00
}
2010-10-24 15:31:09 +03:00
2010-10-28 15:15:50 +03:00
for ( i = 0 ; i < s - > slice_count ; i + + ) {
av_freep ( & s - > slice_context [ i ] ) ;
}
2003-06-09 05:24:51 +03:00
return 0 ;
}
2011-04-29 17:08:20 +03:00
static av_always_inline void decode_line ( FFV1Context * s , int w ,
int16_t * sample [ 2 ] ,
int plane_index , int bits )
{
2003-06-09 05:24:51 +03:00
PlaneContext * const p = & s - > plane [ plane_index ] ;
2004-10-31 12:08:50 +02:00
RangeCoder * const c = & s - > c ;
2003-11-01 19:38:25 +02:00
int x ;
int run_count = 0 ;
int run_mode = 0 ;
int run_index = s - > run_index ;
for ( x = 0 ; x < w ; x + + ) {
int diff , context , sign ;
2005-12-17 20:14:38 +02:00
2010-10-15 01:03:41 +03:00
context = get_context ( p , sample [ 1 ] + x , sample [ 0 ] + x , sample [ 1 ] + x ) ;
2003-11-01 19:38:25 +02:00
if ( context < 0 ) {
context = - context ;
sign = 1 ;
} else
sign = 0 ;
2005-12-17 20:14:38 +02:00
2010-10-15 01:03:38 +03:00
av_assert2 ( context < p - > context_count ) ;
2003-11-01 19:38:25 +02:00
2004-10-31 14:22:00 +02:00
if ( s - > ac ) {
2009-04-24 04:50:09 +03:00
diff = get_symbol_inline ( c , p - > state [ context ] , 1 ) ;
2004-10-31 14:22:00 +02:00
} else {
2003-11-01 19:38:25 +02:00
if ( context = = 0 & & run_mode = = 0 ) run_mode = 1 ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
if ( run_mode ) {
if ( run_count = = 0 & & run_mode = = 1 ) {
if ( get_bits1 ( & s - > gb ) ) {
2008-06-26 19:39:21 +03:00
run_count = 1 < < ff_log2_run [ run_index ] ;
2003-11-01 19:38:25 +02:00
if ( x + run_count < = w ) run_index + + ;
} else {
2008-06-26 19:39:21 +03:00
if ( ff_log2_run [ run_index ] ) run_count = get_bits ( & s - > gb , ff_log2_run [ run_index ] ) ;
2003-11-01 19:38:25 +02:00
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 ) ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
// printf("count:%d index:%d, mode:%d, x:%d y:%d pos:%d\n", run_count, run_index, run_mode, x, y, get_bits_count(&s->gb));
}
if ( sign ) diff = - diff ;
sample [ 1 ] [ x ] = ( predict ( sample [ 1 ] + x , sample [ 0 ] + x ) + diff ) & ( ( 1 < < bits ) - 1 ) ;
}
2005-12-17 20:14:38 +02:00
s - > run_index = run_index ;
2003-11-01 19:38:25 +02:00
}
static void decode_plane ( FFV1Context * s , uint8_t * src , int w , int h , int stride , int plane_index ) {
int x , y ;
2011-04-29 17:08:20 +03:00
int16_t * sample [ 2 ] ;
2010-06-26 18:53:25 +03:00
sample [ 0 ] = s - > sample_buffer + 3 ;
sample [ 1 ] = s - > sample_buffer + w + 6 + 3 ;
2003-11-01 19:38:25 +02:00
s - > run_index = 0 ;
2005-12-17 20:14:38 +02:00
2010-06-26 18:53:25 +03:00
memset ( s - > sample_buffer , 0 , 2 * ( w + 6 ) * sizeof ( * s - > sample_buffer ) ) ;
2005-12-17 20:14:38 +02:00
2003-06-09 05:24:51 +03:00
for ( y = 0 ; y < h ; y + + ) {
2011-04-29 17:08:20 +03:00
int16_t * temp = sample [ 0 ] ; //FIXME try a normal buffer
2003-06-09 05:24:51 +03:00
2003-07-02 19:50:20 +03:00
sample [ 0 ] = sample [ 1 ] ;
sample [ 1 ] = temp ;
2003-06-09 05:24:51 +03:00
2003-07-02 19:50:20 +03:00
sample [ 1 ] [ - 1 ] = sample [ 0 ] [ 0 ] ;
sample [ 0 ] [ w ] = sample [ 0 ] [ w - 1 ] ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
//{START_TIMER
2009-04-24 07:10:32 +03:00
if ( s - > avctx - > bits_per_raw_sample < = 8 ) {
2009-04-24 16:38:28 +03:00
decode_line ( s , w , sample , plane_index , 8 ) ;
for ( x = 0 ; x < w ; x + + ) {
src [ x + stride * y ] = sample [ 1 ] [ x ] ;
}
2009-04-24 07:10:32 +03:00
} else {
decode_line ( s , w , sample , plane_index , s - > avctx - > bits_per_raw_sample ) ;
2011-05-12 18:27:31 +03:00
if ( s - > packed_at_lsb ) {
for ( x = 0 ; x < w ; x + + ) {
( ( uint16_t * ) ( src + stride * y ) ) [ x ] = sample [ 1 ] [ x ] ;
}
} else {
for ( x = 0 ; x < w ; x + + ) {
( ( uint16_t * ) ( src + stride * y ) ) [ x ] = sample [ 1 ] [ x ] < < ( 16 - s - > avctx - > bits_per_raw_sample ) ;
}
2009-04-24 07:10:32 +03:00
}
}
2003-11-01 19:38:25 +02:00
//STOP_TIMER("decode-line")}
}
}
2003-06-09 05:24:51 +03:00
2003-11-01 19:38:25 +02:00
static void decode_rgb_frame ( FFV1Context * s , uint32_t * src , int w , int h , int stride ) {
int x , y , p ;
2011-11-28 19:40:39 +03:00
int16_t * sample [ 4 ] [ 2 ] ;
for ( x = 0 ; x < 4 ; x + + ) {
2010-06-26 18:53:25 +03:00
sample [ x ] [ 0 ] = s - > sample_buffer + x * 2 * ( w + 6 ) + 3 ;
sample [ x ] [ 1 ] = s - > sample_buffer + ( x * 2 + 1 ) * ( w + 6 ) + 3 ;
2008-05-24 10:19:12 +03:00
}
2003-11-01 19:38:25 +02:00
s - > run_index = 0 ;
2005-12-17 20:14:38 +02:00
2011-11-28 19:40:39 +03:00
memset ( s - > sample_buffer , 0 , 8 * ( w + 6 ) * sizeof ( * s - > sample_buffer ) ) ;
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
for ( y = 0 ; y < h ; y + + ) {
2011-11-28 19:40:39 +03:00
for ( p = 0 ; p < 3 + s - > transparency ; p + + ) {
2011-04-29 17:08:20 +03:00
int16_t * temp = sample [ p ] [ 0 ] ; //FIXME try a normal buffer
2003-11-01 19:38:25 +02:00
sample [ p ] [ 0 ] = sample [ p ] [ 1 ] ;
sample [ p ] [ 1 ] = temp ;
2003-06-09 05:24:51 +03:00
2003-11-01 19:38:25 +02:00
sample [ p ] [ 1 ] [ - 1 ] = sample [ p ] [ 0 ] [ 0 ] ;
sample [ p ] [ 0 ] [ w ] = sample [ p ] [ 0 ] [ w - 1 ] ;
2011-11-28 19:40:39 +03:00
decode_line ( s , w , sample [ p ] , ( p + 1 ) / 2 , 9 ) ;
2003-11-01 19:38:25 +02:00
}
for ( x = 0 ; x < w ; x + + ) {
int g = sample [ 0 ] [ 1 ] [ x ] ;
int b = sample [ 1 ] [ 1 ] [ x ] ;
int r = sample [ 2 ] [ 1 ] [ x ] ;
2011-11-28 19:40:39 +03:00
int a = sample [ 3 ] [ 1 ] [ x ] ;
2003-06-14 00:31:28 +03:00
2003-11-01 19:38:25 +02:00
// assert(g>=0 && b>=0 && r>=0);
// assert(g<256 && b<512 && r<512);
2005-12-17 20:14:38 +02:00
2003-11-01 19:38:25 +02:00
b - = 0x100 ;
r - = 0x100 ;
g - = ( b + r ) > > 2 ;
b + = g ;
r + = g ;
2005-12-17 20:14:38 +02:00
2011-11-28 19:40:39 +03:00
src [ x + stride * y ] = b + ( g < < 8 ) + ( r < < 16 ) + ( a < < 24 ) ;
2003-06-09 05:24:51 +03:00
}
}
}
2012-04-20 16:05:36 +03:00
static int decode_slice_header ( FFV1Context * f , FFV1Context * fs ) {
RangeCoder * c = & fs - > c ;
uint8_t state [ CONTEXT_SIZE ] ;
unsigned ps , i , context_count ;
memset ( state , 128 , sizeof ( state ) ) ;
av_assert0 ( f - > version > 2 ) ;
fs - > slice_x = get_symbol ( c , state , 0 ) * f - > width ;
fs - > slice_y = get_symbol ( c , state , 0 ) * f - > height ;
fs - > slice_width = ( get_symbol ( c , state , 0 ) + 1 ) * f - > width + fs - > slice_x ;
fs - > slice_height = ( get_symbol ( c , state , 0 ) + 1 ) * f - > height + fs - > slice_y ;
fs - > slice_x / = f - > num_h_slices ;
fs - > slice_y / = f - > num_v_slices ;
fs - > slice_width = fs - > slice_width / f - > num_h_slices - fs - > slice_x ;
fs - > slice_height = fs - > slice_height / f - > num_v_slices - fs - > slice_y ;
if ( ( unsigned ) fs - > slice_width > f - > width | | ( unsigned ) fs - > slice_height > f - > height )
return - 1 ;
if ( ( unsigned ) fs - > slice_x + ( uint64_t ) fs - > slice_width > f - > width
| | ( unsigned ) fs - > slice_y + ( uint64_t ) fs - > slice_height > f - > height )
return - 1 ;
for ( i = 0 ; i < f - > plane_count ; i + + ) {
PlaneContext * const p = & fs - > plane [ i ] ;
int idx = get_symbol ( c , state , 0 ) ;
if ( idx > ( unsigned ) f - > quant_table_count ) {
av_log ( f - > avctx , AV_LOG_ERROR , " quant_table_index out of range \n " ) ;
return - 1 ;
}
p - > quant_table_index = idx ;
memcpy ( p - > quant_table , f - > quant_tables [ idx ] , sizeof ( p - > quant_table ) ) ;
context_count = f - > context_count [ idx ] ;
if ( p - > context_count < context_count ) {
av_freep ( & p - > state ) ;
av_freep ( & p - > vlc_state ) ;
}
p - > context_count = context_count ;
}
ps = get_symbol ( c , state , 0 ) ;
if ( ps = = 1 ) {
f - > picture . interlaced_frame = 1 ;
f - > picture . top_field_first = 1 ;
} else if ( ps = = 2 ) {
f - > picture . interlaced_frame = 1 ;
f - > picture . top_field_first = 0 ;
} else if ( ps = = 3 ) {
f - > picture . interlaced_frame = 0 ;
}
f - > picture . sample_aspect_ratio . num = get_symbol ( c , state , 0 ) ;
f - > picture . sample_aspect_ratio . den = get_symbol ( c , state , 0 ) ;
return 0 ;
}
2010-10-15 01:03:32 +03:00
static int decode_slice ( AVCodecContext * c , void * arg ) {
FFV1Context * fs = * ( void * * ) arg ;
FFV1Context * f = fs - > avctx - > priv_data ;
2012-04-20 16:05:36 +03:00
int width , height , x , y ;
2011-05-26 02:55:12 +03:00
const int ps = ( c - > bits_per_raw_sample > 8 ) + 1 ;
2010-10-15 01:03:32 +03:00
AVFrame * const p = & f - > picture ;
2012-04-20 16:05:36 +03:00
if ( f - > version > 2 ) {
if ( init_slice_state ( f , fs ) < 0 )
return AVERROR ( ENOMEM ) ;
2012-04-25 18:50:55 +03:00
if ( decode_slice_header ( f , fs ) < 0 )
return AVERROR_INVALIDDATA ;
2012-04-20 16:05:36 +03:00
}
2012-04-25 18:50:55 +03:00
if ( init_slice_state ( f , fs ) < 0 )
return AVERROR ( ENOMEM ) ;
2012-04-20 15:55:09 +03:00
if ( f - > picture . key_frame )
clear_slice_state ( f , fs ) ;
2012-04-20 16:05:36 +03:00
width = fs - > slice_width ;
height = fs - > slice_height ;
x = fs - > slice_x ;
y = fs - > slice_y ;
2012-04-20 15:55:09 +03:00
2012-04-25 00:27:47 +03:00
if ( ! fs - > ac ) {
fs - > ac_byte_count = f - > version > 2 | | ( ! x & & ! y ) ? fs - > c . bytestream - fs - > c . bytestream_start - 1 : 0 ;
init_get_bits ( & fs - > gb ,
fs - > c . bytestream_start + fs - > ac_byte_count ,
( fs - > c . bytestream_end - fs - > c . bytestream_start - fs - > ac_byte_count ) * 8 ) ;
}
2010-10-15 01:03:32 +03:00
av_assert1 ( width & & height ) ;
if ( f - > colorspace = = 0 ) {
const int chroma_width = - ( ( - width ) > > f - > chroma_h_shift ) ;
const int chroma_height = - ( ( - height ) > > f - > chroma_v_shift ) ;
const int cx = x > > f - > chroma_h_shift ;
const int cy = y > > f - > chroma_v_shift ;
2011-05-26 02:55:12 +03:00
decode_plane ( fs , p - > data [ 0 ] + ps * x + y * p - > linesize [ 0 ] , width , height , p - > linesize [ 0 ] , 0 ) ;
2010-10-15 01:03:32 +03:00
2012-02-06 21:23:44 +03:00
if ( f - > chroma_planes ) {
decode_plane ( fs , p - > data [ 1 ] + ps * cx + cy * p - > linesize [ 1 ] , chroma_width , chroma_height , p - > linesize [ 1 ] , 1 ) ;
decode_plane ( fs , p - > data [ 2 ] + ps * cx + cy * p - > linesize [ 2 ] , chroma_width , chroma_height , p - > linesize [ 2 ] , 1 ) ;
}
2012-01-31 23:18:22 +03:00
if ( fs - > transparency )
decode_plane ( fs , p - > data [ 3 ] + ps * x + y * p - > linesize [ 3 ] , width , height , p - > linesize [ 3 ] , 2 ) ;
2010-10-15 01:03:32 +03:00
} else {
2011-05-26 02:55:12 +03:00
decode_rgb_frame ( fs , ( uint32_t * ) p - > data [ 0 ] + ps * x + y * ( p - > linesize [ 0 ] / 4 ) , width , height , p - > linesize [ 0 ] / 4 ) ;
2010-10-15 01:03:32 +03:00
}
emms_c ( ) ;
return 0 ;
}
2004-10-31 12:08:50 +02:00
static int read_quant_table ( RangeCoder * c , int16_t * quant_table , int scale ) {
2003-06-09 05:24:51 +03:00
int v ;
int i = 0 ;
2004-10-31 12:08:50 +02:00
uint8_t state [ CONTEXT_SIZE ] ;
memset ( state , 128 , sizeof ( state ) ) ;
2003-06-09 05:24:51 +03:00
2003-06-14 00:31:28 +03:00
for ( v = 0 ; i < 128 ; v + + ) {
2012-06-02 03:37:36 +03:00
unsigned len = get_symbol ( c , state , 0 ) + 1 ;
2003-06-09 05:24:51 +03:00
2012-06-02 03:37:36 +03:00
if ( len > 128 - i ) return - 1 ;
2005-12-17 20:14:38 +02:00
2003-06-09 05:24:51 +03:00
while ( len - - ) {
2003-06-14 00:31:28 +03:00
quant_table [ i ] = scale * v ;
i + + ;
2003-06-09 05:24:51 +03:00
//printf("%2d ",v);
//if(i%16==0) printf("\n");
}
}
2003-06-14 00:31:28 +03:00
for ( i = 1 ; i < 128 ; i + + ) {
quant_table [ 256 - i ] = - quant_table [ i ] ;
}
quant_table [ 128 ] = - quant_table [ 127 ] ;
2005-12-17 20:14:38 +02:00
2003-06-14 00:31:28 +03:00
return 2 * v - 1 ;
2003-06-09 05:24:51 +03:00
}
2010-10-19 20:26:27 +03:00
static int read_quant_tables ( RangeCoder * c , int16_t quant_table [ MAX_CONTEXT_INPUTS ] [ 256 ] ) {
2010-10-11 00:04:34 +03:00
int i ;
int context_count = 1 ;
for ( i = 0 ; i < 5 ; i + + ) {
context_count * = read_quant_table ( c , quant_table [ i ] , context_count ) ;
if ( context_count > 32768U ) {
return - 1 ;
}
}
return ( context_count + 1 ) / 2 ;
}
2010-10-11 00:04:41 +03:00
static int read_extra_header ( FFV1Context * f ) {
RangeCoder * const c = & f - > c ;
uint8_t state [ CONTEXT_SIZE ] ;
2010-10-27 02:01:14 +03:00
int i , j , k ;
uint8_t state2 [ 32 ] [ CONTEXT_SIZE ] ;
2010-10-11 00:04:41 +03:00
2010-10-27 02:01:14 +03:00
memset ( state2 , 128 , sizeof ( state2 ) ) ;
2010-10-11 00:04:41 +03:00
memset ( state , 128 , sizeof ( state ) ) ;
ff_init_range_decoder ( c , f - > avctx - > extradata , f - > avctx - > extradata_size ) ;
ff_build_rac_states ( c , 0.05 * ( 1LL < < 32 ) , 256 - 8 ) ;
f - > version = get_symbol ( c , state , 0 ) ;
2012-05-31 01:47:36 +03:00
if ( f - > version > 2 ) {
c - > bytestream_end - = 4 ;
2012-04-08 15:20:17 +03:00
f - > minor_version = get_symbol ( c , state , 0 ) ;
2012-05-31 01:47:36 +03:00
}
2010-10-11 00:04:41 +03:00
f - > ac = f - > avctx - > coder_type = get_symbol ( c , state , 0 ) ;
if ( f - > ac > 1 ) {
for ( i = 1 ; i < 256 ; i + + ) {
f - > state_transition [ i ] = get_symbol ( c , state , 1 ) + c - > one_state [ i ] ;
}
}
f - > colorspace = get_symbol ( c , state , 0 ) ; //YUV cs type
f - > avctx - > bits_per_raw_sample = get_symbol ( c , state , 0 ) ;
2012-04-08 16:03:40 +03:00
f - > chroma_planes = get_rac ( c , state ) ;
2010-10-11 00:04:41 +03:00
f - > chroma_h_shift = get_symbol ( c , state , 0 ) ;
f - > chroma_v_shift = get_symbol ( c , state , 0 ) ;
2011-11-28 19:40:39 +03:00
f - > transparency = get_rac ( c , state ) ;
f - > plane_count = 2 + f - > transparency ;
2010-10-15 01:03:32 +03:00
f - > num_h_slices = 1 + get_symbol ( c , state , 0 ) ;
f - > num_v_slices = 1 + get_symbol ( c , state , 0 ) ;
2010-10-15 05:05:06 +03:00
if ( f - > num_h_slices > ( unsigned ) f - > width | | f - > num_v_slices > ( unsigned ) f - > height ) {
2010-10-15 01:03:32 +03:00
av_log ( f - > avctx , AV_LOG_ERROR , " too many slices \n " ) ;
return - 1 ;
}
2010-10-11 00:04:41 +03:00
2010-10-11 00:04:45 +03:00
f - > quant_table_count = get_symbol ( c , state , 0 ) ;
if ( f - > quant_table_count > ( unsigned ) MAX_QUANT_TABLES )
return - 1 ;
for ( i = 0 ; i < f - > quant_table_count ; i + + ) {
if ( ( f - > context_count [ i ] = read_quant_tables ( c , f - > quant_tables [ i ] ) ) < 0 ) {
av_log ( f - > avctx , AV_LOG_ERROR , " read_quant_table error \n " ) ;
return - 1 ;
2010-10-11 00:04:41 +03:00
}
}
2010-10-27 02:01:14 +03:00
if ( allocate_initial_states ( f ) < 0 )
return AVERROR ( ENOMEM ) ;
for ( i = 0 ; i < f - > quant_table_count ; i + + ) {
if ( get_rac ( c , state ) ) {
for ( j = 0 ; j < f - > context_count [ i ] ; j + + ) {
for ( k = 0 ; k < CONTEXT_SIZE ; k + + ) {
int pred = j ? f - > initial_states [ i ] [ j - 1 ] [ k ] : 128 ;
f - > initial_states [ i ] [ j ] [ k ] = ( pred + get_symbol ( c , state2 [ k ] , 1 ) ) & 0xFF ;
}
}
}
}
2012-04-20 16:08:28 +03:00
if ( f - > version > 2 ) {
f - > ec = get_symbol ( c , state , 0 ) ;
}
2012-04-20 15:47:24 +03:00
if ( f - > version > 2 ) {
unsigned v ;
v = av_crc ( av_crc_get_table ( AV_CRC_32_IEEE ) , 0 , f - > avctx - > extradata , f - > avctx - > extradata_size ) ;
if ( v ) {
av_log ( f - > avctx , AV_LOG_ERROR , " CRC mismatch %X! \n " , v ) ;
return AVERROR_INVALIDDATA ;
}
}
2010-10-11 00:04:41 +03:00
return 0 ;
}
2003-06-09 05:24:51 +03:00
static int read_header ( FFV1Context * f ) {
2004-10-31 12:08:50 +02:00
uint8_t state [ CONTEXT_SIZE ] ;
2010-10-15 01:03:32 +03:00
int i , j , context_count ;
RangeCoder * const c = & f - > slice_context [ 0 ] - > c ;
2005-12-17 20:14:38 +02:00
2004-10-31 12:08:50 +02:00
memset ( state , 128 , sizeof ( state ) ) ;
2010-10-11 00:04:41 +03:00
if ( f - > version < 2 ) {
2012-06-02 03:21:30 +03:00
unsigned v = get_symbol ( c , state , 0 ) ;
if ( v > = 2 ) {
av_log ( f - > avctx , AV_LOG_ERROR , " invalid version %d in ver01 header \n " , v ) ;
return AVERROR_INVALIDDATA ;
}
f - > version = v ;
2010-10-15 01:10:50 +03:00
f - > ac = f - > avctx - > coder_type = get_symbol ( c , state , 0 ) ;
if ( f - > ac > 1 ) {
for ( i = 1 ; i < 256 ; i + + ) {
f - > state_transition [ i ] = get_symbol ( c , state , 1 ) + c - > one_state [ i ] ;
}
2010-04-01 21:51:08 +03:00
}
2010-10-15 01:10:50 +03:00
f - > colorspace = get_symbol ( c , state , 0 ) ; //YUV cs type
if ( f - > version > 0 )
f - > avctx - > bits_per_raw_sample = get_symbol ( c , state , 0 ) ;
2012-02-06 21:23:44 +03:00
f - > chroma_planes = get_rac ( c , state ) ;
2010-10-15 01:10:50 +03:00
f - > chroma_h_shift = get_symbol ( c , state , 0 ) ;
f - > chroma_v_shift = get_symbol ( c , state , 0 ) ;
2011-11-28 19:40:39 +03:00
f - > transparency = get_rac ( c , state ) ;
f - > plane_count = 2 + f - > transparency ;
2010-10-11 00:04:41 +03:00
}
2003-07-02 13:45:04 +03:00
2003-11-01 19:38:25 +02:00
if ( f - > colorspace = = 0 ) {
2012-02-14 08:39:03 +03:00
if ( ! f - > transparency & & ! f - > chroma_planes ) {
if ( f - > avctx - > bits_per_raw_sample < = 8 )
f - > avctx - > pix_fmt = PIX_FMT_GRAY8 ;
else
f - > avctx - > pix_fmt = PIX_FMT_GRAY16 ;
2012-02-06 21:23:44 +03:00
} else if ( f - > avctx - > bits_per_raw_sample < = 8 & & ! f - > transparency ) {
2009-04-24 16:38:28 +03:00
switch ( 16 * f - > chroma_h_shift + f - > chroma_v_shift ) {
case 0x00 : f - > avctx - > pix_fmt = PIX_FMT_YUV444P ; break ;
2012-02-01 04:54:18 +03:00
case 0x01 : f - > avctx - > pix_fmt = PIX_FMT_YUV440P ; break ;
2009-04-24 16:38:28 +03:00
case 0x10 : f - > avctx - > pix_fmt = PIX_FMT_YUV422P ; break ;
case 0x11 : f - > avctx - > pix_fmt = PIX_FMT_YUV420P ; break ;
case 0x20 : f - > avctx - > pix_fmt = PIX_FMT_YUV411P ; break ;
case 0x22 : f - > avctx - > pix_fmt = PIX_FMT_YUV410P ; break ;
default :
2012-01-31 23:18:22 +03:00
av_log ( f - > avctx , AV_LOG_ERROR , " format not supported \n " ) ;
return - 1 ;
}
} else if ( f - > avctx - > bits_per_raw_sample < = 8 & & f - > transparency ) {
switch ( 16 * f - > chroma_h_shift + f - > chroma_v_shift ) {
2012-01-31 23:18:24 +03:00
case 0x00 : f - > avctx - > pix_fmt = PIX_FMT_YUVA444P ; break ;
2012-05-08 09:49:36 +03:00
case 0x10 : f - > avctx - > pix_fmt = PIX_FMT_YUVA422P ; break ;
2012-01-31 23:18:22 +03:00
case 0x11 : f - > avctx - > pix_fmt = PIX_FMT_YUVA420P ; break ;
default :
2009-04-24 16:38:28 +03:00
av_log ( f - > avctx , AV_LOG_ERROR , " format not supported \n " ) ;
return - 1 ;
}
2011-05-12 18:46:02 +03:00
} else if ( f - > avctx - > bits_per_raw_sample = = 9 ) {
2012-03-07 02:16:39 +03:00
f - > packed_at_lsb = 1 ;
2011-05-12 18:46:02 +03:00
switch ( 16 * f - > chroma_h_shift + f - > chroma_v_shift ) {
2012-03-07 02:16:39 +03:00
case 0x00 : f - > avctx - > pix_fmt = PIX_FMT_YUV444P9 ; break ;
case 0x10 : f - > avctx - > pix_fmt = PIX_FMT_YUV422P9 ; break ;
case 0x11 : f - > avctx - > pix_fmt = PIX_FMT_YUV420P9 ; break ;
2011-05-12 18:46:02 +03:00
default :
av_log ( f - > avctx , AV_LOG_ERROR , " format not supported \n " ) ;
return - 1 ;
}
2011-05-12 18:27:31 +03:00
} else if ( f - > avctx - > bits_per_raw_sample = = 10 ) {
2012-03-07 02:16:40 +03:00
f - > packed_at_lsb = 1 ;
2011-05-12 18:27:31 +03:00
switch ( 16 * f - > chroma_h_shift + f - > chroma_v_shift ) {
2012-03-07 02:16:40 +03:00
case 0x00 : f - > avctx - > pix_fmt = PIX_FMT_YUV444P10 ; break ;
case 0x10 : f - > avctx - > pix_fmt = PIX_FMT_YUV422P10 ; break ;
case 0x11 : f - > avctx - > pix_fmt = PIX_FMT_YUV420P10 ; break ;
2011-05-12 18:27:31 +03:00
default :
av_log ( f - > avctx , AV_LOG_ERROR , " format not supported \n " ) ;
return - 1 ;
}
} else {
2009-04-24 07:10:32 +03:00
switch ( 16 * f - > chroma_h_shift + f - > chroma_v_shift ) {
case 0x00 : f - > avctx - > pix_fmt = PIX_FMT_YUV444P16 ; break ;
case 0x10 : f - > avctx - > pix_fmt = PIX_FMT_YUV422P16 ; break ;
case 0x11 : f - > avctx - > pix_fmt = PIX_FMT_YUV420P16 ; break ;
default :
av_log ( f - > avctx , AV_LOG_ERROR , " format not supported \n " ) ;
return - 1 ;
}
}
2003-11-01 19:38:25 +02:00
} else if ( f - > colorspace = = 1 ) {
if ( f - > chroma_h_shift | | f - > chroma_v_shift ) {
2003-11-03 15:26:22 +02:00
av_log ( f - > avctx , AV_LOG_ERROR , " chroma subsampling not supported in this colorspace \n " ) ;
2003-11-01 19:38:25 +02:00
return - 1 ;
}
2011-11-28 19:41:27 +03:00
if ( f - > transparency ) f - > avctx - > pix_fmt = PIX_FMT_RGB32 ;
else f - > avctx - > pix_fmt = PIX_FMT_0RGB32 ;
2003-11-01 19:38:25 +02:00
} else {
2003-11-03 15:26:22 +02:00
av_log ( f - > avctx , AV_LOG_ERROR , " colorspace not supported \n " ) ;
2003-07-02 13:45:04 +03:00
return - 1 ;
}
2003-11-01 19:38:25 +02:00
2003-07-02 13:45:04 +03:00
//printf("%d %d %d\n", f->chroma_h_shift, f->chroma_v_shift,f->avctx->pix_fmt);
2010-10-11 00:04:41 +03:00
if ( f - > version < 2 ) {
2010-10-15 01:10:50 +03:00
context_count = read_quant_tables ( c , f - > quant_table ) ;
if ( context_count < 0 ) {
av_log ( f - > avctx , AV_LOG_ERROR , " read_quant_table error \n " ) ;
return - 1 ;
2003-07-02 13:45:04 +03:00
}
2012-04-25 16:01:32 +03:00
} else if ( f - > version < 3 ) {
2010-10-15 05:05:06 +03:00
f - > slice_count = get_symbol ( c , state , 0 ) ;
2012-04-25 16:01:32 +03:00
} else {
const uint8_t * p = c - > bytestream_end ;
for ( f - > slice_count = 0 ; f - > slice_count < MAX_SLICES & & 3 < p - c - > bytestream_start ; f - > slice_count + + ) {
int trailer = 3 + 5 * ! ! f - > ec ;
int size = AV_RB24 ( p - trailer ) ;
if ( size + trailer > p - c - > bytestream_start )
break ;
p - = size + trailer ;
}
}
if ( f - > slice_count > ( unsigned ) MAX_SLICES | | f - > slice_count < = 0 ) {
av_log ( f - > avctx , AV_LOG_ERROR , " slice count %d is invalid \n " , f - > slice_count ) ;
return - 1 ;
2010-10-11 00:04:45 +03:00
}
2010-10-15 05:05:06 +03:00
2010-10-15 01:03:32 +03:00
for ( j = 0 ; j < f - > slice_count ; j + + ) {
FFV1Context * fs = f - > slice_context [ j ] ;
fs - > ac = f - > ac ;
2011-05-12 18:27:31 +03:00
fs - > packed_at_lsb = f - > packed_at_lsb ;
2010-10-15 05:05:06 +03:00
2012-04-20 16:05:36 +03:00
if ( f - > version = = 2 ) {
2010-10-15 05:05:06 +03:00
fs - > slice_x = get_symbol ( c , state , 0 ) * f - > width ;
fs - > slice_y = get_symbol ( c , state , 0 ) * f - > height ;
fs - > slice_width = ( get_symbol ( c , state , 0 ) + 1 ) * f - > width + fs - > slice_x ;
fs - > slice_height = ( get_symbol ( c , state , 0 ) + 1 ) * f - > height + fs - > slice_y ;
fs - > slice_x / = f - > num_h_slices ;
fs - > slice_y / = f - > num_v_slices ;
fs - > slice_width = fs - > slice_width / f - > num_h_slices - fs - > slice_x ;
fs - > slice_height = fs - > slice_height / f - > num_v_slices - fs - > slice_y ;
if ( ( unsigned ) fs - > slice_width > f - > width | | ( unsigned ) fs - > slice_height > f - > height )
return - 1 ;
if ( ( unsigned ) fs - > slice_x + ( uint64_t ) fs - > slice_width > f - > width
| | ( unsigned ) fs - > slice_y + ( uint64_t ) fs - > slice_height > f - > height )
return - 1 ;
}
2010-10-15 01:10:50 +03:00
for ( i = 0 ; i < f - > plane_count ; i + + ) {
PlaneContext * const p = & fs - > plane [ i ] ;
2012-04-20 16:05:36 +03:00
if ( f - > version = = 2 ) {
2010-10-15 01:10:50 +03:00
int idx = get_symbol ( c , state , 0 ) ;
if ( idx > ( unsigned ) f - > quant_table_count ) {
av_log ( f - > avctx , AV_LOG_ERROR , " quant_table_index out of range \n " ) ;
return - 1 ;
}
2010-10-26 04:59:03 +03:00
p - > quant_table_index = idx ;
2010-10-15 01:10:50 +03:00
memcpy ( p - > quant_table , f - > quant_tables [ idx ] , sizeof ( p - > quant_table ) ) ;
context_count = f - > context_count [ idx ] ;
} else {
memcpy ( p - > quant_table , f - > quant_table , sizeof ( p - > quant_table ) ) ;
2010-10-15 01:03:41 +03:00
}
2012-04-20 16:05:36 +03:00
if ( f - > version < = 2 ) {
2012-04-25 18:51:17 +03:00
if ( p - > context_count < context_count ) {
av_freep ( & p - > state ) ;
av_freep ( & p - > vlc_state ) ;
}
p - > context_count = context_count ;
2012-04-20 16:05:36 +03:00
}
2003-06-14 00:31:28 +03:00
}
2003-06-09 05:24:51 +03:00
}
return 0 ;
}
2008-03-21 05:11:20 +02:00
static av_cold int decode_init ( AVCodecContext * avctx )
2003-06-09 05:24:51 +03:00
{
2010-10-11 00:04:41 +03:00
FFV1Context * f = avctx - > priv_data ;
2003-06-09 05:24:51 +03:00
common_init ( avctx ) ;
2005-12-17 20:14:38 +02:00
2010-10-15 01:03:32 +03:00
if ( avctx - > extradata & & read_extra_header ( f ) < 0 )
return - 1 ;
if ( init_slice_contexts ( f ) < 0 )
return - 1 ;
2010-10-11 00:04:41 +03:00
2003-06-09 05:24:51 +03:00
return 0 ;
}
2009-04-07 18:59:50 +03:00
static int decode_frame ( AVCodecContext * avctx , void * data , int * data_size , AVPacket * avpkt ) {
const uint8_t * buf = avpkt - > data ;
int buf_size = avpkt - > size ;
2003-06-09 05:24:51 +03:00
FFV1Context * f = avctx - > priv_data ;
2010-10-15 01:03:32 +03:00
RangeCoder * const c = & f - > slice_context [ 0 ] - > c ;
2003-06-09 05:24:51 +03:00
AVFrame * const p = & f - > picture ;
2012-05-05 15:54:57 +03:00
int i ;
2004-10-31 12:08:50 +02:00
uint8_t keystate = 128 ;
2010-10-15 01:03:32 +03:00
const uint8_t * buf_p ;
2003-06-09 05:24:51 +03:00
AVFrame * picture = data ;
2010-11-05 00:45:46 +02:00
/* release previously stored data */
if ( p - > data [ 0 ] )
avctx - > release_buffer ( avctx , p ) ;
2004-10-31 12:08:50 +02:00
ff_init_range_decoder ( c , buf , buf_size ) ;
ff_build_rac_states ( c , 0.05 * ( 1LL < < 32 ) , 256 - 8 ) ;
2004-03-26 21:35:53 +02:00
2003-06-09 05:24:51 +03:00
2011-04-28 02:40:44 +03:00
p - > pict_type = AV_PICTURE_TYPE_I ; //FIXME I vs. P
2004-10-31 12:08:50 +02:00
if ( get_rac ( c , & keystate ) ) {
2003-06-09 05:24:51 +03:00
p - > key_frame = 1 ;
2012-04-22 14:56:07 +03:00
f - > key_frame_ok = 0 ;
2006-02-09 11:38:03 +02:00
if ( read_header ( f ) < 0 )
return - 1 ;
2012-04-22 14:56:07 +03:00
f - > key_frame_ok = 1 ;
2003-06-09 05:24:51 +03:00
} else {
2012-04-22 14:56:07 +03:00
if ( ! f - > key_frame_ok ) {
av_log ( avctx , AV_LOG_ERROR , " Cant decode non keyframe without valid keyframe \n " ) ;
return AVERROR_INVALIDDATA ;
}
2003-06-09 05:24:51 +03:00
p - > key_frame = 0 ;
}
2010-04-01 21:51:08 +03:00
2003-07-02 13:45:04 +03:00
p - > reference = 0 ;
if ( avctx - > get_buffer ( avctx , p ) < 0 ) {
2003-11-03 15:26:22 +02:00
av_log ( avctx , AV_LOG_ERROR , " get_buffer() failed \n " ) ;
2003-07-02 13:45:04 +03:00
return - 1 ;
}
2003-06-09 05:24:51 +03:00
if ( avctx - > debug & FF_DEBUG_PICT_INFO )
2012-06-04 02:00:26 +03:00
av_log ( avctx , AV_LOG_DEBUG , " ver:%d keyframe:%d coder:%d ec:%d slices:%d \n " ,
f - > version , p - > key_frame , f - > ac , f - > ec , f - > slice_count ) ;
2005-12-17 20:14:38 +02:00
2010-10-15 01:03:32 +03:00
buf_p = buf + buf_size ;
2012-04-20 15:57:03 +03:00
for ( i = f - > slice_count - 1 ; i > = 0 ; i - - ) {
2010-10-15 01:03:32 +03:00
FFV1Context * fs = f - > slice_context [ i ] ;
2012-04-25 13:05:06 +03:00
int trailer = 3 + 5 * ! ! f - > ec ;
2012-04-20 15:57:03 +03:00
int v ;
2012-04-25 15:59:15 +03:00
if ( i | | f - > version > 2 ) v = AV_RB24 ( buf_p - trailer ) + trailer ;
else v = buf_p - c - > bytestream_start ;
2012-04-20 15:57:03 +03:00
if ( buf_p - c - > bytestream_start < v ) {
2010-10-15 01:03:32 +03:00
av_log ( avctx , AV_LOG_ERROR , " Slice pointer chain broken \n " ) ;
return - 1 ;
}
buf_p - = v ;
2012-04-20 15:57:03 +03:00
2012-04-20 16:08:28 +03:00
if ( f - > ec ) {
unsigned crc = av_crc ( av_crc_get_table ( AV_CRC_32_IEEE ) , 0 , buf_p , v ) ;
if ( crc ) {
av_log ( f - > avctx , AV_LOG_ERROR , " CRC mismatch %X! \n " , crc ) ;
}
}
2012-04-20 15:57:03 +03:00
if ( i ) {
2012-04-25 00:27:47 +03:00
ff_init_range_decoder ( & fs - > c , buf_p , v ) ;
2010-10-15 01:03:32 +03:00
}
2003-06-09 05:24:51 +03:00
}
2005-12-17 20:14:38 +02:00
2010-10-15 01:03:32 +03:00
avctx - > execute ( avctx , decode_slice , & f - > slice_context [ 0 ] , NULL , f - > slice_count , sizeof ( void * ) ) ;
2003-06-09 05:24:51 +03:00
f - > picture_number + + ;
* picture = * p ;
* data_size = sizeof ( AVFrame ) ;
2005-12-17 20:14:38 +02:00
2010-10-15 01:03:32 +03:00
return buf_size ;
2003-06-09 05:24:51 +03:00
}
2011-01-25 23:40:11 +02:00
AVCodec ff_ffv1_decoder = {
2011-07-17 13:54:31 +03:00
. name = " ffv1 " ,
. type = AVMEDIA_TYPE_VIDEO ,
. id = CODEC_ID_FFV1 ,
. priv_data_size = sizeof ( FFV1Context ) ,
. init = decode_init ,
. close = common_end ,
. decode = decode_frame ,
2012-04-06 19:19:39 +03:00
. capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/ |
CODEC_CAP_SLICE_THREADS ,
. long_name = NULL_IF_CONFIG_SMALL ( " FFmpeg video codec #1 " ) ,
2003-06-09 05:24:51 +03:00
} ;
2009-01-14 01:44:16 +02:00
# if CONFIG_FFV1_ENCODER
2012-04-30 16:00:10 +03:00
# define OFFSET(x) offsetof(FFV1Context, x)
# define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options [ ] = {
{ " slicecrc " , " Protect slices with CRCs " , OFFSET ( ec ) , AV_OPT_TYPE_INT , { - 1 } , - 1 , 1 , VE } ,
{ NULL }
} ;
static const AVClass class = {
. class_name = " ffv1 encoder " ,
. item_name = av_default_item_name ,
. option = options ,
. version = LIBAVUTIL_VERSION_INT ,
} ;
2011-01-25 23:40:11 +02:00
AVCodec ff_ffv1_encoder = {
2011-07-17 13:54:31 +03:00
. name = " ffv1 " ,
. type = AVMEDIA_TYPE_VIDEO ,
. id = CODEC_ID_FFV1 ,
. priv_data_size = sizeof ( FFV1Context ) ,
. init = encode_init ,
2012-02-12 11:32:40 +03:00
. encode2 = encode_frame ,
2011-07-17 13:54:31 +03:00
. close = common_end ,
2012-04-06 19:19:39 +03:00
. capabilities = CODEC_CAP_SLICE_THREADS ,
2012-06-12 23:41:18 +03:00
. pix_fmts = ( const enum PixelFormat [ ] ) {
PIX_FMT_YUV420P , PIX_FMT_YUVA420P , PIX_FMT_YUVA422P , PIX_FMT_YUV444P ,
PIX_FMT_YUVA444P , PIX_FMT_YUV440P , PIX_FMT_YUV422P , PIX_FMT_YUV411P ,
PIX_FMT_YUV410P , PIX_FMT_0RGB32 , PIX_FMT_RGB32 , PIX_FMT_YUV420P16 ,
PIX_FMT_YUV422P16 , PIX_FMT_YUV444P16 , PIX_FMT_YUV444P9 , PIX_FMT_YUV422P9 ,
PIX_FMT_YUV420P9 , PIX_FMT_YUV420P10 , PIX_FMT_YUV422P10 , PIX_FMT_YUV444P10 ,
PIX_FMT_GRAY16 , PIX_FMT_GRAY8 ,
PIX_FMT_NONE
} ,
2012-04-06 19:19:39 +03:00
. long_name = NULL_IF_CONFIG_SMALL ( " FFmpeg video codec #1 " ) ,
2012-04-30 16:00:10 +03:00
. priv_class = & class ,
2003-06-09 05:24:51 +03:00
} ;
2003-06-22 14:08:22 +03:00
# endif