/src/ffmpeg/libavcodec/vc1_parser.c
Line | Count | Source |
1 | | /* |
2 | | * VC-1 and WMV3 parser |
3 | | * Copyright (c) 2006-2007 Konstantin Shishkov |
4 | | * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer |
5 | | * |
6 | | * This file is part of FFmpeg. |
7 | | * |
8 | | * FFmpeg is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public |
10 | | * License as published by the Free Software Foundation; either |
11 | | * version 2.1 of the License, or (at your option) any later version. |
12 | | * |
13 | | * FFmpeg is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public |
19 | | * License along with FFmpeg; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | */ |
22 | | |
23 | | /** |
24 | | * @file |
25 | | * VC-1 and WMV3 parser |
26 | | */ |
27 | | |
28 | | #include "libavutil/attributes.h" |
29 | | #include "libavutil/avassert.h" |
30 | | #include "parser.h" |
31 | | #include "parser_internal.h" |
32 | | #include "vc1.h" |
33 | | #include "get_bits.h" |
34 | | #include "vc1dsp.h" |
35 | | |
36 | | /** The maximum number of bytes of a sequence, entry point or |
37 | | * frame header whose values we pay any attention to */ |
38 | 36.2M | #define UNESCAPED_THRESHOLD 37 |
39 | | |
40 | | /** The maximum number of bytes of a sequence, entry point or |
41 | | * frame header which must be valid memory (because they are |
42 | | * used to update the bitstream cache in skip_bits() calls) |
43 | | */ |
44 | | #define UNESCAPED_LIMIT 144 |
45 | | |
46 | | typedef enum { |
47 | | NO_MATCH, |
48 | | ONE_ZERO, |
49 | | TWO_ZEROS, |
50 | | ONE |
51 | | } VC1ParseSearchState; |
52 | | |
53 | | typedef struct VC1ParseContext { |
54 | | ParseContext pc; |
55 | | VC1Context v; |
56 | | uint8_t prev_start_code; |
57 | | size_t bytes_to_skip; |
58 | | uint8_t unesc_buffer[UNESCAPED_LIMIT]; |
59 | | size_t unesc_index; |
60 | | VC1ParseSearchState search_state; |
61 | | } VC1ParseContext; |
62 | | |
63 | | static void vc1_extract_header(AVCodecParserContext *s, AVCodecContext *avctx, |
64 | | const uint8_t *buf, int buf_size) |
65 | 1.26M | { |
66 | | /* Parse the header we just finished unescaping */ |
67 | 1.26M | VC1ParseContext *vpc = s->priv_data; |
68 | 1.26M | GetBitContext gb; |
69 | 1.26M | int ret; |
70 | 1.26M | vpc->v.s.avctx = avctx; |
71 | 1.26M | ret = init_get_bits8(&gb, buf, buf_size); |
72 | 1.26M | av_assert1(ret >= 0); // buf_size is bounded by UNESCAPED_THRESHOLD |
73 | | |
74 | 1.26M | switch (vpc->prev_start_code) { |
75 | 167k | case VC1_CODE_SEQHDR & 0xFF: |
76 | 167k | ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb); |
77 | 167k | break; |
78 | 178k | case VC1_CODE_ENTRYPOINT & 0xFF: |
79 | 178k | ff_vc1_decode_entry_point(avctx, &vpc->v, &gb); |
80 | 178k | break; |
81 | 341k | case VC1_CODE_FRAME & 0xFF: |
82 | 341k | if(vpc->v.profile < PROFILE_ADVANCED) |
83 | 226k | ret = ff_vc1_parse_frame_header (&vpc->v, &gb); |
84 | 114k | else |
85 | 114k | ret = ff_vc1_parse_frame_header_adv(&vpc->v, &gb); |
86 | | |
87 | 341k | if (ret < 0) |
88 | 29.2k | break; |
89 | | |
90 | | /* keep AV_PICTURE_TYPE_BI internal to VC1 */ |
91 | 312k | if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI) |
92 | 9.66k | s->pict_type = AV_PICTURE_TYPE_B; |
93 | 302k | else |
94 | 302k | s->pict_type = vpc->v.s.pict_type; |
95 | | |
96 | 312k | if (vpc->v.broadcast){ |
97 | | // process pulldown flags |
98 | 78.6k | s->repeat_pict = 1; |
99 | | // Pulldown flags are only valid when 'broadcast' has been set. |
100 | 78.6k | if (vpc->v.rff){ |
101 | | // repeat field |
102 | 33.6k | s->repeat_pict = 2; |
103 | 45.0k | }else if (vpc->v.rptfrm){ |
104 | | // repeat frames |
105 | 13.2k | s->repeat_pict = vpc->v.rptfrm * 2 + 1; |
106 | 13.2k | } |
107 | 233k | }else{ |
108 | 233k | s->repeat_pict = 0; |
109 | 233k | } |
110 | | |
111 | 312k | if (vpc->v.broadcast && vpc->v.interlace && !vpc->v.psf) |
112 | 58.6k | s->field_order = vpc->v.tff ? AV_FIELD_TT : AV_FIELD_BB; |
113 | 253k | else |
114 | 253k | s->field_order = AV_FIELD_PROGRESSIVE; |
115 | | |
116 | 312k | break; |
117 | 1.26M | } |
118 | 1.26M | s->format = vpc->v.chromaformat == 1 ? AV_PIX_FMT_YUV420P |
119 | 1.26M | : AV_PIX_FMT_NONE; |
120 | 1.26M | if (avctx->width && avctx->height) { |
121 | 1.17M | s->width = avctx->width; |
122 | 1.17M | s->height = avctx->height; |
123 | 1.17M | s->coded_width = FFALIGN(avctx->coded_width, 16); |
124 | 1.17M | s->coded_height = FFALIGN(avctx->coded_height, 16); |
125 | 1.17M | } |
126 | 1.26M | } |
127 | | |
128 | | static int vc1_parse(AVCodecParserContext *s, |
129 | | AVCodecContext *avctx, |
130 | | const uint8_t **poutbuf, int *poutbuf_size, |
131 | | const uint8_t *buf, int buf_size) |
132 | 542k | { |
133 | | /* Here we do the searching for frame boundaries and headers at |
134 | | * the same time. Only a minimal amount at the start of each |
135 | | * header is unescaped. */ |
136 | 542k | VC1ParseContext *vpc = s->priv_data; |
137 | 542k | int pic_found = vpc->pc.frame_start_found; |
138 | 542k | uint8_t *unesc_buffer = vpc->unesc_buffer; |
139 | 542k | size_t unesc_index = vpc->unesc_index; |
140 | 542k | VC1ParseSearchState search_state = vpc->search_state; |
141 | 542k | int start_code_found = 0; |
142 | 542k | int next = END_NOT_FOUND; |
143 | 542k | int i = vpc->bytes_to_skip; |
144 | | |
145 | 542k | if (pic_found && buf_size == 0) { |
146 | | /* EOF considered as end of frame */ |
147 | 526 | memset(unesc_buffer + unesc_index, 0, UNESCAPED_THRESHOLD - unesc_index); |
148 | 526 | vc1_extract_header(s, avctx, unesc_buffer, unesc_index); |
149 | 526 | next = 0; |
150 | 526 | } |
151 | 1.48M | while (i < buf_size) { |
152 | 1.37M | uint8_t b; |
153 | 1.37M | start_code_found = 0; |
154 | 32.1M | while (i < buf_size && unesc_index < UNESCAPED_THRESHOLD) { |
155 | 31.6M | b = buf[i++]; |
156 | 31.6M | unesc_buffer[unesc_index++] = b; |
157 | 31.6M | if (search_state <= ONE_ZERO) |
158 | 26.5M | search_state = b ? NO_MATCH : search_state + 1; |
159 | 5.10M | else if (search_state == TWO_ZEROS) { |
160 | 4.29M | if (b == 1) |
161 | 819k | search_state = ONE; |
162 | 3.47M | else if (b > 1) { |
163 | 1.29M | if (b == 3) |
164 | 62.9k | unesc_index--; // swallow emulation prevention byte |
165 | 1.29M | search_state = NO_MATCH; |
166 | 1.29M | } |
167 | 4.29M | } |
168 | 809k | else { // search_state == ONE |
169 | | // Header unescaping terminates early due to detection of next start code |
170 | 809k | search_state = NO_MATCH; |
171 | 809k | start_code_found = 1; |
172 | 809k | break; |
173 | 809k | } |
174 | 31.6M | } |
175 | 1.37M | if ((s->flags & PARSER_FLAG_COMPLETE_FRAMES) && |
176 | 4.51k | unesc_index >= UNESCAPED_THRESHOLD && |
177 | 1.81k | vpc->prev_start_code == (VC1_CODE_FRAME & 0xFF)) |
178 | 2 | { |
179 | | // No need to keep scanning the rest of the buffer for |
180 | | // start codes if we know it contains a complete frame and |
181 | | // we've already unescaped all we need of the frame header |
182 | 2 | vc1_extract_header(s, avctx, unesc_buffer, unesc_index); |
183 | 2 | unesc_index = 0; |
184 | 2 | break; |
185 | 2 | } |
186 | 1.37M | if (unesc_index >= UNESCAPED_THRESHOLD && !start_code_found) { |
187 | 11.2M | while (i < buf_size) { |
188 | 11.2M | if (search_state == NO_MATCH) { |
189 | 2.57M | i += vpc->v.vc1dsp.startcode_find_candidate(buf + i, buf_size - i); |
190 | 2.57M | if (i < buf_size) { |
191 | 2.53M | search_state = ONE_ZERO; |
192 | 2.53M | } |
193 | 2.57M | i++; |
194 | 8.62M | } else { |
195 | 8.62M | b = buf[i++]; |
196 | 8.62M | if (search_state == ONE_ZERO) |
197 | 2.58M | search_state = b ? NO_MATCH : TWO_ZEROS; |
198 | 6.04M | else if (search_state == TWO_ZEROS) { |
199 | 5.58M | if (b >= 1) |
200 | 1.60M | search_state = b == 1 ? ONE : NO_MATCH; |
201 | 5.58M | } |
202 | 455k | else { // search_state == ONE |
203 | 455k | search_state = NO_MATCH; |
204 | 455k | start_code_found = 1; |
205 | 455k | break; |
206 | 455k | } |
207 | 8.62M | } |
208 | 11.2M | } |
209 | 512k | } |
210 | 1.37M | if (start_code_found) { |
211 | 1.26M | vc1_extract_header(s, avctx, unesc_buffer, unesc_index); |
212 | | |
213 | 1.26M | vpc->prev_start_code = b; |
214 | 1.26M | unesc_index = 0; |
215 | | |
216 | 1.26M | if (!(s->flags & PARSER_FLAG_COMPLETE_FRAMES)) { |
217 | 1.26M | if (!pic_found && (b == (VC1_CODE_FRAME & 0xFF) || b == (VC1_CODE_FIELD & 0xFF))) { |
218 | 170k | pic_found = 1; |
219 | 170k | } |
220 | 1.09M | else if (pic_found && b != (VC1_CODE_FIELD & 0xFF) && b != (VC1_CODE_SLICE & 0xFF) |
221 | 430k | && b != (VC1_CODE_ENDOFSEQ & 0xFF)) { |
222 | 430k | next = i - 4; |
223 | 430k | pic_found = b == (VC1_CODE_FRAME & 0xFF); |
224 | 430k | break; |
225 | 430k | } |
226 | 1.26M | } |
227 | 1.26M | } |
228 | 1.37M | } |
229 | | |
230 | 542k | vpc->pc.frame_start_found = pic_found; |
231 | 542k | vpc->unesc_index = unesc_index; |
232 | 542k | vpc->search_state = search_state; |
233 | | |
234 | 542k | if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { |
235 | 144 | next = buf_size; |
236 | 542k | } else { |
237 | 542k | if (ff_combine_frame(&vpc->pc, next, &buf, &buf_size) < 0) { |
238 | 110k | vpc->bytes_to_skip = 0; |
239 | 110k | *poutbuf = NULL; |
240 | 110k | *poutbuf_size = 0; |
241 | 110k | return buf_size; |
242 | 110k | } |
243 | 542k | } |
244 | | |
245 | | /* If we return with a valid pointer to a combined frame buffer |
246 | | * then on the next call then we'll have been unhelpfully rewound |
247 | | * by up to 4 bytes (depending upon whether the start code |
248 | | * overlapped the input buffer, and if so by how much). We don't |
249 | | * want this: it will either cause spurious second detections of |
250 | | * the start code we've already seen, or cause extra bytes to be |
251 | | * inserted at the start of the unescaped buffer. */ |
252 | 432k | vpc->bytes_to_skip = 4; |
253 | 432k | if (next < 0 && next != END_NOT_FOUND) |
254 | 1.51k | vpc->bytes_to_skip += next; |
255 | | |
256 | 432k | *poutbuf = buf; |
257 | 432k | *poutbuf_size = buf_size; |
258 | 432k | return next; |
259 | 542k | } |
260 | | |
261 | | static av_cold int vc1_parse_init(AVCodecParserContext *s) |
262 | 7.17k | { |
263 | 7.17k | VC1ParseContext *vpc = s->priv_data; |
264 | 7.17k | vpc->v.s.slice_context_count = 1; |
265 | 7.17k | vpc->v.first_pic_header_flag = 1; |
266 | 7.17k | vpc->v.parse_only = 1; |
267 | 7.17k | vpc->prev_start_code = 0; |
268 | 7.17k | vpc->bytes_to_skip = 0; |
269 | 7.17k | vpc->unesc_index = 0; |
270 | 7.17k | vpc->search_state = NO_MATCH; |
271 | 7.17k | ff_vc1dsp_init(&vpc->v.vc1dsp); /* startcode_find_candidate */ |
272 | 7.17k | return 0; |
273 | 7.17k | } |
274 | | |
275 | | const FFCodecParser ff_vc1_parser = { |
276 | | PARSER_CODEC_LIST(AV_CODEC_ID_VC1), |
277 | | .priv_data_size = sizeof(VC1ParseContext), |
278 | | .init = vc1_parse_init, |
279 | | .parse = vc1_parse, |
280 | | .close = ff_parse_close, |
281 | | }; |