[vlc-commits] [Git][videolan/vlc][3.0.x] 14 commits: avcodec: don't assume ticks_per_frame can be 0

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Thu Jan 23 08:49:32 UTC 2025



Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC


Commits:
c0da09ef by Steve Lhomme at 2025-01-23T08:27:42+00:00
avcodec: don't assume ticks_per_frame can be 0

The documentation says it's either 1 or 2.
I verified this is the case in FFmpeg 7.1. Only h264dec, mpeg12dec, mpegvideo_parser, vc1 set it.

(cherry picked from commit 2f5c860459f9d72a42b55cf0d0df4dc9b0eb0de5) (edited)
edited:
- p_sys is accessed via dec->p_sys on 3.0

- - - - -
2f0e6205 by Steve Lhomme at 2025-01-23T08:27:42+00:00
avcodec: use AV_CODEC_PROP_FIELDS to tell the number of ticks

codecs sending 2 fields set the flag, otherwise it's one field.

ticks_per_frame is deprecated and will be removed in the next major API bump.

(cherry picked from commit 47b878be880242637aea7a0ea2fa0aa4d6794cde) (rebased)
rebased:
- the code around is slightly different

- - - - -
2748c79f by Steve Lhomme at 2025-01-23T08:27:42+00:00
avcodec/encoder: use frame flags instead of fields

The structure fields are deprecated.
It was introduced in lavu 58.7.100.

(cherry picked from commit 44dfaf630c9b1b536797917e619c8eba0aa40b6c)

- - - - -
5815fdd7 by Steve Lhomme at 2025-01-23T08:27:42+00:00
avcodec/encoder: use AV_CODEC_CONFIG_FRAME_RATE to get supported frame rates

p_codec->supported_framerates is deprecated.

(cherry picked from commit e1f4cc8240f62c37aeb2d1fed8b6b4073f35d433) (rebased)
rebased:
- the code around is slightly different

- - - - -
9f5ad85d by Steve Lhomme at 2025-01-23T08:27:42+00:00
avcodec/encoder: use AV_CODEC_CONFIG_PIX_FORMAT to get supported pixel formats

p_codec->pix_fmts is deprecated.
It both cases the array was ending with AV_PIX_FMT_NONE.

(cherry picked from commit 5e11c8f387f3c135d9aa2e36fd0ee81774917404) (edited)
edited:
- 3.0 was using PixelFormat instead of AVPixelFormat

- - - - -
82cee41e by Steve Lhomme at 2025-01-23T08:27:42+00:00
avcodec/encoder: use AV_CODEC_CONFIG_SAMPLE_FORMAT to get supported sample formats

p_codec->sample_fmts is deprecated.
It both cases the array was ending with AV_SAMPLE_FMT_NONE.

(cherry picked from commit f20c48050e0b4f42269ff4e0340c8c430712a691)

- - - - -
43e84806 by Steve Lhomme at 2025-01-23T08:27:42+00:00
avcodec/encoder: use avcodec_free_context in place of avcodec_close()

avcodec_close() has been discouraged since 2016 [^1].
The internal closing we need under lock is done inside avcodec_free_context().

[^1] https://github.com/FFmpeg/FFmpeg/commit/1cc24d749569a42510399a29b034f7a77bdec34e

(cherry picked from commit cda249f4ffd150539dfc145b7ee2fcaca7ab67c3)

- - - - -
4f91d136 by Vittorio Giovara at 2025-01-23T08:27:42+00:00
demux/avformat: Prioritize side data rotation rather than metadata one

The side data API will offer a more accurate representation of the
rendering operations in the next commit.

(cherry picked from commit 1997cec8abd801bbf4ebcae72db28ab8277f221c)

- - - - -
9c1c856d by Vittorio Giovara at 2025-01-23T08:27:42+00:00
demux/avformat: Apply flip operations from the display matrix

(cherry picked from commit 6903d3a77520d9ae110f112c7ba9010612f5d36a)

- - - - -
349ab812 by Steve Lhomme at 2025-01-23T08:27:42+00:00
avformat: add a helper to read stream side data

av_packet_side_data_get() was introduced in lavc 60.29.100 [^1].
av_stream_get_side_data() is deprecated and will be removed in the future.

 [^1] https://github.com/FFmpeg/FFmpeg/commit/74279227dd28d01b447edb8e617a545982171c2c

