static int read_data(void *opaque, uint8_t *buf, int buf_size) { struct variant *v = opaque; HLSContext *c = v->parent->priv_data; int ret, i; restart: if (!v->input) { /* If this is a live stream and the reload interval has elapsed since * the last playlist reload, reload the variant playlists now. */ int64_t reload_interval = v->n_segments > 0 ? v->segments[v->n_segments - 1]->duration : v->target_duration; reload_interval *= 1000000; reload: if (!v->finished && av_gettime() - v->last_load_time >= reload_interval) { if ((ret = parse_playlist(c, v->url, v, NULL)) < 0) return ret; /* If we need to reload the playlist again below (if * there's still no more segments), switch to a reload * interval of half the target duration. */ reload_interval = v->target_duration * 500000LL; } if (v->cur_seq_no < v->start_seq_no) { av_log(NULL, AV_LOG_WARNING, "skipping %d segments ahead, expired from playlists\n", v->start_seq_no - v->cur_seq_no); v->cur_seq_no = v->start_seq_no; } if (v->cur_seq_no >= v->start_seq_no + v->n_segments) { if (v->finished) return AVERROR_EOF; while (av_gettime() - v->last_load_time < reload_interval) { if (ff_check_interrupt(c->interrupt_callback)) return AVERROR_EXIT; av_usleep(100*1000); } /* Enough time has elapsed since the last reload */ goto reload; } ret = open_input(c, v); if (ret < 0) return ret; } ret = ffurl_read(v->input, buf, buf_size); if (ret > 0) return ret; ffurl_close(v->input); v->input = NULL; v->cur_seq_no++; c->end_of_segment = 1; c->cur_seq_no = v->cur_seq_no; if (v->ctx && v->ctx->nb_streams && v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) { v->needed = 0; for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams; i++) { if (v->parent->streams[i]->discard < AVDISCARD_ALL) v->needed = 1; } } if (!v->needed) { av_log(v->parent, AV_LOG_INFO, "No longer receiving variant %d\n", v->index); return AVERROR_EOF; } goto restart; }
static int sap_read_header(AVFormatContext *s, AVFormatParameters *ap) { struct SAPState *sap = s->priv_data; char host[1024], path[1024], url[1024]; uint8_t recvbuf[1500]; int port; int ret, i; AVInputFormat* infmt; if (!ff_network_init()) return AVERROR(EIO); av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, path, sizeof(path), s->filename); if (port < 0) port = 9875; if (!host[0]) { /* Listen for announcements on sap.mcast.net if no host was specified */ av_strlcpy(host, "224.2.127.254", sizeof(host)); } ff_url_join(url, sizeof(url), "udp", NULL, host, port, "?localport=%d", port); ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_READ, &s->interrupt_callback, NULL); if (ret) goto fail; while (1) { int addr_type, auth_len; int pos; ret = ffurl_read(sap->ann_fd, recvbuf, sizeof(recvbuf) - 1); if (ret == AVERROR(EAGAIN)) continue; if (ret < 0) goto fail; recvbuf[ret] = '\0'; /* Null terminate for easier parsing */ if (ret < 8) { av_log(s, AV_LOG_WARNING, "Received too short packet\n"); continue; } if ((recvbuf[0] & 0xe0) != 0x20) { av_log(s, AV_LOG_WARNING, "Unsupported SAP version packet " "received\n"); continue; } if (recvbuf[0] & 0x04) { av_log(s, AV_LOG_WARNING, "Received stream deletion " "announcement\n"); continue; } addr_type = recvbuf[0] & 0x10; auth_len = recvbuf[1]; sap->hash = AV_RB16(&recvbuf[2]); pos = 4; if (addr_type) pos += 16; /* IPv6 */ else pos += 4; /* IPv4 */ pos += auth_len * 4; if (pos + 4 >= ret) { av_log(s, AV_LOG_WARNING, "Received too short packet\n"); continue; } #define MIME "application/sdp" if (strcmp(&recvbuf[pos], MIME) == 0) { pos += strlen(MIME) + 1; } else if (strncmp(&recvbuf[pos], "v=0\r\n", 5) == 0) { // Direct SDP without a mime type } else { av_log(s, AV_LOG_WARNING, "Unsupported mime type %s\n", &recvbuf[pos]); continue; } sap->sdp = av_strdup(&recvbuf[pos]); break; } av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sap->sdp); ffio_init_context(&sap->sdp_pb, sap->sdp, strlen(sap->sdp), 0, NULL, NULL, NULL, NULL); infmt = av_find_input_format("sdp"); if (!infmt) goto fail; sap->sdp_ctx = avformat_alloc_context(); if (!sap->sdp_ctx) { ret = AVERROR(ENOMEM); goto fail; } sap->sdp_ctx->max_delay = s->max_delay; sap->sdp_ctx->pb = &sap->sdp_pb; sap->sdp_ctx->interrupt_callback = s->interrupt_callback; ret = avformat_open_input(&sap->sdp_ctx, "temp.sdp", infmt, NULL); if (ret < 0) goto fail; if (sap->sdp_ctx->ctx_flags & AVFMTCTX_NOHEADER) s->ctx_flags |= AVFMTCTX_NOHEADER; for (i = 0; i < sap->sdp_ctx->nb_streams; i++) { AVStream *st = avformat_new_stream(s, NULL); if (!st) { ret = AVERROR(ENOMEM); goto fail; } st->id = i; avcodec_copy_context(st->codec, sap->sdp_ctx->streams[i]->codec); st->time_base = sap->sdp_ctx->streams[i]->time_base; } return 0; fail: sap_read_close(s); return ret; }
static int read_data(void *opaque, uint8_t *buf, int buf_size) { struct variant *v = opaque; AppleHTTPContext *c = v->parent->priv_data; int ret, i; restart: if (!v->input) { reload: /* If this is a live stream and target_duration has elapsed since * the last playlist reload, reload the variant playlists now. */ if (!v->finished && av_gettime() - v->last_load_time >= v->target_duration*1000000 && (ret = parse_playlist(c, v->url, v, NULL)) < 0) return ret; if (v->cur_seq_no < v->start_seq_no) { av_log(NULL, AV_LOG_WARNING, "skipping %d segments ahead, expired from playlists\n", v->start_seq_no - v->cur_seq_no); v->cur_seq_no = v->start_seq_no; } if (v->cur_seq_no >= v->start_seq_no + v->n_segments) { if (v->finished) return AVERROR_EOF; while (av_gettime() - v->last_load_time < v->target_duration*1000000) { if (url_interrupt_cb()) return AVERROR_EXIT; usleep(100*1000); } /* Enough time has elapsed since the last reload */ goto reload; } ret = ffurl_open(&v->input, v->segments[v->cur_seq_no - v->start_seq_no]->url, AVIO_RDONLY); if (ret < 0) return ret; } ret = ffurl_read(v->input, buf, buf_size); if (ret > 0) return ret; if (ret < 0 && ret != AVERROR_EOF) return ret; ffurl_close(v->input); v->input = NULL; v->cur_seq_no++; c->end_of_segment = 1; c->cur_seq_no = v->cur_seq_no; if (v->ctx) { v->needed = 0; for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams; i++) { if (v->parent->streams[i]->discard < AVDISCARD_ALL) v->needed = 1; } } if (!v->needed) { av_log(v->parent, AV_LOG_INFO, "No longer receiving variant %d\n", v->index); return AVERROR_EOF; } goto restart; }
int url_read(URLContext *h, unsigned char *buf, int size) { return ffurl_read(h, buf, size); }