* Parse interval specification, according to the format: * INTERVAL ::= [START|+START_OFFSET][%[END|+END_OFFSET]] * INTERVALS ::= INTERVAL[,INTERVALS] */
| 2926 | * INTERVALS ::= INTERVAL[,INTERVALS] |
| 2927 | */ |
| 2928 | static int parse_read_interval(const char *interval_spec, |
| 2929 | ReadInterval *interval) |
| 2930 | { |
| 2931 | int ret = 0; |
| 2932 | char *next, *p, *spec = av_strdup(interval_spec); |
| 2933 | if (!spec) |
| 2934 | return AVERROR(ENOMEM); |
| 2935 | |
| 2936 | if (!*spec) { |
| 2937 | av_log(NULL, AV_LOG_ERROR, "Invalid empty interval specification\n"); |
| 2938 | ret = AVERROR(EINVAL); |
| 2939 | goto end; |
| 2940 | } |
| 2941 | |
| 2942 | p = spec; |
| 2943 | next = strchr(spec, '%'); |
| 2944 | if (next) |
| 2945 | *next++ = 0; |
| 2946 | |
| 2947 | /* parse first part */ |
| 2948 | if (*p) { |
| 2949 | interval->has_start = 1; |
| 2950 | |
| 2951 | if (*p == '+') { |
| 2952 | interval->start_is_offset = 1; |
| 2953 | p++; |
| 2954 | } else { |
| 2955 | interval->start_is_offset = 0; |
| 2956 | } |
| 2957 | |
| 2958 | ret = av_parse_time(&interval->start, p, 1); |
| 2959 | if (ret < 0) { |
| 2960 | av_log(NULL, AV_LOG_ERROR, "Invalid interval start specification '%s'\n", p); |
| 2961 | goto end; |
| 2962 | } |
| 2963 | } else { |
| 2964 | interval->has_start = 0; |
| 2965 | } |
| 2966 | |
| 2967 | /* parse second part */ |
| 2968 | p = next; |
| 2969 | if (p && *p) { |
| 2970 | int64_t us; |
| 2971 | interval->has_end = 1; |
| 2972 | |
| 2973 | if (*p == '+') { |
| 2974 | interval->end_is_offset = 1; |
| 2975 | p++; |
| 2976 | } else { |
| 2977 | interval->end_is_offset = 0; |
| 2978 | } |
| 2979 | |
| 2980 | if (interval->end_is_offset && *p == '#') { |
| 2981 | long long int lli; |
| 2982 | char *tail; |
| 2983 | interval->duration_frames = 1; |
| 2984 | p++; |
| 2985 | lli = strtoll(p, &tail, 10); |
no test coverage detected