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