1 /*
2 * FFM (ffserver live feed) demuxer
3 * Copyright (c) 2001 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
28
30 {
32 int64_t pos, avail_size;
34
36 if (size <= len)
37 return 1;
43 } else {
45 /* exactly at the end of stream */
49 } else {
51 }
52 }
54 if (size <= avail_size)
55 return 1;
56 else
58 }
59
61 {
66 return -1;
67 }
69 }
70 return 0;
71 }
72
73 /* first is true if we read the frame header */
76 {
79 int len, fill_size, size1, frame_offset,
id;
80
82 while (size > 0) {
83 redo:
85 if (len < 0)
86 return -1;
87 if (len > size)
89 if (len == 0) {
92 retry_read:
97 }
101 return -1;
108 return -1;
109 /* if first packet or resynchronization packet, we must
110 handle it specifically */
112 if (!frame_offset) {
113 /* This packet has no frame headers in it */
116 goto retry_read;
117 }
118 /* This is bad, we cannot find a valid frame header */
119 return 0;
120 }
123 return -1;
125 if (!header)
126 break;
127 } else {
129 }
130 goto redo;
131 }
136 header = 0;
137 }
139 }
140
141 /* ensure that acutal seeking happens between FFM_PACKET_SIZE
142 and file_size - FFM_PACKET_SIZE */
144 {
147 int64_t pos;
148
151 av_dlog(s,
"seek to %"PRIx64
" -> %"PRIx64
"\n", pos1, pos);
153 }
154
156 {
158 int64_t dts;
159
163 av_dlog(s,
"dts=%0.6f\n", dts / 1000000.0);
164 return dts;
165 }
166
168 {
171 int64_t pts;
172 //int64_t orig_write_index = ffm->write_index;
173 int64_t pos_min, pos_max;
174 int64_t pts_start;
176
177
178 pos_min = 0;
180
181 pts_start =
get_dts(s, pos_min);
182
184
185 if (pts - 100000 > pts_start)
187
189
190 pts_start =
get_dts(s, pos_min);
191
193
194 if (pts - 100000 <= pts_start) {
195 while (1) {
196 int64_t newpos;
197 int64_t newpts;
198
200
201 if (newpos == pos_min)
202 break;
203
205
206 if (newpts - 100000 <= pts) {
207 pos_max = newpos;
208 pts = newpts;
209 } else {
210 pos_min = newpos;
211 }
212 }
214 }
215
218 }
219
220
222 {
223 int i;
224
227
228 return 0;
229 }
230
232 {
237
240 goto fail;
242 /* get also filesize */
247 } else {
248 ffm->
file_size = (UINT64_C(1) << 63) - 1;
249 }
250
255 char rc_eq_buf[128];
256
257 if(!id)
258 break;
259
260 switch(id) {
261 case MKBETAG(
'M',
'A',
'I',
'N'):
264 break;
265 case MKBETAG(
'C',
'O',
'M',
'M'):
267 if (!st)
268 goto fail;
269
271
273 /* generic info */
284 }
289 switch(id) {
290 case MKBETAG(
'S',
'T',
'V',
'I'):
303 avio_get_str(pb, INT_MAX, rc_eq_buf,
sizeof(rc_eq_buf));
335 break;
336 case MKBETAG(
'S',
'T',
'A',
'U'):
340 break;
341 }
342 break;
343 }
345 }
346
347 /* get until end of block reached */
350
351 /* init packet demux */
358 return 0;
359 fail:
361 return -1;
362 }
363
365 {
370 int i, nb_streams;
372
373 /* header */
375 if (tag ==
MKTAG(
'F',
'F',
'M',
'2'))
377 if (tag !=
MKTAG(
'F',
'F',
'M',
'1'))
378 goto fail;
381 goto fail;
383 /* get also filesize */
388 } else {
389 ffm->
file_size = (UINT64_C(1) << 63) - 1;
390 }
391
394 /* read each stream */
395 for(i=0;i<nb_streams;i++) {
396 char rc_eq_buf[128];
397
399 if (!st)
400 goto fail;
401
403
405 /* generic info */
412 /* specific info */
427 avio_get_str(pb, INT_MAX, rc_eq_buf,
sizeof(rc_eq_buf));
459 break;
464 break;
465 default:
466 goto fail;
467 }
472 }
473 }
474
475 /* get until end of block reached */
478
479 /* init packet demux */
486 return 0;
487 fail:
489 return -1;
490 }
491
492 /* return < 0 if eof */
494 {
498
503
504 av_dlog(s,
"pos=%08"PRIx64
" spos=%"PRIx64
", write_index=%"PRIx64
" size=%"PRIx64
"\n",
508 return -1;
511 return -1;
513 /* fall thru */
518
520
523 }
529 return -1;
530 }
534
537 /* bad case: desynchronized packet. we cancel all the packet loading */
539 return -1;
540 }
544 else
547 break;
548 }
549 return 0;
550 }
551
552 /* seek to a given time in the file. The file read pointer is
553 positioned at or before pts. XXX: the following code is quite
554 approximative */
556 {
558 int64_t pos_min, pos_max, pos;
559 int64_t pts_min, pts_max, pts;
560 double pos1;
561
562 av_dlog(s,
"wanted_pts=%0.6f\n", wanted_pts / 1000000.0);
563 /* find the position using linear interpolation (better than
564 dichotomy in typical cases) */
569 } else {
572 }
573 } else {
576 }
577 while (pos_min <= pos_max) {
580 if (pts_min > wanted_pts || pts_max <= wanted_pts) {
581 pos = pts_min > wanted_pts ? pos_min : pos_max;
582 goto found;
583 }
584 /* linear interpolation */
585 pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) /
586 (double)(pts_max - pts_min);
588 if (pos <= pos_min)
589 pos = pos_min;
590 else if (pos >= pos_max)
591 pos = pos_max;
593 /* check if we are lucky */
594 if (pts == wanted_pts) {
595 goto found;
596 } else if (pts > wanted_pts) {
598 } else {
600 }
601 }
603
604 found:
606 return -1;
607
608 /* reset read state */
613
614 return 0;
615 }
616
618 {
619 if (
620 p->
buf[0] ==
'F' && p->
buf[1] ==
'F' && p->
buf[2] ==
'M' &&
621 (p->
buf[3] ==
'1' || p->
buf[3] ==
'2'))
623 return 0;
624 }
625
635 };