Mercurial > libavformat.hg
annotate ffmdec.c @ 5836:2997c88028cd libavformat
Move the probe loop from av_open_input_file() into its own method
av_probe_input_buffer() so that it can be reused. Here are a few
differences to the original way things were probed:
- maximum probe buffer size can be specified as a parameter.
- offset within the stream to probe from can be specified as a parameter.
- instead of seeking back to the start each time a probe fails, stream
data is appended to the reallocated buffer. This lowers the amount
of data read from the stream (there is no repetition) and results in
fewer closed and reopened streams (when seeking fails).
New attempt after r22296, which was revert in r22315 due to a FATE
failure.
See the thread:
Subject: [FFmpeg-devel] [PATCH] Move av_open_input_file probe loop to its own method
Date: 2010-03-05 03:23:57 GMT
Patch by Micah F. Galizia printf("%s%s@%s.%s", "micah", "galizia", "gmail", "com").
author | stefano |
---|---|
date | Sun, 14 Mar 2010 22:40:16 +0000 |
parents | cc7800226186 |
children | 98bd293526db |
rev | line source |
---|---|
0 | 1 /* |
3348 | 2 * FFM (ffserver live feed) demuxer |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4206
diff
changeset
|
3 * Copyright (c) 2001 Fabrice Bellard |
0 | 4 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
0 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 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 | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1169
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
887
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
3348 | 21 |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
3973
diff
changeset
|
22 #include "libavutil/intreadwrite.h" |
0 | 23 #include "avformat.h" |
3348 | 24 #include "ffm.h" |
4206 | 25 #if CONFIG_FFSERVER |
0 | 26 #include <unistd.h> |
27 | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
28 int64_t ffm_read_write_index(int fd) |
3353
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
29 { |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
30 uint8_t buf[8]; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
31 |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
32 lseek(fd, 8, SEEK_SET); |
4459 | 33 if (read(fd, buf, 8) != 8) |
34 return AVERROR(EIO); | |
3353
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
35 return AV_RB64(buf); |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
36 } |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
37 |
4458
f734aba9452e
Change ffm_write_write_index to return int, and return if error occured.
bcoudurier
parents:
4334
diff
changeset
|
38 int ffm_write_write_index(int fd, int64_t pos) |
3353
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
39 { |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
40 uint8_t buf[8]; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
41 int i; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
42 |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
43 for(i=0;i<8;i++) |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
44 buf[i] = (pos >> (56 - i * 8)) & 0xff; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
45 lseek(fd, 8, SEEK_SET); |
4458
f734aba9452e
Change ffm_write_write_index to return int, and return if error occured.
bcoudurier
parents:
4334
diff
changeset
|
46 if (write(fd, buf, 8) != 8) |
f734aba9452e
Change ffm_write_write_index to return int, and return if error occured.
bcoudurier
parents:
4334
diff
changeset
|
47 return AVERROR(EIO); |
f734aba9452e
Change ffm_write_write_index to return int, and return if error occured.
bcoudurier
parents:
4334
diff
changeset
|
48 return 8; |
3353
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
49 } |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
50 |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
51 void ffm_set_write_index(AVFormatContext *s, int64_t pos, int64_t file_size) |
3353
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
52 { |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
53 FFMContext *ffm = s->priv_data; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
54 ffm->write_index = pos; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
55 ffm->file_size = file_size; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
56 } |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
57 #endif // CONFIG_FFSERVER |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
58 |
0 | 59 static int ffm_is_avail_data(AVFormatContext *s, int size) |
60 { | |
61 FFMContext *ffm = s->priv_data; | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
62 int64_t pos, avail_size; |
0 | 63 int len; |
64 | |
65 len = ffm->packet_end - ffm->packet_ptr; | |
3347 | 66 if (size <= len) |
67 return 1; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
68 pos = url_ftell(s->pb); |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
69 if (!ffm->write_index) { |
4757 | 70 if (pos == ffm->file_size) |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
71 return AVERROR_EOF; |
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
72 avail_size = ffm->file_size - pos; |
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
73 } else { |
0 | 74 if (pos == ffm->write_index) { |
75 /* exactly at the end of stream */ | |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
76 return AVERROR(EAGAIN); |
0 | 77 } else if (pos < ffm->write_index) { |
78 avail_size = ffm->write_index - pos; | |
79 } else { | |
80 avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE); | |
81 } | |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
82 } |
0 | 83 avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len; |
84 if (size <= avail_size) | |
85 return 1; | |
86 else | |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
87 return AVERROR(EAGAIN); |
0 | 88 } |
89 | |
4758 | 90 static int ffm_resync(AVFormatContext *s, int state) |
91 { | |
92 av_log(s, AV_LOG_ERROR, "resyncing\n"); | |
93 while (state != PACKET_ID) { | |
94 if (url_feof(s->pb)) { | |
95 av_log(s, AV_LOG_ERROR, "cannot find FFM syncword\n"); | |
96 return -1; | |
97 } | |
98 state = (state << 8) | get_byte(s->pb); | |
99 } | |
100 return 0; | |
101 } | |
102 | |
0 | 103 /* first is true if we read the frame header */ |
104 static int ffm_read_data(AVFormatContext *s, | |
3434
3224f8d495a8
cosmetics, rename first to header, more explicit name
bcoudurier
parents:
3424
diff
changeset
|
105 uint8_t *buf, int size, int header) |
0 | 106 { |
107 FFMContext *ffm = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
108 ByteIOContext *pb = s->pb; |
4758 | 109 int len, fill_size, size1, frame_offset, id; |
0 | 110 |
111 size1 = size; | |
112 while (size > 0) { | |
113 redo: | |
114 len = ffm->packet_end - ffm->packet_ptr; | |
3354
5be8d622e458
return error if len is negative, prevent segfault
bcoudurier
parents:
3353
diff
changeset
|
115 if (len < 0) |
5be8d622e458
return error if len is negative, prevent segfault
bcoudurier
parents:
3353
diff
changeset
|
116 return -1; |
0 | 117 if (len > size) |
118 len = size; | |
119 if (len == 0) { | |
120 if (url_ftell(pb) == ffm->file_size) | |
121 url_fseek(pb, ffm->packet_size, SEEK_SET); | |
122 retry_read: | |
4758 | 123 id = get_be16(pb); /* PACKET_ID */ |
124 if (id != PACKET_ID) | |
125 if (ffm_resync(s, id) < 0) | |
126 return -1; | |
0 | 127 fill_size = get_be16(pb); |
3492 | 128 ffm->dts = get_be64(pb); |
0 | 129 frame_offset = get_be16(pb); |
130 get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE); | |
131 ffm->packet_end = ffm->packet + (ffm->packet_size - FFM_HEADER_SIZE - fill_size); | |
3355
fa366fc51861
return error if frame_offset is negative, prevent segfault
bcoudurier
parents:
3354
diff
changeset
|
132 if (ffm->packet_end < ffm->packet || frame_offset < 0) |
537 | 133 return -1; |
0 | 134 /* if first packet or resynchronization packet, we must |
135 handle it specifically */ | |
136 if (ffm->first_packet || (frame_offset & 0x8000)) { | |
137 if (!frame_offset) { | |
138 /* This packet has no frame headers in it */ | |
139 if (url_ftell(pb) >= ffm->packet_size * 3) { | |
140 url_fseek(pb, -ffm->packet_size * 2, SEEK_CUR); | |
141 goto retry_read; | |
142 } | |
143 /* This is bad, we cannot find a valid frame header */ | |
144 return 0; | |
145 } | |
146 ffm->first_packet = 0; | |
3366 | 147 if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE) |
537 | 148 return -1; |
0 | 149 ffm->packet_ptr = ffm->packet + (frame_offset & 0x7fff) - FFM_HEADER_SIZE; |
3434
3224f8d495a8
cosmetics, rename first to header, more explicit name
bcoudurier
parents:
3424
diff
changeset
|
150 if (!header) |
0 | 151 break; |
152 } else { | |
153 ffm->packet_ptr = ffm->packet; | |
154 } | |
155 goto redo; | |
156 } | |
157 memcpy(buf, ffm->packet_ptr, len); | |
158 buf += len; | |
159 ffm->packet_ptr += len; | |
160 size -= len; | |
3434
3224f8d495a8
cosmetics, rename first to header, more explicit name
bcoudurier
parents:
3424
diff
changeset
|
161 header = 0; |
0 | 162 } |
163 return size1 - size; | |
164 } | |
165 | |
3351
6063f3cf59e6
move DEBUG_SEEK definition before get_pts since func uses it
bcoudurier
parents:
3350
diff
changeset
|
166 //#define DEBUG_SEEK |
6063f3cf59e6
move DEBUG_SEEK definition before get_pts since func uses it
bcoudurier
parents:
3350
diff
changeset
|
167 |
4762 | 168 /* ensure that acutal seeking happens between FFM_PACKET_SIZE |
169 and file_size - FFM_PACKET_SIZE */ | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
170 static void ffm_seek1(AVFormatContext *s, int64_t pos1) |
3352
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
171 { |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
172 FFMContext *ffm = s->priv_data; |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
173 ByteIOContext *pb = s->pb; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
174 int64_t pos; |
3352
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
175 |
4762 | 176 pos = FFMIN(pos1, ffm->file_size - FFM_PACKET_SIZE); |
177 pos = FFMAX(pos, FFM_PACKET_SIZE); | |
3352
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
178 #ifdef DEBUG_SEEK |
3360 | 179 av_log(s, AV_LOG_DEBUG, "seek to %"PRIx64" -> %"PRIx64"\n", pos1, pos); |
3352
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
180 #endif |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
181 url_fseek(pb, pos, SEEK_SET); |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
182 } |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
183 |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
184 static int64_t get_dts(AVFormatContext *s, int64_t pos) |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
185 { |
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
186 ByteIOContext *pb = s->pb; |
3492 | 187 int64_t dts; |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
188 |
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
189 ffm_seek1(s, pos); |
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
190 url_fskip(pb, 4); |
3492 | 191 dts = get_be64(pb); |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
192 #ifdef DEBUG_SEEK |
4763 | 193 av_log(s, AV_LOG_DEBUG, "dts=%0.6f\n", dts / 1000000.0); |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
194 #endif |
3492 | 195 return dts; |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
196 } |
0 | 197 |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
198 static void adjust_write_index(AVFormatContext *s) |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
199 { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
200 FFMContext *ffm = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
201 ByteIOContext *pb = s->pb; |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
202 int64_t pts; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
203 //int64_t orig_write_index = ffm->write_index; |
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
204 int64_t pos_min, pos_max; |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
205 int64_t pts_start; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
206 int64_t ptr = url_ftell(pb); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
207 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
208 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
209 pos_min = 0; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
210 pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
211 |
3492 | 212 pts_start = get_dts(s, pos_min); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
213 |
3492 | 214 pts = get_dts(s, pos_max); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
215 |
885 | 216 if (pts - 100000 > pts_start) |
390
3a40642dc4df
adjust_write_index() fix by ("Curi Fabio Eduardo (SFL)" <curif at TELEFONICA dot COM dot AR>)
michael
parents:
318
diff
changeset
|
217 goto end; |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
218 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
219 ffm->write_index = FFM_PACKET_SIZE; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
220 |
3492 | 221 pts_start = get_dts(s, pos_min); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
222 |
3492 | 223 pts = get_dts(s, pos_max); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
224 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
225 if (pts - 100000 <= pts_start) { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
226 while (1) { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
227 int64_t newpos; |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
228 int64_t newpts; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
229 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
230 newpos = ((pos_max + pos_min) / (2 * FFM_PACKET_SIZE)) * FFM_PACKET_SIZE; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
231 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
232 if (newpos == pos_min) |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
233 break; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
234 |
3492 | 235 newpts = get_dts(s, newpos); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
236 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
237 if (newpts - 100000 <= pts) { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
238 pos_max = newpos; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
239 pts = newpts; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
240 } else { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
241 pos_min = newpos; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
242 } |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
243 } |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
244 ffm->write_index += pos_max; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
245 } |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
246 |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
247 //printf("Adjusted write index from %"PRId64" to %"PRId64": pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.); |
3492 | 248 //printf("pts range %0.6f - %0.6f\n", get_dts(s, 0) / 1000000. , get_dts(s, ffm->file_size - 2 * FFM_PACKET_SIZE) / 1000000. ); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
249 |
390
3a40642dc4df
adjust_write_index() fix by ("Curi Fabio Eduardo (SFL)" <curif at TELEFONICA dot COM dot AR>)
michael
parents:
318
diff
changeset
|
250 end: |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
251 url_fseek(pb, ptr, SEEK_SET); |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
252 } |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
253 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
254 |
0 | 255 static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) |
256 { | |
257 FFMContext *ffm = s->priv_data; | |
258 AVStream *st; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
259 ByteIOContext *pb = s->pb; |
0 | 260 AVCodecContext *codec; |
187 | 261 int i, nb_streams; |
65 | 262 uint32_t tag; |
0 | 263 |
264 /* header */ | |
265 tag = get_le32(pb); | |
266 if (tag != MKTAG('F', 'F', 'M', '1')) | |
267 goto fail; | |
268 ffm->packet_size = get_be32(pb); | |
269 if (ffm->packet_size != FFM_PACKET_SIZE) | |
270 goto fail; | |
271 ffm->write_index = get_be64(pb); | |
272 /* get also filesize */ | |
273 if (!url_is_streamed(pb)) { | |
764
cdb845a57ae4
drop most url_fileno() calls (allows to use ByteIOContext directly in caller apps instead of URLProtocol)
aurel
parents:
751
diff
changeset
|
274 ffm->file_size = url_fsize(pb); |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
275 if (ffm->write_index) |
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
276 adjust_write_index(s); |
0 | 277 } else { |
1556 | 278 ffm->file_size = (UINT64_C(1) << 63) - 1; |
0 | 279 } |
280 | |
187 | 281 nb_streams = get_be32(pb); |
0 | 282 get_be32(pb); /* total bitrate */ |
283 /* read each stream */ | |
187 | 284 for(i=0;i<nb_streams;i++) { |
0 | 285 char rc_eq_buf[128]; |
286 | |
187 | 287 st = av_new_stream(s, 0); |
0 | 288 if (!st) |
289 goto fail; | |
885 | 290 |
468 | 291 av_set_pts_info(st, 64, 1, 1000000); |
885 | 292 |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
293 codec = st->codec; |
0 | 294 /* generic info */ |
862
aa0abab5e320
fix feed read_header, avoid using put_tag in write_header, to be consistent with read_header, also some minor cosmetics
alex
parents:
858
diff
changeset
|
295 codec->codec_id = get_be32(pb); |
aa0abab5e320
fix feed read_header, avoid using put_tag in write_header, to be consistent with read_header, also some minor cosmetics
alex
parents:
858
diff
changeset
|
296 codec->codec_type = get_byte(pb); /* codec_type */ |
0 | 297 codec->bit_rate = get_be32(pb); |
862
aa0abab5e320
fix feed read_header, avoid using put_tag in write_header, to be consistent with read_header, also some minor cosmetics
alex
parents:
858
diff
changeset
|
298 st->quality = get_be32(pb); |
0 | 299 codec->flags = get_be32(pb); |
744
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
300 codec->flags2 = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
301 codec->debug = get_be32(pb); |
0 | 302 /* specific info */ |
303 switch(codec->codec_type) { | |
304 case CODEC_TYPE_VIDEO: | |
743 | 305 codec->time_base.num = get_be32(pb); |
306 codec->time_base.den = get_be32(pb); | |
0 | 307 codec->width = get_be16(pb); |
308 codec->height = get_be16(pb); | |
309 codec->gop_size = get_be16(pb); | |
744
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
310 codec->pix_fmt = get_be32(pb); |
0 | 311 codec->qmin = get_byte(pb); |
312 codec->qmax = get_byte(pb); | |
313 codec->max_qdiff = get_byte(pb); | |
314 codec->qcompress = get_be16(pb) / 10000.0; | |
315 codec->qblur = get_be16(pb) / 10000.0; | |
316 codec->bit_rate_tolerance = get_be32(pb); | |
34 | 317 codec->rc_eq = av_strdup(get_strz(pb, rc_eq_buf, sizeof(rc_eq_buf))); |
0 | 318 codec->rc_max_rate = get_be32(pb); |
319 codec->rc_min_rate = get_be32(pb); | |
320 codec->rc_buffer_size = get_be32(pb); | |
823 | 321 codec->i_quant_factor = av_int2dbl(get_be64(pb)); |
322 codec->b_quant_factor = av_int2dbl(get_be64(pb)); | |
323 codec->i_quant_offset = av_int2dbl(get_be64(pb)); | |
324 codec->b_quant_offset = av_int2dbl(get_be64(pb)); | |
0 | 325 codec->dct_algo = get_be32(pb); |
744
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
326 codec->strict_std_compliance = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
327 codec->max_b_frames = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
328 codec->luma_elim_threshold = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
329 codec->chroma_elim_threshold = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
330 codec->mpeg_quant = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
331 codec->intra_dc_precision = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
332 codec->me_method = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
333 codec->mb_decision = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
334 codec->nsse_weight = get_be32(pb); |
da5b3b9e898e
Add in many fields that have been added to the Codec structure. This means
philipjsg
parents:
743
diff
changeset
|
335 codec->frame_skip_cmp = get_be32(pb); |
823 | 336 codec->rc_buffer_aggressivity = av_int2dbl(get_be64(pb)); |
1809
491581a2b9a7
codec_tag settable via VideoTag, and transmit codec_tag in ffm
alex
parents:
1787
diff
changeset
|
337 codec->codec_tag = get_be32(pb); |
3489 | 338 codec->thread_count = get_byte(pb); |
5385
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
339 codec->coder_type = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
340 codec->me_cmp = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
341 codec->partitions = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
342 codec->me_subpel_quality = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
343 codec->me_range = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
344 codec->keyint_min = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
345 codec->scenechange_threshold = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
346 codec->b_frame_strategy = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
347 codec->qcompress = av_int2dbl(get_be64(pb)); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
348 codec->qblur = av_int2dbl(get_be64(pb)); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
349 codec->max_qdiff = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
350 codec->refs = get_be32(pb); |
de6eb16c2b5b
Update ffserver to include all basic x264 parameters in .ffm files.
darkshikari
parents:
4846
diff
changeset
|
351 codec->directpred = get_be32(pb); |
0 | 352 break; |
353 case CODEC_TYPE_AUDIO: | |
354 codec->sample_rate = get_be32(pb); | |
355 codec->channels = get_le16(pb); | |
356 codec->frame_size = get_le16(pb); | |
5463
08abadf5350b
Fix breakage introduced by setting the sample_fmt to SAMPLE_FMT_NONE (r20623). This makes
banan
parents:
5385
diff
changeset
|
357 codec->sample_fmt = get_le16(pb); |
0 | 358 break; |
359 default: | |
360 goto fail; | |
361 } | |
3441 | 362 if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { |
363 codec->extradata_size = get_be32(pb); | |
364 codec->extradata = av_malloc(codec->extradata_size); | |
365 if (!codec->extradata) | |
366 return AVERROR(ENOMEM); | |
367 get_buffer(pb, codec->extradata, codec->extradata_size); | |
368 } | |
0 | 369 } |
370 | |
371 /* get until end of block reached */ | |
372 while ((url_ftell(pb) % ffm->packet_size) != 0) | |
373 get_byte(pb); | |
374 | |
375 /* init packet demux */ | |
376 ffm->packet_ptr = ffm->packet; | |
377 ffm->packet_end = ffm->packet; | |
378 ffm->frame_offset = 0; | |
3492 | 379 ffm->dts = 0; |
0 | 380 ffm->read_state = READ_HEADER; |
381 ffm->first_packet = 1; | |
382 return 0; | |
383 fail: | |
384 for(i=0;i<s->nb_streams;i++) { | |
385 st = s->streams[i]; | |
386 if (st) { | |
387 av_free(st); | |
388 } | |
389 } | |
390 return -1; | |
391 } | |
392 | |
393 /* return < 0 if eof */ | |
394 static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt) | |
395 { | |
396 int size; | |
397 FFMContext *ffm = s->priv_data; | |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
398 int duration, ret; |
4334
376664156fe2
return eof/error if only ffm header has been written, should fix #815
bcoudurier
parents:
4251
diff
changeset
|
399 |
0 | 400 switch(ffm->read_state) { |
401 case READ_HEADER: | |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
402 if ((ret = ffm_is_avail_data(s, FRAME_HEADER_SIZE+4)) < 0) |
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
403 return ret; |
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
404 |
3358 | 405 dprintf(s, "pos=%08"PRIx64" spos=%"PRIx64", write_index=%"PRIx64" size=%"PRIx64"\n", |
3444
59989e1a2154
Fix compilation with -DDEBUG, patch by Albert Astals Cid, aastals tv-wan es.
diego
parents:
3442
diff
changeset
|
406 url_ftell(s->pb), s->pb->pos, ffm->write_index, ffm->file_size); |
885 | 407 if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) != |
0 | 408 FRAME_HEADER_SIZE) |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
409 return -1; |
3442
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
410 if (ffm->header[1] & FLAG_DTS) |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
411 if (ffm_read_data(s, ffm->header+16, 4, 1) != 4) |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
412 return -1; |
0 | 413 #if 0 |
3359 | 414 av_hexdump_log(s, AV_LOG_DEBUG, ffm->header, FRAME_HEADER_SIZE); |
0 | 415 #endif |
416 ffm->read_state = READ_DATA; | |
417 /* fall thru */ | |
418 case READ_DATA: | |
2222 | 419 size = AV_RB24(ffm->header + 2); |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
420 if ((ret = ffm_is_avail_data(s, size)) < 0) |
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
421 return ret; |
0 | 422 |
2222 | 423 duration = AV_RB24(ffm->header + 5); |
0 | 424 |
425 av_new_packet(pkt, size); | |
426 pkt->stream_index = ffm->header[0]; | |
3307
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
427 if ((unsigned)pkt->stream_index >= s->nb_streams) { |
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
428 av_log(s, AV_LOG_ERROR, "invalid stream index %d\n", pkt->stream_index); |
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
429 av_free_packet(pkt); |
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
430 ffm->read_state = READ_HEADER; |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
431 return -1; |
3307
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
432 } |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
433 pkt->pos = url_ftell(s->pb); |
0 | 434 if (ffm->header[1] & FLAG_KEY_FRAME) |
435 pkt->flags |= PKT_FLAG_KEY; | |
436 | |
437 ffm->read_state = READ_HEADER; | |
438 if (ffm_read_data(s, pkt->data, size, 0) != size) { | |
439 /* bad case: desynchronized packet. we cancel all the packet loading */ | |
440 av_free_packet(pkt); | |
4756
d426504e401b
do not write ffm write index by default, detect if file is being written and return EOF
bcoudurier
parents:
4459
diff
changeset
|
441 return -1; |
0 | 442 } |
3442
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
443 pkt->pts = AV_RB64(ffm->header+8); |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
444 if (ffm->header[1] & FLAG_DTS) |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
445 pkt->dts = pkt->pts - AV_RB32(ffm->header+16); |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
446 else |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
447 pkt->dts = pkt->pts; |
0 | 448 pkt->duration = duration; |
449 break; | |
450 } | |
451 return 0; | |
452 } | |
453 | |
454 /* seek to a given time in the file. The file read pointer is | |
2915 | 455 positioned at or before pts. XXX: the following code is quite |
0 | 456 approximative */ |
558 | 457 static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags) |
0 | 458 { |
459 FFMContext *ffm = s->priv_data; | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3603
diff
changeset
|
460 int64_t pos_min, pos_max, pos; |
65 | 461 int64_t pts_min, pts_max, pts; |
0 | 462 double pos1; |
463 | |
464 #ifdef DEBUG_SEEK | |
3360 | 465 av_log(s, AV_LOG_DEBUG, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0); |
0 | 466 #endif |
467 /* find the position using linear interpolation (better than | |
468 dichotomy in typical cases) */ | |
4762 | 469 pos_min = FFM_PACKET_SIZE; |
470 pos_max = ffm->file_size - FFM_PACKET_SIZE; | |
0 | 471 while (pos_min <= pos_max) { |
3492 | 472 pts_min = get_dts(s, pos_min); |
473 pts_max = get_dts(s, pos_max); | |
0 | 474 /* linear interpolation */ |
475 pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) / | |
476 (double)(pts_max - pts_min); | |
65 | 477 pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE; |
0 | 478 if (pos <= pos_min) |
479 pos = pos_min; | |
480 else if (pos >= pos_max) | |
481 pos = pos_max; | |
3492 | 482 pts = get_dts(s, pos); |
0 | 483 /* check if we are lucky */ |
484 if (pts == wanted_pts) { | |
485 goto found; | |
486 } else if (pts > wanted_pts) { | |
487 pos_max = pos - FFM_PACKET_SIZE; | |
488 } else { | |
489 pos_min = pos + FFM_PACKET_SIZE; | |
490 } | |
491 } | |
558 | 492 pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; |
4762 | 493 |
0 | 494 found: |
495 ffm_seek1(s, pos); | |
3437 | 496 |
497 /* reset read state */ | |
498 ffm->read_state = READ_HEADER; | |
499 ffm->packet_ptr = ffm->packet; | |
500 ffm->packet_end = ffm->packet; | |
501 ffm->first_packet = 1; | |
502 | |
0 | 503 return 0; |
504 } | |
505 | |
506 static int ffm_probe(AVProbeData *p) | |
507 { | |
2001
1a3c9056982a
allocate 32 extra bytes at the end of the probe buffer and remove most probe buf_size checks
michael
parents:
1809
diff
changeset
|
508 if ( |
885 | 509 p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' && |
0 | 510 p->buf[3] == '1') |
511 return AVPROBE_SCORE_MAX + 1; | |
512 return 0; | |
513 } | |
514 | |
5806 | 515 static int ffm_close(AVFormatContext *s) |
5805 | 516 { |
517 int i; | |
518 | |
519 for (i = 0; i < s->nb_streams; i++) | |
520 av_freep(&s->streams[i]->codec->rc_eq); | |
5806 | 521 |
522 return 0; | |
5805 | 523 } |
524 | |
1169 | 525 AVInputFormat ffm_demuxer = { |
0 | 526 "ffm", |
3603 | 527 NULL_IF_CONFIG_SMALL("FFM (FFserver live feed) format"), |
0 | 528 sizeof(FFMContext), |
529 ffm_probe, | |
530 ffm_read_header, | |
531 ffm_read_packet, | |
5805 | 532 ffm_close, |
0 | 533 ffm_seek, |
534 }; |