static int gopher_open(URLContext *h, const char *uri, int flags) { GopherContext *s = h->priv_data; char hostname[1024], auth[1024], path[1024], buf[1024]; int port, err; h->is_streamed = 1; /* needed in any case to build the host string */ av_url_split(NULL, 0, auth, sizeof(auth), hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (port < 0) port = 70; ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL); s->hd = NULL; err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h); if (err < 0) goto fail; if ((err = gopher_connect(h, path)) < 0) goto fail; return 0; fail: gopher_close(h); return err; }
static int subfile_open(URLContext *h, const char *filename, int flags, AVDictionary **options) { SubfileContext *c = h->priv_data; int ret; if (!c->end) c->end = INT64_MAX; if (c->end <= c->start) { av_log(h, AV_LOG_ERROR, "end before start\n"); return AVERROR(EINVAL); } av_strstart(filename, "subfile:", &filename); ret = ffurl_open_whitelist(&c->h, filename, flags, &h->interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist, h); if (ret < 0) return ret; c->pos = c->start; if ((ret = slave_seek(h)) < 0) { ffurl_close(c->h); return ret; } return 0; }
static int md5_close(URLContext *h) { struct MD5Context *c = h->priv_data; const char *filename = h->filename; uint8_t md5[16], buf[64]; URLContext *out; int i, err = 0; av_md5_final(c->md5, md5); for (i = 0; i < sizeof(md5); i++) snprintf(buf + i*2, 3, "%02x", md5[i]); buf[i*2] = '\n'; av_strstart(filename, "md5:", &filename); if (*filename) { err = ffurl_open_whitelist(&out, filename, AVIO_FLAG_WRITE, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist); if (err) return err; err = ffurl_write(out, buf, i*2+1); ffurl_close(out); } else { if (fwrite(buf, 1, i*2+1, stdout) < i*2+1) err = AVERROR(errno); } av_freep(&c->md5); return err; }
static int rtmpe_open(URLContext *h, const char *uri, int flags) { RTMPEContext *rt = h->priv_data; char host[256], url[1024]; int ret, port; av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, uri); if (rt->tunneling) { if (port < 0) port = 80; ff_url_join(url, sizeof(url), "ffrtmphttp", NULL, host, port, NULL); } else { if (port < 0) port = 1935; ff_url_join(url, sizeof(url), "tcp", NULL, host, port, NULL); } /* open the tcp or ffrtmphttp connection */ if ((ret = ffurl_open_whitelist(&rt->stream, url, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h)) < 0) { rtmpe_close(h); return ret; } return 0; }
int ffurl_open(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options) { return ffurl_open_whitelist(puc, filename, flags, int_cb, options, NULL, NULL, NULL); }
static int icecast_open(URLContext *h, const char *uri, int flags) { IcecastContext *s = h->priv_data; // Dict to set options that we pass to the HTTP protocol AVDictionary *opt_dict = NULL; // URI part variables char h_url[1024], host[1024], auth[1024], path[1024]; char *headers = NULL, *user = NULL; int port, ret; AVBPrint bp; if (flags & AVIO_FLAG_READ) return AVERROR(ENOSYS); av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); // Build header strings cat_header(&bp, "Ice-Name", s->name); cat_header(&bp, "Ice-Description", s->description); cat_header(&bp, "Ice-URL", s->url); cat_header(&bp, "Ice-Genre", s->genre); cat_header(&bp, "Ice-Public", s->public ? "1" : "0"); if (!av_bprint_is_complete(&bp)) { ret = AVERROR(ENOMEM); goto cleanup; } av_bprint_finalize(&bp, &headers); // Set options av_dict_set(&opt_dict, "method", s->legacy_icecast ? "SOURCE" : "PUT", 0); av_dict_set(&opt_dict, "auth_type", "basic", 0); av_dict_set(&opt_dict, "headers", headers, 0); av_dict_set(&opt_dict, "chunked_post", "0", 0); av_dict_set(&opt_dict, "send_expect_100", s->legacy_icecast ? "0" : "1", 0); if (NOT_EMPTY(s->content_type)) av_dict_set(&opt_dict, "content_type", s->content_type, 0); else av_dict_set(&opt_dict, "content_type", "audio/mpeg", 0); if (NOT_EMPTY(s->user_agent)) av_dict_set(&opt_dict, "user_agent", s->user_agent, 0); // Parse URI av_url_split(NULL, 0, auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), uri); // Check for auth data in URI if (auth[0]) { char *sep = strchr(auth, ':'); if (sep) { *sep = 0; sep++; if (s->pass) { av_free(s->pass); av_log(h, AV_LOG_WARNING, "Overwriting -password <pass> with URI password!\n"); } if (!(s->pass = av_strdup(sep))) { ret = AVERROR(ENOMEM); goto cleanup; } } if (!(user = av_strdup(auth))) { ret = AVERROR(ENOMEM); goto cleanup; } } // Build new authstring snprintf(auth, sizeof(auth), "%s:%s", user ? user : DEFAULT_ICE_USER, s->pass ? s->pass : ""); // Check for mountpoint (path) if (!path[0] || strcmp(path, "/") == 0) { av_log(h, AV_LOG_ERROR, "No mountpoint (path) specified!\n"); ret = AVERROR(EIO); goto cleanup; } // Build new URI for passing to http protocol ff_url_join(h_url, sizeof(h_url), "http", auth, host, port, "%s", path); // Finally open http proto handler ret = ffurl_open_whitelist(&s->hd, h_url, AVIO_FLAG_READ_WRITE, NULL, &opt_dict, h->protocol_whitelist, h->protocol_blacklist, h); cleanup: av_freep(&user); av_freep(&headers); av_dict_free(&opt_dict); return ret; }
static int mms_open(URLContext *h, const char *uri, int flags) { MMSTContext *mmst = h->priv_data; MMSContext *mms; int port, err; char tcpname[256]; h->is_streamed = 1; mms = &mmst->mms; // only for MMS over TCP, so set proto = NULL av_url_split(NULL, 0, NULL, 0, mmst->host, sizeof(mmst->host), &port, mmst->path, sizeof(mmst->path), uri); if(port<0) port = 1755; // defaut mms protocol port // establish tcp connection. ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, mmst->host, port, NULL); err = ffurl_open_whitelist(&mms->mms_hd, tcpname, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, NULL, h->protocol_whitelist); if (err) goto fail; mmst->packet_id = 3; // default, initial value. mmst->header_packet_id = 2; // default, initial value. err = mms_safe_send_recv(mmst, send_startup_packet, SC_PKT_CLIENT_ACCEPTED); if (err) goto fail; err = mms_safe_send_recv(mmst, send_time_test_data, SC_PKT_TIMING_TEST_REPLY); if (err) goto fail; err = mms_safe_send_recv(mmst, send_protocol_select, SC_PKT_PROTOCOL_ACCEPTED); if (err) goto fail; err = mms_safe_send_recv(mmst, send_media_file_request, SC_PKT_MEDIA_FILE_DETAILS); if (err) goto fail; err = mms_safe_send_recv(mmst, send_media_header_request, SC_PKT_HEADER_REQUEST_ACCEPTED); if (err) goto fail; err = mms_safe_send_recv(mmst, NULL, SC_PKT_ASF_HEADER); if (err) goto fail; if((mmst->incoming_flags != 0X08) && (mmst->incoming_flags != 0X0C)) { av_log(NULL, AV_LOG_ERROR, "The server does not support MMST (try MMSH or RTSP)\n"); err = AVERROR(EINVAL); goto fail; } err = ff_mms_asf_header_parser(mms); if (err) { av_log(NULL, AV_LOG_TRACE, "asf header parsed failed!\n"); goto fail; } mms->header_parsed = 1; if (!mms->asf_packet_len || !mms->stream_num) goto fail; clear_stream_buffers(mms); err = mms_safe_send_recv(mmst, send_stream_selection_request, SC_PKT_STREAM_ID_ACCEPTED); if (err) goto fail; // send media packet request err = mms_safe_send_recv(mmst, send_media_packet_request, SC_PKT_MEDIA_PKT_FOLLOWS); if (err) { goto fail; } av_log(NULL, AV_LOG_TRACE, "Leaving open (success)\n"); return 0; fail: mms_close(h); av_log(NULL, AV_LOG_TRACE, "Leaving open (failure: %d)\n", err); return err; }
static av_cold int concat_open(URLContext *h, const char *uri, int flags) { char *node_uri = NULL; int err = 0; int64_t size; size_t len, i; URLContext *uc; struct concat_data *data = h->priv_data; struct concat_nodes *nodes; if (!av_strstart(uri, "concat:", &uri)) { av_log(h, AV_LOG_ERROR, "URL %s lacks prefix\n", uri); return AVERROR(EINVAL); } for (i = 0, len = 1; uri[i]; i++) { if (uri[i] == *AV_CAT_SEPARATOR) { /* integer overflow */ if (++len == UINT_MAX / sizeof(*nodes)) { av_freep(&h->priv_data); return AVERROR(ENAMETOOLONG); } } } if (!(nodes = av_realloc(NULL, sizeof(*nodes) * len))) return AVERROR(ENOMEM); else data->nodes = nodes; /* handle input */ if (!*uri) err = AVERROR(ENOENT); for (i = 0; *uri; i++) { /* parsing uri */ len = strcspn(uri, AV_CAT_SEPARATOR); if ((err = av_reallocp(&node_uri, len + 1)) < 0) break; av_strlcpy(node_uri, uri, len + 1); uri += len + strspn(uri + len, AV_CAT_SEPARATOR); /* creating URLContext */ err = ffurl_open_whitelist(&uc, node_uri, flags, &h->interrupt_callback, NULL, h->protocol_whitelist); if (err < 0) break; /* creating size */ if ((size = ffurl_size(uc)) < 0) { ffurl_close(uc); err = AVERROR(ENOSYS); break; } /* assembling */ nodes[i].uc = uc; nodes[i].size = size; } av_free(node_uri); data->length = i; if (err < 0) concat_close(h); else if (!(nodes = av_realloc(nodes, data->length * sizeof(*nodes)))) { concat_close(h); err = AVERROR(ENOMEM); } else data->nodes = nodes; return err; }
static int sap_read_header(AVFormatContext *s) { struct SAPState *sap = s->priv_data; char host[1024], path[1024], url[1024]; uint8_t recvbuf[RTP_MAX_PACKET_LENGTH]; 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_whitelist(&sap->ann_fd, url, AVIO_FLAG_READ, &s->interrupt_callback, NULL, s->protocol_whitelist); 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; if ((ret = ff_copy_whitelists(sap->sdp_ctx, s)) < 0) goto fail; 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 rtsp_listen(AVFormatContext *s) { RTSPState *rt = s->priv_data; char proto[128], host[128], path[512], auth[128]; char uri[500]; int port; int default_port = RTSP_DEFAULT_PORT; char tcpname[500]; const char *lower_proto = "tcp"; unsigned char rbuf[4096]; unsigned char method[10]; int rbuflen = 0; int ret; enum RTSPMethod methodcode; /* extract hostname and port */ av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), s->url); /* ff_url_join. No authorization by now (NULL) */ ff_url_join(rt->control_uri, sizeof(rt->control_uri), proto, NULL, host, port, "%s", path); if (!strcmp(proto, "rtsps")) { lower_proto = "tls"; default_port = RTSPS_DEFAULT_PORT; } if (port < 0) port = default_port; /* Create TCP connection */ ff_url_join(tcpname, sizeof(tcpname), lower_proto, NULL, host, port, "?listen&listen_timeout=%d", rt->initial_timeout * 1000); if (ret = ffurl_open_whitelist(&rt->rtsp_hd, tcpname, AVIO_FLAG_READ_WRITE, &s->interrupt_callback, NULL, s->protocol_whitelist, s->protocol_blacklist, NULL)) { av_log(s, AV_LOG_ERROR, "Unable to open RTSP for listening\n"); return ret; } rt->state = RTSP_STATE_IDLE; rt->rtsp_hd_out = rt->rtsp_hd; for (;;) { /* Wait for incoming RTSP messages */ ret = read_line(s, rbuf, sizeof(rbuf), &rbuflen); if (ret < 0) return ret; ret = parse_command_line(s, rbuf, rbuflen, uri, sizeof(uri), method, sizeof(method), &methodcode); if (ret) { av_log(s, AV_LOG_ERROR, "RTSP: Unexpected Command\n"); return ret; } if (methodcode == ANNOUNCE) { ret = rtsp_read_announce(s); rt->state = RTSP_STATE_PAUSED; } else if (methodcode == OPTIONS) { ret = rtsp_read_options(s); } else if (methodcode == RECORD) { ret = rtsp_read_record(s); if (!ret) return 0; // We are ready for streaming } else if (methodcode == SETUP) ret = rtsp_read_setup(s, host, uri); if (ret) { ffurl_close(rt->rtsp_hd); return AVERROR_INVALIDDATA; } } }
static int rtsp_read_setup(AVFormatContext *s, char* host, char *controlurl) { RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; int ret = 0; char url[1024]; RTSPStream *rtsp_st; char responseheaders[1024]; int localport = -1; int transportidx = 0; int streamid = 0; ret = rtsp_read_request(s, &request, "SETUP"); if (ret) return ret; rt->seq++; if (!request.nb_transports) { av_log(s, AV_LOG_ERROR, "No transport defined in SETUP\n"); return AVERROR_INVALIDDATA; } for (transportidx = 0; transportidx < request.nb_transports; transportidx++) { if (!request.transports[transportidx].mode_record || (request.transports[transportidx].lower_transport != RTSP_LOWER_TRANSPORT_UDP && request.transports[transportidx].lower_transport != RTSP_LOWER_TRANSPORT_TCP)) { av_log(s, AV_LOG_ERROR, "mode=record/receive not set or transport" " protocol not supported (yet)\n"); return AVERROR_INVALIDDATA; } } if (request.nb_transports > 1) av_log(s, AV_LOG_WARNING, "More than one transport not supported, " "using first of all\n"); for (streamid = 0; streamid < rt->nb_rtsp_streams; streamid++) { if (!strcmp(rt->rtsp_streams[streamid]->control_url, controlurl)) break; } if (streamid == rt->nb_rtsp_streams) { av_log(s, AV_LOG_ERROR, "Unable to find requested track\n"); return AVERROR_STREAM_NOT_FOUND; } rtsp_st = rt->rtsp_streams[streamid]; localport = rt->rtp_port_min; if (request.transports[0].lower_transport == RTSP_LOWER_TRANSPORT_TCP) { rt->lower_transport = RTSP_LOWER_TRANSPORT_TCP; if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) { rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq); return ret; } rtsp_st->interleaved_min = request.transports[0].interleaved_min; rtsp_st->interleaved_max = request.transports[0].interleaved_max; snprintf(responseheaders, sizeof(responseheaders), "Transport: " "RTP/AVP/TCP;unicast;mode=receive;interleaved=%d-%d" "\r\n", request.transports[0].interleaved_min, request.transports[0].interleaved_max); } else { do { AVDictionary *opts = NULL; char buf[256]; snprintf(buf, sizeof(buf), "%d", rt->buffer_size); av_dict_set(&opts, "buffer_size", buf, 0); ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL); av_log(s, AV_LOG_TRACE, "Opening: %s", url); ret = ffurl_open_whitelist(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback, &opts, s->protocol_whitelist, s->protocol_blacklist, NULL); av_dict_free(&opts); if (ret) localport += 2; } while (ret || localport > rt->rtp_port_max); if (localport > rt->rtp_port_max) { rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq); return ret; } av_log(s, AV_LOG_TRACE, "Listening on: %d", ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle)); if ((ret = ff_rtsp_open_transport_ctx(s, rtsp_st))) { rtsp_send_reply(s, RTSP_STATUS_TRANSPORT, NULL, request.seq); return ret; } localport = ff_rtp_get_local_rtp_port(rtsp_st->rtp_handle); snprintf(responseheaders, sizeof(responseheaders), "Transport: " "RTP/AVP/UDP;unicast;mode=receive;source=%s;" "client_port=%d-%d;server_port=%d-%d\r\n", host, request.transports[0].client_port_min, request.transports[0].client_port_max, localport, localport + 1); } /* Establish sessionid if not previously set */ /* Put this in a function? */ /* RFC 2326: session id must be at least 8 digits */ while (strlen(rt->session_id) < 8) av_strlcatf(rt->session_id, 512, "%u", av_get_random_seed()); av_strlcatf(responseheaders, sizeof(responseheaders), "Session: %s\r\n", rt->session_id); /* Send Reply */ rtsp_send_reply(s, RTSP_STATUS_OK, responseheaders, request.seq); rt->state = RTSP_STATE_PAUSED; return 0; }
static int hls_read(URLContext *h, uint8_t *buf, int size) { HLSContext *s = h->priv_data; const char *url; int ret; int64_t reload_interval; start: if (s->seg_hd) { ret = ffurl_read(s->seg_hd, buf, size); if (ret > 0) return ret; } if (s->seg_hd) { ffurl_close(s->seg_hd); s->seg_hd = NULL; s->cur_seq_no++; } reload_interval = s->n_segments > 0 ? s->segments[s->n_segments - 1]->duration : s->target_duration; retry: if (!s->finished) { int64_t now = av_gettime_relative(); if (now - s->last_load_time >= reload_interval) { if ((ret = parse_playlist(h, s->playlisturl)) < 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 = s->target_duration / 2; } } if (s->cur_seq_no < s->start_seq_no) { av_log(h, AV_LOG_WARNING, "skipping %d segments ahead, expired from playlist\n", s->start_seq_no - s->cur_seq_no); s->cur_seq_no = s->start_seq_no; } if (s->cur_seq_no - s->start_seq_no >= s->n_segments) { if (s->finished) return AVERROR_EOF; while (av_gettime_relative() - s->last_load_time < reload_interval) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; av_usleep(100*1000); } goto retry; } url = s->segments[s->cur_seq_no - s->start_seq_no]->url; av_log(h, AV_LOG_DEBUG, "opening %s\n", url); ret = ffurl_open_whitelist(&s->seg_hd, url, AVIO_FLAG_READ, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h); if (ret < 0) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; av_log(h, AV_LOG_WARNING, "Unable to open %s\n", url); s->cur_seq_no++; goto retry; } goto start; }
static int crypto_open2(URLContext *h, const char *uri, int flags, AVDictionary **options) { const char *nested_url; int ret = 0; CryptoContext *c = h->priv_data; c->flags = flags; if (!av_strstart(uri, "crypto+", &nested_url) && !av_strstart(uri, "crypto:", &nested_url)) { av_log(h, AV_LOG_ERROR, "Unsupported url %s\n", uri); ret = AVERROR(EINVAL); goto err; } c->position = 0; if (flags & AVIO_FLAG_READ) { if ((ret = set_aes_arg(c, &c->decrypt_key, &c->decrypt_keylen, c->key, c->keylen, "decryption key")) < 0) goto err; if ((ret = set_aes_arg(c, &c->decrypt_iv, &c->decrypt_ivlen, c->iv, c->ivlen, "decryption IV")) < 0) goto err; } if (flags & AVIO_FLAG_WRITE) { if ((ret = set_aes_arg(c, &c->encrypt_key, &c->encrypt_keylen, c->key, c->keylen, "encryption key")) < 0) if (ret < 0) goto err; if ((ret = set_aes_arg(c, &c->encrypt_iv, &c->encrypt_ivlen, c->iv, c->ivlen, "encryption IV")) < 0) goto err; } if ((ret = ffurl_open_whitelist(&c->hd, nested_url, flags, &h->interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist, h)) < 0) { av_log(h, AV_LOG_ERROR, "Unable to open resource: %s\n", nested_url); goto err; } if (flags & AVIO_FLAG_READ) { c->aes_decrypt = av_aes_alloc(); if (!c->aes_decrypt) { ret = AVERROR(ENOMEM); goto err; } ret = av_aes_init(c->aes_decrypt, c->decrypt_key, BLOCKSIZE*8, 1); if (ret < 0) goto err; // pass back information about the context we openned if (c->hd->is_streamed) h->is_streamed = c->hd->is_streamed; } if (flags & AVIO_FLAG_WRITE) { c->aes_encrypt = av_aes_alloc(); if (!c->aes_encrypt) { ret = AVERROR(ENOMEM); goto err; } ret = av_aes_init(c->aes_encrypt, c->encrypt_key, BLOCKSIZE*8, 0); if (ret < 0) goto err; // for write, we must be streamed // - linear write only for crytpo aes-128-cbc h->is_streamed = 1; } c->pad_len = 0; err: return ret; }