[FFmpeg-devel] [PATCH v4 1/2] lavf/hls: refactoring of read_header
--- libavformat/hls.c | 208 +++--- 1 file changed, 119 insertions(+), 89 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index ab6ff187a6..3c2c720abe 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -314,6 +314,8 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->is_id3_timestamped = -1; pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; +pls->index = c->n_playlists; +pls->needed = 0; dynarray_add(>playlists, >n_playlists, pls); return pls; } @@ -1670,6 +1672,121 @@ static int hls_close(AVFormatContext *s) return 0; } +static int init_playlist(HLSContext *c, struct playlist *pls) +{ +AVInputFormat *in_fmt = NULL; +int highest_cur_seq_no = 0; +int ret; +int i; + +if (!(pls->ctx = avformat_alloc_context())) { +return AVERROR(ENOMEM); +} + +if (pls->n_segments == 0) +return 0; + +pls->needed = 1; +pls->parent = c->ctx; + +/* + * 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. + */ +highest_cur_seq_no = 0; +for (i = 0; i < c->n_playlists; i++) { +struct playlist *pls = c->playlists[i]; +if (pls->cur_seq_no > highest_cur_seq_no) +highest_cur_seq_no = pls->cur_seq_no; +} +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; +return ret; +} +ffio_init_context(>pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls, + read_data, NULL, NULL); +pls->pb.seekable = 0; +ret = av_probe_input_buffer(>pb, _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(c->ctx, AV_LOG_ERROR, "Error when loading first segment '%s'\n", pls->segments[0]->url); +avio_closep(>pb); +avformat_free_context(pls->ctx); +pls->ctx = NULL; +return ret; +} +pls->ctx->pb = >pb; +pls->ctx->io_open = nested_io_open; +pls->ctx->flags |= c->ctx->flags & ~AVFMT_FLAG_CUSTOM_IO; + +if ((ret = ff_copy_whiteblacklists(pls->ctx, c->ctx)) < 0) +return ret; + +ret = avformat_open_input(>ctx, pls->segments[0]->url, in_fmt, NULL); +if (ret < 0) { +av_log(c->ctx, AV_LOG_ERROR, "Error opening playlist %s", pls->segments[0]->url); +avformat_free_context(pls->ctx); +pls->ctx = NULL; +return ret; +} + +if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) { +ff_id3v2_parse_apic(pls->ctx, >id3_deferred_extra); +avformat_queue_attached_pictures(pls->ctx); +ff_id3v2_free_extra_meta(>id3_deferred_extra); +pls->id3_deferred_extra = NULL; +} + +if (pls->is_id3_timestamped == -1) +av_log(c->ctx, 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) { +avformat_free_context(pls->ctx); +pls->ctx = NULL; +return ret; +} +} + +pls->has_noheader_flag = !!(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER); + +/* Create new AVStreams for each stream in this playlist */ +ret = update_streams_from_subdemuxer(c->ctx, pls); +if (ret < 0) { +avformat_free_context(pls->ctx); +pls->ctx = NULL; +return ret; +} + +add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_AUDIO); +add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_VIDEO); +add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_SUBTITLE); + +return 0; +} + static int hls_read_header(AVFormatContext *s) { void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb; @@ -1775,97
[FFmpeg-devel] [PATCH v4 2/2] lavf/hls: add option to defer parsing of variants
--- doc/demuxers.texi | 6 libavformat/hls.c | 106 ++ 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 73dc0feec1..33643f966a 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -316,6 +316,12 @@ segment index to start live streams at (negative values are from the end). @item max_reload Maximum number of times a insufficient list is attempted to be reloaded. Default value is 1000. + +@item load_all_variants +If 0, only the first variant/playlist is loaded on open. All other variants +get disabled and can be enabled by setting discard option in program. +Default value is 1. + @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index 3c2c720abe..500e3c15de 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -112,6 +112,7 @@ struct playlist { int n_segments; struct segment **segments; int needed; +int parsed; int cur_seq_no; int64_t cur_seg_offset; int64_t last_load_time; @@ -206,6 +207,7 @@ typedef struct HLSContext { int strict_std_compliance; char *allowed_extensions; int max_reload; +int load_all_variants; } HLSContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -315,6 +317,7 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; pls->index = c->n_playlists; +pls->parsed = 0; pls->needed = 0; dynarray_add(>playlists, >n_playlists, pls); return pls; @@ -867,6 +870,10 @@ fail: av_free(new_url); if (close_in) ff_format_io_close(c->ctx, ); + +if (pls) +pls->parsed = 1; + return ret; } @@ -1260,17 +1267,30 @@ static int64_t default_reload_interval(struct playlist *pls) pls->target_duration; } -static int playlist_needed(struct playlist *pls) +static int playlist_needed(AVFormatContext *s, struct playlist *pls, int check_parsed) { -AVFormatContext *s = pls->parent; +HLSContext *c = s->priv_data; int i, j; int stream_needed = 0; int first_st; /* If there is no context or streams yet, the playlist is needed */ -if (!pls->ctx || !pls->n_main_streams) +if (check_parsed && (!pls->ctx || !pls->n_main_streams)) return 1; +/* If the playlist belongs to a non discarded variant and is not parsed, + * we need to parse and activate it later */ +for (i = 0; i < s->nb_programs; i++) { +AVProgram *program = s->programs[i]; +struct variant *var = c->variants[i]; +if (program->discard < AVDISCARD_ALL) { +for (j = 0; j < var->n_playlists; j++) { +if (var->playlists[j] == pls && !var->playlists[j]->parsed) +return 1; +} +} +} + /* check if any of the streams in the playlist are needed */ for (i = 0; i < pls->n_main_streams; i++) { if (pls->main_streams[i]->discard < AVDISCARD_ALL) { @@ -1324,7 +1344,7 @@ restart: /* Check that the playlist is still needed before opening a new * segment. */ -v->needed = playlist_needed(v); +v->needed = playlist_needed(v->parent, v, 1); if (!v->needed) { av_log(v->parent, AV_LOG_INFO, "No longer receiving playlist %d\n", @@ -1418,23 +1438,41 @@ reload: static void add_renditions_to_variant(HLSContext *c, struct variant *var, enum AVMediaType type, const char *group_id) { -int i; +int i, j; +int found; for (i = 0; i < c->n_renditions; i++) { struct rendition *rend = c->renditions[i]; if (rend->type == type && !strcmp(rend->group_id, group_id)) { -if (rend->playlist) +if (rend->playlist) { /* rendition is an external playlist * => add the playlist to the variant */ -dynarray_add(>playlists, >n_playlists, rend->playlist); -else +found = 0; +for (j = 0; j < var->n_playlists; j++) { +if (var->playlists[j] == rend->playlist) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists, >n_playlists, rend->playlist); +} else { /* rendition is part of the variant main Media Playlist * => add the rendition to the main Media Playlist */ -dynarray_add(>playlists[0]->renditions, - >playlists[0]->n_renditions, - rend); +found = 0; +for (j = 0; j < var->playlists[0]->n_renditions; j++) { +if (var->playlists[0]->renditions[j] == rend) { +
[FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
v4: fixed the memleak properly ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH v3 2/2] lavf/hls: add option to defer parsing of variants
--- doc/demuxers.texi | 6 libavformat/hls.c | 106 ++ 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 73dc0feec1..33643f966a 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -316,6 +316,12 @@ segment index to start live streams at (negative values are from the end). @item max_reload Maximum number of times a insufficient list is attempted to be reloaded. Default value is 1000. + +@item load_all_variants +If 0, only the first variant/playlist is loaded on open. All other variants +get disabled and can be enabled by setting discard option in program. +Default value is 1. + @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index 3f83707c1f..731e8a569c 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -112,6 +112,7 @@ struct playlist { int n_segments; struct segment **segments; int needed; +int parsed; int cur_seq_no; int64_t cur_seg_offset; int64_t last_load_time; @@ -206,6 +207,7 @@ typedef struct HLSContext { int strict_std_compliance; char *allowed_extensions; int max_reload; +int load_all_variants; } HLSContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -315,6 +317,7 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; pls->index = c->n_playlists; +pls->parsed = 0; pls->needed = 0; dynarray_add(>playlists, >n_playlists, pls); return pls; @@ -867,6 +870,10 @@ fail: av_free(new_url); if (close_in) ff_format_io_close(c->ctx, ); + +if (pls) +pls->parsed = 1; + return ret; } @@ -1260,17 +1267,30 @@ static int64_t default_reload_interval(struct playlist *pls) pls->target_duration; } -static int playlist_needed(struct playlist *pls) +static int playlist_needed(AVFormatContext *s, struct playlist *pls, int check_parsed) { -AVFormatContext *s = pls->parent; +HLSContext *c = s->priv_data; int i, j; int stream_needed = 0; int first_st; /* If there is no context or streams yet, the playlist is needed */ -if (!pls->ctx || !pls->n_main_streams) +if (check_parsed && (!pls->ctx || !pls->n_main_streams)) return 1; +/* If the playlist belongs to a non discarded variant and is not parsed, + * we need to parse and activate it later */ +for (i = 0; i < s->nb_programs; i++) { +AVProgram *program = s->programs[i]; +struct variant *var = c->variants[i]; +if (program->discard < AVDISCARD_ALL) { +for (j = 0; j < var->n_playlists; j++) { +if (var->playlists[j] == pls && !var->playlists[j]->parsed) +return 1; +} +} +} + /* check if any of the streams in the playlist are needed */ for (i = 0; i < pls->n_main_streams; i++) { if (pls->main_streams[i]->discard < AVDISCARD_ALL) { @@ -1324,7 +1344,7 @@ restart: /* Check that the playlist is still needed before opening a new * segment. */ -v->needed = playlist_needed(v); +v->needed = playlist_needed(v->parent, v, 1); if (!v->needed) { av_log(v->parent, AV_LOG_INFO, "No longer receiving playlist %d\n", @@ -1418,23 +1438,41 @@ reload: static void add_renditions_to_variant(HLSContext *c, struct variant *var, enum AVMediaType type, const char *group_id) { -int i; +int i, j; +int found; for (i = 0; i < c->n_renditions; i++) { struct rendition *rend = c->renditions[i]; if (rend->type == type && !strcmp(rend->group_id, group_id)) { -if (rend->playlist) +if (rend->playlist) { /* rendition is an external playlist * => add the playlist to the variant */ -dynarray_add(>playlists, >n_playlists, rend->playlist); -else +found = 0; +for (j = 0; j < var->n_playlists; j++) { +if (var->playlists[j] == rend->playlist) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists, >n_playlists, rend->playlist); +} else { /* rendition is part of the variant main Media Playlist * => add the rendition to the main Media Playlist */ -dynarray_add(>playlists[0]->renditions, - >playlists[0]->n_renditions, - rend); +found = 0; +for (j = 0; j < var->playlists[0]->n_renditions; j++) { +if (var->playlists[0]->renditions[j] == rend) { +
[FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
fixed mem leak poined out by Steven --- doc/demuxers.texi | 5 + libavformat/hls.c | 304 -- 2 files changed, 209 insertions(+), 100 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 73dc0feec1..634b122e10 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -316,6 +316,11 @@ segment index to start live streams at (negative values are from the end). @item max_reload Maximum number of times a insufficient list is attempted to be reloaded. Default value is 1000. + +@item load_all_variants +If 0, only the first variant/playlist is loaded on open. All other variants +get disabled and can be enabled by setting discard option in program. +Default value is 1. @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index 786934af03..c42e0b0f95 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -112,6 +112,7 @@ struct playlist { int n_segments; struct segment **segments; int needed, cur_needed; +int parsed; int cur_seq_no; int64_t cur_seg_offset; int64_t last_load_time; @@ -206,6 +207,7 @@ typedef struct HLSContext { int strict_std_compliance; char *allowed_extensions; int max_reload; +int load_all_variants; } HLSContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -314,6 +316,9 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->is_id3_timestamped = -1; pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; +pls->index = c->n_playlists; +pls->parsed = 0; +pls->needed = 0; dynarray_add(>playlists, >n_playlists, pls); return pls; } @@ -721,6 +726,7 @@ static int parse_playlist(HLSContext *c, const char *url, free_segment_list(pls); pls->finished = 0; pls->type = PLS_TYPE_UNSPECIFIED; +pls->parsed = 1; } while (!avio_feof(in)) { read_chomp_line(in, line, sizeof(line)); @@ -1377,23 +1383,41 @@ reload: static void add_renditions_to_variant(HLSContext *c, struct variant *var, enum AVMediaType type, const char *group_id) { -int i; +int i, j; +int found; for (i = 0; i < c->n_renditions; i++) { struct rendition *rend = c->renditions[i]; if (rend->type == type && !strcmp(rend->group_id, group_id)) { -if (rend->playlist) +if (rend->playlist) { /* rendition is an external playlist * => add the playlist to the variant */ -dynarray_add(>playlists, >n_playlists, rend->playlist); -else +found = 0; +for (j = 0; j < var->n_playlists; j++) { +if (var->playlists[j] == rend->playlist) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists, >n_playlists, rend->playlist); +} else { /* rendition is part of the variant main Media Playlist * => add the rendition to the main Media Playlist */ -dynarray_add(>playlists[0]->renditions, - >playlists[0]->n_renditions, - rend); +found = 0; +for (j = 0; j < var->playlists[0]->n_renditions; j++) { +if (var->playlists[0]->renditions[j] == rend) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists[0]->renditions, + >playlists[0]->n_renditions, + rend); +} } } } @@ -1631,6 +1655,124 @@ static int hls_close(AVFormatContext *s) return 0; } +static int init_playlist(HLSContext *c, struct playlist *pls) +{ +AVInputFormat *in_fmt = NULL; +int highest_cur_seq_no = 0; +int ret; +int i; + +if (!(pls->ctx = avformat_alloc_context())) { +return AVERROR(ENOMEM); +} + +if (pls->n_segments == 0) +return 0; + +pls->needed = 1; +pls->parent = c->ctx; + +/* + * 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. + */ +highest_cur_seq_no = 0; +for (i = 0; i < c->n_playlists; i++) { +struct playlist *pls = c->playlists[i]; +if (!pls->parsed) +continue; +if (pls->cur_seq_no > highest_cur_seq_no) +highest_cur_seq_no =
[FFmpeg-devel] [PATCH v3 1/2] lavf/hls: refactoring of read_header
--- libavformat/hls.c | 209 +++--- 1 file changed, 120 insertions(+), 89 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index ab6ff187a6..3f83707c1f 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -314,6 +314,8 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->is_id3_timestamped = -1; pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; +pls->index = c->n_playlists; +pls->needed = 0; dynarray_add(>playlists, >n_playlists, pls); return pls; } @@ -1670,6 +1672,122 @@ static int hls_close(AVFormatContext *s) return 0; } +static int init_playlist(HLSContext *c, struct playlist *pls) +{ +AVInputFormat *in_fmt = NULL; +int highest_cur_seq_no = 0; +int ret; +int i; + +if (!(pls->ctx = avformat_alloc_context())) { +return AVERROR(ENOMEM); +} + +if (pls->n_segments == 0) +return 0; + +pls->needed = 1; +pls->parent = c->ctx; + +/* + * 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. + */ +highest_cur_seq_no = 0; +for (i = 0; i < c->n_playlists; i++) { +struct playlist *pls = c->playlists[i]; +if (pls->cur_seq_no > highest_cur_seq_no) +highest_cur_seq_no = pls->cur_seq_no; +} +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; +return ret; +} +ffio_init_context(>pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, pls, + read_data, NULL, NULL); +pls->pb.seekable = 0; +ret = av_probe_input_buffer(>pb, _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(c->ctx, AV_LOG_ERROR, "Error when loading first segment '%s'\n", pls->segments[0]->url); +av_free(pls->read_buffer); +pls->read_buffer = NULL; +avformat_free_context(pls->ctx); +pls->ctx = NULL; +return ret; +} +pls->ctx->pb = >pb; +pls->ctx->io_open = nested_io_open; +pls->ctx->flags |= c->ctx->flags & ~AVFMT_FLAG_CUSTOM_IO; + +if ((ret = ff_copy_whiteblacklists(pls->ctx, c->ctx)) < 0) +return ret; + +ret = avformat_open_input(>ctx, pls->segments[0]->url, in_fmt, NULL); +if (ret < 0) { +av_log(c->ctx, AV_LOG_ERROR, "Error opening playlist %s", pls->segments[0]->url); +avformat_free_context(pls->ctx); +pls->ctx = NULL; +return ret; +} + +if (pls->id3_deferred_extra && pls->ctx->nb_streams == 1) { +ff_id3v2_parse_apic(pls->ctx, >id3_deferred_extra); +avformat_queue_attached_pictures(pls->ctx); +ff_id3v2_free_extra_meta(>id3_deferred_extra); +pls->id3_deferred_extra = NULL; +} + +if (pls->is_id3_timestamped == -1) +av_log(c->ctx, 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) { +avformat_free_context(pls->ctx); +pls->ctx = NULL; +return ret; +} +} + +pls->has_noheader_flag = !!(pls->ctx->ctx_flags & AVFMTCTX_NOHEADER); + +/* Create new AVStreams for each stream in this playlist */ +ret = update_streams_from_subdemuxer(c->ctx, pls); +if (ret < 0) { +avformat_free_context(pls->ctx); +pls->ctx = NULL; +return ret; +} + +add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_AUDIO); +add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_VIDEO); +add_metadata_from_renditions(c->ctx, pls, AVMEDIA_TYPE_SUBTITLE); + +return 0; +} + static int hls_read_header(AVFormatContext *s) { void *u = (s->flags &
[FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
I tried to implement what you requested ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
2017-11-27 22:53 GMT+01:00 Anssi Hannula <anssi.hann...@iki.fi>: > Hi, > > Rainer Hochecker kirjoitti 2017-11-26 12:46: >> >> fixed mem leak poined out by Steven >> >> --- >> doc/demuxers.texi | 5 + >> libavformat/hls.c | 304 >> -- >> 2 files changed, 209 insertions(+), 100 deletions(-) >> > [...] >> >> + >> +@item load_all_variants >> +If 0, only the first variant/playlist is loaded on open. All other >> variants >> +get disabled and can be enabled by setting discard option in program. >> +Default value is 1. >> @end table > > > If playlist download+parsing is indeed taking long enough time that this is > warranted, I wonder if we should maybe just never read any variant playlists > in read_header(), and instead set AVFMTCTX_NOHEADER. > Then the user may discard AVPrograms right after open, before unneeded > playlists are loaded+parsed. > > This would avoid having a separate option/mode for this. > > Any thoughts? I actually tried it like this but somwhow did not like it because this is different to all other demuxers/formats. In general you open an input, call find_stream_info, and select a program. I did not like selecting the program between open and find_stream_info. > > >> @section image2 >> diff --git a/libavformat/hls.c b/libavformat/hls.c >> index 786934af03..c42e0b0f95 100644 >> --- a/libavformat/hls.c >> +++ b/libavformat/hls.c >> @@ -112,6 +112,7 @@ struct playlist { >> int n_segments; >> struct segment **segments; >> int needed, cur_needed; >> +int parsed; >> int cur_seq_no; >> int64_t cur_seg_offset; >> int64_t last_load_time; >> @@ -206,6 +207,7 @@ typedef struct HLSContext { >> int strict_std_compliance; >> char *allowed_extensions; >> int max_reload; >> +int load_all_variants; >> } HLSContext; > > [...] >> >> @@ -721,6 +726,7 @@ static int parse_playlist(HLSContext *c, const char >> *url, >> free_segment_list(pls); >> pls->finished = 0; >> pls->type = PLS_TYPE_UNSPECIFIED; >> +pls->parsed = 1; >> } > > > That "pls->parsed = 1" is in the "reinit old playlist for re-parse" block, > is that intentional? > > I'd think it should rather be at the end of the function alongside setting > pls->last_load_time, so it is set to 1 whenever parsing has been done. > I put it at the beginning because I wanted to avoid that it gets tried again on error. >> while (!avio_feof(in)) { >> read_chomp_line(in, line, sizeof(line)); > > [...] >> >> @@ -1631,6 +1655,124 @@ static int hls_close(AVFormatContext *s) >> return 0; >> } >> >> +static int init_playlist(HLSContext *c, struct playlist *pls) >> +{ > > > This init_playlist() seems to be mostly code moved from below, could you > split the patch so that the first patch moves the code around but does not > change behavior, and the second patch makes the actual changes (i.e. adds > the option)? > > That would ease e.g. future bisecting. Sure. At least I can try. > > [...] >> >> +return 0; >> +} >> + >> static int hls_read_header(AVFormatContext *s) >> { >> void *u = (s->flags & AVFMT_FLAG_CUSTOM_IO) ? NULL : s->pb; >> @@ -1663,6 +1805,9 @@ static int hls_read_header(AVFormatContext *s) >> if ((ret = parse_playlist(c, s->filename, NULL, s->pb)) < 0) >> goto fail; >> >> +/* first playlist was created, set it to parsed */ >> +c->variants[0]->playlists[0]->parsed = 1; >> + > > > I think parse_playlist() should set this when it parses something. That was pitfall for my v1. The first playlist gets parsed with no playlist given as argument. fate failed because non-master playlists were not set to parsed. > >> if ((ret = save_avio_options(s)) < 0) >> goto fail; >> >> @@ -1675,8 +1820,15 @@ static int hls_read_header(AVFormatContext *s) >> goto fail; > > [...] >> >> >> /* Select the starting segments */ >> for (i = 0; i < c->n_playlists; i++) { >> struct playlist *pls = c->playlists[i]; >> >> -if (pls->n_segments == 0) >> +if (pls->n_segments == 0 && !pls->parsed) >> continue; > > > Why? playlists not parsed are invalid, right? maybe n_segments is 0 for not parsed playlists but this was no obvious to me. > >> pls->cur_seq_no = select_cur_seq_no(c, pls); >> @@ -1736,97 +1892,9 @@ static int hls_read_header(AVFormatContext *s) >> /* Open the demuxer for each playlist */ >> for (i = 0; i < c->n_playlists; i++) { >> struct playlist *pls = c->playlists[i]; >> -AVInputFormat *in_fmt = NULL; >> - > > [...] > > -- > Anssi Hannula > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
Variants are presented as programs and can be loaded later by setting discard flags on the program. Currently Kodi chooses the program that best matches the desired bit rate. Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
2017-11-26 12:04 GMT+01:00 Steven Liu <lingjiujia...@gmail.com>: > 2017-11-26 18:46 GMT+08:00 Rainer Hochecker <fernetme...@online.de>: >> fixed mem leak poined out by Steven > Hi Rainer, > > I'm not sure that is memleak, but looks like memleak when reading > the code, i see the code always in hls.c before this patch, but no > people report it memleak. > If that is memleak, maybe use goto method is better way, because > the workflow of bellow have alloc resource faild check, i will point > out base on your patch. >> Hi Steven, As soon as you associate the probe buffer with the context, the context cares about allocated resources. That's most likely the reason why pb was not cleared here. It is assigned to the context right after this block. Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
>> +/* >> + * 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. >> + */ >> +highest_cur_seq_no = 0; >> +for (i = 0; i < c->n_playlists; i++) { >> +struct playlist *pls = c->playlists[i]; >> +if (!pls->parsed) >> +continue; >> +if (pls->cur_seq_no > highest_cur_seq_no) >> +highest_cur_seq_no = pls->cur_seq_no; >> +} >> +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; >> +return ret; >> +} >> +ffio_init_context(>pb, pls->read_buffer, INITIAL_BUFFER_SIZE, 0, >> pls, >> + read_data, NULL, NULL); >> +pls->pb.seekable = 0; >> +ret = av_probe_input_buffer(>pb, _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(c->ctx, AV_LOG_ERROR, "Error when loading first segment >> '%s'\n", pls->segments[0]->url); >> +avformat_free_context(pls->ctx); >> +pls->ctx = NULL; >> +return ret; > Is that pls->read_buffer will memleak? > > yes, looks like this. this is already an issue in current code. nevertheless, I will fix it here. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
fixed mem leak poined out by Steven --- doc/demuxers.texi | 5 + libavformat/hls.c | 304 -- 2 files changed, 209 insertions(+), 100 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 73dc0feec1..634b122e10 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -316,6 +316,11 @@ segment index to start live streams at (negative values are from the end). @item max_reload Maximum number of times a insufficient list is attempted to be reloaded. Default value is 1000. + +@item load_all_variants +If 0, only the first variant/playlist is loaded on open. All other variants +get disabled and can be enabled by setting discard option in program. +Default value is 1. @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index 786934af03..c42e0b0f95 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -112,6 +112,7 @@ struct playlist { int n_segments; struct segment **segments; int needed, cur_needed; +int parsed; int cur_seq_no; int64_t cur_seg_offset; int64_t last_load_time; @@ -206,6 +207,7 @@ typedef struct HLSContext { int strict_std_compliance; char *allowed_extensions; int max_reload; +int load_all_variants; } HLSContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -314,6 +316,9 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->is_id3_timestamped = -1; pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; +pls->index = c->n_playlists; +pls->parsed = 0; +pls->needed = 0; dynarray_add(>playlists, >n_playlists, pls); return pls; } @@ -721,6 +726,7 @@ static int parse_playlist(HLSContext *c, const char *url, free_segment_list(pls); pls->finished = 0; pls->type = PLS_TYPE_UNSPECIFIED; +pls->parsed = 1; } while (!avio_feof(in)) { read_chomp_line(in, line, sizeof(line)); @@ -1377,23 +1383,41 @@ reload: static void add_renditions_to_variant(HLSContext *c, struct variant *var, enum AVMediaType type, const char *group_id) { -int i; +int i, j; +int found; for (i = 0; i < c->n_renditions; i++) { struct rendition *rend = c->renditions[i]; if (rend->type == type && !strcmp(rend->group_id, group_id)) { -if (rend->playlist) +if (rend->playlist) { /* rendition is an external playlist * => add the playlist to the variant */ -dynarray_add(>playlists, >n_playlists, rend->playlist); -else +found = 0; +for (j = 0; j < var->n_playlists; j++) { +if (var->playlists[j] == rend->playlist) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists, >n_playlists, rend->playlist); +} else { /* rendition is part of the variant main Media Playlist * => add the rendition to the main Media Playlist */ -dynarray_add(>playlists[0]->renditions, - >playlists[0]->n_renditions, - rend); +found = 0; +for (j = 0; j < var->playlists[0]->n_renditions; j++) { +if (var->playlists[0]->renditions[j] == rend) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists[0]->renditions, + >playlists[0]->n_renditions, + rend); +} } } } @@ -1631,6 +1655,124 @@ static int hls_close(AVFormatContext *s) return 0; } +static int init_playlist(HLSContext *c, struct playlist *pls) +{ +AVInputFormat *in_fmt = NULL; +int highest_cur_seq_no = 0; +int ret; +int i; + +if (!(pls->ctx = avformat_alloc_context())) { +return AVERROR(ENOMEM); +} + +if (pls->n_segments == 0) +return 0; + +pls->needed = 1; +pls->parent = c->ctx; + +/* + * 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. + */ +highest_cur_seq_no = 0; +for (i = 0; i < c->n_playlists; i++) { +struct playlist *pls = c->playlists[i]; +if (!pls->parsed) +continue; +if (pls->cur_seq_no > highest_cur_seq_no) +highest_cur_seq_no =
[FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
fate runs now without error, sorry for that --- doc/demuxers.texi | 5 + libavformat/hls.c | 302 -- 2 files changed, 207 insertions(+), 100 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 73dc0feec1..634b122e10 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -316,6 +316,11 @@ segment index to start live streams at (negative values are from the end). @item max_reload Maximum number of times a insufficient list is attempted to be reloaded. Default value is 1000. + +@item load_all_variants +If 0, only the first variant/playlist is loaded on open. All other variants +get disabled and can be enabled by setting discard option in program. +Default value is 1. @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index 786934af03..c1c93f8067 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -112,6 +112,7 @@ struct playlist { int n_segments; struct segment **segments; int needed, cur_needed; +int parsed; int cur_seq_no; int64_t cur_seg_offset; int64_t last_load_time; @@ -206,6 +207,7 @@ typedef struct HLSContext { int strict_std_compliance; char *allowed_extensions; int max_reload; +int load_all_variants; } HLSContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -314,6 +316,9 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->is_id3_timestamped = -1; pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; +pls->index = c->n_playlists; +pls->parsed = 0; +pls->needed = 0; dynarray_add(>playlists, >n_playlists, pls); return pls; } @@ -721,6 +726,7 @@ static int parse_playlist(HLSContext *c, const char *url, free_segment_list(pls); pls->finished = 0; pls->type = PLS_TYPE_UNSPECIFIED; +pls->parsed = 1; } while (!avio_feof(in)) { read_chomp_line(in, line, sizeof(line)); @@ -1377,23 +1383,41 @@ reload: static void add_renditions_to_variant(HLSContext *c, struct variant *var, enum AVMediaType type, const char *group_id) { -int i; +int i, j; +int found; for (i = 0; i < c->n_renditions; i++) { struct rendition *rend = c->renditions[i]; if (rend->type == type && !strcmp(rend->group_id, group_id)) { -if (rend->playlist) +if (rend->playlist) { /* rendition is an external playlist * => add the playlist to the variant */ -dynarray_add(>playlists, >n_playlists, rend->playlist); -else +found = 0; +for (j = 0; j < var->n_playlists; j++) { +if (var->playlists[j] == rend->playlist) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists, >n_playlists, rend->playlist); +} else { /* rendition is part of the variant main Media Playlist * => add the rendition to the main Media Playlist */ -dynarray_add(>playlists[0]->renditions, - >playlists[0]->n_renditions, - rend); +found = 0; +for (j = 0; j < var->playlists[0]->n_renditions; j++) { +if (var->playlists[0]->renditions[j] == rend) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists[0]->renditions, + >playlists[0]->n_renditions, + rend); +} } } } @@ -1631,6 +1655,122 @@ static int hls_close(AVFormatContext *s) return 0; } +static int init_playlist(HLSContext *c, struct playlist *pls) +{ +AVInputFormat *in_fmt = NULL; +int highest_cur_seq_no = 0; +int ret; +int i; + +if (!(pls->ctx = avformat_alloc_context())) { +return AVERROR(ENOMEM); +} + +if (pls->n_segments == 0) +return 0; + +pls->needed = 1; +pls->parent = c->ctx; + +/* + * 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. + */ +highest_cur_seq_no = 0; +for (i = 0; i < c->n_playlists; i++) { +struct playlist *pls = c->playlists[i]; +if (!pls->parsed) +continue; +if (pls->cur_seq_no > highest_cur_seq_no) +highest_cur_seq_no =
Re: [FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
Shouldn't this be: 0 (or -1) for all streams (default), n>0 (or > -1) for the nth stream. I guess it is at least possible that the user knows in advance which streams the source will offer. No? Carl Eugen It is very unlikely that this is known in advance. Also there is no reason why you want to load more than a single variant at a time. Note this are variants, not streams. Different variants bundle the same streams with different resolutions. Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] (no subject)
Currently all variants/playlists get parsed on open. For a master playlist with many different bitrates this can take several seconds. With the new option set to 0 only the first variant of a master playlist is opened. Others can be activated later by setting discard option on a program. Default value of option preserves current behaviour. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] hls demuxer: add option to defer parsing of variants
--- doc/demuxers.texi | 5 + libavformat/hls.c | 299 -- 2 files changed, 204 insertions(+), 100 deletions(-) diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 73dc0feec1..634b122e10 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -316,6 +316,11 @@ segment index to start live streams at (negative values are from the end). @item max_reload Maximum number of times a insufficient list is attempted to be reloaded. Default value is 1000. + +@item load_all_variants +If 0, only the first variant/playlist is loaded on open. All other variants +get disabled and can be enabled by setting discard option in program. +Default value is 1. @end table @section image2 diff --git a/libavformat/hls.c b/libavformat/hls.c index 786934af03..c55f5ea439 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -112,6 +112,7 @@ struct playlist { int n_segments; struct segment **segments; int needed, cur_needed; +int parsed; int cur_seq_no; int64_t cur_seg_offset; int64_t last_load_time; @@ -206,6 +207,7 @@ typedef struct HLSContext { int strict_std_compliance; char *allowed_extensions; int max_reload; +int load_all_variants; } HLSContext; static int read_chomp_line(AVIOContext *s, char *buf, int maxlen) @@ -314,6 +316,9 @@ static struct playlist *new_playlist(HLSContext *c, const char *url, pls->is_id3_timestamped = -1; pls->id3_mpegts_timestamp = AV_NOPTS_VALUE; +pls->index = c->n_playlists; +pls->parsed = 0; +pls->needed = 0; dynarray_add(>playlists, >n_playlists, pls); return pls; } @@ -721,6 +726,7 @@ static int parse_playlist(HLSContext *c, const char *url, free_segment_list(pls); pls->finished = 0; pls->type = PLS_TYPE_UNSPECIFIED; +pls->parsed = 1; } while (!avio_feof(in)) { read_chomp_line(in, line, sizeof(line)); @@ -1377,23 +1383,41 @@ reload: static void add_renditions_to_variant(HLSContext *c, struct variant *var, enum AVMediaType type, const char *group_id) { -int i; +int i, j; +int found; for (i = 0; i < c->n_renditions; i++) { struct rendition *rend = c->renditions[i]; if (rend->type == type && !strcmp(rend->group_id, group_id)) { -if (rend->playlist) +if (rend->playlist) { /* rendition is an external playlist * => add the playlist to the variant */ -dynarray_add(>playlists, >n_playlists, rend->playlist); -else +found = 0; +for (j = 0; j < var->n_playlists; j++) { +if (var->playlists[j] == rend->playlist) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists, >n_playlists, rend->playlist); +} else { /* rendition is part of the variant main Media Playlist * => add the rendition to the main Media Playlist */ -dynarray_add(>playlists[0]->renditions, - >playlists[0]->n_renditions, - rend); +found = 0; +for (j = 0; j < var->playlists[0]->n_renditions; j++) { +if (var->playlists[0]->renditions[j] == rend) { +found = 1; +break; +} +} +if (!found) +dynarray_add(>playlists[0]->renditions, + >playlists[0]->n_renditions, + rend); +} } } } @@ -1631,6 +1655,122 @@ static int hls_close(AVFormatContext *s) return 0; } +static int init_playlist(HLSContext *c, struct playlist *pls) +{ +AVInputFormat *in_fmt = NULL; +int highest_cur_seq_no = 0; +int ret; +int i; + +if (!(pls->ctx = avformat_alloc_context())) { +return AVERROR(ENOMEM); +} + +if (pls->n_segments == 0) +return 0; + +pls->needed = 1; +pls->parent = c->ctx; + +/* + * 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. + */ +highest_cur_seq_no = 0; +for (i = 0; i < c->n_playlists; i++) { +struct playlist *pls = c->playlists[i]; +if (!pls->parsed) +continue; +if (pls->cur_seq_no > highest_cur_seq_no) +highest_cur_seq_no = pls->cur_seq_no; +} +if (!pls->finished &&
Re: [FFmpeg-devel] [PATCH] matroskadec: partly revert "demux relevant subtitle packets after a seek" c16582579b1c6f66a86615c5808cd5b2bf17be73
absolutely. thanks! ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] matroskadec: partly revert "demux relevant subtitle packets after a seek" c16582579b1c6f66a86615c5808cd5b2bf17be73
We already included this patch in Kodi v17. Dropping this incomplete feature is much better than living with the downsides. Having files on a network share is a common use case and in most cases there is no index anyway: start video and seek forward. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] matroskadec: partly revert "demux relevant subtitle packets after a seek" c16582579b1c6f66a86615c5808cd5b2bf17be73
From: Rainer Hochecker <fernetme...@online.de> Alternative patch. Revert the original code because it does more harm than any good. Signed-off-by: Rainer Hochecker <fernetme...@online.de> --- libavformat/matroskadec.c | 12 1 file changed, 12 deletions(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index f79511e..cf3de96 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3398,18 +3398,6 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, tracks[i].audio.sub_packet_cnt = 0; tracks[i].audio.buf_timecode = AV_NOPTS_VALUE; tracks[i].end_timecode = 0; -if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE && -tracks[i].stream && -tracks[i].stream->discard != AVDISCARD_ALL) { -index_sub = av_index_search_timestamp( -tracks[i].stream, st->index_entries[index].timestamp, -AVSEEK_FLAG_BACKWARD); -while (index_sub >= 0 && - index_min > 0 && - tracks[i].stream->index_entries[index_sub].pos < st->index_entries[index_min].pos && - st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < 300 / matroska->time_scale) -index_min--; -} } avio_seek(s->pb, st->index_entries[index_min].pos, SEEK_SET); -- 2.9.3 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] matroska read_seek: make max diff for last known subtitle configurable
I was tempted to submit a patch with this feature deleted. Unfortunately I was not able to find the original reason why this was implemented. I am sure there was a good reason and this reason may still be a good one. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] matroska read_seek: make max diff for last known subtitle configurable
From: Rainer Hochecker <fernetme...@online.de> Allow players to reduce the time read_seek sets the file pos before desired position. Hard coded 30 seconds is a lot and takes several seconds when the source is on a network share. Signed-off-by: Rainer Hochecker <fernetme...@online.de> --- libavformat/matroskadec.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index f79511e..eb2bc31 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -353,6 +353,9 @@ typedef struct MatroskaDemuxContext { /* WebM DASH Manifest live flag/ */ int is_live; + +/* set file pos up to 30 seconds before desired timestamp on seek */ +int subtitle_seek_diff; } MatroskaDemuxContext; typedef struct MatroskaBlock { @@ -3407,7 +3410,7 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, while (index_sub >= 0 && index_min > 0 && tracks[i].stream->index_entries[index_sub].pos < st->index_entries[index_min].pos && - st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < 300 / matroska->time_scale) + st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < matroska->subtitle_seek_diff * 1E9 / matroska->time_scale) index_min--; } } @@ -3813,9 +3816,17 @@ static int webm_dash_manifest_read_packet(AVFormatContext *s, AVPacket *pkt) #define OFFSET(x) offsetof(MatroskaDemuxContext, x) static const AVOption options[] = { { "live", "flag indicating that the input is a live file that only has the headers.", OFFSET(is_live), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, +{ "subtitle_seek_diff", "max difference in seconds between desired seek pos and last known subtitle pos.", OFFSET(subtitle_seek_diff), AV_OPT_TYPE_INT, {.i64 = 30}, 0, 30, AV_OPT_FLAG_DECODING_PARAM }, { NULL }, }; +static const AVClass matroska_class = { +.class_name = "matroska,webm demuxer", +.item_name = av_default_item_name, +.option = options, +.version= LIBAVUTIL_VERSION_INT, +}; + static const AVClass webm_dash_class = { .class_name = "WebM DASH Manifest demuxer", .item_name = av_default_item_name, @@ -3828,6 +3839,7 @@ AVInputFormat ff_matroska_demuxer = { .long_name = NULL_IF_CONFIG_SMALL("Matroska / WebM"), .extensions = "mkv,mk3d,mka,mks", .priv_data_size = sizeof(MatroskaDemuxContext), +.priv_class = _class, .read_probe = matroska_probe, .read_header= matroska_read_header, .read_packet= matroska_read_packet, -- 2.9.3 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] estimate_timings_from_pts - increase retry counter, fixes invalid duration for ts files with hevc codec
I got a mpegts file with hevc that fails estimating duration. Increasing number of retries fixes the issue. Rainer --- libavformat/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 251b2c6..f8ddaf7 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2463,7 +2463,7 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic) } #define DURATION_MAX_READ_SIZE 25LL -#define DURATION_MAX_RETRY 4 +#define DURATION_MAX_RETRY 6 /* only usable for MPEG-PS streams */ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) -- 2.5.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] hevc - fix split function of parser
--- libavcodec/hevc_parser.c | 25 ++--- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index f970de5..35cace5 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -410,19 +410,30 @@ static int hevc_split(AVCodecContext *avctx, const uint8_t *buf, int buf_size) { const uint8_t *ptr = buf, *end = buf + buf_size; uint32_t state = -1; -int has_ps = 0, nut; +int has_vps = 0; +int has_sps = 0; +int has_pps = 0; +int nut; while (ptr < end) { ptr = avpriv_find_start_code(ptr, end, ); if ((state >> 8) != START_CODE) break; nut = (state >> 1) & 0x3F; -if (nut >= NAL_VPS && nut <= NAL_PPS) -has_ps = 1; -else if (has_ps) -return ptr - 4 - buf; -else // no parameter set at the beginning of the stream -return 0; +if (nut == NAL_VPS) +has_vps = 1; +else if (nut == NAL_SPS) +has_sps = 1; +else if (nut == NAL_PPS) +has_pps = 1; +else if ((nut != NAL_SEI_PREFIX || has_pps) && + nut != NAL_AUD) { +if (has_vps && has_sps) { +while (ptr - 4 > buf && ptr[-5] == 0) +ptr--; +return ptr - 4 - buf; +} +} } return 0; } -- 2.1.4 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] hevc - fix split function of parser
fix splitting extradata from ts ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] hevc - fix split function of parser
Carl Eugen Hoyos ag.or.at> writes: > Do you have a sample for us? > Or an explanation on how to reproduce. I tested with this sample: http://www.demo-uhd3d.com/fiche.php?cat=uhd=22 check spec 7.4.2.4.4 Order of NAL units and coded pictures and their association to access units > > Sorry if it is just me but isn't the > following more readable? > > int a = 0, b = 0, c = 0; personally I don't like multiple statements on a single line but feel free to change. I followed the example from h264_parser > > (But please feel free to ignore!) > > Carl Eugen > ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] x86/swr: fix pack_8ch functions on compilers without aligned stack
Carl Eugen Hoyos cehoyos at ag.or.at writes: That sounds impossible since the patch was pushed as http://git.videolan.org/?p=ffmpeg.git;a=commitdiff;h=f7ed997a Carl Eugen Why exactly is that impossible? It crashes in ff_pack_8ch_float_to_int32_a_sse2 on Windows. Same code, same scenario is fine on other platforms. Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] x86/swr: fix pack_8ch functions on compilers without aligned stack
Michael Niedermayer michaelni at gmx.at writes: can someone who has ICL/MSVC setup test this please failing that, lets apply the patch [...] Kodi crashes on Windows when doing 8 channel conversion. This seems to be the source of the problem. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] x86/swr: fix pack_8ch functions on compilers without aligned stack
Hendrik Leppkes h.leppkes at gmail.com writes: Kodi's build script suggests that FFmpeg is build with gcc - this crash and fix only ever applied to MSVC/ICL builds. It starts crashing with this commit: https://github.com/FFmpeg/FFmpeg/commit/37b35feb64e4e0382cd5e4502dbf0f7ff9aa0 b5f Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] x86/swr: fix pack_8ch functions on compilers without aligned stack
Carl Eugen Hoyos cehoyos at ag.or.at writes: So does adding attribute_align_arg to swr_convert_frame() (and friends?) fix the issue? Carl Eugen I added it to swr_convert and it does fix the issue here. Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] (no subject)
From 85ea58a3129b1766d44bf1425c6656d7a4f5624c Mon Sep 17 00:00:00 2001 From: Rainer Hochecker fernetme...@online.de Date: Wed, 13 May 2015 18:21:38 +0200 Subject: [PATCH] swr: fix alignment issue caused by 8ch sse functions --- libswresample/swresample.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 6d13bc5..76b7a84 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -23,6 +23,7 @@ #include audioconvert.h #include libavutil/avassert.h #include libavutil/channel_layout.h +#include libavutil/internal.h #include float.h @@ -663,8 +664,8 @@ int swr_is_initialized(struct SwrContext *s) { return !!s-in_buffer.ch_count; } -int swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count, -const uint8_t *in_arg [SWR_CH_MAX], int in_count){ +int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count, +const uint8_t *in_arg [SWR_CH_MAX], int in_count){ AudioData * in= s-in; AudioData *out= s-out; -- 2.1.4 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] (no subject)
[PATCH] swr: fix alignment issue caused by 8ch sse functions Fix crash when doing 8 ch conversion from apps compiled with MSVS Thanks to Ronald for giving this hint: https://ffmpeg.org/pipermail/ffmpeg-devel/2015-May/173049.html ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] vda: fix h64 decoding, vda wants the entire buffer
Michael Niedermayer michaelni at gmx.at writes: could it be that this should be using nal_length_size ? [...] I tried nal_length_size and it does not fix the issue. Instead it breaks some other files. Seems silly VDA does only support 4 byte avcC flavour. The patch brakes annexb. Should we add a parameter to AVVDAContext so that the application can instruct decoder what method to use? ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] vda: fix h64 decoding, vda wants the entire buffer
vda wants the entire buffer with all info. it has no other means to deliver picture parameters. according to documentation start_frame can pass the entire buffer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] vda: fix h64 decoding, vda wants the entire buffer
--- libavcodec/h264.c | 2 +- libavcodec/vda_h264.c | 25 - 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index e8d5120..60f8aa1 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -1589,7 +1589,7 @@ again: decode_postinit(h, nal_index = nals_needed); if (h-avctx-hwaccel -(ret = h-avctx-hwaccel-start_frame(h-avctx, NULL, 0)) 0) +(ret = h-avctx-hwaccel-start_frame(h-avctx, buf, buf_size)) 0) return ret; if (CONFIG_H264_VDPAU_DECODER h-avctx-codec-capabilities CODEC_CAP_HWACCEL_VDPAU) diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c index 081c366..d8053cf 100644 --- a/libavcodec/vda_h264.c +++ b/libavcodec/vda_h264.c @@ -320,8 +320,15 @@ static int vda_h264_start_frame(AVCodecContext *avctx, uint32_t size) { VDAContext *vda = avctx-internal-hwaccel_priv_data; +void *tmp; -vda-bitstream_size = 0; +tmp = av_fast_realloc(vda-bitstream, + vda-allocated_size, + size); + +vda-bitstream = tmp; +memcpy(vda-bitstream, buffer, size); +vda-bitstream_size = size; return 0; } @@ -330,22 +337,6 @@ static int vda_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { -VDAContext *vda = avctx-internal-hwaccel_priv_data; -void *tmp; - -tmp = av_fast_realloc(vda-bitstream, - vda-allocated_size, - vda-bitstream_size + size + 4); -if (!tmp) -return AVERROR(ENOMEM); - -vda-bitstream = tmp; - -AV_WB32(vda-bitstream + vda-bitstream_size, size); -memcpy(vda-bitstream + vda-bitstream_size + 4, buffer, size); - -vda-bitstream_size += size + 4; - return 0; } -- 2.1.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] vda: fix h64 decoding, vda wants the entire buffer
Hendrik Leppkes h.leppkes at gmail.com writes: On Wed, Apr 1, 2015 at 12:40 PM, Rainer Hochecker fernetmenta at online.de wrote: vda wants the entire buffer with all info. it has no other means to deliver picture parameters. according to documentation start_frame can pass the entire buffer This doesn't make much sense. If I follow that argument, then vda would never have worked, at all. How is it that it does work for many other people, presumably including the author of this code? - Hendrik Correct, it never worked properly. For that reason we had our own decoder for vda which worked properly with consuming the entire bitstream. I don't know why nobody cared about this so far. //Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] vda: fix h64 decoding, vda wants the entire buffer
Michael Niedermayer michaelni at gmx.at writes: could it be that this should be using nal_length_size ? [...] I am quite sure that the fix is correct. Our VDA decoder has always been working like this. Further I could not find any info on developer@apple that the current code is valid. No idea what was the source of information for the original code here. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] vda: fix h64 decoding, vda wants the entire buffer
Carl Eugen Hoyos cehoyos at ag.or.at writes: (guessing, needs --enable-libx264) $ ffmpeg -f lavfi -i testsrc -pix_fmt yuv420p -t 10 out.mp4 $ ffmpeg -f lavfi -i testsrc -pix_fmt yuv420p -t 10 out.h264 Carl Eugen my vda decoder does not even open with those generated samples. it fails in VDADecoderCreate (not related to this change) ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] h264: avoid unnecessary calls to get_format
--- libavcodec/h264_slice.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 80d27e5..9477650 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1417,7 +1417,8 @@ int ff_h264_decode_slice_header(H264Context *h, H264Context *h0) || h-mb_width != h-sps.mb_width || h-mb_height != h-sps.mb_height * (2 - h-sps.frame_mbs_only_flag) )); -if (non_j_pixfmt(h0-avctx-pix_fmt) != non_j_pixfmt(get_pixel_format(h0, 0))) +if (h0-avctx-pix_fmt == AV_PIX_FMT_NONE +|| (non_j_pixfmt(h0-avctx-pix_fmt) != non_j_pixfmt(get_pixel_format(h0, 0 must_reinit = 1; if (first_slice av_cmp_q(h-sps.sar, h-avctx-sample_aspect_ratio)) -- 2.1.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 1/2] hevc: avoid unnecessary calls to get_format
--- libavcodec/hevc.c | 25 - 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index fdbaa28..b52e778 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -280,7 +280,7 @@ static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb) return 0; } -static int set_sps(HEVCContext *s, const HEVCSPS *sps) +static int set_sps(HEVCContext *s, const HEVCSPS *sps, enum AVPixelFormat pix_fmt) { #define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; @@ -304,13 +304,18 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps) #endif } -*fmt++ = sps-pix_fmt; -*fmt = AV_PIX_FMT_NONE; +if (pix_fmt == AV_PIX_FMT_NONE) { +*fmt++ = sps-pix_fmt; +*fmt = AV_PIX_FMT_NONE; -ret = ff_thread_get_format(s-avctx, pix_fmts); -if (ret 0) -goto fail; -s-avctx-pix_fmt = ret; +ret = ff_thread_get_format(s-avctx, pix_fmts); +if (ret 0) +goto fail; +s-avctx-pix_fmt = ret; +} +else { +s-avctx-pix_fmt = pix_fmt; +} ff_set_sar(s-avctx, sps-vui.sar); @@ -420,7 +425,7 @@ static int hls_slice_header(HEVCContext *s) sh-no_output_of_prior_pics_flag = 0; } ff_hevc_clear_refs(s); -ret = set_sps(s, s-sps); +ret = set_sps(s, s-sps, AV_PIX_FMT_NONE); if (ret 0) return ret; @@ -3334,7 +3339,7 @@ static int hevc_update_thread_context(AVCodecContext *dst, } if (s-sps != s0-sps) -if ((ret = set_sps(s, s0-sps)) 0) +if ((ret = set_sps(s, s0-sps, src-pix_fmt)) 0) return ret; s-seq_decode = s0-seq_decode; @@ -3476,6 +3481,8 @@ static void hevc_decode_flush(AVCodecContext *avctx) { HEVCContext *s = avctx-priv_data; ff_hevc_flush_dpb(s); +hevc_decode_free(avctx); +s-context_initialized = 0; s-max_ra = INT_MAX; } -- 2.1.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH 2/2] hevc: delay ff_thread_finish_setup for hwaccel
--- libavcodec/hevc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index b52e778..998d58e 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -2605,7 +2605,8 @@ static int hevc_frame_start(HEVCContext *s) if (ret 0) goto fail; -ff_thread_finish_setup(s-avctx); +if (!s-avctx-hwaccel) +ff_thread_finish_setup(s-avctx); return 0; -- 2.1.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] hevc: fixes for hwaccel when running frame threaded
The first patch avoids unnecessary calls to get_format. We open a new hw decoder on every call to get_format. hevc seems to do something different than h264. deleting any provious allocated hw decoders at the application level results in heap corruption. There may be some other issue left but the multiple and unnecessary calls to get_format already bothered us with h264 which should be fixed too. The second patch avoids a flicker when running dxva frame threaded ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH 1/2] hevc: avoid unnecessary calls to get_format
Rainer Hochecker fernetmenta at online.de writes: hevc_decode_flush(AVCodecContext *avctx) { HEVCContext *s = avctx-priv_data; ff_hevc_flush_dpb(s); +hevc_decode_free(avctx); +s-context_initialized = 0; s-max_ra = INT_MAX; } this is a left over from debugging. does not belong to the patch ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] pthread: Fix?ff_thread_get_formatissues?when called outside frame decode.
Hendrik Leppkes h.leppkes at gmail.com writes: Just making the ff_thread_finish_setup call in hevc_frame_start conditional on !hwaccel should do what the other patches did. My code isn't setup to use this path, so someone that does should test it and send it. - Hendrik ___ I does not solve my particular problem which is all the pointers to hwaccel. flush_buffers triggers a return of all video surfaces back to application but application can't terminate the hw decoder because ffmpeg has still pointers to hwaccel. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] pthread: Fix ff_thread_get_formatissues when called outside frame decode.
Reimar Döffinger Reimar.Doeffinger at gmx.de writes: Any reason to believe this patch causes it? Because I can't see how it would. Maybe it's just a bug with DXVA and multithreading in the HEVC code? Can you provide some more information like a stacktrace, possibly using a tool like DrMemory? I don't think the patch itself is the root cause of the issue, it just triggers it. get_format is called 4 times, something seems to get corrupted in opening our hw decoder. Do you have an explanation why it works with thread_safe_callbacks set to 1? I am wondering if hevc misses the multithreading fix done for other codecs: http://ffmpeg.org/pipermail/ffmpeg-cvslog/2013-March/062620.html What do you think? ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] pthread: Fix ff_thread_get_formatissues when called outside frame decode.
Reimar Döffinger Reimar.Doeffinger at gmx.de writes: I tried this patch with Kodi but did not get very far. int ff_thread_can_start_frame(AVCodecContext *avctx) { PerThreadContext *p = avctx-internal-thread_ctx; if (avctx-active_thread_typeFF_THREAD_FRAME) return 0; av_assert0(!p-main_thread); It hit this assert and call stack showed avformat_find_stream_info How can I help progressing this. I want to run hevc frame threaded but without thread_safe_callback because of DXVA. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] pthread: Fix ff_thread_get_formatissues when called outside frame decode.
Reimar Döffinger Reimar.Doeffinger at gmx.de writes: I have tested this with Kodi. Works with sw decoding. With DXVA it crashes, looks like heap corruption or the like. setting thread_safe_callbacks = 1 cures the issue but I get some green frames at start of playback. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
[FFmpeg-devel] [PATCH] hevc: fix deadlock for frame threading safe callbacks disabled
--- libavcodec/hevc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index fdbaa28..7c7f920 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -307,7 +307,7 @@ static int set_sps(HEVCContext *s, const HEVCSPS *sps) *fmt++ = sps-pix_fmt; *fmt = AV_PIX_FMT_NONE; -ret = ff_thread_get_format(s-avctx, pix_fmts); +ret = ff_get_format(s-avctx, pix_fmts); if (ret 0) goto fail; s-avctx-pix_fmt = ret; -- 2.1.0 ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] hevc: fix deadlock for frame threading safe callbacks disabled
Rainer Hochecker fernetmenta at online.de writes: --- libavcodec/hevc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index fdbaa28..7c7f920 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c at at -307,7 +307,7 at at static int set_sps(HEVCContext *s, const HEVCSPS *sps) *fmt++ = sps-pix_fmt; *fmt = AV_PIX_FMT_NONE; -ret = ff_thread_get_format(s-avctx, pix_fmts); +ret = ff_get_format(s-avctx, pix_fmts); if (ret 0) goto fail; s-avctx-pix_fmt = ret; this is called from the main thread, hence a requesting the main thread do the call to get_format results in a hang waiting for the state to be changed to STATE_SETTING_UP ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] hevc: fix deadlock for frame threading safe callbacks disabled
Reimar Döffinger Reimar.Doeffinger at gmx.de writes: I sent an alternative patch pthread: Fix ff_thread_get_format issues when called outside frame decode. right, I didn't see you patch not the other code path. However there are additional bugs like update_context calling this and thus a single SPS change with n threads resulting in n get_format callbacks, all except the first completely pointless (and potentially causing issues with implementations that don't ensure that multiple get_format are side-effect free). As a result I am somewhat hesitant about my patch that would end up hiding all these issues. the issue with multiple get_format calls is already present for other codecs. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [libav-devel] [PATCH 2/2] lavf: move internal fields from public to internal context
Michael Niedermayer michaelni at gmx.at writes: ive already applied wm4s patch yesterday, so the next ffmpeg release (2.6) should contain avformat_flush() if further changes are needed please tell me [...] Thanks for notification. I will switch Kodi to 2.6 this weekend. ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat: remove FF_API_ASS_SSA dead code
Rainer Hochecker fernetmenta at online.de writes: It's me again. I got a matroshka sample for which I get ASS subs without timestamps (NOPTS_VALUE): https://mega.co.nz/#!dEcRwZ4C!cg_6xlpPlhRN0trGEDH1C-ErJ7gXIe6CUezaEokBSV8 . Am I doing anything wrong? Rainer This file has no timestamps at all. I doubt that it worked before upgrade to ffmpeg 2.4. Please ignore my previous post. Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat: remove FF_API_ASS_SSA dead code
Clément Bœsch u at pkh.me writes: I'm seeing timestamps set in the packets with: ffprobe -show_packets -show_data -select_streams s:0 ~/samples/Test_File-01.mkv Same with other streams Thanks, making use of ffprobe was a good idea. Now I see the difference. With version 2.4 we got one packet with multiple Dialogue: ... http://paste.ubuntu.com/8426844/ Now we get multiple packets with equal pts. This requires an additional change for us. http://paste.ubuntu.com/8426767/ Thanks again, Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat: remove FF_API_ASS_SSA dead code
Clément Bœsch u at pkh.me writes: +1 Applied We at XBMC got the first complaints about broken subtitles. Why was this removed? ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat: remove FF_API_ASS_SSA dead code
Clément Bœsch u at pkh.me writes: Hi, We just made the ASS packets from the Matroska output them verbatim, and not hacked with timestamps included into the timestamps. The packets are now typically broadcastable to libass. Note that this change has been documented since 2.0; doc/APIchanges states: 2013-04-18 - 7c1a002 - lavf 55.3.100 The matroska demuxer can now output proper verbatim ASS packets. It will become the default starting lavf 56.0.100. It was also mentioned in the RELEASE_NOTES of 2.4 after the bump: http://git.videolan.org/?p=ffmpeg.git;a=blob;f=RELEASE_NOTES;hb=HEAD#l40 I'm sorry about the compatibility break but we had to move on, and I believe it was done in a proper way (slow and documented, while providing benefits for the end user at the same time) Best regards, PS: this commit didn't disable the code, it was disabled since last bump, which means in 2.4 Hi, Thank you very much for this explanation and sorry for not having read release notes properly. subs are not my territory but the maintainer is busy with real life so I will try to adapt to those changes. Cheers, Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] [PATCH] avformat: remove FF_API_ASS_SSA dead code
Clément Bœsch u at pkh.me writes: On Mon, Sep 22, 2014 at 03:12:02PM +, Rainer Hochecker wrote: [...] Hi, Thank you very much for this explanation and sorry for not having read release notes properly. subs are not my territory but the maintainer is busy with real life so I will try to adapt to those changes. Feel free to ask more direct questions. Basically, the idea is that the matroska demuxer will now output AVPacket.data that looks like this: 1,,Wolf main,Cher,,,,,Et les enregistrements de ses ondes delta ? instead of: Dialogue: Marked=0,0:02:42.42,0:02:44.15,Wolf main,autre,,,,,Toujours rien. (to take the matroska specs example) The later had several problems, like including timestamp in a string which couldn't be altered without insane hacks at format level. It also dropped the ReadOrder fields which is needed to get proper rendering. [...] Note that we still use the Dialogue: ... form for internal decoded form of the subtitles (what you get into AVSubtitle when calling the decode subtitles function on the AVPacket), but I'm working on fixing this. I'll try to document that change even more, and compatibility will last for a long time again. I only needed to add AV_CODEC_ID_ASS to our handler which already took AV_CODEC_ID_SSA. According to the discussion here: http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-May/157170.html, is it correct to drop AV_CODEC_ID_SSA? Regards, Rainer ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel