[FFmpeg-trac] #6885(avformat:open): Some media files don't work on FFmpeg as HTTP stream-in (worked with much older FFmpeg version)

FFmpeg trac at avcodec.org
Mon Oct 29 12:48:41 EET 2018


#6885: Some media files don't work on FFmpeg as HTTP stream-in (worked with much
older FFmpeg version)
-------------------------------------+-------------------------------------
             Reporter:  jaypadia     |                    Owner:
                 Type:  defect       |                   Status:  open
             Priority:  important    |                Component:  avformat
              Version:  git-master   |               Resolution:
             Keywords:  http mov     |               Blocked By:
  regression                         |  Reproduced by developer:  0
             Blocking:               |
Analyzed by developer:  0            |
-------------------------------------+-------------------------------------

Comment (by qichaoshen):

 The previous modification is not correct.

 The implement of
 "avio_seek(AVIOContext *s, int64_t offset, int whence)"
 #libavformat/avio.c#" encapsulates all IO operation of FILE, HTTP,
 Streaming,and so on.
 And I think that if a media file can seek to file end in local file mode,
 it should seek to the file end when it is on a HTTP Server.

 If a XXX.mp4 is a local file and the size is 200,420,354, we call
 avio_seek(AVIOContext *s, int64_t offset, int whence) by whence = SEEK_SET
 and offset=200,420,354, it finally call the following code:

 /////////////////////////////////////////////
 /* XXX: use llseek */
 static int64_t file_seek(URLContext *h, int64_t pos, int whence)
 {
     FileContext *c = h->priv_data;
     int64_t ret;

     if (whence == AVSEEK_SIZE) {
         struct stat st;
         ret = fstat(c->fd, &st);
         return ret < 0 ? AVERROR(errno) : (S_ISFIFO(st.st_mode) ? 0 :
 st.st_size);
     }

     ret = lseek(c->fd, pos, whence);

     return ret < 0 ? AVERROR(errno) : ret;
 }
 /////////////////////////////////////////////
 And it return 200,420,354.

 But if the same file at a HTTP Server, we call avio_seek(AVIOContext *s,
 int64_t offset, int whence) by whence = SEEK_SET and offset=200,420,354,
 it finally call the following code:
 ////////////////////////////////////////////
 static int64_t http_seek_internal(URLContext *h, int64_t off, int whence,
 int force_reconnect)
 {
     HTTPContext *s = h->priv_data;
     URLContext *old_hd = s->hd;
     uint64_t old_off = s->off;
     uint8_t old_buf[BUFFER_SIZE];
     int old_buf_size, ret;
     AVDictionary *options = NULL;

     if (whence == AVSEEK_SIZE)
         return s->filesize;
     else if (!force_reconnect &&
              ((whence == SEEK_CUR && off == 0) ||
               (whence == SEEK_SET && off == s->off)))
         return s->off;
     else if ((s->filesize == UINT64_MAX && whence == SEEK_END))
         return AVERROR(ENOSYS);

     if (whence == SEEK_CUR)
         off += s->off;
     else if (whence == SEEK_END)
         off += s->filesize;
     else if (whence != SEEK_SET)
         return AVERROR(EINVAL);
     if (off < 0)
         return AVERROR(EINVAL);
     s->off = off;

     if (s->off && h->is_streamed)
         return AVERROR(ENOSYS);

     /* we save the old context in case the seek fails */
     old_buf_size = s->buf_end - s->buf_ptr;
     memcpy(old_buf, s->buf_ptr, old_buf_size);
     s->hd = NULL;

     /* if it fails, continue on old connection */
     if ((ret = http_open_cnx(h, &options)) < 0) {
         av_dict_free(&options);
         memcpy(s->buffer, old_buf, old_buf_size);
         s->buf_ptr = s->buffer;
         s->buf_end = s->buffer + old_buf_size;
         s->hd      = old_hd;
         s->off     = old_off;
         return ret;
     }
     av_dict_free(&options);
     ffurl_close(old_hd);
     return off;
 }

 ////////////////////////////////////////////
 and it return fail, because the HTTP Server return 416 as following:

 "[http @ 0x7fd9d3c00240] header='HTTP/1.1 416 Requested Range Not
 Satisfiable' "

 It is strange that if the file at HTTP Server, we can not seek to the file
 end.
 Consider that some http resource is streamed, the file size of the
 resource is undefined or changing, and we should except it.
 So the modification can be

     if ((whence == AVSEEK_SIZE) || (h->is_streamed ==0 && whence ==
 SEEK_SET && off == s->filesize))
         return s->filesize;

--
Ticket URL: <https://trac.ffmpeg.org/ticket/6885#comment:15>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list