2 * Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (C) 2006 Robert Edele <yartrebo@earthlink.net>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #ifndef AVCODEC_SNOW_H
23 #define AVCODEC_SNOW_H
25 #include "libavutil/motion_vector.h"
31 #include "rangecoder.h"
37 #define SNOW_MAX_PLANES 4
43 #define QROOT (1<<QSHIFT)
44 #define LOSSLESS_QLOG -128
46 #define MAX_REF_FRAMES 8
48 #define LOG2_OBMC_MAX 8
49 #define OBMC_MAX (1<<(LOG2_OBMC_MAX))
50 typedef struct BlockNode
{
51 int16_t mx
; ///< Motion vector component X, see mv_scale
52 int16_t my
; ///< Motion vector component Y, see mv_scale
53 uint8_t ref
; ///< Reference frame index
54 uint8_t color
[3]; ///< Color for intra
55 uint8_t type
; ///< Bitfield of BLOCK_*
56 //#define TYPE_SPLIT 1
57 #define BLOCK_INTRA 1 ///< Intra block, inter otherwise
58 #define BLOCK_OPT 2 ///< Block needs no checks in this round of iterative motion estiation
59 //#define TYPE_NOCOLOR 4
60 uint8_t level
; //FIXME merge into type?
63 static const BlockNode null_block
= { //FIXME add border maybe
64 .color
= {128,128,128},
72 #define LOG2_MB_SIZE 4
73 #define MB_SIZE (1<<LOG2_MB_SIZE)
74 #define ENCODER_EXTRA_BITS 4
77 typedef struct x_and_coeff
{
82 typedef struct SubBand
{
87 int qlog
; ///< log(qscale)/log[2^(1/6)]
92 int stride_line
; ///< Stride measured in lines, not pixels.
93 x_and_coeff
* x_coeff
;
94 struct SubBand
*parent
;
95 uint8_t state
[/*7*2*/ 7 + 512][32];
101 SubBand band
[MAX_DECOMPOSITIONS
][4];
104 int8_t hcoeff
[HTAPS_MAX
/2];
109 int8_t last_hcoeff
[HTAPS_MAX
/2];
113 typedef struct SnowContext
{
115 AVCodecContext
*avctx
;
118 VideoDSPContext vdsp
;
119 H264QpelContext h264qpel
;
121 AVFrame
*input_picture
; ///< new_picture with the internal linesizes
122 AVFrame
*current_picture
;
123 AVFrame
*last_picture
[MAX_REF_FRAMES
];
124 AVFrame
*mconly_picture
;
125 // uint8_t q_context[16];
126 uint8_t header_state
[32];
127 uint8_t block_state
[128 + 32*128];
131 int spatial_decomposition_type
;
132 int last_spatial_decomposition_type
;
133 int temporal_decomposition_type
;
134 int spatial_decomposition_count
;
135 int last_spatial_decomposition_count
;
136 int temporal_decomposition_count
;
139 int16_t (*ref_mvs
[MAX_REF_FRAMES
])[2];
140 uint32_t *ref_scores
[MAX_REF_FRAMES
];
141 DWTELEM
*spatial_dwt_buffer
;
142 DWTELEM
*temp_dwt_buffer
;
143 IDWTELEM
*spatial_idwt_buffer
;
144 IDWTELEM
*temp_idwt_buffer
;
149 int spatial_scalability
;
156 #define QBIAS_SHIFT 3
160 int last_block_max_depth
;
162 Plane plane
[MAX_PLANES
];
167 uint8_t *emu_edge_buffer
;
169 AVMotionVector
*avmv
;
175 extern const uint8_t * const ff_obmc_tab
[4];
176 extern const uint8_t ff_qexp
[QROOT
];
177 extern int ff_scale_mv_ref
[MAX_REF_FRAMES
][MAX_REF_FRAMES
];
181 int ff_snow_common_init(AVCodecContext
*avctx
);
182 int ff_snow_common_init_after_header(AVCodecContext
*avctx
);
183 void ff_snow_common_end(SnowContext
*s
);
184 void ff_snow_release_buffer(AVCodecContext
*avctx
);
185 void ff_snow_reset_contexts(SnowContext
*s
);
186 int ff_snow_alloc_blocks(SnowContext
*s
);
187 int ff_snow_frames_prepare(SnowContext
*s
);
188 void ff_snow_pred_block(SnowContext
*s
, uint8_t *dst
, uint8_t *tmp
, ptrdiff_t stride
,
189 int sx
, int sy
, int b_w
, int b_h
, const BlockNode
*block
,
190 int plane_index
, int w
, int h
);
191 /* common inline functions */
192 //XXX doublecheck all of them should stay inlined
194 static inline void pred_mv(SnowContext
*s
, int *mx
, int *my
, int ref
,
195 const BlockNode
*left
, const BlockNode
*top
, const BlockNode
*tr
){
196 if(s
->ref_frames
== 1){
197 *mx
= mid_pred(left
->mx
, top
->mx
, tr
->mx
);
198 *my
= mid_pred(left
->my
, top
->my
, tr
->my
);
200 const int *scale
= ff_scale_mv_ref
[ref
];
201 *mx
= mid_pred((left
->mx
* scale
[left
->ref
] + 128) >>8,
202 (top
->mx
* scale
[top
->ref
] + 128) >>8,
203 (tr
->mx
* scale
[tr
->ref
] + 128) >>8);
204 *my
= mid_pred((left
->my
* scale
[left
->ref
] + 128) >>8,
205 (top
->my
* scale
[top
->ref
] + 128) >>8,
206 (tr
->my
* scale
[tr
->ref
] + 128) >>8);
210 static av_always_inline
int same_block(BlockNode
*a
, BlockNode
*b
){
211 if((a
->type
&BLOCK_INTRA
) && (b
->type
&BLOCK_INTRA
)){
212 return !((a
->color
[0] - b
->color
[0]) | (a
->color
[1] - b
->color
[1]) | (a
->color
[2] - b
->color
[2]));
214 return !((a
->mx
- b
->mx
) | (a
->my
- b
->my
) | (a
->ref
- b
->ref
) | ((a
->type
^ b
->type
)&BLOCK_INTRA
));
218 //FIXME name cleanup (b_w, block_w, b_width stuff)
219 //XXX should we really inline it?
220 static av_always_inline
void add_yblock(SnowContext
*s
, int sliced
, slice_buffer
*sb
, IDWTELEM
*dst
, uint8_t *dst8
, const uint8_t *obmc
, int src_x
, int src_y
, int b_w
, int b_h
, int w
, int h
, int dst_stride
, int src_stride
, int obmc_stride
, int b_x
, int b_y
, int add
, int offset_dst
, int plane_index
){
221 const int b_width
= s
->b_width
<< s
->block_max_depth
;
222 const int b_height
= s
->b_height
<< s
->block_max_depth
;
223 const int b_stride
= b_width
;
224 BlockNode
*lt
= &s
->block
[b_x
+ b_y
*b_stride
];
226 BlockNode
*lb
= lt
+b_stride
;
229 // When src_stride is large enough, it is possible to interleave the blocks.
230 // Otherwise the blocks are written sequentially in the tmp buffer.
231 int tmp_step
= src_stride
>= 7*MB_SIZE
? MB_SIZE
: MB_SIZE
*src_stride
;
232 uint8_t *tmp
= s
->scratchbuf
;
239 }else if(b_x
+ 1 >= b_width
){
246 }else if(b_y
+ 1 >= b_height
){
251 if(src_x
<0){ //FIXME merge with prev & always round internal width up to *16
254 if(!sliced
&& !offset_dst
)
262 obmc
-= src_y
*obmc_stride
;
264 if(!sliced
&& !offset_dst
)
265 dst
-= src_y
*dst_stride
;
272 if(b_w
<=0 || b_h
<=0) return;
274 if(!sliced
&& offset_dst
)
275 dst
+= src_x
+ src_y
*dst_stride
;
276 dst8
+= src_x
+ src_y
*src_stride
;
277 // src += src_x + src_y*src_stride;
279 ptmp
= tmp
+ 3*tmp_step
;
282 ff_snow_pred_block(s
, block
[0], tmp
, src_stride
, src_x
, src_y
, b_w
, b_h
, lt
, plane_index
, w
, h
);
284 if(same_block(lt
, rt
)){
289 ff_snow_pred_block(s
, block
[1], tmp
, src_stride
, src_x
, src_y
, b_w
, b_h
, rt
, plane_index
, w
, h
);
292 if(same_block(lt
, lb
)){
294 }else if(same_block(rt
, lb
)){
299 ff_snow_pred_block(s
, block
[2], tmp
, src_stride
, src_x
, src_y
, b_w
, b_h
, lb
, plane_index
, w
, h
);
302 if(same_block(lt
, rb
) ){
304 }else if(same_block(rt
, rb
)){
306 }else if(same_block(lb
, rb
)){
310 ff_snow_pred_block(s
, block
[3], tmp
, src_stride
, src_x
, src_y
, b_w
, b_h
, rb
, plane_index
, w
, h
);
313 s
->dwt
.inner_add_yblock(obmc
, obmc_stride
, block
, b_w
, b_h
, src_x
,src_y
, src_stride
, sb
, add
, dst8
);
315 for(y
=0; y
<b_h
; y
++){
316 //FIXME ugly misuse of obmc_stride
317 const uint8_t *obmc1
= obmc
+ y
*obmc_stride
;
318 const uint8_t *obmc2
= obmc1
+ (obmc_stride
>>1);
319 const uint8_t *obmc3
= obmc1
+ obmc_stride
*(obmc_stride
>>1);
320 const uint8_t *obmc4
= obmc3
+ (obmc_stride
>>1);
321 for(x
=0; x
<b_w
; x
++){
322 int v
= obmc1
[x
] * block
[3][x
+ y
*src_stride
]
323 +obmc2
[x
] * block
[2][x
+ y
*src_stride
]
324 +obmc3
[x
] * block
[1][x
+ y
*src_stride
]
325 +obmc4
[x
] * block
[0][x
+ y
*src_stride
];
327 v
<<= 8 - LOG2_OBMC_MAX
;
332 v
+= dst
[x
+ y
*dst_stride
];
333 v
= (v
+ (1<<(FRAC_BITS
-1))) >> FRAC_BITS
;
334 if(v
&(~255)) v
= ~(v
>>31);
335 dst8
[x
+ y
*src_stride
] = v
;
337 dst
[x
+ y
*dst_stride
] -= v
;
344 static av_always_inline
void predict_slice(SnowContext
*s
, IDWTELEM
*buf
, int plane_index
, int add
, int mb_y
){
345 Plane
*p
= &s
->plane
[plane_index
];
346 const int mb_w
= s
->b_width
<< s
->block_max_depth
;
347 const int mb_h
= s
->b_height
<< s
->block_max_depth
;
349 int block_size
= MB_SIZE
>> s
->block_max_depth
;
350 int block_w
= plane_index
? block_size
>>s
->chroma_h_shift
: block_size
;
351 int block_h
= plane_index
? block_size
>>s
->chroma_v_shift
: block_size
;
352 const uint8_t *obmc
= plane_index
? ff_obmc_tab
[s
->block_max_depth
+s
->chroma_h_shift
] : ff_obmc_tab
[s
->block_max_depth
];
353 const int obmc_stride
= plane_index
? (2*block_size
)>>s
->chroma_h_shift
: 2*block_size
;
354 int ref_stride
= s
->current_picture
->linesize
[plane_index
];
355 uint8_t *dst8
= s
->current_picture
->data
[plane_index
];
358 av_assert2(s
->chroma_h_shift
== s
->chroma_v_shift
); // obmc params assume squares
359 if(s
->keyframe
|| (s
->avctx
->debug
&512)){
364 for(y
=block_h
*mb_y
; y
<FFMIN(h
,block_h
*(mb_y
+1)); y
++){
366 int v
= buf
[x
+ y
*w
] + (128<<FRAC_BITS
) + (1<<(FRAC_BITS
-1));
368 if(v
&(~255)) v
= ~(v
>>31);
369 dst8
[x
+ y
*ref_stride
]= v
;
373 for(y
=block_h
*mb_y
; y
<FFMIN(h
,block_h
*(mb_y
+1)); y
++){
375 buf
[x
+ y
*w
]-= 128<<FRAC_BITS
;
383 for(mb_x
=0; mb_x
<=mb_w
; mb_x
++){
384 add_yblock(s
, 0, NULL
, buf
, dst8
, obmc
,
385 block_w
*mb_x
- block_w
/2,
386 block_h
*mb_y
- block_h
/2,
389 w
, ref_stride
, obmc_stride
,
391 add
, 1, plane_index
);
395 static av_always_inline
void predict_plane(SnowContext
*s
, IDWTELEM
*buf
, int plane_index
, int add
){
396 const int mb_h
= s
->b_height
<< s
->block_max_depth
;
398 for(mb_y
=0; mb_y
<=mb_h
; mb_y
++)
399 predict_slice(s
, buf
, plane_index
, add
, mb_y
);
402 static inline void set_blocks(SnowContext
*s
, int level
, int x
, int y
, int l
, int cb
, int cr
, int mx
, int my
, int ref
, int type
){
403 const int w
= s
->b_width
<< s
->block_max_depth
;
404 const int rem_depth
= s
->block_max_depth
- level
;
405 const int index
= (x
+ y
*w
) << rem_depth
;
406 const int block_w
= 1<<rem_depth
;
407 const int block_h
= 1<<rem_depth
; //FIXME "w!=h"
420 for(j
=0; j
<block_h
; j
++){
421 for(i
=0; i
<block_w
; i
++){
422 s
->block
[index
+ i
+ j
*w
]= block
;
427 extern const int8_t ff_quant3bA
[256];
429 #define QEXPSHIFT (7-FRAC_BITS+8) //FIXME try to change this to 0
431 #endif /* AVCODEC_SNOW_H */