[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