Mercurial > libavcodec.hg
annotate svq3.c @ 12197:fbf4d5b1b664 libavcodec
Remove FF_MM_SSE2/3 flags for CPUs where this is generally not faster than
regular MMX code. Examples of this are the Core1 CPU. Instead, set a new flag,
FF_MM_SSE2/3SLOW, which can be checked for particular SSE2/3 functions that
have been checked specifically on such CPUs and are actually faster than
their MMX counterparts.
In addition, use this flag to enable particular VP8 and LPC SSE2 functions
that are faster than their MMX counterparts.
Based on a patch by Loren Merritt <lorenm AT u washington edu>.
author | rbultje |
---|---|
date | Mon, 19 Jul 2010 22:38:23 +0000 |
parents | 8daf3134622c |
children |
rev | line source |
---|---|
1234 | 1 /* |
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8590
diff
changeset
|
2 * Copyright (c) 2003 The FFmpeg Project |
1234 | 3 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
4 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
5 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
6 * FFmpeg is free software; you can redistribute it and/or |
1234 | 7 * modify it under the terms of the GNU Lesser General Public |
8 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
9 * version 2.1 of the License, or (at your option) any later version. |
1234 | 10 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
11 * FFmpeg is distributed in the hope that it will be useful, |
1234 | 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Lesser General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Lesser General Public | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
17 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
5215 | 19 */ |
20 | |
21 /* | |
1234 | 22 * How to use this decoder: |
23 * SVQ3 data is transported within Apple Quicktime files. Quicktime files | |
1235
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
24 * have stsd atoms to describe media trak properties. A stsd atom for a |
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
25 * video trak contains 1 or more ImageDescription atoms. These atoms begin |
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
26 * with the 4-byte length of the atom followed by the codec fourcc. Some |
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
27 * decoders need information in this atom to operate correctly. Such |
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
28 * is the case with SVQ3. In order to get the best use out of this decoder, |
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
29 * the calling app must make the SVQ3 ImageDescription atom available |
1234 | 30 * via the AVCodecContext's extradata[_size] field: |
31 * | |
2967 | 32 * AVCodecContext.extradata = pointer to ImageDescription, first characters |
1235
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
33 * are expected to be 'S', 'V', 'Q', and '3', NOT the 4-byte atom length |
2967 | 34 * AVCodecContext.extradata_size = size of ImageDescription atom memory |
35 * buffer (which will be the same as the ImageDescription atom size field | |
1235
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
36 * from the QT file, minus 4 bytes since the length is missing) |
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
37 * |
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
38 * You will know you have these parameters passed correctly when the decoder |
8bb75c3c2f21
change the way the ImageDescription is passed to the decoder
tmmm
parents:
1234
diff
changeset
|
39 * correctly decodes this file: |
8459 | 40 * http://samples.mplayerhq.hu/V-codecs/SVQ3/Vertical400kbit.sorenson3.mov |
1234 | 41 */ |
10852 | 42 #include "internal.h" |
43 #include "dsputil.h" | |
44 #include "avcodec.h" | |
45 #include "mpegvideo.h" | |
46 #include "h264.h" | |
47 | |
48 #include "h264data.h" //FIXME FIXME FIXME | |
49 | |
10864 | 50 #include "h264_mvpred.h" |
10852 | 51 #include "golomb.h" |
52 #include "rectangle.h" | |
53 #include "vdpau_internal.h" | |
54 | |
8590 | 55 #if CONFIG_ZLIB |
8067 | 56 #include <zlib.h> |
57 #endif | |
58 | |
8080
847bcb16028a
Add the function declaration of ff_svq1_packet_checksum to svq1.h and include
diego
parents:
8067
diff
changeset
|
59 #include "svq1.h" |
847bcb16028a
Add the function declaration of ff_svq1_packet_checksum to svq1.h and include
diego
parents:
8067
diff
changeset
|
60 |
1234 | 61 /** |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
62 * @file |
1234 | 63 * svq3 decoder. |
64 */ | |
65 | |
2967 | 66 #define FULLPEL_MODE 1 |
67 #define HALFPEL_MODE 2 | |
1265 | 68 #define THIRDPEL_MODE 3 |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
69 #define PREDICT_MODE 4 |
2967 | 70 |
1252 | 71 /* dual scan (from some older h264 draft) |
72 o-->o-->o o | |
73 | /| | |
74 o o o / o | |
75 | / | |/ | | |
76 o o o o | |
2967 | 77 / |
1252 | 78 o-->o-->o-->o |
79 */ | |
8196 | 80 static const uint8_t svq3_scan[16] = { |
81 0+0*4, 1+0*4, 2+0*4, 2+1*4, | |
82 2+2*4, 3+0*4, 3+1*4, 3+2*4, | |
83 0+1*4, 0+2*4, 1+1*4, 1+2*4, | |
84 0+3*4, 1+3*4, 2+3*4, 3+3*4, | |
1234 | 85 }; |
86 | |
87 static const uint8_t svq3_pred_0[25][2] = { | |
8196 | 88 { 0, 0 }, |
89 { 1, 0 }, { 0, 1 }, | |
90 { 0, 2 }, { 1, 1 }, { 2, 0 }, | |
91 { 3, 0 }, { 2, 1 }, { 1, 2 }, { 0, 3 }, | |
92 { 0, 4 }, { 1, 3 }, { 2, 2 }, { 3, 1 }, { 4, 0 }, | |
93 { 4, 1 }, { 3, 2 }, { 2, 3 }, { 1, 4 }, | |
94 { 2, 4 }, { 3, 3 }, { 4, 2 }, | |
95 { 4, 3 }, { 3, 4 }, | |
96 { 4, 4 } | |
1234 | 97 }; |
98 | |
99 static const int8_t svq3_pred_1[6][6][5] = { | |
8196 | 100 { { 2,-1,-1,-1,-1 }, { 2, 1,-1,-1,-1 }, { 1, 2,-1,-1,-1 }, |
101 { 2, 1,-1,-1,-1 }, { 1, 2,-1,-1,-1 }, { 1, 2,-1,-1,-1 } }, | |
102 { { 0, 2,-1,-1,-1 }, { 0, 2, 1, 4, 3 }, { 0, 1, 2, 4, 3 }, | |
103 { 0, 2, 1, 4, 3 }, { 2, 0, 1, 3, 4 }, { 0, 4, 2, 1, 3 } }, | |
104 { { 2, 0,-1,-1,-1 }, { 2, 1, 0, 4, 3 }, { 1, 2, 4, 0, 3 }, | |
105 { 2, 1, 0, 4, 3 }, { 2, 1, 4, 3, 0 }, { 1, 2, 4, 0, 3 } }, | |
106 { { 2, 0,-1,-1,-1 }, { 2, 0, 1, 4, 3 }, { 1, 2, 0, 4, 3 }, | |
107 { 2, 1, 0, 4, 3 }, { 2, 1, 3, 4, 0 }, { 2, 4, 1, 0, 3 } }, | |
108 { { 0, 2,-1,-1,-1 }, { 0, 2, 1, 3, 4 }, { 1, 2, 3, 0, 4 }, | |
109 { 2, 0, 1, 3, 4 }, { 2, 1, 3, 0, 4 }, { 2, 0, 4, 3, 1 } }, | |
110 { { 0, 2,-1,-1,-1 }, { 0, 2, 4, 1, 3 }, { 1, 4, 2, 0, 3 }, | |
111 { 4, 2, 0, 1, 3 }, { 2, 0, 1, 4, 3 }, { 4, 2, 1, 0, 3 } }, | |
1234 | 112 }; |
113 | |
114 static const struct { uint8_t run; uint8_t level; } svq3_dct_tables[2][16] = { | |
8196 | 115 { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 0, 2 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, |
116 { 0, 3 }, { 1, 2 }, { 2, 2 }, { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 0, 4 } }, | |
117 { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 0, 2 }, { 2, 1 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, | |
118 { 3, 1 }, { 4, 1 }, { 1, 2 }, { 1, 3 }, { 0, 6 }, { 0, 7 }, { 0, 8 }, { 0, 9 } } | |
1234 | 119 }; |
120 | |
121 static const uint32_t svq3_dequant_coeff[32] = { | |
8196 | 122 3881, 4351, 4890, 5481, 6154, 6914, 7761, 8718, |
123 9781, 10987, 12339, 13828, 15523, 17435, 19561, 21873, | |
124 24552, 27656, 30847, 34870, 38807, 43747, 49103, 54683, | |
125 61694, 68745, 77615, 89113,100253,109366,126635,141533 | |
1234 | 126 }; |
127 | |
128 | |
11031 | 129 void ff_svq3_luma_dc_dequant_idct_c(DCTELEM *block, int qp) |
8195 | 130 { |
8196 | 131 const int qmul = svq3_dequant_coeff[qp]; |
1234 | 132 #define stride 16 |
133 int i; | |
134 int temp[16]; | |
8196 | 135 static const int x_offset[4] = {0, 1*stride, 4* stride, 5*stride}; |
136 static const int y_offset[4] = {0, 2*stride, 8* stride, 10*stride}; | |
1234 | 137 |
8196 | 138 for (i = 0; i < 4; i++){ |
139 const int offset = y_offset[i]; | |
140 const int z0 = 13*(block[offset+stride*0] + block[offset+stride*4]); | |
141 const int z1 = 13*(block[offset+stride*0] - block[offset+stride*4]); | |
142 const int z2 = 7* block[offset+stride*1] - 17*block[offset+stride*5]; | |
143 const int z3 = 17* block[offset+stride*1] + 7*block[offset+stride*5]; | |
1234 | 144 |
8196 | 145 temp[4*i+0] = z0+z3; |
146 temp[4*i+1] = z1+z2; | |
147 temp[4*i+2] = z1-z2; | |
148 temp[4*i+3] = z0-z3; | |
1234 | 149 } |
150 | |
8196 | 151 for (i = 0; i < 4; i++){ |
152 const int offset = x_offset[i]; | |
153 const int z0 = 13*(temp[4*0+i] + temp[4*2+i]); | |
154 const int z1 = 13*(temp[4*0+i] - temp[4*2+i]); | |
155 const int z2 = 7* temp[4*1+i] - 17*temp[4*3+i]; | |
156 const int z3 = 17* temp[4*1+i] + 7*temp[4*3+i]; | |
1234 | 157 |
8196 | 158 block[stride*0 +offset] = ((z0 + z3)*qmul + 0x80000) >> 20; |
159 block[stride*2 +offset] = ((z1 + z2)*qmul + 0x80000) >> 20; | |
160 block[stride*8 +offset] = ((z1 - z2)*qmul + 0x80000) >> 20; | |
161 block[stride*10+offset] = ((z0 - z3)*qmul + 0x80000) >> 20; | |
1234 | 162 } |
163 } | |
164 #undef stride | |
165 | |
11031 | 166 void ff_svq3_add_idct_c(uint8_t *dst, DCTELEM *block, int stride, int qp, |
8196 | 167 int dc) |
8195 | 168 { |
8196 | 169 const int qmul = svq3_dequant_coeff[qp]; |
1234 | 170 int i; |
4176 | 171 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP; |
1234 | 172 |
173 if (dc) { | |
174 dc = 13*13*((dc == 1) ? 1538*block[0] : ((qmul*(block[0] >> 3)) / 2)); | |
175 block[0] = 0; | |
176 } | |
177 | |
8196 | 178 for (i = 0; i < 4; i++) { |
179 const int z0 = 13*(block[0 + 4*i] + block[2 + 4*i]); | |
180 const int z1 = 13*(block[0 + 4*i] - block[2 + 4*i]); | |
181 const int z2 = 7* block[1 + 4*i] - 17*block[3 + 4*i]; | |
182 const int z3 = 17* block[1 + 4*i] + 7*block[3 + 4*i]; | |
1234 | 183 |
8196 | 184 block[0 + 4*i] = z0 + z3; |
185 block[1 + 4*i] = z1 + z2; | |
186 block[2 + 4*i] = z1 - z2; | |
187 block[3 + 4*i] = z0 - z3; | |
1234 | 188 } |
189 | |
8196 | 190 for (i = 0; i < 4; i++) { |
191 const int z0 = 13*(block[i + 4*0] + block[i + 4*2]); | |
192 const int z1 = 13*(block[i + 4*0] - block[i + 4*2]); | |
193 const int z2 = 7* block[i + 4*1] - 17*block[i + 4*3]; | |
194 const int z3 = 17* block[i + 4*1] + 7*block[i + 4*3]; | |
195 const int rr = (dc + 0x80000); | |
1234 | 196 |
8196 | 197 dst[i + stride*0] = cm[ dst[i + stride*0] + (((z0 + z3)*qmul + rr) >> 20) ]; |
198 dst[i + stride*1] = cm[ dst[i + stride*1] + (((z1 + z2)*qmul + rr) >> 20) ]; | |
199 dst[i + stride*2] = cm[ dst[i + stride*2] + (((z1 - z2)*qmul + rr) >> 20) ]; | |
200 dst[i + stride*3] = cm[ dst[i + stride*3] + (((z0 - z3)*qmul + rr) >> 20) ]; | |
1234 | 201 } |
202 } | |
203 | |
8195 | 204 static inline int svq3_decode_block(GetBitContext *gb, DCTELEM *block, |
205 int index, const int type) | |
206 { | |
8196 | 207 static const uint8_t *const scan_patterns[4] = |
208 { luma_dc_zigzag_scan, zigzag_scan, svq3_scan, chroma_dc_scan }; | |
1234 | 209 |
8196 | 210 int run, level, sign, vlc, limit; |
211 const int intra = (3 * type) >> 2; | |
212 const uint8_t *const scan = scan_patterns[type]; | |
1234 | 213 |
8196 | 214 for (limit = (16 >> intra); index < 16; index = limit, limit += 8) { |
215 for (; (vlc = svq3_get_ue_golomb(gb)) != 0; index++) { | |
1234 | 216 |
8196 | 217 if (vlc == INVALID_VLC) |
218 return -1; | |
1234 | 219 |
8196 | 220 sign = (vlc & 0x1) - 1; |
221 vlc = (vlc + 1) >> 1; | |
1234 | 222 |
8196 | 223 if (type == 3) { |
224 if (vlc < 3) { | |
225 run = 0; | |
226 level = vlc; | |
227 } else if (vlc < 4) { | |
228 run = 1; | |
229 level = 1; | |
230 } else { | |
231 run = (vlc & 0x3); | |
232 level = ((vlc + 9) >> 2) - run; | |
233 } | |
234 } else { | |
235 if (vlc < 16) { | |
236 run = svq3_dct_tables[intra][vlc].run; | |
237 level = svq3_dct_tables[intra][vlc].level; | |
238 } else if (intra) { | |
239 run = (vlc & 0x7); | |
240 level = (vlc >> 3) + ((run == 0) ? 8 : ((run < 2) ? 2 : ((run < 5) ? 0 : -1))); | |
241 } else { | |
242 run = (vlc & 0xF); | |
243 level = (vlc >> 4) + ((run == 0) ? 4 : ((run < 3) ? 2 : ((run < 10) ? 1 : 0))); | |
244 } | |
245 } | |
246 | |
247 if ((index += run) >= limit) | |
248 return -1; | |
249 | |
250 block[scan[index]] = (level ^ sign) - sign; | |
2979 | 251 } |
8196 | 252 |
253 if (type != 2) { | |
254 break; | |
2979 | 255 } |
1234 | 256 } |
257 | |
8196 | 258 return 0; |
1234 | 259 } |
260 | |
8195 | 261 static inline void svq3_mc_dir_part(MpegEncContext *s, |
262 int x, int y, int width, int height, | |
263 int mx, int my, int dxy, | |
264 int thirdpel, int dir, int avg) | |
265 { | |
8196 | 266 const Picture *pic = (dir == 0) ? &s->last_picture : &s->next_picture; |
267 uint8_t *src, *dest; | |
268 int i, emu = 0; | |
269 int blocksize = 2 - (width>>3); //16->0, 8->1, 4->2 | |
270 | |
271 mx += x; | |
272 my += y; | |
1234 | 273 |
8196 | 274 if (mx < 0 || mx >= (s->h_edge_pos - width - 1) || |
275 my < 0 || my >= (s->v_edge_pos - height - 1)) { | |
2967 | 276 |
8196 | 277 if ((s->flags & CODEC_FLAG_EMU_EDGE)) { |
278 emu = 1; | |
279 } | |
1234 | 280 |
8196 | 281 mx = av_clip (mx, -16, (s->h_edge_pos - width + 15)); |
282 my = av_clip (my, -16, (s->v_edge_pos - height + 15)); | |
1234 | 283 } |
284 | |
8196 | 285 /* form component predictions */ |
286 dest = s->current_picture.data[0] + x + y*s->linesize; | |
287 src = pic->data[0] + mx + my*s->linesize; | |
1234 | 288 |
8196 | 289 if (emu) { |
290 ff_emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, (width + 1), (height + 1), | |
291 mx, my, s->h_edge_pos, s->v_edge_pos); | |
292 src = s->edge_emu_buffer; | |
293 } | |
294 if (thirdpel) | |
295 (avg ? s->dsp.avg_tpel_pixels_tab : s->dsp.put_tpel_pixels_tab)[dxy](dest, src, s->linesize, width, height); | |
296 else | |
297 (avg ? s->dsp.avg_pixels_tab : s->dsp.put_pixels_tab)[blocksize][dxy](dest, src, s->linesize, height); | |
1234 | 298 |
8196 | 299 if (!(s->flags & CODEC_FLAG_GRAY)) { |
300 mx = (mx + (mx < (int) x)) >> 1; | |
301 my = (my + (my < (int) y)) >> 1; | |
302 width = (width >> 1); | |
303 height = (height >> 1); | |
304 blocksize++; | |
1234 | 305 |
8196 | 306 for (i = 1; i < 3; i++) { |
307 dest = s->current_picture.data[i] + (x >> 1) + (y >> 1)*s->uvlinesize; | |
308 src = pic->data[i] + mx + my*s->uvlinesize; | |
1234 | 309 |
8196 | 310 if (emu) { |
311 ff_emulated_edge_mc(s->edge_emu_buffer, src, s->uvlinesize, (width + 1), (height + 1), | |
312 mx, my, (s->h_edge_pos >> 1), (s->v_edge_pos >> 1)); | |
313 src = s->edge_emu_buffer; | |
314 } | |
315 if (thirdpel) | |
316 (avg ? s->dsp.avg_tpel_pixels_tab : s->dsp.put_tpel_pixels_tab)[dxy](dest, src, s->uvlinesize, width, height); | |
317 else | |
318 (avg ? s->dsp.avg_pixels_tab : s->dsp.put_pixels_tab)[blocksize][dxy](dest, src, s->uvlinesize, height); | |
319 } | |
1234 | 320 } |
321 } | |
322 | |
8195 | 323 static inline int svq3_mc_dir(H264Context *h, int size, int mode, int dir, |
324 int avg) | |
325 { | |
8196 | 326 int i, j, k, mx, my, dx, dy, x, y; |
327 MpegEncContext *const s = (MpegEncContext *) h; | |
328 const int part_width = ((size & 5) == 4) ? 4 : 16 >> (size & 1); | |
329 const int part_height = 16 >> ((unsigned) (size + 1) / 3); | |
330 const int extra_width = (mode == PREDICT_MODE) ? -16*6 : 0; | |
331 const int h_edge_pos = 6*(s->h_edge_pos - part_width ) - extra_width; | |
332 const int v_edge_pos = 6*(s->v_edge_pos - part_height) - extra_width; | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
333 |
8196 | 334 for (i = 0; i < 16; i += part_height) { |
335 for (j = 0; j < 16; j += part_width) { | |
336 const int b_xy = (4*s->mb_x + (j >> 2)) + (4*s->mb_y + (i >> 2))*h->b_stride; | |
337 int dxy; | |
338 x = 16*s->mb_x + j; | |
339 y = 16*s->mb_y + i; | |
340 k = ((j >> 2) & 1) + ((i >> 1) & 2) + ((j >> 1) & 4) + (i & 8); | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
341 |
8196 | 342 if (mode != PREDICT_MODE) { |
343 pred_motion(h, k, (part_width >> 2), dir, 1, &mx, &my); | |
344 } else { | |
345 mx = s->next_picture.motion_val[0][b_xy][0]<<1; | |
346 my = s->next_picture.motion_val[0][b_xy][1]<<1; | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
347 |
8196 | 348 if (dir == 0) { |
349 mx = ((mx * h->frame_num_offset) / h->prev_frame_num_offset + 1) >> 1; | |
350 my = ((my * h->frame_num_offset) / h->prev_frame_num_offset + 1) >> 1; | |
351 } else { | |
352 mx = ((mx * (h->frame_num_offset - h->prev_frame_num_offset)) / h->prev_frame_num_offset + 1) >> 1; | |
353 my = ((my * (h->frame_num_offset - h->prev_frame_num_offset)) / h->prev_frame_num_offset + 1) >> 1; | |
354 } | |
355 } | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
356 |
8196 | 357 /* clip motion vector prediction to frame border */ |
358 mx = av_clip(mx, extra_width - 6*x, h_edge_pos - 6*x); | |
359 my = av_clip(my, extra_width - 6*y, v_edge_pos - 6*y); | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
360 |
8196 | 361 /* get (optional) motion vector differential */ |
362 if (mode == PREDICT_MODE) { | |
363 dx = dy = 0; | |
364 } else { | |
365 dy = svq3_get_se_golomb(&s->gb); | |
366 dx = svq3_get_se_golomb(&s->gb); | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
367 |
8196 | 368 if (dx == INVALID_VLC || dy == INVALID_VLC) { |
369 av_log(h->s.avctx, AV_LOG_ERROR, "invalid MV vlc\n"); | |
370 return -1; | |
371 } | |
372 } | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
373 |
8196 | 374 /* compute motion vector */ |
375 if (mode == THIRDPEL_MODE) { | |
376 int fx, fy; | |
377 mx = ((mx + 1)>>1) + dx; | |
378 my = ((my + 1)>>1) + dy; | |
379 fx = ((unsigned)(mx + 0x3000))/3 - 0x1000; | |
380 fy = ((unsigned)(my + 0x3000))/3 - 0x1000; | |
381 dxy = (mx - 3*fx) + 4*(my - 3*fy); | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
382 |
8196 | 383 svq3_mc_dir_part(s, x, y, part_width, part_height, fx, fy, dxy, 1, dir, avg); |
384 mx += mx; | |
385 my += my; | |
386 } else if (mode == HALFPEL_MODE || mode == PREDICT_MODE) { | |
387 mx = ((unsigned)(mx + 1 + 0x3000))/3 + dx - 0x1000; | |
388 my = ((unsigned)(my + 1 + 0x3000))/3 + dy - 0x1000; | |
389 dxy = (mx&1) + 2*(my&1); | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
390 |
8196 | 391 svq3_mc_dir_part(s, x, y, part_width, part_height, mx>>1, my>>1, dxy, 0, dir, avg); |
392 mx *= 3; | |
393 my *= 3; | |
394 } else { | |
395 mx = ((unsigned)(mx + 3 + 0x6000))/6 + dx - 0x1000; | |
396 my = ((unsigned)(my + 3 + 0x6000))/6 + dy - 0x1000; | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
397 |
8196 | 398 svq3_mc_dir_part(s, x, y, part_width, part_height, mx, my, 0, 0, dir, avg); |
399 mx *= 6; | |
400 my *= 6; | |
401 } | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
402 |
8196 | 403 /* update mv_cache */ |
404 if (mode != PREDICT_MODE) { | |
405 int32_t mv = pack16to32(mx,my); | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
406 |
8196 | 407 if (part_height == 8 && i < 8) { |
408 *(int32_t *) h->mv_cache[dir][scan8[k] + 1*8] = mv; | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
409 |
8196 | 410 if (part_width == 8 && j < 8) { |
411 *(int32_t *) h->mv_cache[dir][scan8[k] + 1 + 1*8] = mv; | |
412 } | |
413 } | |
414 if (part_width == 8 && j < 8) { | |
415 *(int32_t *) h->mv_cache[dir][scan8[k] + 1] = mv; | |
416 } | |
417 if (part_width == 4 || part_height == 4) { | |
418 *(int32_t *) h->mv_cache[dir][scan8[k]] = mv; | |
419 } | |
420 } | |
421 | |
422 /* write back motion vectors */ | |
423 fill_rectangle(s->current_picture.motion_val[dir][b_xy], part_width>>2, part_height>>2, h->b_stride, pack16to32(mx,my), 4); | |
2979 | 424 } |
8196 | 425 } |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
426 |
8196 | 427 return 0; |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
428 } |
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
429 |
8195 | 430 static int svq3_decode_mb(H264Context *h, unsigned int mb_type) |
431 { | |
8196 | 432 int i, j, k, m, dir, mode; |
433 int cbp = 0; | |
434 uint32_t vlc; | |
435 int8_t *top, *left; | |
436 MpegEncContext *const s = (MpegEncContext *) h; | |
437 const int mb_xy = h->mb_xy; | |
438 const int b_xy = 4*s->mb_x + 4*s->mb_y*h->b_stride; | |
439 | |
440 h->top_samples_available = (s->mb_y == 0) ? 0x33FF : 0xFFFF; | |
441 h->left_samples_available = (s->mb_x == 0) ? 0x5F5F : 0xFFFF; | |
442 h->topright_samples_available = 0xFFFF; | |
443 | |
444 if (mb_type == 0) { /* SKIP */ | |
445 if (s->pict_type == FF_P_TYPE || s->next_picture.mb_type[mb_xy] == -1) { | |
446 svq3_mc_dir_part(s, 16*s->mb_x, 16*s->mb_y, 16, 16, 0, 0, 0, 0, 0, 0); | |
1234 | 447 |
8196 | 448 if (s->pict_type == FF_B_TYPE) { |
449 svq3_mc_dir_part(s, 16*s->mb_x, 16*s->mb_y, 16, 16, 0, 0, 0, 0, 1, 1); | |
450 } | |
1234 | 451 |
8196 | 452 mb_type = MB_TYPE_SKIP; |
453 } else { | |
454 mb_type = FFMIN(s->next_picture.mb_type[mb_xy], 6); | |
455 if (svq3_mc_dir(h, mb_type, PREDICT_MODE, 0, 0) < 0) | |
456 return -1; | |
457 if (svq3_mc_dir(h, mb_type, PREDICT_MODE, 1, 1) < 0) | |
458 return -1; | |
1319 | 459 |
8196 | 460 mb_type = MB_TYPE_16x16; |
461 } | |
462 } else if (mb_type < 8) { /* INTER */ | |
463 if (h->thirdpel_flag && h->halfpel_flag == !get_bits1 (&s->gb)) { | |
464 mode = THIRDPEL_MODE; | |
465 } else if (h->halfpel_flag && h->thirdpel_flag == !get_bits1 (&s->gb)) { | |
466 mode = HALFPEL_MODE; | |
467 } else { | |
468 mode = FULLPEL_MODE; | |
469 } | |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
470 |
8196 | 471 /* fill caches */ |
472 /* note ref_cache should contain here: | |
473 ???????? | |
474 ???11111 | |
475 N??11111 | |
476 N??11111 | |
477 N??11111 | |
478 */ | |
1319 | 479 |
8196 | 480 for (m = 0; m < 2; m++) { |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
481 if (s->mb_x > 0 && h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1]+6] != -1) { |
8196 | 482 for (i = 0; i < 4; i++) { |
483 *(uint32_t *) h->mv_cache[m][scan8[0] - 1 + i*8] = *(uint32_t *) s->current_picture.motion_val[m][b_xy - 1 + i*h->b_stride]; | |
484 } | |
485 } else { | |
486 for (i = 0; i < 4; i++) { | |
487 *(uint32_t *) h->mv_cache[m][scan8[0] - 1 + i*8] = 0; | |
488 } | |
489 } | |
490 if (s->mb_y > 0) { | |
491 memcpy(h->mv_cache[m][scan8[0] - 1*8], s->current_picture.motion_val[m][b_xy - h->b_stride], 4*2*sizeof(int16_t)); | |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
492 memset(&h->ref_cache[m][scan8[0] - 1*8], (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1, 4); |
1234 | 493 |
8196 | 494 if (s->mb_x < (s->mb_width - 1)) { |
495 *(uint32_t *) h->mv_cache[m][scan8[0] + 4 - 1*8] = *(uint32_t *) s->current_picture.motion_val[m][b_xy - h->b_stride + 4]; | |
496 h->ref_cache[m][scan8[0] + 4 - 1*8] = | |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
497 (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride + 1]+6] == -1 || |
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
498 h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride ] ] == -1) ? PART_NOT_AVAILABLE : 1; |
8196 | 499 }else |
500 h->ref_cache[m][scan8[0] + 4 - 1*8] = PART_NOT_AVAILABLE; | |
501 if (s->mb_x > 0) { | |
502 *(uint32_t *) h->mv_cache[m][scan8[0] - 1 - 1*8] = *(uint32_t *) s->current_picture.motion_val[m][b_xy - h->b_stride - 1]; | |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
503 h->ref_cache[m][scan8[0] - 1 - 1*8] = (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride - 1]+3] == -1) ? PART_NOT_AVAILABLE : 1; |
8196 | 504 }else |
505 h->ref_cache[m][scan8[0] - 1 - 1*8] = PART_NOT_AVAILABLE; | |
506 }else | |
507 memset(&h->ref_cache[m][scan8[0] - 1*8 - 1], PART_NOT_AVAILABLE, 8); | |
508 | |
509 if (s->pict_type != FF_B_TYPE) | |
510 break; | |
511 } | |
2967 | 512 |
8196 | 513 /* decode motion vector(s) and form prediction(s) */ |
514 if (s->pict_type == FF_P_TYPE) { | |
515 if (svq3_mc_dir(h, (mb_type - 1), mode, 0, 0) < 0) | |
516 return -1; | |
517 } else { /* FF_B_TYPE */ | |
518 if (mb_type != 2) { | |
519 if (svq3_mc_dir(h, 0, mode, 0, 0) < 0) | |
520 return -1; | |
521 } else { | |
522 for (i = 0; i < 4; i++) { | |
523 memset(s->current_picture.motion_val[0][b_xy + i*h->b_stride], 0, 4*2*sizeof(int16_t)); | |
524 } | |
525 } | |
526 if (mb_type != 1) { | |
527 if (svq3_mc_dir(h, 0, mode, 1, (mb_type == 3)) < 0) | |
528 return -1; | |
529 } else { | |
530 for (i = 0; i < 4; i++) { | |
531 memset(s->current_picture.motion_val[1][b_xy + i*h->b_stride], 0, 4*2*sizeof(int16_t)); | |
532 } | |
533 } | |
2979 | 534 } |
8196 | 535 |
536 mb_type = MB_TYPE_16x16; | |
537 } else if (mb_type == 8 || mb_type == 33) { /* INTRA4x4 */ | |
538 memset(h->intra4x4_pred_mode_cache, -1, 8*5*sizeof(int8_t)); | |
539 | |
540 if (mb_type == 8) { | |
541 if (s->mb_x > 0) { | |
542 for (i = 0; i < 4; i++) { | |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
543 h->intra4x4_pred_mode_cache[scan8[0] - 1 + i*8] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1]+6-i]; |
8196 | 544 } |
545 if (h->intra4x4_pred_mode_cache[scan8[0] - 1] == -1) { | |
546 h->left_samples_available = 0x5F5F; | |
547 } | |
548 } | |
549 if (s->mb_y > 0) { | |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
550 h->intra4x4_pred_mode_cache[4+8*0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride]+0]; |
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
551 h->intra4x4_pred_mode_cache[5+8*0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride]+1]; |
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
552 h->intra4x4_pred_mode_cache[6+8*0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride]+2]; |
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
553 h->intra4x4_pred_mode_cache[7+8*0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride]+3]; |
8196 | 554 |
555 if (h->intra4x4_pred_mode_cache[4+8*0] == -1) { | |
556 h->top_samples_available = 0x33FF; | |
557 } | |
558 } | |
559 | |
560 /* decode prediction codes for luma blocks */ | |
561 for (i = 0; i < 16; i+=2) { | |
562 vlc = svq3_get_ue_golomb(&s->gb); | |
1234 | 563 |
8196 | 564 if (vlc >= 25){ |
565 av_log(h->s.avctx, AV_LOG_ERROR, "luma prediction:%d\n", vlc); | |
566 return -1; | |
567 } | |
568 | |
569 left = &h->intra4x4_pred_mode_cache[scan8[i] - 1]; | |
570 top = &h->intra4x4_pred_mode_cache[scan8[i] - 8]; | |
571 | |
572 left[1] = svq3_pred_1[top[0] + 1][left[0] + 1][svq3_pred_0[vlc][0]]; | |
573 left[2] = svq3_pred_1[top[1] + 1][left[1] + 1][svq3_pred_0[vlc][1]]; | |
1319 | 574 |
8196 | 575 if (left[1] == -1 || left[2] == -1){ |
576 av_log(h->s.avctx, AV_LOG_ERROR, "weird prediction\n"); | |
577 return -1; | |
578 } | |
579 } | |
580 } else { /* mb_type == 33, DC_128_PRED block type */ | |
581 for (i = 0; i < 4; i++) { | |
582 memset(&h->intra4x4_pred_mode_cache[scan8[0] + 8*i], DC_PRED, 4); | |
583 } | |
584 } | |
585 | |
10852 | 586 ff_h264_write_back_intra_pred_mode(h); |
1234 | 587 |
8196 | 588 if (mb_type == 8) { |
10863
974ac220c93a
Move check_intra4x4_pred_mode() back from h264.h to h264.c, the function is just
michael
parents:
10852
diff
changeset
|
589 ff_h264_check_intra4x4_pred_mode(h); |
8196 | 590 |
591 h->top_samples_available = (s->mb_y == 0) ? 0x33FF : 0xFFFF; | |
592 h->left_samples_available = (s->mb_x == 0) ? 0x5F5F : 0xFFFF; | |
593 } else { | |
594 for (i = 0; i < 4; i++) { | |
595 memset(&h->intra4x4_pred_mode_cache[scan8[0] + 8*i], DC_128_PRED, 4); | |
596 } | |
597 | |
598 h->top_samples_available = 0x33FF; | |
599 h->left_samples_available = 0x5F5F; | |
2979 | 600 } |
8196 | 601 |
602 mb_type = MB_TYPE_INTRA4x4; | |
603 } else { /* INTRA16x16 */ | |
604 dir = i_mb_type_info[mb_type - 8].pred_mode; | |
605 dir = (dir >> 1) ^ 3*(dir & 1) ^ 1; | |
606 | |
10852 | 607 if ((h->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, dir)) == -1){ |
8196 | 608 av_log(h->s.avctx, AV_LOG_ERROR, "check_intra_pred_mode = -1\n"); |
609 return -1; | |
2979 | 610 } |
8196 | 611 |
612 cbp = i_mb_type_info[mb_type - 8].cbp; | |
613 mb_type = MB_TYPE_INTRA16x16; | |
1234 | 614 } |
615 | |
8196 | 616 if (!IS_INTER(mb_type) && s->pict_type != FF_I_TYPE) { |
617 for (i = 0; i < 4; i++) { | |
618 memset(s->current_picture.motion_val[0][b_xy + i*h->b_stride], 0, 4*2*sizeof(int16_t)); | |
2979 | 619 } |
8196 | 620 if (s->pict_type == FF_B_TYPE) { |
621 for (i = 0; i < 4; i++) { | |
622 memset(s->current_picture.motion_val[1][b_xy + i*h->b_stride], 0, 4*2*sizeof(int16_t)); | |
623 } | |
2979 | 624 } |
8196 | 625 } |
626 if (!IS_INTRA4x4(mb_type)) { | |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
627 memset(h->intra4x4_pred_mode+h->mb2br_xy[mb_xy], DC_PRED, 8); |
8196 | 628 } |
629 if (!IS_SKIP(mb_type) || s->pict_type == FF_B_TYPE) { | |
630 memset(h->non_zero_count_cache + 8, 0, 4*9*sizeof(uint8_t)); | |
631 s->dsp.clear_blocks(h->mb); | |
632 } | |
1319 | 633 |
8196 | 634 if (!IS_INTRA16x16(mb_type) && (!IS_SKIP(mb_type) || s->pict_type == FF_B_TYPE)) { |
635 if ((vlc = svq3_get_ue_golomb(&s->gb)) >= 48){ | |
636 av_log(h->s.avctx, AV_LOG_ERROR, "cbp_vlc=%d\n", vlc); | |
637 return -1; | |
2452 | 638 } |
1319 | 639 |
8196 | 640 cbp = IS_INTRA(mb_type) ? golomb_to_intra4x4_cbp[vlc] : golomb_to_inter_cbp[vlc]; |
1234 | 641 } |
8196 | 642 if (IS_INTRA16x16(mb_type) || (s->pict_type != FF_I_TYPE && s->adaptive_quant && cbp)) { |
643 s->qscale += svq3_get_se_golomb(&s->gb); | |
1319 | 644 |
8196 | 645 if (s->qscale > 31){ |
646 av_log(h->s.avctx, AV_LOG_ERROR, "qscale:%d\n", s->qscale); | |
647 return -1; | |
648 } | |
1319 | 649 } |
8196 | 650 if (IS_INTRA16x16(mb_type)) { |
651 if (svq3_decode_block(&s->gb, h->mb, 0, 0)){ | |
652 av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding intra luma dc\n"); | |
653 return -1; | |
654 } | |
2452 | 655 } |
1234 | 656 |
8196 | 657 if (cbp) { |
658 const int index = IS_INTRA16x16(mb_type) ? 1 : 0; | |
659 const int type = ((s->qscale < 24 && IS_INTRA4x4(mb_type)) ? 2 : 1); | |
660 | |
661 for (i = 0; i < 4; i++) { | |
662 if ((cbp & (1 << i))) { | |
663 for (j = 0; j < 4; j++) { | |
664 k = index ? ((j&1) + 2*(i&1) + 2*(j&2) + 4*(i&2)) : (4*i + j); | |
665 h->non_zero_count_cache[ scan8[k] ] = 1; | |
666 | |
667 if (svq3_decode_block(&s->gb, &h->mb[16*k], index, type)){ | |
668 av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding block\n"); | |
669 return -1; | |
670 } | |
671 } | |
672 } | |
673 } | |
1234 | 674 |
8196 | 675 if ((cbp & 0x30)) { |
676 for (i = 0; i < 2; ++i) { | |
677 if (svq3_decode_block(&s->gb, &h->mb[16*(16 + 4*i)], 0, 3)){ | |
678 av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding chroma dc block\n"); | |
679 return -1; | |
680 } | |
681 } | |
1234 | 682 |
8196 | 683 if ((cbp & 0x20)) { |
684 for (i = 0; i < 8; i++) { | |
685 h->non_zero_count_cache[ scan8[16+i] ] = 1; | |
686 | |
687 if (svq3_decode_block(&s->gb, &h->mb[16*(16 + i)], 1, 1)){ | |
688 av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding chroma ac block\n"); | |
689 return -1; | |
690 } | |
691 } | |
692 } | |
693 } | |
2452 | 694 } |
1330
c05c381a9c47
- fix PLANE_PRED8x8 prediction (H/V are swapped, this is correct!)
tmmm
parents:
1321
diff
changeset
|
695 |
8381
10aed1a9444b
10l, svq3 didnt set h->cbp, this broke decoding a little.
michael
parents:
8364
diff
changeset
|
696 h->cbp= cbp; |
8196 | 697 s->current_picture.mb_type[mb_xy] = mb_type; |
1234 | 698 |
8196 | 699 if (IS_INTRA(mb_type)) { |
10852 | 700 h->chroma_pred_mode = ff_h264_check_intra_pred_mode(h, DC_PRED8x8); |
1234 | 701 } |
702 | |
8196 | 703 return 0; |
1234 | 704 } |
705 | |
8195 | 706 static int svq3_decode_slice_header(H264Context *h) |
707 { | |
8196 | 708 MpegEncContext *const s = (MpegEncContext *) h; |
709 const int mb_xy = h->mb_xy; | |
710 int i, header; | |
711 | |
712 header = get_bits(&s->gb, 8); | |
1319 | 713 |
8196 | 714 if (((header & 0x9F) != 1 && (header & 0x9F) != 2) || (header & 0x60) == 0) { |
715 /* TODO: what? */ | |
716 av_log(h->s.avctx, AV_LOG_ERROR, "unsupported slice header (%02X)\n", header); | |
717 return -1; | |
718 } else { | |
719 int length = (header >> 5) & 3; | |
720 | |
721 h->next_slice_index = get_bits_count(&s->gb) + 8*show_bits(&s->gb, 8*length) + 8*length; | |
1319 | 722 |
8196 | 723 if (h->next_slice_index > s->gb.size_in_bits) { |
724 av_log(h->s.avctx, AV_LOG_ERROR, "slice after bitstream end\n"); | |
725 return -1; | |
726 } | |
727 | |
728 s->gb.size_in_bits = h->next_slice_index - 8*(length - 1); | |
729 skip_bits(&s->gb, 8); | |
1319 | 730 |
8196 | 731 if (h->svq3_watermark_key) { |
732 uint32_t header = AV_RL32(&s->gb.buffer[(get_bits_count(&s->gb)>>3)+1]); | |
733 AV_WL32(&s->gb.buffer[(get_bits_count(&s->gb)>>3)+1], header ^ h->svq3_watermark_key); | |
734 } | |
735 if (length > 0) { | |
736 memcpy((uint8_t *) &s->gb.buffer[get_bits_count(&s->gb) >> 3], | |
737 &s->gb.buffer[s->gb.size_in_bits >> 3], (length - 1)); | |
738 } | |
9080 | 739 skip_bits_long(&s->gb, 0); |
8196 | 740 } |
1319 | 741 |
8196 | 742 if ((i = svq3_get_ue_golomb(&s->gb)) == INVALID_VLC || i >= 3){ |
743 av_log(h->s.avctx, AV_LOG_ERROR, "illegal slice type %d \n", i); | |
744 return -1; | |
1754
bdf3927bf8c5
closed gop support & flags2 as all bits in flags are used
michael
parents:
1699
diff
changeset
|
745 } |
1319 | 746 |
8196 | 747 h->slice_type = golomb_to_pict_type[i]; |
1319 | 748 |
8196 | 749 if ((header & 0x9F) == 2) { |
750 i = (s->mb_num < 64) ? 6 : (1 + av_log2 (s->mb_num - 1)); | |
751 s->mb_skip_run = get_bits(&s->gb, i) - (s->mb_x + (s->mb_y * s->mb_width)); | |
752 } else { | |
753 skip_bits1(&s->gb); | |
754 s->mb_skip_run = 0; | |
8066
94fa05bc0390
svq3 watermark decoding support, based on reverse engineering work by chrono
bcoudurier
parents:
8059
diff
changeset
|
755 } |
1319 | 756 |
8196 | 757 h->slice_num = get_bits(&s->gb, 8); |
758 s->qscale = get_bits(&s->gb, 5); | |
759 s->adaptive_quant = get_bits1(&s->gb); | |
1319 | 760 |
8196 | 761 /* unknown fields */ |
762 skip_bits1(&s->gb); | |
763 | |
764 if (h->unknown_svq3_flag) { | |
765 skip_bits1(&s->gb); | |
766 } | |
1319 | 767 |
8196 | 768 skip_bits1(&s->gb); |
769 skip_bits(&s->gb, 2); | |
1319 | 770 |
8196 | 771 while (get_bits1(&s->gb)) { |
772 skip_bits(&s->gb, 8); | |
773 } | |
1319 | 774 |
8196 | 775 /* reset intra predictors and invalidate motion vector references */ |
776 if (s->mb_x > 0) { | |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
777 memset(h->intra4x4_pred_mode+h->mb2br_xy[mb_xy - 1 ]+3, -1, 4*sizeof(int8_t)); |
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
778 memset(h->intra4x4_pred_mode+h->mb2br_xy[mb_xy - s->mb_x] , -1, 8*sizeof(int8_t)*s->mb_x); |
8196 | 779 } |
780 if (s->mb_y > 0) { | |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
781 memset(h->intra4x4_pred_mode+h->mb2br_xy[mb_xy - s->mb_stride], -1, 8*sizeof(int8_t)*(s->mb_width - s->mb_x)); |
1319 | 782 |
8196 | 783 if (s->mb_x > 0) { |
11291
1527e25ec9d4
svq3 now in working condition, at least vissually, ill let fate tell us
michael
parents:
11290
diff
changeset
|
784 h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride - 1]+3] = -1; |
8196 | 785 } |
786 } | |
1319 | 787 |
8196 | 788 return 0; |
1319 | 789 } |
790 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8718
diff
changeset
|
791 static av_cold int svq3_decode_init(AVCodecContext *avctx) |
8195 | 792 { |
8196 | 793 MpegEncContext *const s = avctx->priv_data; |
794 H264Context *const h = avctx->priv_data; | |
8209
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
795 int m; |
8196 | 796 unsigned char *extradata; |
797 unsigned int size; | |
798 | |
10151
6cd8b6fd5f0f
Check thread count as multithreaded decoding is not supported.
michael
parents:
10146
diff
changeset
|
799 if(avctx->thread_count > 1){ |
6cd8b6fd5f0f
Check thread count as multithreaded decoding is not supported.
michael
parents:
10146
diff
changeset
|
800 av_log(avctx, AV_LOG_ERROR, "SVQ3 does not support multithreaded decoding, patch welcome! (check latest SVN too)\n"); |
6cd8b6fd5f0f
Check thread count as multithreaded decoding is not supported.
michael
parents:
10146
diff
changeset
|
801 return -1; |
6cd8b6fd5f0f
Check thread count as multithreaded decoding is not supported.
michael
parents:
10146
diff
changeset
|
802 } |
6cd8b6fd5f0f
Check thread count as multithreaded decoding is not supported.
michael
parents:
10146
diff
changeset
|
803 |
10852 | 804 if (ff_h264_decode_init(avctx) < 0) |
8209
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
805 return -1; |
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
806 |
8196 | 807 s->flags = avctx->flags; |
808 s->flags2 = avctx->flags2; | |
809 s->unrestricted_mv = 1; | |
8364
4a01f7144da5
Fix svq3 decoding, is_complex was not initialized.
michael
parents:
8209
diff
changeset
|
810 h->is_complex=1; |
10677
abf5c20eebf4
SVQ3 : Set avctx->pix_fmt correctly during decoder initialisation.
jai_menon
parents:
10442
diff
changeset
|
811 avctx->pix_fmt = avctx->codec->pix_fmts[0]; |
8196 | 812 |
813 if (!s->context_initialized) { | |
814 s->width = avctx->width; | |
815 s->height = avctx->height; | |
816 h->halfpel_flag = 1; | |
817 h->thirdpel_flag = 1; | |
818 h->unknown_svq3_flag = 0; | |
819 h->chroma_qp[0] = h->chroma_qp[1] = 4; | |
820 | |
821 if (MPV_common_init(s) < 0) | |
822 return -1; | |
823 | |
824 h->b_stride = 4*s->mb_width; | |
825 | |
10852 | 826 ff_h264_alloc_tables(h); |
1319 | 827 |
8196 | 828 /* prowl for the "SEQH" marker in the extradata */ |
829 extradata = (unsigned char *)avctx->extradata; | |
830 for (m = 0; m < avctx->extradata_size; m++) { | |
831 if (!memcmp(extradata, "SEQH", 4)) | |
832 break; | |
833 extradata++; | |
834 } | |
835 | |
836 /* if a match was found, parse the extra data */ | |
837 if (extradata && !memcmp(extradata, "SEQH", 4)) { | |
838 | |
839 GetBitContext gb; | |
10020
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
840 int frame_size_code; |
8196 | 841 |
842 size = AV_RB32(&extradata[4]); | |
843 init_get_bits(&gb, extradata + 8, size*8); | |
844 | |
845 /* 'frame size code' and optional 'width, height' */ | |
10020
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
846 frame_size_code = get_bits(&gb, 3); |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
847 switch (frame_size_code) { |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
848 case 0: avctx->width = 160; avctx->height = 120; break; |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
849 case 1: avctx->width = 128; avctx->height = 96; break; |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
850 case 2: avctx->width = 176; avctx->height = 144; break; |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
851 case 3: avctx->width = 352; avctx->height = 288; break; |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
852 case 4: avctx->width = 704; avctx->height = 576; break; |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
853 case 5: avctx->width = 240; avctx->height = 180; break; |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
854 case 6: avctx->width = 320; avctx->height = 240; break; |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
855 case 7: |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
856 avctx->width = get_bits(&gb, 12); |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
857 avctx->height = get_bits(&gb, 12); |
617166c76faf
Parse frame size code, see "svq3.c: parse frame size" thread on ML.
rbultje
parents:
9733
diff
changeset
|
858 break; |
8196 | 859 } |
860 | |
861 h->halfpel_flag = get_bits1(&gb); | |
862 h->thirdpel_flag = get_bits1(&gb); | |
1699 | 863 |
8196 | 864 /* unknown fields */ |
865 skip_bits1(&gb); | |
866 skip_bits1(&gb); | |
867 skip_bits1(&gb); | |
868 skip_bits1(&gb); | |
869 | |
870 s->low_delay = get_bits1(&gb); | |
871 | |
872 /* unknown field */ | |
873 skip_bits1(&gb); | |
1234 | 874 |
8196 | 875 while (get_bits1(&gb)) { |
876 skip_bits(&gb, 8); | |
877 } | |
878 | |
879 h->unknown_svq3_flag = get_bits1(&gb); | |
880 avctx->has_b_frames = !s->low_delay; | |
881 if (h->unknown_svq3_flag) { | |
8590 | 882 #if CONFIG_ZLIB |
8196 | 883 unsigned watermark_width = svq3_get_ue_golomb(&gb); |
884 unsigned watermark_height = svq3_get_ue_golomb(&gb); | |
885 int u1 = svq3_get_ue_golomb(&gb); | |
886 int u2 = get_bits(&gb, 8); | |
887 int u3 = get_bits(&gb, 2); | |
888 int u4 = svq3_get_ue_golomb(&gb); | |
11881
8daf3134622c
Fix svq3 watermark log uncompress on 64bit, probably fixes issue 1263
bcoudurier
parents:
11644
diff
changeset
|
889 unsigned long buf_len = watermark_width*watermark_height*4; |
8196 | 890 int offset = (get_bits_count(&gb)+7)>>3; |
891 uint8_t *buf; | |
1234 | 892 |
8196 | 893 if ((uint64_t)watermark_width*4 > UINT_MAX/watermark_height) |
894 return -1; | |
1319 | 895 |
8196 | 896 buf = av_malloc(buf_len); |
897 av_log(avctx, AV_LOG_DEBUG, "watermark size: %dx%d\n", watermark_width, watermark_height); | |
898 av_log(avctx, AV_LOG_DEBUG, "u1: %x u2: %x u3: %x compressed data size: %d offset: %d\n", u1, u2, u3, u4, offset); | |
11881
8daf3134622c
Fix svq3 watermark log uncompress on 64bit, probably fixes issue 1263
bcoudurier
parents:
11644
diff
changeset
|
899 if (uncompress(buf, &buf_len, extradata + 8 + offset, size - offset) != Z_OK) { |
8196 | 900 av_log(avctx, AV_LOG_ERROR, "could not uncompress watermark logo\n"); |
901 av_free(buf); | |
902 return -1; | |
903 } | |
904 h->svq3_watermark_key = ff_svq1_packet_checksum(buf, buf_len, 0); | |
905 h->svq3_watermark_key = h->svq3_watermark_key << 16 | h->svq3_watermark_key; | |
906 av_log(avctx, AV_LOG_DEBUG, "watermark key %#x\n", h->svq3_watermark_key); | |
907 av_free(buf); | |
908 #else | |
909 av_log(avctx, AV_LOG_ERROR, "this svq3 file contains watermark which need zlib support compiled in\n"); | |
910 return -1; | |
911 #endif | |
912 } | |
913 } | |
914 } | |
915 | |
8209
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
916 return 0; |
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
917 } |
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
918 |
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
919 static int svq3_decode_frame(AVCodecContext *avctx, |
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
920 void *data, int *data_size, |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9080
diff
changeset
|
921 AVPacket *avpkt) |
8209
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
922 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9080
diff
changeset
|
923 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
9080
diff
changeset
|
924 int buf_size = avpkt->size; |
8209
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
925 MpegEncContext *const s = avctx->priv_data; |
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
926 H264Context *const h = avctx->priv_data; |
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
927 int m, mb_type; |
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
928 |
8196 | 929 /* special case for last picture */ |
930 if (buf_size == 0) { | |
931 if (s->next_picture_ptr && !s->low_delay) { | |
932 *(AVFrame *) data = *(AVFrame *) &s->next_picture; | |
933 s->next_picture_ptr = NULL; | |
934 *data_size = sizeof(AVFrame); | |
935 } | |
936 return 0; | |
1877
869256817a91
smarten up the SVQ3 extradata decoder without changing the external API
melanson
parents:
1754
diff
changeset
|
937 } |
1878
838c18d1e7fc
be smarter about the variable size of the extra SVQ3 data
melanson
parents:
1877
diff
changeset
|
938 |
8196 | 939 init_get_bits (&s->gb, buf, 8*buf_size); |
1234 | 940 |
8196 | 941 s->mb_x = s->mb_y = h->mb_xy = 0; |
1319 | 942 |
8196 | 943 if (svq3_decode_slice_header(h)) |
944 return -1; | |
1319 | 945 |
8196 | 946 s->pict_type = h->slice_type; |
947 s->picture_number = h->slice_num; | |
8066
94fa05bc0390
svq3 watermark decoding support, based on reverse engineering work by chrono
bcoudurier
parents:
8059
diff
changeset
|
948 |
8196 | 949 if (avctx->debug&FF_DEBUG_PICT_INFO){ |
950 av_log(h->s.avctx, AV_LOG_DEBUG, "%c hpel:%d, tpel:%d aqp:%d qp:%d, slice_num:%02X\n", | |
951 av_get_pict_type_char(s->pict_type), h->halfpel_flag, h->thirdpel_flag, | |
952 s->adaptive_quant, s->qscale, h->slice_num); | |
1234 | 953 } |
954 | |
8196 | 955 /* for hurry_up == 5 */ |
956 s->current_picture.pict_type = s->pict_type; | |
957 s->current_picture.key_frame = (s->pict_type == FF_I_TYPE); | |
1234 | 958 |
8196 | 959 /* Skip B-frames if we do not have reference frames. */ |
960 if (s->last_picture_ptr == NULL && s->pict_type == FF_B_TYPE) | |
961 return 0; | |
962 /* Skip B-frames if we are in a hurry. */ | |
963 if (avctx->hurry_up && s->pict_type == FF_B_TYPE) | |
964 return 0; | |
965 /* Skip everything if we are in a hurry >= 5. */ | |
966 if (avctx->hurry_up >= 5) | |
967 return 0; | |
968 if ( (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type == FF_B_TYPE) | |
969 ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type != FF_I_TYPE) | |
970 || avctx->skip_frame >= AVDISCARD_ALL) | |
971 return 0; | |
1319 | 972 |
8196 | 973 if (s->next_p_frame_damaged) { |
974 if (s->pict_type == FF_B_TYPE) | |
975 return 0; | |
976 else | |
977 s->next_p_frame_damaged = 0; | |
1319 | 978 } |
979 | |
10852 | 980 if (ff_h264_frame_start(h) < 0) |
8196 | 981 return -1; |
2967 | 982 |
8196 | 983 if (s->pict_type == FF_B_TYPE) { |
984 h->frame_num_offset = (h->slice_num - h->prev_frame_num); | |
1319 | 985 |
8196 | 986 if (h->frame_num_offset < 0) { |
987 h->frame_num_offset += 256; | |
988 } | |
989 if (h->frame_num_offset == 0 || h->frame_num_offset >= h->prev_frame_num_offset) { | |
990 av_log(h->s.avctx, AV_LOG_ERROR, "error in B-frame picture id\n"); | |
991 return -1; | |
992 } | |
993 } else { | |
994 h->prev_frame_num = h->frame_num; | |
995 h->frame_num = h->slice_num; | |
996 h->prev_frame_num_offset = (h->frame_num - h->prev_frame_num); | |
1234 | 997 |
8196 | 998 if (h->prev_frame_num_offset < 0) { |
999 h->prev_frame_num_offset += 256; | |
1000 } | |
1234 | 1001 } |
1268 | 1002 |
8196 | 1003 for (m = 0; m < 2; m++){ |
1004 int i; | |
1005 for (i = 0; i < 4; i++){ | |
1006 int j; | |
1007 for (j = -1; j < 4; j++) | |
1008 h->ref_cache[m][scan8[0] + 8*i + j]= 1; | |
1009 if (i < 3) | |
1010 h->ref_cache[m][scan8[0] + 8*i + j]= PART_NOT_AVAILABLE; | |
1011 } | |
1012 } | |
1234 | 1013 |
8196 | 1014 for (s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) { |
1015 for (s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) { | |
1016 h->mb_xy = s->mb_x + s->mb_y*s->mb_stride; | |
1017 | |
1018 if ( (get_bits_count(&s->gb) + 7) >= s->gb.size_in_bits && | |
1019 ((get_bits_count(&s->gb) & 7) == 0 || show_bits(&s->gb, (-get_bits_count(&s->gb) & 7)) == 0)) { | |
1020 | |
1021 skip_bits(&s->gb, h->next_slice_index - get_bits_count(&s->gb)); | |
1022 s->gb.size_in_bits = 8*buf_size; | |
1023 | |
1024 if (svq3_decode_slice_header(h)) | |
1025 return -1; | |
1026 | |
1027 /* TODO: support s->mb_skip_run */ | |
1028 } | |
1029 | |
1030 mb_type = svq3_get_ue_golomb(&s->gb); | |
1319 | 1031 |
8196 | 1032 if (s->pict_type == FF_I_TYPE) { |
1033 mb_type += 8; | |
1034 } else if (s->pict_type == FF_B_TYPE && mb_type >= 4) { | |
1035 mb_type += 4; | |
1036 } | |
1037 if (mb_type > 33 || svq3_decode_mb(h, mb_type)) { | |
1038 av_log(h->s.avctx, AV_LOG_ERROR, "error while decoding MB %d %d\n", s->mb_x, s->mb_y); | |
1039 return -1; | |
1040 } | |
1041 | |
1042 if (mb_type != 0) { | |
10852 | 1043 ff_h264_hl_decode_mb (h); |
8196 | 1044 } |
1045 | |
1046 if (s->pict_type != FF_B_TYPE && !s->low_delay) { | |
1047 s->current_picture.mb_type[s->mb_x + s->mb_y*s->mb_stride] = | |
1048 (s->pict_type == FF_P_TYPE && mb_type < 8) ? (mb_type - 1) : -1; | |
1049 } | |
1050 } | |
1234 | 1051 |
8196 | 1052 ff_draw_horiz_band(s, 16*s->mb_y, 16); |
1053 } | |
1054 | |
1055 MPV_frame_end(s); | |
1319 | 1056 |
8196 | 1057 if (s->pict_type == FF_B_TYPE || s->low_delay) { |
1058 *(AVFrame *) data = *(AVFrame *) &s->current_picture; | |
1059 } else { | |
1060 *(AVFrame *) data = *(AVFrame *) &s->last_picture; | |
1061 } | |
1319 | 1062 |
8196 | 1063 /* Do not output the last pic after seeking. */ |
1064 if (s->last_picture_ptr || s->low_delay) { | |
1065 *data_size = sizeof(AVFrame); | |
1066 } | |
1067 | |
1068 return buf_size; | |
1234 | 1069 } |
1070 | |
1071 | |
1072 AVCodec svq3_decoder = { | |
1073 "svq3", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11291
diff
changeset
|
1074 AVMEDIA_TYPE_VIDEO, |
1234 | 1075 CODEC_ID_SVQ3, |
1076 sizeof(H264Context), | |
8209
65e05fda5280
move decoder initialization in separate function, earlier failure detection
bcoudurier
parents:
8196
diff
changeset
|
1077 svq3_decode_init, |
1234 | 1078 NULL, |
10852 | 1079 ff_h264_decode_end, |
1234 | 1080 svq3_decode_frame, |
2453 | 1081 CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_DELAY, |
10442
fc06fc944c6d
Add additional long names for the Sorenson Vector Quantizer 3 decoder.
stefano
parents:
10151
diff
changeset
|
1082 .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 3 / Sorenson Video 3 / SVQ3"), |
10146
38cfe222e1a4
Mark all pix_fmts and supported_framerates compound literals as const.
reimar
parents:
10020
diff
changeset
|
1083 .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUVJ420P, PIX_FMT_NONE}, |
1234 | 1084 }; |