#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 _______________________________________________ FFmpeg-trac mailing list FFmpeg-trac@avcodec.org http://ffmpeg.org/mailman/listinfo/ffmpeg-trac