static int rtsp_send_reply(AVFormatContext *s, enum RTSPStatusCode code, const char *extracontent, uint16_t seq) { RTSPState *rt = s->priv_data; char message[4096]; int index = 0; while (status_messages[index].code) { if (status_messages[index].code == code) { snprintf(message, sizeof(message), "RTSP/1.0 %d %s\r\n", code, status_messages[index].message); break; } index++; } if (!status_messages[index].code) return AVERROR(EINVAL); av_strlcatf(message, sizeof(message), "CSeq: %d\r\n", seq); av_strlcatf(message, sizeof(message), "Server: %s\r\n", LIBAVFORMAT_IDENT); if (extracontent) av_strlcat(message, extracontent, sizeof(message)); av_strlcat(message, "\r\n", sizeof(message)); av_dlog(s, "Sending response:\n%s", message); ffurl_write(rt->rtsp_hd, message, strlen(message)); return 0; }
/* Match desired bitrate */ static int get_bitrate_mode(int bitrate, void *log_ctx) { /* make the correspondance between bitrate and mode */ static const AMR_bitrates rates[] = { { 4750, MR475 }, { 5150, MR515 }, { 5900, MR59 }, { 6700, MR67 }, { 7400, MR74 }, { 7950, MR795 }, { 10200, MR102 }, { 12200, MR122 } }; int i, best = -1, min_diff = 0; char log_buf[200]; for (i = 0; i < 8; i++) { if (rates[i].rate == bitrate) return rates[i].mode; if (best < 0 || abs(rates[i].rate - bitrate) < min_diff) { best = i; min_diff = abs(rates[i].rate - bitrate); } } /* no bitrate matching exactly, log a warning */ snprintf(log_buf, sizeof(log_buf), "bitrate not supported: use one of "); for (i = 0; i < 8; i++) av_strlcatf(log_buf, sizeof(log_buf), "%.2fk, ", rates[i].rate / 1000.f); av_strlcatf(log_buf, sizeof(log_buf), "using %.2fk", rates[best].rate / 1000.f); av_log(log_ctx, AV_LOG_WARNING, "%s\n", log_buf); return best; }
static int framecrc_write_packet(struct AVFormatContext *s, AVPacket *pkt) { uint32_t crc = av_adler32_update(0, pkt->data, pkt->size); char buf[256]; snprintf(buf, sizeof(buf), "%d, %10"PRId64", %10"PRId64", %8d, %8d, 0x%08x", pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size, crc); if (pkt->flags != AV_PKT_FLAG_KEY) av_strlcatf(buf, sizeof(buf), ", F=0x%0X", pkt->flags); if (pkt->side_data_elems) { int i, j; av_strlcatf(buf, sizeof(buf), ", S=%d", pkt->side_data_elems); for (i=0; i<pkt->side_data_elems; i++) { uint32_t side_data_crc = 0; if (HAVE_BIGENDIAN && AV_PKT_DATA_PALETTE == pkt->side_data[i].type) { for (j=0; j<pkt->side_data[i].size; j++) { side_data_crc = av_adler32_update(side_data_crc, pkt->side_data[i].data + (j^3), 1); } } else { side_data_crc = av_adler32_update(0, pkt->side_data[i].data, pkt->side_data[i].size); } av_strlcatf(buf, sizeof(buf), ", %8d, 0x%08x", pkt->side_data[i].size, side_data_crc); } } av_strlcatf(buf, sizeof(buf), "\n"); avio_write(s->pb, buf, strlen(buf)); return 0; }
static void sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, int port, int ttl) { const char *type; int payload_type; payload_type = ff_rtp_get_payload_type(c); if (payload_type < 0) { payload_type = RTP_PT_PRIVATE + (c->codec_type == CODEC_TYPE_AUDIO); } switch (c->codec_type) { case CODEC_TYPE_VIDEO : type = "video" ; break; case CODEC_TYPE_AUDIO : type = "audio" ; break; case CODEC_TYPE_SUBTITLE: type = "text" ; break; default : type = "application"; break; } av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type); sdp_write_address(buff, size, dest_addr, ttl); if (c->bit_rate) { av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000); } sdp_write_media_attributes(buff, size, c, payload_type); }
static int func_eval_expr_int_format(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { DrawTextContext *s = ctx->priv; double res; int intval; int ret; unsigned int positions = 0; char fmt_str[30] = "%"; /* * argv[0] expression to be converted to `int` * argv[1] format: 'x', 'X', 'd' or 'u' * argv[2] positions printed (optional) */ ret = av_expr_parse_and_eval(&res, argv[0], var_names, s->var_values, NULL, NULL, fun2_names, fun2, &s->prng, 0, ctx); if (ret < 0) { av_log(ctx, AV_LOG_ERROR, "Expression '%s' for the expr text expansion function is not valid\n", argv[0]); return ret; } if (!strchr("xXdu", argv[1][0])) { av_log(ctx, AV_LOG_ERROR, "Invalid format '%c' specified," " allowed values: 'x', 'X', 'd', 'u'\n", argv[1][0]); return AVERROR(EINVAL); } if (argc == 3) { ret = sscanf(argv[2], "%u", &positions); if (ret != 1) { av_log(ctx, AV_LOG_ERROR, "expr_int_format(): Invalid number of positions" " to print: '%s'\n", argv[2]); return AVERROR(EINVAL); } } feclearexcept(FE_ALL_EXCEPT); intval = res; if ((ret = fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW))) { av_log(ctx, AV_LOG_ERROR, "Conversion of floating-point result to int failed. Control register: 0x%08x. Conversion result: %d\n", ret, intval); return AVERROR(EINVAL); } if (argc == 3) av_strlcatf(fmt_str, sizeof(fmt_str), "0%u", positions); av_strlcatf(fmt_str, sizeof(fmt_str), "%c", argv[1][0]); av_log(ctx, AV_LOG_DEBUG, "Formatting value %f (expr '%s') with spec '%s'\n", res, argv[0], fmt_str); av_bprintf(bp, fmt_str, intval); return 0; }
static void sdp_write_address(char *buff, int size, const char *dest_addr, int ttl) { if (dest_addr) { if (ttl > 0) { av_strlcatf(buff, size, "c=IN IP4 %s/%d\r\n", dest_addr, ttl); } else { av_strlcatf(buff, size, "c=IN IP4 %s\r\n", dest_addr); } } }
static void sdp_write_header(char *buff, int size, struct sdp_session_level *s) { av_strlcatf(buff, size, "v=%d\r\n" "o=- %d %d IN IP4 %s\r\n" "s=%s\r\n", s->sdp_version, s->id, s->version, s->src_addr, s->name); sdp_write_address(buff, size, s->dst_addr, s->ttl); av_strlcatf(buff, size, "t=%d %d\r\n" "a=tool:libavformat " AV_STRINGIFY(LIBAVFORMAT_VERSION) "\r\n", s->start_time, s->end_time); }
void ff_rdt_subscribe_rule (char *cmd, int size, int stream_nr, int rule_nr) { av_strlcatf(cmd, size, "stream=%d;rule=%d,stream=%d;rule=%d", stream_nr, rule_nr * 2, stream_nr, rule_nr * 2 + 1); }
static av_cold void uninit(AVFilterContext *ctx) { PSNRContext *s = ctx->priv; if (s->nb_frames > 0) { int j; char buf[256]; buf[0] = 0; for (j = 0; j < s->nb_components; j++) { int c = s->is_rgb ? s->rgba_map[j] : j; av_strlcatf(buf, sizeof(buf), " %c:%f", s->comps[j], get_psnr(s->mse_comp[c], s->nb_frames, s->max[c])); } av_log(ctx, AV_LOG_INFO, "PSNR%s average:%f min:%f max:%f\n", buf, get_psnr(s->mse, s->nb_frames, s->average_max), get_psnr(s->max_mse, 1, s->average_max), get_psnr(s->min_mse, 1, s->average_max)); } ff_dualinput_uninit(&s->dinput); if (s->stats_file && s->stats_file != stdout) fclose(s->stats_file); }
int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags) { if(!strcmp(cmd, "ping")){ av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name); return 0; }else if(filter->filter->process_command) { return filter->filter->process_command(filter, cmd, arg, res, res_len, flags); } return AVERROR(ENOSYS); }
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt, ...) { #if CONFIG_NETWORK struct addrinfo hints = { 0 }, *ai; #endif str[0] = '\0'; if (proto) av_strlcatf(str, size, "%s://", proto); if (authorization && authorization[0]) av_strlcatf(str, size, "%s@", authorization); #if CONFIG_NETWORK && defined(AF_INET6) /* Determine if hostname is a numerical IPv6 address, * properly escape it within [] in that case. */ hints.ai_flags = AI_NUMERICHOST; if (!getaddrinfo(hostname, NULL, &hints, &ai)) { if (ai->ai_family == AF_INET6) { av_strlcat(str, "[", size); av_strlcat(str, hostname, size); av_strlcat(str, "]", size); } else { av_strlcat(str, hostname, size); } freeaddrinfo(ai); } else #endif /* Not an IPv6 address, just output the plain string. */ av_strlcat(str, hostname, size); if (port >= 0) av_strlcatf(str, size, ":%d", port); if (fmt) { va_list vl; size_t len = strlen(str); va_start(vl, fmt); vsnprintf(str + len, size > len ? size - len : 0, fmt, vl); va_end(vl); } return strlen(str); }
static int trace_headers(AVBSFContext *bsf, AVPacket *out) { TraceHeadersContext *ctx = bsf->priv_data; CodedBitstreamFragment au; AVPacket *in; char tmp[256] = { 0 }; int err; err = ff_bsf_get_packet(bsf, &in); if (err < 0) return err; if (in->flags & AV_PKT_FLAG_KEY) av_strlcat(tmp, ", key frame", sizeof(tmp)); if (in->flags & AV_PKT_FLAG_CORRUPT) av_strlcat(tmp, ", corrupt", sizeof(tmp)); if (in->pts != AV_NOPTS_VALUE) av_strlcatf(tmp, sizeof(tmp), ", pts %"PRId64, in->pts); else av_strlcat(tmp, ", no pts", sizeof(tmp)); if (in->dts != AV_NOPTS_VALUE) av_strlcatf(tmp, sizeof(tmp), ", dts %"PRId64, in->dts); else av_strlcat(tmp, ", no dts", sizeof(tmp)); if (in->duration > 0) av_strlcatf(tmp, sizeof(tmp), ", duration %"PRId64, in->duration); av_log(bsf, AV_LOG_INFO, "Packet: %d bytes%s.\n", in->size, tmp); err = ff_cbs_read_packet(&ctx->cbc, &au, in); if (err < 0) return err; ff_cbs_fragment_uninit(&ctx->cbc, &au); av_packet_move_ref(out, in); av_packet_free(&in); return 0; }
int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; int ret, i, simple = !fg->graph_desc; const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; avfilter_graph_free(&fg->graph); if (!(fg->graph = avfilter_graph_alloc())) return AVERROR(ENOMEM); if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[512]; AVDictionaryEntry *e = NULL; snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags); fg->graph->scale_sws_opts = av_strdup(args); args[0] = '\0'; while ((e = av_dict_get(fg->outputs[0]->ost->resample_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args) - 1] = '\0'; fg->graph->resample_lavr_opts = av_strdup(args); } if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) return ret; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have " "exactly one input and output.\n", graph_desc); return AVERROR(EINVAL); } for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) return ret; avfilter_inout_free(&inputs); for (cur = outputs, i = 0; cur; cur = cur->next, i++) configure_output_filter(fg, fg->outputs[i], cur); avfilter_inout_free(&outputs); if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) return ret; return 0; }
static int peak_write_chunk(AVFormatContext *s) { WAVMuxContext *wav = s->priv_data; AVIOContext *pb = s->pb; AVCodecContext *enc = s->streams[0]->codec; int64_t peak = ff_start_tag(s->pb, "levl"); int64_t now0; time_t now_secs; char timestamp[28]; /* Peak frame of incomplete block at end */ if (wav->peak_block_pos) peak_write_frame(s); memset(timestamp, 0, sizeof(timestamp)); if (!(s->flags & AVFMT_FLAG_BITEXACT)) { struct tm tmpbuf; av_log(s, AV_LOG_INFO, "Writing local time and date to Peak Envelope Chunk\n"); now0 = av_gettime(); now_secs = now0 / 1000000; if (strftime(timestamp, sizeof(timestamp), "%Y:%m:%d:%H:%M:%S:", localtime_r(&now_secs, &tmpbuf))) { av_strlcatf(timestamp, sizeof(timestamp), "%03d", (int)((now0 / 1000) % 1000)); } else { av_log(s, AV_LOG_ERROR, "Failed to write timestamp\n"); return -1; } } avio_wl32(pb, 1); /* version */ avio_wl32(pb, wav->peak_format); /* 8 or 16 bit */ avio_wl32(pb, wav->peak_ppv); /* positive and negative */ avio_wl32(pb, wav->peak_block_size); /* frames per value */ avio_wl32(pb, enc->channels); /* number of channels */ avio_wl32(pb, wav->peak_num_frames); /* number of peak frames */ avio_wl32(pb, wav->peak_pos_pop); /* audio sample frame index */ avio_wl32(pb, 128); /* equal to size of header */ avio_write(pb, timestamp, 28); /* ASCII time stamp */ ffio_fill(pb, 0, 60); avio_write(pb, wav->peak_output, wav->peak_outbuf_bytes); ff_end_tag(pb, peak); if (!wav->data) wav->data = peak; return 0; }
int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size) { AVMetadataTag *title = av_metadata_get(ac[0]->metadata, "title", NULL, 0); struct sdp_session_level s; int i, j, port, ttl; char dst[32]; memset(buff, 0, size); memset(&s, 0, sizeof(struct sdp_session_level)); s.user = "******"; s.src_addr = "127.0.0.1"; /* FIXME: Properly set this */ s.name = title ? title->value : "No Name"; port = 0; ttl = 0; if (n_files == 1) { port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->filename); resolve_destination(dst, sizeof(dst)); if (dst[0]) { s.dst_addr = dst; s.ttl = ttl; } } sdp_write_header(buff, size, &s); dst[0] = 0; for (i = 0; i < n_files; i++) { if (n_files != 1) { port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->filename); resolve_destination(dst, sizeof(dst)); } for (j = 0; j < ac[i]->nb_streams; j++) { sdp_write_media(buff, size, ac[i]->streams[j]->codec, dst[0] ? dst : NULL, (port > 0) ? port + j * 2 : 0, ttl); if (port <= 0) { av_strlcatf(buff, size, "a=control:streamid=%d\r\n", i + j); } } } return 0; }
int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags) { if(!strcmp(cmd, "ping")){ char local_res[256] = {0}; if (!res) { res = local_res; res_len = sizeof(local_res); } av_strlcatf(res, res_len, "pong from:%s %s\n", filter->filter->name, filter->name); if (res == local_res) av_log(filter, AV_LOG_INFO, "%s", res); return 0; }else if(!strcmp(cmd, "enable")) { return set_enable_expr(filter, arg); }else if(filter->filter->process_command) { return filter->filter->process_command(filter, cmd, arg, res, res_len, flags); } return AVERROR(ENOSYS); }
// Concat all Icy- header lines static int parse_icy(HTTPContext *s, const char *tag, const char *p) { int len = 4 + strlen(p) + strlen(tag); int is_first = !s->icy_metadata_headers; int ret; av_dict_set(&s->metadata, tag, p, 0); if (s->icy_metadata_headers) len += strlen(s->icy_metadata_headers); if ((ret = av_reallocp(&s->icy_metadata_headers, len)) < 0) return ret; if (is_first) *s->icy_metadata_headers = '\0'; av_strlcatf(s->icy_metadata_headers, len, "%s: %s\n", tag, p); return 0; }
static int cookie_string(AVDictionary *dict, char **cookies) { AVDictionaryEntry *e = NULL; int len = 1; // determine how much memory is needed for the cookies string while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)) len += strlen(e->key) + strlen(e->value) + 1; // reallocate the cookies e = NULL; if (*cookies) av_free(*cookies); *cookies = av_malloc(len); if (!*cookies) return AVERROR(ENOMEM); *cookies[0] = '\0'; // write out the cookies while (e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)) av_strlcatf(*cookies, len, "%s%s\n", e->key, e->value); return 0; }
int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply) { RTSPState *rt = s->priv_data; char cmd[1024]; unsigned char *content = NULL; int ret; /* describe the stream */ snprintf(cmd, sizeof(cmd), "Accept: application/sdp\r\n"); av_strlcatf(cmd, sizeof(cmd), "User-Agent: %s\r\n", rt->user_agent); if (rt->server_type == RTSP_SERVER_REAL) { /** * The Require: attribute is needed for proper streaming from * Realmedia servers. */ av_strlcat(cmd, "Require: com.real.retain-entity-for-setup\r\n", sizeof(cmd)); } ff_rtsp_send_cmd(s, "DESCRIBE", rt->control_uri, cmd, reply, &content); if (!content) return AVERROR_INVALIDDATA; if (reply->status_code != RTSP_STATUS_OK) { av_freep(&content); return AVERROR_INVALIDDATA; } av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", content); /* now we got the SDP description, we parse it */ ret = ff_sdp_parse(s, (const char *)content); av_freep(&content); if (ret < 0) return ret; return 0; }
static av_cold void uninit(AVFilterContext *ctx) { SSIMContext *s = ctx->priv; if (s->nb_frames > 0) { char buf[256]; int i; buf[0] = 0; for (i = 0; i < s->nb_components; i++) { int c = s->is_rgb ? s->rgba_map[i] : i; av_strlcatf(buf, sizeof(buf), " %c:%f (%f)", s->comps[i], s->ssim[c] / s->nb_frames, ssim_db(s->ssim[c], s->nb_frames)); } av_log(ctx, AV_LOG_INFO, "SSIM%s All:%f (%f)\n", buf, s->ssim_total / s->nb_frames, ssim_db(s->ssim_total, s->nb_frames)); } ff_framesync_uninit(&s->fs); if (s->stats_file && s->stats_file != stdout) fclose(s->stats_file); av_freep(&s->temp); }
int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; int ret, i, init = !fg->graph, simple = !fg->graph_desc; const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; avfilter_graph_free(&fg->graph); if (!(fg->graph = avfilter_graph_alloc())) return AVERROR(ENOMEM); if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[512]; AVDictionaryEntry *e = NULL; snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags); fg->graph->scale_sws_opts = av_strdup(args); args[0] = '\0'; while ((e = av_dict_get(fg->outputs[0]->ost->resample_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args) - 1] = '\0'; fg->graph->resample_lavr_opts = av_strdup(args); } if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) return ret; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have " "exactly one input and output.\n", graph_desc); return AVERROR(EINVAL); } for (cur = inputs; !simple && init && cur; cur = cur->next) init_input_filter(fg, cur); for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) return ret; avfilter_inout_free(&inputs); if (!init || simple) { /* we already know the mappings between lavfi outputs and output streams, * so we can finish the setup */ for (cur = outputs, i = 0; cur; cur = cur->next, i++) configure_output_filter(fg, fg->outputs[i], cur); avfilter_inout_free(&outputs); if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) return ret; } else { /* wait until output mappings are processed */ for (cur = outputs; cur;) { GROW_ARRAY(fg->outputs, fg->nb_outputs); if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0])))) exit(1); fg->outputs[fg->nb_outputs - 1]->graph = fg; fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; cur = cur->next; fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; } } return 0; }
/* parse HTTP request and prepare header */ static int http_parse_request(HTTPContext *c) { char *q, msg[1024]; const char *mime_type, *p; HTTPContext *ctx; int ret = 0, is_first = 0; const char *first_tag = "First-Request=0"; RequestData rd = {{0}}; p = c->buffer; while(get_line(msg, sizeof(msg), &p) > 0){ ret = handle_line(c, msg, sizeof(msg), &rd); if(ret < 0)return ret; } is_first = !av_stristr(rd.cookie, first_tag); if(c->post && c->content_length && !av_match_ext(c->url, "m3u8") && !av_match_ext(c->url, "ts") && !av_match_ext(c->url, "flv")){ c->post = 0; c->content_length = read_request_content(c, rd.content, sizeof(rd.content)); } #if defined(PLUGIN_DVB) if(!c->post && !strcmp(c->url, "digitalDvb/allServiceType/getClientInfo")){ uint32_t *ptr = (uint32_t*)rd.content, *ptr_end = (uint32_t*)(rd.content+sizeof(rd.content)-8); for(ctx = first_http_ctx; ctx; ctx = ctx->next) if(!ctx->post && av_match_ext(ctx->url, "flv") ) {/*todo: record hls*/ if(ptr < ptr_end){ int chid = -1; sscanf(ctx->url, "%d", &chid); *ptr++ = inet_addr(inet_ntoa(ctx->from_addr.sin_addr)); *ptr++ = chid; printf("ip %s id %u %s\t", inet_ntoa(ctx->from_addr.sin_addr), chid, ctx->url); } } } #endif //http_log("New conn: %s:%u %d %s cookie:%s\n", inet_ntoa(c->from_addr.sin_addr), ntohs(c->from_addr.sin_port), c->post, c->url, rd.cookie); /*handle m3u8/ts request solely*/ if(av_match_ext(c->url, "m3u8") || av_match_ext(c->url, "ts")){ c->keep_alive = 0; ret = hls_parse_request(c, c->url, is_first); if(ret < 0)goto send_error; else if(ret == 1){ long chid = atoi(c->url); if(!(0 <= chid && chid <= 10000)){ sprintf(msg, "bad request: %s-->%ld", c->url, chid); http_log("%s\n", msg); goto send_error; } #if defined(PLUGIN_DVB) ff_ctl_send_string(1, c->url, rd.content); #endif http_log("wait get %s\n", c->url); } if(c->state == HTTPSTATE_SEND_HEADER) goto send_header; return 0; /*end here*/ } #if defined(PLUGIN_DVB) ret = plugin_dvb(c, &rd); if(ret < 0){ goto send_error; }else if(ret > 0){ return 0; } #endif /*handle feed request*/ if (c->post) { ctx = find_feed(c->url); if(ctx && ctx != c){ sprintf(msg, "file %s has been feeded", c->url); http_log("%s\n", msg); goto send_error; } c->http_error = 0; c->state = HTTPSTATE_RECEIVE_DATA; return 0; /*end here*/ }else{ if(prepare_local_file(c) > 0){ c->http_error = 200; c->state = HTTPSTATE_SEND_HEADER; return 0; /*no need feed, send local files directly.*/ } ctx = find_feed(c->url); if(!ctx){ c->keep_alive = 0; sprintf(msg, "wait to get %s", c->url); http_log("%s\n", msg); #if defined(PLUGIN_DVB) ff_ctl_send(2, c->url, strlen(c->url)+1, rd.content, sizeof(rd.content)); #endif }else{ ctx->sff_ref_cnt++; } c->feed_ctx = ctx; } send_header: /* prepare HTTP header */ c->buffer[0] = 0; av_strlcatf(c->buffer, c->buffer_size, "HTTP/1.1 200 OK\r\n"); mime_type = get_mine_type(c->url); av_strlcatf(c->buffer, c->buffer_size, "Pragma: no-cache\r\n"); av_strlcatf(c->buffer, c->buffer_size, "Content-Type: %s\r\n", mime_type); av_strlcatf(c->buffer, c->buffer_size, "Connection: %s\r\n", (c->keep_alive ? "keep-alive" : "close")); av_strlcatf(c->buffer, c->buffer_size, "Set-Cookie: %s; Path=/; Domain=%s\r\n", first_tag, rd.domain); av_strlcatf(c->buffer, c->buffer_size, "\r\n"); q = c->buffer + strlen(c->buffer); /* prepare output buffer */ c->http_error = 0; c->buffer_ptr = c->buffer; c->buffer_end = q; c->state = HTTPSTATE_SEND_HEADER; #if 0 if(S == c->hls_idx){ HLS *s = &s_hls[c->hls_idx]; char *ext = strrchr(c->url, '.'); if(!(2 == s->flag && s->data && s->csize > 0)){/*not exist yet, fake one*/ c->http_error = 200; c->buffer_end += sprintf(c->buffer_end, "#EXTM3U\n" "#EXT-X-VERSION:3\n" "#EXT-X-TARGETDURATION:2\n" "#EXT-X-MEDIA-SEQUENCE:0\n" "#EXTINF:1.283989,\n" "%.*s0.ts\n", ext - c->url, c->url); } } #endif return 0; send_error: c->keep_alive = 0; c->http_error = 404; q = c->buffer; htmlstrip(msg); snprintf(q, c->buffer_size, "HTTP/1.1 404 Not Found\r\n" "Content-type: text/html\r\n" "\r\n" "<html>\n" "<head><title>404 Not Found</title></head>\n" "<body>%s</body>\n" "</html>\n", msg); q += strlen(q); /* prepare output buffer */ c->buffer_ptr = c->buffer; c->buffer_end = q; c->state = HTTPSTATE_SEND_HEADER; return 0; }
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) { RTSPState *rt = s->priv_data; int ret; RTSPMessageHeader reply1, *reply = &reply1; char cmd[1024]; retry: if (rt->server_type == RTSP_SERVER_REAL) { int i; for (i = 0; i < s->nb_streams; i++) rt->real_setup[i] = s->streams[i]->discard; if (!rt->need_subscription) { if (memcmp (rt->real_setup, rt->real_setup_cache, sizeof(enum AVDiscard) * s->nb_streams)) { snprintf(cmd, sizeof(cmd), "Unsubscribe: %s\r\n", rt->last_subscription); ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; rt->need_subscription = 1; } } if (rt->need_subscription) { int r, rule_nr, first = 1; memcpy(rt->real_setup_cache, rt->real_setup, sizeof(enum AVDiscard) * s->nb_streams); rt->last_subscription[0] = 0; snprintf(cmd, sizeof(cmd), "Subscribe: "); for (i = 0; i < rt->nb_rtsp_streams; i++) { rule_nr = 0; for (r = 0; r < s->nb_streams; r++) { if (s->streams[r]->id == i) { if (s->streams[r]->discard != AVDISCARD_ALL) { if (!first) av_strlcat(rt->last_subscription, ",", sizeof(rt->last_subscription)); ff_rdt_subscribe_rule( rt->last_subscription, sizeof(rt->last_subscription), i, rule_nr); first = 0; } rule_nr++; } } } av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription); ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; rt->need_subscription = 0; if (rt->state == RTSP_STATE_STREAMING) rtsp_read_play (s); } } ret = ff_rtsp_fetch_packet(s, pkt); if (ret < 0) { if (ret == AVERROR(ETIMEDOUT) && !rt->packets) { if (rt->lower_transport == RTSP_LOWER_TRANSPORT_UDP && rt->lower_transport_mask & (1 << RTSP_LOWER_TRANSPORT_TCP)) { RTSPMessageHeader reply1, *reply = &reply1; av_log(s, AV_LOG_WARNING, "UDP timeout, retrying with TCP\n"); if (rtsp_read_pause(s) != 0) return -1; // TEARDOWN is required on Real-RTSP, but might make // other servers close the connection. if (rt->server_type == RTSP_SERVER_REAL) ff_rtsp_send_cmd(s, "TEARDOWN", rt->control_uri, NULL, reply, NULL); rt->session_id[0] = '\0'; if (resetup_tcp(s) == 0) { rt->state = RTSP_STATE_IDLE; rt->need_subscription = 1; if (rtsp_read_play(s) != 0) return -1; goto retry; } } } return ret; } rt->packets++; /* send dummy request to keep TCP connection alive */ if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 || rt->auth_state.stale) { if (rt->server_type == RTSP_SERVER_WMS || (rt->server_type != RTSP_SERVER_REAL && rt->get_parameter_supported)) { ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); } else { ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); } /* The stale flag should be reset when creating the auth response in * ff_rtsp_send_cmd_async, but reset it here just in case we never * called the auth code (if we didn't have any credentials set). */ rt->auth_state.stale = 0; } return 0; }
int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; int ret, i, simple = !fg->graph_desc; const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter : fg->graph_desc; avfilter_graph_free(&fg->graph); if (!(fg->graph = avfilter_graph_alloc())) return AVERROR(ENOMEM); if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[512]; AVDictionaryEntry *e = NULL; args[0] = 0; while ((e = av_dict_get(ost->sws_dict, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args)-1] = 0; fg->graph->scale_sws_opts = av_strdup(args); args[0] = 0; while ((e = av_dict_get(ost->swr_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args)-1] = 0; av_opt_set(fg->graph, "aresample_swr_opts", args, 0); args[0] = '\0'; while ((e = av_dict_get(fg->outputs[0]->ost->resample_opts, "", e, AV_DICT_IGNORE_SUFFIX))) { av_strlcatf(args, sizeof(args), "%s=%s:", e->key, e->value); } if (strlen(args)) args[strlen(args) - 1] = '\0'; fg->graph->resample_lavr_opts = av_strdup(args); e = av_dict_get(ost->encoder_opts, "threads", NULL, 0); if (e) av_opt_set(fg->graph, "threads", e->value, 0); } if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0) return ret; if (simple && (!inputs || inputs->next || !outputs || outputs->next)) { const char *num_inputs; const char *num_outputs; if (!outputs) { num_outputs = "0"; } else if (outputs->next) { num_outputs = ">1"; } else { num_outputs = "1"; } if (!inputs) { num_inputs = "0"; } else if (inputs->next) { num_inputs = ">1"; } else { num_inputs = "1"; } av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " "to have exactly 1 input and 1 output." " However, it had %s input(s) and %s output(s)." " Please adjust, or use a complex filtergraph (-filter_complex) instead.\n", graph_desc, num_inputs, num_outputs); return AVERROR(EINVAL); } for (cur = inputs, i = 0; cur; cur = cur->next, i++) if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0) { avfilter_inout_free(&inputs); avfilter_inout_free(&outputs); return ret; } avfilter_inout_free(&inputs); for (cur = outputs, i = 0; cur; cur = cur->next, i++) configure_output_filter(fg, fg->outputs[i], cur); avfilter_inout_free(&outputs); if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) return ret; fg->reconfiguration = 1; for (i = 0; i < fg->nb_outputs; i++) { OutputStream *ost = fg->outputs[i]->ost; if (!ost->enc) { /* identical to the same check in ffmpeg.c, needed because complex filter graphs are initialized earlier */ av_log(NULL, AV_LOG_ERROR, "Encoder (codec %s) not found for output stream #%d:%d\n", avcodec_get_name(ost->st->codec->codec_id), ost->file_index, ost->index); return AVERROR(EINVAL); } if (ost->enc->type == AVMEDIA_TYPE_AUDIO && !(ost->enc->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) av_buffersink_set_frame_size(ost->filter->filter, ost->enc_ctx->frame_size); } return 0; }
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 { ff_url_join(url, sizeof(url), "rtp", NULL, host, localport, NULL); av_dlog(s, "Opening: %s", url); ret = ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback, NULL); 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_dlog(s, "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 http_connect(URLContext *h, const char *path, const char *hoststr, const char *auth, int *new_location) { HTTPContext *s = h->priv_data; int post, err; char line[1024]; char headers[1024] = ""; char *authstr = NULL; int64_t off = s->off; int len = 0; /* send http header */ post = h->flags & URL_WRONLY; authstr = ff_http_auth_create_response(&s->auth_state, auth, path, post ? "POST" : "GET"); /* set default headers if needed */ if (!has_header(s->headers, "\r\nUser-Agent: ")) len += av_strlcatf(headers + len, sizeof(headers) - len, "User-Agent: %s\r\n", LIBAVFORMAT_IDENT); if (!has_header(s->headers, "\r\nAccept: ")) len += av_strlcpy(headers + len, "Accept: */*\r\n", sizeof(headers) - len); if (!has_header(s->headers, "\r\nRange: ")) len += av_strlcatf(headers + len, sizeof(headers) - len, "Range: bytes=%"PRId64"-\r\n", s->off); if (!has_header(s->headers, "\r\nConnection: ")) len += av_strlcpy(headers + len, "Connection: close\r\n", sizeof(headers)-len); if (!has_header(s->headers, "\r\nHost: ")) len += av_strlcatf(headers + len, sizeof(headers) - len, "Host: %s\r\n", hoststr); /* now add in custom headers */ av_strlcpy(headers+len, s->headers, sizeof(headers)-len); snprintf(s->buffer, sizeof(s->buffer), "%s %s HTTP/1.1\r\n" "%s" "%s" "%s" "\r\n", post ? "POST" : "GET", path, post && s->is_chunked ? "Transfer-Encoding: chunked\r\n" : "", headers, authstr ? authstr : ""); av_freep(&authstr); if (url_write(s->hd, s->buffer, strlen(s->buffer)) < 0) return AVERROR(EIO); /* init input buffer */ s->buf_ptr = s->buffer; s->buf_end = s->buffer; s->line_count = 0; s->off = 0; s->filesize = -1; s->chunksize = -1; if (post) { /* always use chunked encoding for upload data */ s->chunksize = 0; /* Pretend that it did work. We didn't read any header yet, since * we've still to send the POST data, but the code calling this * function will check http_code after we return. */ s->http_code = 200; return 0; } /* wait for header */ for(;;) { if (http_get_line(s, line, sizeof(line)) < 0) return AVERROR(EIO); dprintf(NULL, "header='%s'\n", line); err = process_line(h, line, s->line_count, new_location); if (err < 0) return err; if (err == 0) break; s->line_count++; } return (off == s->off) ? 0 : -1; }
/* Generate a digest reply, according to RFC 2617. */ static char *make_digest_auth(HTTPAuthState *state, const char *username, const char *password, const char *uri, const char *method) { DigestParams *digest = &state->digest_params; int len; uint32_t cnonce_buf[2]; char cnonce[17]; char nc[9]; int i; char A1hash[33], A2hash[33], response[33]; struct AVMD5 *md5ctx; uint8_t hash[16]; char *authstr; digest->nc++; snprintf(nc, sizeof(nc), "%08x", digest->nc); /* Generate a client nonce. */ for (i = 0; i < 2; i++) cnonce_buf[i] = av_get_random_seed(); ff_data_to_hex(cnonce, (const uint8_t*) cnonce_buf, sizeof(cnonce_buf), 1); cnonce[2*sizeof(cnonce_buf)] = 0; md5ctx = av_md5_alloc(); if (!md5ctx) return NULL; av_md5_init(md5ctx); update_md5_strings(md5ctx, username, ":", state->realm, ":", password, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A1hash, hash, 16, 1); A1hash[32] = 0; if (!strcmp(digest->algorithm, "") || !strcmp(digest->algorithm, "MD5")) { } else if (!strcmp(digest->algorithm, "MD5-sess")) { av_md5_init(md5ctx); update_md5_strings(md5ctx, A1hash, ":", digest->nonce, ":", cnonce, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A1hash, hash, 16, 1); A1hash[32] = 0; } else { /* Unsupported algorithm */ av_free(md5ctx); return NULL; } av_md5_init(md5ctx); update_md5_strings(md5ctx, method, ":", uri, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A2hash, hash, 16, 1); A2hash[32] = 0; av_md5_init(md5ctx); update_md5_strings(md5ctx, A1hash, ":", digest->nonce, NULL); if (!strcmp(digest->qop, "auth") || !strcmp(digest->qop, "auth-int")) { update_md5_strings(md5ctx, ":", nc, ":", cnonce, ":", digest->qop, NULL); } update_md5_strings(md5ctx, ":", A2hash, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(response, hash, 16, 1); response[32] = 0; av_free(md5ctx); if (!strcmp(digest->qop, "") || !strcmp(digest->qop, "auth")) { } else if (!strcmp(digest->qop, "auth-int")) { /* qop=auth-int not supported */ return NULL; } else { /* Unsupported qop value. */ return NULL; } len = strlen(username) + strlen(state->realm) + strlen(digest->nonce) + strlen(uri) + strlen(response) + strlen(digest->algorithm) + strlen(digest->opaque) + strlen(digest->qop) + strlen(cnonce) + strlen(nc) + 150; authstr = av_malloc(len); if (!authstr) return NULL; snprintf(authstr, len, "Authorization: Digest "); /* TODO: Escape the quoted strings properly. */ av_strlcatf(authstr, len, "username=\"%s\"", username); av_strlcatf(authstr, len, ", realm=\"%s\"", state->realm); av_strlcatf(authstr, len, ", nonce=\"%s\"", digest->nonce); av_strlcatf(authstr, len, ", uri=\"%s\"", uri); av_strlcatf(authstr, len, ", response=\"%s\"", response); if (digest->algorithm[0]) av_strlcatf(authstr, len, ", algorithm=%s", digest->algorithm); if (digest->opaque[0]) av_strlcatf(authstr, len, ", opaque=\"%s\"", digest->opaque); if (digest->qop[0]) { av_strlcatf(authstr, len, ", qop=\"%s\"", digest->qop); av_strlcatf(authstr, len, ", cnonce=\"%s\"", cnonce); av_strlcatf(authstr, len, ", nc=%s", nc); } av_strlcatf(authstr, len, "\r\n"); return authstr; }
int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr) { RTSPState *rt = s->priv_data; RTSPMessageHeader reply1, *reply = &reply1; int i; char *sdp; AVFormatContext sdp_ctx, *ctx_array[1]; s->start_time_realtime = av_gettime(); /* Announce the stream */ sdp = av_mallocz(SDP_MAX_SIZE); if (sdp == NULL) return AVERROR(ENOMEM); /* We create the SDP based on the RTSP AVFormatContext where we * aren't allowed to change the filename field. (We create the SDP * based on the RTSP context since the contexts for the RTP streams * don't exist yet.) In order to specify a custom URL with the actual * peer IP instead of the originally specified hostname, we create * a temporary copy of the AVFormatContext, where the custom URL is set. * * FIXME: Create the SDP without copying the AVFormatContext. * This either requires setting up the RTP stream AVFormatContexts * already here (complicating things immensely) or getting a more * flexible SDP creation interface. */ sdp_ctx = *s; ff_url_join(sdp_ctx.filename, sizeof(sdp_ctx.filename), "rtsp", NULL, addr, -1, NULL); ctx_array[0] = &sdp_ctx; if (av_sdp_create(ctx_array, 1, sdp, SDP_MAX_SIZE)) { av_free(sdp); return AVERROR_INVALIDDATA; } av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", sdp); ff_rtsp_send_cmd_with_content(s, "ANNOUNCE", rt->control_uri, "Content-Type: application/sdp\r\n", reply, NULL, sdp, strlen(sdp)); av_free(sdp); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; /* Set up the RTSPStreams for each AVStream */ for (i = 0; i < s->nb_streams; i++) { RTSPStream *rtsp_st; rtsp_st = av_mallocz(sizeof(RTSPStream)); if (!rtsp_st) return AVERROR(ENOMEM); dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st); rtsp_st->stream_index = i; av_strlcpy(rtsp_st->control_url, rt->control_uri, sizeof(rtsp_st->control_url)); /* Note, this must match the relative uri set in the sdp content */ av_strlcatf(rtsp_st->control_url, sizeof(rtsp_st->control_url), "/streamid=%d", i); } return 0; }
static int http_connect(URLContext *h, const char *path, const char *local_path, const char *hoststr, const char *auth, const char *proxyauth, int *new_location) { HTTPContext *s = h->priv_data; int post, err; char headers[HTTP_HEADERS_SIZE] = ""; char *authstr = NULL, *proxyauthstr = NULL; int64_t off = s->off; int len = 0; const char *method; int send_expect_100 = 0; /* send http header */ post = h->flags & AVIO_FLAG_WRITE; if (s->post_data) { /* force POST method and disable chunked encoding when * custom HTTP post data is set */ post = 1; s->chunked_post = 0; } if (s->method) method = s->method; else method = post ? "POST" : "GET"; authstr = ff_http_auth_create_response(&s->auth_state, auth, local_path, method); proxyauthstr = ff_http_auth_create_response(&s->proxy_auth_state, proxyauth, local_path, method); if (post && !s->post_data) { send_expect_100 = s->send_expect_100; /* The user has supplied authentication but we don't know the auth type, * send Expect: 100-continue to get the 401 response including the * WWW-Authenticate header, or an 100 continue if no auth actually * is needed. */ if (auth && *auth && s->auth_state.auth_type == HTTP_AUTH_NONE && s->http_code != 401) send_expect_100 = 1; } /* set default headers if needed */ if (!has_header(s->headers, "\r\nUser-Agent: ")) len += av_strlcatf(headers + len, sizeof(headers) - len, "User-Agent: %s\r\n", s->user_agent); if (!has_header(s->headers, "\r\nAccept: ")) len += av_strlcpy(headers + len, "Accept: */*\r\n", sizeof(headers) - len); // Note: we send this on purpose even when s->off is 0 when we're probing, // since it allows us to detect more reliably if a (non-conforming) // server supports seeking by analysing the reply headers. if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable == -1)) { len += av_strlcatf(headers + len, sizeof(headers) - len, "Range: bytes=%"PRId64"-", s->off); if (s->end_off) len += av_strlcatf(headers + len, sizeof(headers) - len, "%"PRId64, s->end_off - 1); len += av_strlcpy(headers + len, "\r\n", sizeof(headers) - len); } if (send_expect_100 && !has_header(s->headers, "\r\nExpect: ")) len += av_strlcatf(headers + len, sizeof(headers) - len, "Expect: 100-continue\r\n"); if (!has_header(s->headers, "\r\nConnection: ")) { if (s->multiple_requests) len += av_strlcpy(headers + len, "Connection: keep-alive\r\n", sizeof(headers) - len); else len += av_strlcpy(headers + len, "Connection: close\r\n", sizeof(headers) - len); } if (!has_header(s->headers, "\r\nHost: ")) len += av_strlcatf(headers + len, sizeof(headers) - len, "Host: %s\r\n", hoststr); if (!has_header(s->headers, "\r\nContent-Length: ") && s->post_data) len += av_strlcatf(headers + len, sizeof(headers) - len, "Content-Length: %d\r\n", s->post_datalen); if (!has_header(s->headers, "\r\nContent-Type: ") && s->content_type) len += av_strlcatf(headers + len, sizeof(headers) - len, "Content-Type: %s\r\n", s->content_type); if (!has_header(s->headers, "\r\nCookie: ") && s->cookies) { char *cookies = NULL; if (!get_cookies(s, &cookies, path, hoststr) && cookies) { len += av_strlcatf(headers + len, sizeof(headers) - len, "Cookie: %s\r\n", cookies); av_free(cookies); } } if (!has_header(s->headers, "\r\nIcy-MetaData: ") && s->icy) len += av_strlcatf(headers + len, sizeof(headers) - len, "Icy-MetaData: %d\r\n", 1); /* now add in custom headers */ if (s->headers) av_strlcpy(headers + len, s->headers, sizeof(headers) - len); snprintf(s->buffer, sizeof(s->buffer), "%s %s HTTP/1.1\r\n" "%s" "%s" "%s" "%s%s" "\r\n", method, path, post && s->chunked_post ? "Transfer-Encoding: chunked\r\n" : "", headers, authstr ? authstr : "", proxyauthstr ? "Proxy-" : "", proxyauthstr ? proxyauthstr : ""); av_log(h, AV_LOG_DEBUG, "request: %s\n", s->buffer); if ((err = ffurl_write(s->hd, s->buffer, strlen(s->buffer))) < 0) goto done; if (s->post_data) if ((err = ffurl_write(s->hd, s->post_data, s->post_datalen)) < 0) goto done; /* init input buffer */ s->buf_ptr = s->buffer; s->buf_end = s->buffer; s->line_count = 0; s->off = 0; s->icy_data_read = 0; s->filesize = -1; s->willclose = 0; s->end_chunked_post = 0; s->end_header = 0; if (post && !s->post_data && !send_expect_100) { /* Pretend that it did work. We didn't read any header yet, since * we've still to send the POST data, but the code calling this * function will check http_code after we return. */ s->http_code = 200; err = 0; goto done; } /* wait for header */ err = http_read_header(h, new_location); if (err < 0) goto done; if (*new_location) s->off = off; err = (off == s->off) ? 0 : -1; done: av_freep(&authstr); av_freep(&proxyauthstr); return err; }
static int rtsp_read_packet(AVFormatContext *s, AVPacket *pkt) { RTSPState *rt = s->priv_data; int ret; RTSPMessageHeader reply1, *reply = &reply1; char cmd[1024]; if (rt->server_type == RTSP_SERVER_REAL) { int i; for (i = 0; i < s->nb_streams; i++) rt->real_setup[i] = s->streams[i]->discard; if (!rt->need_subscription) { if (memcmp (rt->real_setup, rt->real_setup_cache, sizeof(enum AVDiscard) * s->nb_streams)) { snprintf(cmd, sizeof(cmd), "Unsubscribe: %s\r\n", rt->last_subscription); ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; rt->need_subscription = 1; } } if (rt->need_subscription) { int r, rule_nr, first = 1; memcpy(rt->real_setup_cache, rt->real_setup, sizeof(enum AVDiscard) * s->nb_streams); rt->last_subscription[0] = 0; snprintf(cmd, sizeof(cmd), "Subscribe: "); for (i = 0; i < rt->nb_rtsp_streams; i++) { rule_nr = 0; for (r = 0; r < s->nb_streams; r++) { if (s->streams[r]->priv_data == rt->rtsp_streams[i]) { if (s->streams[r]->discard != AVDISCARD_ALL) { if (!first) av_strlcat(rt->last_subscription, ",", sizeof(rt->last_subscription)); ff_rdt_subscribe_rule( rt->last_subscription, sizeof(rt->last_subscription), i, rule_nr); first = 0; } rule_nr++; } } } av_strlcatf(cmd, sizeof(cmd), "%s\r\n", rt->last_subscription); ff_rtsp_send_cmd(s, "SET_PARAMETER", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return AVERROR_INVALIDDATA; rt->need_subscription = 0; if (rt->state == RTSP_STATE_STREAMING) rtsp_read_play (s); } } ret = ff_rtsp_fetch_packet(s, pkt); if (ret < 0) return ret; /* send dummy request to keep TCP connection alive */ if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2) { if (rt->server_type == RTSP_SERVER_WMS) { ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL); } else { ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); } } return 0; }