## ffmpeg / libavcodec / rv40.c @ ce5e49b0

History | View | Annotate | Download (26.5 KB)

1 | ae4ca617 | Kostya Shishkov | ```
/*
``` |
---|---|---|---|

2 | ```
* RV40 decoder
``` |
||

3 | ```
* Copyright (c) 2007 Konstantin Shishkov
``` |
||

4 | ```
*
``` |
||

5 | ```
* This file is part of FFmpeg.
``` |
||

6 | ```
*
``` |
||

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.
``` |
||

11 | ```
*
``` |
||

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.
``` |
||

16 | ```
*
``` |
||

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
``` |
||

20 | ```
*/
``` |
||

21 | |||

22 | ```
/**
``` |
||

23 | ba87f080 | Diego Biurrun | ```
* @file
``` |

24 | ae4ca617 | Kostya Shishkov | ```
* RV40 decoder
``` |

25 | ```
*/
``` |
||

26 | |||

27 | 7ffe76e5 | Reinhard Tartler | #include "libavutil/imgutils.h" |

28 | 6ce9b431 | Stefano Sabatini | |

29 | ae4ca617 | Kostya Shishkov | #include "avcodec.h" |

30 | #include "dsputil.h" |
||

31 | #include "mpegvideo.h" |
||

32 | 4978618b | Kostya Shishkov | #include "golomb.h" |

33 | ae4ca617 | Kostya Shishkov | |

34 | #include "rv34.h" |
||

35 | #include "rv40vlc2.h" |
||

36 | #include "rv40data.h" |
||

37 | |||

38 | ```
static VLC aic_top_vlc;
``` |
||

39 | ```
static VLC aic_mode1_vlc[AIC_MODE1_NUM], aic_mode2_vlc[AIC_MODE2_NUM];
``` |
||

40 | ```
static VLC ptype_vlc[NUM_PTYPE_VLCS], btype_vlc[NUM_BTYPE_VLCS];
``` |
||

41 | |||

42 | 0a044f0f | Kostya Shishkov | static const int16_t mode2_offs[] = { |

43 | 0, 614, 1222, 1794, 2410, 3014, 3586, 4202, 4792, 5382, 5966, 6542, |
||

44 | 7138, 7716, 8292, 8864, 9444, 10030, 10642, 11212, 11814 |
||

45 | }; |
||

46 | |||

47 | ae4ca617 | Kostya Shishkov | ```
/**
``` |

48 | ```
* Initialize all tables.
``` |
||

49 | ```
*/
``` |
||

50 | dc8a7c93 | Diego Biurrun | static av_cold void rv40_init_tables(void) |

51 | ae4ca617 | Kostya Shishkov | { |

52 | ```
int i;
``` |
||

53 | 0a044f0f | Kostya Shishkov | static VLC_TYPE aic_table[1 << AIC_TOP_BITS][2]; |

54 | static VLC_TYPE aic_mode1_table[AIC_MODE1_NUM << AIC_MODE1_BITS][2]; |
||

55 | static VLC_TYPE aic_mode2_table[11814][2]; |
||

56 | static VLC_TYPE ptype_table[NUM_PTYPE_VLCS << PTYPE_VLC_BITS][2]; |
||

57 | static VLC_TYPE btype_table[NUM_BTYPE_VLCS << BTYPE_VLC_BITS][2]; |
||

58 | ae4ca617 | Kostya Shishkov | |

59 | 0a044f0f | Kostya Shishkov | aic_top_vlc.table = aic_table; |

60 | ```
aic_top_vlc.table_allocated = 1 << AIC_TOP_BITS;
``` |
||

61 | ae4ca617 | Kostya Shishkov | init_vlc(&aic_top_vlc, AIC_TOP_BITS, AIC_TOP_SIZE, |

62 | rv40_aic_top_vlc_bits, 1, 1, |
||

63 | 0a044f0f | Kostya Shishkov | rv40_aic_top_vlc_codes, 1, 1, INIT_VLC_USE_NEW_STATIC); |

64 | ae4ca617 | Kostya Shishkov | for(i = 0; i < AIC_MODE1_NUM; i++){ |

65 | ```
// Every tenth VLC table is empty
``` |
||

66 | if((i % 10) == 9) continue; |
||

67 | 0a044f0f | Kostya Shishkov | aic_mode1_vlc[i].table = &aic_mode1_table[i << AIC_MODE1_BITS]; |

68 | ```
aic_mode1_vlc[i].table_allocated = 1 << AIC_MODE1_BITS;
``` |
||

69 | ae4ca617 | Kostya Shishkov | init_vlc(&aic_mode1_vlc[i], AIC_MODE1_BITS, AIC_MODE1_SIZE, |

70 | aic_mode1_vlc_bits[i], 1, 1, |
||

71 | 0a044f0f | Kostya Shishkov | aic_mode1_vlc_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); |

72 | ae4ca617 | Kostya Shishkov | } |

73 | for(i = 0; i < AIC_MODE2_NUM; i++){ |
||

74 | 0a044f0f | Kostya Shishkov | aic_mode2_vlc[i].table = &aic_mode2_table[mode2_offs[i]]; |

75 | ```
aic_mode2_vlc[i].table_allocated = mode2_offs[i + 1] - mode2_offs[i];
``` |
||

76 | ae4ca617 | Kostya Shishkov | init_vlc(&aic_mode2_vlc[i], AIC_MODE2_BITS, AIC_MODE2_SIZE, |

77 | aic_mode2_vlc_bits[i], 1, 1, |
||

78 | 0a044f0f | Kostya Shishkov | aic_mode2_vlc_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); |

79 | ae4ca617 | Kostya Shishkov | } |

80 | 0a044f0f | Kostya Shishkov | for(i = 0; i < NUM_PTYPE_VLCS; i++){ |

81 | 120ac262 | Kostya Shishkov | ptype_vlc[i].table = &ptype_table[i << PTYPE_VLC_BITS]; |

82 | ```
ptype_vlc[i].table_allocated = 1 << PTYPE_VLC_BITS;
``` |
||

83 | init_vlc_sparse(&ptype_vlc[i], PTYPE_VLC_BITS, PTYPE_VLC_SIZE, |
||

84 | ae4ca617 | Kostya Shishkov | ptype_vlc_bits[i], 1, 1, |

85 | ptype_vlc_codes[i], 1, 1, |
||

86 | 0a044f0f | Kostya Shishkov | ptype_vlc_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); |

87 | } |
||

88 | for(i = 0; i < NUM_BTYPE_VLCS; i++){ |
||

89 | 120ac262 | Kostya Shishkov | btype_vlc[i].table = &btype_table[i << BTYPE_VLC_BITS]; |

90 | ```
btype_vlc[i].table_allocated = 1 << BTYPE_VLC_BITS;
``` |
||

91 | init_vlc_sparse(&btype_vlc[i], BTYPE_VLC_BITS, BTYPE_VLC_SIZE, |
||

92 | ae4ca617 | Kostya Shishkov | btype_vlc_bits[i], 1, 1, |

93 | btype_vlc_codes[i], 1, 1, |
||

94 | 0a044f0f | Kostya Shishkov | btype_vlc_syms, 1, 1, INIT_VLC_USE_NEW_STATIC); |

95 | } |
||

96 | ae4ca617 | Kostya Shishkov | } |

97 | |||

98 | ```
/**
``` |
||

99 | ```
* Get stored dimension from bitstream.
``` |
||

100 | ```
*
``` |
||

101 | ```
* If the width/height is the standard one then it's coded as a 3-bit index.
``` |
||

102 | ```
* Otherwise it is coded as escaped 8-bit portions.
``` |
||

103 | ```
*/
``` |
||

104 | static int get_dimension(GetBitContext *gb, const int *dim) |
||

105 | { |
||

106 | int t = get_bits(gb, 3); |
||

107 | ```
int val = dim[t];
``` |
||

108 | if(val < 0) |
||

109 | val = dim[get_bits1(gb) - val]; |
||

110 | ```
if(!val){
``` |
||

111 | ```
do{
``` |
||

112 | ```
t = get_bits(gb, 8);
``` |
||

113 | ```
val += t << 2;
``` |
||

114 | }while(t == 0xFF); |
||

115 | } |
||

116 | ```
return val;
``` |
||

117 | } |
||

118 | |||

119 | ```
/**
``` |
||

120 | ```
* Get encoded picture size - usually this is called from rv40_parse_slice_header.
``` |
||

121 | ```
*/
``` |
||

122 | static void rv40_parse_picture_size(GetBitContext *gb, int *w, int *h) |
||

123 | { |
||

124 | *w = get_dimension(gb, rv40_standard_widths); |
||

125 | *h = get_dimension(gb, rv40_standard_heights); |
||

126 | } |
||

127 | |||

128 | static int rv40_parse_slice_header(RV34DecContext *r, GetBitContext *gb, SliceInfo *si) |
||

129 | { |
||

130 | 39902a8c | Kostya Shishkov | ```
int mb_bits;
``` |

131 | ae4ca617 | Kostya Shishkov | ```
int w = r->s.width, h = r->s.height;
``` |

132 | ```
int mb_size;
``` |
||

133 | |||

134 | memset(si, 0, sizeof(SliceInfo)); |
||

135 | ```
if(get_bits1(gb))
``` |
||

136 | return -1; |
||

137 | ```
si->type = get_bits(gb, 2);
``` |
||

138 | if(si->type == 1) si->type = 0; |
||

139 | ```
si->quant = get_bits(gb, 5);
``` |
||

140 | if(get_bits(gb, 2)) |
||

141 | return -1; |
||

142 | ```
si->vlc_set = get_bits(gb, 2);
``` |
||

143 | skip_bits1(gb); |
||

144 | 39902a8c | Kostya Shishkov | ```
si->pts = get_bits(gb, 13);
``` |

145 | ae4ca617 | Kostya Shishkov | ```
if(!si->type || !get_bits1(gb))
``` |

146 | rv40_parse_picture_size(gb, &w, &h); |
||

147 | e16f217c | Stefano Sabatini | if(av_image_check_size(w, h, 0, r->s.avctx) < 0) |

148 | b192e564 | Kostya Shishkov | return -1; |

149 | ae4ca617 | Kostya Shishkov | si->width = w; |

150 | si->height = h; |
||

151 | mb_size = ((w + 15) >> 4) * ((h + 15) >> 4); |
||

152 | mb_bits = ff_rv34_get_start_offset(gb, mb_size); |
||

153 | si->start = get_bits(gb, mb_bits); |
||

154 | |||

155 | return 0; |
||

156 | } |
||

157 | |||

158 | ```
/**
``` |
||

159 | ```
* Decode 4x4 intra types array.
``` |
||

160 | ```
*/
``` |
||

161 | ea61e33a | Kostya Shishkov | static int rv40_decode_intra_types(RV34DecContext *r, GetBitContext *gb, int8_t *dst) |

162 | ae4ca617 | Kostya Shishkov | { |

163 | MpegEncContext *s = &r->s; |
||

164 | ```
int i, j, k, v;
``` |
||

165 | ```
int A, B, C;
``` |
||

166 | ```
int pattern;
``` |
||

167 | ea61e33a | Kostya Shishkov | int8_t *ptr; |

168 | ae4ca617 | Kostya Shishkov | |

169 | 39c601b5 | Kostya Shishkov | for(i = 0; i < 4; i++, dst += r->intra_types_stride){ |

170 | ae4ca617 | Kostya Shishkov | ```
if(!i && s->first_slice_line){
``` |

171 | ```
pattern = get_vlc2(gb, aic_top_vlc.table, AIC_TOP_BITS, 1);
``` |
||

172 | dst[0] = (pattern >> 2) & 2; |
||

173 | dst[1] = (pattern >> 1) & 2; |
||

174 | dst[2] = pattern & 2; |
||

175 | dst[3] = (pattern << 1) & 2; |
||

176 | ```
continue;
``` |
||

177 | } |
||

178 | ptr = dst; |
||

179 | for(j = 0; j < 4; j++){ |
||

180 | ```
/* Coefficients are read using VLC chosen by the prediction pattern
``` |
||

181 | ```
* The first one (used for retrieving a pair of coefficients) is
``` |
||

182 | ```
* constructed from the top, top right and left coefficients
``` |
||

183 | ```
* The second one (used for retrieving only one coefficient) is
``` |
||

184 | ```
* top + 10 * left.
``` |
||

185 | ```
*/
``` |
||

186 | 39c601b5 | Kostya Shishkov | A = ptr[-r->intra_types_stride + 1]; // it won't be used for the last coefficient in a row |

187 | B = ptr[-r->intra_types_stride]; |
||

188 | ae4ca617 | Kostya Shishkov | ```
C = ptr[-1];
``` |

189 | pattern = A + (B << 4) + (C << 8); |
||

190 | for(k = 0; k < MODE2_PATTERNS_NUM; k++) |
||

191 | ```
if(pattern == rv40_aic_table_index[k])
``` |
||

192 | ```
break;
``` |
||

193 | if(j < 3 && k < MODE2_PATTERNS_NUM){ //pattern is found, decoding 2 coefficients |
||

194 | ```
v = get_vlc2(gb, aic_mode2_vlc[k].table, AIC_MODE2_BITS, 2);
``` |
||

195 | ```
*ptr++ = v/9;
``` |
||

196 | ```
*ptr++ = v%9;
``` |
||

197 | j++; |
||

198 | ```
}else{
``` |
||

199 | if(B != -1 && C != -1) |
||

200 | v = get_vlc2(gb, aic_mode1_vlc[B + C*10].table, AIC_MODE1_BITS, 1); |
||

201 | else{ // tricky decoding |
||

202 | ```
v = 0;
``` |
||

203 | ```
switch(C){
``` |
||

204 | case -1: // code 0 -> 1, 1 -> 0 |
||

205 | if(B < 2) |
||

206 | ```
v = get_bits1(gb) ^ 1;
``` |
||

207 | ```
break;
``` |
||

208 | case 0: |
||

209 | case 2: // code 0 -> 2, 1 -> 0 |
||

210 | v = (get_bits1(gb) ^ 1) << 1; |
||

211 | ```
break;
``` |
||

212 | } |
||

213 | } |
||

214 | *ptr++ = v; |
||

215 | } |
||

216 | } |
||

217 | } |
||

218 | return 0; |
||

219 | } |
||

220 | |||

221 | ```
/**
``` |
||

222 | ```
* Decode macroblock information.
``` |
||

223 | ```
*/
``` |
||

224 | static int rv40_decode_mb_info(RV34DecContext *r) |
||

225 | { |
||

226 | MpegEncContext *s = &r->s; |
||

227 | GetBitContext *gb = &s->gb; |
||

228 | ```
int q, i;
``` |
||

229 | int prev_type = 0; |
||

230 | ```
int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
``` |
||

231 | int blocks[RV34_MB_TYPES] = {0}; |
||

232 | int count = 0; |
||

233 | |||

234 | ```
if(!r->s.mb_skip_run)
``` |
||

235 | 4978618b | Kostya Shishkov | ```
r->s.mb_skip_run = svq3_get_ue_golomb(gb) + 1;
``` |

236 | ae4ca617 | Kostya Shishkov | |

237 | ```
if(--r->s.mb_skip_run)
``` |
||

238 | ```
return RV34_MB_SKIP;
``` |
||

239 | |||

240 | 20622c4a | Kostya Shishkov | if(r->avail_cache[6-1]) |

241 | ae4ca617 | Kostya Shishkov | ```
blocks[r->mb_type[mb_pos - 1]]++;
``` |

242 | 20622c4a | Kostya Shishkov | if(r->avail_cache[6-4]){ |

243 | ae4ca617 | Kostya Shishkov | blocks[r->mb_type[mb_pos - s->mb_stride]]++; |

244 | 20622c4a | Kostya Shishkov | if(r->avail_cache[6-2]) |

245 | ae4ca617 | Kostya Shishkov | ```
blocks[r->mb_type[mb_pos - s->mb_stride + 1]]++;
``` |

246 | 20622c4a | Kostya Shishkov | if(r->avail_cache[6-5]) |

247 | ae4ca617 | Kostya Shishkov | ```
blocks[r->mb_type[mb_pos - s->mb_stride - 1]]++;
``` |

248 | } |
||

249 | |||

250 | for(i = 0; i < RV34_MB_TYPES; i++){ |
||

251 | ```
if(blocks[i] > count){
``` |
||

252 | count = blocks[i]; |
||

253 | prev_type = i; |
||

254 | } |
||

255 | } |
||

256 | ce5e49b0 | Stefano Sabatini | ```
if(s->pict_type == AV_PICTURE_TYPE_P){
``` |

257 | ae4ca617 | Kostya Shishkov | prev_type = block_num_to_ptype_vlc_num[prev_type]; |

258 | ```
q = get_vlc2(gb, ptype_vlc[prev_type].table, PTYPE_VLC_BITS, 1);
``` |
||

259 | ```
if(q < PBTYPE_ESCAPE)
``` |
||

260 | ```
return q;
``` |
||

261 | ```
q = get_vlc2(gb, ptype_vlc[prev_type].table, PTYPE_VLC_BITS, 1);
``` |
||

262 | ```
av_log(s->avctx, AV_LOG_ERROR, "Dquant for P-frame\n");
``` |
||

263 | ```
}else{
``` |
||

264 | prev_type = block_num_to_btype_vlc_num[prev_type]; |
||

265 | ```
q = get_vlc2(gb, btype_vlc[prev_type].table, BTYPE_VLC_BITS, 1);
``` |
||

266 | ```
if(q < PBTYPE_ESCAPE)
``` |
||

267 | ```
return q;
``` |
||

268 | ```
q = get_vlc2(gb, btype_vlc[prev_type].table, BTYPE_VLC_BITS, 1);
``` |
||

269 | ```
av_log(s->avctx, AV_LOG_ERROR, "Dquant for B-frame\n");
``` |
||

270 | } |
||

271 | return 0; |
||

272 | } |
||

273 | |||

274 | 70f42303 | Kostya Shishkov | ```
#define CLIP_SYMM(a, b) av_clip(a, -(b), b)
``` |

275 | ```
/**
``` |
||

276 | ```
* weaker deblocking very similar to the one described in 4.4.2 of JVT-A003r1
``` |
||

277 | ```
*/
``` |
||

278 | static inline void rv40_weak_loop_filter(uint8_t *src, const int step, |
||

279 | const int filter_p1, const int filter_q1, |
||

280 | const int alpha, const int beta, |
||

281 | const int lim_p0q0, |
||

282 | const int lim_q1, const int lim_p1, |
||

283 | const int diff_p1p0, const int diff_q1q0, |
||

284 | const int diff_p1p2, const int diff_q1q2) |
||

285 | { |
||

286 | uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; |
||

287 | ```
int t, u, diff;
``` |
||

288 | |||

289 | t = src[0*step] - src[-1*step]; |
||

290 | ```
if(!t)
``` |
||

291 | ```
return;
``` |
||

292 | ```
u = (alpha * FFABS(t)) >> 7;
``` |
||

293 | if(u > 3 - (filter_p1 && filter_q1)) |
||

294 | ```
return;
``` |
||

295 | |||

296 | ```
t <<= 2;
``` |
||

297 | ```
if(filter_p1 && filter_q1)
``` |
||

298 | t += src[-2*step] - src[1*step]; |
||

299 | diff = CLIP_SYMM((t + 4) >> 3, lim_p0q0); |
||

300 | src[-1*step] = cm[src[-1*step] + diff]; |
||

301 | src[ 0*step] = cm[src[ 0*step] - diff]; |
||

302 | ```
if(FFABS(diff_p1p2) <= beta && filter_p1){
``` |
||

303 | ```
t = (diff_p1p0 + diff_p1p2 - diff) >> 1;
``` |
||

304 | src[-2*step] = cm[src[-2*step] - CLIP_SYMM(t, lim_p1)]; |
||

305 | } |
||

306 | ```
if(FFABS(diff_q1q2) <= beta && filter_q1){
``` |
||

307 | ```
t = (diff_q1q0 + diff_q1q2 + diff) >> 1;
``` |
||

308 | src[ 1*step] = cm[src[ 1*step] - CLIP_SYMM(t, lim_q1)]; |
||

309 | } |
||

310 | } |
||

311 | |||

312 | dd8e127a | MÃ¥ns RullgÃ¥rd | static av_always_inline void rv40_adaptive_loop_filter(uint8_t *src, const int step, |

313 | e9d0fdef | Kostya Shishkov | const int stride, const int dmode, |

314 | const int lim_q1, const int lim_p1, |
||

315 | const int alpha, |
||

316 | const int beta, const int beta2, |
||

317 | const int chroma, const int edge) |
||

318 | { |
||

319 | int diff_p1p0[4], diff_q1q0[4], diff_p1p2[4], diff_q1q2[4]; |
||

320 | int sum_p1p0 = 0, sum_q1q0 = 0, sum_p1p2 = 0, sum_q1q2 = 0; |
||

321 | uint8_t *ptr; |
||

322 | int flag_strong0 = 1, flag_strong1 = 1; |
||

323 | ```
int filter_p1, filter_q1;
``` |
||

324 | ```
int i;
``` |
||

325 | ```
int lims;
``` |
||

326 | |||

327 | for(i = 0, ptr = src; i < 4; i++, ptr += stride){ |
||

328 | diff_p1p0[i] = ptr[-2*step] - ptr[-1*step]; |
||

329 | diff_q1q0[i] = ptr[ 1*step] - ptr[ 0*step]; |
||

330 | sum_p1p0 += diff_p1p0[i]; |
||

331 | sum_q1q0 += diff_q1q0[i]; |
||

332 | } |
||

333 | ```
filter_p1 = FFABS(sum_p1p0) < (beta<<2);
``` |
||

334 | ```
filter_q1 = FFABS(sum_q1q0) < (beta<<2);
``` |
||

335 | ```
if(!filter_p1 && !filter_q1)
``` |
||

336 | ```
return;
``` |
||

337 | |||

338 | for(i = 0, ptr = src; i < 4; i++, ptr += stride){ |
||

339 | diff_p1p2[i] = ptr[-2*step] - ptr[-3*step]; |
||

340 | diff_q1q2[i] = ptr[ 1*step] - ptr[ 2*step]; |
||

341 | sum_p1p2 += diff_p1p2[i]; |
||

342 | sum_q1q2 += diff_q1q2[i]; |
||

343 | } |
||

344 | |||

345 | ```
if(edge){
``` |
||

346 | flag_strong0 = filter_p1 && (FFABS(sum_p1p2) < beta2); |
||

347 | flag_strong1 = filter_q1 && (FFABS(sum_q1q2) < beta2); |
||

348 | ```
}else{
``` |
||

349 | ```
flag_strong0 = flag_strong1 = 0;
``` |
||

350 | } |
||

351 | |||

352 | lims = filter_p1 + filter_q1 + ((lim_q1 + lim_p1) >> 1) + 1; |
||

353 | if(flag_strong0 && flag_strong1){ /* strong filtering */ |
||

354 | for(i = 0; i < 4; i++, src += stride){ |
||

355 | ```
int sflag, p0, q0, p1, q1;
``` |
||

356 | int t = src[0*step] - src[-1*step]; |
||

357 | |||

358 | if(!t) continue; |
||

359 | ```
sflag = (alpha * FFABS(t)) >> 7;
``` |
||

360 | if(sflag > 1) continue; |
||

361 | |||

362 | p0 = (25*src[-3*step] + 26*src[-2*step] |
||

363 | + 26*src[-1*step] |
||

364 | + 26*src[ 0*step] + 25*src[ 1*step] + rv40_dither_l[dmode + i]) >> 7; |
||

365 | q0 = (25*src[-2*step] + 26*src[-1*step] |
||

366 | + 26*src[ 0*step] |
||

367 | + 26*src[ 1*step] + 25*src[ 2*step] + rv40_dither_r[dmode + i]) >> 7; |
||

368 | ```
if(sflag){
``` |
||

369 | p0 = av_clip(p0, src[-1*step] - lims, src[-1*step] + lims); |
||

370 | q0 = av_clip(q0, src[ 0*step] - lims, src[ 0*step] + lims); |
||

371 | } |
||

372 | p1 = (25*src[-4*step] + 26*src[-3*step] |
||

373 | + 26*src[-2*step] |
||

374 | + 26*p0 + 25*src[ 0*step] + rv40_dither_l[dmode + i]) >> 7; |
||

375 | q1 = (25*src[-1*step] + 26*q0 |
||

376 | + 26*src[ 1*step] |
||

377 | + 26*src[ 2*step] + 25*src[ 3*step] + rv40_dither_r[dmode + i]) >> 7; |
||

378 | ```
if(sflag){
``` |
||

379 | p1 = av_clip(p1, src[-2*step] - lims, src[-2*step] + lims); |
||

380 | q1 = av_clip(q1, src[ 1*step] - lims, src[ 1*step] + lims); |
||

381 | } |
||

382 | ```
src[-2*step] = p1;
``` |
||

383 | ```
src[-1*step] = p0;
``` |
||

384 | ```
src[ 0*step] = q0;
``` |
||

385 | ```
src[ 1*step] = q1;
``` |
||

386 | ```
if(!chroma){
``` |
||

387 | src[-3*step] = (25*src[-1*step] + 26*src[-2*step] + 51*src[-3*step] + 26*src[-4*step] + 64) >> 7; |
||

388 | src[ 2*step] = (25*src[ 0*step] + 26*src[ 1*step] + 51*src[ 2*step] + 26*src[ 3*step] + 64) >> 7; |
||

389 | } |
||

390 | } |
||

391 | }else if(filter_p1 && filter_q1){ |
||

392 | for(i = 0; i < 4; i++, src += stride) |
||

393 | rv40_weak_loop_filter(src, step, 1, 1, alpha, beta, lims, lim_q1, lim_p1, |
||

394 | diff_p1p0[i], diff_q1q0[i], diff_p1p2[i], diff_q1q2[i]); |
||

395 | ```
}else{
``` |
||

396 | for(i = 0; i < 4; i++, src += stride) |
||

397 | rv40_weak_loop_filter(src, step, filter_p1, filter_q1, |
||

398 | alpha, beta, lims>>1, lim_q1>>1, lim_p1>>1, |
||

399 | diff_p1p0[i], diff_q1q0[i], diff_p1p2[i], diff_q1q2[i]); |
||

400 | } |
||

401 | } |
||

402 | |||

403 | static void rv40_v_loop_filter(uint8_t *src, int stride, int dmode, |
||

404 | int lim_q1, int lim_p1, |
||

405 | int alpha, int beta, int beta2, int chroma, int edge){ |
||

406 | ```
rv40_adaptive_loop_filter(src, 1, stride, dmode, lim_q1, lim_p1,
``` |
||

407 | alpha, beta, beta2, chroma, edge); |
||

408 | } |
||

409 | static void rv40_h_loop_filter(uint8_t *src, int stride, int dmode, |
||

410 | int lim_q1, int lim_p1, |
||

411 | int alpha, int beta, int beta2, int chroma, int edge){ |
||

412 | ```
rv40_adaptive_loop_filter(src, stride, 1, dmode, lim_q1, lim_p1,
``` |
||

413 | alpha, beta, beta2, chroma, edge); |
||

414 | } |
||

415 | |||

416 | d33ee3f2 | Kostya Shishkov | ```
enum RV40BlockPos{
``` |

417 | POS_CUR, |
||

418 | POS_TOP, |
||

419 | POS_LEFT, |
||

420 | POS_BOTTOM, |
||

421 | }; |
||

422 | |||

423 | #define MASK_CUR 0x0001 |
||

424 | #define MASK_RIGHT 0x0008 |
||

425 | #define MASK_BOTTOM 0x0010 |
||

426 | #define MASK_TOP 0x1000 |
||

427 | #define MASK_Y_TOP_ROW 0x000F |
||

428 | #define MASK_Y_LAST_ROW 0xF000 |
||

429 | #define MASK_Y_LEFT_COL 0x1111 |
||

430 | #define MASK_Y_RIGHT_COL 0x8888 |
||

431 | #define MASK_C_TOP_ROW 0x0003 |
||

432 | #define MASK_C_LAST_ROW 0x000C |
||

433 | #define MASK_C_LEFT_COL 0x0005 |
||

434 | #define MASK_C_RIGHT_COL 0x000A |
||

435 | |||

436 | static const int neighbour_offs_x[4] = { 0, 0, -1, 0 }; |
||

437 | static const int neighbour_offs_y[4] = { 0, -1, 0, 1 }; |
||

438 | |||

439 | ```
/**
``` |
||

440 | ```
* RV40 loop filtering function
``` |
||

441 | ```
*/
``` |
||

442 | static void rv40_loop_filter(RV34DecContext *r, int row) |
||

443 | { |
||

444 | MpegEncContext *s = &r->s; |
||

445 | ```
int mb_pos, mb_x;
``` |
||

446 | ```
int i, j, k;
``` |
||

447 | uint8_t *Y, *C; |
||

448 | ```
int alpha, beta, betaY, betaC;
``` |
||

449 | ```
int q;
``` |
||

450 | int mbtype[4]; ///< current macroblock and its neighbours types |
||

451 | ```
/**
``` |
||

452 | ```
* flags indicating that macroblock can be filtered with strong filter
``` |
||

453 | ```
* it is set only for intra coded MB and MB with DCs coded separately
``` |
||

454 | ```
*/
``` |
||

455 | int mb_strong[4]; |
||

456 | int clip[4]; ///< MB filter clipping value calculated from filtering strength |
||

457 | ```
/**
``` |
||

458 | ```
* coded block patterns for luma part of current macroblock and its neighbours
``` |
||

459 | ```
* Format:
``` |
||

460 | ```
* LSB corresponds to the top left block,
``` |
||

461 | ```
* each nibble represents one row of subblocks.
``` |
||

462 | ```
*/
``` |
||

463 | int cbp[4]; |
||

464 | ```
/**
``` |
||

465 | ```
* coded block patterns for chroma part of current macroblock and its neighbours
``` |
||

466 | ```
* Format is the same as for luma with two subblocks in a row.
``` |
||

467 | ```
*/
``` |
||

468 | int uvcbp[4][2]; |
||

469 | ```
/**
``` |
||

470 | ```
* This mask represents the pattern of luma subblocks that should be filtered
``` |
||

471 | ```
* in addition to the coded ones because because they lie at the edge of
``` |
||

472 | ```
* 8x8 block with different enough motion vectors
``` |
||

473 | ```
*/
``` |
||

474 | int mvmasks[4]; |
||

475 | |||

476 | mb_pos = row * s->mb_stride; |
||

477 | for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ |
||

478 | ```
int mbtype = s->current_picture_ptr->mb_type[mb_pos];
``` |
||

479 | ```
if(IS_INTRA(mbtype) || IS_SEPARATE_DC(mbtype))
``` |
||

480 | 6c3fca64 | Kostya Shishkov | ```
r->cbp_luma [mb_pos] = r->deblock_coefs[mb_pos] = 0xFFFF;
``` |

481 | d33ee3f2 | Kostya Shishkov | ```
if(IS_INTRA(mbtype))
``` |

482 | ```
r->cbp_chroma[mb_pos] = 0xFF;
``` |
||

483 | } |
||

484 | mb_pos = row * s->mb_stride; |
||

485 | for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ |
||

486 | ```
int y_h_deblock, y_v_deblock;
``` |
||

487 | int c_v_deblock[2], c_h_deblock[2]; |
||

488 | ```
int clip_left;
``` |
||

489 | int avail[4]; |
||

490 | int y_to_deblock, c_to_deblock[2]; |
||

491 | |||

492 | q = s->current_picture_ptr->qscale_table[mb_pos]; |
||

493 | alpha = rv40_alpha_tab[q]; |
||

494 | beta = rv40_beta_tab [q]; |
||

495 | ```
betaY = betaC = beta * 3;
``` |
||

496 | if(s->width * s->height <= 176*144) |
||

497 | betaY += beta; |
||

498 | |||

499 | avail[0] = 1; |
||

500 | ```
avail[1] = row;
``` |
||

501 | ```
avail[2] = mb_x;
``` |
||

502 | avail[3] = row < s->mb_height - 1; |
||

503 | for(i = 0; i < 4; i++){ |
||

504 | ```
if(avail[i]){
``` |
||

505 | ```
int pos = mb_pos + neighbour_offs_x[i] + neighbour_offs_y[i]*s->mb_stride;
``` |
||

506 | mvmasks[i] = r->deblock_coefs[pos]; |
||

507 | mbtype [i] = s->current_picture_ptr->mb_type[pos]; |
||

508 | cbp [i] = r->cbp_luma[pos]; |
||

509 | uvcbp[i][0] = r->cbp_chroma[pos] & 0xF; |
||

510 | uvcbp[i][1] = r->cbp_chroma[pos] >> 4; |
||

511 | ```
}else{
``` |
||

512 | ```
mvmasks[i] = 0;
``` |
||

513 | ```
mbtype [i] = mbtype[0];
``` |
||

514 | ```
cbp [i] = 0;
``` |
||

515 | uvcbp[i][0] = uvcbp[i][1] = 0; |
||

516 | } |
||

517 | mb_strong[i] = IS_INTRA(mbtype[i]) || IS_SEPARATE_DC(mbtype[i]); |
||

518 | ```
clip[i] = rv40_filter_clip_tbl[mb_strong[i] + 1][q];
``` |
||

519 | } |
||

520 | 6c3fca64 | Kostya Shishkov | y_to_deblock = mvmasks[POS_CUR] |

521 | d33ee3f2 | Kostya Shishkov | ```
| (mvmasks[POS_BOTTOM] << 16);
``` |

522 | ```
/* This pattern contains bits signalling that horizontal edges of
``` |
||

523 | ```
* the current block can be filtered.
``` |
||

524 | ```
* That happens when either of adjacent subblocks is coded or lies on
``` |
||

525 | ```
* the edge of 8x8 blocks with motion vectors differing by more than
``` |
||

526 | ```
* 3/4 pel in any component (any edge orientation for some reason).
``` |
||

527 | ```
*/
``` |
||

528 | y_h_deblock = y_to_deblock |
||

529 | ```
| ((cbp[POS_CUR] << 4) & ~MASK_Y_TOP_ROW)
``` |
||

530 | ```
| ((cbp[POS_TOP] & MASK_Y_LAST_ROW) >> 12);
``` |
||

531 | ```
/* This pattern contains bits signalling that vertical edges of
``` |
||

532 | ```
* the current block can be filtered.
``` |
||

533 | ```
* That happens when either of adjacent subblocks is coded or lies on
``` |
||

534 | ```
* the edge of 8x8 blocks with motion vectors differing by more than
``` |
||

535 | ```
* 3/4 pel in any component (any edge orientation for some reason).
``` |
||

536 | ```
*/
``` |
||

537 | y_v_deblock = y_to_deblock |
||

538 | ```
| ((cbp[POS_CUR] << 1) & ~MASK_Y_LEFT_COL)
``` |
||

539 | ```
| ((cbp[POS_LEFT] & MASK_Y_RIGHT_COL) >> 3);
``` |
||

540 | ```
if(!mb_x)
``` |
||

541 | y_v_deblock &= ~MASK_Y_LEFT_COL; |
||

542 | ```
if(!row)
``` |
||

543 | y_h_deblock &= ~MASK_Y_TOP_ROW; |
||

544 | if(row == s->mb_height - 1 || (mb_strong[POS_CUR] || mb_strong[POS_BOTTOM])) |
||

545 | ```
y_h_deblock &= ~(MASK_Y_TOP_ROW << 16);
``` |
||

546 | ```
/* Calculating chroma patterns is similar and easier since there is
``` |
||

547 | ```
* no motion vector pattern for them.
``` |
||

548 | ```
*/
``` |
||

549 | for(i = 0; i < 2; i++){ |
||

550 | ```
c_to_deblock[i] = (uvcbp[POS_BOTTOM][i] << 4) | uvcbp[POS_CUR][i];
``` |
||

551 | c_v_deblock[i] = c_to_deblock[i] |
||

552 | ```
| ((uvcbp[POS_CUR] [i] << 1) & ~MASK_C_LEFT_COL)
``` |
||

553 | ```
| ((uvcbp[POS_LEFT][i] & MASK_C_RIGHT_COL) >> 1);
``` |
||

554 | c_h_deblock[i] = c_to_deblock[i] |
||

555 | ```
| ((uvcbp[POS_TOP][i] & MASK_C_LAST_ROW) >> 2)
``` |
||

556 | ```
| (uvcbp[POS_CUR][i] << 2);
``` |
||

557 | ```
if(!mb_x)
``` |
||

558 | c_v_deblock[i] &= ~MASK_C_LEFT_COL; |
||

559 | ```
if(!row)
``` |
||

560 | c_h_deblock[i] &= ~MASK_C_TOP_ROW; |
||

561 | if(row == s->mb_height - 1 || mb_strong[POS_CUR] || mb_strong[POS_BOTTOM]) |
||

562 | ```
c_h_deblock[i] &= ~(MASK_C_TOP_ROW << 4);
``` |
||

563 | } |
||

564 | |||

565 | for(j = 0; j < 16; j += 4){ |
||

566 | Y = s->current_picture_ptr->data[0] + mb_x*16 + (row*16 + j) * s->linesize; |
||

567 | for(i = 0; i < 4; i++, Y += 4){ |
||

568 | ```
int ij = i + j;
``` |
||

569 | int clip_cur = y_to_deblock & (MASK_CUR << ij) ? clip[POS_CUR] : 0; |
||

570 | int dither = j ? ij : i*4; |
||

571 | |||

572 | ```
// if bottom block is coded then we can filter its top edge
``` |
||

573 | ```
// (or bottom edge of this block, which is the same)
``` |
||

574 | ```
if(y_h_deblock & (MASK_BOTTOM << ij)){
``` |
||

575 | ```
rv40_h_loop_filter(Y+4*s->linesize, s->linesize, dither,
``` |
||

576 | ```
y_to_deblock & (MASK_BOTTOM << ij) ? clip[POS_CUR] : 0,
``` |
||

577 | clip_cur, |
||

578 | alpha, beta, betaY, 0, 0); |
||

579 | } |
||

580 | ```
// filter left block edge in ordinary mode (with low filtering strength)
``` |
||

581 | ```
if(y_v_deblock & (MASK_CUR << ij) && (i || !(mb_strong[POS_CUR] || mb_strong[POS_LEFT]))){
``` |
||

582 | ```
if(!i)
``` |
||

583 | 6c3fca64 | Kostya Shishkov | ```
clip_left = mvmasks[POS_LEFT] & (MASK_RIGHT << j) ? clip[POS_LEFT] : 0;
``` |

584 | d33ee3f2 | Kostya Shishkov | ```
else
``` |

585 | clip_left = y_to_deblock & (MASK_CUR << (ij-1)) ? clip[POS_CUR] : 0; |
||

586 | rv40_v_loop_filter(Y, s->linesize, dither, |
||

587 | clip_cur, |
||

588 | clip_left, |
||

589 | alpha, beta, betaY, 0, 0); |
||

590 | } |
||

591 | ```
// filter top edge of the current macroblock when filtering strength is high
``` |
||

592 | ```
if(!j && y_h_deblock & (MASK_CUR << i) && (mb_strong[POS_CUR] || mb_strong[POS_TOP])){
``` |
||

593 | rv40_h_loop_filter(Y, s->linesize, dither, |
||

594 | clip_cur, |
||

595 | 6c3fca64 | Kostya Shishkov | ```
mvmasks[POS_TOP] & (MASK_TOP << i) ? clip[POS_TOP] : 0,
``` |

596 | d33ee3f2 | Kostya Shishkov | alpha, beta, betaY, 0, 1); |

597 | } |
||

598 | ```
// filter left block edge in edge mode (with high filtering strength)
``` |
||

599 | ```
if(y_v_deblock & (MASK_CUR << ij) && !i && (mb_strong[POS_CUR] || mb_strong[POS_LEFT])){
``` |
||

600 | 6c3fca64 | Kostya Shishkov | ```
clip_left = mvmasks[POS_LEFT] & (MASK_RIGHT << j) ? clip[POS_LEFT] : 0;
``` |

601 | d33ee3f2 | Kostya Shishkov | rv40_v_loop_filter(Y, s->linesize, dither, |

602 | clip_cur, |
||

603 | clip_left, |
||

604 | alpha, beta, betaY, 0, 1); |
||

605 | } |
||

606 | } |
||

607 | } |
||

608 | for(k = 0; k < 2; k++){ |
||

609 | for(j = 0; j < 2; j++){ |
||

610 | C = s->current_picture_ptr->data[k+1] + mb_x*8 + (row*8 + j*4) * s->uvlinesize; |
||

611 | for(i = 0; i < 2; i++, C += 4){ |
||

612 | int ij = i + j*2; |
||

613 | int clip_cur = c_to_deblock[k] & (MASK_CUR << ij) ? clip[POS_CUR] : 0; |
||

614 | if(c_h_deblock[k] & (MASK_CUR << (ij+2))){ |
||

615 | int clip_bot = c_to_deblock[k] & (MASK_CUR << (ij+2)) ? clip[POS_CUR] : 0; |
||

616 | rv40_h_loop_filter(C+4*s->uvlinesize, s->uvlinesize, i*8, |
||

617 | clip_bot, |
||

618 | clip_cur, |
||

619 | alpha, beta, betaC, 1, 0); |
||

620 | } |
||

621 | ```
if((c_v_deblock[k] & (MASK_CUR << ij)) && (i || !(mb_strong[POS_CUR] || mb_strong[POS_LEFT]))){
``` |
||

622 | ```
if(!i)
``` |
||

623 | clip_left = uvcbp[POS_LEFT][k] & (MASK_CUR << (2*j+1)) ? clip[POS_LEFT] : 0; |
||

624 | ```
else
``` |
||

625 | clip_left = c_to_deblock[k] & (MASK_CUR << (ij-1)) ? clip[POS_CUR] : 0; |
||

626 | ```
rv40_v_loop_filter(C, s->uvlinesize, j*8,
``` |
||

627 | clip_cur, |
||

628 | clip_left, |
||

629 | alpha, beta, betaC, 1, 0); |
||

630 | } |
||

631 | ```
if(!j && c_h_deblock[k] & (MASK_CUR << ij) && (mb_strong[POS_CUR] || mb_strong[POS_TOP])){
``` |
||

632 | int clip_top = uvcbp[POS_TOP][k] & (MASK_CUR << (ij+2)) ? clip[POS_TOP] : 0; |
||

633 | ```
rv40_h_loop_filter(C, s->uvlinesize, i*8,
``` |
||

634 | clip_cur, |
||

635 | clip_top, |
||

636 | alpha, beta, betaC, 1, 1); |
||

637 | } |
||

638 | ```
if(c_v_deblock[k] & (MASK_CUR << ij) && !i && (mb_strong[POS_CUR] || mb_strong[POS_LEFT])){
``` |
||

639 | clip_left = uvcbp[POS_LEFT][k] & (MASK_CUR << (2*j+1)) ? clip[POS_LEFT] : 0; |
||

640 | ```
rv40_v_loop_filter(C, s->uvlinesize, j*8,
``` |
||

641 | clip_cur, |
||

642 | clip_left, |
||

643 | alpha, beta, betaC, 1, 1); |
||

644 | } |
||

645 | } |
||

646 | } |
||

647 | } |
||

648 | } |
||

649 | } |
||

650 | |||

651 | ae4ca617 | Kostya Shishkov | ```
/**
``` |

652 | ```
* Initialize decoder.
``` |
||

653 | ```
*/
``` |
||

654 | 98a6fff9 | Zuxy Meng | static av_cold int rv40_decode_init(AVCodecContext *avctx) |

655 | ae4ca617 | Kostya Shishkov | { |

656 | RV34DecContext *r = avctx->priv_data; |
||

657 | |||

658 | ```
r->rv30 = 0;
``` |
||

659 | ff_rv34_decode_init(avctx); |
||

660 | ```
if(!aic_top_vlc.bits)
``` |
||

661 | rv40_init_tables(); |
||

662 | r->parse_slice_header = rv40_parse_slice_header; |
||

663 | r->decode_intra_types = rv40_decode_intra_types; |
||

664 | r->decode_mb_info = rv40_decode_mb_info; |
||

665 | d33ee3f2 | Kostya Shishkov | r->loop_filter = rv40_loop_filter; |

666 | ae4ca617 | Kostya Shishkov | ```
r->luma_dc_quant_i = rv40_luma_dc_quant[0];
``` |

667 | ```
r->luma_dc_quant_p = rv40_luma_dc_quant[1];
``` |
||

668 | return 0; |
||

669 | } |
||

670 | |||

671 | e7e2df27 | Diego Elio PettenÃ² | AVCodec ff_rv40_decoder = { |

672 | ae4ca617 | Kostya Shishkov | ```
"rv40",
``` |

673 | 72415b2a | Stefano Sabatini | AVMEDIA_TYPE_VIDEO, |

674 | ae4ca617 | Kostya Shishkov | CODEC_ID_RV40, |

675 | ```
sizeof(RV34DecContext),
``` |
||

676 | rv40_decode_init, |
||

677 | ```
NULL,
``` |
||

678 | ff_rv34_decode_end, |
||

679 | ff_rv34_decode_frame, |
||

680 | 52b91753 | Kostya Shishkov | CODEC_CAP_DR1 | CODEC_CAP_DELAY, |

681 | 186f155e | Kostya Shishkov | .flush = ff_mpeg_flush, |

682 | fe4bf374 | Stefano Sabatini | ```
.long_name = NULL_IF_CONFIG_SMALL("RealVideo 4.0"),
``` |

683 | 09a9b45e | Michael Niedermayer | .pix_fmts= ff_pixfmt_list_420, |

684 | ae4ca617 | Kostya Shishkov | }; |