[FFmpeg-devel] [PATCH 01/20] avformat/matroskaenc: Ensure that ChapterUID are != 0

Steve Lhomme robux4 at ycbcr.xyz
Sun Apr 19 09:52:37 EEST 2020


> On April 5, 2020 5:59 PM Andreas Rheinhardt <andreas.rheinhardt at gmail.com> wrote:
> 
>  
> AVChapters have an int as id field and therefore this value can appear
> <= 0. When remuxing from Matroska, this value actually contains
> the lower 32 bits of the original ChapterUID (which can be 64 bits).
> 
> In order to ensure that the ChapterUID is always > 0, they were offset
> as follows (since 07704c61): First max(0, 1LL - chapter[i].id) was computed
> and stored in an uint32_t. And then the IDs were offset using this value.
> 
> This has two downsides:
> 1. It does not ensure that the UID is actually != 0: Namely if there is
> a chapter with id == INT_MIN, then the offset will be 2^31 + 1 and a
> chapter with id == INT_MAX will become 2^31 - 1 + 2^31 + 1 = 2^32 = 0,
> because the actual calculation was performed in 32 bits.
> 2. As soon as a chapter id appears to be negative, a nontrivial offset
> is used, so that not even a ChapterUID that only uses 32 bits is
> preserved.
> 
> So change this by treating the id as an unsigned value internally and
> only offset (by 1) if an id vanishes. The actual offsetting then has to
> be performed in 64 bits in order to make sure that no UINT32_MAX wraps
> around.

That means you are changing the chapter UIDs of the source when remuxing (if for some reason a chapter with no id was added in the process). If tags were referencing the chapter UIDs (TagChapterUID) they don't match the chapter anymore.

I think silently changing the IDs is wrong. But its was already like that before, so that's not breaking your patch. If anything your patch is less likely to break remuxing.

> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
> ---
>  libavformat/matroskaenc.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
> index 060e8b7816..a377d092df 100644
> --- a/libavformat/matroskaenc.c
> +++ b/libavformat/matroskaenc.c
> @@ -1422,7 +1422,8 @@ static int mkv_write_chapters(AVFormatContext *s)
>          }
>  
>          chapteratom = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERATOM, 0);
> -        put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, c->id + mkv->chapter_id_offset);
> +        put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID,
> +                      (uint32_t)c->id + (uint64_t)mkv->chapter_id_offset);
>          put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart);
>          put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend);
>          if (mkv->mode != MODE_WEBM) {
> @@ -1479,7 +1480,7 @@ static int mkv_write_simpletag(AVIOContext *pb, AVDictionaryEntry *t)
>  }
>  
>  static int mkv_write_tag_targets(AVFormatContext *s, uint32_t elementid,
> -                                 unsigned int uid, ebml_master *tag)
> +                                 uint64_t uid, ebml_master *tag)
>  {
>      AVIOContext *pb;
>      MatroskaMuxContext *mkv = s->priv_data;
> @@ -1518,7 +1519,7 @@ static int mkv_check_tag_name(const char *name, uint32_t elementid)
>  }
>  
>  static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, uint32_t elementid,
> -                         unsigned int uid)
> +                         uint64_t uid)
>  {
>      MatroskaMuxContext *mkv = s->priv_data;
>      ebml_master tag;
> @@ -1612,7 +1613,8 @@ static int mkv_write_tags(AVFormatContext *s)
>              if (!mkv_check_tag(ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID))
>                  continue;
>  
> -            ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID, ch->id + mkv->chapter_id_offset);
> +            ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID,
> +                                (uint32_t)ch->id + (uint64_t)mkv->chapter_id_offset);
>              if (ret < 0)
>                  return ret;
>          }
> @@ -1882,7 +1884,10 @@ static int mkv_write_header(AVFormatContext *s)
>          return ret;
>  
>      for (i = 0; i < s->nb_chapters; i++)
> -        mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id);
> +        if (!s->chapters[i]->id) {
> +            mkv->chapter_id_offset = 1;
> +            break;
> +        }
>  
>      ret = mkv_write_chapters(s);
>      if (ret < 0)
> -- 
> 2.20.1
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-devel mailing list