Originally committed as revision 2492 to svn://svn.ffmpeg.org/ffmpeg/trunk
Fabrice Bellard authored on 2003/11/11 00:29:20... | ... |
@@ -19,7 +19,7 @@ OBJS= common.o utils.o mem.o allcodecs.o \ |
19 | 19 |
vp3.o asv1.o 4xm.o cabac.o ffv1.o ra144.o ra288.o vcr1.o cljr.o \ |
20 | 20 |
roqvideo.o dpcm.o interplayvideo.o xan.o rpza.o cinepak.o msrle.o \ |
21 | 21 |
msvideo1.o vqavideo.o idcinvideo.o adx.o rational.o faandct.o 8bps.o \ |
22 |
- smc.o |
|
22 |
+ smc.o parser.o |
|
23 | 23 |
|
24 | 24 |
ifeq ($(AMR_NB),yes) |
25 | 25 |
ifeq ($(AMR_NB_FIXED),yes) |
... | ... |
@@ -193,5 +193,16 @@ PCM_CODEC(CODEC_ID_ADPCM_XA, adpcm_xa); |
193 | 193 |
PCM_CODEC(CODEC_ID_ADPCM_ADX, adpcm_adx); |
194 | 194 |
|
195 | 195 |
#undef PCM_CODEC |
196 |
+ |
|
197 |
+ /* parsers */ |
|
198 |
+ av_register_codec_parser(&mpegvideo_parser); |
|
199 |
+ av_register_codec_parser(&mpeg4video_parser); |
|
200 |
+ av_register_codec_parser(&h263_parser); |
|
201 |
+ av_register_codec_parser(&h264_parser); |
|
202 |
+ |
|
203 |
+ av_register_codec_parser(&mpegaudio_parser); |
|
204 |
+#ifdef CONFIG_AC3 |
|
205 |
+ av_register_codec_parser(&ac3_parser); |
|
206 |
+#endif |
|
196 | 207 |
} |
197 | 208 |
|
... | ... |
@@ -16,7 +16,7 @@ extern "C" { |
16 | 16 |
|
17 | 17 |
#define FFMPEG_VERSION_INT 0x000408 |
18 | 18 |
#define FFMPEG_VERSION "0.4.8" |
19 |
-#define LIBAVCODEC_BUILD 4691 |
|
19 |
+#define LIBAVCODEC_BUILD 4692 |
|
20 | 20 |
|
21 | 21 |
#define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT |
22 | 22 |
#define LIBAVCODEC_VERSION FFMPEG_VERSION |
... | ... |
@@ -1839,6 +1839,50 @@ typedef enum { |
1839 | 1839 |
*/ |
1840 | 1840 |
int avcodec(void* handle, avc_cmd_t cmd, void* pin, void* pout); |
1841 | 1841 |
|
1842 |
+/* frame parsing */ |
|
1843 |
+typedef struct AVCodecParserContext { |
|
1844 |
+ void *priv_data; |
|
1845 |
+ struct AVCodecParser *parser; |
|
1846 |
+ int64_t frame_offset; /* offset of the current frame */ |
|
1847 |
+ int64_t cur_offset; /* current offset |
|
1848 |
+ (incremented by each av_parser_parse()) */ |
|
1849 |
+ int64_t last_frame_offset; /* offset of the last frame */ |
|
1850 |
+ /* video info */ |
|
1851 |
+ int pict_type; /* XXX: put it back in AVCodecContext */ |
|
1852 |
+ int repeat_pict; /* XXX: put it back in AVCodecContext */ |
|
1853 |
+ int64_t pts; /* in us, if given by the codec (used by raw mpeg4) */ |
|
1854 |
+ int64_t dts; /* in us, if given by the codec (used by raw mpeg4) */ |
|
1855 |
+} AVCodecParserContext; |
|
1856 |
+ |
|
1857 |
+typedef struct AVCodecParser { |
|
1858 |
+ int codec_ids[3]; /* several codec IDs are permitted */ |
|
1859 |
+ int priv_data_size; |
|
1860 |
+ int (*parser_init)(AVCodecParserContext *s); |
|
1861 |
+ int (*parser_parse)(AVCodecParserContext *s, |
|
1862 |
+ AVCodecContext *avctx, |
|
1863 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
1864 |
+ const uint8_t *buf, int buf_size); |
|
1865 |
+ void (*parser_close)(AVCodecParserContext *s); |
|
1866 |
+ struct AVCodecParser *next; |
|
1867 |
+} AVCodecParser; |
|
1868 |
+ |
|
1869 |
+extern AVCodecParser *av_first_parser; |
|
1870 |
+ |
|
1871 |
+void av_register_codec_parser(AVCodecParser *parser); |
|
1872 |
+AVCodecParserContext *av_parser_init(int codec_id); |
|
1873 |
+int av_parser_parse(AVCodecParserContext *s, |
|
1874 |
+ AVCodecContext *avctx, |
|
1875 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
1876 |
+ const uint8_t *buf, int buf_size); |
|
1877 |
+void av_parser_close(AVCodecParserContext *s); |
|
1878 |
+ |
|
1879 |
+extern AVCodecParser mpegvideo_parser; |
|
1880 |
+extern AVCodecParser mpeg4video_parser; |
|
1881 |
+extern AVCodecParser h263_parser; |
|
1882 |
+extern AVCodecParser h264_parser; |
|
1883 |
+extern AVCodecParser mpegaudio_parser; |
|
1884 |
+extern AVCodecParser ac3_parser; |
|
1885 |
+ |
|
1842 | 1886 |
/* memory */ |
1843 | 1887 |
void *av_malloc(unsigned int size); |
1844 | 1888 |
void *av_mallocz(unsigned int size); |
1845 | 1889 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,892 @@ |
0 |
+/* |
|
1 |
+ * Audio and Video frame extraction |
|
2 |
+ * Copyright (c) 2003 Fabrice Bellard. |
|
3 |
+ * Copyright (c) 2003 Michael Niedermayer. |
|
4 |
+ * |
|
5 |
+ * This library is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * This library is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with this library; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 |
+ */ |
|
19 |
+#include "avcodec.h" |
|
20 |
+#include "mpegvideo.h" |
|
21 |
+#include "mpegaudio.h" |
|
22 |
+ |
|
23 |
+AVCodecParser *av_first_parser = NULL; |
|
24 |
+ |
|
25 |
+void av_register_codec_parser(AVCodecParser *parser) |
|
26 |
+{ |
|
27 |
+ parser->next = av_first_parser; |
|
28 |
+ av_first_parser = parser; |
|
29 |
+} |
|
30 |
+ |
|
31 |
+AVCodecParserContext *av_parser_init(int codec_id) |
|
32 |
+{ |
|
33 |
+ AVCodecParserContext *s; |
|
34 |
+ AVCodecParser *parser; |
|
35 |
+ int ret; |
|
36 |
+ |
|
37 |
+ for(parser = av_first_parser; parser != NULL; parser = parser->next) { |
|
38 |
+ if (parser->codec_ids[0] == codec_id || |
|
39 |
+ parser->codec_ids[1] == codec_id || |
|
40 |
+ parser->codec_ids[2] == codec_id) |
|
41 |
+ goto found; |
|
42 |
+ } |
|
43 |
+ return NULL; |
|
44 |
+ found: |
|
45 |
+ s = av_mallocz(sizeof(AVCodecParserContext)); |
|
46 |
+ if (!s) |
|
47 |
+ return NULL; |
|
48 |
+ s->parser = parser; |
|
49 |
+ s->priv_data = av_mallocz(parser->priv_data_size); |
|
50 |
+ if (!s->priv_data) { |
|
51 |
+ av_free(s); |
|
52 |
+ return NULL; |
|
53 |
+ } |
|
54 |
+ if (parser->parser_init) { |
|
55 |
+ ret = parser->parser_init(s); |
|
56 |
+ if (ret != 0) { |
|
57 |
+ av_free(s->priv_data); |
|
58 |
+ av_free(s); |
|
59 |
+ return NULL; |
|
60 |
+ } |
|
61 |
+ } |
|
62 |
+ return s; |
|
63 |
+} |
|
64 |
+ |
|
65 |
+int av_parser_parse(AVCodecParserContext *s, |
|
66 |
+ AVCodecContext *avctx, |
|
67 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
68 |
+ const uint8_t *buf, int buf_size) |
|
69 |
+{ |
|
70 |
+ int index; |
|
71 |
+ /* WARNING: the returned index can be negative */ |
|
72 |
+ index = s->parser->parser_parse(s, avctx, poutbuf, poutbuf_size, buf, buf_size); |
|
73 |
+ /* update the file pointer */ |
|
74 |
+ if (*poutbuf_size) { |
|
75 |
+ s->frame_offset = s->last_frame_offset; |
|
76 |
+ s->last_frame_offset = s->cur_offset + index; |
|
77 |
+ } |
|
78 |
+ if (index < 0) |
|
79 |
+ index = 0; |
|
80 |
+ s->cur_offset += index; |
|
81 |
+ return index; |
|
82 |
+} |
|
83 |
+ |
|
84 |
+void av_parser_close(AVCodecParserContext *s) |
|
85 |
+{ |
|
86 |
+ if (s->parser->parser_close) |
|
87 |
+ s->parser->parser_close(s); |
|
88 |
+ av_free(s->priv_data); |
|
89 |
+ av_free(s); |
|
90 |
+} |
|
91 |
+ |
|
92 |
+/*****************************************************/ |
|
93 |
+ |
|
94 |
+//#define END_NOT_FOUND (-100) |
|
95 |
+ |
|
96 |
+#define PICTURE_START_CODE 0x00000100 |
|
97 |
+#define SEQ_START_CODE 0x000001b3 |
|
98 |
+#define EXT_START_CODE 0x000001b5 |
|
99 |
+#define SLICE_MIN_START_CODE 0x00000101 |
|
100 |
+#define SLICE_MAX_START_CODE 0x000001af |
|
101 |
+ |
|
102 |
+typedef struct ParseContext1{ |
|
103 |
+ uint8_t *buffer; |
|
104 |
+ int index; |
|
105 |
+ int last_index; |
|
106 |
+ int buffer_size; |
|
107 |
+ uint32_t state; ///< contains the last few bytes in MSB order |
|
108 |
+ int frame_start_found; |
|
109 |
+ int overread; ///< the number of bytes which where irreversibly read from the next frame |
|
110 |
+ int overread_index; ///< the index into ParseContext1.buffer of the overreaded bytes |
|
111 |
+ |
|
112 |
+ /* MPEG2 specific */ |
|
113 |
+ int frame_rate; |
|
114 |
+ int progressive_sequence; |
|
115 |
+ int width, height; |
|
116 |
+ /* XXX: suppress that, needed by MPEG4 */ |
|
117 |
+ MpegEncContext *enc; |
|
118 |
+} ParseContext1; |
|
119 |
+ |
|
120 |
+/** |
|
121 |
+ * combines the (truncated) bitstream to a complete frame |
|
122 |
+ * @returns -1 if no complete frame could be created |
|
123 |
+ */ |
|
124 |
+static int ff_combine_frame1(ParseContext1 *pc, int next, uint8_t **buf, int *buf_size) |
|
125 |
+{ |
|
126 |
+#if 0 |
|
127 |
+ if(pc->overread){ |
|
128 |
+ printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); |
|
129 |
+ printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); |
|
130 |
+ } |
|
131 |
+#endif |
|
132 |
+ |
|
133 |
+ /* copy overreaded bytes from last frame into buffer */ |
|
134 |
+ for(; pc->overread>0; pc->overread--){ |
|
135 |
+ pc->buffer[pc->index++]= pc->buffer[pc->overread_index++]; |
|
136 |
+ } |
|
137 |
+ |
|
138 |
+ pc->last_index= pc->index; |
|
139 |
+ |
|
140 |
+ /* copy into buffer end return */ |
|
141 |
+ if(next == END_NOT_FOUND){ |
|
142 |
+ pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, (*buf_size) + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); |
|
143 |
+ |
|
144 |
+ memcpy(&pc->buffer[pc->index], *buf, *buf_size); |
|
145 |
+ pc->index += *buf_size; |
|
146 |
+ return -1; |
|
147 |
+ } |
|
148 |
+ |
|
149 |
+ *buf_size= |
|
150 |
+ pc->overread_index= pc->index + next; |
|
151 |
+ |
|
152 |
+ /* append to buffer */ |
|
153 |
+ if(pc->index){ |
|
154 |
+ pc->buffer= av_fast_realloc(pc->buffer, &pc->buffer_size, next + pc->index + FF_INPUT_BUFFER_PADDING_SIZE); |
|
155 |
+ |
|
156 |
+ memcpy(&pc->buffer[pc->index], *buf, next + FF_INPUT_BUFFER_PADDING_SIZE ); |
|
157 |
+ pc->index = 0; |
|
158 |
+ *buf= pc->buffer; |
|
159 |
+ } |
|
160 |
+ |
|
161 |
+ /* store overread bytes */ |
|
162 |
+ for(;next < 0; next++){ |
|
163 |
+ pc->state = (pc->state<<8) | pc->buffer[pc->last_index + next]; |
|
164 |
+ pc->overread++; |
|
165 |
+ } |
|
166 |
+ |
|
167 |
+#if 0 |
|
168 |
+ if(pc->overread){ |
|
169 |
+ printf("overread %d, state:%X next:%d index:%d o_index:%d\n", pc->overread, pc->state, next, pc->index, pc->overread_index); |
|
170 |
+ printf("%X %X %X %X\n", (*buf)[0], (*buf)[1],(*buf)[2],(*buf)[3]); |
|
171 |
+ } |
|
172 |
+#endif |
|
173 |
+ |
|
174 |
+ return 0; |
|
175 |
+} |
|
176 |
+ |
|
177 |
+/** |
|
178 |
+ * finds the end of the current frame in the bitstream. |
|
179 |
+ * @return the position of the first byte of the next frame, or -1 |
|
180 |
+ */ |
|
181 |
+static int mpeg1_find_frame_end(ParseContext1 *pc, const uint8_t *buf, int buf_size) |
|
182 |
+{ |
|
183 |
+ int i; |
|
184 |
+ uint32_t state; |
|
185 |
+ |
|
186 |
+ state= pc->state; |
|
187 |
+ |
|
188 |
+ i=0; |
|
189 |
+ if(!pc->frame_start_found){ |
|
190 |
+ for(i=0; i<buf_size; i++){ |
|
191 |
+ state= (state<<8) | buf[i]; |
|
192 |
+ if(state >= SLICE_MIN_START_CODE && state <= SLICE_MAX_START_CODE){ |
|
193 |
+ i++; |
|
194 |
+ pc->frame_start_found=1; |
|
195 |
+ break; |
|
196 |
+ } |
|
197 |
+ } |
|
198 |
+ } |
|
199 |
+ |
|
200 |
+ if(pc->frame_start_found){ |
|
201 |
+ for(; i<buf_size; i++){ |
|
202 |
+ state= (state<<8) | buf[i]; |
|
203 |
+ if((state&0xFFFFFF00) == 0x100){ |
|
204 |
+ if(state < SLICE_MIN_START_CODE || state > SLICE_MAX_START_CODE){ |
|
205 |
+ pc->frame_start_found=0; |
|
206 |
+ pc->state=-1; |
|
207 |
+ return i-3; |
|
208 |
+ } |
|
209 |
+ } |
|
210 |
+ } |
|
211 |
+ } |
|
212 |
+ pc->state= state; |
|
213 |
+ return END_NOT_FOUND; |
|
214 |
+} |
|
215 |
+ |
|
216 |
+static int find_start_code(const uint8_t **pbuf_ptr, const uint8_t *buf_end) |
|
217 |
+{ |
|
218 |
+ const uint8_t *buf_ptr; |
|
219 |
+ unsigned int state=0xFFFFFFFF, v; |
|
220 |
+ int val; |
|
221 |
+ |
|
222 |
+ buf_ptr = *pbuf_ptr; |
|
223 |
+ while (buf_ptr < buf_end) { |
|
224 |
+ v = *buf_ptr++; |
|
225 |
+ if (state == 0x000001) { |
|
226 |
+ state = ((state << 8) | v) & 0xffffff; |
|
227 |
+ val = state; |
|
228 |
+ goto found; |
|
229 |
+ } |
|
230 |
+ state = ((state << 8) | v) & 0xffffff; |
|
231 |
+ } |
|
232 |
+ val = -1; |
|
233 |
+ found: |
|
234 |
+ *pbuf_ptr = buf_ptr; |
|
235 |
+ return val; |
|
236 |
+} |
|
237 |
+ |
|
238 |
+/* XXX: merge with libavcodec ? */ |
|
239 |
+#define MPEG1_FRAME_RATE_BASE 1001 |
|
240 |
+ |
|
241 |
+static const int frame_rate_tab[16] = { |
|
242 |
+ 0, |
|
243 |
+ 24000, |
|
244 |
+ 24024, |
|
245 |
+ 25025, |
|
246 |
+ 30000, |
|
247 |
+ 30030, |
|
248 |
+ 50050, |
|
249 |
+ 60000, |
|
250 |
+ 60060, |
|
251 |
+ // Xing's 15fps: (9) |
|
252 |
+ 15015, |
|
253 |
+ // libmpeg3's "Unofficial economy rates": (10-13) |
|
254 |
+ 5005, |
|
255 |
+ 10010, |
|
256 |
+ 12012, |
|
257 |
+ 15015, |
|
258 |
+ // random, just to avoid segfault !never encode these |
|
259 |
+ 25025, |
|
260 |
+ 25025, |
|
261 |
+}; |
|
262 |
+ |
|
263 |
+static void mpegvideo_extract_headers(AVCodecParserContext *s, |
|
264 |
+ AVCodecContext *avctx, |
|
265 |
+ const uint8_t *buf, int buf_size) |
|
266 |
+{ |
|
267 |
+ ParseContext1 *pc = s->priv_data; |
|
268 |
+ const uint8_t *buf_end; |
|
269 |
+ int32_t start_code; |
|
270 |
+ int frame_rate_index, ext_type, bytes_left; |
|
271 |
+ int frame_rate_ext_n, frame_rate_ext_d; |
|
272 |
+ int top_field_first, repeat_first_field, progressive_frame; |
|
273 |
+ int horiz_size_ext, vert_size_ext; |
|
274 |
+ |
|
275 |
+ s->repeat_pict = 0; |
|
276 |
+ buf_end = buf + buf_size; |
|
277 |
+ while (buf < buf_end) { |
|
278 |
+ start_code = find_start_code(&buf, buf_end); |
|
279 |
+ bytes_left = buf_end - buf; |
|
280 |
+ switch(start_code) { |
|
281 |
+ case PICTURE_START_CODE: |
|
282 |
+ if (bytes_left >= 2) { |
|
283 |
+ s->pict_type = (buf[1] >> 3) & 7; |
|
284 |
+ } |
|
285 |
+ break; |
|
286 |
+ case SEQ_START_CODE: |
|
287 |
+ if (bytes_left >= 4) { |
|
288 |
+ pc->width = avctx->width = (buf[0] << 4) | (buf[1] >> 4); |
|
289 |
+ pc->height = avctx->height = ((buf[1] & 0x0f) << 8) | buf[2]; |
|
290 |
+ frame_rate_index = buf[3] & 0xf; |
|
291 |
+ pc->frame_rate = avctx->frame_rate = frame_rate_tab[frame_rate_index]; |
|
292 |
+ avctx->frame_rate_base = MPEG1_FRAME_RATE_BASE; |
|
293 |
+ } |
|
294 |
+ break; |
|
295 |
+ case EXT_START_CODE: |
|
296 |
+ if (bytes_left >= 1) { |
|
297 |
+ ext_type = (buf[0] >> 4); |
|
298 |
+ switch(ext_type) { |
|
299 |
+ case 0x1: /* sequence extension */ |
|
300 |
+ if (bytes_left >= 6) { |
|
301 |
+ horiz_size_ext = ((buf[1] & 1) << 1) | (buf[2] >> 7); |
|
302 |
+ vert_size_ext = (buf[2] >> 5) & 3; |
|
303 |
+ frame_rate_ext_n = (buf[5] >> 5) & 3; |
|
304 |
+ frame_rate_ext_d = (buf[5] & 0x1f); |
|
305 |
+ pc->progressive_sequence = buf[1] & (1 << 3); |
|
306 |
+ |
|
307 |
+ avctx->width = pc->width | (horiz_size_ext << 12); |
|
308 |
+ avctx->height = pc->height | (vert_size_ext << 12); |
|
309 |
+ avctx->frame_rate = pc->frame_rate * (frame_rate_ext_n + 1); |
|
310 |
+ avctx->frame_rate_base = MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d + 1); |
|
311 |
+ avctx->sub_id = 2; /* forces MPEG2 */ |
|
312 |
+ } |
|
313 |
+ break; |
|
314 |
+ case 0x8: /* picture coding extension */ |
|
315 |
+ if (bytes_left >= 5) { |
|
316 |
+ top_field_first = buf[3] & (1 << 7); |
|
317 |
+ repeat_first_field = buf[3] & (1 << 1); |
|
318 |
+ progressive_frame = buf[4] & (1 << 7); |
|
319 |
+ |
|
320 |
+ /* check if we must repeat the frame */ |
|
321 |
+ if (repeat_first_field) { |
|
322 |
+ if (pc->progressive_sequence) { |
|
323 |
+ if (top_field_first) |
|
324 |
+ s->repeat_pict = 4; |
|
325 |
+ else |
|
326 |
+ s->repeat_pict = 2; |
|
327 |
+ } else if (progressive_frame) { |
|
328 |
+ s->repeat_pict = 1; |
|
329 |
+ } |
|
330 |
+ } |
|
331 |
+ } |
|
332 |
+ break; |
|
333 |
+ } |
|
334 |
+ } |
|
335 |
+ break; |
|
336 |
+ case -1: |
|
337 |
+ goto the_end; |
|
338 |
+ default: |
|
339 |
+ /* we stop parsing when we encounter a slice. It ensures |
|
340 |
+ that this function takes a negligible amount of time */ |
|
341 |
+ if (start_code >= SLICE_MIN_START_CODE && |
|
342 |
+ start_code <= SLICE_MAX_START_CODE) |
|
343 |
+ goto the_end; |
|
344 |
+ break; |
|
345 |
+ } |
|
346 |
+ } |
|
347 |
+ the_end: ; |
|
348 |
+} |
|
349 |
+ |
|
350 |
+static int mpegvideo_parse(AVCodecParserContext *s, |
|
351 |
+ AVCodecContext *avctx, |
|
352 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
353 |
+ const uint8_t *buf, int buf_size) |
|
354 |
+{ |
|
355 |
+ ParseContext1 *pc = s->priv_data; |
|
356 |
+ int next; |
|
357 |
+ |
|
358 |
+ next= mpeg1_find_frame_end(pc, buf, buf_size); |
|
359 |
+ |
|
360 |
+ if (ff_combine_frame1(pc, next, (uint8_t **)&buf, &buf_size) < 0) { |
|
361 |
+ *poutbuf = NULL; |
|
362 |
+ *poutbuf_size = 0; |
|
363 |
+ return buf_size; |
|
364 |
+ } |
|
365 |
+ /* we have a full frame : we just parse the first few MPEG headers |
|
366 |
+ to have the full timing information. The time take by this |
|
367 |
+ function should be negligible for uncorrupted streams */ |
|
368 |
+ mpegvideo_extract_headers(s, avctx, buf, buf_size); |
|
369 |
+#if 0 |
|
370 |
+ printf("pict_type=%d frame_rate=%0.3f repeat_pict=%d\n", |
|
371 |
+ s->pict_type, (double)avctx->frame_rate / avctx->frame_rate_base, s->repeat_pict); |
|
372 |
+#endif |
|
373 |
+ |
|
374 |
+ *poutbuf = (uint8_t *)buf; |
|
375 |
+ *poutbuf_size = buf_size; |
|
376 |
+ return next; |
|
377 |
+} |
|
378 |
+ |
|
379 |
+static void mpegvideo_parse_close(AVCodecParserContext *s) |
|
380 |
+{ |
|
381 |
+ ParseContext1 *pc = s->priv_data; |
|
382 |
+ |
|
383 |
+ av_free(pc->buffer); |
|
384 |
+ av_free(pc->enc); |
|
385 |
+} |
|
386 |
+ |
|
387 |
+/*************************/ |
|
388 |
+ |
|
389 |
+/** |
|
390 |
+ * finds the end of the current frame in the bitstream. |
|
391 |
+ * @return the position of the first byte of the next frame, or -1 |
|
392 |
+ */ |
|
393 |
+static int mpeg4_find_frame_end(ParseContext1 *pc, |
|
394 |
+ const uint8_t *buf, int buf_size) |
|
395 |
+{ |
|
396 |
+ int vop_found, i; |
|
397 |
+ uint32_t state; |
|
398 |
+ |
|
399 |
+ vop_found= pc->frame_start_found; |
|
400 |
+ state= pc->state; |
|
401 |
+ |
|
402 |
+ i=0; |
|
403 |
+ if(!vop_found){ |
|
404 |
+ for(i=0; i<buf_size; i++){ |
|
405 |
+ state= (state<<8) | buf[i]; |
|
406 |
+ if(state == 0x1B6){ |
|
407 |
+ i++; |
|
408 |
+ vop_found=1; |
|
409 |
+ break; |
|
410 |
+ } |
|
411 |
+ } |
|
412 |
+ } |
|
413 |
+ |
|
414 |
+ if(vop_found){ |
|
415 |
+ for(; i<buf_size; i++){ |
|
416 |
+ state= (state<<8) | buf[i]; |
|
417 |
+ if((state&0xFFFFFF00) == 0x100){ |
|
418 |
+ pc->frame_start_found=0; |
|
419 |
+ pc->state=-1; |
|
420 |
+ return i-3; |
|
421 |
+ } |
|
422 |
+ } |
|
423 |
+ } |
|
424 |
+ pc->frame_start_found= vop_found; |
|
425 |
+ pc->state= state; |
|
426 |
+ return END_NOT_FOUND; |
|
427 |
+} |
|
428 |
+ |
|
429 |
+/* used by parser */ |
|
430 |
+/* XXX: make it use less memory */ |
|
431 |
+static int av_mpeg4_decode_header(AVCodecParserContext *s1, |
|
432 |
+ AVCodecContext *avctx, |
|
433 |
+ const uint8_t *buf, int buf_size) |
|
434 |
+{ |
|
435 |
+ ParseContext1 *pc = s1->priv_data; |
|
436 |
+ MpegEncContext *s = pc->enc; |
|
437 |
+ GetBitContext gb1, *gb = &gb1; |
|
438 |
+ int ret; |
|
439 |
+ |
|
440 |
+ s->avctx = avctx; |
|
441 |
+ init_get_bits(gb, buf, 8 * buf_size); |
|
442 |
+ ret = ff_mpeg4_decode_picture_header(s, gb); |
|
443 |
+ if (s->width) { |
|
444 |
+ avctx->width = s->width; |
|
445 |
+ avctx->height = s->height; |
|
446 |
+ } |
|
447 |
+ return ret; |
|
448 |
+} |
|
449 |
+ |
|
450 |
+int mpeg4video_parse_init(AVCodecParserContext *s) |
|
451 |
+{ |
|
452 |
+ ParseContext1 *pc = s->priv_data; |
|
453 |
+ pc->enc = av_mallocz(sizeof(MpegEncContext)); |
|
454 |
+ if (!pc->enc) |
|
455 |
+ return -1; |
|
456 |
+ return 0; |
|
457 |
+} |
|
458 |
+ |
|
459 |
+static int mpeg4video_parse(AVCodecParserContext *s, |
|
460 |
+ AVCodecContext *avctx, |
|
461 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
462 |
+ const uint8_t *buf, int buf_size) |
|
463 |
+{ |
|
464 |
+ ParseContext1 *pc = s->priv_data; |
|
465 |
+ int next; |
|
466 |
+ |
|
467 |
+ next= mpeg4_find_frame_end(pc, buf, buf_size); |
|
468 |
+ |
|
469 |
+ if (ff_combine_frame1(pc, next, (uint8_t **)&buf, &buf_size) < 0) { |
|
470 |
+ *poutbuf = NULL; |
|
471 |
+ *poutbuf_size = 0; |
|
472 |
+ return buf_size; |
|
473 |
+ } |
|
474 |
+ av_mpeg4_decode_header(s, avctx, buf, buf_size); |
|
475 |
+ |
|
476 |
+ *poutbuf = (uint8_t *)buf; |
|
477 |
+ *poutbuf_size = buf_size; |
|
478 |
+ return next; |
|
479 |
+} |
|
480 |
+ |
|
481 |
+/*************************/ |
|
482 |
+ |
|
483 |
+static int h263_find_frame_end(ParseContext1 *pc, const uint8_t *buf, int buf_size) |
|
484 |
+{ |
|
485 |
+ int vop_found, i; |
|
486 |
+ uint32_t state; |
|
487 |
+ |
|
488 |
+ vop_found= pc->frame_start_found; |
|
489 |
+ state= pc->state; |
|
490 |
+ |
|
491 |
+ i=0; |
|
492 |
+ if(!vop_found){ |
|
493 |
+ for(i=0; i<buf_size; i++){ |
|
494 |
+ state= (state<<8) | buf[i]; |
|
495 |
+ if(state>>(32-22) == 0x20){ |
|
496 |
+ i++; |
|
497 |
+ vop_found=1; |
|
498 |
+ break; |
|
499 |
+ } |
|
500 |
+ } |
|
501 |
+ } |
|
502 |
+ |
|
503 |
+ if(vop_found){ |
|
504 |
+ for(; i<buf_size; i++){ |
|
505 |
+ state= (state<<8) | buf[i]; |
|
506 |
+ if(state>>(32-22) == 0x20){ |
|
507 |
+ pc->frame_start_found=0; |
|
508 |
+ pc->state=-1; |
|
509 |
+ return i-3; |
|
510 |
+ } |
|
511 |
+ } |
|
512 |
+ } |
|
513 |
+ pc->frame_start_found= vop_found; |
|
514 |
+ pc->state= state; |
|
515 |
+ |
|
516 |
+ return END_NOT_FOUND; |
|
517 |
+} |
|
518 |
+ |
|
519 |
+static int h263_parse(AVCodecParserContext *s, |
|
520 |
+ AVCodecContext *avctx, |
|
521 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
522 |
+ const uint8_t *buf, int buf_size) |
|
523 |
+{ |
|
524 |
+ ParseContext1 *pc = s->priv_data; |
|
525 |
+ int next; |
|
526 |
+ |
|
527 |
+ next= h263_find_frame_end(pc, buf, buf_size); |
|
528 |
+ |
|
529 |
+ if (ff_combine_frame1(pc, next, (uint8_t **)&buf, &buf_size) < 0) { |
|
530 |
+ *poutbuf = NULL; |
|
531 |
+ *poutbuf_size = 0; |
|
532 |
+ return buf_size; |
|
533 |
+ } |
|
534 |
+ |
|
535 |
+ *poutbuf = (uint8_t *)buf; |
|
536 |
+ *poutbuf_size = buf_size; |
|
537 |
+ return next; |
|
538 |
+} |
|
539 |
+ |
|
540 |
+/*************************/ |
|
541 |
+ |
|
542 |
+/** |
|
543 |
+ * finds the end of the current frame in the bitstream. |
|
544 |
+ * @return the position of the first byte of the next frame, or -1 |
|
545 |
+ */ |
|
546 |
+static int h264_find_frame_end(ParseContext1 *pc, const uint8_t *buf, int buf_size) |
|
547 |
+{ |
|
548 |
+ int i; |
|
549 |
+ uint32_t state; |
|
550 |
+//printf("first %02X%02X%02X%02X\n", buf[0], buf[1],buf[2],buf[3]); |
|
551 |
+// mb_addr= pc->mb_addr - 1; |
|
552 |
+ state= pc->state; |
|
553 |
+ //FIXME this will fail with slices |
|
554 |
+ for(i=0; i<buf_size; i++){ |
|
555 |
+ state= (state<<8) | buf[i]; |
|
556 |
+ if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){ |
|
557 |
+ if(pc->frame_start_found){ |
|
558 |
+ pc->state=-1; |
|
559 |
+ pc->frame_start_found= 0; |
|
560 |
+ return i-3; |
|
561 |
+ } |
|
562 |
+ pc->frame_start_found= 1; |
|
563 |
+ } |
|
564 |
+ } |
|
565 |
+ |
|
566 |
+ pc->state= state; |
|
567 |
+ return END_NOT_FOUND; |
|
568 |
+} |
|
569 |
+ |
|
570 |
+static int h264_parse(AVCodecParserContext *s, |
|
571 |
+ AVCodecContext *avctx, |
|
572 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
573 |
+ const uint8_t *buf, int buf_size) |
|
574 |
+{ |
|
575 |
+ ParseContext1 *pc = s->priv_data; |
|
576 |
+ int next; |
|
577 |
+ |
|
578 |
+ next= h264_find_frame_end(pc, buf, buf_size); |
|
579 |
+ |
|
580 |
+ if (ff_combine_frame1(pc, next, (uint8_t **)&buf, &buf_size) < 0) { |
|
581 |
+ *poutbuf = NULL; |
|
582 |
+ *poutbuf_size = 0; |
|
583 |
+ return buf_size; |
|
584 |
+ } |
|
585 |
+ |
|
586 |
+ *poutbuf = (uint8_t *)buf; |
|
587 |
+ *poutbuf_size = buf_size; |
|
588 |
+ return next; |
|
589 |
+} |
|
590 |
+ |
|
591 |
+/*************************/ |
|
592 |
+ |
|
593 |
+typedef struct MpegAudioParseContext { |
|
594 |
+ uint8_t inbuf[MPA_MAX_CODED_FRAME_SIZE]; /* input buffer */ |
|
595 |
+ uint8_t *inbuf_ptr; |
|
596 |
+ int frame_size; |
|
597 |
+ int free_format_frame_size; |
|
598 |
+ int free_format_next_header; |
|
599 |
+} MpegAudioParseContext; |
|
600 |
+ |
|
601 |
+#define MPA_HEADER_SIZE 4 |
|
602 |
+ |
|
603 |
+/* header + layer + bitrate + freq + lsf/mpeg25 */ |
|
604 |
+#define SAME_HEADER_MASK \ |
|
605 |
+ (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19)) |
|
606 |
+ |
|
607 |
+static int mpegaudio_parse_init(AVCodecParserContext *s1) |
|
608 |
+{ |
|
609 |
+ MpegAudioParseContext *s = s1->priv_data; |
|
610 |
+ s->inbuf_ptr = s->inbuf; |
|
611 |
+ return 0; |
|
612 |
+} |
|
613 |
+ |
|
614 |
+static int mpegaudio_parse(AVCodecParserContext *s1, |
|
615 |
+ AVCodecContext *avctx, |
|
616 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
617 |
+ const uint8_t *buf, int buf_size) |
|
618 |
+{ |
|
619 |
+ MpegAudioParseContext *s = s1->priv_data; |
|
620 |
+ int len, ret; |
|
621 |
+ uint32_t header; |
|
622 |
+ const uint8_t *buf_ptr; |
|
623 |
+ |
|
624 |
+ *poutbuf = NULL; |
|
625 |
+ *poutbuf_size = 0; |
|
626 |
+ buf_ptr = buf; |
|
627 |
+ while (buf_size > 0) { |
|
628 |
+ len = s->inbuf_ptr - s->inbuf; |
|
629 |
+ if (s->frame_size == 0) { |
|
630 |
+ /* special case for next header for first frame in free |
|
631 |
+ format case (XXX: find a simpler method) */ |
|
632 |
+ if (s->free_format_next_header != 0) { |
|
633 |
+ s->inbuf[0] = s->free_format_next_header >> 24; |
|
634 |
+ s->inbuf[1] = s->free_format_next_header >> 16; |
|
635 |
+ s->inbuf[2] = s->free_format_next_header >> 8; |
|
636 |
+ s->inbuf[3] = s->free_format_next_header; |
|
637 |
+ s->inbuf_ptr = s->inbuf + 4; |
|
638 |
+ s->free_format_next_header = 0; |
|
639 |
+ goto got_header; |
|
640 |
+ } |
|
641 |
+ /* no header seen : find one. We need at least MPA_HEADER_SIZE |
|
642 |
+ bytes to parse it */ |
|
643 |
+ len = MPA_HEADER_SIZE - len; |
|
644 |
+ if (len > buf_size) |
|
645 |
+ len = buf_size; |
|
646 |
+ if (len > 0) { |
|
647 |
+ memcpy(s->inbuf_ptr, buf_ptr, len); |
|
648 |
+ buf_ptr += len; |
|
649 |
+ buf_size -= len; |
|
650 |
+ s->inbuf_ptr += len; |
|
651 |
+ } |
|
652 |
+ if ((s->inbuf_ptr - s->inbuf) >= MPA_HEADER_SIZE) { |
|
653 |
+ got_header: |
|
654 |
+ header = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) | |
|
655 |
+ (s->inbuf[2] << 8) | s->inbuf[3]; |
|
656 |
+ |
|
657 |
+ ret = mpa_decode_header(avctx, header); |
|
658 |
+ if (ret < 0) { |
|
659 |
+ /* no sync found : move by one byte (inefficient, but simple!) */ |
|
660 |
+ memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); |
|
661 |
+ s->inbuf_ptr--; |
|
662 |
+ dprintf("skip %x\n", header); |
|
663 |
+ /* reset free format frame size to give a chance |
|
664 |
+ to get a new bitrate */ |
|
665 |
+ s->free_format_frame_size = 0; |
|
666 |
+ } else { |
|
667 |
+ s->frame_size = ret; |
|
668 |
+#if 0 |
|
669 |
+ /* free format: prepare to compute frame size */ |
|
670 |
+ if (decode_header(s, header) == 1) { |
|
671 |
+ s->frame_size = -1; |
|
672 |
+ } |
|
673 |
+#endif |
|
674 |
+ } |
|
675 |
+ } |
|
676 |
+ } else |
|
677 |
+#if 0 |
|
678 |
+ if (s->frame_size == -1) { |
|
679 |
+ /* free format : find next sync to compute frame size */ |
|
680 |
+ len = MPA_MAX_CODED_FRAME_SIZE - len; |
|
681 |
+ if (len > buf_size) |
|
682 |
+ len = buf_size; |
|
683 |
+ if (len == 0) { |
|
684 |
+ /* frame too long: resync */ |
|
685 |
+ s->frame_size = 0; |
|
686 |
+ memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1); |
|
687 |
+ s->inbuf_ptr--; |
|
688 |
+ } else { |
|
689 |
+ uint8_t *p, *pend; |
|
690 |
+ uint32_t header1; |
|
691 |
+ int padding; |
|
692 |
+ |
|
693 |
+ memcpy(s->inbuf_ptr, buf_ptr, len); |
|
694 |
+ /* check for header */ |
|
695 |
+ p = s->inbuf_ptr - 3; |
|
696 |
+ pend = s->inbuf_ptr + len - 4; |
|
697 |
+ while (p <= pend) { |
|
698 |
+ header = (p[0] << 24) | (p[1] << 16) | |
|
699 |
+ (p[2] << 8) | p[3]; |
|
700 |
+ header1 = (s->inbuf[0] << 24) | (s->inbuf[1] << 16) | |
|
701 |
+ (s->inbuf[2] << 8) | s->inbuf[3]; |
|
702 |
+ /* check with high probability that we have a |
|
703 |
+ valid header */ |
|
704 |
+ if ((header & SAME_HEADER_MASK) == |
|
705 |
+ (header1 & SAME_HEADER_MASK)) { |
|
706 |
+ /* header found: update pointers */ |
|
707 |
+ len = (p + 4) - s->inbuf_ptr; |
|
708 |
+ buf_ptr += len; |
|
709 |
+ buf_size -= len; |
|
710 |
+ s->inbuf_ptr = p; |
|
711 |
+ /* compute frame size */ |
|
712 |
+ s->free_format_next_header = header; |
|
713 |
+ s->free_format_frame_size = s->inbuf_ptr - s->inbuf; |
|
714 |
+ padding = (header1 >> 9) & 1; |
|
715 |
+ if (s->layer == 1) |
|
716 |
+ s->free_format_frame_size -= padding * 4; |
|
717 |
+ else |
|
718 |
+ s->free_format_frame_size -= padding; |
|
719 |
+ dprintf("free frame size=%d padding=%d\n", |
|
720 |
+ s->free_format_frame_size, padding); |
|
721 |
+ decode_header(s, header1); |
|
722 |
+ goto next_data; |
|
723 |
+ } |
|
724 |
+ p++; |
|
725 |
+ } |
|
726 |
+ /* not found: simply increase pointers */ |
|
727 |
+ buf_ptr += len; |
|
728 |
+ s->inbuf_ptr += len; |
|
729 |
+ buf_size -= len; |
|
730 |
+ } |
|
731 |
+ } else |
|
732 |
+#endif |
|
733 |
+ if (len < s->frame_size) { |
|
734 |
+ if (s->frame_size > MPA_MAX_CODED_FRAME_SIZE) |
|
735 |
+ s->frame_size = MPA_MAX_CODED_FRAME_SIZE; |
|
736 |
+ len = s->frame_size - len; |
|
737 |
+ if (len > buf_size) |
|
738 |
+ len = buf_size; |
|
739 |
+ memcpy(s->inbuf_ptr, buf_ptr, len); |
|
740 |
+ buf_ptr += len; |
|
741 |
+ s->inbuf_ptr += len; |
|
742 |
+ buf_size -= len; |
|
743 |
+ } |
|
744 |
+ // next_data: |
|
745 |
+ if (s->frame_size > 0 && |
|
746 |
+ (s->inbuf_ptr - s->inbuf) >= s->frame_size) { |
|
747 |
+ *poutbuf = s->inbuf; |
|
748 |
+ *poutbuf_size = s->inbuf_ptr - s->inbuf; |
|
749 |
+ s->inbuf_ptr = s->inbuf; |
|
750 |
+ s->frame_size = 0; |
|
751 |
+ break; |
|
752 |
+ } |
|
753 |
+ } |
|
754 |
+ return buf_ptr - buf; |
|
755 |
+} |
|
756 |
+ |
|
757 |
+#ifdef CONFIG_AC3 |
|
758 |
+extern int a52_syncinfo (const uint8_t * buf, int * flags, |
|
759 |
+ int * sample_rate, int * bit_rate); |
|
760 |
+ |
|
761 |
+typedef struct AC3ParseContext { |
|
762 |
+ uint8_t inbuf[4096]; /* input buffer */ |
|
763 |
+ uint8_t *inbuf_ptr; |
|
764 |
+ int frame_size; |
|
765 |
+ int flags; |
|
766 |
+} AC3ParseContext; |
|
767 |
+ |
|
768 |
+#define AC3_HEADER_SIZE 7 |
|
769 |
+#define A52_LFE 16 |
|
770 |
+ |
|
771 |
+static int ac3_parse_init(AVCodecParserContext *s1) |
|
772 |
+{ |
|
773 |
+ AC3ParseContext *s = s1->priv_data; |
|
774 |
+ s->inbuf_ptr = s->inbuf; |
|
775 |
+ return 0; |
|
776 |
+} |
|
777 |
+ |
|
778 |
+static int ac3_parse(AVCodecParserContext *s1, |
|
779 |
+ AVCodecContext *avctx, |
|
780 |
+ uint8_t **poutbuf, int *poutbuf_size, |
|
781 |
+ const uint8_t *buf, int buf_size) |
|
782 |
+{ |
|
783 |
+ AC3ParseContext *s = s1->priv_data; |
|
784 |
+ const uint8_t *buf_ptr; |
|
785 |
+ int len, sample_rate, bit_rate; |
|
786 |
+ static const int ac3_channels[8] = { |
|
787 |
+ 2, 1, 2, 3, 3, 4, 4, 5 |
|
788 |
+ }; |
|
789 |
+ |
|
790 |
+ *poutbuf = NULL; |
|
791 |
+ *poutbuf_size = 0; |
|
792 |
+ |
|
793 |
+ buf_ptr = buf; |
|
794 |
+ while (buf_size > 0) { |
|
795 |
+ len = s->inbuf_ptr - s->inbuf; |
|
796 |
+ if (s->frame_size == 0) { |
|
797 |
+ /* no header seen : find one. We need at least 7 bytes to parse it */ |
|
798 |
+ len = AC3_HEADER_SIZE - len; |
|
799 |
+ if (len > buf_size) |
|
800 |
+ len = buf_size; |
|
801 |
+ memcpy(s->inbuf_ptr, buf_ptr, len); |
|
802 |
+ buf_ptr += len; |
|
803 |
+ s->inbuf_ptr += len; |
|
804 |
+ buf_size -= len; |
|
805 |
+ if ((s->inbuf_ptr - s->inbuf) == AC3_HEADER_SIZE) { |
|
806 |
+ len = a52_syncinfo(s->inbuf, &s->flags, &sample_rate, &bit_rate); |
|
807 |
+ if (len == 0) { |
|
808 |
+ /* no sync found : move by one byte (inefficient, but simple!) */ |
|
809 |
+ memmove(s->inbuf, s->inbuf + 1, AC3_HEADER_SIZE - 1); |
|
810 |
+ s->inbuf_ptr--; |
|
811 |
+ } else { |
|
812 |
+ s->frame_size = len; |
|
813 |
+ /* update codec info */ |
|
814 |
+ avctx->sample_rate = sample_rate; |
|
815 |
+ avctx->channels = ac3_channels[s->flags & 7]; |
|
816 |
+ if (s->flags & A52_LFE) |
|
817 |
+ avctx->channels++; |
|
818 |
+ avctx->bit_rate = bit_rate; |
|
819 |
+ avctx->frame_size = 6 * 256; |
|
820 |
+ } |
|
821 |
+ } |
|
822 |
+ } else if (len < s->frame_size) { |
|
823 |
+ len = s->frame_size - len; |
|
824 |
+ if (len > buf_size) |
|
825 |
+ len = buf_size; |
|
826 |
+ |
|
827 |
+ memcpy(s->inbuf_ptr, buf_ptr, len); |
|
828 |
+ buf_ptr += len; |
|
829 |
+ s->inbuf_ptr += len; |
|
830 |
+ buf_size -= len; |
|
831 |
+ } else { |
|
832 |
+ *poutbuf = s->inbuf; |
|
833 |
+ *poutbuf_size = s->frame_size; |
|
834 |
+ s->inbuf_ptr = s->inbuf; |
|
835 |
+ s->frame_size = 0; |
|
836 |
+ break; |
|
837 |
+ } |
|
838 |
+ } |
|
839 |
+ return buf_ptr - buf; |
|
840 |
+} |
|
841 |
+#endif |
|
842 |
+ |
|
843 |
+AVCodecParser mpegvideo_parser = { |
|
844 |
+ { CODEC_ID_MPEG1VIDEO, CODEC_ID_MPEG2VIDEO }, |
|
845 |
+ sizeof(ParseContext1), |
|
846 |
+ NULL, |
|
847 |
+ mpegvideo_parse, |
|
848 |
+ mpegvideo_parse_close, |
|
849 |
+}; |
|
850 |
+ |
|
851 |
+AVCodecParser mpeg4video_parser = { |
|
852 |
+ { CODEC_ID_MPEG4 }, |
|
853 |
+ sizeof(ParseContext1), |
|
854 |
+ mpeg4video_parse_init, |
|
855 |
+ mpeg4video_parse, |
|
856 |
+ mpegvideo_parse_close, |
|
857 |
+}; |
|
858 |
+ |
|
859 |
+AVCodecParser h263_parser = { |
|
860 |
+ { CODEC_ID_H263 }, |
|
861 |
+ sizeof(ParseContext1), |
|
862 |
+ NULL, |
|
863 |
+ h263_parse, |
|
864 |
+ mpegvideo_parse_close, |
|
865 |
+}; |
|
866 |
+ |
|
867 |
+AVCodecParser h264_parser = { |
|
868 |
+ { CODEC_ID_H264 }, |
|
869 |
+ sizeof(ParseContext1), |
|
870 |
+ NULL, |
|
871 |
+ h264_parse, |
|
872 |
+ mpegvideo_parse_close, |
|
873 |
+}; |
|
874 |
+ |
|
875 |
+AVCodecParser mpegaudio_parser = { |
|
876 |
+ { CODEC_ID_MP2, CODEC_ID_MP3 }, |
|
877 |
+ sizeof(MpegAudioParseContext), |
|
878 |
+ mpegaudio_parse_init, |
|
879 |
+ mpegaudio_parse, |
|
880 |
+ NULL, |
|
881 |
+}; |
|
882 |
+ |
|
883 |
+#ifdef CONFIG_AC3 |
|
884 |
+AVCodecParser ac3_parser = { |
|
885 |
+ { CODEC_ID_AC3 }, |
|
886 |
+ sizeof(AC3ParseContext), |
|
887 |
+ ac3_parse_init, |
|
888 |
+ ac3_parse, |
|
889 |
+ NULL, |
|
890 |
+}; |
|
891 |
+#endif |