Mercurial > libavformat.hg
annotate mpeg.c @ 319:6285d395baf4 libavformat
fixed memory leak
author | bellard |
---|---|
date | Thu, 20 Nov 2003 11:22:25 +0000 |
parents | 944c8edaf609 |
children | 4530681af424 |
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 | |
310 | 23 //#define DEBUG_SEEK |
0 | 24 |
25 typedef struct { | |
65 | 26 uint8_t buffer[MAX_PAYLOAD_SIZE]; |
0 | 27 int buffer_ptr; |
65 | 28 uint8_t id; |
0 | 29 int max_buffer_size; /* in bytes */ |
30 int packet_number; | |
65 | 31 int64_t start_pts; |
0 | 32 } StreamInfo; |
33 | |
34 typedef struct { | |
35 int packet_size; /* required packet size */ | |
36 int packet_data_max_size; /* maximum data size inside a packet */ | |
37 int packet_number; | |
38 int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */ | |
39 int system_header_freq; | |
40 int mux_rate; /* bitrate in units of 50 bytes/s */ | |
41 /* stream info */ | |
42 int audio_bound; | |
43 int video_bound; | |
44 int is_mpeg2; | |
45 int is_vcd; | |
46 } MpegMuxContext; | |
47 | |
48 #define PACK_START_CODE ((unsigned int)0x000001ba) | |
49 #define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb) | |
50 #define SEQUENCE_END_CODE ((unsigned int)0x000001b7) | |
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 | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
65 #ifdef CONFIG_ENCODERS |
0 | 66 extern AVOutputFormat mpeg1system_mux; |
67 extern AVOutputFormat mpeg1vcd_mux; | |
68 extern AVOutputFormat mpeg2vob_mux; | |
69 | |
70 static int put_pack_header(AVFormatContext *ctx, | |
65 | 71 uint8_t *buf, int64_t timestamp) |
0 | 72 { |
73 MpegMuxContext *s = ctx->priv_data; | |
74 PutBitContext pb; | |
75 | |
276 | 76 init_put_bits(&pb, buf, 128); |
0 | 77 |
78 put_bits(&pb, 32, PACK_START_CODE); | |
79 if (s->is_mpeg2) { | |
174
7d56e9f83fdb
Write correct MPEG2-PS streams patch by (mru at users dot sourceforge dot net (Mns Rullgrd))
michaelni
parents:
165
diff
changeset
|
80 put_bits(&pb, 2, 0x1); |
0 | 81 } else { |
82 put_bits(&pb, 4, 0x2); | |
83 } | |
65 | 84 put_bits(&pb, 3, (uint32_t)((timestamp >> 30) & 0x07)); |
0 | 85 put_bits(&pb, 1, 1); |
65 | 86 put_bits(&pb, 15, (uint32_t)((timestamp >> 15) & 0x7fff)); |
0 | 87 put_bits(&pb, 1, 1); |
65 | 88 put_bits(&pb, 15, (uint32_t)((timestamp) & 0x7fff)); |
0 | 89 put_bits(&pb, 1, 1); |
90 if (s->is_mpeg2) { | |
91 /* clock extension */ | |
92 put_bits(&pb, 9, 0); | |
93 put_bits(&pb, 1, 1); | |
94 } | |
95 put_bits(&pb, 1, 1); | |
96 put_bits(&pb, 22, s->mux_rate); | |
97 put_bits(&pb, 1, 1); | |
98 if (s->is_mpeg2) { | |
99 put_bits(&pb, 5, 0x1f); /* reserved */ | |
100 put_bits(&pb, 3, 0); /* stuffing length */ | |
101 } | |
102 flush_put_bits(&pb); | |
103 return pbBufPtr(&pb) - pb.buf; | |
104 } | |
105 | |
65 | 106 static int put_system_header(AVFormatContext *ctx, uint8_t *buf) |
0 | 107 { |
108 MpegMuxContext *s = ctx->priv_data; | |
109 int size, rate_bound, i, private_stream_coded, id; | |
110 PutBitContext pb; | |
111 | |
276 | 112 init_put_bits(&pb, buf, 128); |
0 | 113 |
114 put_bits(&pb, 32, SYSTEM_HEADER_START_CODE); | |
115 put_bits(&pb, 16, 0); | |
116 put_bits(&pb, 1, 1); | |
117 | |
118 rate_bound = s->mux_rate; /* maximum bit rate of the multiplexed stream */ | |
119 put_bits(&pb, 22, rate_bound); | |
120 put_bits(&pb, 1, 1); /* marker */ | |
121 put_bits(&pb, 6, s->audio_bound); | |
122 | |
123 put_bits(&pb, 1, 1); /* variable bitrate */ | |
124 put_bits(&pb, 1, 1); /* non constrainted bit stream */ | |
125 | |
126 put_bits(&pb, 1, 0); /* audio locked */ | |
127 put_bits(&pb, 1, 0); /* video locked */ | |
128 put_bits(&pb, 1, 1); /* marker */ | |
129 | |
130 put_bits(&pb, 5, s->video_bound); | |
131 put_bits(&pb, 8, 0xff); /* reserved byte */ | |
132 | |
133 /* audio stream info */ | |
134 private_stream_coded = 0; | |
135 for(i=0;i<ctx->nb_streams;i++) { | |
136 StreamInfo *stream = ctx->streams[i]->priv_data; | |
137 id = stream->id; | |
138 if (id < 0xc0) { | |
139 /* special case for private streams (AC3 use that) */ | |
140 if (private_stream_coded) | |
141 continue; | |
142 private_stream_coded = 1; | |
143 id = 0xbd; | |
144 } | |
145 put_bits(&pb, 8, id); /* stream ID */ | |
146 put_bits(&pb, 2, 3); | |
147 if (id < 0xe0) { | |
148 /* audio */ | |
149 put_bits(&pb, 1, 0); | |
150 put_bits(&pb, 13, stream->max_buffer_size / 128); | |
151 } else { | |
152 /* video */ | |
153 put_bits(&pb, 1, 1); | |
154 put_bits(&pb, 13, stream->max_buffer_size / 1024); | |
155 } | |
156 } | |
157 flush_put_bits(&pb); | |
158 size = pbBufPtr(&pb) - pb.buf; | |
159 /* patch packet size */ | |
160 buf[4] = (size - 6) >> 8; | |
161 buf[5] = (size - 6) & 0xff; | |
162 | |
163 return size; | |
164 } | |
165 | |
166 static int mpeg_mux_init(AVFormatContext *ctx) | |
167 { | |
168 MpegMuxContext *s = ctx->priv_data; | |
169 int bitrate, i, mpa_id, mpv_id, ac3_id; | |
170 AVStream *st; | |
171 StreamInfo *stream; | |
172 | |
173 s->packet_number = 0; | |
174 s->is_vcd = (ctx->oformat == &mpeg1vcd_mux); | |
175 s->is_mpeg2 = (ctx->oformat == &mpeg2vob_mux); | |
176 | |
177 if (s->is_vcd) | |
178 s->packet_size = 2324; /* VCD packet size */ | |
179 else | |
180 s->packet_size = 2048; | |
181 | |
182 /* startcode(4) + length(2) + flags(1) */ | |
183 s->packet_data_max_size = s->packet_size - 7; | |
184 s->audio_bound = 0; | |
185 s->video_bound = 0; | |
186 mpa_id = AUDIO_ID; | |
187 ac3_id = 0x80; | |
188 mpv_id = VIDEO_ID; | |
189 for(i=0;i<ctx->nb_streams;i++) { | |
190 st = ctx->streams[i]; | |
191 stream = av_mallocz(sizeof(StreamInfo)); | |
192 if (!stream) | |
193 goto fail; | |
194 st->priv_data = stream; | |
195 | |
196 switch(st->codec.codec_type) { | |
197 case CODEC_TYPE_AUDIO: | |
198 if (st->codec.codec_id == CODEC_ID_AC3) | |
199 stream->id = ac3_id++; | |
200 else | |
201 stream->id = mpa_id++; | |
202 stream->max_buffer_size = 4 * 1024; | |
203 s->audio_bound++; | |
204 break; | |
205 case CODEC_TYPE_VIDEO: | |
206 stream->id = mpv_id++; | |
207 stream->max_buffer_size = 46 * 1024; | |
208 s->video_bound++; | |
209 break; | |
210 default: | |
211 av_abort(); | |
212 } | |
213 } | |
214 | |
215 /* we increase slightly the bitrate to take into account the | |
216 headers. XXX: compute it exactly */ | |
217 bitrate = 2000; | |
218 for(i=0;i<ctx->nb_streams;i++) { | |
219 st = ctx->streams[i]; | |
220 bitrate += st->codec.bit_rate; | |
221 } | |
222 s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50); | |
223 | |
224 if (s->is_vcd || s->is_mpeg2) | |
225 /* every packet */ | |
226 s->pack_header_freq = 1; | |
227 else | |
228 /* every 2 seconds */ | |
229 s->pack_header_freq = 2 * bitrate / s->packet_size / 8; | |
291
b19f70a6d60f
1/0 fix by (Tim Allen <tim at proximity dot com dot au>)
michael
parents:
277
diff
changeset
|
230 |
b19f70a6d60f
1/0 fix by (Tim Allen <tim at proximity dot com dot au>)
michael
parents:
277
diff
changeset
|
231 /* the above seems to make pack_header_freq zero sometimes */ |
b19f70a6d60f
1/0 fix by (Tim Allen <tim at proximity dot com dot au>)
michael
parents:
277
diff
changeset
|
232 if (s->pack_header_freq == 0) |
b19f70a6d60f
1/0 fix by (Tim Allen <tim at proximity dot com dot au>)
michael
parents:
277
diff
changeset
|
233 s->pack_header_freq = 1; |
0 | 234 |
235 if (s->is_mpeg2) | |
236 /* every 200 packets. Need to look at the spec. */ | |
237 s->system_header_freq = s->pack_header_freq * 40; | |
238 else if (s->is_vcd) | |
239 /* every 40 packets, this is my invention */ | |
240 s->system_header_freq = s->pack_header_freq * 40; | |
241 else | |
242 s->system_header_freq = s->pack_header_freq * 5; | |
243 | |
244 for(i=0;i<ctx->nb_streams;i++) { | |
245 stream = ctx->streams[i]->priv_data; | |
246 stream->buffer_ptr = 0; | |
247 stream->packet_number = 0; | |
248 stream->start_pts = -1; | |
249 } | |
250 return 0; | |
251 fail: | |
252 for(i=0;i<ctx->nb_streams;i++) { | |
253 av_free(ctx->streams[i]->priv_data); | |
254 } | |
255 return -ENOMEM; | |
256 } | |
257 | |
258 /* flush the packet on stream stream_index */ | |
242 | 259 static void flush_packet(AVFormatContext *ctx, int stream_index) |
0 | 260 { |
261 MpegMuxContext *s = ctx->priv_data; | |
262 StreamInfo *stream = ctx->streams[stream_index]->priv_data; | |
65 | 263 uint8_t *buf_ptr; |
0 | 264 int size, payload_size, startcode, id, len, stuffing_size, i, header_len; |
65 | 265 int64_t timestamp; |
266 uint8_t buffer[128]; | |
0 | 267 |
268 id = stream->id; | |
269 timestamp = stream->start_pts; | |
270 | |
271 #if 0 | |
272 printf("packet ID=%2x PTS=%0.3f\n", | |
273 id, timestamp / 90000.0); | |
274 #endif | |
275 | |
276 buf_ptr = buffer; | |
277 if (((s->packet_number % s->pack_header_freq) == 0)) { | |
278 /* output pack and systems header if needed */ | |
279 size = put_pack_header(ctx, buf_ptr, timestamp); | |
280 buf_ptr += size; | |
281 if ((s->packet_number % s->system_header_freq) == 0) { | |
282 size = put_system_header(ctx, buf_ptr); | |
283 buf_ptr += size; | |
284 } | |
285 } | |
286 size = buf_ptr - buffer; | |
287 put_buffer(&ctx->pb, buffer, size); | |
288 | |
289 /* packet header */ | |
290 if (s->is_mpeg2) { | |
291 header_len = 8; | |
292 } else { | |
293 header_len = 5; | |
294 } | |
242 | 295 payload_size = s->packet_size - (size + 6 + header_len); |
0 | 296 if (id < 0xc0) { |
297 startcode = PRIVATE_STREAM_1; | |
298 payload_size -= 4; | |
299 } else { | |
300 startcode = 0x100 + id; | |
301 } | |
302 stuffing_size = payload_size - stream->buffer_ptr; | |
303 if (stuffing_size < 0) | |
304 stuffing_size = 0; | |
305 | |
306 put_be32(&ctx->pb, startcode); | |
307 | |
308 put_be16(&ctx->pb, payload_size + header_len); | |
309 /* stuffing */ | |
310 for(i=0;i<stuffing_size;i++) | |
311 put_byte(&ctx->pb, 0xff); | |
312 | |
313 if (s->is_mpeg2) { | |
314 put_byte(&ctx->pb, 0x80); /* mpeg2 id */ | |
315 put_byte(&ctx->pb, 0x80); /* flags */ | |
316 put_byte(&ctx->pb, 0x05); /* header len (only pts is included) */ | |
317 } | |
318 put_byte(&ctx->pb, | |
319 (0x02 << 4) | | |
320 (((timestamp >> 30) & 0x07) << 1) | | |
321 1); | |
65 | 322 put_be16(&ctx->pb, (uint16_t)((((timestamp >> 15) & 0x7fff) << 1) | 1)); |
323 put_be16(&ctx->pb, (uint16_t)((((timestamp) & 0x7fff) << 1) | 1)); | |
0 | 324 |
325 if (startcode == PRIVATE_STREAM_1) { | |
326 put_byte(&ctx->pb, id); | |
327 if (id >= 0x80 && id <= 0xbf) { | |
328 /* XXX: need to check AC3 spec */ | |
329 put_byte(&ctx->pb, 1); | |
330 put_byte(&ctx->pb, 0); | |
331 put_byte(&ctx->pb, 2); | |
332 } | |
333 } | |
334 | |
335 /* output data */ | |
336 put_buffer(&ctx->pb, stream->buffer, payload_size - stuffing_size); | |
337 put_flush_packet(&ctx->pb); | |
338 | |
339 /* preserve remaining data */ | |
340 len = stream->buffer_ptr - payload_size; | |
341 if (len < 0) | |
342 len = 0; | |
343 memmove(stream->buffer, stream->buffer + stream->buffer_ptr - len, len); | |
344 stream->buffer_ptr = len; | |
345 | |
346 s->packet_number++; | |
347 stream->packet_number++; | |
348 stream->start_pts = -1; | |
349 } | |
350 | |
351 static int mpeg_mux_write_packet(AVFormatContext *ctx, int stream_index, | |
241 | 352 const uint8_t *buf, int size, int64_t pts) |
0 | 353 { |
354 MpegMuxContext *s = ctx->priv_data; | |
355 AVStream *st = ctx->streams[stream_index]; | |
356 StreamInfo *stream = st->priv_data; | |
357 int len; | |
358 | |
359 while (size > 0) { | |
360 /* set pts */ | |
361 if (stream->start_pts == -1) { | |
362 stream->start_pts = pts; | |
363 } | |
364 len = s->packet_data_max_size - stream->buffer_ptr; | |
365 if (len > size) | |
366 len = size; | |
367 memcpy(stream->buffer + stream->buffer_ptr, buf, len); | |
368 stream->buffer_ptr += len; | |
369 buf += len; | |
370 size -= len; | |
371 while (stream->buffer_ptr >= s->packet_data_max_size) { | |
372 /* output the packet */ | |
373 if (stream->start_pts == -1) | |
374 stream->start_pts = pts; | |
242 | 375 flush_packet(ctx, stream_index); |
0 | 376 } |
377 } | |
378 return 0; | |
379 } | |
380 | |
381 static int mpeg_mux_end(AVFormatContext *ctx) | |
382 { | |
383 StreamInfo *stream; | |
384 int i; | |
385 | |
386 /* flush each packet */ | |
387 for(i=0;i<ctx->nb_streams;i++) { | |
388 stream = ctx->streams[i]->priv_data; | |
389 if (stream->buffer_ptr > 0) { | |
242 | 390 flush_packet(ctx, i); |
0 | 391 } |
392 } | |
393 | |
242 | 394 /* End header according to MPEG1 systems standard. We do not write |
395 it as it is usually not needed by decoders and because it | |
396 complicates MPEG stream concatenation. */ | |
0 | 397 //put_be32(&ctx->pb, ISO_11172_END_CODE); |
398 //put_flush_packet(&ctx->pb); | |
237
35231c0be8e5
memleak fix by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michaelni
parents:
210
diff
changeset
|
399 |
35231c0be8e5
memleak fix by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michaelni
parents:
210
diff
changeset
|
400 for(i=0;i<ctx->nb_streams;i++) |
35231c0be8e5
memleak fix by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michaelni
parents:
210
diff
changeset
|
401 av_freep(&ctx->streams[i]->priv_data); |
35231c0be8e5
memleak fix by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michaelni
parents:
210
diff
changeset
|
402 |
0 | 403 return 0; |
404 } | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
405 #endif //CONFIG_ENCODERS |
0 | 406 |
407 /*********************************************/ | |
408 /* demux code */ | |
409 | |
410 #define MAX_SYNC_SIZE 100000 | |
411 | |
412 static int mpegps_probe(AVProbeData *p) | |
413 { | |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
414 int code, c, i; |
0 | 415 |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
416 code = 0xff; |
0 | 417 /* we search the first start code. If it is a packet start code, |
418 then we decide it is mpeg ps. We do not send highest value to | |
419 give a chance to mpegts */ | |
49 | 420 /* NOTE: the search range was restricted to avoid too many false |
421 detections */ | |
422 | |
423 if (p->buf_size < 6) | |
424 return 0; | |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
425 |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
426 for (i = 0; i < 20; i++) { |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
427 c = p->buf[i]; |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
428 code = (code << 8) | c; |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
429 if ((code & 0xffffff00) == 0x100) { |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
430 if (code == PACK_START_CODE || |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
431 code == SYSTEM_HEADER_START_CODE || |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
432 (code >= 0x1e0 && code <= 0x1ef) || |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
433 (code >= 0x1c0 && code <= 0x1df) || |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
434 code == PRIVATE_STREAM_2 || |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
435 code == PROGRAM_STREAM_MAP || |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
436 code == PRIVATE_STREAM_1 || |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
437 code == PADDING_STREAM) |
210 | 438 return AVPROBE_SCORE_MAX - 2; |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
439 else |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
440 return 0; |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
441 } |
0 | 442 } |
443 return 0; | |
444 } | |
445 | |
446 | |
447 typedef struct MpegDemuxContext { | |
448 int header_state; | |
449 } MpegDemuxContext; | |
450 | |
310 | 451 static int mpegps_read_header(AVFormatContext *s, |
452 AVFormatParameters *ap) | |
453 { | |
454 MpegDemuxContext *m = s->priv_data; | |
455 m->header_state = 0xff; | |
456 s->ctx_flags |= AVFMTCTX_NOHEADER; | |
457 | |
458 /* no need to do more */ | |
459 return 0; | |
460 } | |
461 | |
462 static int64_t get_pts(ByteIOContext *pb, int c) | |
463 { | |
464 int64_t pts; | |
465 int val; | |
466 | |
467 if (c < 0) | |
468 c = get_byte(pb); | |
469 pts = (int64_t)((c >> 1) & 0x07) << 30; | |
470 val = get_be16(pb); | |
471 pts |= (int64_t)(val >> 1) << 15; | |
472 val = get_be16(pb); | |
473 pts |= (int64_t)(val >> 1); | |
474 return pts; | |
475 } | |
476 | |
477 static int find_next_start_code(ByteIOContext *pb, int *size_ptr, | |
478 uint32_t *header_state) | |
0 | 479 { |
480 unsigned int state, v; | |
481 int val, n; | |
482 | |
483 state = *header_state; | |
484 n = *size_ptr; | |
485 while (n > 0) { | |
486 if (url_feof(pb)) | |
487 break; | |
488 v = get_byte(pb); | |
489 n--; | |
490 if (state == 0x000001) { | |
491 state = ((state << 8) | v) & 0xffffff; | |
492 val = state; | |
493 goto found; | |
494 } | |
495 state = ((state << 8) | v) & 0xffffff; | |
496 } | |
497 val = -1; | |
498 found: | |
499 *header_state = state; | |
500 *size_ptr = n; | |
501 return val; | |
502 } | |
503 | |
310 | 504 /* XXX: optimize */ |
505 static int find_prev_start_code(ByteIOContext *pb, int *size_ptr) | |
0 | 506 { |
310 | 507 int64_t pos, pos_start; |
508 int max_size, start_code; | |
509 | |
510 max_size = *size_ptr; | |
511 pos_start = url_ftell(pb); | |
512 | |
513 /* in order to go faster, we fill the buffer */ | |
514 pos = pos_start - 16386; | |
515 if (pos < 0) | |
516 pos = 0; | |
517 url_fseek(pb, pos, SEEK_SET); | |
518 get_byte(pb); | |
293
62cec412a186
make AVFMT_NOHEADER flag dynamic - added av_open_input_stream()
bellard
parents:
291
diff
changeset
|
519 |
310 | 520 pos = pos_start; |
521 for(;;) { | |
522 pos--; | |
523 if (pos < 0 || (pos_start - pos) >= max_size) { | |
524 start_code = -1; | |
525 goto the_end; | |
526 } | |
527 url_fseek(pb, pos, SEEK_SET); | |
528 start_code = get_be32(pb); | |
529 if ((start_code & 0xffffff00) == 0x100) | |
530 break; | |
531 } | |
532 the_end: | |
533 *size_ptr = pos_start - pos; | |
534 return start_code; | |
0 | 535 } |
536 | |
310 | 537 /* read the next (or previous) PES header. Return its position in ppos |
538 (if not NULL), and its start code, pts and dts. | |
539 */ | |
540 static int mpegps_read_pes_header(AVFormatContext *s, | |
541 int64_t *ppos, int *pstart_code, | |
542 int64_t *ppts, int64_t *pdts, int find_next) | |
0 | 543 { |
544 MpegDemuxContext *m = s->priv_data; | |
310 | 545 int len, size, startcode, c, flags, header_len; |
546 int64_t pts, dts, last_pos; | |
0 | 547 |
310 | 548 last_pos = -1; |
0 | 549 redo: |
310 | 550 if (find_next) { |
551 /* next start code (should be immediately after) */ | |
552 m->header_state = 0xff; | |
553 size = MAX_SYNC_SIZE; | |
554 startcode = find_next_start_code(&s->pb, &size, &m->header_state); | |
555 } else { | |
556 if (last_pos >= 0) | |
557 url_fseek(&s->pb, last_pos, SEEK_SET); | |
558 size = MAX_SYNC_SIZE; | |
559 startcode = find_prev_start_code(&s->pb, &size); | |
560 last_pos = url_ftell(&s->pb) - 4; | |
561 } | |
0 | 562 //printf("startcode=%x pos=0x%Lx\n", startcode, url_ftell(&s->pb)); |
563 if (startcode < 0) | |
564 return -EIO; | |
565 if (startcode == PACK_START_CODE) | |
566 goto redo; | |
567 if (startcode == SYSTEM_HEADER_START_CODE) | |
568 goto redo; | |
569 if (startcode == PADDING_STREAM || | |
570 startcode == PRIVATE_STREAM_2) { | |
571 /* skip them */ | |
572 len = get_be16(&s->pb); | |
573 url_fskip(&s->pb, len); | |
574 goto redo; | |
575 } | |
576 /* find matching stream */ | |
577 if (!((startcode >= 0x1c0 && startcode <= 0x1df) || | |
578 (startcode >= 0x1e0 && startcode <= 0x1ef) || | |
579 (startcode == 0x1bd))) | |
580 goto redo; | |
310 | 581 if (ppos) { |
582 *ppos = url_ftell(&s->pb) - 4; | |
583 } | |
0 | 584 len = get_be16(&s->pb); |
585 pts = AV_NOPTS_VALUE; | |
586 dts = AV_NOPTS_VALUE; | |
587 /* stuffing */ | |
588 for(;;) { | |
310 | 589 if (len < 1) |
590 goto redo; | |
0 | 591 c = get_byte(&s->pb); |
592 len--; | |
593 /* XXX: for mpeg1, should test only bit 7 */ | |
594 if (c != 0xff) | |
595 break; | |
596 } | |
597 if ((c & 0xc0) == 0x40) { | |
598 /* buffer scale & size */ | |
310 | 599 if (len < 2) |
600 goto redo; | |
0 | 601 get_byte(&s->pb); |
602 c = get_byte(&s->pb); | |
603 len -= 2; | |
604 } | |
605 if ((c & 0xf0) == 0x20) { | |
310 | 606 if (len < 4) |
607 goto redo; | |
608 dts = pts = get_pts(&s->pb, c); | |
0 | 609 len -= 4; |
610 } else if ((c & 0xf0) == 0x30) { | |
310 | 611 if (len < 9) |
612 goto redo; | |
0 | 613 pts = get_pts(&s->pb, c); |
614 dts = get_pts(&s->pb, -1); | |
615 len -= 9; | |
616 } else if ((c & 0xc0) == 0x80) { | |
617 /* mpeg 2 PES */ | |
618 if ((c & 0x30) != 0) { | |
310 | 619 /* Encrypted multiplex not handled */ |
620 goto redo; | |
0 | 621 } |
622 flags = get_byte(&s->pb); | |
623 header_len = get_byte(&s->pb); | |
624 len -= 2; | |
625 if (header_len > len) | |
626 goto redo; | |
627 if ((flags & 0xc0) == 0x80) { | |
310 | 628 dts = pts = get_pts(&s->pb, -1); |
629 if (header_len < 5) | |
630 goto redo; | |
0 | 631 header_len -= 5; |
632 len -= 5; | |
633 } if ((flags & 0xc0) == 0xc0) { | |
634 pts = get_pts(&s->pb, -1); | |
635 dts = get_pts(&s->pb, -1); | |
310 | 636 if (header_len < 10) |
637 goto redo; | |
0 | 638 header_len -= 10; |
639 len -= 10; | |
640 } | |
641 len -= header_len; | |
642 while (header_len > 0) { | |
643 get_byte(&s->pb); | |
644 header_len--; | |
645 } | |
646 } | |
647 if (startcode == 0x1bd) { | |
310 | 648 if (len < 1) |
649 goto redo; | |
0 | 650 startcode = get_byte(&s->pb); |
651 len--; | |
652 if (startcode >= 0x80 && startcode <= 0xbf) { | |
653 /* audio: skip header */ | |
310 | 654 if (len < 3) |
655 goto redo; | |
0 | 656 get_byte(&s->pb); |
657 get_byte(&s->pb); | |
658 get_byte(&s->pb); | |
659 len -= 3; | |
660 } | |
661 } | |
310 | 662 *pstart_code = startcode; |
663 *ppts = pts; | |
664 *pdts = dts; | |
665 return len; | |
666 } | |
667 | |
668 static int mpegps_read_packet(AVFormatContext *s, | |
669 AVPacket *pkt) | |
670 { | |
671 AVStream *st; | |
672 int len, startcode, i, type, codec_id; | |
673 int64_t pts, dts; | |
674 | |
675 redo: | |
676 len = mpegps_read_pes_header(s, NULL, &startcode, &pts, &dts, 1); | |
677 if (len < 0) | |
678 return len; | |
0 | 679 |
680 /* now find stream */ | |
681 for(i=0;i<s->nb_streams;i++) { | |
682 st = s->streams[i]; | |
683 if (st->id == startcode) | |
684 goto found; | |
685 } | |
686 if (startcode >= 0x1e0 && startcode <= 0x1ef) { | |
687 type = CODEC_TYPE_VIDEO; | |
688 codec_id = CODEC_ID_MPEG1VIDEO; | |
689 } else if (startcode >= 0x1c0 && startcode <= 0x1df) { | |
690 type = CODEC_TYPE_AUDIO; | |
691 codec_id = CODEC_ID_MP2; | |
692 } else if (startcode >= 0x80 && startcode <= 0x9f) { | |
693 type = CODEC_TYPE_AUDIO; | |
694 codec_id = CODEC_ID_AC3; | |
41 | 695 } else if (startcode >= 0xa0 && startcode <= 0xbf) { |
696 type = CODEC_TYPE_AUDIO; | |
697 codec_id = CODEC_ID_PCM_S16BE; | |
0 | 698 } else { |
699 skip: | |
700 /* skip packet */ | |
701 url_fskip(&s->pb, len); | |
702 goto redo; | |
703 } | |
704 /* no stream found: add a new stream */ | |
705 st = av_new_stream(s, startcode); | |
706 if (!st) | |
707 goto skip; | |
708 st->codec.codec_type = type; | |
709 st->codec.codec_id = codec_id; | |
310 | 710 if (codec_id != CODEC_ID_PCM_S16BE) |
711 st->need_parsing = 1; | |
0 | 712 found: |
41 | 713 if (startcode >= 0xa0 && startcode <= 0xbf) { |
714 int b1, freq; | |
715 static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 }; | |
716 | |
717 /* for LPCM, we just skip the header and consider it is raw | |
718 audio data */ | |
719 if (len <= 3) | |
720 goto skip; | |
721 get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */ | |
722 b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */ | |
723 get_byte(&s->pb); /* dynamic range control (0x80 = off) */ | |
724 len -= 3; | |
725 freq = (b1 >> 4) & 3; | |
726 st->codec.sample_rate = lpcm_freq_tab[freq]; | |
727 st->codec.channels = 1 + (b1 & 7); | |
728 st->codec.bit_rate = st->codec.channels * st->codec.sample_rate * 2; | |
729 } | |
0 | 730 av_new_packet(pkt, len); |
731 //printf("\nRead Packet ID: %x PTS: %f Size: %d", startcode, | |
732 // (float)pts/90000, len); | |
733 get_buffer(&s->pb, pkt->data, pkt->size); | |
734 pkt->pts = pts; | |
310 | 735 pkt->dts = dts; |
0 | 736 pkt->stream_index = st->index; |
737 return 0; | |
738 } | |
739 | |
740 static int mpegps_read_close(AVFormatContext *s) | |
741 { | |
742 return 0; | |
743 } | |
744 | |
310 | 745 static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, |
746 int64_t *ppos, int find_next) | |
747 { | |
748 int len, startcode; | |
749 int64_t pos, pts, dts; | |
750 | |
751 pos = *ppos; | |
752 #ifdef DEBUG_SEEK | |
753 printf("read_dts: pos=0x%llx next=%d -> ", pos, find_next); | |
754 #endif | |
755 url_fseek(&s->pb, pos, SEEK_SET); | |
756 for(;;) { | |
757 len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts, find_next); | |
758 if (len < 0) { | |
759 #ifdef DEBUG_SEEK | |
760 printf("none (ret=%d)\n", len); | |
761 #endif | |
762 return AV_NOPTS_VALUE; | |
763 } | |
764 if (startcode == s->streams[stream_index]->id && | |
765 dts != AV_NOPTS_VALUE) { | |
766 break; | |
767 } | |
768 if (find_next) { | |
769 url_fskip(&s->pb, len); | |
770 } else { | |
771 url_fseek(&s->pb, pos, SEEK_SET); | |
772 } | |
773 } | |
774 #ifdef DEBUG_SEEK | |
775 printf("pos=0x%llx dts=0x%llx %0.3f\n", pos, dts, dts / 90000.0); | |
776 #endif | |
777 *ppos = pos; | |
778 return dts; | |
779 } | |
780 | |
781 static int find_stream_index(AVFormatContext *s) | |
782 { | |
783 int i; | |
784 AVStream *st; | |
785 | |
786 if (s->nb_streams <= 0) | |
787 return -1; | |
788 for(i = 0; i < s->nb_streams; i++) { | |
789 st = s->streams[i]; | |
790 if (st->codec.codec_type == CODEC_TYPE_VIDEO) { | |
791 return i; | |
792 } | |
793 } | |
794 return 0; | |
795 } | |
796 | |
797 static int mpegps_read_seek(AVFormatContext *s, | |
798 int stream_index, int64_t timestamp) | |
799 { | |
800 int64_t pos_min, pos_max, pos; | |
801 int64_t dts_min, dts_max, dts; | |
802 | |
803 timestamp = (timestamp * 90000) / AV_TIME_BASE; | |
804 | |
805 #ifdef DEBUG_SEEK | |
806 printf("read_seek: %d %0.3f\n", stream_index, timestamp / 90000.0); | |
807 #endif | |
808 | |
809 /* XXX: find stream_index by looking at the first PES packet found */ | |
810 if (stream_index < 0) { | |
811 stream_index = find_stream_index(s); | |
812 if (stream_index < 0) | |
813 return -1; | |
814 } | |
815 pos_min = 0; | |
816 dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1); | |
817 if (dts_min == AV_NOPTS_VALUE) { | |
818 /* we can reach this case only if no PTS are present in | |
819 the whole stream */ | |
820 return -1; | |
821 } | |
822 pos_max = url_filesize(url_fileno(&s->pb)) - 1; | |
823 dts_max = mpegps_read_dts(s, stream_index, &pos_max, 0); | |
824 | |
825 while (pos_min <= pos_max) { | |
826 #ifdef DEBUG_SEEK | |
827 printf("pos_min=0x%llx pos_max=0x%llx dts_min=%0.3f dts_max=%0.3f\n", | |
828 pos_min, pos_max, | |
829 dts_min / 90000.0, dts_max / 90000.0); | |
830 #endif | |
831 if (timestamp <= dts_min) { | |
832 pos = pos_min; | |
833 goto found; | |
834 } else if (timestamp >= dts_max) { | |
835 pos = pos_max; | |
836 goto found; | |
837 } else { | |
838 /* interpolate position (better than dichotomy) */ | |
839 pos = (int64_t)((double)(pos_max - pos_min) * | |
840 (double)(timestamp - dts_min) / | |
841 (double)(dts_max - dts_min)) + pos_min; | |
842 } | |
843 #ifdef DEBUG_SEEK | |
844 printf("pos=0x%llx\n", pos); | |
845 #endif | |
846 /* read the next timestamp */ | |
847 dts = mpegps_read_dts(s, stream_index, &pos, 1); | |
848 /* check if we are lucky */ | |
849 if (dts == AV_NOPTS_VALUE) { | |
850 /* should never happen */ | |
851 pos = pos_min; | |
852 goto found; | |
853 } else if (timestamp == dts) { | |
854 goto found; | |
855 } else if (timestamp < dts) { | |
856 pos_max = pos; | |
857 dts_max = mpegps_read_dts(s, stream_index, &pos_max, 0); | |
858 if (dts_max == AV_NOPTS_VALUE) { | |
859 /* should never happen */ | |
860 break; | |
861 } else if (timestamp >= dts_max) { | |
862 pos = pos_max; | |
863 goto found; | |
864 } | |
865 } else { | |
866 pos_min = pos + 1; | |
867 dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1); | |
868 if (dts_min == AV_NOPTS_VALUE) { | |
869 /* should never happen */ | |
870 goto found; | |
871 } else if (timestamp <= dts_min) { | |
872 goto found; | |
873 } | |
874 } | |
875 } | |
876 pos = pos_min; | |
877 found: | |
878 #ifdef DEBUG_SEEK | |
879 pos_min = pos; | |
880 dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1); | |
881 pos_min++; | |
882 dts_max = mpegps_read_dts(s, stream_index, &pos_min, 1); | |
883 printf("pos=0x%llx %0.3f<=%0.3f<=%0.3f\n", | |
884 pos, dts_min / 90000.0, timestamp / 90000.0, dts_max / 90000.0); | |
885 #endif | |
886 /* do the seek */ | |
887 url_fseek(&s->pb, pos, SEEK_SET); | |
888 return 0; | |
889 } | |
890 | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
891 #ifdef CONFIG_ENCODERS |
0 | 892 static AVOutputFormat mpeg1system_mux = { |
893 "mpeg", | |
894 "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
|
895 "video/mpeg", |
0 | 896 "mpg,mpeg", |
897 sizeof(MpegMuxContext), | |
898 CODEC_ID_MP2, | |
899 CODEC_ID_MPEG1VIDEO, | |
900 mpeg_mux_init, | |
901 mpeg_mux_write_packet, | |
902 mpeg_mux_end, | |
903 }; | |
904 | |
905 static AVOutputFormat mpeg1vcd_mux = { | |
906 "vcd", | |
907 "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
|
908 "video/mpeg", |
0 | 909 NULL, |
910 sizeof(MpegMuxContext), | |
911 CODEC_ID_MP2, | |
912 CODEC_ID_MPEG1VIDEO, | |
913 mpeg_mux_init, | |
914 mpeg_mux_write_packet, | |
915 mpeg_mux_end, | |
916 }; | |
917 | |
918 static AVOutputFormat mpeg2vob_mux = { | |
919 "vob", | |
920 "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
|
921 "video/mpeg", |
0 | 922 "vob", |
923 sizeof(MpegMuxContext), | |
924 CODEC_ID_MP2, | |
925 CODEC_ID_MPEG1VIDEO, | |
926 mpeg_mux_init, | |
927 mpeg_mux_write_packet, | |
928 mpeg_mux_end, | |
929 }; | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
930 #endif //CONFIG_ENCODERS |
0 | 931 |
190 | 932 AVInputFormat mpegps_demux = { |
0 | 933 "mpeg", |
934 "MPEG PS format", | |
935 sizeof(MpegDemuxContext), | |
936 mpegps_probe, | |
937 mpegps_read_header, | |
938 mpegps_read_packet, | |
939 mpegps_read_close, | |
310 | 940 mpegps_read_seek, |
0 | 941 }; |
942 | |
943 int mpegps_init(void) | |
944 { | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
945 #ifdef CONFIG_ENCODERS |
0 | 946 av_register_output_format(&mpeg1system_mux); |
947 av_register_output_format(&mpeg1vcd_mux); | |
948 av_register_output_format(&mpeg2vob_mux); | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
949 #endif //CONFIG_ENCODERS |
0 | 950 av_register_input_format(&mpegps_demux); |
951 return 0; | |
952 } |