func: static int hls_read_header(AVFormatContext *s)
  
  {
  
      void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb;
  
      HLSContext *c = s->priv_data;
  
      int ret = 0, i;
  
      int highest_cur_seq_no = 0;
  
  
  
      c->ctx                = s;
  
      c->interrupt_callback = &s->interrupt_callback;
  
      c->strict_std_compliance = s->strict_std_compliance;
  
  
  
      c->first_packet = 1;
  
      c->first_timestamp = AV_NOPTS_VALUE;
  
      c->cur_timestamp = AV_NOPTS_VALUE;
  
  
  
      if (u) {
  
          // get the previous user agent & set back to null if string size is zero
  
          update_options(&c->user_agent, "user-agent", u);
  
  
  
          // get the previous cookies & set back to null if string size is zero
  
          update_options(&c->cookies, "cookies", u);
  
  
  
          // get the previous headers & set back to null if string size is zero
  
          update_options(&c->headers, "headers", u);
  
  
  
          // get the previous http proxt & set back to null if string size is zero
  
          update_options(&c->http_proxy, "http_proxy", u);
  
      }
  
  
  
      if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0)
  
          goto fail;
  
  
  
      if ((ret = save_avio_options(s)) < 0)
  
          goto fail;
  
  
  
      /* Some HLS servers don't like being sent the range header */
  
      av_dict_set(&c->avio_opts, "seekable", "0", 0);
  
  
  
      if (c->n_variants == 0) {
  
          av_log(NULL, AV_LOG_WARNING, "Empty playlist\n");
  
          ret = AVERROR_EOF;
  
          goto fail;
  
      }
  
      /* If the playlist only contained playlists (Master Playlist),
  
       * parse each individual playlist. */
  
      if (c->n_playlists > 1 || c->playlists[0]->n_segments == 0) {
  
          for (i = 0; i < c->n_playlists; i++) {
  
              struct playlist *pls = c->playlists[i];
  
              if ((ret = parse_playlist(c, pls->url, pls, NULL)) < 0)
  
                  goto fail;
  
          }
  
      }
  
  
  
      if (c->variants[0]->playlists[0]->n_segments == 0) {
  
          av_log(NULL, AV_LOG_WARNING, "Empty playlist\n");
  
          ret = AVERROR_EOF;
  
          goto fail;
  
      }
  
  
  
      /* If this isn't a live stream, calculate the total duration of the
  
       * stream. */
  
      if (c->variants[0]->playlists[0]->finished) {
  
          int64_t duration = 0;
  
          for (i = 0; i < c->variants[0]->playlists[0]->n_segments; i++)
  
              duration += c->variants[0]->playlists[0]->segments[i]->duration;
  
          s->duration = duration;
  
      }
  
  
  
      /* Associate renditions with variants */
  
      for (i = 0; i < c->n_variants; i++) {
  
          struct variant *var = c->variants[i];
  
  
  
          if (var->audio_group[0])
  
              add_renditions_to_variant(c, var, AVMEDIA_TYPE_AUDIO, var->audio_group);
  
          if (var->video_group[0])
  
              add_renditions_to_variant(c, var, AVMEDIA_TYPE_VIDEO, var->video_group);
  
          if (var->subtitles_group[0])
  
              add_renditions_to_variant(c, var, AVMEDIA_TYPE_SUBTITLE, var->subtitles_group);
  
      }
  
  
  
      /* Create a program for each variant */
  
      for (i = 0; i < c->n_variants; i++) {
  
          struct variant *v = c->variants[i];
  
          AVProgram *program;
  
  
  
          program = av_new_program(s, i);
  
          if (!program)
  
              goto fail;
  
          av_dict_set_int(&program->metadata, "variant_bitrate", v->bandwidth, 0);
  
      }
  
  
  
      /* Select the starting segments */
  
      for (i = 0; i < c->n_playlists; i++) {
  
          struct playlist *pls = c->playlists[i];
  
  
  
          if (pls->n_segments == 0)
  
              continue;
  
  
  
          pls->cur_seq_no = select_cur_seq_no(c, pls);
  
          highest_cur_seq_no = FFMAX(highest_cur_seq_no, pls->cur_seq_no);
  
      }
  
  
  
      /* Open the demuxer for each playlist */
  
      for (i = 0; i < c->n_playlists; i++) {
  
          struct playlist *pls = c->playlists[i];
  
          AVInputFormat *in_fmt = NULL;
  
  
  
          if (!(pls->ctx = avformat_alloc_context())) {
  
              ret = AVERROR(ENOMEM);
  
              goto fail;
  
          }
  
  
  
          if (pls->n_segments == 0)
  
              continue;
  
  
  
          pls->index  = i;
  
          pls->needed = 1;
  
          pls->parent = s;
  
  
  
          /*
  
           * If this is a live stream and this playlist looks like it is one segment
  
           * behind, try to sync it up so that every substream starts at the same
  
           * time position (so e.g. avformat_find_stream_info() will see packets from
  
           * all active streams within the first few seconds). This is not very generic,
  
           * though, as the sequence numbers are technically independent.
  
           */
  
          if (!pls->finished && pls->cur_seq_no == highest_cur_seq_no - 1 &&
  
              highest_cur_seq_no < pls->start_seq_no + pls->n_segments) {
  
              pls->cur_seq_no = highest_cur_seq_no;
  
          }
  
  
  
          pls->read_buffer = av_malloc(INITIAL_BUFFER_SIZE);
  
          if (!pls->read_buffer){
  
              ret = AVERROR(ENOMEM);
  
              avformat_free_context(pls->ctx);
  
              pls->ctx = NULL;
  
              goto fail;
  
          }
  
          ffio_init_context(&pls->pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls,
  
                            read_data, NULL, NULL);
  
          pls->pb.seekable = 0;
  
          ret = av_probe_input_buffer(&pls->pb, &in_fmt, pls->segments[0]->url,
  
                                      NULL, 0, 0);
  
          if (ret < 0) {
  
              /* Free the ctx - it isn't initialized properly at this point,
  
               * so avformat_close_input shouldn't be called. If
  
               * avformat_open_input fails below, it frees and zeros the
  
               * context, so it doesn't need any special treatment like this. */
  
              av_log(s, AV_LOG_ERROR, "Error when loading first segment '%s'\n", pls->segments[0]->url);
  
              avformat_free_context(pls->ctx);
  
              pls->ctx = NULL;
  
              goto fail;
  
          }
  
          pls->ctx->pb       = &pls->pb;
  
          pls->ctx->io_open  = nested_io_open;
  
  
  
          if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0)
  
              goto fail;
  
  
  
          ret = avformat_open_input(&pls->ctx, pls->segments[0]->url, in_fmt, NULL);
  
          if (ret < 0)
  
              goto fail;
  
  
  
          if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) {
  
              ff_id3v2_parse_apic(pls->ctx, &pls->id3_deferred_extra);
  
              avformat_queue_attached_pictures(pls->ctx);
  
              ff_id3v2_free_extra_meta(&pls->id3_deferred_extra);
  
              pls->id3_deferred_extra = NULL;
  
          }
  
  
  
          if (pls->is_id3_timestamped == -1)
  
              av_log(s, AV_LOG_WARNING, "No expected HTTP requests have been made\n");
  
  
  
          /*
  
           * For ID3 timestamped raw audio streams we need to detect the packet
  
           * durations to calculate timestamps in fill_timing_for_id3_timestamped_stream(),
  
           * but for other streams we can rely on our user calling avformat_find_stream_info()
  
           * on us if they want to.
  
           */
  
          if (pls->is_id3_timestamped) {
  
              ret = avformat_find_stream_info(pls->ctx, NULL);
  
              if (ret < 0)
  
                  goto fail;
  
          }
  
  
  
          pls->has_noheader_flag = !!(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER);
  
  
  
          /* Create new AVStreams for each stream in this playlist */
  
          ret = update_streams_from_subdemuxer(s, pls);
  
          if (ret < 0)
  
              goto fail;
  
  
  
          add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_AUDIO);
  
          add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_VIDEO);
  
          add_metadata_from_renditions(s, pls, AVMEDIA_TYPE_SUBTITLE);
  
      }
  
  
  
      update_noheader_flag(s);
  
  
  
      return 0;
  
  fail:
  
      free_playlist_list(c);
  
      free_variant_list(c);
  
      free_rendition_list(c);
  
      return ret;
  
  }
  