Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * RV30 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 | * @file | ||
24 | * RV30 decoder | ||
25 | */ | ||
26 | |||
27 | #include "avcodec.h" | ||
28 | #include "codec_internal.h" | ||
29 | #include "mpegutils.h" | ||
30 | #include "mpegvideo.h" | ||
31 | #include "mpegvideodec.h" | ||
32 | #include "golomb.h" | ||
33 | |||
34 | #include "rv34.h" | ||
35 | #include "rv30data.h" | ||
36 | |||
37 | |||
38 | 707 | static int rv30_parse_slice_header(RV34DecContext *r, GetBitContext *gb, SliceInfo *si) | |
39 | { | ||
40 | 707 | AVCodecContext *avctx = r->s.avctx; | |
41 | int mb_bits; | ||
42 | 707 | int w = r->s.width, h = r->s.height; | |
43 | int mb_size; | ||
44 | int rpr; | ||
45 | |||
46 | 707 | memset(si, 0, sizeof(SliceInfo)); | |
47 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 706 times.
|
707 | if(get_bits(gb, 3)) |
48 | 1 | return -1; | |
49 | 706 | si->type = get_bits(gb, 2); | |
50 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
|
706 | if(si->type == 1) si->type = 0; |
51 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 706 times.
|
706 | if(get_bits1(gb)) |
52 | ✗ | return -1; | |
53 | 706 | si->quant = get_bits(gb, 5); | |
54 | 706 | skip_bits1(gb); | |
55 | 706 | si->pts = get_bits(gb, 13); | |
56 | 706 | rpr = get_bits(gb, av_log2(r->max_rpr) + 1); | |
57 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 706 times.
|
706 | if(rpr){ |
58 | ✗ | if (rpr > r->max_rpr) { | |
59 | ✗ | av_log(avctx, AV_LOG_ERROR, "rpr too large\n"); | |
60 | ✗ | return AVERROR_INVALIDDATA; | |
61 | } | ||
62 | |||
63 | ✗ | if (avctx->extradata_size < rpr * 2 + 8) { | |
64 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
65 | "Insufficient extradata - need at least %d bytes, got %d\n", | ||
66 | ✗ | 8 + rpr * 2, avctx->extradata_size); | |
67 | ✗ | return AVERROR(EINVAL); | |
68 | } | ||
69 | |||
70 | ✗ | w = r->s.avctx->extradata[6 + rpr*2] << 2; | |
71 | ✗ | h = r->s.avctx->extradata[7 + rpr*2] << 2; | |
72 | } else { | ||
73 | 706 | w = r->orig_width; | |
74 | 706 | h = r->orig_height; | |
75 | } | ||
76 | 706 | si->width = w; | |
77 | 706 | si->height = h; | |
78 | 706 | mb_size = ((w + 15) >> 4) * ((h + 15) >> 4); | |
79 | 706 | mb_bits = ff_rv34_get_start_offset(gb, mb_size); | |
80 | 706 | si->start = get_bits(gb, mb_bits); | |
81 | 706 | skip_bits1(gb); | |
82 | 706 | return 0; | |
83 | } | ||
84 | |||
85 | /** | ||
86 | * Decode 4x4 intra types array. | ||
87 | */ | ||
88 | 2739 | static int rv30_decode_intra_types(RV34DecContext *r, GetBitContext *gb, int8_t *dst) | |
89 | { | ||
90 | int i, j, k; | ||
91 | |||
92 |
2/2✓ Branch 0 taken 10956 times.
✓ Branch 1 taken 2739 times.
|
13695 | for(i = 0; i < 4; i++, dst += r->intra_types_stride - 4){ |
93 |
2/2✓ Branch 0 taken 21912 times.
✓ Branch 1 taken 10956 times.
|
32868 | for(j = 0; j < 4; j+= 2){ |
94 | 21912 | unsigned code = get_interleaved_ue_golomb(gb) << 1; | |
95 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21912 times.
|
21912 | if (code > 80U*2U) { |
96 | ✗ | av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction code\n"); | |
97 | ✗ | return -1; | |
98 | } | ||
99 |
2/2✓ Branch 0 taken 43824 times.
✓ Branch 1 taken 21912 times.
|
65736 | for(k = 0; k < 2; k++){ |
100 | 43824 | int A = dst[-r->intra_types_stride] + 1; | |
101 | 43824 | int B = dst[-1] + 1; | |
102 | 43824 | *dst++ = rv30_itype_from_context[A * 90 + B * 9 + rv30_itype_code[code + k]]; | |
103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43824 times.
|
43824 | if(dst[-1] == 9){ |
104 | ✗ | av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction mode\n"); | |
105 | ✗ | return -1; | |
106 | } | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | 2739 | return 0; | |
111 | } | ||
112 | |||
113 | /** | ||
114 | * Decode macroblock information. | ||
115 | */ | ||
116 | 68640 | static int rv30_decode_mb_info(RV34DecContext *r) | |
117 | { | ||
118 | static const int rv30_p_types[6] = { RV34_MB_SKIP, RV34_MB_P_16x16, RV34_MB_P_8x8, -1, RV34_MB_TYPE_INTRA, RV34_MB_TYPE_INTRA16x16 }; | ||
119 | static const int rv30_b_types[6] = { RV34_MB_SKIP, RV34_MB_B_DIRECT, RV34_MB_B_FORWARD, RV34_MB_B_BACKWARD, RV34_MB_TYPE_INTRA, RV34_MB_TYPE_INTRA16x16 }; | ||
120 | 68640 | MpegEncContext *s = &r->s; | |
121 | 68640 | GetBitContext *gb = &s->gb; | |
122 | 68640 | unsigned code = get_interleaved_ue_golomb(gb); | |
123 | |||
124 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 68640 times.
|
68640 | if (code > 11) { |
125 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "Incorrect MB type code\n"); | |
126 | ✗ | return -1; | |
127 | } | ||
128 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 68640 times.
|
68640 | if(code > 5){ |
129 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "dquant needed\n"); | |
130 | ✗ | code -= 6; | |
131 | } | ||
132 |
2/2✓ Branch 0 taken 15180 times.
✓ Branch 1 taken 53460 times.
|
68640 | if(s->pict_type != AV_PICTURE_TYPE_B) |
133 | 15180 | return rv30_p_types[code]; | |
134 | else | ||
135 | 53460 | return rv30_b_types[code]; | |
136 | } | ||
137 | |||
138 | 1048204 | static inline void rv30_weak_loop_filter(uint8_t *src, const int step, | |
139 | const int stride, const int lim) | ||
140 | { | ||
141 | 1048204 | const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; | |
142 | int i, diff; | ||
143 | |||
144 |
2/2✓ Branch 0 taken 4192816 times.
✓ Branch 1 taken 1048204 times.
|
5241020 | for(i = 0; i < 4; i++){ |
145 | 4192816 | diff = ((src[-2*step] - src[1*step]) - (src[-1*step] - src[0*step])*4) >> 3; | |
146 | 4192816 | diff = av_clip(diff, -lim, lim); | |
147 | 4192816 | src[-1*step] = cm[src[-1*step] + diff]; | |
148 | 4192816 | src[ 0*step] = cm[src[ 0*step] - diff]; | |
149 | 4192816 | src += stride; | |
150 | } | ||
151 | 1048204 | } | |
152 | |||
153 | 3308 | static void rv30_loop_filter(RV34DecContext *r, int row) | |
154 | { | ||
155 | 3308 | MpegEncContext *s = &r->s; | |
156 | int mb_pos, mb_x; | ||
157 | int i, j, k; | ||
158 | uint8_t *Y, *C; | ||
159 | 3308 | int loc_lim, cur_lim, left_lim = 0, top_lim = 0; | |
160 | |||
161 | 3308 | mb_pos = row * s->mb_stride; | |
162 |
2/2✓ Branch 0 taken 72680 times.
✓ Branch 1 taken 3308 times.
|
75988 | for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ |
163 | 72680 | int mbtype = s->cur_pic.mb_type[mb_pos]; | |
164 |
3/4✓ Branch 0 taken 63574 times.
✓ Branch 1 taken 9106 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 63574 times.
|
72680 | if(IS_INTRA(mbtype) || IS_SEPARATE_DC(mbtype)) |
165 | 9106 | r->deblock_coefs[mb_pos] = 0xFFFF; | |
166 |
2/2✓ Branch 0 taken 9106 times.
✓ Branch 1 taken 63574 times.
|
72680 | if(IS_INTRA(mbtype)) |
167 | 9106 | r->cbp_chroma[mb_pos] = 0xFF; | |
168 | } | ||
169 | |||
170 | /* all vertical edges are filtered first | ||
171 | * and horizontal edges are filtered on the next iteration | ||
172 | */ | ||
173 | 3308 | mb_pos = row * s->mb_stride; | |
174 |
2/2✓ Branch 0 taken 72680 times.
✓ Branch 1 taken 3308 times.
|
75988 | for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ |
175 | 72680 | cur_lim = rv30_loop_filt_lim[s->cur_pic.qscale_table[mb_pos]]; | |
176 |
2/2✓ Branch 0 taken 69372 times.
✓ Branch 1 taken 3308 times.
|
72680 | if(mb_x) |
177 | 69372 | left_lim = rv30_loop_filt_lim[s->cur_pic.qscale_table[mb_pos - 1]]; | |
178 |
2/2✓ Branch 0 taken 290720 times.
✓ Branch 1 taken 72680 times.
|
363400 | for(j = 0; j < 16; j += 4){ |
179 |
2/2✓ Branch 0 taken 13232 times.
✓ Branch 1 taken 277488 times.
|
290720 | Y = s->cur_pic.data[0] + mb_x*16 + (row*16 + j) * s->linesize + 4 * !mb_x; |
180 |
2/2✓ Branch 0 taken 1149648 times.
✓ Branch 1 taken 290720 times.
|
1440368 | for(i = !mb_x; i < 4; i++, Y += 4){ |
181 | 1149648 | int ij = i + j; | |
182 | 1149648 | loc_lim = 0; | |
183 |
2/2✓ Branch 0 taken 351712 times.
✓ Branch 1 taken 797936 times.
|
1149648 | if(r->deblock_coefs[mb_pos] & (1 << ij)) |
184 | 351712 | loc_lim = cur_lim; | |
185 |
4/4✓ Branch 0 taken 181856 times.
✓ Branch 1 taken 616080 times.
✓ Branch 2 taken 14120 times.
✓ Branch 3 taken 167736 times.
|
797936 | else if(!i && r->deblock_coefs[mb_pos - 1] & (1 << (ij + 3))) |
186 | 14120 | loc_lim = left_lim; | |
187 |
4/4✓ Branch 0 taken 616080 times.
✓ Branch 1 taken 167736 times.
✓ Branch 2 taken 38450 times.
✓ Branch 3 taken 577630 times.
|
783816 | else if( i && r->deblock_coefs[mb_pos] & (1 << (ij - 1))) |
188 | 38450 | loc_lim = cur_lim; | |
189 |
2/2✓ Branch 0 taken 373358 times.
✓ Branch 1 taken 776290 times.
|
1149648 | if(loc_lim) |
190 | 373358 | rv30_weak_loop_filter(Y, 1, s->linesize, loc_lim); | |
191 | } | ||
192 | } | ||
193 |
2/2✓ Branch 0 taken 145360 times.
✓ Branch 1 taken 72680 times.
|
218040 | for(k = 0; k < 2; k++){ |
194 | 145360 | int cur_cbp, left_cbp = 0; | |
195 | 145360 | cur_cbp = (r->cbp_chroma[mb_pos] >> (k*4)) & 0xF; | |
196 |
2/2✓ Branch 0 taken 138744 times.
✓ Branch 1 taken 6616 times.
|
145360 | if(mb_x) |
197 | 138744 | left_cbp = (r->cbp_chroma[mb_pos - 1] >> (k*4)) & 0xF; | |
198 |
2/2✓ Branch 0 taken 290720 times.
✓ Branch 1 taken 145360 times.
|
436080 | for(j = 0; j < 8; j += 4){ |
199 |
2/2✓ Branch 0 taken 13232 times.
✓ Branch 1 taken 277488 times.
|
290720 | C = s->cur_pic.data[k + 1] + mb_x*8 + (row*8 + j) * s->uvlinesize + 4 * !mb_x; |
200 |
2/2✓ Branch 0 taken 568208 times.
✓ Branch 1 taken 290720 times.
|
858928 | for(i = !mb_x; i < 2; i++, C += 4){ |
201 | 568208 | int ij = i + (j >> 1); | |
202 | 568208 | loc_lim = 0; | |
203 |
2/2✓ Branch 0 taken 132602 times.
✓ Branch 1 taken 435606 times.
|
568208 | if (cur_cbp & (1 << ij)) |
204 | 132602 | loc_lim = cur_lim; | |
205 |
4/4✓ Branch 0 taken 212204 times.
✓ Branch 1 taken 223402 times.
✓ Branch 2 taken 24668 times.
✓ Branch 3 taken 187536 times.
|
435606 | else if(!i && left_cbp & (1 << (ij + 1))) |
206 | 24668 | loc_lim = left_lim; | |
207 |
4/4✓ Branch 0 taken 223402 times.
✓ Branch 1 taken 187536 times.
✓ Branch 2 taken 16738 times.
✓ Branch 3 taken 206664 times.
|
410938 | else if( i && cur_cbp & (1 << (ij - 1))) |
208 | 16738 | loc_lim = cur_lim; | |
209 |
2/2✓ Branch 0 taken 143764 times.
✓ Branch 1 taken 424444 times.
|
568208 | if(loc_lim) |
210 | 143764 | rv30_weak_loop_filter(C, 1, s->uvlinesize, loc_lim); | |
211 | } | ||
212 | } | ||
213 | } | ||
214 | } | ||
215 | 3308 | mb_pos = row * s->mb_stride; | |
216 |
2/2✓ Branch 0 taken 72680 times.
✓ Branch 1 taken 3308 times.
|
75988 | for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){ |
217 | 72680 | cur_lim = rv30_loop_filt_lim[s->cur_pic.qscale_table[mb_pos]]; | |
218 |
2/2✓ Branch 0 taken 67830 times.
✓ Branch 1 taken 4850 times.
|
72680 | if(row) |
219 | 67830 | top_lim = rv30_loop_filt_lim[s->cur_pic.qscale_table[mb_pos - s->mb_stride]]; | |
220 |
4/4✓ Branch 0 taken 4850 times.
✓ Branch 1 taken 67830 times.
✓ Branch 2 taken 285870 times.
✓ Branch 3 taken 72680 times.
|
358550 | for(j = 4*!row; j < 16; j += 4){ |
221 | 285870 | Y = s->cur_pic.data[0] + mb_x*16 + (row*16 + j) * s->linesize; | |
222 |
2/2✓ Branch 0 taken 1143480 times.
✓ Branch 1 taken 285870 times.
|
1429350 | for(i = 0; i < 4; i++, Y += 4){ |
223 | 1143480 | int ij = i + j; | |
224 | 1143480 | loc_lim = 0; | |
225 |
2/2✓ Branch 0 taken 350204 times.
✓ Branch 1 taken 793276 times.
|
1143480 | if(r->deblock_coefs[mb_pos] & (1 << ij)) |
226 | 350204 | loc_lim = cur_lim; | |
227 |
4/4✓ Branch 0 taken 177032 times.
✓ Branch 1 taken 616244 times.
✓ Branch 2 taken 15928 times.
✓ Branch 3 taken 161104 times.
|
793276 | else if(!j && r->deblock_coefs[mb_pos - s->mb_stride] & (1 << (ij + 12))) |
228 | 15928 | loc_lim = top_lim; | |
229 |
4/4✓ Branch 0 taken 616244 times.
✓ Branch 1 taken 161104 times.
✓ Branch 2 taken 45866 times.
✓ Branch 3 taken 570378 times.
|
777348 | else if( j && r->deblock_coefs[mb_pos] & (1 << (ij - 4))) |
230 | 45866 | loc_lim = cur_lim; | |
231 |
2/2✓ Branch 0 taken 381230 times.
✓ Branch 1 taken 762250 times.
|
1143480 | if(loc_lim) |
232 | 381230 | rv30_weak_loop_filter(Y, s->linesize, 1, loc_lim); | |
233 | } | ||
234 | } | ||
235 |
2/2✓ Branch 0 taken 145360 times.
✓ Branch 1 taken 72680 times.
|
218040 | for(k = 0; k < 2; k++){ |
236 | 145360 | int cur_cbp, top_cbp = 0; | |
237 | 145360 | cur_cbp = (r->cbp_chroma[mb_pos] >> (k*4)) & 0xF; | |
238 |
2/2✓ Branch 0 taken 135660 times.
✓ Branch 1 taken 9700 times.
|
145360 | if(row) |
239 | 135660 | top_cbp = (r->cbp_chroma[mb_pos - s->mb_stride] >> (k*4)) & 0xF; | |
240 |
4/4✓ Branch 0 taken 9700 times.
✓ Branch 1 taken 135660 times.
✓ Branch 2 taken 281020 times.
✓ Branch 3 taken 145360 times.
|
426380 | for(j = 4*!row; j < 8; j += 4){ |
241 | 281020 | C = s->cur_pic.data[k+1] + mb_x*8 + (row*8 + j) * s->uvlinesize; | |
242 |
2/2✓ Branch 0 taken 562040 times.
✓ Branch 1 taken 281020 times.
|
843060 | for(i = 0; i < 2; i++, C += 4){ |
243 | 562040 | int ij = i + (j >> 1); | |
244 | 562040 | loc_lim = 0; | |
245 |
2/2✓ Branch 0 taken 129332 times.
✓ Branch 1 taken 432708 times.
|
562040 | if (r->cbp_chroma[mb_pos] & (1 << ij)) |
246 | 129332 | loc_lim = cur_lim; | |
247 |
4/4✓ Branch 0 taken 209600 times.
✓ Branch 1 taken 223108 times.
✓ Branch 2 taken 28486 times.
✓ Branch 3 taken 181114 times.
|
432708 | else if(!j && top_cbp & (1 << (ij + 2))) |
248 | 28486 | loc_lim = top_lim; | |
249 |
4/4✓ Branch 0 taken 223108 times.
✓ Branch 1 taken 181114 times.
✓ Branch 2 taken 22304 times.
✓ Branch 3 taken 200804 times.
|
404222 | else if( j && cur_cbp & (1 << (ij - 2))) |
250 | 22304 | loc_lim = cur_lim; | |
251 |
2/2✓ Branch 0 taken 149852 times.
✓ Branch 1 taken 412188 times.
|
562040 | if(loc_lim) |
252 | 149852 | rv30_weak_loop_filter(C, s->uvlinesize, 1, loc_lim); | |
253 | } | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | 3308 | } | |
258 | |||
259 | /** | ||
260 | * Initialize decoder. | ||
261 | */ | ||
262 | 5 | static av_cold int rv30_decode_init(AVCodecContext *avctx) | |
263 | { | ||
264 | 5 | RV34DecContext *r = avctx->priv_data; | |
265 | int ret; | ||
266 | |||
267 | 5 | r->orig_width = avctx->coded_width; | |
268 | 5 | r->orig_height = avctx->coded_height; | |
269 | |||
270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (avctx->extradata_size < 2) { |
271 | ✗ | av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n"); | |
272 | ✗ | return AVERROR(EINVAL); | |
273 | } | ||
274 | 5 | r->rv30 = 1; | |
275 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
|
5 | if ((ret = ff_rv34_decode_init(avctx)) < 0) |
276 | ✗ | return ret; | |
277 | |||
278 | 5 | r->max_rpr = avctx->extradata[1] & 7; | |
279 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if(avctx->extradata_size < 2*r->max_rpr + 8){ |
280 | ✗ | av_log(avctx, AV_LOG_WARNING, "Insufficient extradata - need at least %d bytes, got %d\n", | |
281 | ✗ | 2*r->max_rpr + 8, avctx->extradata_size); | |
282 | } | ||
283 | |||
284 | 5 | r->parse_slice_header = rv30_parse_slice_header; | |
285 | 5 | r->decode_intra_types = rv30_decode_intra_types; | |
286 | 5 | r->decode_mb_info = rv30_decode_mb_info; | |
287 | 5 | r->loop_filter = rv30_loop_filter; | |
288 | 5 | r->luma_dc_quant_i = rv30_luma_dc_quant; | |
289 | 5 | r->luma_dc_quant_p = rv30_luma_dc_quant; | |
290 | 5 | ff_rv30dsp_init(&r->rdsp); | |
291 | 5 | return 0; | |
292 | } | ||
293 | |||
294 | const FFCodec ff_rv30_decoder = { | ||
295 | .p.name = "rv30", | ||
296 | CODEC_LONG_NAME("RealVideo 3.0"), | ||
297 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
298 | .p.id = AV_CODEC_ID_RV30, | ||
299 | .priv_data_size = sizeof(RV34DecContext), | ||
300 | .init = rv30_decode_init, | ||
301 | .close = ff_rv34_decode_end, | ||
302 | FF_CODEC_DECODE_CB(ff_rv34_decode_frame), | ||
303 | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | | ||
304 | AV_CODEC_CAP_FRAME_THREADS, | ||
305 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | ||
306 | .flush = ff_mpeg_flush, | ||
307 | UPDATE_THREAD_CONTEXT(ff_rv34_decode_update_thread_context), | ||
308 | }; | ||
309 |