[FFmpeg-devel] [PATCH] Question for Intel QSV low latency
Hi, this is re-posting of below message. http://ffmpeg.org/pipermail/ffmpeg-devel/2017-November/219643.html I believe the patch format is correct this time around. In order to encode with low latency in Intel QSV, we need to fix libavcodec/qsvenc.c like below diff info. I don't understand why q->async_fifo would be set to q->async_depth "+1". If you know about that or have any comments or suggestions, please tell me. Thank you. --- libavcodec/qsvenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bc19f5241..7d73c64dca 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -803,7 +803,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) q->param.AsyncDepth = q->async_depth; -q->async_fifo = av_fifo_alloc((1 + q->async_depth) * +q->async_fifo = av_fifo_alloc((q->async_depth) * (sizeof(AVPacket) + sizeof(mfxSyncPoint*) + sizeof(mfxBitstream*))); if (!q->async_fifo) return AVERROR(ENOMEM); -- 2.13.6 (Apple Git-96) ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] avcodec/qsvenc Question for Intel QSV low latency
Hello guys, this is my first posting to ffmpeg-devel, and I believe my mail format is correct. I'm using ffmpeg for encoding video in real-time, so low encode delay is needed. Once I call "avcodec_send_frame(avctx, frame)", I'd like to get the encoded data from "avcodec_receive_packet(avctx, avpkt)". However I cannot do that in ffmpeg and Intel QSV (qsv), "avcodec_receive_packet()" returns nothing when I input the first frame to qsv encoder by calling "avcodec_send_frame()". Of cource, after second frame inputs, qsv encoder returns valid data. I'd like to get a valid data from first calling. I've tried some cases and as a result, my requirement is satisfied when avcodec/qsvenc.c will be fixed like below diff info. Then I have a question. Why q->async_fifo is set to be q->async_depth "+ 1"? Anybody knows? --- a/avcodec/qsvenc.c +++ b/avcodec/qsvenc.c @@ -803,7 +803,7 @@ q->param.AsyncDepth = q->async_depth; -q->async_fifo = av_fifo_alloc((1 + q->async_depth) * +q->async_fifo = av_fifo_alloc((q->async_depth) * (sizeof(AVPacket) + sizeof(mfxSyncPoint*) + sizeof(mfxBitstream*))); if (!q->async_fifo) return AVERROR(ENOMEM); ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] avcodec/qsvenc Question for Intel QSV low latency
Oh sorry, I don't understand how to do well yet... I'll try again. Thank you guys. diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 2bc19f5241..7d73c64dca 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -803,7 +803,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) q->param.AsyncDepth = q->async_depth; -q->async_fifo = av_fifo_alloc((1 + q->async_depth) * +q->async_fifo = av_fifo_alloc((q->async_depth) * (sizeof(AVPacket) + sizeof(mfxSyncPoint*) + sizeof(mfxBitstream*))); if (!q->async_fifo) return AVERROR(ENOMEM); On Mon, Nov 13, 2017 at 1:13 AM, Michael Niedermayer wrote: > On Sun, Nov 12, 2017 at 11:40:57AM +0900, Natsuki Kai wrote: > > Hello guys, > > > > this is my first posting to ffmpeg-devel, and I believe my mail format is > > correct. > > > > I'm using ffmpeg for encoding video in real-time, so low encode delay is > > needed. > > Once I call "avcodec_send_frame(avctx, frame)", I'd like to get the > encoded > > data from "avcodec_receive_packet(avctx, avpkt)". > > > > However I cannot do that in ffmpeg and Intel QSV (qsv), > > "avcodec_receive_packet()" returns nothing when I input the first frame > to > > qsv encoder by calling "avcodec_send_frame()". > > Of cource, after second frame inputs, qsv encoder returns valid data. > > I'd like to get a valid data from first calling. > > > > I've tried some cases and as a result, my requirement is satisfied when > > avcodec/qsvenc.c will be fixed like below diff info. > > Then I have a question. > > Why q->async_fifo is set to be q->async_depth "+ 1"? > > Anybody knows? > > > > --- a/avcodec/qsvenc.c > > +++ b/avcodec/qsvenc.c > > @@ -803,7 +803,7 @@ > > > > q->param.AsyncDepth = q->async_depth; > > > > -q->async_fifo = av_fifo_alloc((1 + q->async_depth) * > > +q->async_fifo = av_fifo_alloc((q->async_depth) * > >(sizeof(AVPacket) + > > sizeof(mfxSyncPoint*) + sizeof(mfxBitstream*))); > > if (!q->async_fifo) > > return AVERROR(ENOMEM); > > This looks corrupted by a newline > > Applying: avcodec/qsvenc Question for Intel QSV low latency > error: corrupt patch at line 10 > > [...] > -- > Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB > > Those who are best at talking, realize last or never when they are wrong. > > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] avcodec/qsvenc Question for Intel QSV low latency
Hi Moritz, Thank you for explaining in details. It really helped me. It seems gmail or other mail tool shouldn't be used, but only "git send-email" is accepted. I posted patch mail from git command. http://ffmpeg.org/pipermail/ffmpeg-devel/2017-November/219805.html So please discuss in that thread. P.S. I've been confused because "git send-email" doesn't work on windows PC... Finally, I gave up working on windows and posted on Mac. On Mon, Nov 13, 2017 at 9:54 PM, Moritz Barsnick wrote: > On Mon, Nov 13, 2017 at 14:13:15 +0900, Natsuki Kai wrote: >> Oh sorry, I don't understand how to do well yet... > [...] >> -q->async_fifo = av_fifo_alloc((1 + q->async_depth) * >> +q->async_fifo = av_fifo_alloc((q->async_depth) * >>(sizeof(AVPacket) + >> sizeof(mfxSyncPoint*) + sizeof(mfxBitstream*))); > > Your mail tool or send chain is inserting linebreaks into the patch. It > will therefore not work anymore on the receiving side (as it is not > only visually inspected on the list, but also tested). You can either > send the patch with "git send-email", or attach it as a separate file. > > Moritz > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] avcodec/qsvenc Question for Intel QSV low latency
I sent it as another thread, but yes it's ok. Please check the attachment patch file. Thank you. On Wed, Nov 15, 2017 at 7:55 AM, Carl Eugen Hoyos wrote: > 2017-11-14 17:02 GMT+01:00 Natsuki Kai : >> Hi Moritz, >> >> Thank you for explaining in details. It really helped me. >> It seems gmail or other mail tool shouldn't be used, but only "git >> send-email" is accepted. > > Just send your patch - made with git format-patch - as > attachment. This should work with all mail clients. > > Carl Eugen > ___ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel 0001-Question-for-Intel-QSV-low-latency.patch Description: Binary data ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] avcodec/hevc: compatible with mixed use of annexb and hvcc on bitstream like h264dec
Hi: I found it's different actions with h264 and hevc when decoded. I try to make it same as blow. But I have no idea about the code: *libavcode/h264dec.c:609 * *AV_RB32(buf+5) > (unsigned)buf_size* I tried to find the answer in specs, but I failed. So I am not sure that it is valid in hevc. From: Li Kai Date: Fri, 12 Jul 2024 10:21:17 +0800 Subject: [PATCH] avcodec/hevc: compatible with mixed use of annexb and hvcc on bitstream like h264dec Signed-off-by: Li Kai --- libavcodec/hevc/hevcdec.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c index fd143cddab..59e99493d5 100644 --- a/libavcodec/hevc/hevcdec.c +++ b/libavcodec/hevc/hevcdec.c @@ -3290,6 +3290,13 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) s->eos = 0; s->slice_initialized = 0; +if (s->nal_length_size == 4) { +if (length > 8 && AV_RB32(buf) == 1 && AV_RB32(buf+5) > (unsigned)length) { +s->is_nalff = 0; +} else if (length > 3 && AV_RB32(buf) > 1 && AV_RB32(buf) <= (unsigned)length) +s->is_nalff = 1; +} + /* split the input packet into NAL units, so we know the upper bound on the * number of slices in the frame */ ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff, -- 2.45.1 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
[FFmpeg-devel] [PATCH] avutil/error: uniformize errbuf size by macro
Signed-off-by: likai --- libavdevice/bktr.c| 2 +- libavdevice/jack.c| 2 +- libavformat/crypto.c | 2 +- libavformat/network.c | 6 +++--- libavutil/file.c | 2 +- tools/aviocat.c | 2 +- tools/ismindex.c | 4 ++-- tools/sidxindex.c | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libavdevice/bktr.c b/libavdevice/bktr.c index 196637852f..a24b80a4bb 100644 --- a/libavdevice/bktr.c +++ b/libavdevice/bktr.c @@ -106,7 +106,7 @@ static av_cold int bktr_init(const char *video_device, int width, int height, int c; struct sigaction act, old; int ret; -char errbuf[128]; +char errbuf[AV_ERROR_MAX_STRING_SIZE]; if (idev < 0 || idev > 4) { diff --git a/libavdevice/jack.c b/libavdevice/jack.c index db056d824f..8150a91f13 100644 --- a/libavdevice/jack.c +++ b/libavdevice/jack.c @@ -289,7 +289,7 @@ static int audio_read_packet(AVFormatContext *context, AVPacket *pkt) av_log(context, AV_LOG_ERROR, "Input error: timed out when waiting for JACK process callback output\n"); } else { -char errbuf[128]; +char errbuf[AV_ERROR_MAX_STRING_SIZE]; int ret = AVERROR(errno); av_strerror(ret, errbuf, sizeof(errbuf)); av_log(context, AV_LOG_ERROR, "Error while waiting for audio packet: %s\n", diff --git a/libavformat/crypto.c b/libavformat/crypto.c index 1d4514e0f2..41391c7a16 100644 --- a/libavformat/crypto.c +++ b/libavformat/crypto.c @@ -314,7 +314,7 @@ static int64_t crypto_seek(URLContext *h, int64_t pos, int whence) // if we did not get all the bytes if (len != 0) { -char errbuf[100] = "unknown error"; +char errbuf[AV_ERROR_MAX_STRING_SIZE] = "unknown error"; av_strerror(res, errbuf, sizeof(errbuf)); av_log(h, AV_LOG_ERROR, "Crypto: discard read did not get all the bytes (%d remain) - read returned (%d)-%s\n", diff --git a/libavformat/network.c b/libavformat/network.c index f752efc411..d02ec65b8a 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -282,7 +282,7 @@ int ff_listen_connect(int fd, const struct sockaddr *addr, if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) ret = AVUNERROR(ff_neterrno()); if (ret != 0) { -char errbuf[100]; +char errbuf[AV_ERROR_MAX_STRING_SIZE]; ret = AVERROR(ret); av_strerror(ret, errbuf, sizeof(errbuf)); if (will_try_next) @@ -416,7 +416,7 @@ int ff_connect_parallel(struct addrinfo *addrs, int timeout_ms_per_address, int64_t next_attempt_us = av_gettime_relative(), next_deadline_us; int last_err = AVERROR(EIO); socklen_t optlen; -char errbuf[100], hostbuf[100], portbuf[20]; +char errbuf[AV_ERROR_MAX_STRING_SIZE], hostbuf[100], portbuf[20]; if (parallel > FF_ARRAY_ELEMS(attempts)) parallel = FF_ARRAY_ELEMS(attempts); @@ -586,7 +586,7 @@ int ff_http_match_no_proxy(const char *no_proxy, const char *hostname) void ff_log_net_error(void *ctx, int level, const char* prefix) { -char errbuf[100]; +char errbuf[AV_ERROR_MAX_STRING_SIZE]; av_strerror(ff_neterrno(), errbuf, sizeof(errbuf)); av_log(ctx, level, "%s: %s\n", prefix, errbuf); } diff --git a/libavutil/file.c b/libavutil/file.c index 6a2f3aa91c..0477b821f0 100644 --- a/libavutil/file.c +++ b/libavutil/file.c @@ -59,7 +59,7 @@ int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, struct stat st; av_unused void *ptr; off_t off_size; -char errbuf[128]; +char errbuf[AV_ERROR_MAX_STRING_SIZE]; *bufptr = NULL; *size = 0; diff --git a/tools/aviocat.c b/tools/aviocat.c index 816ab700ef..969a883011 100644 --- a/tools/aviocat.c +++ b/tools/aviocat.c @@ -37,7 +37,7 @@ int main(int argc, char **argv) const char *input_url = NULL, *output_url = NULL; int64_t stream_pos = 0; int64_t start_time; -char errbuf[50]; +char errbuf[AV_ERROR_MAX_STRING_SIZE]; AVIOContext *input, *output; AVDictionary *in_opts = NULL; AVDictionary *out_opts = NULL; diff --git a/tools/ismindex.c b/tools/ismindex.c index 39b5378190..7778c92797 100644 --- a/tools/ismindex.c +++ b/tools/ismindex.c @@ -148,7 +148,7 @@ static int write_fragment(const char *filename, AVIOContext *in) int ret; if ((ret = avio_open2(&out, filename, AVIO_FLAG_WRITE, NULL, NULL)) < 0) { -char errbuf[100]; +char errbuf[AV_ERROR_MAX_STRING_SIZE]; av_strerror(ret, errbuf, sizeof(errbuf)); fprintf(stderr, "Unable to open %s: %s\n", filename, errbuf); return ret; @@ -499,7 +499,7 @@ static int handle_file(struct Tracks *tracks, const char *file, int split, { AVFormatContext *ctx = NULL; int err = 0, i, orig_tracks = tracks->nb_tracks; -char errbuf[50], *ptr; +
Re: [FFmpeg-devel] [PATCH] avformat/hls:use EXT-X-START instead of live_start_index if it's in playlist
From: Li Kai Signed-off-by: Li Kai --- libavformat/hls.c | 55 +-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 8204f55df3..bfb20f6492 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -120,6 +120,8 @@ struct playlist { enum PlaylistType type; int64_t target_duration; int64_t start_seq_no; +int time_offset_flag; +int64_t start_time_offset; int n_segments; struct segment **segments; int needed; @@ -741,6 +743,7 @@ static int parse_playlist(HLSContext *c, const char *url, struct segment **prev_segments = NULL; int prev_n_segments = 0; int64_t prev_start_seq_no = -1; +const char *p; if (is_http && !in && c->http_persistent && c->playlist_pb) { in = c->playlist_pb; @@ -889,6 +892,18 @@ static int parse_playlist(HLSContext *c, const char *url, cur_init_section->key = NULL; } +} else if (av_strstart(line, "#EXT-X-START:", &ptr)) { +ret = ensure_playlist(c, &pls, url); +if (ret < 0) { +goto fail; +} +if (av_strstart(ptr, "TIME-OFFSET=", &p)) { +float offset = strtof(p, NULL); +pls->start_time_offset = offset * AV_TIME_BASE; +pls->time_offset_flag = 1; +} else { +goto fail; +} } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { if (pls) pls->finished = 1; @@ -1722,9 +1737,45 @@ static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls) /* If this is a live stream, start live_start_index segments from the * start or end */ If EXT-X-START tag in playlist and users set live_start_index, the live_start_index will not work for current codes, which makes users confused. If make live_start_index valid when EXT-X-START tag in playlist, maybe live_start_index needs a flag, or make live_start_index default value is INT_MIN to distinguish. becuase the live_start_index default value is -3, I have no idea to distinguish users action or default value when live_start_index=-3. May I need to set default value=INT_MIN as live_start_index default value? And only when not exist EXT-X-START tag in playlist, make live_start_index = -3 or users's configuration value, it's ok? if (c->live_start_index < 0) -return pls->start_seq_no + FFMAX(pls->n_segments + c->live_start_index, 0); +seq_no = pls->start_seq_no + FFMAX(pls->n_segments + +c->live_start_index, 0); else -return pls->start_seq_no + FFMIN(c->live_start_index, pls->n_segments - 1); +seq_no = pls->start_seq_no + FFMIN(c->live_start_index, +pls->n_segments - 1); + +/* If #EXT-X-START in playlist, need to recalculate */ +if (pls->time_offset_flag) { +int64_t start_timestamp; +int64_t playlist_duration = 0; +int64_t cur_timestamp = c->cur_timestamp == AV_NOPTS_VALUE ? 0 : +c->cur_timestamp; + +for (int i = 0; i < pls->n_segments; i++) +playlist_duration += pls->segments[i]->duration; + +/* If the absolute value of TIME-OFFSET exceeds + * the duration of the playlist, it indicates either the end of the + * playlist (if positive) or the beginning of the playlist (if + * negative). */ +if (pls->start_time_offset >=0 && +pls->start_time_offset > playlist_duration) +start_timestamp = cur_timestamp + playlist_duration; +else if (pls->start_time_offset >= 0 && +pls->start_time_offset <= playlist_duration) +start_timestamp = cur_timestamp + pls->start_time_offset; +else if (pls->start_time_offset < 0 && +pls->start_time_offset < -playlist_duration) +start_timestamp = cur_timestamp; +else if (pls->start_time_offset < 0 && +pls->start_time_offset > -playlist_duration) +start_timestamp = cur_timestamp + playlist_duration + +pls->start_time_offset; +else +start_timestamp = cur_timestamp; + +find_timestamp_in_playlist(c, pls, start_timestamp, &seq_no, NULL); +} +return seq_no; } /* Otherwise just start on the first segment. */ -- 2.25.1 Thanks a lot! ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avformat/hls:use EXT-X-START instead of live_start_index if it's in playlist
m, start live_start_index segments > >> from the > >>> * start or end */ > >>> -if (c->live_start_index < 0) > >>> -return pls->start_seq_no + FFMAX(pls->n_segments + > >> c->live_start_index, 0); > >>> -else > >>> -return pls->start_seq_no + FFMIN(c->live_start_index, > >> pls->n_segments - 1); > >>> +if (c->live_start_index != INT_MIN) { > >> Maybe you should not change current logic. > >> You can just add about process EXT-X-START sence,. > >> For example: > >> compute the start_seq_no and save the value to a temp varible and > >> don't return immediately, check the third scence which get EXT-X-START > >> tag from playlist. > >> process the temp varible after start_seq_no compute from > >> live_start_index or EXT-X-START. > >> > >>> +if (c->live_start_index < 0) > >>> +return pls->start_seq_no + FFMAX(pls->n_segments + > >>> +c->live_start_index, > 0); > >>> +else > >>> +return pls->start_seq_no + FFMIN(c->live_start_index, > >>> +pls->n_segments - 1); > >>> +} else if (c->live_start_index == INT_MIN && > >> !pls->time_offset_flag) { > >>> +return pls->start_seq_no + FFMAX(pls->n_segments - 3, 0); > >>> +} else { > >>> +/* If playlist indicate a TIME-OFFSET and user not use > >> live_start_index, > >>> + * need to recalculate seq_no */ > >>> +int i; > >>> +int64_t start_timestamp; > >>> +int64_t playlist_duration = 0; > >>> +int64_t cur_timestamp = c->cur_timestamp == AV_NOPTS_VALUE > >> ? 0 : > >>> +c->cur_timestamp; > >>> + > >>> +for (i = 0; i < pls->n_segments; i++) { > >>> +playlist_duration += pls->segments[i]->duration; > >>> +} > >>> +/* If the absolute value of TIME-OFFSET exceeds > >>> + * the duration of the playlist, it indicates either the > >> end of the > >>> + * playlist (if positive) or the beginning of the playlist > >> (if > >>> + * negative). */ > >>> +if (pls->start_time_offset >=0 && > >>> +pls->start_time_offset > playlist_duration) > >>> +start_timestamp = cur_timestamp + playlist_duration; > >>> +else if (pls->start_time_offset >= 0 && > >>> +pls->start_time_offset <= playlist_duration) > >>> +start_timestamp = cur_timestamp + > >> pls->start_time_offset; > >>> +else if (pls->start_time_offset < 0 && > >>> +pls->start_time_offset < -playlist_duration) > >>> +start_timestamp = cur_timestamp; > >>> +else if (pls->start_time_offset < 0 && > >>> +pls->start_time_offset > -playlist_duration) > >>> +start_timestamp = cur_timestamp + playlist_duration + > >>> +pls->start_time_offset; > >>> +else > >>> +start_timestamp = cur_timestamp; > >>> + > >>> +find_timestamp_in_playlist(c, pls, start_timestamp, > >> &seq_no, NULL); > >>> +av_log(c, AV_LOG_DEBUG, "start_timestamp: %" PRId64 > >>> +"cur_timestamp:%" PRId64 > >>> + "cur_seq_no:%" PRId64 "\n", > >>> +start_timestamp, cur_timestamp, > >> seq_no); > >>> +return seq_no; > >>> +} > >>> } > >>> > >>> /* Otherwise just start on the first segment. */ > >>> @@ -2475,7 +2534,7 @@ static int hls_probe(const AVProbeData *p) > >>> #define FLAGS AV_OPT_FLAG_DECODING_PARAM > >>> static const AVOption hls_options[]
Re: [FFmpeg-devel] [PATCH] avformat/hls:use EXT-X-START instead of live_start_index if it's in playlist
m, start live_start_index segments > >> from the > >>> * start or end */ > >>> -if (c->live_start_index < 0) > >>> -return pls->start_seq_no + FFMAX(pls->n_segments + > >> c->live_start_index, 0); > >>> -else > >>> -return pls->start_seq_no + FFMIN(c->live_start_index, > >> pls->n_segments - 1); > >>> +if (c->live_start_index != INT_MIN) { > >> Maybe you should not change current logic. > >> You can just add about process EXT-X-START sence,. > >> For example: > >> compute the start_seq_no and save the value to a temp varible and > >> don't return immediately, check the third scence which get EXT-X-START > >> tag from playlist. > >> process the temp varible after start_seq_no compute from > >> live_start_index or EXT-X-START. > >> > >>> +if (c->live_start_index < 0) > >>> +return pls->start_seq_no + FFMAX(pls->n_segments + > >>> +c->live_start_index, > 0); > >>> +else > >>> +return pls->start_seq_no + FFMIN(c->live_start_index, > >>> +pls->n_segments - 1); > >>> +} else if (c->live_start_index == INT_MIN && > >> !pls->time_offset_flag) { > >>> +return pls->start_seq_no + FFMAX(pls->n_segments - 3, 0); > >>> +} else { > >>> +/* If playlist indicate a TIME-OFFSET and user not use > >> live_start_index, > >>> + * need to recalculate seq_no */ > >>> +int i; > >>> +int64_t start_timestamp; > >>> +int64_t playlist_duration = 0; > >>> +int64_t cur_timestamp = c->cur_timestamp == AV_NOPTS_VALUE > >> ? 0 : > >>> +c->cur_timestamp; > >>> + > >>> +for (i = 0; i < pls->n_segments; i++) { > >>> +playlist_duration += pls->segments[i]->duration; > >>> +} > >>> +/* If the absolute value of TIME-OFFSET exceeds > >>> + * the duration of the playlist, it indicates either the > >> end of the > >>> + * playlist (if positive) or the beginning of the playlist > >> (if > >>> + * negative). */ > >>> +if (pls->start_time_offset >=0 && > >>> +pls->start_time_offset > playlist_duration) > >>> +start_timestamp = cur_timestamp + playlist_duration; > >>> +else if (pls->start_time_offset >= 0 && > >>> +pls->start_time_offset <= playlist_duration) > >>> +start_timestamp = cur_timestamp + > >> pls->start_time_offset; > >>> +else if (pls->start_time_offset < 0 && > >>> +pls->start_time_offset < -playlist_duration) > >>> +start_timestamp = cur_timestamp; > >>> +else if (pls->start_time_offset < 0 && > >>> +pls->start_time_offset > -playlist_duration) > >>> +start_timestamp = cur_timestamp + playlist_duration + > >>> +pls->start_time_offset; > >>> +else > >>> +start_timestamp = cur_timestamp; > >>> + > >>> +find_timestamp_in_playlist(c, pls, start_timestamp, > >> &seq_no, NULL); > >>> +av_log(c, AV_LOG_DEBUG, "start_timestamp: %" PRId64 > >>> +"cur_timestamp:%" PRId64 > >>> + "cur_seq_no:%" PRId64 "\n", > >>> +start_timestamp, cur_timestamp, > >> seq_no); > >>> +return seq_no; > >>> +} > >>> } > >>> > >>> /* Otherwise just start on the first segment. */ > >>> @@ -2475,7 +2534,7 @@ static int hls_probe(const AVProbeData *p) > >>> #define FLAGS AV_OPT_FLAG_DECODING_PARAM > >>> static const AVOption hls_options[]
Re: [FFmpeg-devel] [PATCH] avformat/hls:use EXT-X-START instead of live_start_index if it's in playlist
OK, I add the option description in doc/demuxers.texi. About invalid EXT-X-START value, it's not played on Safari. So I make it error to handle. You opinion, it's better way. The latest patch fix it. On 2022/6/25 21:26, Steven Liu wrote: > > >> 在 2022年6月25日,13:24,Li Kai 写道: >> >> Ok, I add allowed_x_start option, and the option default is 0. So current > What about use “prefer_x_start” for option name. > > BTW, add option descriptions into document doc/demuxers.texi > > > +} else if (av_strstart(line, "#EXT-X-START:", &ptr)) { > +ret = ensure_playlist(c, &pls, url); > +if (ret < 0) { > +goto fail; > +} > +if (av_strstart(ptr, "TIME-OFFSET=", &p)) { > +float offset = strtof(p, NULL); > +pls->start_time_offset = offset * AV_TIME_BASE; > +pls->time_offset_flag = 1; > +} else { > +goto fail; > +} > > should this logic goto fail? > why don’t output a warning and continue try to use live_start_index? Or maybe there have some reason, are they? >> users will not be affected. >> please review again. >> >> At last, Thanks your tips. >> >> Steven Liu 于2022年6月25日周六 12:51写道: >> >>> >>> >>>> 在 2022年6月25日,12:32,少宇李 写道: >>>> >>>> Hi Steven, >>>> >>>> Please review code. >>>> >>>> I changed code, but I still have a question. >>>> If EXT-X-START tag in playlist and users set live_start_index, the >>>> live_start_index will not work >>>> for current codes, which makes maybe users confused. >>>> Is that OK? >>> for current codes, user cannot aware there have EXT-X-START tag in the >>> playlist, so i think we should reserve the old use method. >>> or maybe you can add an option for user to decide which way they can use >>> (either EXT-X-START or live_start_index). >>> Because there should have many people using live_start_index for 'time >>> shift’ by player (user control), >>> >>>> >>>> In other hand, if make live_start_index valid when EXT-X-START tag in >>>> playlist, maybe live_start_index needs a flag, or >>>> make live_start_index default value is INT_MIN to distinguish. >>>> becuase the live_start_index default value is -3, I have no idea to >>>> distinguish users action or >>>> default value when live_start_index=-3. >>> yes cannot distinguish users action, but user should can decided use >>> live_start_index or EXT-X-START. >>> >>>> >>>> May I need to set default value=INT_MIN as live_start_index default >>> value? >>>> And only when does not exist EXT-X-START >>>> tag in playlist, make live_start_index = -3 or users's configuration >>> value. >>>> I have no idea which is better~ >>>> >>>> Thanks a lot! >>>> >>>> Steven Liu 于2022年6月24日周五 14:21写道: >>>> >>>>> 少宇李 于2022年6月24日周五 11:58写道: >>>>>>> >>>>>>> >>>>>>> Hi, Steven >>>>>> >>>>>> >>>>>> I got it. >>>>>> >>>>>> User could use "live_start_index" option even if #EXT-X-START in the >>>>> playlist. >>>>>> >>>>>> I changed the priority about #EXT-X-START/live_start_index, >>>>>> >>>>>> this is new bellow: >>>>>> >>>>>> --- >>>>>> libavformat/hls.c | 69 +++ >>>>>> 1 file changed, 64 insertions(+), 5 deletions(-) >>>>>> >>>>>> diff --git a/libavformat/hls.c b/libavformat/hls.c >>>>>> index b736f093a9..309471efce 100644 >>>>>> --- a/libavformat/hls.c >>>>>> +++ b/libavformat/hls.c >>>>>> @@ -120,6 +120,8 @@ struct playlist { >>>>>>enum PlaylistType type; >>>>>>int64_t target_duration; >>>>>>int64_t start_seq_no; >>>>>> +int time_offset_flag; >>>>>> +int64_t start_time_offset; >>>>>>int n_segments; >>>>>>struct segment **segments; >>>>>>int needed; >>>>>> @@ -741,6 +743,7 @@ static int par
Re: [FFmpeg-devel] [PATCH] avformat/hls:use EXT-X-START instead of live_start_index if it's in playlist
OK, I got it. Thanks a lot. 在 2022/6/27 上午10:23, Steven Liu 写道: Li Kai 于2022年6月25日周六 22:15写道: OK, I add the option description in doc/demuxers.texi. About invalid EXT-X-START value, it's not played on Safari. So I make it error to handle. You opinion, it's better way. The latest patch fix it. @@ -741,6 +744,7 @@ static int parse_playlist(HLSContext *c, const char *url, struct segment **prev_segments = NULL; int prev_n_segments = 0; int64_t prev_start_seq_no = -1; +const char *p; if (is_http && !in && c->http_persistent && c->playlist_pb) { in = c->playlist_pb; @@ -889,6 +893,20 @@ static int parse_playlist(HLSContext *c, const char *url, cur_init_section->key = NULL; } +} else if (av_strstart(line, "#EXT-X-START:", &ptr)) { Can the "const char *p;" move to here? And maybe make a clarify name will better i think, e.g. const char *time_offset_value? +ret = ensure_playlist(c, &pls, url); +if (ret < 0) { +goto fail; +} +if (av_strstart(ptr, "TIME-OFFSET=", &p)) { +float offset = strtof(p, NULL); +pls->start_time_offset = offset * AV_TIME_BASE; +pls->time_offset_flag = 1; +} else { +av_log(c->ctx, AV_LOG_WARNING, "#EXT-X-START value is" +"invalid, it will be ignored"); +continue; +} } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { if (pls) pls->finished = 1; Thanks StevenFrom 9c812414bc21030182fda00e702ea6433c920c9d Mon Sep 17 00:00:00 2001 From: Li Kai Date: Thu, 23 Jun 2022 00:55:38 +0800 Subject: [PATCH v4] avformat/hls: add #EXT-X-START tag support by prefer_x_start opt Signed-off-by: Li Kai --- doc/demuxers.texi | 3 +++ libavformat/hls.c | 60 +-- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index c95a9ae594..2b6dd86c2a 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -373,6 +373,9 @@ It accepts the following options: @item live_start_index segment index to start live streams at (negative values are from the end). +@item prefer_x_start +prefer to use #EXT-X-START if it's in playlist instead of live_start_index. + @item allowed_extensions ',' separated list of file extensions that hls is allowed to access. diff --git a/libavformat/hls.c b/libavformat/hls.c index b736f093a9..8ea4ff4671 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -120,6 +120,8 @@ struct playlist { enum PlaylistType type; int64_t target_duration; int64_t start_seq_no; +int time_offset_flag; +int64_t start_time_offset; int n_segments; struct segment **segments; int needed; @@ -211,6 +213,7 @@ typedef struct HLSContext { int64_t cur_seq_no; int m3u8_hold_counters; int live_start_index; +int prefer_x_start; int first_packet; int64_t first_timestamp; int64_t cur_timestamp; @@ -889,6 +892,21 @@ static int parse_playlist(HLSContext *c, const char *url, cur_init_section->key = NULL; } +} else if (av_strstart(line, "#EXT-X-START:", &ptr)) { +ret = ensure_playlist(c, &pls, url); +if (ret < 0) { +goto fail; +} +const char *time_offset_value; +if (av_strstart(ptr, "TIME-OFFSET=", &time_offset_value)) { +float offset = strtof(time_offset_value, NULL); +pls->start_time_offset = offset * AV_TIME_BASE; +pls->time_offset_flag = 1; +} else { +av_log(c->ctx, AV_LOG_WARNING, "#EXT-X-START value is" +"invalid, it will be ignored"); +continue; +} } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { if (pls) pls->finished = 1; @@ -1722,9 +1740,45 @@ static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls) /* If this is a live stream, start live_start_index segments from the * start or end */ if (c->live_start_index < 0) -return pls->start_seq_no + FFMAX(pls->n_segments + c->live_start_index, 0); +seq_no = pls->start_seq_no + FFMAX(pls->n_segments + +c->live_start_index, 0); else -return pls->start_seq_no + FFMIN(c->live_start_index, pls->n_segments - 1); +seq_no = pls-&g