00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028 #include "libavutil/avstring.h"
00029 #include "libavutil/intreadwrite.h"
00030 #include "libavutil/mathematics.h"
00031 #include "libavutil/opt.h"
00032 #include "libavutil/dict.h"
00033 #include "libavutil/time.h"
00034 #include "avformat.h"
00035 #include "internal.h"
00036 #include "avio_internal.h"
00037 #include "url.h"
00038
00039 #define INITIAL_BUFFER_SIZE 32768
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 enum KeyType {
00054 KEY_NONE,
00055 KEY_AES_128,
00056 };
00057
00058 struct segment {
00059 int duration;
00060 char url[MAX_URL_SIZE];
00061 char key[MAX_URL_SIZE];
00062 enum KeyType key_type;
00063 uint8_t iv[16];
00064 };
00065
00066
00067
00068
00069
00070
00071 struct variant {
00072 int bandwidth;
00073 char url[MAX_URL_SIZE];
00074 AVIOContext pb;
00075 uint8_t* read_buffer;
00076 URLContext *input;
00077 AVFormatContext *parent;
00078 int index;
00079 AVFormatContext *ctx;
00080 AVPacket pkt;
00081 int stream_offset;
00082
00083 int finished;
00084 int target_duration;
00085 int start_seq_no;
00086 int n_segments;
00087 struct segment **segments;
00088 int needed, cur_needed;
00089 int cur_seq_no;
00090 int64_t last_load_time;
00091
00092 char key_url[MAX_URL_SIZE];
00093 uint8_t key[16];
00094 };
00095
00096 typedef struct HLSContext {
00097 int n_variants;
00098 struct variant **variants;
00099 int cur_seq_no;
00100 int end_of_segment;
00101 int first_packet;
00102 int64_t first_timestamp;
00103 int64_t seek_timestamp;
00104 int seek_flags;
00105 AVIOInterruptCB *interrupt_callback;
00106 } HLSContext;
00107
00108 static int read_chomp_line(AVIOContext *s, char *buf, int maxlen)
00109 {
00110 int len = ff_get_line(s, buf, maxlen);
00111 while (len > 0 && isspace(buf[len - 1]))
00112 buf[--len] = '\0';
00113 return len;
00114 }
00115
00116 static void free_segment_list(struct variant *var)
00117 {
00118 int i;
00119 for (i = 0; i < var->n_segments; i++)
00120 av_free(var->segments[i]);
00121 av_freep(&var->segments);
00122 var->n_segments = 0;
00123 }
00124
00125 static void free_variant_list(HLSContext *c)
00126 {
00127 int i;
00128 for (i = 0; i < c->n_variants; i++) {
00129 struct variant *var = c->variants[i];
00130 free_segment_list(var);
00131 av_free_packet(&var->pkt);
00132 av_free(var->pb.buffer);
00133 if (var->input)
00134 ffurl_close(var->input);
00135 if (var->ctx) {
00136 var->ctx->pb = NULL;
00137 avformat_close_input(&var->ctx);
00138 }
00139 av_free(var);
00140 }
00141 av_freep(&c->variants);
00142 c->n_variants = 0;
00143 }
00144
00145
00146
00147
00148
00149 static void reset_packet(AVPacket *pkt)
00150 {
00151 av_init_packet(pkt);
00152 pkt->data = NULL;
00153 }
00154
00155 static struct variant *new_variant(HLSContext *c, int bandwidth,
00156 const char *url, const char *base)
00157 {
00158 struct variant *var = av_mallocz(sizeof(struct variant));
00159 if (!var)
00160 return NULL;
00161 reset_packet(&var->pkt);
00162 var->bandwidth = bandwidth;
00163 ff_make_absolute_url(var->url, sizeof(var->url), base, url);
00164 dynarray_add(&c->variants, &c->n_variants, var);
00165 return var;
00166 }
00167
00168 struct variant_info {
00169 char bandwidth[20];
00170 };
00171
00172 static void handle_variant_args(struct variant_info *info, const char *key,
00173 int key_len, char **dest, int *dest_len)
00174 {
00175 if (!strncmp(key, "BANDWIDTH=", key_len)) {
00176 *dest = info->bandwidth;
00177 *dest_len = sizeof(info->bandwidth);
00178 }
00179 }
00180
00181 struct key_info {
00182 char uri[MAX_URL_SIZE];
00183 char method[10];
00184 char iv[35];
00185 };
00186
00187 static void handle_key_args(struct key_info *info, const char *key,
00188 int key_len, char **dest, int *dest_len)
00189 {
00190 if (!strncmp(key, "METHOD=", key_len)) {
00191 *dest = info->method;
00192 *dest_len = sizeof(info->method);
00193 } else if (!strncmp(key, "URI=", key_len)) {
00194 *dest = info->uri;
00195 *dest_len = sizeof(info->uri);
00196 } else if (!strncmp(key, "IV=", key_len)) {
00197 *dest = info->iv;
00198 *dest_len = sizeof(info->iv);
00199 }
00200 }
00201
00202 static int parse_playlist(HLSContext *c, const char *url,
00203 struct variant *var, AVIOContext *in)
00204 {
00205 int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0;
00206 enum KeyType key_type = KEY_NONE;
00207 uint8_t iv[16] = "";
00208 int has_iv = 0;
00209 char key[MAX_URL_SIZE] = "";
00210 char line[1024];
00211 const char *ptr;
00212 int close_in = 0;
00213
00214 if (!in) {
00215 AVDictionary *opts = NULL;
00216 close_in = 1;
00217
00218 av_dict_set(&opts, "seekable", "0", 0);
00219 ret = avio_open2(&in, url, AVIO_FLAG_READ,
00220 c->interrupt_callback, &opts);
00221 av_dict_free(&opts);
00222 if (ret < 0)
00223 return ret;
00224 }
00225
00226 read_chomp_line(in, line, sizeof(line));
00227 if (strcmp(line, "#EXTM3U")) {
00228 ret = AVERROR_INVALIDDATA;
00229 goto fail;
00230 }
00231
00232 if (var) {
00233 free_segment_list(var);
00234 var->finished = 0;
00235 }
00236 while (!url_feof(in)) {
00237 read_chomp_line(in, line, sizeof(line));
00238 if (av_strstart(line, "#EXT-X-STREAM-INF:", &ptr)) {
00239 struct variant_info info = {{0}};
00240 is_variant = 1;
00241 ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_variant_args,
00242 &info);
00243 bandwidth = atoi(info.bandwidth);
00244 } else if (av_strstart(line, "#EXT-X-KEY:", &ptr)) {
00245 struct key_info info = {{0}};
00246 ff_parse_key_value(ptr, (ff_parse_key_val_cb) handle_key_args,
00247 &info);
00248 key_type = KEY_NONE;
00249 has_iv = 0;
00250 if (!strcmp(info.method, "AES-128"))
00251 key_type = KEY_AES_128;
00252 if (!strncmp(info.iv, "0x", 2) || !strncmp(info.iv, "0X", 2)) {
00253 ff_hex_to_data(iv, info.iv + 2);
00254 has_iv = 1;
00255 }
00256 av_strlcpy(key, info.uri, sizeof(key));
00257 } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) {
00258 if (!var) {
00259 var = new_variant(c, 0, url, NULL);
00260 if (!var) {
00261 ret = AVERROR(ENOMEM);
00262 goto fail;
00263 }
00264 }
00265 var->target_duration = atoi(ptr);
00266 } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
00267 if (!var) {
00268 var = new_variant(c, 0, url, NULL);
00269 if (!var) {
00270 ret = AVERROR(ENOMEM);
00271 goto fail;
00272 }
00273 }
00274 var->start_seq_no = atoi(ptr);
00275 } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) {
00276 if (var)
00277 var->finished = 1;
00278 } else if (av_strstart(line, "#EXTINF:", &ptr)) {
00279 is_segment = 1;
00280 duration = atoi(ptr);
00281 } else if (av_strstart(line, "#", NULL)) {
00282 continue;
00283 } else if (line[0]) {
00284 if (is_variant) {
00285 if (!new_variant(c, bandwidth, line, url)) {
00286 ret = AVERROR(ENOMEM);
00287 goto fail;
00288 }
00289 is_variant = 0;
00290 bandwidth = 0;
00291 }
00292 if (is_segment) {
00293 struct segment *seg;
00294 if (!var) {
00295 var = new_variant(c, 0, url, NULL);
00296 if (!var) {
00297 ret = AVERROR(ENOMEM);
00298 goto fail;
00299 }
00300 }
00301 seg = av_malloc(sizeof(struct segment));
00302 if (!seg) {
00303 ret = AVERROR(ENOMEM);
00304 goto fail;
00305 }
00306 seg->duration = duration;
00307 seg->key_type = key_type;
00308 if (has_iv) {
00309 memcpy(seg->iv, iv, sizeof(iv));
00310 } else {
00311 int seq = var->start_seq_no + var->n_segments;
00312 memset(seg->iv, 0, sizeof(seg->iv));
00313 AV_WB32(seg->iv + 12, seq);
00314 }
00315 ff_make_absolute_url(seg->key, sizeof(seg->key), url, key);
00316 ff_make_absolute_url(seg->url, sizeof(seg->url), url, line);
00317 dynarray_add(&var->segments, &var->n_segments, seg);
00318 is_segment = 0;
00319 }
00320 }
00321 }
00322 if (var)
00323 var->last_load_time = av_gettime();
00324
00325 fail:
00326 if (close_in)
00327 avio_close(in);
00328 return ret;
00329 }
00330
00331 static int open_input(struct variant *var)
00332 {
00333 AVDictionary *opts = NULL;
00334 int ret;
00335 struct segment *seg = var->segments[var->cur_seq_no - var->start_seq_no];
00336 av_dict_set(&opts, "seekable", "0", 0);
00337 if (seg->key_type == KEY_NONE) {
00338 ret = ffurl_open(&var->input, seg->url, AVIO_FLAG_READ,
00339 &var->parent->interrupt_callback, &opts);
00340 goto cleanup;
00341 } else if (seg->key_type == KEY_AES_128) {
00342 char iv[33], key[33], url[MAX_URL_SIZE];
00343 if (strcmp(seg->key, var->key_url)) {
00344 URLContext *uc;
00345 if (ffurl_open(&uc, seg->key, AVIO_FLAG_READ,
00346 &var->parent->interrupt_callback, &opts) == 0) {
00347 if (ffurl_read_complete(uc, var->key, sizeof(var->key))
00348 != sizeof(var->key)) {
00349 av_log(NULL, AV_LOG_ERROR, "Unable to read key file %s\n",
00350 seg->key);
00351 }
00352 ffurl_close(uc);
00353 } else {
00354 av_log(NULL, AV_LOG_ERROR, "Unable to open key file %s\n",
00355 seg->key);
00356 }
00357 av_strlcpy(var->key_url, seg->key, sizeof(var->key_url));
00358 }
00359 ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0);
00360 ff_data_to_hex(key, var->key, sizeof(var->key), 0);
00361 iv[32] = key[32] = '\0';
00362 if (strstr(seg->url, "://"))
00363 snprintf(url, sizeof(url), "crypto+%s", seg->url);
00364 else
00365 snprintf(url, sizeof(url), "crypto:%s", seg->url);
00366 if ((ret = ffurl_alloc(&var->input, url, AVIO_FLAG_READ,
00367 &var->parent->interrupt_callback)) < 0)
00368 goto cleanup;
00369 av_opt_set(var->input->priv_data, "key", key, 0);
00370 av_opt_set(var->input->priv_data, "iv", iv, 0);
00371
00372 av_dict_free(&opts);
00373 av_dict_set(&opts, "seekable", "0", 0);
00374 if ((ret = ffurl_connect(var->input, &opts)) < 0) {
00375 ffurl_close(var->input);
00376 var->input = NULL;
00377 goto cleanup;
00378 }
00379 ret = 0;
00380 }
00381 else
00382 ret = AVERROR(ENOSYS);
00383
00384 cleanup:
00385 av_dict_free(&opts);
00386 return ret;
00387 }
00388
00389 static int read_data(void *opaque, uint8_t *buf, int buf_size)
00390 {
00391 struct variant *v = opaque;
00392 HLSContext *c = v->parent->priv_data;
00393 int ret, i;
00394
00395 restart:
00396 if (!v->input) {
00397
00398
00399 int64_t reload_interval = v->n_segments > 0 ?
00400 v->segments[v->n_segments - 1]->duration :
00401 v->target_duration;
00402 reload_interval *= 1000000;
00403
00404 reload:
00405 if (!v->finished &&
00406 av_gettime() - v->last_load_time >= reload_interval) {
00407 if ((ret = parse_playlist(c, v->url, v, NULL)) < 0)
00408 return ret;
00409
00410
00411
00412 reload_interval = v->target_duration * 500000LL;
00413 }
00414 if (v->cur_seq_no < v->start_seq_no) {
00415 av_log(NULL, AV_LOG_WARNING,
00416 "skipping %d segments ahead, expired from playlists\n",
00417 v->start_seq_no - v->cur_seq_no);
00418 v->cur_seq_no = v->start_seq_no;
00419 }
00420 if (v->cur_seq_no >= v->start_seq_no + v->n_segments) {
00421 if (v->finished)
00422 return AVERROR_EOF;
00423 while (av_gettime() - v->last_load_time < reload_interval) {
00424 if (ff_check_interrupt(c->interrupt_callback))
00425 return AVERROR_EXIT;
00426 av_usleep(100*1000);
00427 }
00428
00429 goto reload;
00430 }
00431
00432 ret = open_input(v);
00433 if (ret < 0)
00434 return ret;
00435 }
00436 ret = ffurl_read(v->input, buf, buf_size);
00437 if (ret > 0)
00438 return ret;
00439 ffurl_close(v->input);
00440 v->input = NULL;
00441 v->cur_seq_no++;
00442
00443 c->end_of_segment = 1;
00444 c->cur_seq_no = v->cur_seq_no;
00445
00446 if (v->ctx && v->ctx->nb_streams && v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) {
00447 v->needed = 0;
00448 for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams;
00449 i++) {
00450 if (v->parent->streams[i]->discard < AVDISCARD_ALL)
00451 v->needed = 1;
00452 }
00453 }
00454 if (!v->needed) {
00455 av_log(v->parent, AV_LOG_INFO, "No longer receiving variant %d\n",
00456 v->index);
00457 return AVERROR_EOF;
00458 }
00459 goto restart;
00460 }
00461
00462 static int hls_read_header(AVFormatContext *s)
00463 {
00464 HLSContext *c = s->priv_data;
00465 int ret = 0, i, j, stream_offset = 0;
00466
00467 c->interrupt_callback = &s->interrupt_callback;
00468
00469 if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0)
00470 goto fail;
00471
00472 if (c->n_variants == 0) {
00473 av_log(NULL, AV_LOG_WARNING, "Empty playlist\n");
00474 ret = AVERROR_EOF;
00475 goto fail;
00476 }
00477
00478
00479 if (c->n_variants > 1 || c->variants[0]->n_segments == 0) {
00480 for (i = 0; i < c->n_variants; i++) {
00481 struct variant *v = c->variants[i];
00482 if ((ret = parse_playlist(c, v->url, v, NULL)) < 0)
00483 goto fail;
00484 }
00485 }
00486
00487 if (c->variants[0]->n_segments == 0) {
00488 av_log(NULL, AV_LOG_WARNING, "Empty playlist\n");
00489 ret = AVERROR_EOF;
00490 goto fail;
00491 }
00492
00493
00494
00495 if (c->variants[0]->finished) {
00496 int64_t duration = 0;
00497 for (i = 0; i < c->variants[0]->n_segments; i++)
00498 duration += c->variants[0]->segments[i]->duration;
00499 s->duration = duration * AV_TIME_BASE;
00500 }
00501
00502
00503 for (i = 0; i < c->n_variants; i++) {
00504 struct variant *v = c->variants[i];
00505 AVInputFormat *in_fmt = NULL;
00506 char bitrate_str[20];
00507 AVProgram *program = NULL;
00508 if (v->n_segments == 0)
00509 continue;
00510
00511 if (!(v->ctx = avformat_alloc_context())) {
00512 ret = AVERROR(ENOMEM);
00513 goto fail;
00514 }
00515
00516 v->index = i;
00517 v->needed = 1;
00518 v->parent = s;
00519
00520
00521
00522 v->cur_seq_no = v->start_seq_no;
00523 if (!v->finished && v->n_segments > 3)
00524 v->cur_seq_no = v->start_seq_no + v->n_segments - 3;
00525
00526 v->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
00527 ffio_init_context(&v->pb, v->read_buffer, INITIAL_BUFFER_SIZE, 0, v,
00528 read_data, NULL, NULL);
00529 v->pb.seekable = 0;
00530 ret = av_probe_input_buffer(&v->pb, &in_fmt, v->segments[0]->url,
00531 NULL, 0, 0);
00532 if (ret < 0) {
00533
00534
00535
00536
00537 av_log(s, AV_LOG_ERROR, "Error when loading first segment '%s'\n", v->segments[0]->url);
00538 avformat_free_context(v->ctx);
00539 v->ctx = NULL;
00540 goto fail;
00541 }
00542 v->ctx->pb = &v->pb;
00543 ret = avformat_open_input(&v->ctx, v->segments[0]->url, in_fmt, NULL);
00544 if (ret < 0)
00545 goto fail;
00546
00547 v->stream_offset = stream_offset;
00548 v->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER;
00549 ret = avformat_find_stream_info(v->ctx, NULL);
00550 if (ret < 0)
00551 goto fail;
00552 snprintf(bitrate_str, sizeof(bitrate_str), "%d", v->bandwidth);
00553
00554
00555 program = av_new_program(s, i);
00556 if (!program)
00557 goto fail;
00558 av_dict_set(&program->metadata, "variant_bitrate", bitrate_str, 0);
00559
00560
00561 for (j = 0; j < v->ctx->nb_streams; j++) {
00562 AVStream *st = avformat_new_stream(s, NULL);
00563 if (!st) {
00564 ret = AVERROR(ENOMEM);
00565 goto fail;
00566 }
00567 ff_program_add_stream_index(s, i, stream_offset + j);
00568 st->id = i;
00569 avcodec_copy_context(st->codec, v->ctx->streams[j]->codec);
00570 if (v->bandwidth)
00571 av_dict_set(&st->metadata, "variant_bitrate", bitrate_str,
00572 0);
00573 }
00574 stream_offset += v->ctx->nb_streams;
00575 }
00576
00577 c->first_packet = 1;
00578 c->first_timestamp = AV_NOPTS_VALUE;
00579 c->seek_timestamp = AV_NOPTS_VALUE;
00580
00581 return 0;
00582 fail:
00583 free_variant_list(c);
00584 return ret;
00585 }
00586
00587 static int recheck_discard_flags(AVFormatContext *s, int first)
00588 {
00589 HLSContext *c = s->priv_data;
00590 int i, changed = 0;
00591
00592
00593 for (i = 0; i < c->n_variants; i++)
00594 c->variants[i]->cur_needed = 0;
00595
00596 for (i = 0; i < s->nb_streams; i++) {
00597 AVStream *st = s->streams[i];
00598 struct variant *var = c->variants[s->streams[i]->id];
00599 if (st->discard < AVDISCARD_ALL)
00600 var->cur_needed = 1;
00601 }
00602 for (i = 0; i < c->n_variants; i++) {
00603 struct variant *v = c->variants[i];
00604 if (v->cur_needed && !v->needed) {
00605 v->needed = 1;
00606 changed = 1;
00607 v->cur_seq_no = c->cur_seq_no;
00608 v->pb.eof_reached = 0;
00609 av_log(s, AV_LOG_INFO, "Now receiving variant %d\n", i);
00610 } else if (first && !v->cur_needed && v->needed) {
00611 if (v->input)
00612 ffurl_close(v->input);
00613 v->input = NULL;
00614 v->needed = 0;
00615 changed = 1;
00616 av_log(s, AV_LOG_INFO, "No longer receiving variant %d\n", i);
00617 }
00618 }
00619 return changed;
00620 }
00621
00622 static int hls_read_packet(AVFormatContext *s, AVPacket *pkt)
00623 {
00624 HLSContext *c = s->priv_data;
00625 int ret, i, minvariant = -1;
00626
00627 if (c->first_packet) {
00628 recheck_discard_flags(s, 1);
00629 c->first_packet = 0;
00630 }
00631
00632 start:
00633 c->end_of_segment = 0;
00634 for (i = 0; i < c->n_variants; i++) {
00635 struct variant *var = c->variants[i];
00636
00637
00638 if (var->needed && !var->pkt.data) {
00639 while (1) {
00640 int64_t ts_diff;
00641 AVStream *st;
00642 ret = av_read_frame(var->ctx, &var->pkt);
00643 if (ret < 0) {
00644 if (!url_feof(&var->pb) && ret != AVERROR_EOF)
00645 return ret;
00646 reset_packet(&var->pkt);
00647 break;
00648 } else {
00649 if (c->first_timestamp == AV_NOPTS_VALUE)
00650 c->first_timestamp = var->pkt.dts;
00651 }
00652
00653 if (c->seek_timestamp == AV_NOPTS_VALUE)
00654 break;
00655
00656 if (var->pkt.dts == AV_NOPTS_VALUE) {
00657 c->seek_timestamp = AV_NOPTS_VALUE;
00658 break;
00659 }
00660
00661 st = var->ctx->streams[var->pkt.stream_index];
00662 ts_diff = av_rescale_rnd(var->pkt.dts, AV_TIME_BASE,
00663 st->time_base.den, AV_ROUND_DOWN) -
00664 c->seek_timestamp;
00665 if (ts_diff >= 0 && (c->seek_flags & AVSEEK_FLAG_ANY ||
00666 var->pkt.flags & AV_PKT_FLAG_KEY)) {
00667 c->seek_timestamp = AV_NOPTS_VALUE;
00668 break;
00669 }
00670 }
00671 }
00672
00673 if (var->pkt.data) {
00674 if(minvariant < 0) {
00675 minvariant = i;
00676 } else {
00677 struct variant *minvar = c->variants[minvariant];
00678 int64_t dts = var->pkt.dts;
00679 int64_t mindts = minvar->pkt.dts;
00680 AVStream *st = var->ctx->streams[ var->pkt.stream_index];
00681 AVStream *minst= minvar->ctx->streams[minvar->pkt.stream_index];
00682
00683 if( st->start_time != AV_NOPTS_VALUE) dts -= st->start_time;
00684 if(minst->start_time != AV_NOPTS_VALUE) mindts -= minst->start_time;
00685
00686 if (av_compare_ts(dts, st->time_base, mindts, minst->time_base) < 0)
00687 minvariant = i;
00688 }
00689 }
00690 }
00691 if (c->end_of_segment) {
00692 if (recheck_discard_flags(s, 0))
00693 goto start;
00694 }
00695
00696 if (minvariant >= 0) {
00697 *pkt = c->variants[minvariant]->pkt;
00698 pkt->stream_index += c->variants[minvariant]->stream_offset;
00699 reset_packet(&c->variants[minvariant]->pkt);
00700 return 0;
00701 }
00702 return AVERROR_EOF;
00703 }
00704
00705 static int hls_close(AVFormatContext *s)
00706 {
00707 HLSContext *c = s->priv_data;
00708
00709 free_variant_list(c);
00710 return 0;
00711 }
00712
00713 static int hls_read_seek(AVFormatContext *s, int stream_index,
00714 int64_t timestamp, int flags)
00715 {
00716 HLSContext *c = s->priv_data;
00717 int i, j, ret;
00718
00719 if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished)
00720 return AVERROR(ENOSYS);
00721
00722 c->seek_flags = flags;
00723 c->seek_timestamp = stream_index < 0 ? timestamp :
00724 av_rescale_rnd(timestamp, AV_TIME_BASE,
00725 s->streams[stream_index]->time_base.den,
00726 flags & AVSEEK_FLAG_BACKWARD ?
00727 AV_ROUND_DOWN : AV_ROUND_UP);
00728 timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ?
00729 s->streams[stream_index]->time_base.den :
00730 AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
00731 AV_ROUND_DOWN : AV_ROUND_UP);
00732 if (s->duration < c->seek_timestamp) {
00733 c->seek_timestamp = AV_NOPTS_VALUE;
00734 return AVERROR(EIO);
00735 }
00736
00737 ret = AVERROR(EIO);
00738 for (i = 0; i < c->n_variants; i++) {
00739
00740 struct variant *var = c->variants[i];
00741 int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 :
00742 av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ?
00743 s->streams[stream_index]->time_base.den :
00744 AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ?
00745 AV_ROUND_DOWN : AV_ROUND_UP);
00746 if (var->input) {
00747 ffurl_close(var->input);
00748 var->input = NULL;
00749 }
00750 av_free_packet(&var->pkt);
00751 reset_packet(&var->pkt);
00752 var->pb.eof_reached = 0;
00753
00754 var->pb.buf_end = var->pb.buf_ptr = var->pb.buffer;
00755
00756 var->pb.pos = 0;
00757
00758
00759 for (j = 0; j < var->n_segments; j++) {
00760 if (timestamp >= pos &&
00761 timestamp < pos + var->segments[j]->duration) {
00762 var->cur_seq_no = var->start_seq_no + j;
00763 ret = 0;
00764 break;
00765 }
00766 pos += var->segments[j]->duration;
00767 }
00768 if (ret)
00769 c->seek_timestamp = AV_NOPTS_VALUE;
00770 }
00771 return ret;
00772 }
00773
00774 static int hls_probe(AVProbeData *p)
00775 {
00776
00777
00778 if (strncmp(p->buf, "#EXTM3U", 7))
00779 return 0;
00780 if (strstr(p->buf, "#EXT-X-STREAM-INF:") ||
00781 strstr(p->buf, "#EXT-X-TARGETDURATION:") ||
00782 strstr(p->buf, "#EXT-X-MEDIA-SEQUENCE:"))
00783 return AVPROBE_SCORE_MAX;
00784 return 0;
00785 }
00786
00787 AVInputFormat ff_hls_demuxer = {
00788 .name = "hls,applehttp",
00789 .long_name = NULL_IF_CONFIG_SMALL("Apple HTTP Live Streaming"),
00790 .priv_data_size = sizeof(HLSContext),
00791 .read_probe = hls_probe,
00792 .read_header = hls_read_header,
00793 .read_packet = hls_read_packet,
00794 .read_close = hls_close,
00795 .read_seek = hls_read_seek,
00796 };