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

**Brief**
If no valid timestamp is given to h264_parse, resort to buffering period and 
picture timing SEIs.

This extends the existing logic reconstructing missing timestamps for 
containers with discontinuities, such as MPEG-TS. Whenever the container, or 
the raw bitstream is decoded without any PTS and DTS indication, it's better to 
return the Picture Timing SEI information than never do anything with it.

Containers that give a PTS, a DTS, or both, are not affected by this change.

I did not offset the timestamps by the `initial_cpb_removal_delay` because this 
is generally a muxer concern, but that's open for discussion.


>From 27bc241b7be2ea14bdace1f50cd91a16e7169afd Mon Sep 17 00:00:00 2001
From: cubicibo <[email protected]>
Date: Thu, 5 Nov 2026 11:15:43 +0100
Subject: [PATCH] lavc h264: use picture timing if neither PTS or DTS are
 valid.

---
 libavcodec/h264_parser.c | 8 ++++++++
 libavcodec/h264_sei.c    | 5 ++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
index 1bd0be38a53..5534725ddd3 100644
--- a/libavcodec/h264_parser.c
+++ b/libavcodec/h264_parser.c
@@ -653,9 +653,17 @@ static int h264_parse(AVCodecParserContext *s,
             if (s->dts != AV_NOPTS_VALUE) {
                 // got DTS from the stream, update reference timestamp
                 p->reference_dts = av_sat_sub64(s->dts, 
av_rescale(s->dts_ref_dts_delta, num, den));
+            } else if (s->pts != AV_NOPTS_VALUE) {
+                // container only has a PTS, guess DTS
+                s->dts = av_sat_sub64(s->pts, av_rescale(s->pts_dts_delta, 
num, den));
+                p->reference_dts = av_sat_sub64(s->dts, 
av_rescale(s->dts_ref_dts_delta, num, den));
             } else if (p->reference_dts != AV_NOPTS_VALUE) {
                 // compute DTS based on reference timestamp
                 s->dts = av_sat_add64(p->reference_dts, 
av_rescale(s->dts_ref_dts_delta, num, den));
+            } else if (s->dts_sync_point > 0) {
+                // both pts and dts are unset but we have a buffering period: 
initialize
+                p->reference_dts = 0;
+                s->dts = av_rescale(s->dts_ref_dts_delta, num, den);
             }
 
             if (p->reference_dts != AV_NOPTS_VALUE && s->pts == 
AV_NOPTS_VALUE) {
diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c
index 6819fb75c40..ec560ce47b8 100644
--- a/libavcodec/h264_sei.c
+++ b/libavcodec/h264_sei.c
@@ -188,7 +188,10 @@ static int decode_buffering_period(H264SEIBufferingPeriod 
*h, GetBitContext *gb,
             skip_bits(gb, sps->initial_cpb_removal_delay_length);
         }
     }
-    if (sps->vcl_hrd_parameters_present_flag) {
+
+    /* H.264 C.3 NOTE 1 claims that NAL HRD has precedence over VCL HRD for 
decoding and
+     * conformance aspects. Type I (VCL) is a subset of Type II (both VCL and 
non-VCL) */
+    if (sps->vcl_hrd_parameters_present_flag && 
!sps->nal_hrd_parameters_present_flag) {
         for (sched_sel_idx = 0; sched_sel_idx < sps->cpb_cnt; sched_sel_idx++) 
{
             h->initial_cpb_removal_delay[sched_sel_idx] =
                 get_bits_long(gb, sps->initial_cpb_removal_delay_length);
-- 
2.54.0

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

Reply via email to