PR #25661 opened by florianmodel
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25661
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25661.patch

DV input is currently reported as 60000 fps, which breaks frame-count-based 
progress and ETA calculations in applications such as HandBrake. This fixes 
[FFmpeg ticket #11339](https://trac.ffmpeg.org/ticket/11339), reported by Dave 
Rice, and the upstream cause of [HandBrake 
#6635](https://github.com/HandBrake/HandBrake/issues/6635) / 
[#6474](https://github.com/HandBrake/HandBrake/issues/6474).

Since c7a852b638b88f129790af31fc47c870c329eaaa, the DV stream time base is 
fixed at 1/60000. Inverting it to set avg_frame_rate therefore yields 60000/1 
for every profile. Derive avg_frame_rate from the current DV profile time base 
instead, as already done for packet duration and bitrate. The fix also covers 
the shared demuxer used by Type 1 DV-in-AVI.

Reproduce on the unmodified master:

```sh
./ffmpeg -y -f lavfi -i testsrc2=size=720x480:rate=30000/1001 -frames:v 3 -c:v 
dvvideo -pix_fmt yuv411p -chroma_sample_location topleft -f dv test.dv
./ffprobe -v error -select_streams v:0 -show_entries 
stream=avg_frame_rate,time_base test.dv
```

Before: avg_frame_rate=60000/1. After: avg_frame_rate=30000/1001. The stream 
time base remains 1/60000.

Validation against master a88838af48 on macOS arm64:

- Four new sample-free FATE tests cover PAL, NTSC, 720p50 and 720p60, checking 
average frame rate, stream time base, packet PTS and duration. All fail before 
the fix and pass after it.
- `make -j8 fate`: 3078 tests passed. The separate FATE sample archive was not 
configured, so sample-dependent tests were not run.
- Generated raw DV and Type 1 DV-in-AVI (video-only AVI with embedded DV audio, 
stream header changed from vids to iavs) both change from 60000/1 to 
30000/1001. Every demuxed packet, including audio, compares identically before 
and after the fix. A Type 2 AVI control retains 30000/1001.
- `git diff --check` passes. `tools/patcheck` was attempted but encounters BSD 
grep/xargs portability errors on macOS.

Development and testing were performed with AI assistance (OpenAI Codex).


>From 72fc2e960f37ff76e24df572553cf403975a7f01 Mon Sep 17 00:00:00 2001
From: florianmodel <[email protected]>
Date: Sun, 1 Nov 2026 17:30:42 +0000
Subject: [PATCH] avformat/dv: derive average frame rate from the DV profile

Since c7a852b638b88f129790af31fc47c870c329eaaa, the DV demuxer uses a
fixed 1/60000 video time base. Inverting that time base therefore sets
avg_frame_rate to 60000/1 for every DV profile, rather than the actual
frame rate. This also affects Type 1 DV in AVI and leads to incorrect
frame counts and progress estimates in applications such as HandBrake.

Use the profile time base to derive avg_frame_rate, as is already done
for packet duration and bitrate. Keep the stream time base unchanged.

Add sample-free FATE tests for PAL, NTSC, 720p50 and 720p60 DV. Check the
average frame rate, stream time base, packet timestamps and durations.
All four tests fail before this change and pass with it.

Fixes: c7a852b638b88f129790af31fc47c870c329eaaa
Fixes: ticket #11339
Reported-by: Dave Rice
Signed-off-by: FModel <[email protected]>
---
 libavformat/dv.c                   |  2 +-
 tests/fate/dvvideo.mak             | 21 ++++++++++++++++++++-
 tests/ref/fate/dv-framerate-720p50 |  4 ++++
 tests/ref/fate/dv-framerate-720p60 |  4 ++++
 tests/ref/fate/dv-framerate-ntsc   |  4 ++++
 tests/ref/fate/dv-framerate-pal    |  4 ++++
 6 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 tests/ref/fate/dv-framerate-720p50
 create mode 100644 tests/ref/fate/dv-framerate-720p60
 create mode 100644 tests/ref/fate/dv-framerate-ntsc
 create mode 100644 tests/ref/fate/dv-framerate-pal

diff --git a/libavformat/dv.c b/libavformat/dv.c
index 84677284bdf..733e7093a10 100644
--- a/libavformat/dv.c
+++ b/libavformat/dv.c
@@ -319,7 +319,7 @@ static int dv_extract_video_info(DVDemuxContext *c, const 
uint8_t *frame)
 
     par = c->vst->codecpar;
 
-    c->vst->avg_frame_rate = av_inv_q(c->vst->time_base);
+    c->vst->avg_frame_rate = av_inv_q(c->sys->time_base);
 
     /* finding out SAR is a little bit messy */
     vsc_pack = dv_extract_pack(frame, DV_VIDEO_CONTROL);
diff --git a/tests/fate/dvvideo.mak b/tests/fate/dvvideo.mak
index 33686d7762b..5656cfa21f8 100644
--- a/tests/fate/dvvideo.mak
+++ b/tests/fate/dvvideo.mak
@@ -5,4 +5,23 @@ fate-bsf-dv-error-marker: REF = 
3190a334b1ceef2d9fd050a1590da7c6
 FATE_DVVIDEO-$(call ALLYES, MOV_DEMUXER DV_ERROR_MARKER_BSF NOISE_BSF 
AVI_MUXER) += fate-bsf-dv-error-marker
 
 FATE_SAMPLES_FFMPEG += $(FATE_DVVIDEO-yes)
-fate-dvvideo: $(FATE_DVVIDEO-yes)
+
+FATE_DVVIDEO_PROBE-$(call ENCDEC, DVVIDEO, DV, LAVFI_INDEV TESTSRC2_FILTER 
SCALE_FILTER \
+                                           FORMAT_FILTER 
WRAPPED_AVFRAME_DECODER) += fate-dv-framerate-pal   \
+                                                                               
     fate-dv-framerate-ntsc  \
+                                                                               
     fate-dv-framerate-720p50 \
+                                                                               
     fate-dv-framerate-720p60
+
+fate-dv-framerate-pal:    DV_OPTS = -s 720x576 -r 25 -pix_fmt yuv420p
+fate-dv-framerate-ntsc:   DV_OPTS = -s 720x480 -r 30000/1001 -pix_fmt yuv411p
+fate-dv-framerate-720p50: DV_OPTS = -s 960x720 -r 50 -pix_fmt yuv422p
+fate-dv-framerate-720p60: DV_OPTS = -s 960x720 -r 60000/1001 -pix_fmt yuv422p
+
+$(FATE_DVVIDEO_PROBE-yes): CMD = run_with_temp \
+    "$(FFMPEG) -nostdin -hide_banner -loglevel error -f lavfi -i testsrc2 
-frames:v 3 \
+    -c:v dvvideo $(DV_OPTS) -threads 1 -flags +bitexact -fflags +bitexact -f 
dv -y" \
+    "ffprobe$(PROGSSUF)$(EXESUF) -v error -bitexact -select_streams v \
+    -show_entries stream=avg_frame_rate,time_base:packet=pts,duration -of 
compact" dv
+
+FATE_FFMPEG_FFPROBE += $(FATE_DVVIDEO_PROBE-yes)
+fate-dvvideo: $(FATE_DVVIDEO-yes) $(FATE_DVVIDEO_PROBE-yes)
diff --git a/tests/ref/fate/dv-framerate-720p50 
b/tests/ref/fate/dv-framerate-720p50
new file mode 100644
index 00000000000..a91ae11921b
--- /dev/null
+++ b/tests/ref/fate/dv-framerate-720p50
@@ -0,0 +1,4 @@
+packet|pts=0|duration=1200
+packet|pts=1200|duration=1200
+packet|pts=2400|duration=1200
+stream|avg_frame_rate=50/1|time_base=1/60000
diff --git a/tests/ref/fate/dv-framerate-720p60 
b/tests/ref/fate/dv-framerate-720p60
new file mode 100644
index 00000000000..36309615f15
--- /dev/null
+++ b/tests/ref/fate/dv-framerate-720p60
@@ -0,0 +1,4 @@
+packet|pts=0|duration=1001
+packet|pts=1001|duration=1001
+packet|pts=2002|duration=1001
+stream|avg_frame_rate=60000/1001|time_base=1/60000
diff --git a/tests/ref/fate/dv-framerate-ntsc b/tests/ref/fate/dv-framerate-ntsc
new file mode 100644
index 00000000000..273f1020902
--- /dev/null
+++ b/tests/ref/fate/dv-framerate-ntsc
@@ -0,0 +1,4 @@
+packet|pts=0|duration=2002
+packet|pts=2002|duration=2002
+packet|pts=4004|duration=2002
+stream|avg_frame_rate=30000/1001|time_base=1/60000
diff --git a/tests/ref/fate/dv-framerate-pal b/tests/ref/fate/dv-framerate-pal
new file mode 100644
index 00000000000..8273a819718
--- /dev/null
+++ b/tests/ref/fate/dv-framerate-pal
@@ -0,0 +1,4 @@
+packet|pts=0|duration=2400
+packet|pts=2400|duration=2400
+packet|pts=4800|duration=2400
+stream|avg_frame_rate=25/1|time_base=1/60000
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to