[FFmpeg-user] Why does the new version of ffmpeg play non-interlaced http files so stuck?

^_^ 180087246 at qq.com
Wed Jul 22 08:28:50 EEST 2020


I use MAC's AVAssetWriter/AVAssetWriterInput to generate MP4, then upload it to the website, and then use the latest version (ffmpeg4.2 or 4.3) of ffplay to play the file as https file on Windows, but I find it is very stuck. I use the old version of ffmpeg For example, the 3.4 version is normal. By analyzing the old and new ffmpeg source code, the general problem is basically located, but the deeper reason is still unclear.

The audio and video frames recorded by MAC are partially (within 3 seconds) non-interleaved

The latest version of Window's ffplay will continue to reconnect http to Seek In the mov.c file, it is found that the number of AVIndexEntry created by the new and old versions ffmpeg is different, because the read buffer size is determined by the calculation of ff_configure_buffers_for_index: the buffer_size of the new version of AVIOContext is only the default 16k, so the pre-step of mov_read_packet avio_seek finds that the pos of the next frame is not within the 16k range, which leads to reconnecting to http and seeking to a new position; while the AVIOContext.buffer_size of the old version of ffmpeg has a size of M Bytes level, it will not trigger reconnection of http.

Further analysis found that ff_configure_buffers_for_index will be calculated based on the relative maximum offset of the AVIndexEntry of each stream, because the new version skips the opportunity to adjust the buffer_size because the pos_delta is greater than 1<<24.

But I don’t know why the new version of AVIndexEntry has this situation. Do you know why the "new" version has made this change? And how to make the player plays as smoothly as the old version?

void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance)  {      int ist1, ist2;      int64_t pos_delta = 0;      int64_t skip = 0;      //We could use URLProtocol flags here but as many user applications do not use URLProtocols this would be unreliable      const char *proto = avio_find_protocol_name(s->filename);      if (!proto) {          av_log(s, AV_LOG_INFO,             "Protocol name not provided, cannot determine if input is local or "             "a network protocol, buffers and access patterns cannot be configured "             "optimally without knowing the protocol\n");      }      if (proto && !(strcmp(proto, "file") && strcmp(proto, "pipe") && strcmp(proto, "cache")))          return;      for (ist1 = 0; ist1 < s->nb_streams; ist1++) {          AVStream *st1 = s->streams[ist1];          for (ist2 = 0; ist2 < s->nb_streams; ist2++) {              AVStream *st2 = s->streams[ist2];              int i1, i2;              if (ist1 == ist2)                  continue;              for (i1 = i2 = 0; i1 < st1->nb_index_entries; i1++) {                  AVIndexEntry *e1 = &st1->index_entries[i1];                  int64_t e1_pts = av_rescale_q(e1->timestamp, st1->time_base, AV_TIME_BASE_Q);                  skip = FFMAX(skip, e1->size);                  for (; i2 < st2->nb_index_entries; i2++) {                      AVIndexEntry *e2 = &st2->index_entries[i2];                      int64_t e2_pts = av_rescale_q(e2->timestamp, st2->time_base, AV_TIME_BASE_Q);                      if (e2_pts - e1_pts < time_tolerance)                          continue;                      pos_delta = FFMAX(pos_delta, e1->pos - e2->pos);                      av_log(s, AV_LOG_VERBOSE, "ff_configure_buffers_for_index  [%d, %d]  (%"PRId64", %"PRId64"):    %"PRId64"\n",  i1, i2, e1_pts, e2_pts, pos_delta);                      break;                  }              }          }      }      pos_delta *= 2;      /* XXX This could be adjusted depending on protocol*/      if (s->pb->buffer_size < pos_delta && pos_delta < (1<<24)) {          av_log(s, AV_LOG_VERBOSE, "Reconfiguring buffers to size %"PRId64"\n", pos_delta);          ffio_set_buf_size(s->pb, pos_delta);          s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, pos_delta/2);      }      if (skip < (1<<23)) {          s->pb->short_seek_threshold = FFMAX(s->pb->short_seek_threshold, skip);      }  }

More information about the ffmpeg-user mailing list