+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 int hls_recover(AVFormatContext *s)
+{
+ HLSContext *hls = s->priv_data;
+ char line[1024];
+ AVIOContext *io;
+ const char *ptr;
+ int ret, is_segment = 0;
+ int64_t duration = 0;
+
+ ret = s->io_open(s, &io, s->filename, AVIO_FLAG_READ, NULL);
+ if (ret < 0) {
+ av_log(s, AV_LOG_WARNING,
+ "Cannot recover the playlist, generating a new one.\n");
+ hls->start_sequence = 0;
+ hls->sequence = 0;
+ return 0;
+ }
+
+ read_chomp_line(io, line, sizeof(line));
+ if (strcmp(line, "#EXTM3U")) {
+ av_log(s, AV_LOG_ERROR,
+ "The playlist file is present but unparsable."
+ " Please remove it.\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ while (!io->eof_reached) {
+ read_chomp_line(io, line, sizeof(line));
+ if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) {
+ hls->sequence = hls->start_sequence = atoi(ptr);
+ } else if (av_strstart(line, "#EXTINF:", &ptr)) {
+ is_segment = 1;
+ duration = atof(ptr) * AV_TIME_BASE;
+ } else if (av_strstart(line, "#", NULL)) {
+ continue;
+ } else if (line[0]) {
+ if (is_segment) {
+ append_entry(hls, duration, av_basename(line));
+ is_segment = 0;
+ }
+ }
+ }
+
+ return 0;
+}
+