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