Mercurial > libavformat.hg
annotate ffmdec.c @ 3754:8d267b43eaba libavformat
Move malloc() down until after all initializations, so that the resource is
only allocated if initialization worked. This means that on failure, we
don't have to deallocate it.
author | rbultje |
---|---|
date | Sat, 23 Aug 2008 18:46:30 +0000 |
parents | 255a1b73b4e3 |
children | 549a09cf23fe |
rev | line source |
---|---|
0 | 1 /* |
3348 | 2 * FFM (ffserver live feed) demuxer |
0 | 3 * Copyright (c) 2001 Fabrice Bellard. |
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 |
0 | 22 #include "avformat.h" |
3348 | 23 #include "ffm.h" |
3353
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
24 #ifdef CONFIG_FFSERVER |
0 | 25 #include <unistd.h> |
26 | |
3353
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
27 offset_t ffm_read_write_index(int fd) |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
28 { |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
29 uint8_t buf[8]; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
30 |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
31 lseek(fd, 8, SEEK_SET); |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
32 read(fd, buf, 8); |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
33 return AV_RB64(buf); |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
34 } |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
35 |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
36 void ffm_write_write_index(int fd, offset_t pos) |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
37 { |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
38 uint8_t buf[8]; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
39 int i; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
40 |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
41 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
|
42 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
|
43 lseek(fd, 8, SEEK_SET); |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
44 write(fd, buf, 8); |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
45 } |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
46 |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
47 void ffm_set_write_index(AVFormatContext *s, offset_t pos, offset_t file_size) |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
48 { |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
49 FFMContext *ffm = s->priv_data; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
50 ffm->write_index = pos; |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
51 ffm->file_size = file_size; |
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 #endif // CONFIG_FFSERVER |
b643008b9dcf
move ffserver specific functions up and only include unistd.h in this case
bcoudurier
parents:
3352
diff
changeset
|
54 |
0 | 55 static int ffm_is_avail_data(AVFormatContext *s, int size) |
56 { | |
57 FFMContext *ffm = s->priv_data; | |
58 offset_t pos, avail_size; | |
59 int len; | |
60 | |
61 len = ffm->packet_end - ffm->packet_ptr; | |
3347 | 62 if (size <= len) |
63 return 1; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
64 pos = url_ftell(s->pb); |
0 | 65 if (pos == ffm->write_index) { |
66 /* exactly at the end of stream */ | |
67 return 0; | |
68 } else if (pos < ffm->write_index) { | |
69 avail_size = ffm->write_index - pos; | |
70 } else { | |
71 avail_size = (ffm->file_size - pos) + (ffm->write_index - FFM_PACKET_SIZE); | |
72 } | |
73 avail_size = (avail_size / ffm->packet_size) * (ffm->packet_size - FFM_HEADER_SIZE) + len; | |
74 if (size <= avail_size) | |
75 return 1; | |
76 else | |
77 return 0; | |
78 } | |
79 | |
80 /* first is true if we read the frame header */ | |
81 static int ffm_read_data(AVFormatContext *s, | |
3434
3224f8d495a8
cosmetics, rename first to header, more explicit name
bcoudurier
parents:
3424
diff
changeset
|
82 uint8_t *buf, int size, int header) |
0 | 83 { |
84 FFMContext *ffm = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
85 ByteIOContext *pb = s->pb; |
0 | 86 int len, fill_size, size1, frame_offset; |
87 | |
88 size1 = size; | |
89 while (size > 0) { | |
90 redo: | |
91 len = ffm->packet_end - ffm->packet_ptr; | |
3354
5be8d622e458
return error if len is negative, prevent segfault
bcoudurier
parents:
3353
diff
changeset
|
92 if (len < 0) |
5be8d622e458
return error if len is negative, prevent segfault
bcoudurier
parents:
3353
diff
changeset
|
93 return -1; |
0 | 94 if (len > size) |
95 len = size; | |
96 if (len == 0) { | |
97 if (url_ftell(pb) == ffm->file_size) | |
98 url_fseek(pb, ffm->packet_size, SEEK_SET); | |
99 retry_read: | |
100 get_be16(pb); /* PACKET_ID */ | |
101 fill_size = get_be16(pb); | |
3492 | 102 ffm->dts = get_be64(pb); |
0 | 103 frame_offset = get_be16(pb); |
104 get_buffer(pb, ffm->packet, ffm->packet_size - FFM_HEADER_SIZE); | |
105 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
|
106 if (ffm->packet_end < ffm->packet || frame_offset < 0) |
537 | 107 return -1; |
0 | 108 /* if first packet or resynchronization packet, we must |
109 handle it specifically */ | |
110 if (ffm->first_packet || (frame_offset & 0x8000)) { | |
111 if (!frame_offset) { | |
112 /* This packet has no frame headers in it */ | |
113 if (url_ftell(pb) >= ffm->packet_size * 3) { | |
114 url_fseek(pb, -ffm->packet_size * 2, SEEK_CUR); | |
115 goto retry_read; | |
116 } | |
117 /* This is bad, we cannot find a valid frame header */ | |
118 return 0; | |
119 } | |
120 ffm->first_packet = 0; | |
3366 | 121 if ((frame_offset & 0x7fff) < FFM_HEADER_SIZE) |
537 | 122 return -1; |
0 | 123 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
|
124 if (!header) |
0 | 125 break; |
126 } else { | |
127 ffm->packet_ptr = ffm->packet; | |
128 } | |
129 goto redo; | |
130 } | |
131 memcpy(buf, ffm->packet_ptr, len); | |
132 buf += len; | |
133 ffm->packet_ptr += len; | |
134 size -= len; | |
3434
3224f8d495a8
cosmetics, rename first to header, more explicit name
bcoudurier
parents:
3424
diff
changeset
|
135 header = 0; |
0 | 136 } |
137 return size1 - size; | |
138 } | |
139 | |
3351
6063f3cf59e6
move DEBUG_SEEK definition before get_pts since func uses it
bcoudurier
parents:
3350
diff
changeset
|
140 //#define DEBUG_SEEK |
6063f3cf59e6
move DEBUG_SEEK definition before get_pts since func uses it
bcoudurier
parents:
3350
diff
changeset
|
141 |
3352
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
142 /* pos is between 0 and file_size - FFM_PACKET_SIZE. It is translated |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
143 by the write position inside this function */ |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
144 static void ffm_seek1(AVFormatContext *s, offset_t pos1) |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
145 { |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
146 FFMContext *ffm = s->priv_data; |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
147 ByteIOContext *pb = s->pb; |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
148 offset_t pos; |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
149 |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
150 pos = pos1 + ffm->write_index; |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
151 if (pos >= ffm->file_size) |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
152 pos -= (ffm->file_size - FFM_PACKET_SIZE); |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
153 #ifdef DEBUG_SEEK |
3360 | 154 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
|
155 #endif |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
156 url_fseek(pb, pos, SEEK_SET); |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
157 } |
10fe58a8cc8b
move ffm_seek1 before get_pts function since func uses it
bcoudurier
parents:
3351
diff
changeset
|
158 |
3492 | 159 static int64_t get_dts(AVFormatContext *s, offset_t pos) |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
160 { |
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
161 ByteIOContext *pb = s->pb; |
3492 | 162 int64_t dts; |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
163 |
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
164 ffm_seek1(s, pos); |
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
165 url_fskip(pb, 4); |
3492 | 166 dts = get_be64(pb); |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
167 #ifdef DEBUG_SEEK |
3360 | 168 av_log(s, AV_LOG_DEBUG, "pts=%0.6f\n", pts / 1000000.0); |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
169 #endif |
3492 | 170 return dts; |
3350
e092bf9b744f
move get_pts function to avoid useless declaration
bcoudurier
parents:
3348
diff
changeset
|
171 } |
0 | 172 |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
173 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
|
174 { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
175 FFMContext *ffm = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
176 ByteIOContext *pb = s->pb; |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
177 int64_t pts; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
178 //offset_t orig_write_index = ffm->write_index; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
179 offset_t pos_min, pos_max; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
180 int64_t pts_start; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
181 offset_t ptr = url_ftell(pb); |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
182 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
183 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
184 pos_min = 0; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
185 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
|
186 |
3492 | 187 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
|
188 |
3492 | 189 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
|
190 |
885 | 191 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
|
192 goto end; |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
193 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
194 ffm->write_index = FFM_PACKET_SIZE; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
195 |
3492 | 196 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
|
197 |
3492 | 198 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
|
199 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
200 if (pts - 100000 <= pts_start) { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
201 while (1) { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
202 offset_t newpos; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
203 int64_t newpts; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
204 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
205 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
|
206 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
207 if (newpos == pos_min) |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
208 break; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
209 |
3492 | 210 newpts = get_dts(s, newpos); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
211 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
212 if (newpts - 100000 <= pts) { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
213 pos_max = newpos; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
214 pts = newpts; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
215 } else { |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
216 pos_min = newpos; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
217 } |
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 += pos_max; |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
220 } |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
221 |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
222 //printf("Adjusted write index from %"PRId64" to %"PRId64": pts=%0.6f\n", orig_write_index, ffm->write_index, pts / 1000000.); |
3492 | 223 //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
|
224 |
390
3a40642dc4df
adjust_write_index() fix by ("Curi Fabio Eduardo (SFL)" <curif at TELEFONICA dot COM dot AR>)
michael
parents:
318
diff
changeset
|
225 end: |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
226 url_fseek(pb, ptr, SEEK_SET); |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
227 } |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
228 |
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
229 |
0 | 230 static int ffm_read_header(AVFormatContext *s, AVFormatParameters *ap) |
231 { | |
232 FFMContext *ffm = s->priv_data; | |
233 AVStream *st; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
234 ByteIOContext *pb = s->pb; |
0 | 235 AVCodecContext *codec; |
187 | 236 int i, nb_streams; |
65 | 237 uint32_t tag; |
0 | 238 |
239 /* header */ | |
240 tag = get_le32(pb); | |
241 if (tag != MKTAG('F', 'F', 'M', '1')) | |
242 goto fail; | |
243 ffm->packet_size = get_be32(pb); | |
244 if (ffm->packet_size != FFM_PACKET_SIZE) | |
245 goto fail; | |
246 ffm->write_index = get_be64(pb); | |
247 /* get also filesize */ | |
248 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
|
249 ffm->file_size = url_fsize(pb); |
318
54e915169d48
Add more resilience in reading ffm files. In particular, don't assume
philipjsg
parents:
277
diff
changeset
|
250 adjust_write_index(s); |
0 | 251 } else { |
1556 | 252 ffm->file_size = (UINT64_C(1) << 63) - 1; |
0 | 253 } |
254 | |
187 | 255 nb_streams = get_be32(pb); |
0 | 256 get_be32(pb); /* total bitrate */ |
257 /* read each stream */ | |
187 | 258 for(i=0;i<nb_streams;i++) { |
0 | 259 char rc_eq_buf[128]; |
260 | |
187 | 261 st = av_new_stream(s, 0); |
0 | 262 if (!st) |
263 goto fail; | |
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
|
264 s->streams[i] = st; |
885 | 265 |
468 | 266 av_set_pts_info(st, 64, 1, 1000000); |
885 | 267 |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
775
diff
changeset
|
268 codec = st->codec; |
0 | 269 /* 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
|
270 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
|
271 codec->codec_type = get_byte(pb); /* codec_type */ |
0 | 272 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
|
273 st->quality = get_be32(pb); |
0 | 274 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
|
275 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
|
276 codec->debug = get_be32(pb); |
0 | 277 /* specific info */ |
278 switch(codec->codec_type) { | |
279 case CODEC_TYPE_VIDEO: | |
743 | 280 codec->time_base.num = get_be32(pb); |
281 codec->time_base.den = get_be32(pb); | |
0 | 282 codec->width = get_be16(pb); |
283 codec->height = get_be16(pb); | |
284 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
|
285 codec->pix_fmt = get_be32(pb); |
0 | 286 codec->qmin = get_byte(pb); |
287 codec->qmax = get_byte(pb); | |
288 codec->max_qdiff = get_byte(pb); | |
289 codec->qcompress = get_be16(pb) / 10000.0; | |
290 codec->qblur = get_be16(pb) / 10000.0; | |
291 codec->bit_rate_tolerance = get_be32(pb); | |
34 | 292 codec->rc_eq = av_strdup(get_strz(pb, rc_eq_buf, sizeof(rc_eq_buf))); |
0 | 293 codec->rc_max_rate = get_be32(pb); |
294 codec->rc_min_rate = get_be32(pb); | |
295 codec->rc_buffer_size = get_be32(pb); | |
823 | 296 codec->i_quant_factor = av_int2dbl(get_be64(pb)); |
297 codec->b_quant_factor = av_int2dbl(get_be64(pb)); | |
298 codec->i_quant_offset = av_int2dbl(get_be64(pb)); | |
299 codec->b_quant_offset = av_int2dbl(get_be64(pb)); | |
0 | 300 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
|
301 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
|
302 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
|
303 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
|
304 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
|
305 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
|
306 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
|
307 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
|
308 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
|
309 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
|
310 codec->frame_skip_cmp = get_be32(pb); |
823 | 311 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
|
312 codec->codec_tag = get_be32(pb); |
3489 | 313 codec->thread_count = get_byte(pb); |
0 | 314 break; |
315 case CODEC_TYPE_AUDIO: | |
316 codec->sample_rate = get_be32(pb); | |
317 codec->channels = get_le16(pb); | |
318 codec->frame_size = get_le16(pb); | |
319 break; | |
320 default: | |
321 goto fail; | |
322 } | |
3441 | 323 if (codec->flags & CODEC_FLAG_GLOBAL_HEADER) { |
324 codec->extradata_size = get_be32(pb); | |
325 codec->extradata = av_malloc(codec->extradata_size); | |
326 if (!codec->extradata) | |
327 return AVERROR(ENOMEM); | |
328 get_buffer(pb, codec->extradata, codec->extradata_size); | |
329 } | |
0 | 330 } |
331 | |
332 /* get until end of block reached */ | |
333 while ((url_ftell(pb) % ffm->packet_size) != 0) | |
334 get_byte(pb); | |
335 | |
336 /* init packet demux */ | |
337 ffm->packet_ptr = ffm->packet; | |
338 ffm->packet_end = ffm->packet; | |
339 ffm->frame_offset = 0; | |
3492 | 340 ffm->dts = 0; |
0 | 341 ffm->read_state = READ_HEADER; |
342 ffm->first_packet = 1; | |
343 return 0; | |
344 fail: | |
345 for(i=0;i<s->nb_streams;i++) { | |
346 st = s->streams[i]; | |
347 if (st) { | |
348 av_free(st); | |
349 } | |
350 } | |
351 return -1; | |
352 } | |
353 | |
354 /* return < 0 if eof */ | |
355 static int ffm_read_packet(AVFormatContext *s, AVPacket *pkt) | |
356 { | |
357 int size; | |
358 FFMContext *ffm = s->priv_data; | |
359 int duration; | |
360 | |
361 switch(ffm->read_state) { | |
362 case READ_HEADER: | |
3442
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
363 if (!ffm_is_avail_data(s, FRAME_HEADER_SIZE+4)) { |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1556
diff
changeset
|
364 return AVERROR(EAGAIN); |
0 | 365 } |
3358 | 366 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
|
367 url_ftell(s->pb), s->pb->pos, ffm->write_index, ffm->file_size); |
885 | 368 if (ffm_read_data(s, ffm->header, FRAME_HEADER_SIZE, 1) != |
0 | 369 FRAME_HEADER_SIZE) |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1556
diff
changeset
|
370 return AVERROR(EAGAIN); |
3442
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
371 if (ffm->header[1] & FLAG_DTS) |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
372 if (ffm_read_data(s, ffm->header+16, 4, 1) != 4) |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
373 return AVERROR(EAGAIN); |
0 | 374 #if 0 |
3359 | 375 av_hexdump_log(s, AV_LOG_DEBUG, ffm->header, FRAME_HEADER_SIZE); |
0 | 376 #endif |
377 ffm->read_state = READ_DATA; | |
378 /* fall thru */ | |
379 case READ_DATA: | |
2222 | 380 size = AV_RB24(ffm->header + 2); |
0 | 381 if (!ffm_is_avail_data(s, size)) { |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1556
diff
changeset
|
382 return AVERROR(EAGAIN); |
0 | 383 } |
384 | |
2222 | 385 duration = AV_RB24(ffm->header + 5); |
0 | 386 |
387 av_new_packet(pkt, size); | |
388 pkt->stream_index = ffm->header[0]; | |
3307
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
389 if ((unsigned)pkt->stream_index >= s->nb_streams) { |
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
390 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
|
391 av_free_packet(pkt); |
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
392 ffm->read_state = READ_HEADER; |
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
393 return AVERROR(EAGAIN); |
e4ff879325c0
check pkt stream index before returning packet, prevent segfault
bcoudurier
parents:
2915
diff
changeset
|
394 } |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2222
diff
changeset
|
395 pkt->pos = url_ftell(s->pb); |
0 | 396 if (ffm->header[1] & FLAG_KEY_FRAME) |
397 pkt->flags |= PKT_FLAG_KEY; | |
398 | |
399 ffm->read_state = READ_HEADER; | |
400 if (ffm_read_data(s, pkt->data, size, 0) != size) { | |
401 /* bad case: desynchronized packet. we cancel all the packet loading */ | |
402 av_free_packet(pkt); | |
1787
eb16c64144ee
This fixes error handling for BeOS, removing the need for some ifdefs.
mmu_man
parents:
1556
diff
changeset
|
403 return AVERROR(EAGAIN); |
0 | 404 } |
3442
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
405 pkt->pts = AV_RB64(ffm->header+8); |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
406 if (ffm->header[1] & FLAG_DTS) |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
407 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
|
408 else |
a6f4d53b738d
pass dts and pts through ffm, should fix streaming b frames
bcoudurier
parents:
3441
diff
changeset
|
409 pkt->dts = pkt->pts; |
0 | 410 pkt->duration = duration; |
411 break; | |
412 } | |
413 return 0; | |
414 } | |
415 | |
416 /* seek to a given time in the file. The file read pointer is | |
2915 | 417 positioned at or before pts. XXX: the following code is quite |
0 | 418 approximative */ |
558 | 419 static int ffm_seek(AVFormatContext *s, int stream_index, int64_t wanted_pts, int flags) |
0 | 420 { |
421 FFMContext *ffm = s->priv_data; | |
422 offset_t pos_min, pos_max, pos; | |
65 | 423 int64_t pts_min, pts_max, pts; |
0 | 424 double pos1; |
425 | |
426 #ifdef DEBUG_SEEK | |
3360 | 427 av_log(s, AV_LOG_DEBUG, "wanted_pts=%0.6f\n", wanted_pts / 1000000.0); |
0 | 428 #endif |
429 /* find the position using linear interpolation (better than | |
430 dichotomy in typical cases) */ | |
431 pos_min = 0; | |
432 pos_max = ffm->file_size - 2 * FFM_PACKET_SIZE; | |
433 while (pos_min <= pos_max) { | |
3492 | 434 pts_min = get_dts(s, pos_min); |
435 pts_max = get_dts(s, pos_max); | |
0 | 436 /* linear interpolation */ |
437 pos1 = (double)(pos_max - pos_min) * (double)(wanted_pts - pts_min) / | |
438 (double)(pts_max - pts_min); | |
65 | 439 pos = (((int64_t)pos1) / FFM_PACKET_SIZE) * FFM_PACKET_SIZE; |
0 | 440 if (pos <= pos_min) |
441 pos = pos_min; | |
442 else if (pos >= pos_max) | |
443 pos = pos_max; | |
3492 | 444 pts = get_dts(s, pos); |
0 | 445 /* check if we are lucky */ |
446 if (pts == wanted_pts) { | |
447 goto found; | |
448 } else if (pts > wanted_pts) { | |
449 pos_max = pos - FFM_PACKET_SIZE; | |
450 } else { | |
451 pos_min = pos + FFM_PACKET_SIZE; | |
452 } | |
453 } | |
558 | 454 pos = (flags & AVSEEK_FLAG_BACKWARD) ? pos_min : pos_max; |
0 | 455 if (pos > 0) |
456 pos -= FFM_PACKET_SIZE; | |
457 found: | |
458 ffm_seek1(s, pos); | |
3437 | 459 |
460 /* reset read state */ | |
461 ffm->read_state = READ_HEADER; | |
462 ffm->packet_ptr = ffm->packet; | |
463 ffm->packet_end = ffm->packet; | |
464 ffm->first_packet = 1; | |
465 | |
0 | 466 return 0; |
467 } | |
468 | |
469 static int ffm_probe(AVProbeData *p) | |
470 { | |
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
|
471 if ( |
885 | 472 p->buf[0] == 'F' && p->buf[1] == 'F' && p->buf[2] == 'M' && |
0 | 473 p->buf[3] == '1') |
474 return AVPROBE_SCORE_MAX + 1; | |
475 return 0; | |
476 } | |
477 | |
1169 | 478 AVInputFormat ffm_demuxer = { |
0 | 479 "ffm", |
3603 | 480 NULL_IF_CONFIG_SMALL("FFM (FFserver live feed) format"), |
0 | 481 sizeof(FFMContext), |
482 ffm_probe, | |
483 ffm_read_header, | |
484 ffm_read_packet, | |
3481 | 485 NULL, |
0 | 486 ffm_seek, |
487 }; |