Revision d3964da2
libavformat/applehttp.c | ||
---|---|---|
61 | 61 |
AVPacket pkt; |
62 | 62 |
int stream_offset; |
63 | 63 |
|
64 |
int finished; |
|
65 |
int target_duration; |
|
64 | 66 |
int start_seq_no; |
65 | 67 |
int n_segments; |
66 | 68 |
struct segment **segments; |
... | ... | |
68 | 70 |
}; |
69 | 71 |
|
70 | 72 |
typedef struct AppleHTTPContext { |
71 |
int target_duration; |
|
72 |
int finished; |
|
73 | 73 |
int n_variants; |
74 | 74 |
struct variant **variants; |
75 | 75 |
int cur_seq_no; |
... | ... | |
170 | 170 |
goto fail; |
171 | 171 |
} |
172 | 172 |
|
173 |
if (var) |
|
173 |
if (var) {
|
|
174 | 174 |
free_segment_list(var); |
175 |
c->finished = 0; |
|
175 |
var->finished = 0; |
|
176 |
} |
|
176 | 177 |
while (!in->eof_reached) { |
177 | 178 |
read_chomp_line(in, line, sizeof(line)); |
178 | 179 |
if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) { |
... | ... | |
182 | 183 |
&info); |
183 | 184 |
bandwidth = atoi(info.bandwidth); |
184 | 185 |
} else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { |
185 |
c->target_duration = atoi(ptr); |
|
186 |
if (!var) { |
|
187 |
var = new_variant(c, 0, url, NULL); |
|
188 |
if (!var) { |
|
189 |
ret = AVERROR(ENOMEM); |
|
190 |
goto fail; |
|
191 |
} |
|
192 |
} |
|
193 |
var->target_duration = atoi(ptr); |
|
186 | 194 |
} else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { |
187 | 195 |
if (!var) { |
188 | 196 |
var = new_variant(c, 0, url, NULL); |
... | ... | |
193 | 201 |
} |
194 | 202 |
var->start_seq_no = atoi(ptr); |
195 | 203 |
} else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { |
196 |
c->finished = 1; |
|
204 |
if (var) |
|
205 |
var->finished = 1; |
|
197 | 206 |
} else if (av_strstart(line, "#EXTINF:", &ptr)) { |
198 | 207 |
is_segment = 1; |
199 | 208 |
duration = atoi(ptr); |
... | ... | |
268 | 277 |
|
269 | 278 |
/* If this isn't a live stream, calculate the total duration of the |
270 | 279 |
* stream. */ |
271 |
if (c->finished) { |
|
280 |
if (c->variants[0]->finished) {
|
|
272 | 281 |
int64_t duration = 0; |
273 | 282 |
for (i = 0; i < c->variants[0]->n_segments; i++) |
274 | 283 |
duration += c->variants[0]->segments[i]->duration; |
... | ... | |
306 | 315 |
c->cur_seq_no = c->max_start_seq; |
307 | 316 |
/* If this is a live stream with more than 3 segments, start at the |
308 | 317 |
* third last segment. */ |
309 |
if (!c->finished && c->min_end_seq - c->max_start_seq > 3) |
|
318 |
if (!c->variants[0]->finished && c->min_end_seq - c->max_start_seq > 3)
|
|
310 | 319 |
c->cur_seq_no = c->min_end_seq - 2; |
311 | 320 |
|
312 | 321 |
return 0; |
... | ... | |
326 | 335 |
return 0; |
327 | 336 |
} |
328 | 337 |
if (c->cur_seq_no - var->start_seq_no >= var->n_segments) |
329 |
return c->finished ? AVERROR_EOF : 0; |
|
338 |
return c->variants[0]->finished ? AVERROR_EOF : 0;
|
|
330 | 339 |
ret = avio_open(&var->pb, |
331 | 340 |
var->segments[c->cur_seq_no - var->start_seq_no]->url, |
332 | 341 |
URL_RDONLY); |
... | ... | |
390 | 399 |
} else if (!var->pb && var->needed) { |
391 | 400 |
if (first) |
392 | 401 |
av_log(s, AV_LOG_DEBUG, "Opening variant stream %d\n", i); |
393 |
if (first && !c->finished)
|
|
402 |
if (first && !var->finished)
|
|
394 | 403 |
if ((ret = parse_playlist(c, var->url, var, NULL)) < 0) |
395 | 404 |
return ret; |
396 | 405 |
ret = open_variant(c, var, first); |
... | ... | |
442 | 451 |
first = 0; |
443 | 452 |
c->cur_seq_no++; |
444 | 453 |
reload: |
445 |
if (!c->finished) { |
|
454 |
if (!c->variants[0]->finished) {
|
|
446 | 455 |
/* If this is a live stream and target_duration has elapsed since |
447 | 456 |
* the last playlist reload, reload the variant playlists now. */ |
448 | 457 |
int64_t now = av_gettime(); |
449 |
if (now - c->last_load_time >= c->target_duration*1000000) { |
|
458 |
if (now - c->last_load_time >= c->variants[0]->target_duration*1000000) {
|
|
450 | 459 |
c->max_start_seq = 0; |
451 | 460 |
c->min_end_seq = INT_MAX; |
452 | 461 |
for (i = 0; i < c->n_variants; i++) { |
... | ... | |
473 | 482 |
goto start; |
474 | 483 |
/* We've reached the end of the playlists - return eof if this is a |
475 | 484 |
* non-live stream, wait until the next playlist reload if it is live. */ |
476 |
if (c->finished) |
|
485 |
if (c->variants[0]->finished)
|
|
477 | 486 |
return AVERROR_EOF; |
478 |
while (av_gettime() - c->last_load_time < c->target_duration*1000000) { |
|
487 |
while (av_gettime() - c->last_load_time < |
|
488 |
c->variants[0]->target_duration*1000000) { |
|
479 | 489 |
if (url_interrupt_cb()) |
480 | 490 |
return AVERROR_EXIT; |
481 | 491 |
usleep(100*1000); |
... | ... | |
500 | 510 |
int i; |
501 | 511 |
struct variant *var = c->variants[0]; |
502 | 512 |
|
503 |
if ((flags & AVSEEK_FLAG_BYTE) || !c->finished) |
|
513 |
if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished)
|
|
504 | 514 |
return AVERROR(ENOSYS); |
505 | 515 |
|
506 | 516 |
/* Reset the variants */ |
Also available in: Unified diff