(cherry picked from commit d3f5c8746f2884a46d8421cd051dc74b25000870)

- - - - -
bb8d0318 by Steve Lhomme at 2025-01-23T08:27:42+00:00
avformat: use av_packet_side_data_get() instead of deprecated av_stream_get_side_data()

(cherry picked from commit de0cf6297d50ad21543719092f1a8a14b0a66931) (edited)
edited:
- 3.0 doesn't carry DolbyVision metadata

- - - - -
d4bcfefe by Steve Lhomme at 2025-01-23T08:27:42+00:00
avformat: pass a const AVStream in side data getters

(cherry picked from commit 27e327e78458261870fd99d0195f41ac4a8bd1f7) (edited)
edited:
- 3.0 doesn't carry DolbyVision metadata

- - - - -
eb35d137 by Steve Lhomme at 2025-01-23T08:27:42+00:00
avformat: use a flag to tell if the matrix is flipped

If it's flipped, it's modifying the source matrix inside the codec
which doesn't seem right...

(cherry picked from commit 0e208650bb10528c4caeb0a8ecfb3a4d460de36f)

- - - - -
7e988ea0 by Steve Lhomme at 2025-01-23T08:27:42+00:00
avformat: get the palette side data

(cherry picked from commit 53858f99d4c334bc131800292a8709173769c882) (rebased)
rebased:
- 3.0 doesn't carry DolbyVision metadata
- the code around is slightly different

- - - - -


3 changed files:

- modules/codec/avcodec/encoder.c
- modules/codec/avcodec/video.c
- modules/demux/avformat/demux.c


Changes:

