| 291 | } |
| 292 | |
| 293 | static int parse_fmtp(AVFormatContext *s, |
| 294 | AVStream *stream, PayloadContext *data, |
| 295 | const char *attr, const char *value) |
| 296 | { |
| 297 | AVCodecParameters *par = stream->codecpar; |
| 298 | int res, i; |
| 299 | |
| 300 | if (!strcmp(attr, "config")) { |
| 301 | res = parse_fmtp_config(par, value); |
| 302 | |
| 303 | if (res < 0) |
| 304 | return res; |
| 305 | } |
| 306 | |
| 307 | if (par->codec_id == AV_CODEC_ID_AAC) { |
| 308 | /* Looking for a known attribute */ |
| 309 | for (i = 0; attr_names[i].str; ++i) { |
| 310 | if (!av_strcasecmp(attr, attr_names[i].str)) { |
| 311 | if (attr_names[i].type == ATTR_NAME_TYPE_INT) { |
| 312 | char *end_ptr = NULL; |
| 313 | long long int val = strtoll(value, &end_ptr, 10); |
| 314 | if (end_ptr == value || end_ptr[0] != '\0') { |
| 315 | av_log(s, AV_LOG_ERROR, |
| 316 | "The %s field value is not a valid number: %s\n", |
| 317 | attr, value); |
| 318 | return AVERROR_INVALIDDATA; |
| 319 | } |
| 320 | if (val < attr_names[i].range.min || |
| 321 | val > attr_names[i].range.max) { |
| 322 | av_log(s, AV_LOG_ERROR, |
| 323 | "fmtp field %s should be in range [%d,%d] (provided value: %lld)", |
| 324 | attr, attr_names[i].range.min, attr_names[i].range.max, val); |
| 325 | return AVERROR_INVALIDDATA; |
| 326 | } |
| 327 | |
| 328 | *(int *)((char *)data+ |
| 329 | attr_names[i].offset) = (int) val; |
| 330 | } else if (attr_names[i].type == ATTR_NAME_TYPE_STR) { |
| 331 | char *val = av_strdup(value); |
| 332 | if (!val) |
| 333 | return AVERROR(ENOMEM); |
| 334 | *(char **)((char *)data+ |
| 335 | attr_names[i].offset) = val; |
| 336 | } |
| 337 | } |
| 338 | } |
| 339 | if (!strcmp(attr, "bitrate")) { |
| 340 | par->bit_rate = data->bitrate; |
| 341 | } |
| 342 | } |
| 343 | return 0; |
| 344 | } |
| 345 | |
| 346 | static int parse_sdp_line(AVFormatContext *s, int st_index, |
| 347 | PayloadContext *data, const char *line) |
nothing calls this directly
no test coverage detected