Mercurial > libavformat.hg
annotate mpeg.c @ 355:46029c682234 libavformat
seeking stuff
adaptively change middle position selection algo for seeking, this avoids some ugly worstcases of the interpolated variant
avoid backward search for mpeg where possible, its 17 times slower then forward according to my benchmark
author | michael |
---|---|
date | Sat, 17 Jan 2004 20:26:44 +0000 |
parents | 6770ca07abe2 |
children | 72c7cf2f3a7a |
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 |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
24 #undef NDEBUG |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
25 #include <assert.h> |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
26 |
0 | 27 typedef struct { |
65 | 28 uint8_t buffer[MAX_PAYLOAD_SIZE]; |
0 | 29 int buffer_ptr; |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
30 int nb_frames; /* number of starting frame encountered (AC3) */ |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
31 int frame_start_offset; /* starting offset of the frame + 1 (0 if none) */ |
65 | 32 uint8_t id; |
0 | 33 int max_buffer_size; /* in bytes */ |
34 int packet_number; | |
65 | 35 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
|
36 int64_t start_dts; |
336 | 37 uint8_t lpcm_header[3]; |
38 int lpcm_align; | |
0 | 39 } StreamInfo; |
40 | |
41 typedef struct { | |
42 int packet_size; /* required packet size */ | |
43 int packet_number; | |
44 int pack_header_freq; /* frequency (in packets^-1) at which we send pack headers */ | |
45 int system_header_freq; | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
46 int system_header_size; |
0 | 47 int mux_rate; /* bitrate in units of 50 bytes/s */ |
48 /* stream info */ | |
49 int audio_bound; | |
50 int video_bound; | |
51 int is_mpeg2; | |
52 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
|
53 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
|
54 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
|
55 int64_t last_scr; /* current system clock */ |
0 | 56 } MpegMuxContext; |
57 | |
58 #define PACK_START_CODE ((unsigned int)0x000001ba) | |
59 #define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb) | |
60 #define SEQUENCE_END_CODE ((unsigned int)0x000001b7) | |
61 #define PACKET_START_CODE_MASK ((unsigned int)0xffffff00) | |
62 #define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100) | |
63 #define ISO_11172_END_CODE ((unsigned int)0x000001b9) | |
64 | |
65 /* mpeg2 */ | |
66 #define PROGRAM_STREAM_MAP 0x1bc | |
67 #define PRIVATE_STREAM_1 0x1bd | |
68 #define PADDING_STREAM 0x1be | |
69 #define PRIVATE_STREAM_2 0x1bf | |
70 | |
71 | |
72 #define AUDIO_ID 0xc0 | |
73 #define VIDEO_ID 0xe0 | |
336 | 74 #define AC3_ID 0x80 |
75 #define LPCM_ID 0xa0 | |
0 | 76 |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
77 #ifdef CONFIG_ENCODERS |
0 | 78 extern AVOutputFormat mpeg1system_mux; |
79 extern AVOutputFormat mpeg1vcd_mux; | |
80 extern AVOutputFormat mpeg2vob_mux; | |
81 | |
336 | 82 static const int lpcm_freq_tab[4] = { 48000, 96000, 44100, 32000 }; |
83 | |
0 | 84 static int put_pack_header(AVFormatContext *ctx, |
65 | 85 uint8_t *buf, int64_t timestamp) |
0 | 86 { |
87 MpegMuxContext *s = ctx->priv_data; | |
88 PutBitContext pb; | |
89 | |
276 | 90 init_put_bits(&pb, buf, 128); |
0 | 91 |
92 put_bits(&pb, 32, PACK_START_CODE); | |
93 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
|
94 put_bits(&pb, 2, 0x1); |
0 | 95 } else { |
96 put_bits(&pb, 4, 0x2); | |
97 } | |
65 | 98 put_bits(&pb, 3, (uint32_t)((timestamp >> 30) & 0x07)); |
0 | 99 put_bits(&pb, 1, 1); |
65 | 100 put_bits(&pb, 15, (uint32_t)((timestamp >> 15) & 0x7fff)); |
0 | 101 put_bits(&pb, 1, 1); |
65 | 102 put_bits(&pb, 15, (uint32_t)((timestamp) & 0x7fff)); |
0 | 103 put_bits(&pb, 1, 1); |
104 if (s->is_mpeg2) { | |
105 /* clock extension */ | |
106 put_bits(&pb, 9, 0); | |
107 put_bits(&pb, 1, 1); | |
108 } | |
109 put_bits(&pb, 1, 1); | |
110 put_bits(&pb, 22, s->mux_rate); | |
111 put_bits(&pb, 1, 1); | |
112 if (s->is_mpeg2) { | |
113 put_bits(&pb, 5, 0x1f); /* reserved */ | |
114 put_bits(&pb, 3, 0); /* stuffing length */ | |
115 } | |
116 flush_put_bits(&pb); | |
117 return pbBufPtr(&pb) - pb.buf; | |
118 } | |
119 | |
65 | 120 static int put_system_header(AVFormatContext *ctx, uint8_t *buf) |
0 | 121 { |
122 MpegMuxContext *s = ctx->priv_data; | |
123 int size, rate_bound, i, private_stream_coded, id; | |
124 PutBitContext pb; | |
125 | |
276 | 126 init_put_bits(&pb, buf, 128); |
0 | 127 |
128 put_bits(&pb, 32, SYSTEM_HEADER_START_CODE); | |
129 put_bits(&pb, 16, 0); | |
130 put_bits(&pb, 1, 1); | |
131 | |
132 rate_bound = s->mux_rate; /* maximum bit rate of the multiplexed stream */ | |
133 put_bits(&pb, 22, rate_bound); | |
134 put_bits(&pb, 1, 1); /* marker */ | |
135 put_bits(&pb, 6, s->audio_bound); | |
136 | |
137 put_bits(&pb, 1, 1); /* variable bitrate */ | |
138 put_bits(&pb, 1, 1); /* non constrainted bit stream */ | |
139 | |
140 put_bits(&pb, 1, 0); /* audio locked */ | |
141 put_bits(&pb, 1, 0); /* video locked */ | |
142 put_bits(&pb, 1, 1); /* marker */ | |
143 | |
144 put_bits(&pb, 5, s->video_bound); | |
145 put_bits(&pb, 8, 0xff); /* reserved byte */ | |
146 | |
147 /* audio stream info */ | |
148 private_stream_coded = 0; | |
149 for(i=0;i<ctx->nb_streams;i++) { | |
150 StreamInfo *stream = ctx->streams[i]->priv_data; | |
151 id = stream->id; | |
152 if (id < 0xc0) { | |
153 /* special case for private streams (AC3 use that) */ | |
154 if (private_stream_coded) | |
155 continue; | |
156 private_stream_coded = 1; | |
157 id = 0xbd; | |
158 } | |
159 put_bits(&pb, 8, id); /* stream ID */ | |
160 put_bits(&pb, 2, 3); | |
161 if (id < 0xe0) { | |
162 /* audio */ | |
163 put_bits(&pb, 1, 0); | |
164 put_bits(&pb, 13, stream->max_buffer_size / 128); | |
165 } else { | |
166 /* video */ | |
167 put_bits(&pb, 1, 1); | |
168 put_bits(&pb, 13, stream->max_buffer_size / 1024); | |
169 } | |
170 } | |
171 flush_put_bits(&pb); | |
172 size = pbBufPtr(&pb) - pb.buf; | |
173 /* patch packet size */ | |
174 buf[4] = (size - 6) >> 8; | |
175 buf[5] = (size - 6) & 0xff; | |
176 | |
177 return size; | |
178 } | |
179 | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
180 static int get_system_header_size(AVFormatContext *ctx) |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
181 { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
182 int buf_index, i, private_stream_coded; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
183 StreamInfo *stream; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
184 |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
185 buf_index = 12; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
186 private_stream_coded = 0; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
187 for(i=0;i<ctx->nb_streams;i++) { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
188 stream = ctx->streams[i]->priv_data; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
189 if (stream->id < 0xc0) { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
190 if (private_stream_coded) |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
191 continue; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
192 private_stream_coded = 1; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
193 } |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
194 buf_index += 3; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
195 } |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
196 return buf_index; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
197 } |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
198 |
0 | 199 static int mpeg_mux_init(AVFormatContext *ctx) |
200 { | |
201 MpegMuxContext *s = ctx->priv_data; | |
336 | 202 int bitrate, i, mpa_id, mpv_id, ac3_id, lpcm_id, j; |
0 | 203 AVStream *st; |
204 StreamInfo *stream; | |
205 | |
206 s->packet_number = 0; | |
207 s->is_vcd = (ctx->oformat == &mpeg1vcd_mux); | |
208 s->is_mpeg2 = (ctx->oformat == &mpeg2vob_mux); | |
209 | |
210 if (s->is_vcd) | |
211 s->packet_size = 2324; /* VCD packet size */ | |
212 else | |
213 s->packet_size = 2048; | |
214 | |
215 s->audio_bound = 0; | |
216 s->video_bound = 0; | |
217 mpa_id = AUDIO_ID; | |
336 | 218 ac3_id = AC3_ID; |
0 | 219 mpv_id = VIDEO_ID; |
336 | 220 lpcm_id = LPCM_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
|
221 s->scr_stream_index = -1; |
0 | 222 for(i=0;i<ctx->nb_streams;i++) { |
223 st = ctx->streams[i]; | |
224 stream = av_mallocz(sizeof(StreamInfo)); | |
225 if (!stream) | |
226 goto fail; | |
227 st->priv_data = stream; | |
228 | |
229 switch(st->codec.codec_type) { | |
230 case CODEC_TYPE_AUDIO: | |
336 | 231 if (st->codec.codec_id == CODEC_ID_AC3) { |
0 | 232 stream->id = ac3_id++; |
336 | 233 } else if (st->codec.codec_id == CODEC_ID_PCM_S16BE) { |
234 stream->id = lpcm_id++; | |
235 for(j = 0; j < 4; j++) { | |
236 if (lpcm_freq_tab[j] == st->codec.sample_rate) | |
237 break; | |
238 } | |
239 if (j == 4) | |
240 goto fail; | |
241 if (st->codec.channels > 8) | |
242 return -1; | |
243 stream->lpcm_header[0] = 0x0c; | |
244 stream->lpcm_header[1] = (st->codec.channels - 1) | (j << 4); | |
245 stream->lpcm_header[2] = 0x80; | |
246 stream->lpcm_align = st->codec.channels * 2; | |
247 } else { | |
0 | 248 stream->id = mpa_id++; |
336 | 249 } |
0 | 250 stream->max_buffer_size = 4 * 1024; |
251 s->audio_bound++; | |
252 break; | |
253 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
|
254 /* 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
|
255 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
|
256 s->scr_stream_index = i; |
0 | 257 stream->id = mpv_id++; |
258 stream->max_buffer_size = 46 * 1024; | |
259 s->video_bound++; | |
260 break; | |
261 default: | |
262 av_abort(); | |
263 } | |
264 } | |
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
|
265 /* 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
|
266 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
|
267 s->scr_stream_index = 0; |
0 | 268 |
269 /* we increase slightly the bitrate to take into account the | |
270 headers. XXX: compute it exactly */ | |
271 bitrate = 2000; | |
272 for(i=0;i<ctx->nb_streams;i++) { | |
273 st = ctx->streams[i]; | |
274 bitrate += st->codec.bit_rate; | |
275 } | |
276 s->mux_rate = (bitrate + (8 * 50) - 1) / (8 * 50); | |
277 | |
278 if (s->is_vcd || s->is_mpeg2) | |
279 /* every packet */ | |
280 s->pack_header_freq = 1; | |
281 else | |
282 /* every 2 seconds */ | |
283 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
|
284 |
b19f70a6d60f
1/0 fix by (Tim Allen <tim at proximity dot com dot au>)
michael
parents:
277
diff
changeset
|
285 /* 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
|
286 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
|
287 s->pack_header_freq = 1; |
0 | 288 |
289 if (s->is_mpeg2) | |
290 /* every 200 packets. Need to look at the spec. */ | |
291 s->system_header_freq = s->pack_header_freq * 40; | |
292 else if (s->is_vcd) | |
293 /* every 40 packets, this is my invention */ | |
294 s->system_header_freq = s->pack_header_freq * 40; | |
295 else | |
296 s->system_header_freq = s->pack_header_freq * 5; | |
297 | |
298 for(i=0;i<ctx->nb_streams;i++) { | |
299 stream = ctx->streams[i]->priv_data; | |
300 stream->buffer_ptr = 0; | |
301 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
|
302 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
|
303 stream->start_dts = AV_NOPTS_VALUE; |
0 | 304 } |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
305 s->system_header_size = get_system_header_size(ctx); |
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
|
306 s->last_scr = 0; |
0 | 307 return 0; |
308 fail: | |
309 for(i=0;i<ctx->nb_streams;i++) { | |
310 av_free(ctx->streams[i]->priv_data); | |
311 } | |
312 return -ENOMEM; | |
313 } | |
314 | |
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
|
315 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
|
316 { |
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
|
317 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
|
318 (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
|
319 (((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
|
320 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
|
321 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
|
322 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
|
323 } |
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 |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
325 |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
326 /* return the exact available payload size for the next packet for |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
327 stream 'stream_index'. 'pts' and 'dts' are only used to know if |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
328 timestamps are needed in the packet header. */ |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
329 static int get_packet_payload_size(AVFormatContext *ctx, int stream_index, |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
330 int64_t pts, int64_t dts) |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
331 { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
332 MpegMuxContext *s = ctx->priv_data; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
333 int buf_index; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
334 StreamInfo *stream; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
335 |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
336 buf_index = 0; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
337 if (((s->packet_number % s->pack_header_freq) == 0)) { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
338 /* pack header size */ |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
339 if (s->is_mpeg2) |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
340 buf_index += 14; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
341 else |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
342 buf_index += 12; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
343 if ((s->packet_number % s->system_header_freq) == 0) |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
344 buf_index += s->system_header_size; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
345 } |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
346 |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
347 /* packet header size */ |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
348 buf_index += 6; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
349 if (s->is_mpeg2) |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
350 buf_index += 3; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
351 if (pts != AV_NOPTS_VALUE) { |
337 | 352 if (dts != pts) |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
353 buf_index += 5 + 5; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
354 else |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
355 buf_index += 5; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
356 } else { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
357 if (!s->is_mpeg2) |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
358 buf_index++; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
359 } |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
360 |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
361 stream = ctx->streams[stream_index]->priv_data; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
362 if (stream->id < 0xc0) { |
336 | 363 /* AC3/LPCM private data header */ |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
364 buf_index += 4; |
336 | 365 if (stream->id >= 0xa0) { |
366 int n; | |
367 buf_index += 3; | |
368 /* NOTE: we round the payload size to an integer number of | |
369 LPCM samples */ | |
370 n = (s->packet_size - buf_index) % stream->lpcm_align; | |
371 if (n) | |
372 buf_index += (stream->lpcm_align - n); | |
373 } | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
374 } |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
375 return s->packet_size - buf_index; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
376 } |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
377 |
0 | 378 /* 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
|
379 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
|
380 int64_t pts, int64_t dts, int64_t scr) |
0 | 381 { |
382 MpegMuxContext *s = ctx->priv_data; | |
383 StreamInfo *stream = ctx->streams[stream_index]->priv_data; | |
65 | 384 uint8_t *buf_ptr; |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
385 int size, payload_size, startcode, id, stuffing_size, i, header_len; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
386 int packet_size; |
65 | 387 uint8_t buffer[128]; |
0 | 388 |
389 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
|
390 |
0 | 391 #if 0 |
392 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
|
393 id, pts / 90000.0); |
0 | 394 #endif |
395 | |
396 buf_ptr = buffer; | |
397 if (((s->packet_number % s->pack_header_freq) == 0)) { | |
398 /* 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
|
399 size = put_pack_header(ctx, buf_ptr, scr); |
0 | 400 buf_ptr += size; |
401 if ((s->packet_number % s->system_header_freq) == 0) { | |
402 size = put_system_header(ctx, buf_ptr); | |
403 buf_ptr += size; | |
404 } | |
405 } | |
406 size = buf_ptr - buffer; | |
407 put_buffer(&ctx->pb, buffer, size); | |
408 | |
409 /* packet header */ | |
410 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
|
411 header_len = 3; |
0 | 412 } 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
|
413 header_len = 0; |
0 | 414 } |
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
|
415 if (pts != AV_NOPTS_VALUE) { |
337 | 416 if (dts != 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
|
417 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
|
418 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
|
419 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
|
420 } 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
|
421 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
|
422 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
|
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 |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
425 packet_size = s->packet_size - (size + 6); |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
426 payload_size = packet_size - header_len; |
0 | 427 if (id < 0xc0) { |
428 startcode = PRIVATE_STREAM_1; | |
429 payload_size -= 4; | |
336 | 430 if (id >= 0xa0) |
431 payload_size -= 3; | |
0 | 432 } else { |
433 startcode = 0x100 + id; | |
434 } | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
435 |
0 | 436 stuffing_size = payload_size - stream->buffer_ptr; |
437 if (stuffing_size < 0) | |
438 stuffing_size = 0; | |
439 put_be32(&ctx->pb, startcode); | |
440 | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
441 put_be16(&ctx->pb, packet_size); |
0 | 442 /* stuffing */ |
443 for(i=0;i<stuffing_size;i++) | |
444 put_byte(&ctx->pb, 0xff); | |
445 | |
446 if (s->is_mpeg2) { | |
447 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
|
448 |
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
|
449 if (pts != AV_NOPTS_VALUE) { |
337 | 450 if (dts != 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
|
451 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
|
452 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
|
453 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
|
454 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
|
455 } 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
|
456 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
|
457 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
|
458 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
|
459 } |
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 } 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
|
461 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
|
462 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
|
463 } |
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
|
464 } 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
|
465 if (pts != AV_NOPTS_VALUE) { |
337 | 466 if (dts != 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
|
467 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
|
468 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
|
469 } 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
|
470 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
|
471 } |
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
|
472 } 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
|
473 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
|
474 } |
0 | 475 } |
476 | |
477 if (startcode == PRIVATE_STREAM_1) { | |
478 put_byte(&ctx->pb, id); | |
336 | 479 if (id >= 0xa0) { |
480 /* LPCM (XXX: check nb_frames) */ | |
481 put_byte(&ctx->pb, 7); | |
482 put_be16(&ctx->pb, 4); /* skip 3 header bytes */ | |
483 put_byte(&ctx->pb, stream->lpcm_header[0]); | |
484 put_byte(&ctx->pb, stream->lpcm_header[1]); | |
485 put_byte(&ctx->pb, stream->lpcm_header[2]); | |
486 } else { | |
487 /* AC3 */ | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
488 put_byte(&ctx->pb, stream->nb_frames); |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
489 put_be16(&ctx->pb, stream->frame_start_offset); |
0 | 490 } |
491 } | |
492 | |
493 /* output data */ | |
494 put_buffer(&ctx->pb, stream->buffer, payload_size - stuffing_size); | |
495 put_flush_packet(&ctx->pb); | |
496 | |
497 s->packet_number++; | |
498 stream->packet_number++; | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
499 stream->nb_frames = 0; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
500 stream->frame_start_offset = 0; |
0 | 501 } |
502 | |
337 | 503 /* XXX: move that to upper layer */ |
504 /* XXX: we assume that there are always 'max_b_frames' between | |
505 reference frames. A better solution would be to use the AVFrame pts | |
506 field */ | |
507 static void compute_pts_dts(AVStream *st, int64_t *ppts, int64_t *pdts, | |
508 int64_t timestamp) | |
509 { | |
510 int frame_delay; | |
511 int64_t pts, dts; | |
512 | |
513 if (st->codec.codec_type == CODEC_TYPE_VIDEO && | |
514 st->codec.max_b_frames != 0) { | |
515 frame_delay = (st->codec.frame_rate_base * 90000LL) / | |
516 st->codec.frame_rate; | |
517 if (timestamp == 0) { | |
518 /* specific case for first frame : DTS just before */ | |
519 pts = timestamp; | |
520 dts = timestamp - frame_delay; | |
521 } else { | |
522 timestamp -= frame_delay; | |
523 if (st->codec.coded_frame->pict_type == FF_B_TYPE) { | |
524 /* B frames has identical pts/dts */ | |
525 pts = timestamp; | |
526 dts = timestamp; | |
527 } else { | |
528 /* a reference frame has a pts equal to the dts of the | |
529 _next_ one */ | |
530 dts = timestamp; | |
531 pts = timestamp + (st->codec.max_b_frames + 1) * frame_delay; | |
532 } | |
533 } | |
534 #if 1 | |
535 printf("pts=%0.3f dts=%0.3f pict_type=%c\n", | |
536 pts / 90000.0, dts / 90000.0, | |
537 av_get_pict_type_char(st->codec.coded_frame->pict_type)); | |
538 #endif | |
539 } else { | |
540 pts = timestamp; | |
541 dts = timestamp; | |
542 } | |
543 *ppts = pts & ((1LL << 33) - 1); | |
544 *pdts = dts & ((1LL << 33) - 1); | |
545 } | |
546 | |
0 | 547 static int mpeg_mux_write_packet(AVFormatContext *ctx, int stream_index, |
337 | 548 const uint8_t *buf, int size, |
549 int64_t timestamp) | |
0 | 550 { |
551 MpegMuxContext *s = ctx->priv_data; | |
552 AVStream *st = ctx->streams[stream_index]; | |
553 StreamInfo *stream = st->priv_data; | |
337 | 554 int64_t pts, dts, new_start_pts, new_start_dts; |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
555 int len, avail_size; |
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
|
556 |
337 | 557 compute_pts_dts(st, &pts, &dts, timestamp); |
558 | |
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
|
559 /* 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
|
560 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
|
561 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
|
562 s->last_scr = pts; |
0 | 563 |
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
|
564 #if 0 |
337 | 565 printf("%d: pts=%0.3f dts=%0.3f scr=%0.3f\n", |
566 stream_index, | |
567 pts / 90000.0, | |
568 dts / 90000.0, | |
569 s->last_scr / 90000.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
|
570 #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
|
571 |
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
|
572 /* we assume here that pts != AV_NOPTS_VALUE */ |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
573 new_start_pts = stream->start_pts; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
574 new_start_dts = stream->start_dts; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
575 |
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
|
576 if (stream->start_pts == AV_NOPTS_VALUE) { |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
577 new_start_pts = pts; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
578 new_start_dts = dts; |
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
|
579 } |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
580 avail_size = get_packet_payload_size(ctx, stream_index, |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
581 new_start_pts, |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
582 new_start_dts); |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
583 if (stream->buffer_ptr >= avail_size) { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
584 /* unlikely case: outputing the pts or dts increase the packet |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
585 size so that we cannot write the start of the next |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
586 packet. In this case, we must flush the current packet with |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
587 padding */ |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
588 flush_packet(ctx, stream_index, |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
589 stream->start_pts, stream->start_dts, s->last_scr); |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
590 stream->buffer_ptr = 0; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
591 } |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
592 stream->start_pts = new_start_pts; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
593 stream->start_dts = new_start_dts; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
594 stream->nb_frames++; |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
595 if (stream->frame_start_offset == 0) |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
596 stream->frame_start_offset = stream->buffer_ptr; |
0 | 597 while (size > 0) { |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
598 avail_size = get_packet_payload_size(ctx, stream_index, |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
599 stream->start_pts, |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
600 stream->start_dts); |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
601 len = avail_size - stream->buffer_ptr; |
0 | 602 if (len > size) |
603 len = size; | |
604 memcpy(stream->buffer + stream->buffer_ptr, buf, len); | |
605 stream->buffer_ptr += len; | |
606 buf += len; | |
607 size -= len; | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
608 if (stream->buffer_ptr >= avail_size) { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
609 /* if packet full, we send it now */ |
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
|
610 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
|
611 stream->start_pts, stream->start_dts, s->last_scr); |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
612 stream->buffer_ptr = 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
|
613 /* 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
|
614 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
|
615 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
|
616 stream->start_dts = AV_NOPTS_VALUE; |
0 | 617 } |
618 } | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
619 |
0 | 620 return 0; |
621 } | |
622 | |
623 static int mpeg_mux_end(AVFormatContext *ctx) | |
624 { | |
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
|
625 MpegMuxContext *s = ctx->priv_data; |
0 | 626 StreamInfo *stream; |
627 int i; | |
628 | |
629 /* flush each packet */ | |
630 for(i=0;i<ctx->nb_streams;i++) { | |
631 stream = ctx->streams[i]->priv_data; | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
632 if (stream->buffer_ptr > 0) { |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
633 /* NOTE: we can always write the remaining data as it was |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
634 tested before in mpeg_mux_write_packet() */ |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
635 flush_packet(ctx, i, stream->start_pts, stream->start_dts, |
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
636 s->last_scr); |
0 | 637 } |
638 } | |
639 | |
242 | 640 /* End header according to MPEG1 systems standard. We do not write |
641 it as it is usually not needed by decoders and because it | |
642 complicates MPEG stream concatenation. */ | |
0 | 643 //put_be32(&ctx->pb, ISO_11172_END_CODE); |
644 //put_flush_packet(&ctx->pb); | |
237
35231c0be8e5
memleak fix by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michaelni
parents:
210
diff
changeset
|
645 |
35231c0be8e5
memleak fix by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michaelni
parents:
210
diff
changeset
|
646 for(i=0;i<ctx->nb_streams;i++) |
35231c0be8e5
memleak fix by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michaelni
parents:
210
diff
changeset
|
647 av_freep(&ctx->streams[i]->priv_data); |
35231c0be8e5
memleak fix by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michaelni
parents:
210
diff
changeset
|
648 |
0 | 649 return 0; |
650 } | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
651 #endif //CONFIG_ENCODERS |
0 | 652 |
653 /*********************************************/ | |
654 /* demux code */ | |
655 | |
656 #define MAX_SYNC_SIZE 100000 | |
657 | |
658 static int mpegps_probe(AVProbeData *p) | |
659 { | |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
660 int code, c, i; |
0 | 661 |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
662 code = 0xff; |
0 | 663 /* we search the first start code. If it is a packet start code, |
664 then we decide it is mpeg ps. We do not send highest value to | |
665 give a chance to mpegts */ | |
49 | 666 /* NOTE: the search range was restricted to avoid too many false |
667 detections */ | |
668 | |
669 if (p->buf_size < 6) | |
670 return 0; | |
165
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
671 |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
672 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
|
673 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
|
674 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
|
675 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
|
676 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
|
677 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
|
678 (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
|
679 (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
|
680 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
|
681 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
|
682 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
|
683 code == PADDING_STREAM) |
210 | 684 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
|
685 else |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
686 return 0; |
e4d2f704bf80
- Looks a tiny bit harder in mpegps_probe() for a valid start code. This is
michaelni
parents:
65
diff
changeset
|
687 } |
0 | 688 } |
689 return 0; | |
690 } | |
691 | |
692 | |
693 typedef struct MpegDemuxContext { | |
694 int header_state; | |
695 } MpegDemuxContext; | |
696 | |
310 | 697 static int mpegps_read_header(AVFormatContext *s, |
698 AVFormatParameters *ap) | |
699 { | |
700 MpegDemuxContext *m = s->priv_data; | |
701 m->header_state = 0xff; | |
702 s->ctx_flags |= AVFMTCTX_NOHEADER; | |
703 | |
704 /* no need to do more */ | |
705 return 0; | |
706 } | |
707 | |
708 static int64_t get_pts(ByteIOContext *pb, int c) | |
709 { | |
710 int64_t pts; | |
711 int val; | |
712 | |
713 if (c < 0) | |
714 c = get_byte(pb); | |
715 pts = (int64_t)((c >> 1) & 0x07) << 30; | |
716 val = get_be16(pb); | |
717 pts |= (int64_t)(val >> 1) << 15; | |
718 val = get_be16(pb); | |
719 pts |= (int64_t)(val >> 1); | |
720 return pts; | |
721 } | |
722 | |
723 static int find_next_start_code(ByteIOContext *pb, int *size_ptr, | |
724 uint32_t *header_state) | |
0 | 725 { |
726 unsigned int state, v; | |
727 int val, n; | |
728 | |
729 state = *header_state; | |
730 n = *size_ptr; | |
731 while (n > 0) { | |
732 if (url_feof(pb)) | |
733 break; | |
734 v = get_byte(pb); | |
735 n--; | |
736 if (state == 0x000001) { | |
737 state = ((state << 8) | v) & 0xffffff; | |
738 val = state; | |
739 goto found; | |
740 } | |
741 state = ((state << 8) | v) & 0xffffff; | |
742 } | |
743 val = -1; | |
744 found: | |
745 *header_state = state; | |
746 *size_ptr = n; | |
747 return val; | |
748 } | |
749 | |
310 | 750 /* XXX: optimize */ |
751 static int find_prev_start_code(ByteIOContext *pb, int *size_ptr) | |
0 | 752 { |
310 | 753 int64_t pos, pos_start; |
754 int max_size, start_code; | |
755 | |
756 max_size = *size_ptr; | |
757 pos_start = url_ftell(pb); | |
758 | |
759 /* in order to go faster, we fill the buffer */ | |
760 pos = pos_start - 16386; | |
761 if (pos < 0) | |
762 pos = 0; | |
763 url_fseek(pb, pos, SEEK_SET); | |
764 get_byte(pb); | |
293
62cec412a186
make AVFMT_NOHEADER flag dynamic - added av_open_input_stream()
bellard
parents:
291
diff
changeset
|
765 |
310 | 766 pos = pos_start; |
767 for(;;) { | |
768 pos--; | |
769 if (pos < 0 || (pos_start - pos) >= max_size) { | |
770 start_code = -1; | |
771 goto the_end; | |
772 } | |
773 url_fseek(pb, pos, SEEK_SET); | |
774 start_code = get_be32(pb); | |
775 if ((start_code & 0xffffff00) == 0x100) | |
776 break; | |
777 } | |
778 the_end: | |
779 *size_ptr = pos_start - pos; | |
780 return start_code; | |
0 | 781 } |
782 | |
310 | 783 /* read the next (or previous) PES header. Return its position in ppos |
784 (if not NULL), and its start code, pts and dts. | |
785 */ | |
786 static int mpegps_read_pes_header(AVFormatContext *s, | |
787 int64_t *ppos, int *pstart_code, | |
788 int64_t *ppts, int64_t *pdts, int find_next) | |
0 | 789 { |
790 MpegDemuxContext *m = s->priv_data; | |
310 | 791 int len, size, startcode, c, flags, header_len; |
792 int64_t pts, dts, last_pos; | |
0 | 793 |
310 | 794 last_pos = -1; |
0 | 795 redo: |
310 | 796 if (find_next) { |
797 /* next start code (should be immediately after) */ | |
798 m->header_state = 0xff; | |
799 size = MAX_SYNC_SIZE; | |
800 startcode = find_next_start_code(&s->pb, &size, &m->header_state); | |
801 } else { | |
802 if (last_pos >= 0) | |
803 url_fseek(&s->pb, last_pos, SEEK_SET); | |
804 size = MAX_SYNC_SIZE; | |
805 startcode = find_prev_start_code(&s->pb, &size); | |
806 last_pos = url_ftell(&s->pb) - 4; | |
807 } | |
0 | 808 //printf("startcode=%x pos=0x%Lx\n", startcode, url_ftell(&s->pb)); |
809 if (startcode < 0) | |
810 return -EIO; | |
811 if (startcode == PACK_START_CODE) | |
812 goto redo; | |
813 if (startcode == SYSTEM_HEADER_START_CODE) | |
814 goto redo; | |
815 if (startcode == PADDING_STREAM || | |
816 startcode == PRIVATE_STREAM_2) { | |
817 /* skip them */ | |
818 len = get_be16(&s->pb); | |
819 url_fskip(&s->pb, len); | |
820 goto redo; | |
821 } | |
822 /* find matching stream */ | |
823 if (!((startcode >= 0x1c0 && startcode <= 0x1df) || | |
824 (startcode >= 0x1e0 && startcode <= 0x1ef) || | |
825 (startcode == 0x1bd))) | |
826 goto redo; | |
310 | 827 if (ppos) { |
828 *ppos = url_ftell(&s->pb) - 4; | |
829 } | |
0 | 830 len = get_be16(&s->pb); |
831 pts = AV_NOPTS_VALUE; | |
832 dts = AV_NOPTS_VALUE; | |
833 /* stuffing */ | |
834 for(;;) { | |
310 | 835 if (len < 1) |
836 goto redo; | |
0 | 837 c = get_byte(&s->pb); |
838 len--; | |
839 /* XXX: for mpeg1, should test only bit 7 */ | |
840 if (c != 0xff) | |
841 break; | |
842 } | |
843 if ((c & 0xc0) == 0x40) { | |
844 /* buffer scale & size */ | |
310 | 845 if (len < 2) |
846 goto redo; | |
0 | 847 get_byte(&s->pb); |
848 c = get_byte(&s->pb); | |
849 len -= 2; | |
850 } | |
851 if ((c & 0xf0) == 0x20) { | |
310 | 852 if (len < 4) |
853 goto redo; | |
854 dts = pts = get_pts(&s->pb, c); | |
0 | 855 len -= 4; |
856 } else if ((c & 0xf0) == 0x30) { | |
310 | 857 if (len < 9) |
858 goto redo; | |
0 | 859 pts = get_pts(&s->pb, c); |
860 dts = get_pts(&s->pb, -1); | |
861 len -= 9; | |
862 } else if ((c & 0xc0) == 0x80) { | |
863 /* mpeg 2 PES */ | |
864 if ((c & 0x30) != 0) { | |
310 | 865 /* Encrypted multiplex not handled */ |
866 goto redo; | |
0 | 867 } |
868 flags = get_byte(&s->pb); | |
869 header_len = get_byte(&s->pb); | |
870 len -= 2; | |
871 if (header_len > len) | |
872 goto redo; | |
873 if ((flags & 0xc0) == 0x80) { | |
310 | 874 dts = pts = get_pts(&s->pb, -1); |
875 if (header_len < 5) | |
876 goto redo; | |
0 | 877 header_len -= 5; |
878 len -= 5; | |
879 } if ((flags & 0xc0) == 0xc0) { | |
880 pts = get_pts(&s->pb, -1); | |
881 dts = get_pts(&s->pb, -1); | |
310 | 882 if (header_len < 10) |
883 goto redo; | |
0 | 884 header_len -= 10; |
885 len -= 10; | |
886 } | |
887 len -= header_len; | |
888 while (header_len > 0) { | |
889 get_byte(&s->pb); | |
890 header_len--; | |
891 } | |
892 } | |
893 if (startcode == 0x1bd) { | |
310 | 894 if (len < 1) |
895 goto redo; | |
0 | 896 startcode = get_byte(&s->pb); |
897 len--; | |
898 if (startcode >= 0x80 && startcode <= 0xbf) { | |
899 /* audio: skip header */ | |
310 | 900 if (len < 3) |
901 goto redo; | |
0 | 902 get_byte(&s->pb); |
903 get_byte(&s->pb); | |
904 get_byte(&s->pb); | |
905 len -= 3; | |
906 } | |
907 } | |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
908 if(dts != AV_NOPTS_VALUE && ppos){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
909 int i; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
910 for(i=0; i<s->nb_streams; i++){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
911 if(startcode == s->streams[i]->id) { |
354
6770ca07abe2
store searched distance in index, so we dont waste time searching for keyframes where we already searched
michael
parents:
346
diff
changeset
|
912 av_add_index_entry(s->streams[i], *ppos, dts, 0, 0 /* FIXME keyframe? */); |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
913 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
914 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
915 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
916 |
310 | 917 *pstart_code = startcode; |
918 *ppts = pts; | |
919 *pdts = dts; | |
920 return len; | |
921 } | |
922 | |
923 static int mpegps_read_packet(AVFormatContext *s, | |
924 AVPacket *pkt) | |
925 { | |
926 AVStream *st; | |
927 int len, startcode, i, type, codec_id; | |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
928 int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work |
310 | 929 |
930 redo: | |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
931 len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts, 1); |
310 | 932 if (len < 0) |
933 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
|
934 |
0 | 935 /* now find stream */ |
936 for(i=0;i<s->nb_streams;i++) { | |
937 st = s->streams[i]; | |
938 if (st->id == startcode) | |
939 goto found; | |
940 } | |
941 if (startcode >= 0x1e0 && startcode <= 0x1ef) { | |
942 type = CODEC_TYPE_VIDEO; | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
943 codec_id = CODEC_ID_MPEG2VIDEO; |
0 | 944 } else if (startcode >= 0x1c0 && startcode <= 0x1df) { |
945 type = CODEC_TYPE_AUDIO; | |
946 codec_id = CODEC_ID_MP2; | |
947 } else if (startcode >= 0x80 && startcode <= 0x9f) { | |
948 type = CODEC_TYPE_AUDIO; | |
949 codec_id = CODEC_ID_AC3; | |
41 | 950 } else if (startcode >= 0xa0 && startcode <= 0xbf) { |
951 type = CODEC_TYPE_AUDIO; | |
952 codec_id = CODEC_ID_PCM_S16BE; | |
0 | 953 } else { |
954 skip: | |
955 /* skip packet */ | |
956 url_fskip(&s->pb, len); | |
957 goto redo; | |
958 } | |
959 /* no stream found: add a new stream */ | |
960 st = av_new_stream(s, startcode); | |
961 if (!st) | |
962 goto skip; | |
963 st->codec.codec_type = type; | |
964 st->codec.codec_id = codec_id; | |
310 | 965 if (codec_id != CODEC_ID_PCM_S16BE) |
966 st->need_parsing = 1; | |
0 | 967 found: |
41 | 968 if (startcode >= 0xa0 && startcode <= 0xbf) { |
969 int b1, freq; | |
970 | |
971 /* for LPCM, we just skip the header and consider it is raw | |
972 audio data */ | |
973 if (len <= 3) | |
974 goto skip; | |
975 get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */ | |
976 b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */ | |
977 get_byte(&s->pb); /* dynamic range control (0x80 = off) */ | |
978 len -= 3; | |
979 freq = (b1 >> 4) & 3; | |
980 st->codec.sample_rate = lpcm_freq_tab[freq]; | |
981 st->codec.channels = 1 + (b1 & 7); | |
982 st->codec.bit_rate = st->codec.channels * st->codec.sample_rate * 2; | |
983 } | |
0 | 984 av_new_packet(pkt, len); |
985 get_buffer(&s->pb, pkt->data, pkt->size); | |
986 pkt->pts = pts; | |
310 | 987 pkt->dts = dts; |
0 | 988 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
|
989 #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
|
990 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
|
991 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
|
992 #endif |
0 | 993 return 0; |
994 } | |
995 | |
996 static int mpegps_read_close(AVFormatContext *s) | |
997 { | |
998 return 0; | |
999 } | |
1000 | |
310 | 1001 static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index, |
1002 int64_t *ppos, int find_next) | |
1003 { | |
1004 int len, startcode; | |
1005 int64_t pos, pts, dts; | |
1006 | |
1007 pos = *ppos; | |
1008 #ifdef DEBUG_SEEK | |
1009 printf("read_dts: pos=0x%llx next=%d -> ", pos, find_next); | |
1010 #endif | |
1011 url_fseek(&s->pb, pos, SEEK_SET); | |
1012 for(;;) { | |
1013 len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts, find_next); | |
1014 if (len < 0) { | |
1015 #ifdef DEBUG_SEEK | |
1016 printf("none (ret=%d)\n", len); | |
1017 #endif | |
1018 return AV_NOPTS_VALUE; | |
1019 } | |
1020 if (startcode == s->streams[stream_index]->id && | |
1021 dts != AV_NOPTS_VALUE) { | |
1022 break; | |
1023 } | |
1024 if (find_next) { | |
1025 url_fskip(&s->pb, len); | |
1026 } else { | |
1027 url_fseek(&s->pb, pos, SEEK_SET); | |
1028 } | |
1029 } | |
1030 #ifdef DEBUG_SEEK | |
1031 printf("pos=0x%llx dts=0x%llx %0.3f\n", pos, dts, dts / 90000.0); | |
1032 #endif | |
1033 *ppos = pos; | |
1034 return dts; | |
1035 } | |
1036 | |
1037 static int mpegps_read_seek(AVFormatContext *s, | |
1038 int stream_index, int64_t timestamp) | |
1039 { | |
355 | 1040 int64_t pos_min, pos_max, pos, pos_limit; |
310 | 1041 int64_t dts_min, dts_max, dts; |
355 | 1042 int index, no_change; |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1043 AVStream *st; |
310 | 1044 |
1045 timestamp = (timestamp * 90000) / AV_TIME_BASE; | |
1046 | |
1047 #ifdef DEBUG_SEEK | |
1048 printf("read_seek: %d %0.3f\n", stream_index, timestamp / 90000.0); | |
1049 #endif | |
1050 | |
1051 /* XXX: find stream_index by looking at the first PES packet found */ | |
1052 if (stream_index < 0) { | |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1053 stream_index = av_find_default_stream_index(s); |
310 | 1054 if (stream_index < 0) |
1055 return -1; | |
1056 } | |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1057 |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1058 dts_max= |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1059 dts_min= AV_NOPTS_VALUE; |
355 | 1060 pos_limit= -1; //gcc falsely says it may be uninitalized |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1061 |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1062 st= s->streams[stream_index]; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1063 if(st->index_entries){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1064 AVIndexEntry *e; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1065 |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1066 index= av_index_search_timestamp(st, timestamp); |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1067 e= &st->index_entries[index]; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1068 if(e->timestamp <= timestamp){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1069 pos_min= e->pos; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1070 dts_min= e->timestamp; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1071 #ifdef DEBUG_SEEK |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1072 printf("unsing cached pos_min=0x%llx dts_min=%0.3f\n", |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1073 pos_min,dts_min / 90000.0); |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1074 #endif |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1075 }else{ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1076 assert(index==0); |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1077 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1078 index++; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1079 if(index < st->nb_index_entries){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1080 e= &st->index_entries[index]; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1081 assert(e->timestamp >= timestamp); |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1082 pos_max= e->pos; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1083 dts_max= e->timestamp; |
355 | 1084 pos_limit= pos_max - e->min_distance; |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1085 #ifdef DEBUG_SEEK |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1086 printf("unsing cached pos_max=0x%llx dts_max=%0.3f\n", |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1087 pos_max,dts_max / 90000.0); |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1088 #endif |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1089 } |
310 | 1090 } |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1091 |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1092 if(dts_min == AV_NOPTS_VALUE){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1093 pos_min = 0; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1094 dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1); |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1095 if (dts_min == AV_NOPTS_VALUE) { |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1096 /* we can reach this case only if no PTS are present in |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1097 the whole stream */ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1098 return -1; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1099 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1100 } |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1101 if(dts_max == AV_NOPTS_VALUE){ |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1102 pos_max = url_filesize(url_fileno(&s->pb)) - 1; |
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1103 dts_max = mpegps_read_dts(s, stream_index, &pos_max, 0); |
355 | 1104 pos_limit= pos_max; |
346
e154eb1b7149
caching of timestamps for mpeg-ps so seeking is faster
michael
parents:
337
diff
changeset
|
1105 } |
355 | 1106 |
1107 no_change=0; | |
1108 while (pos_min < pos_limit) { | |
310 | 1109 #ifdef DEBUG_SEEK |
1110 printf("pos_min=0x%llx pos_max=0x%llx dts_min=%0.3f dts_max=%0.3f\n", | |
1111 pos_min, pos_max, | |
1112 dts_min / 90000.0, dts_max / 90000.0); | |
1113 #endif | |
355 | 1114 int64_t start_pos; |
1115 assert(pos_limit <= pos_max); | |
1116 | |
1117 if(no_change==0){ | |
1118 int64_t approximate_keyframe_distance= pos_max - pos_limit; | |
1119 // interpolate position (better than dichotomy) | |
1120 pos = (int64_t)((double)(pos_max - pos_min) * | |
310 | 1121 (double)(timestamp - dts_min) / |
355 | 1122 (double)(dts_max - dts_min)) + pos_min - approximate_keyframe_distance; |
1123 }else if(no_change==1){ | |
1124 // bisection, if interpolation failed to change min or max pos last time | |
1125 pos = (pos_min + pos_limit)>>1; | |
1126 }else{ | |
1127 // linear search if bisection failed, can only happen if there are very few or no keframes between min/max | |
1128 pos=pos_min; | |
310 | 1129 } |
355 | 1130 if(pos <= pos_min) |
1131 pos= pos_min + 1; | |
1132 else if(pos > pos_limit) | |
1133 pos= pos_limit; | |
1134 start_pos= pos; | |
1135 | |
1136 // read the next timestamp | |
1137 dts = mpegps_read_dts(s, stream_index, &pos, 1); | |
1138 if(pos == pos_max) | |
1139 no_change++; | |
1140 else | |
1141 no_change=0; | |
310 | 1142 #ifdef DEBUG_SEEK |
355 | 1143 printf("%Ld %Ld %Ld / %Ld %Ld %Ld target:%Ld limit:%Ld start:%Ld noc:%d\n", pos_min, pos, pos_max, dts_min, dts, dts_max, timestamp, pos_limit, start_pos, no_change); |
310 | 1144 #endif |
355 | 1145 assert(dts != AV_NOPTS_VALUE); |
1146 if (timestamp < dts) { | |
1147 pos_limit = start_pos - 1; | |
310 | 1148 pos_max = pos; |
355 | 1149 dts_max = dts; |
310 | 1150 } else { |
355 | 1151 pos_min = pos; |
1152 dts_min = dts; | |
1153 /* check if we are lucky */ | |
1154 if (timestamp == dts) | |
1155 break; | |
310 | 1156 } |
1157 } | |
355 | 1158 |
310 | 1159 pos = pos_min; |
1160 #ifdef DEBUG_SEEK | |
1161 pos_min = pos; | |
1162 dts_min = mpegps_read_dts(s, stream_index, &pos_min, 1); | |
1163 pos_min++; | |
1164 dts_max = mpegps_read_dts(s, stream_index, &pos_min, 1); | |
1165 printf("pos=0x%llx %0.3f<=%0.3f<=%0.3f\n", | |
1166 pos, dts_min / 90000.0, timestamp / 90000.0, dts_max / 90000.0); | |
1167 #endif | |
1168 /* do the seek */ | |
1169 url_fseek(&s->pb, pos, SEEK_SET); | |
1170 return 0; | |
1171 } | |
1172 | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
1173 #ifdef CONFIG_ENCODERS |
0 | 1174 static AVOutputFormat mpeg1system_mux = { |
1175 "mpeg", | |
1176 "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
|
1177 "video/mpeg", |
0 | 1178 "mpg,mpeg", |
1179 sizeof(MpegMuxContext), | |
1180 CODEC_ID_MP2, | |
1181 CODEC_ID_MPEG1VIDEO, | |
1182 mpeg_mux_init, | |
1183 mpeg_mux_write_packet, | |
1184 mpeg_mux_end, | |
1185 }; | |
1186 | |
1187 static AVOutputFormat mpeg1vcd_mux = { | |
1188 "vcd", | |
1189 "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
|
1190 "video/mpeg", |
0 | 1191 NULL, |
1192 sizeof(MpegMuxContext), | |
1193 CODEC_ID_MP2, | |
1194 CODEC_ID_MPEG1VIDEO, | |
1195 mpeg_mux_init, | |
1196 mpeg_mux_write_packet, | |
1197 mpeg_mux_end, | |
1198 }; | |
1199 | |
1200 static AVOutputFormat mpeg2vob_mux = { | |
1201 "vob", | |
1202 "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
|
1203 "video/mpeg", |
0 | 1204 "vob", |
1205 sizeof(MpegMuxContext), | |
1206 CODEC_ID_MP2, | |
335
b0ac206f232d
better and simpler logic for MPEG muxing - fixed rare MPEG muxing PTS generation bug (stuffing is added in such rare cases) - fixed AC3 payload size generation - generate correct AC3 frame header (need spec checking)
bellard
parents:
331
diff
changeset
|
1207 CODEC_ID_MPEG2VIDEO, |
0 | 1208 mpeg_mux_init, |
1209 mpeg_mux_write_packet, | |
1210 mpeg_mux_end, | |
1211 }; | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
1212 #endif //CONFIG_ENCODERS |
0 | 1213 |
190 | 1214 AVInputFormat mpegps_demux = { |
0 | 1215 "mpeg", |
1216 "MPEG PS format", | |
1217 sizeof(MpegDemuxContext), | |
1218 mpegps_probe, | |
1219 mpegps_read_header, | |
1220 mpegps_read_packet, | |
1221 mpegps_read_close, | |
310 | 1222 mpegps_read_seek, |
0 | 1223 }; |
1224 | |
1225 int mpegps_init(void) | |
1226 { | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
1227 #ifdef CONFIG_ENCODERS |
0 | 1228 av_register_output_format(&mpeg1system_mux); |
1229 av_register_output_format(&mpeg1vcd_mux); | |
1230 av_register_output_format(&mpeg2vob_mux); | |
277
a313e1080322
disable encoders where appropriate (patch courtesy of BERO
melanson
parents:
276
diff
changeset
|
1231 #endif //CONFIG_ENCODERS |
0 | 1232 av_register_input_format(&mpegps_demux); |
1233 return 0; | |
1234 } |