Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ffmpeg: Rescale DTS better during FPS passthrough #416

Merged
merged 1 commit into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ffmpeg/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,9 @@ static int encode(AVCodecContext* encoder, AVFrame *frame, struct output_ctx* oc
if (AVMEDIA_TYPE_VIDEO == ost->codecpar->codec_type && !octx->fps.den && octx->vf.active) {
// try to preserve source timestamps for fps passthrough.
time_base = octx->vf.time_base;
int64_t pts_dts_diff = pkt->pts - pkt->dts;
pkt->pts = (int64_t)pkt->opaque; // already in filter timebase
pkt->dts = av_rescale_q(pkt->dts, encoder->time_base, time_base);
pkt->dts = pkt->pts - av_rescale_q(pts_dts_diff, encoder->time_base, time_base);
}
ret = mux(pkt, time_base, octx, ost);
if (ret < 0) goto encode_cleanup;
Expand Down
69 changes: 69 additions & 0 deletions ffmpeg/ffmpeg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,75 @@ func TestTranscoder_PassthroughFPS(t *testing.T) {
run(cmd)
}

func TestTranscoder_PassthroughFPS_AdjustTimestamps(t *testing.T) {
// check timestamp adjustments for fps passthrough

run, dir := setupTest(t)
defer os.RemoveAll(dir)

cmd := `
ffmpeg -i "$1/../transcoder/test.ts" -an -c:v copy -t 0.5 test-short.ts
ffprobe -loglevel warning -show_entries frame=pts,duration -of csv=p=0 test-short.ts | grep -v '^$' > expected-frame-pts.out
wc -l expected-frame-pts.out | grep "32 expected-frame-pts.out"
cat << EXPECTED_TS_EOF > expected-pkt-ts.out
pts,dts,duration
128970,125970,1500
134910,127410,1500
131940,128940,1500
130500,130500,1500
133380,131880,1500
137970,133470,1500
136440,134940,1500
143910,136410,1500
140940,137940,1500
139410,139410,1500
142470,140970,1500
149940,142440,1500
146970,143970,1500
145440,145440,1500
148500,147000,1500
155970,148470,1500
152910,149910,1500
151380,151380,1500
154440,152940,1500
161910,154410,1500
158940,155940,1500
157410,157410,1500
160470,158970,1500
167940,160440,1500
164970,161970,1500
163440,163440,1500
166500,165000,1500
173970,166470,1500
170910,167910,1500
169380,169380,1500
172440,170940,1500
176940,172440,1500
EXPECTED_TS_EOF
`
run(cmd)

in := &TranscodeOptionsIn{Fname: dir + "/test-short.ts"}
out := []TranscodeOptions{{Profile: P144p30fps16x9}}
out[0].Profile.Framerate = 0 // Passthrough!
out[0].Profile.Profile = ProfileH264High
out[0].Oname = dir + "/out-0.ts"
_, err := Transcode3(in, out)
require.Nil(t, err)
cmd = `
echo "pts,dts,duration" > received-pkt-ts.out
ffprobe -loglevel warning -show_entries packet=pts,dts,duration,pict_type -of csv=p=0 out-0.ts | grep -v '^$' | sed 's/,*$//g' >> received-pkt-ts.out
ffprobe -loglevel warning -show_entries frame=pts,duration -of csv=p=0 test-short.ts | grep -v '^$' > received-frame-pts.out

# ensure packet pts+dts matches what is expected
diff -u expected-pkt-ts.out received-pkt-ts.out

# ensure all pts are accounted for from original
diff -u expected-frame-pts.out received-frame-pts.out
`
run(cmd)
}

func TestTranscoder_FormatOptions(t *testing.T) {
// Test combinations of VideoProfile.Format and TranscodeOptions.Muxer
// The former takes precedence over the latter if set
Expand Down
Loading