Mercurial > libavformat.hg
annotate mpeg.c @ 14:b167760cd0aa libavformat
mimetype fixes patch by (Ryutaroh Matsumoto <ryutaroh at it dot ss dot titech dot ac dot jp>)
author | michaelni |
---|---|
date | Fri, 20 Dec 2002 23:10:58 +0000 |
parents | 05318cf2e886 |
children | b892b9f97291 |
rev | line source |
---|---|
0 | 1 /* |
2 * MPEG1/2 mux/demux | |
3 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. | |
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 "avformat.h" | |
20 | |
21 #define MAX_PAYLOAD_SIZE 4096 | |
22 #define NB_STREAMS 2 | |
23 | |
24 typedef struct { | |
25 UINT8 buffer[MAX_PAYLOAD_SIZE]; | |
26 int buffer_ptr; | |
27 UINT8 id; | |
28 int max_buffer_size; /* in bytes */ | |
29 int packet_number; | |
30 INT64 start_pts; | |
31 } StreamInfo; | |
32 | |
33 typedef struct { | |
34 int packet_size; /* required packet size */ | |
35 int packet_data_max_size; /* maximum data size inside a packet */ | |
36 int packet_number; | |
37 int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */ | |
38 int system_header_freq; | |
39 int mux_rate; /* bitrate in units of 50 bytes/s */ | |
40 /* stream info */ | |
41 int audio_bound; | |
42 int video_bound; | |
43 int is_mpeg2; | |
44 int is_vcd; | |
45 } MpegMuxContext; | |
46 | |
47 #define PACK_START_CODE ((unsigned int)0x000001ba) | |
48 #define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb) | |
49 #define SEQUENCE_END_CODE ((unsigned int)0x000001b7) | |
50 #define PACKET_START_CODE_MASK ((unsigned int)0xffffff00) | |
51 #define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100) | |
52 #define ISO_11172_END_CODE ((unsigned int)0x000001b9) | |
53 | |
54 /* mpeg2 */ | |
55 #define PROGRAM_STREAM_MAP 0x1bc | |
56 #define PRIVATE_STREAM_1 0x1bd | |
57 #define PADDING_STREAM 0x1be | |
58 #define PRIVATE_STREAM_2 0x1bf | |
59 | |
60 | |
61 #define AUDIO_ID 0xc0 | |
62 #define VIDEO_ID 0xe0 | |
63 | |
64 extern AVOutputFormat mpeg1system_mux; | |
65 extern AVOutputFormat mpeg1vcd_mux; | |
66 extern AVOutputFormat mpeg2vob_mux; | |
67 | |
68 static int put_pack_header(AVFormatContext *ctx, | |
69 UINT8 *buf, INT64 timestamp) | |
70 { | |
71 MpegMuxContext *s = ctx->priv_data; | |
72 PutBitContext pb; | |
73 | |
74 init_put_bits(&pb, buf, 128, NULL, NULL); | |
75 | |
76 put_bits(&pb, 32, PACK_START_CODE); | |
77 if (s->is_mpeg2) { | |
78 put_bits(&pb, 2, 0x2); | |
79 } else { | |
80 put_bits(&pb, 4, 0x2); | |
81 } | |
82 put_bits(&pb, 3, (UINT32)((timestamp >> 30) & 0x07)); | |
83 put_bits(&pb, 1, 1); | |
84 put_bits(&pb, 15, (UINT32)((timestamp >> 15) & 0x7fff)); | |
85 put_bits(&pb, 1, 1); | |
86 put_bits(&pb, 15, (UINT32)((timestamp) & 0x7fff)); | |
87 put_bits(&pb, 1, 1); | |
88 if (s->is_mpeg2) { | |
89 /* clock extension */ | |
90 put_bits(&pb, 9, 0); | |
91 put_bits(&pb, 1, 1); | |
92 } | |
93 put_bits(&pb, 1, 1); | |
94 put_bits(&pb, 22, s->mux_rate); | |
95 put_bits(&pb, 1, 1); | |
96 if (s->is_mpeg2) { | |
97 put_bits(&pb, 5, 0x1f); /* reserved */ | |
98 put_bits(&pb, 3, 0); /* stuffing length */ | |
99 } | |
100 flush_put_bits(&pb); | |
101 return pbBufPtr(&pb) - pb.buf; | |
102 } | |
103 | |
104 static int put_system_header(AVFormatContext *ctx, UINT8 *buf) | |
105 { | |
106 MpegMuxContext *s = ctx->priv_data; | |
107 int size, rate_bound, i, private_stream_coded, id; | |
108 PutBitContext pb; | |
109 | |
110 init_put_bits(&pb, buf, 128, NULL, NULL); | |
111 | |
112 put_bits(&pb, 32, SYSTEM_HEADER_START_CODE); | |
113 put_bits(&pb, 16, 0); | |
114 put_bits(&pb, 1, 1); | |
115 | |
116 rate_bound = s->mux_rate; /* maximum bit rate of the multiplexed stream */ | |
117 put_bits(&pb, 22, rate_bound); | |
118 put_bits(&pb, 1, 1); /* marker */ | |
119 put_bits(&pb, 6, s->audio_bound); | |
120 | |
121 put_bits(&pb, 1, 1); /* variable bitrate */ | |
122 put_bits(&pb, 1, 1); /* non constrainted bit stream */ | |
123 | |
124 put_bits(&pb, 1, 0); /* audio locked */ | |
125 put_bits(&pb, 1, 0); /* video locked */ | |
126 put_bits(&pb, 1, 1); /* marker */ | |
127 | |
128 put_bits(&pb, 5, s->video_bound); | |
129 put_bits(&pb, 8, 0xff); /* reserved byte */ | |
130 | |
131 /* audio stream info */ | |
132 private_stream_coded = 0; | |
133 for(i=0;i<ctx->nb_streams;i++) { | |
134 StreamInfo *stream = ctx->streams[i]->priv_data; | |
135 id = stream->id; | |
136 if (id < 0xc0) { | |
137 /* special case for private streams (AC3 use that) */ | |
138 if (private_stream_coded) | |
139 continue; | |
140 private_stream_coded = 1; | |
141 id = 0xbd; | |
142 } | |
143 put_bits(&pb, 8, id); /* stream ID */ | |
144 put_bits(&pb, 2, 3); | |
145 if (id < 0xe0) { | |
146 /* audio */ | |
147 put_bits(&pb, 1, 0); | |
148 put_bits(&pb, 13, stream->max_buffer_size / 128); | |
149 } else { | |
150 /* video */ | |
151 put_bits(&pb, 1, 1); | |
152 put_bits(&pb, 13, stream->max_buffer_size / 1024); | |
153 } | |
154 } | |
155 flush_put_bits(&pb); | |
156 size = pbBufPtr(&pb) - pb.buf; | |
157 /* patch packet size */ | |
158 buf[4] = (size - 6) >> 8; | |
159 buf[5] = (size - 6) & 0xff; | |
160 | |
161 return size; | |
162 } | |
163 | |
164 static int mpeg_mux_init(AVFormatContext *ctx) | |
165 { | |
166 MpegMuxContext *s = ctx->priv_data; | |
167 int bitrate, i, mpa_id, mpv_id, ac3_id; | |
168 AVStream *st; | |
169 StreamInfo *stream; | |
170 | |
171 s->packet_number = 0; | |
172 s->is_vcd = (ctx->oformat == &mpeg1vcd_mux); | |
173 s->is_mpeg2 = (ctx->oformat == &mpeg2vob_mux); | |
174 | |
175 if (s->is_vcd) | |
176 s->packet_size = 2324; /* VCD packet size */ | |
177 else | |
178 s->packet_size = 2048; | |
179 | |
180 /* startcode(4) + length(2) + flags(1) */ | |
181 s->packet_data_max_size = s->packet_size - 7; | |
182 s->audio_bound = 0; | |
183 s->video_bound = 0; | |
184 mpa_id = AUDIO_ID; | |
185 ac3_id = 0x80; | |
186 mpv_id = VIDEO_ID; | |
187 for(i=0;i<ctx->nb_streams;i++) { | |
188 st = ctx->streams[i]; | |
189 stream = av_mallocz(sizeof(StreamInfo)); | |
190 if (!stream) | |
191 goto fail; | |
192 st->priv_data = stream; | |
193 | |
194 switch(st->codec.codec_type) { | |
195 case CODEC_TYPE_AUDIO: | |
196 if (st->codec.codec_id == CODEC_ID_AC3) | |
197 stream->id = ac3_id++; | |
198 else | |
199 stream->id = mpa_id++; | |
200 stream->max_buffer_size = 4 * 1024; | |
201 s->audio_bound++; | |
202 break; | |
203 case CODEC_TYPE_VIDEO: | |
204 stream->id = mpv_id++; | |
205 stream->max_buffer_size = 46 * 1024; | |
206 s->video_bound++; | |
207 break; | |
208 default: | |
209 av_abort(); | |
210 } | |
211 } | |
212 | |
213 /* we increase slightly the bitrate to take into account the | |
214 headers. XXX: compute it exactly */ | |
215 bitrate = 2000; | |
216 for(i=0;i<ctx->nb_streams;i++) { | |
217 st = ctx->streams[i]; | |
218 bitrate += st->codec.bit_rate; | |
219 } | |
220 s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50); | |
221 | |
222 if (s->is_vcd || s->is_mpeg2) | |
223 /* every packet */ | |
224 s->pack_header_freq = 1; | |
225 else | |
226 /* every 2 seconds */ | |
227 s->pack_header_freq = 2 * bitrate / s->packet_size / 8; | |
228 | |
229 if (s->is_mpeg2) | |
230 /* every 200 packets. Need to look at the spec. */ | |
231 s->system_header_freq = s->pack_header_freq * 40; | |
232 else if (s->is_vcd) | |
233 /* every 40 packets, this is my invention */ | |
234 s->system_header_freq = s->pack_header_freq * 40; | |
235 else | |
236 s->system_header_freq = s->pack_header_freq * 5; | |
237 | |
238 for(i=0;i<ctx->nb_streams;i++) { | |
239 stream = ctx->streams[i]->priv_data; | |
240 stream->buffer_ptr = 0; | |
241 stream->packet_number = 0; | |
242 stream->start_pts = -1; | |
243 } | |
244 return 0; | |
245 fail: | |
246 for(i=0;i<ctx->nb_streams;i++) { | |
247 av_free(ctx->streams[i]->priv_data); | |
248 } | |
249 return -ENOMEM; | |
250 } | |
251 | |
252 /* flush the packet on stream stream_index */ | |
253 static void flush_packet(AVFormatContext *ctx, int stream_index, int last_pkt) | |
254 { | |
255 MpegMuxContext *s = ctx->priv_data; | |
256 StreamInfo *stream = ctx->streams[stream_index]->priv_data; | |
257 UINT8 *buf_ptr; | |
258 int size, payload_size, startcode, id, len, stuffing_size, i, header_len; | |
259 INT64 timestamp; | |
260 UINT8 buffer[128]; | |
261 int last = last_pkt ? 4 : 0; | |
262 | |
263 id = stream->id; | |
264 timestamp = stream->start_pts; | |
265 | |
266 #if 0 | |
267 printf("packet ID=%2x PTS=%0.3f\n", | |
268 id, timestamp / 90000.0); | |
269 #endif | |
270 | |
271 buf_ptr = buffer; | |
272 if (((s->packet_number % s->pack_header_freq) == 0)) { | |
273 /* output pack and systems header if needed */ | |
274 size = put_pack_header(ctx, buf_ptr, timestamp); | |
275 buf_ptr += size; | |
276 if ((s->packet_number % s->system_header_freq) == 0) { | |
277 size = put_system_header(ctx, buf_ptr); | |
278 buf_ptr += size; | |
279 } | |
280 } | |
281 size = buf_ptr - buffer; | |
282 put_buffer(&ctx->pb, buffer, size); | |
283 | |
284 /* packet header */ | |
285 if (s->is_mpeg2) { | |
286 header_len = 8; | |
287 } else { | |
288 header_len = 5; | |
289 } | |
290 payload_size = s->packet_size - (size + 6 + header_len + last); | |
291 if (id < 0xc0) { | |
292 startcode = PRIVATE_STREAM_1; | |
293 payload_size -= 4; | |
294 } else { | |
295 startcode = 0x100 + id; | |
296 } | |
297 stuffing_size = payload_size - stream->buffer_ptr; | |
298 if (stuffing_size < 0) | |
299 stuffing_size = 0; | |
300 | |
301 put_be32(&ctx->pb, startcode); | |
302 | |
303 put_be16(&ctx->pb, payload_size + header_len); | |
304 /* stuffing */ | |
305 for(i=0;i<stuffing_size;i++) | |
306 put_byte(&ctx->pb, 0xff); | |
307 | |
308 if (s->is_mpeg2) { | |
309 put_byte(&ctx->pb, 0x80); /* mpeg2 id */ | |
310 put_byte(&ctx->pb, 0x80); /* flags */ | |
311 put_byte(&ctx->pb, 0x05); /* header len (only pts is included) */ | |
312 } | |
313 put_byte(&ctx->pb, | |
314 (0x02 << 4) | | |
315 (((timestamp >> 30) & 0x07) << 1) | | |
316 1); | |
317 put_be16(&ctx->pb, (UINT16)((((timestamp >> 15) & 0x7fff) << 1) | 1)); | |
318 put_be16(&ctx->pb, (UINT16)((((timestamp) & 0x7fff) << 1) | 1)); | |
319 | |
320 if (startcode == PRIVATE_STREAM_1) { | |
321 put_byte(&ctx->pb, id); | |
322 if (id >= 0x80 && id <= 0xbf) { | |
323 /* XXX: need to check AC3 spec */ | |
324 put_byte(&ctx->pb, 1); | |
325 put_byte(&ctx->pb, 0); | |
326 put_byte(&ctx->pb, 2); | |
327 } | |
328 } | |
329 | |
330 if (last_pkt) { | |
331 put_be32(&ctx->pb, ISO_11172_END_CODE); | |
332 } | |
333 /* output data */ | |
334 put_buffer(&ctx->pb, stream->buffer, payload_size - stuffing_size); | |
335 put_flush_packet(&ctx->pb); | |
336 | |
337 /* preserve remaining data */ | |
338 len = stream->buffer_ptr - payload_size; | |
339 if (len < 0) | |
340 len = 0; | |
341 memmove(stream->buffer, stream->buffer + stream->buffer_ptr - len, len); | |
342 stream->buffer_ptr = len; | |
343 | |
344 s->packet_number++; | |
345 stream->packet_number++; | |
346 stream->start_pts = -1; | |
347 } | |
348 | |
349 static int mpeg_mux_write_packet(AVFormatContext *ctx, int stream_index, | |
350 UINT8 *buf, int size, int pts) | |
351 { | |
352 MpegMuxContext *s = ctx->priv_data; | |
353 AVStream *st = ctx->streams[stream_index]; | |
354 StreamInfo *stream = st->priv_data; | |
355 int len; | |
356 | |
357 while (size > 0) { | |
358 /* set pts */ | |
359 if (stream->start_pts == -1) { | |
360 stream->start_pts = pts; | |
361 } | |
362 len = s->packet_data_max_size - stream->buffer_ptr; | |
363 if (len > size) | |
364 len = size; | |
365 memcpy(stream->buffer + stream->buffer_ptr, buf, len); | |
366 stream->buffer_ptr += len; | |
367 buf += len; | |
368 size -= len; | |
369 while (stream->buffer_ptr >= s->packet_data_max_size) { | |
370 /* output the packet */ | |
371 if (stream->start_pts == -1) | |
372 stream->start_pts = pts; | |
373 flush_packet(ctx, stream_index, 0); | |
374 } | |
375 } | |
376 return 0; | |
377 } | |
378 | |
379 static int mpeg_mux_end(AVFormatContext *ctx) | |
380 { | |
381 StreamInfo *stream; | |
382 int i; | |
383 | |
384 /* flush each packet */ | |
385 for(i=0;i<ctx->nb_streams;i++) { | |
386 stream = ctx->streams[i]->priv_data; | |
387 if (stream->buffer_ptr > 0) { | |
388 if (i == (ctx->nb_streams - 1)) | |
389 flush_packet(ctx, i, 1); | |
390 else | |
391 flush_packet(ctx, i, 0); | |
392 } | |
393 } | |
394 | |
395 /* write the end header */ | |
396 //put_be32(&ctx->pb, ISO_11172_END_CODE); | |
397 //put_flush_packet(&ctx->pb); | |
398 return 0; | |
399 } | |
400 | |
401 /*********************************************/ | |
402 /* demux code */ | |
403 | |
404 #define MAX_SYNC_SIZE 100000 | |
405 | |
406 static int mpegps_probe(AVProbeData *p) | |
407 { | |
408 int code, c, i; | |
409 code = 0xff; | |
410 | |
411 /* we search the first start code. If it is a packet start code, | |
412 then we decide it is mpeg ps. We do not send highest value to | |
413 give a chance to mpegts */ | |
414 for(i=0;i<p->buf_size;i++) { | |
415 c = p->buf[i]; | |
416 code = (code << 8) | c; | |
417 if ((code & 0xffffff00) == 0x100) { | |
418 if (code == PACK_START_CODE || | |
419 code == SYSTEM_HEADER_START_CODE || | |
420 (code >= 0x1e0 && code <= 0x1ef) || | |
421 (code >= 0x1c0 && code <= 0x1df) || | |
422 code == PRIVATE_STREAM_2 || | |
423 code == PROGRAM_STREAM_MAP || | |
424 code == PRIVATE_STREAM_1 || | |
425 code == PADDING_STREAM) | |
426 return AVPROBE_SCORE_MAX - 1; | |
427 else | |
428 return 0; | |
429 } | |
430 } | |
431 return 0; | |
432 } | |
433 | |
434 | |
435 typedef struct MpegDemuxContext { | |
436 int header_state; | |
437 } MpegDemuxContext; | |
438 | |
439 static int find_start_code(ByteIOContext *pb, int *size_ptr, | |
440 UINT32 *header_state) | |
441 { | |
442 unsigned int state, v; | |
443 int val, n; | |
444 | |
445 state = *header_state; | |
446 n = *size_ptr; | |
447 while (n > 0) { | |
448 if (url_feof(pb)) | |
449 break; | |
450 v = get_byte(pb); | |
451 n--; | |
452 if (state == 0x000001) { | |
453 state = ((state << 8) | v) & 0xffffff; | |
454 val = state; | |
455 goto found; | |
456 } | |
457 state = ((state << 8) | v) & 0xffffff; | |
458 } | |
459 val = -1; | |
460 found: | |
461 *header_state = state; | |
462 *size_ptr = n; | |
463 return val; | |
464 } | |
465 | |
466 static int mpegps_read_header(AVFormatContext *s, | |
467 AVFormatParameters *ap) | |
468 { | |
469 MpegDemuxContext *m = s->priv_data; | |
470 m->header_state = 0xff; | |
471 /* no need to do more */ | |
472 return 0; | |
473 } | |
474 | |
475 static INT64 get_pts(ByteIOContext *pb, int c) | |
476 { | |
477 INT64 pts; | |
478 int val; | |
479 | |
480 if (c < 0) | |
481 c = get_byte(pb); | |
482 pts = (INT64)((c >> 1) & 0x07) << 30; | |
483 val = get_be16(pb); | |
484 pts |= (INT64)(val >> 1) << 15; | |
485 val = get_be16(pb); | |
486 pts |= (INT64)(val >> 1); | |
487 return pts; | |
488 } | |
489 | |
490 static int mpegps_read_packet(AVFormatContext *s, | |
491 AVPacket *pkt) | |
492 { | |
493 MpegDemuxContext *m = s->priv_data; | |
494 AVStream *st; | |
495 int len, size, startcode, i, c, flags, header_len, type, codec_id; | |
496 INT64 pts, dts; | |
497 | |
498 /* next start code (should be immediately after) */ | |
499 redo: | |
500 m->header_state = 0xff; | |
501 size = MAX_SYNC_SIZE; | |
502 startcode = find_start_code(&s->pb, &size, &m->header_state); | |
503 //printf("startcode=%x pos=0x%Lx\n", startcode, url_ftell(&s->pb)); | |
504 if (startcode < 0) | |
505 return -EIO; | |
506 if (startcode == PACK_START_CODE) | |
507 goto redo; | |
508 if (startcode == SYSTEM_HEADER_START_CODE) | |
509 goto redo; | |
510 if (startcode == PADDING_STREAM || | |
511 startcode == PRIVATE_STREAM_2) { | |
512 /* skip them */ | |
513 len = get_be16(&s->pb); | |
514 url_fskip(&s->pb, len); | |
515 goto redo; | |
516 } | |
517 /* find matching stream */ | |
518 if (!((startcode >= 0x1c0 && startcode <= 0x1df) || | |
519 (startcode >= 0x1e0 && startcode <= 0x1ef) || | |
520 (startcode == 0x1bd))) | |
521 goto redo; | |
522 | |
523 len = get_be16(&s->pb); | |
524 pts = AV_NOPTS_VALUE; | |
525 dts = AV_NOPTS_VALUE; | |
526 /* stuffing */ | |
527 for(;;) { | |
528 c = get_byte(&s->pb); | |
529 len--; | |
530 /* XXX: for mpeg1, should test only bit 7 */ | |
531 if (c != 0xff) | |
532 break; | |
533 } | |
534 if ((c & 0xc0) == 0x40) { | |
535 /* buffer scale & size */ | |
536 get_byte(&s->pb); | |
537 c = get_byte(&s->pb); | |
538 len -= 2; | |
539 } | |
540 if ((c & 0xf0) == 0x20) { | |
541 pts = get_pts(&s->pb, c); | |
542 len -= 4; | |
543 } else if ((c & 0xf0) == 0x30) { | |
544 pts = get_pts(&s->pb, c); | |
545 dts = get_pts(&s->pb, -1); | |
546 len -= 9; | |
547 } else if ((c & 0xc0) == 0x80) { | |
548 /* mpeg 2 PES */ | |
549 if ((c & 0x30) != 0) { | |
550 fprintf(stderr, "Encrypted multiplex not handled\n"); | |
551 return -EIO; | |
552 } | |
553 flags = get_byte(&s->pb); | |
554 header_len = get_byte(&s->pb); | |
555 len -= 2; | |
556 if (header_len > len) | |
557 goto redo; | |
558 if ((flags & 0xc0) == 0x80) { | |
559 pts = get_pts(&s->pb, -1); | |
560 header_len -= 5; | |
561 len -= 5; | |
562 } if ((flags & 0xc0) == 0xc0) { | |
563 pts = get_pts(&s->pb, -1); | |
564 dts = get_pts(&s->pb, -1); | |
565 header_len -= 10; | |
566 len -= 10; | |
567 } | |
568 len -= header_len; | |
569 while (header_len > 0) { | |
570 get_byte(&s->pb); | |
571 header_len--; | |
572 } | |
573 } | |
574 if (startcode == 0x1bd) { | |
575 startcode = get_byte(&s->pb); | |
576 len--; | |
577 if (startcode >= 0x80 && startcode <= 0xbf) { | |
578 /* audio: skip header */ | |
579 get_byte(&s->pb); | |
580 get_byte(&s->pb); | |
581 get_byte(&s->pb); | |
582 len -= 3; | |
583 } | |
584 } | |
585 | |
586 /* now find stream */ | |
587 for(i=0;i<s->nb_streams;i++) { | |
588 st = s->streams[i]; | |
589 if (st->id == startcode) | |
590 goto found; | |
591 } | |
592 if (startcode >= 0x1e0 && startcode <= 0x1ef) { | |
593 type = CODEC_TYPE_VIDEO; | |
594 codec_id = CODEC_ID_MPEG1VIDEO; | |
595 } else if (startcode >= 0x1c0 && startcode <= 0x1df) { | |
596 type = CODEC_TYPE_AUDIO; | |
597 codec_id = CODEC_ID_MP2; | |
598 } else if (startcode >= 0x80 && startcode <= 0x9f) { | |
599 type = CODEC_TYPE_AUDIO; | |
600 codec_id = CODEC_ID_AC3; | |
601 } else { | |
602 skip: | |
603 /* skip packet */ | |
604 url_fskip(&s->pb, len); | |
605 goto redo; | |
606 } | |
607 /* no stream found: add a new stream */ | |
608 st = av_new_stream(s, startcode); | |
609 if (!st) | |
610 goto skip; | |
611 st->codec.codec_type = type; | |
612 st->codec.codec_id = codec_id; | |
613 found: | |
614 av_new_packet(pkt, len); | |
615 //printf("\nRead Packet ID: %x PTS: %f Size: %d", startcode, | |
616 // (float)pts/90000, len); | |
617 get_buffer(&s->pb, pkt->data, pkt->size); | |
618 pkt->pts = pts; | |
619 pkt->stream_index = st->index; | |
620 return 0; | |
621 } | |
622 | |
623 static int mpegps_read_close(AVFormatContext *s) | |
624 { | |
625 return 0; | |
626 } | |
627 | |
628 static AVOutputFormat mpeg1system_mux = { | |
629 "mpeg", | |
630 "MPEG1 System format", | |
14
b167760cd0aa
mimetype fixes patch by (Ryutaroh Matsumoto <ryutaroh at it dot ss dot titech dot ac dot jp>)
michaelni
parents:
0
diff
changeset
|
631 "video/mpeg", |
0 | 632 "mpg,mpeg", |
633 sizeof(MpegMuxContext), | |
634 CODEC_ID_MP2, | |
635 CODEC_ID_MPEG1VIDEO, | |
636 mpeg_mux_init, | |
637 mpeg_mux_write_packet, | |
638 mpeg_mux_end, | |
639 }; | |
640 | |
641 static AVOutputFormat mpeg1vcd_mux = { | |
642 "vcd", | |
643 "MPEG1 System format (VCD)", | |
14
b167760cd0aa
mimetype fixes patch by (Ryutaroh Matsumoto <ryutaroh at it dot ss dot titech dot ac dot jp>)
michaelni
parents:
0
diff
changeset
|
644 "video/mpeg", |
0 | 645 NULL, |
646 sizeof(MpegMuxContext), | |
647 CODEC_ID_MP2, | |
648 CODEC_ID_MPEG1VIDEO, | |
649 mpeg_mux_init, | |
650 mpeg_mux_write_packet, | |
651 mpeg_mux_end, | |
652 }; | |
653 | |
654 static AVOutputFormat mpeg2vob_mux = { | |
655 "vob", | |
656 "MPEG2 PS format (VOB)", | |
14
b167760cd0aa
mimetype fixes patch by (Ryutaroh Matsumoto <ryutaroh at it dot ss dot titech dot ac dot jp>)
michaelni
parents:
0
diff
changeset
|
657 "video/mpeg", |
0 | 658 "vob", |
659 sizeof(MpegMuxContext), | |
660 CODEC_ID_MP2, | |
661 CODEC_ID_MPEG1VIDEO, | |
662 mpeg_mux_init, | |
663 mpeg_mux_write_packet, | |
664 mpeg_mux_end, | |
665 }; | |
666 | |
667 static AVInputFormat mpegps_demux = { | |
668 "mpeg", | |
669 "MPEG PS format", | |
670 sizeof(MpegDemuxContext), | |
671 mpegps_probe, | |
672 mpegps_read_header, | |
673 mpegps_read_packet, | |
674 mpegps_read_close, | |
675 .flags = AVFMT_NOHEADER, | |
676 }; | |
677 | |
678 int mpegps_init(void) | |
679 { | |
680 av_register_output_format(&mpeg1system_mux); | |
681 av_register_output_format(&mpeg1vcd_mux); | |
682 av_register_output_format(&mpeg2vob_mux); | |
683 av_register_input_format(&mpegps_demux); | |
684 return 0; | |
685 } |