Re: [FFmpeg-devel] [PATCH] lavf/dv: do not set video timebase more than once

2023-05-01 Thread Anton Khirnov
Will push the set tomorrow if nobody has further objections.

-- 
Anton Khirnov
___
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".


[FFmpeg-devel] [PATCH] lavf/dv: do not set video timebase more than once

2023-04-27 Thread Anton Khirnov
Current code will call avpriv_set_pts_info() for each video frame,
possibly setting a different timebase if the stream framerate changes.
This violates API conventions, as the timebase is supposed to stay
constant after stream creation.

Change the demuxer to set a single timebase that is fine enough to
handle all supported DV framerates.

The seek tests change slightly because the new timebase is more
granular.
---
 libavcodec/dv.h   |  3 +++
 libavformat/avidec.c  | 22 +--
 libavformat/dv.c  | 36 +++
 libavformat/dv.h  |  2 +-
 tests/ref/seek/lavf-dv| 16 +++---
 tests/ref/seek/vsynth_lena-dv | 24 ++---
 tests/ref/seek/vsynth_lena-dv-411 | 24 ++---
 tests/ref/seek/vsynth_lena-dv-50  | 24 ++---
 8 files changed, 91 insertions(+), 60 deletions(-)

diff --git a/libavcodec/dv.h b/libavcodec/dv.h
index 29f97b6089..b473bdc992 100644
--- a/libavcodec/dv.h
+++ b/libavcodec/dv.h
@@ -60,6 +60,9 @@ enum DVPackType {
  */
 #define DV_MAX_FRAME_SIZE 576000
 
+// LCM of video framerate numerators
+#define DV_TIMESCALE_VIDEO 6
+
 /**
  * maximum number of blocks per macroblock in any DV format
  */
diff --git a/libavformat/avidec.c b/libavformat/avidec.c
index 7a3fad6392..00bd7a98a9 100644
--- a/libavformat/avidec.c
+++ b/libavformat/avidec.c
@@ -1869,13 +1869,20 @@ static int avi_read_seek(AVFormatContext *s, int 
stream_index,
 st= s->streams[stream_index];
 sti   = ffstream(st);
 ast   = st->priv_data;
-index = av_index_search_timestamp(st,
-  timestamp * FFMAX(ast->sample_size, 1),
-  flags);
+
+if (avi->dv_demux) {
+// index entries are in the AVI scale/rate timebase, which does
+// not match DV demuxer's stream timebase
+timestamp = av_rescale_q(timestamp, st->time_base,
+ (AVRational){ ast->scale, ast->rate });
+} else
+timestamp *= FFMAX(ast->sample_size, 1);
+
+index = av_index_search_timestamp(st, timestamp, flags);
 if (index < 0) {
 if (sti->nb_index_entries > 0)
 av_log(s, AV_LOG_DEBUG, "Failed to find timestamp %"PRId64 " in 
index %"PRId64 " .. %"PRId64 "\n",
-   timestamp * FFMAX(ast->sample_size, 1),
+   timestamp,
sti->index_entries[0].timestamp,
sti->index_entries[sti->nb_index_entries - 1].timestamp);
 return AVERROR_INVALIDDATA;
@@ -1883,7 +1890,7 @@ static int avi_read_seek(AVFormatContext *s, int 
stream_index,
 
 /* find the position */
 pos   = sti->index_entries[index].pos;
-timestamp = sti->index_entries[index].timestamp / FFMAX(ast->sample_size, 
1);
+timestamp = sti->index_entries[index].timestamp;
 
 av_log(s, AV_LOG_TRACE, "XX %"PRId64" %d %"PRId64"\n",
 timestamp, index, sti->index_entries[index].timestamp);
@@ -1898,11 +1905,14 @@ static int avi_read_seek(AVFormatContext *s, int 
stream_index,
 
 /* Feed the DV video stream version of the timestamp to the */
 /* DV demux so it can synthesize correct timestamps.*/
-ff_dv_offset_reset(avi->dv_demux, timestamp);
+ff_dv_ts_reset(avi->dv_demux,
+   av_rescale_q(timestamp, (AVRational){ ast->scale, 
ast->rate },
+st->time_base));
 
 avi->stream_index = -1;
 return 0;
 }
+timestamp /= FFMAX(ast->sample_size, 1);
 
 pos_min = pos;
 for (i = 0; i < s->nb_streams; i++) {
diff --git a/libavformat/dv.c b/libavformat/dv.c
index ffed1a7a90..9888c10b48 100644
--- a/libavformat/dv.c
+++ b/libavformat/dv.c
@@ -69,6 +69,8 @@ struct DVDemuxContext {
 uint8_t   audio_buf[4][8192];
 int   ach;
 int   frames;
+
+int64_t   next_pts_video;
 };
 
 static inline uint16_t dv_audio_12to16(uint16_t sample)
@@ -314,8 +316,6 @@ static int dv_extract_video_info(DVDemuxContext *c, const 
uint8_t *frame)
 
 par = c->vst->codecpar;
 
-avpriv_set_pts_info(c->vst, 64, c->sys->time_base.num,
-c->sys->time_base.den);
 c->vst->avg_frame_rate = av_inv_q(c->vst->time_base);
 
 /* finding out SAR is a little bit messy */
@@ -360,6 +360,8 @@ static int dv_init_demux(AVFormatContext *s, DVDemuxContext 
*c)
 c->vst->codecpar->bit_rate   = 2500;
 c->vst->start_time= 0;
 
+avpriv_set_pts_info(c->vst, 64, 1, DV_TIMESCALE_VIDEO);
+
 /* Audio streams are added later as they are encountered. */
 s->ctx_flags |= AVFMTCTX_NOHEADER;
 
@@ -463,7 +465,10 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket 
*pkt,
 pkt->size = size;
 pkt->flags   |= AV_PKT_FLAG_KEY;
 pkt->stream_index = c->vst->index;
-