James Almer (12021-03-23):
> Signed-off-by: James Almer <jamr...@gmail.com>
> ---
> Following "lavf: move AVStream.*index_entries* to AVStreamInternal", it was
> revealed that some library users apparently found these fields useful and were
> accessing them despite not being public.
> This patch introduces a few functions to recover this functionality in a 
> proper
> and supported way.
> 

> We can't simply return a const pointer to the corresponding AVIndexEntry in 
> the
> array because it may change at any time by for example calling
> av_add_index_entry(), so it's either a copy of the AVIndexEntry, or adding 
> half
> a dozen output parameters to the function signature for each field in
> AVIndexEntry.

We can return a const pointer to the AVIndexEntry if we document it:

        Warning: the returned pointer is only valid until the next
        operation that may modify the AVStream or the AVFormatContext it
        belongs to. Accessing it after av_read_frame() or other
        functions results in undefined behavior.

Users can still copy it immediately if they need it longer.

> 
>  libavformat/avformat.h | 39 +++++++++++++++++++++++++++++++++++++++
>  libavformat/utils.c    | 32 ++++++++++++++++++++++++++++++++
>  2 files changed, 71 insertions(+)
> 
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 765bc3b6f5..ac8b57149e 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -2754,6 +2754,45 @@ int av_find_default_stream_index(AVFormatContext *s);
>   */
>  int av_index_search_timestamp(AVStream *st, int64_t timestamp, int flags);
>  
> +/**
> + * Get the index entry count for the given AVStream.
> + *
> + * @param st stream
> + * @return the number of index entries in the stream
> + */
> +int av_index_get_entries_count(AVStream *st);
> +
> +/**
> + * Get the AVIndexEntry corresponding to the given index.
> + *
> + * @param st          stream containing the requested AVIndexEntry
> + * @param index_entry pointer to an AVIndexEntry where to store the entry. 
> On failure,
> + *                    or if the index entry could not be found, this struct 
> will remain
> + *                    untouched
> + * @param idx         the desired index
> + * @return >= 0 on success. AVERROR(ENOENT) if no entry for the requested 
> index could
> +           be found. other negative AVERROR codes on failure.
> + */
> +int av_index_get_entry(AVStream *st, AVIndexEntry *index_entry, int idx);
> +
> +/**
> + * Get the AVIndexEntry corresponding to the given timestamp.
> + *
> + * @param st          stream containing the requested AVIndexEntry
> + * @param index_entry pointer to an AVIndexEntry where to store the entry. 
> On failure,
> + *                    or if the index entry could not be found, this struct 
> will remain
> + *                    untouched
> + * @param timestamp   timestamp to retrieve the index entry for
> + * @param flags       if AVSEEK_FLAG_BACKWARD then the returned entry will 
> correspond
> + *                    to the timestamp which is <= the requested one, if 
> backward
> + *                    is 0, then it will be >=
> + *                    if AVSEEK_FLAG_ANY seek to any frame, only keyframes 
> otherwise
> + * @return >= 0 on success. AVERROR(ENOENT) if no entry for the requested 
> timestamp could
> + *          be found. other negative AVERROR codes on failure.
> + */
> +int av_index_get_entry_from_timestamp(AVStream *st, AVIndexEntry 
> *index_entry,
> +                                      int64_t wanted_timestamp, int flags);
> +
>  /**
>   * Add an index entry into a sorted list. Update the entry if the list
>   * already contains it.
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index f31826f2ea..4e7a8bf23e 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -2129,6 +2129,38 @@ int av_index_search_timestamp(AVStream *st, int64_t 
> wanted_timestamp, int flags)
>                                       wanted_timestamp, flags);
>  }
>  
> +int av_index_get_entries_count(AVStream *st)
> +{
> +    return st->internal->nb_index_entries;
> +}
> +
> +int av_index_get_entry(AVStream *st, AVIndexEntry *index_entry, int idx)
> +{

> +    if (idx < 0)
> +        return AVERROR(EINVAL);

Make idx unsigned.

> +    if (idx >= st->internal->nb_index_entries)
> +        return AVERROR(ENOENT);
> +

> +    memcpy(index_entry, &st->internal->index_entries[idx], 
> sizeof(*index_entry));

Why not using an assignment?

But this makes sizeof(AVIndexEntry) part of the ABI. Probably not what
we want.

> +
> +    return 0;
> +}
> +
> +int av_index_get_entry_from_timestamp(AVStream *st, AVIndexEntry 
> *index_entry,
> +                                      int64_t wanted_timestamp, int flags)
> +{
> +    int idx = ff_index_search_timestamp(st->internal->index_entries,
> +                                        st->internal->nb_index_entries,
> +                                        wanted_timestamp, flags);
> +
> +    if (idx < 0)
> +        return AVERROR(ENOENT);
> +

> +    memcpy(index_entry, &st->internal->index_entries[idx], 
> sizeof(*index_entry));

Same, of course.

> +
> +    return 0;
> +}
> +
>  static int64_t ff_read_timestamp(AVFormatContext *s, int stream_index, 
> int64_t *ppos, int64_t pos_limit,
>                                   int64_t (*read_timestamp)(struct 
> AVFormatContext *, int , int64_t *, int64_t ))
>  {

Regards,

-- 
  Nicolas George

Attachment: signature.asc
Description: PGP signature

_______________________________________________
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".

Reply via email to