static int rt_event_to_ass(AVBPrint *buf, const char *p) { int prev_chr_is_space = 1; while (*p) { if (*p != '<') { if (!av_isspace(*p)) av_bprint_chars(buf, *p, 1); else if (!prev_chr_is_space) av_bprint_chars(buf, ' ', 1); prev_chr_is_space = av_isspace(*p); } else { const char *end = strchr(p, '>'); if (!end) break; if (!av_strncasecmp(p, "<br/>", 5) || !av_strncasecmp(p, "<br>", 4)) { av_bprintf(buf, "\\N"); } p = end; } p++; } av_bprintf(buf, "\r\n"); return 0; }
static void get_arg(char *buf, int buf_size, const char **pp) { const char *p; char *q; int quote; p = *pp; while (av_isspace(*p)) p++; q = buf; quote = 0; if (*p == '\"' || *p == '\'') quote = *p++; for(;;) { if (quote) { if (*p == quote) break; } else { if (av_isspace(*p)) break; } if (*p == '\0') break; if ((q - buf) < buf_size - 1) *q++ = *p; p++; } *q = '\0'; if (quote && *p == quote) p++; *pp = p; }
static int split_tag_value(char **tag, char **value, char *line) { char *p = line; int foundData = 0; *tag = NULL; *value = NULL; while (*p != '\0' && *p != ':') { if (!av_isspace(*p)) { foundData = 1; } p++; } if (*p != ':') return foundData ? AVERROR_INVALIDDATA : 0; *p = '\0'; *tag = line; trim_right(*tag); p++; while (av_isspace(*p)) p++; *value = p; trim_right(*value); return 0; }
void ffserver_get_arg(char *buf, int buf_size, const char **pp) { const char *p; char *q; int quote = 0; p = *pp; q = buf; while (av_isspace(*p)) p++; if (*p == '\"' || *p == '\'') quote = *p++; while (*p != '\0') { if (quote && *p == quote || !quote && av_isspace(*p)) break; if ((q - buf) < buf_size - 1) *q++ = *p; p++; } *q = '\0'; if (quote && *p == quote) p++; *pp = p; }
static void choose_qop(char *qop, int size) { char *ptr = strstr(qop, "auth"); char *end = ptr + strlen("auth"); if (ptr && (!*end || av_isspace(*end) || *end == ',') && (ptr == qop || av_isspace(ptr[-1]) || ptr[-1] == ',')) { av_strlcpy(qop, "auth", size); } else { qop[0] = 0; } }
static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) { int len = ff_get_line(s, buf, maxlen); while (len > 0 && av_isspace(buf[len - 1])) buf[--len] = '\0'; return len; }
static char* mpjpeg_get_boundary(AVIOContext* pb) { uint8_t *mime_type = NULL; const char *start; const char *end; uint8_t *res = NULL; int len; /* get MIME type, and skip to the first parameter */ av_opt_get(pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type); start = mime_type; while (start != NULL && *start != '\0') { start = strchr(start, ';'); if (!start) break; start = start+1; while (av_isspace(*start)) start++; if (!av_stristart(start, "boundary=", &start)) { end = strchr(start, ';'); if (end) len = end - start - 1; else len = strlen(start); res = av_strndup(start, len); break; } } av_freep(&mime_type); return res; }
const char *ff_smil_get_attr_ptr(const char *s, const char *attr) { int in_quotes = 0; const int len = strlen(attr); while (*s) { while (*s) { if (!in_quotes && av_isspace(*s)) break; in_quotes ^= *s == '"'; // XXX: support escaping? s++; } while (av_isspace(*s)) s++; if (!av_strncasecmp(s, attr, len) && s[len] == '=') return s + len + 1 + (s[len + 1] == '"'); } return NULL; }
static void trim_right(char *p) { char *end; if (!p || !*p) return; end = p + strlen(p); while (end > p && av_isspace(*(end-1))) *(--end) = '\0'; }
static void trim_right(char* p) { char *end; if (!p || !*p) return; end = p + strlen(p) - 1; while (end != p && av_isspace(*end)) { *end = '\0'; end--; } }
static double avpriv_strtod(const char *nptr, char **endptr) { char *end; double res; /* Skip leading spaces */ while (av_isspace(*nptr)) nptr++; if (!av_strncasecmp(nptr, "infinity", 8)) { end = nptr + 8; res = INFINITY; } else if (!av_strncasecmp(nptr, "inf", 3)) { end = nptr + 3; res = INFINITY; } else if (!av_strncasecmp(nptr, "+infinity", 9)) { end = nptr + 9; res = INFINITY; } else if (!av_strncasecmp(nptr, "+inf", 4)) { end = nptr + 4; res = INFINITY; } else if (!av_strncasecmp(nptr, "-infinity", 9)) { end = nptr + 9; res = -INFINITY; } else if (!av_strncasecmp(nptr, "-inf", 4)) { end = nptr + 4; res = -INFINITY; } else if (!av_strncasecmp(nptr, "nan", 3)) { end = check_nan_suffix(nptr + 3); res = NAN; } else if (!av_strncasecmp(nptr, "+nan", 4) || !av_strncasecmp(nptr, "-nan", 4)) { end = check_nan_suffix(nptr + 4); res = NAN; } else if (!av_strncasecmp(nptr, "0x", 2) || !av_strncasecmp(nptr, "-0x", 3) || !av_strncasecmp(nptr, "+0x", 3)) { /* FIXME this doesn't handle exponents, non-integers (float/double) * and numbers too large for long long */ res = strtoll(nptr, &end, 16); } else { res = strtod(nptr, &end); } if (endptr) *endptr = end; return res; }
static void get_word(char *buf, int buf_size, const char **pp) { const char *p; char *q; p = *pp; skip_spaces(&p); q = buf; while (!av_isspace(*p) && *p != '\0') { if ((q - buf) < buf_size - 1) *q++ = *p; p++; } if (buf_size > 0) *q = '\0'; *pp = p; }
static int split_tag_value(char **tag, char **value, char *line) { char *p = line; while (*p != '\0' && *p != ':') p++; if (*p != ':') return AVERROR_INVALIDDATA; *p = '\0'; *tag = line; p++; while (av_isspace(*p)) p++; *value = p; return 0; }
/* conf file parsing */ static int parse_ffconfig(const char *filename) { FILE *f; char line[1024]; char cmd[64]; char arg[1024], arg2[1024]; const char *p; int val, errors, warnings, line_num; iStream **last_stream, *stream, *redirect; int ret = 0; f = fopen(filename, "r"); if (!f) { ret = AVERROR(errno); av_log(NULL, AV_LOG_ERROR, "Could not open the configuration file '%s'\n", filename); return ret; } errors = warnings = 0; line_num = 0; first_stream = NULL; last_stream = &first_stream; stream = NULL; redirect = NULL; #define ERROR(...) printf #define WARNING(...) printf for(;;) { if (fgets(line, sizeof(line), f) == NULL) break; line_num++; p = line; while (av_isspace(*p)) p++; if (*p == '\0' || *p == '#') continue; get_arg(cmd, sizeof(cmd), &p); printf("cmd = %s \n", cmd); if (!av_strcasecmp(cmd, "RTSPPort")) { get_arg(arg, sizeof(arg), &p); val = atoi(arg); if (val < 1 || val > 65536) { ERROR("%s:%d: Invalid port: %s\n", arg); } my_rtsp_addr.sin_port = htons(atoi(arg)); } else if (!av_strcasecmp(cmd, "RTSPBindAddress")) { get_arg(arg, sizeof(arg), &p); if (resolve_host(&my_rtsp_addr.sin_addr, arg) != 0) { ERROR("Invalid host/IP address: %s\n", arg); } } else if (!av_strcasecmp(cmd, "File") || !av_strcasecmp(cmd, "ReadOnlyFile")) { if (stream) { get_arg(stream->filename, sizeof(stream->filename), &p); // set index filename too int len = strlen(stream->filename); //printf("filename = %s, len = %d\n", stream->filename, len); strcpy(stream->idx_filename, stream->filename); stream->idx_filename[len] = 'x'; stream->idx_filename[len+1] = '\0'; len = strlen(stream->idx_filename); //printf("idx filename = %s, len = %d\n", stream->idx_filename, len); } } else if (!av_strcasecmp(cmd, "<Stream")) { /*********************************************/ /* Stream related options */ char *q; if (stream) { ERROR("Already in a tag\n"); } else { iStream *s; s = av_mallocz(sizeof(*s)); if (!s) { ret = AVERROR(ENOMEM); goto end; } stream = s; get_arg(stream->name, sizeof(stream->name), &p); q = strrchr(stream->name, '>'); if (q) *q = '\0'; printf("stream name = %s \n", stream->name); for (s = first_stream; s; s = s->next) { if (!strcmp(stream->name, s->name)) { ERROR("Stream '%s' already registered\n", s->filename); } } *last_stream = stream; last_stream = &stream->next; } } else if (!av_strcasecmp(cmd, "</Stream>")) { if (!stream) { ERROR("No corresponding <Stream> for </Stream>\n"); } else { printf("stream end! codec name = %s\n", stream->codec_name); stream = NULL; } } else { //ERROR("Incorrect keyword: '%s'\n", cmd); printf("Incorrect keyword: '%s'\n", cmd); } } #undef ERROR end: fclose(f); if (ret < 0) return ret; if (errors) return AVERROR(EINVAL); else return 0; }
static int sami_paragraph_to_ass(AVCodecContext *avctx, const char *src) { SAMIContext *sami = avctx->priv_data; int ret = 0; char *tag = NULL; char *dupsrc = av_strdup(src); char *p = dupsrc; av_bprint_clear(&sami->content); for (;;) { char *saveptr = NULL; int prev_chr_is_space = 0; AVBPrint *dst = &sami->content; /* parse & extract paragraph tag */ p = av_stristr(p, "<P"); if (!p) break; if (p[2] != '>' && !av_isspace(p[2])) { // avoid confusion with tags such as <PRE> p++; continue; } if (dst->len) // add a separator with the previous paragraph if there was one av_bprintf(dst, "\\N"); tag = av_strtok(p, ">", &saveptr); if (!tag || !saveptr) break; p = saveptr; /* check if the current paragraph is the "source" (speaker name) */ if (av_stristr(tag, "ID=Source") || av_stristr(tag, "ID=\"Source\"")) { dst = &sami->source; av_bprint_clear(dst); } /* if empty event -> skip subtitle */ while (av_isspace(*p)) p++; if (!strncmp(p, " ", 6)) { ret = -1; goto end; } /* extract the text, stripping most of the tags */ while (*p) { if (*p == '<') { if (!av_strncasecmp(p, "<P", 2) && (p[2] == '>' || av_isspace(p[2]))) break; if (!av_strncasecmp(p, "<BR", 3)) av_bprintf(dst, "\\N"); p++; while (*p && *p != '>') p++; if (!*p) break; if (*p == '>') p++; } if (!av_isspace(*p)) av_bprint_chars(dst, *p, 1); else if (!prev_chr_is_space) av_bprint_chars(dst, ' ', 1); prev_chr_is_space = av_isspace(*p); p++; } } av_bprint_clear(&sami->full); if (sami->source.len) av_bprintf(&sami->full, "{\\i1}%s{\\i0}\\N", sami->source.str); av_bprintf(&sami->full, "%s", sami->content.str); end: av_free(dupsrc); return ret; }
static int rtmp_http_open(URLContext *h, const char *uri, int flags) { RTMP_HTTPContext *rt = h->priv_data; char headers[1024], url[1024]; int ret, off = 0; av_url_split(NULL, 0, NULL, 0, rt->host, sizeof(rt->host), &rt->port, NULL, 0, uri); /* This is the first request that is sent to the server in order to * register a client on the server and start a new session. The server * replies with a unique id (usually a number) that is used by the client * for all future requests. * Note: the reply doesn't contain a value for the polling interval. * A successful connect resets the consecutive index that is used * in the URLs. */ if (rt->tls) { if (rt->port < 0) rt->port = RTMPTS_DEFAULT_PORT; ff_url_join(url, sizeof(url), "https", NULL, rt->host, rt->port, "/open/1"); } else { if (rt->port < 0) rt->port = RTMPT_DEFAULT_PORT; ff_url_join(url, sizeof(url), "http", NULL, rt->host, rt->port, "/open/1"); } /* alloc the http context */ if ((ret = ffurl_alloc(&rt->stream, url, AVIO_FLAG_READ_WRITE, NULL)) < 0) goto fail; /* set options */ snprintf(headers, sizeof(headers), "Cache-Control: no-cache\r\n" "Content-type: application/x-fcs\r\n" "User-Agent: Shockwave Flash\r\n"); av_opt_set(rt->stream->priv_data, "headers", headers, 0); av_opt_set(rt->stream->priv_data, "multiple_requests", "1", 0); av_opt_set_bin(rt->stream->priv_data, "post_data", "", 1, 0); /* open the http context */ if ((ret = ffurl_connect(rt->stream, NULL)) < 0) goto fail; /* read the server reply which contains a unique ID */ for (;;) { ret = ffurl_read(rt->stream, rt->client_id + off, sizeof(rt->client_id) - off); if (!ret || ret == AVERROR_EOF) break; if (ret < 0) goto fail; off += ret; if (off == sizeof(rt->client_id)) { ret = AVERROR(EIO); goto fail; } } while (off > 0 && av_isspace(rt->client_id[off - 1])) off--; rt->client_id[off] = '\0'; /* http context is now initialized */ rt->initialized = 1; return 0; fail: rtmp_http_close(h); return ret; }
static int process_line(URLContext *h, char *line, int line_count, int *new_location) { HTTPContext *s = h->priv_data; const char *auto_method = h->flags & AVIO_FLAG_READ ? "POST" : "GET"; char *tag, *p, *end, *method, *resource, *version; int ret; /* end of header */ if (line[0] == '\0') { s->end_header = 1; return 0; } p = line; if (line_count == 0) { if (s->listen) { // HTTP method method = p; while (!av_isspace(*p)) p++; *(p++) = '\0'; av_log(h, AV_LOG_TRACE, "Received method: %s\n", method); if (s->method) { if (av_strcasecmp(s->method, method)) { av_log(h, AV_LOG_ERROR, "Received and expected HTTP method do not match. (%s expected, %s received)\n", s->method, method); return ff_http_averror(400, AVERROR(EIO)); } } else { // use autodetected HTTP method to expect av_log(h, AV_LOG_TRACE, "Autodetected %s HTTP method\n", auto_method); if (av_strcasecmp(auto_method, method)) { av_log(h, AV_LOG_ERROR, "Received and autodetected HTTP method did not match " "(%s autodetected %s received)\n", auto_method, method); return ff_http_averror(400, AVERROR(EIO)); } } // HTTP resource while (av_isspace(*p)) p++; resource = p; while (!av_isspace(*p)) p++; *(p++) = '\0'; av_log(h, AV_LOG_TRACE, "Requested resource: %s\n", resource); // HTTP version while (av_isspace(*p)) p++; version = p; while (!av_isspace(*p)) p++; *p = '\0'; if (av_strncasecmp(version, "HTTP/", 5)) { av_log(h, AV_LOG_ERROR, "Malformed HTTP version string.\n"); return ff_http_averror(400, AVERROR(EIO)); } av_log(h, AV_LOG_TRACE, "HTTP version string: %s\n", version); } else { while (!av_isspace(*p) && *p != '\0') p++; while (av_isspace(*p)) p++; s->http_code = strtol(p, &end, 10); av_log(h, AV_LOG_TRACE, "http_code=%d\n", s->http_code); if ((ret = check_http_code(h, s->http_code, end)) < 0) return ret; } } else { while (*p != '\0' && *p != ':') p++; if (*p != ':') return 1; *p = '\0'; tag = line; p++; while (av_isspace(*p)) p++; if (!av_strcasecmp(tag, "Location")) { if ((ret = parse_location(s, p)) < 0) return ret; *new_location = 1; } else if (!av_strcasecmp(tag, "Content-Length") && s->filesize == -1) { s->filesize = strtoll(p, NULL, 10); } else if (!av_strcasecmp(tag, "Content-Range")) { parse_content_range(h, p); } else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5) && s->seekable == -1) { h->is_streamed = 0; } else if (!av_strcasecmp(tag, "Transfer-Encoding") && !av_strncasecmp(p, "chunked", 7)) { s->filesize = -1; s->chunksize = 0; } else if (!av_strcasecmp(tag, "WWW-Authenticate")) { ff_http_auth_handle_header(&s->auth_state, tag, p); } else if (!av_strcasecmp(tag, "Authentication-Info")) { ff_http_auth_handle_header(&s->auth_state, tag, p); } else if (!av_strcasecmp(tag, "Proxy-Authenticate")) { ff_http_auth_handle_header(&s->proxy_auth_state, tag, p); } else if (!av_strcasecmp(tag, "Connection")) { if (!strcmp(p, "close")) s->willclose = 1; } else if (!av_strcasecmp(tag, "Server")) { if (!av_strcasecmp(p, "AkamaiGHost")) { s->is_akamai = 1; } else if (!av_strncasecmp(p, "MediaGateway", 12)) { s->is_mediagateway = 1; } } else if (!av_strcasecmp(tag, "Content-Type")) { av_free(s->mime_type); s->mime_type = av_strdup(p); } else if (!av_strcasecmp(tag, "Set-Cookie")) { if (parse_cookie(s, p, &s->cookie_dict)) av_log(h, AV_LOG_WARNING, "Unable to parse '%s'\n", p); } else if (!av_strcasecmp(tag, "Icy-MetaInt")) { s->icy_metaint = strtoll(p, NULL, 10); } else if (!av_strncasecmp(tag, "Icy-", 4)) { if ((ret = parse_icy(s, tag, p)) < 0) return ret; } else if (!av_strcasecmp(tag, "Content-Encoding")) { if ((ret = parse_content_encoding(h, p)) < 0) return ret; } } return 1; }
static int process_line(URLContext *h, char *line, int line_count, int *new_location) { HTTPContext *s = h->priv_data; char *tag, *p, *end; int ret; /* end of header */ if (line[0] == '\0') { s->end_header = 1; return 0; } p = line; if (line_count == 0) { while (!av_isspace(*p) && *p != '\0') p++; while (av_isspace(*p)) p++; s->http_code = strtol(p, &end, 10); av_log(NULL, AV_LOG_TRACE, "http_code=%d\n", s->http_code); if ((ret = check_http_code(h, s->http_code, end)) < 0) return ret; } else { while (*p != '\0' && *p != ':') p++; if (*p != ':') return 1; *p = '\0'; tag = line; p++; while (av_isspace(*p)) p++; if (!av_strcasecmp(tag, "Location")) { if ((ret = parse_location(s, p)) < 0) return ret; *new_location = 1; } else if (!av_strcasecmp(tag, "Content-Length") && s->filesize == -1) { s->filesize = strtoll(p, NULL, 10); } else if (!av_strcasecmp(tag, "Content-Range")) { parse_content_range(h, p); } else if (!av_strcasecmp(tag, "Accept-Ranges") && !strncmp(p, "bytes", 5)) { h->is_streamed = 0; } else if (!av_strcasecmp(tag, "Transfer-Encoding") && !av_strncasecmp(p, "chunked", 7)) { s->filesize = -1; s->chunksize = 0; } else if (!av_strcasecmp(tag, "WWW-Authenticate")) { ff_http_auth_handle_header(&s->auth_state, tag, p); } else if (!av_strcasecmp(tag, "Authentication-Info")) { ff_http_auth_handle_header(&s->auth_state, tag, p); } else if (!av_strcasecmp(tag, "Proxy-Authenticate")) { ff_http_auth_handle_header(&s->proxy_auth_state, tag, p); } else if (!av_strcasecmp(tag, "Connection")) { if (!strcmp(p, "close")) s->willclose = 1; } else if (!av_strcasecmp(tag, "Content-Type")) { av_free(s->mime_type); s->mime_type = av_strdup(p); } else if (!av_strcasecmp(tag, "Icy-MetaInt")) { s->icy_metaint = strtoll(p, NULL, 10); } else if (!av_strncasecmp(tag, "Icy-", 4)) { if ((ret = parse_icy(s, tag, p)) < 0) return ret; } else if (!av_strcasecmp(tag, "Content-Encoding")) { if ((ret = parse_content_encoding(h, p)) < 0) return ret; } } return 1; }
int ffserver_parse_ffconfig(const char *filename, FFServerConfig *config) { FILE *f; char line[1024]; char cmd[64]; const char *p; FFServerStream **last_stream, *stream = NULL, *redirect = NULL; FFServerStream **last_feed, *feed = NULL; int ret = 0; av_assert0(config); f = fopen(filename, "r"); if (!f) { ret = AVERROR(errno); av_log(NULL, AV_LOG_ERROR, "Could not open the configuration file '%s'\n", filename); return ret; } config->first_stream = NULL; config->first_feed = NULL; config->errors = config->warnings = 0; last_stream = &config->first_stream; last_feed = &config->first_feed; config->line_num = 0; while (fgets(line, sizeof(line), f) != NULL) { config->line_num++; p = line; while (av_isspace(*p)) p++; if (*p == '\0' || *p == '#') continue; ffserver_get_arg(cmd, sizeof(cmd), &p); if (feed || !av_strcasecmp(cmd, "<Feed")) { int opening = !av_strcasecmp(cmd, "<Feed"); if (opening && (stream || feed || redirect)) { ERROR("Already in a tag\n"); } else { ret = ffserver_parse_config_feed(config, cmd, &p, &feed); if (ret < 0) break; if (opening) { /* add in stream & feed list */ *last_stream = feed; *last_feed = feed; last_stream = &feed->next; last_feed = &feed->next_feed; } } } else if (stream || !av_strcasecmp(cmd, "<Stream")) { int opening = !av_strcasecmp(cmd, "<Stream"); if (opening && (stream || feed || redirect)) { ERROR("Already in a tag\n"); } else { ret = ffserver_parse_config_stream(config, cmd, &p, &stream); if (ret < 0) break; if (opening) { /* add in stream list */ *last_stream = stream; last_stream = &stream->next; } } } else if (redirect || !av_strcasecmp(cmd, "<Redirect")) { int opening = !av_strcasecmp(cmd, "<Redirect"); if (opening && (stream || feed || redirect)) ERROR("Already in a tag\n"); else { ret = ffserver_parse_config_redirect(config, cmd, &p, &redirect); if (ret < 0) break; if (opening) { /* add in stream list */ *last_stream = redirect; last_stream = &redirect->next; } } } else { ffserver_parse_config_global(config, cmd, &p); } } if (stream || feed || redirect) ERROR("Missing closing </%s> tag\n", stream ? "Stream" : (feed ? "Feed" : "Redirect")); fclose(f); if (ret < 0) return ret; if (config->errors) return AVERROR(EINVAL); else return 0; }