=====================================
modules/codec/avcodec/encoder.c
=====================================
@@ -258,19 +258,29 @@ static void probe_video_frame_rate( encoder_t *p_enc, AVCodecContext *p_context,
                                   ( p_enc->fmt_out.i_codec == VLC_CODEC_MP4V ? 25 : CLOCK_FREQ );
 
     msg_Dbg( p_enc, "Time base for probing set to %d/%d", p_context->time_base.num, p_context->time_base.den );
-    if( p_codec->supported_framerates )
+
+    const AVRational *supported_framerates;
+#if LIBAVCODEC_VERSION_CHECK( 61, 13, 100 )
+    if (avcodec_get_supported_config(p_context, p_codec, AV_CODEC_CONFIG_FRAME_RATE, 0,
+                                     (const void **)&supported_framerates, NULL) < 0)
+        supported_framerates = NULL;
+#else
+    supported_framerates = p_codec->supported_framerates;
+#endif
+
+    if( supported_framerates )
     {
         /* We are finding fps values so 1/time_base */
         AVRational target = {
             .num = p_context->time_base.den,
             .den = p_context->time_base.num
         };
-        int idx = av_find_nearest_q_idx(target, p_codec->supported_framerates);
+        int idx = av_find_nearest_q_idx(target, supported_framerates);
 
-        p_context->time_base.num = p_codec->supported_framerates[idx].den ?
-                                    p_codec->supported_framerates[idx].den : 1;
-        p_context->time_base.den = p_codec->supported_framerates[idx].den ?
-                                    p_codec->supported_framerates[idx].num : CLOCK_FREQ;
+        p_context->time_base.num = supported_framerates[idx].den ?
+                                    supported_framerates[idx].den : 1;
+        p_context->time_base.den = supported_framerates[idx].den ?
+                                    supported_framerates[idx].num : CLOCK_FREQ;
 
         /* If we have something reasonable on supported framerates, use that*/
         if( p_context->time_base.den && p_context->time_base.den < CLOCK_FREQ )
@@ -559,7 +569,16 @@ int InitVideoEnc( vlc_object_t *p_this )
         p_enc->fmt_in.video.i_chroma = p_enc->fmt_in.i_codec;
         GetFfmpegChroma( &p_context->pix_fmt, &p_enc->fmt_in.video );
 
-        if( p_codec->pix_fmts )
+        const enum AVPixelFormat *pix_fmts;
+#if LIBAVCODEC_VERSION_CHECK( 61, 13, 100 )
+        if (avcodec_get_supported_config(p_context, p_codec, AV_CODEC_CONFIG_PIX_FORMAT, 0,
+                                        (const void **)&pix_fmts, NULL) < 0)
+            pix_fmts = NULL;
+#else
+        pix_fmts = p_codec->pix_fmts;
+#endif
+
+        if( pix_fmts )
         {
             static const enum AVPixelFormat vlc_pix_fmts[] = {
                 AV_PIX_FMT_YUV420P,
@@ -567,8 +586,8 @@ int InitVideoEnc( vlc_object_t *p_this )
                 AV_PIX_FMT_RGB24,
             };
             bool found = false;
-            const enum PixelFormat *p = p_codec->pix_fmts;
-            for( ; !found && *p != -1; p++ )
+            const enum AVPixelFormat *p = pix_fmts;
+            for( ; !found && *p != AV_PIX_FMT_NONE; p++ )
             {
                 for( size_t i = 0; i < ARRAY_SIZE(vlc_pix_fmts); ++i )
                 {
@@ -580,7 +599,7 @@ int InitVideoEnc( vlc_object_t *p_this )
                     }
                 }
             }
-            if (!found) p_context->pix_fmt = p_codec->pix_fmts[0];
+            if (!found) p_context->pix_fmt = pix_fmts[0];
             GetVlcChroma( &p_enc->fmt_in.video, p_context->pix_fmt );
             p_enc->fmt_in.i_codec = p_enc->fmt_in.video.i_chroma;
         }
@@ -705,22 +724,29 @@ int InitVideoEnc( vlc_object_t *p_this )
     }
     else if( p_enc->fmt_in.i_cat == AUDIO_ES )
     {
+        const enum AVSampleFormat *sample_fmts;
+#if LIBAVCODEC_VERSION_CHECK( 61, 13, 100 )
+        if (avcodec_get_supported_config(p_context, p_codec, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
+                                        (const void **)&sample_fmts, NULL) < 0)
+            sample_fmts = NULL;
+#else
+        sample_fmts = p_codec->sample_fmts;
+#endif
+
         p_context->codec_type  = AVMEDIA_TYPE_AUDIO;
-        p_context->sample_fmt  = p_codec->sample_fmts ?
-                                    p_codec->sample_fmts[0] :
-                                    AV_SAMPLE_FMT_S16;
+        p_context->sample_fmt  = sample_fmts ? sample_fmts[0] : AV_SAMPLE_FMT_S16;
 
         /* Try to match avcodec input format to vlc format so we could avoid one
            format conversion */
         if( GetVlcAudioFormat( p_context->sample_fmt ) != p_enc->fmt_in.i_codec
-            && p_codec->sample_fmts )
+            && sample_fmts )
         {
             msg_Dbg( p_enc, "Trying to find more suitable sample format instead of %s", av_get_sample_fmt_name( p_context->sample_fmt ) );
-            for( unsigned int i=0; p_codec->sample_fmts[i] != -1; i++ )
+            for( unsigned int i=0; sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++ )
             {
-                if( GetVlcAudioFormat( p_codec->sample_fmts[i] ) == p_enc->fmt_in.i_codec )
+                if( GetVlcAudioFormat( sample_fmts[i] ) == p_enc->fmt_in.i_codec )
                 {
-                    p_context->sample_fmt = p_codec->sample_fmts[i];
+                    p_context->sample_fmt = sample_fmts[i];
                     msg_Dbg( p_enc, "Using %s as new sample format", av_get_sample_fmt_name( p_context->sample_fmt ) );
                     break;
                 }
@@ -729,14 +755,14 @@ int InitVideoEnc( vlc_object_t *p_this )
         p_sys->b_planar = av_sample_fmt_is_planar( p_context->sample_fmt );
         // Try if we can use interleaved format for codec input as VLC doesn't really do planar audio yet
         // FIXME: Remove when planar/interleaved audio in vlc is equally supported
-        if( p_sys->b_planar && p_codec->sample_fmts )
+        if( p_sys->b_planar && sample_fmts )
         {
             msg_Dbg( p_enc, "Trying to find packet sample format instead of planar %s", av_get_sample_fmt_name( p_context->sample_fmt ) );
-            for( unsigned int i=0; p_codec->sample_fmts[i] != -1; i++ )
+            for( unsigned int i=0; sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++ )
             {
-                if( !av_sample_fmt_is_planar( p_codec->sample_fmts[i] ) )
+                if( !av_sample_fmt_is_planar( sample_fmts[i] ) )
                 {
-                    p_context->sample_fmt = p_codec->sample_fmts[i];
+                    p_context->sample_fmt = sample_fmts[i];
                     msg_Dbg( p_enc, "Changing to packet format %s as new sample format", av_get_sample_fmt_name( p_context->sample_fmt ) );
                     break;
                 }
@@ -1227,8 +1253,19 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
         frame->pict_type = 0;
 
         frame->repeat_pict = p_pict->i_nb_fields - 2;
+#if LIBAVUTIL_VERSION_CHECK( 58, 7, 100 )
+        if (p_pict->b_progressive)
+            frame->flags &= ~AV_FRAME_FLAG_INTERLACED;
+        else
+            frame->flags |= AV_FRAME_FLAG_INTERLACED;
+        if (p_pict->b_top_field_first)
+            frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
+        else
+            frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST;
+#else
         frame->interlaced_frame = !p_pict->b_progressive;
         frame->top_field_first = !!p_pict->b_top_field_first;
+#endif
 
         frame->format = p_sys->p_context->pix_fmt;
         frame->width = p_sys->p_context->width;
@@ -1483,9 +1520,8 @@ void EndVideoEnc( vlc_object_t *p_this )
     av_frame_free( &p_sys->frame );
 
     vlc_avcodec_lock();
-    avcodec_close( p_sys->p_context );
-    vlc_avcodec_unlock();
     avcodec_free_context( &p_sys->p_context );
+    vlc_avcodec_unlock();
 
 
     av_free( p_sys->p_interleave_buf );


=====================================
modules/codec/avcodec/video.c
=====================================
@@ -205,8 +205,7 @@ static int lavc_GetVideoFormat(decoder_t *dec, video_format_t *restrict fmt,
     else if (ctx->time_base.num > 0 && ctx->time_base.den > 0)
     {
         fmt->i_frame_rate = ctx->time_base.den;
-        fmt->i_frame_rate_base = ctx->time_base.num
-                                 * __MAX(ctx->ticks_per_frame, 1);
+        fmt->i_frame_rate_base = ctx->time_base.num;
     }
 
     /* FIXME we should only set the known values and let the core decide
@@ -328,12 +327,10 @@ static int lavc_UpdateVideoFormat(decoder_t *dec, AVCodecContext *ctx,
 
     /* always have date in fields/ticks units */
     if(dec->p_sys->pts.i_divider_num)
-        date_Change(&dec->p_sys->pts, fmt_out.i_frame_rate *
-                                      __MAX(ctx->ticks_per_frame, 1),
+        date_Change(&dec->p_sys->pts, fmt_out.i_frame_rate,
                                       fmt_out.i_frame_rate_base);
     else
-        date_Init(&dec->p_sys->pts, fmt_out.i_frame_rate *
-                                    __MAX(ctx->ticks_per_frame, 1),
+        date_Init(&dec->p_sys->pts, fmt_out.i_frame_rate,
                                     fmt_out.i_frame_rate_base);
 
     fmt_out.p_palette = dec->fmt_out.video.p_palette;
@@ -946,9 +943,11 @@ static vlc_tick_t interpolate_next_pts( decoder_t *p_dec, AVFrame *frame )
         p_sys->pts.i_divider_num == 0 )
         return VLC_TICK_INVALID;
 
+#if LIBAVCODEC_VERSION_CHECK( 60, 12, 100 )
+    int i_tick = p_context->codec_descriptor->props & AV_CODEC_PROP_FIELDS ? 2 : 1;
+#else
     int i_tick = p_context->ticks_per_frame;
-    if( i_tick <= 0 )
-        i_tick = 1;
+#endif
 
     /* interpolate the next PTS */
     return date_Increment( &p_sys->pts, i_tick + frame->repeat_pict );


=====================================
modules/demux/avformat/demux.c
=====================================
@@ -111,18 +111,63 @@ static vlc_fourcc_t CodecTagToFourcc( uint32_t codec_tag )
 #endif
 }
 
+static inline void* GetStreamSideData(const AVStream *s, enum AVPacketSideDataType type)
+{
+#if LIBAVCODEC_VERSION_CHECK( 60, 29, 100 )
+    const AVCodecParameters *cp = s->codecpar;
+    const AVPacketSideData *psd =
+        av_packet_side_data_get(cp->coded_side_data, cp->nb_coded_side_data, type);
+    return psd ? psd->data : NULL;
+#else
+    return av_stream_get_side_data(s, type, NULL);
+#endif
+}
+
 /*****************************************************************************
  * Open
  *****************************************************************************/
 
-static void get_rotation(es_format_t *fmt, AVStream *s)
+static void get_rotation(es_format_t *fmt, const AVStream *s)
 {
     char const *kRotateKey = "rotate";
     AVDictionaryEntry *rotation = av_dict_get(s->metadata, kRotateKey, NULL, 0);
     long angle = 0;
 
-    if( rotation )
-    {
+    int32_t *matrix = GetStreamSideData(s, AV_PKT_DATA_DISPLAYMATRIX);
+    if( matrix ) {
+        bool flipped = (int64_t)matrix[0] * matrix[4] < (int64_t)matrix[1] * matrix[3];
+        if (flipped) {
+            /* Flip the matrix to decouple flip and rotation operations.
+             * Always assume an horizontal flip for simplicity,
+             * it can be changed later if rotation is 180º. */
+            av_display_matrix_flip(matrix, 1, 0);
+        }
+        angle = lround(av_display_rotation_get(matrix));
+
+        if (angle > 45 && angle < 135)
+            fmt->video.orientation = ORIENT_ROTATED_270;
+
+        else if (angle > 135 || angle < -135) {
+            if (flipped)
+                fmt->video.orientation = ORIENT_VFLIPPED;
+            else
+                fmt->video.orientation = ORIENT_ROTATED_180;
+        }
+        else if (angle < -45 && angle > -135)
+            fmt->video.orientation = ORIENT_ROTATED_90;
+
+        else
+            fmt->video.orientation = ORIENT_NORMAL;
+
+        /* Flip is already applied to the 180º case. */
+        if (flipped && !(angle > 135 || angle < -135)) {
+            video_transform_t transform = (video_transform_t)fmt->video.orientation;
+            /* Flip first then rotate */
+            fmt->video.orientation = ORIENT_HFLIPPED;
+            video_format_TransformBy(&fmt->video, transform);
+        }
+
+    } else if( rotation ) {
         angle = strtol(rotation->value, NULL, 10);
 
         if (angle > 45 && angle < 135)
@@ -137,21 +182,18 @@ static void get_rotation(es_format_t *fmt, AVStream *s)
         else
             fmt->video.orientation = ORIENT_NORMAL;
     }
-    int32_t *matrix = (int32_t *)av_stream_get_side_data(s, AV_PKT_DATA_DISPLAYMATRIX, NULL);
-    if( matrix ) {
-        angle = lround(av_display_rotation_get(matrix));
-
-        if (angle > 45 && angle < 135)
-            fmt->video.orientation = ORIENT_ROTATED_270;
-
-        else if (angle > 135 || angle < -135)
-            fmt->video.orientation = ORIENT_ROTATED_180;
-
-        else if (angle < -45 && angle > -135)
-            fmt->video.orientation = ORIENT_ROTATED_90;
+}
 
-        else
-            fmt->video.orientation = ORIENT_NORMAL;
+static void get_palette(es_format_t *fmt, const AVStream *s)
+{
+    const uint8_t *pal = GetStreamSideData(s, AV_PKT_DATA_PALETTE);
+    if (pal) {
+        video_palette_t *p_palette = fmt->video.p_palette;
+        for (size_t i=0; i<ARRAY_SIZE(p_palette->palette); i++)
+        {
+            memcpy(p_palette->palette[i], pal, sizeof(p_palette->palette[0]));
+            pal += sizeof(p_palette->palette[0]);
+        }
     }
 }
 
@@ -450,8 +492,8 @@ int avformat_OpenDemux( vlc_object_t *p_this )
             es_fmt.video.i_visible_height = es_fmt.video.i_height;
 
             get_rotation(&es_fmt, s);
+            get_palette(&es_fmt, s);
 
-# warning FIXME: implement palette transmission
             psz_type = "video";
 
             AVRational rate;



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/38c5c239a8729f8d04430f41dfc677ade0f22ad1...7e988ea031c6f386cd733fa3117b1cf6d8c33ba2

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/38c5c239a8729f8d04430f41dfc677ade0f22ad1...7e988ea031c6f386cd733fa3117b1cf6d8c33ba2
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list