Repository navigation
Add VFR support to ratecontrol and slicetype, fix HRD timing. - #966
Conversation
7d554ee to
cb0ed1e
Compare
|
@mcw-Lavanya Ready for review. I don't know why only some debug VC smoke test fails. The same test pass on non-debug binaries. |
|
Hi @cubicibo, thanks for the detailed writeup on this — really nice work threading frame duration through the whole ratecontrol/slicetype/cuTree chain. I dug into the Windows Debug + --bitrate smoke test failures a bit, and I have a suspicion about where it's coming from. Wanted to flag it humbly since I could be missing context on your side. In ratecontrol.cpp, the constructor (RateControl::RateControl()) used to have: cpp In commit bc7e03c ("ratecontrol: support arbitrary timebases for VFR"), this line looks like it was replaced with: cpp But m_fps (declared in ratecontrol.h, no default initializer) still seems to be read in several places later in the file, e.g.: If I'm reading it right, m_fps is never reassigned anywhere else, so those reads are of an uninitialized member. That would explain the pattern you're seeing pretty well — MSVC's debug CRT poisons freshly allocated memory, so an uninitialized double there would come back with garbage in Debug but often "accidentally work" in Release. And since m_fps is only touched in the ABR/VBV/CBR paths, it'd only bite --bitrate runs, not CRF/CQP ones. Could well be I'm missing an initializer somewhere else in the flow — if so, apologies for the noise! But if it checks out, restoring something like: cpp right next to the new m_timebase line seems like it should clear it up. |
92282fb to
15fb730
Compare
|
Thank you, a bad oversight of mine. Unfortunately that does not solve it. |
0001-ratecontrol-initialize-m_durationDone.patch Hi @cubicibo , |
362c835 to
c209d50
Compare
|
Hi @cubicibo , Thank you |
|
Hi @cubicibo, |
|
Hi @cubicibo , Thank you |
|
I have found one more conformance issue. However it is present in the master branch, it does not come from this PR. x265 bitstreams sometime breach Equation C-18 (§ C.4). This is not a problem for most decoders using the H.222 leak method... but it still needs fixing. I will try to address it in another PR first. Regarding your question: Test set-up & toolings
I have included a readme to the Python HRD verifier. You are free to make any use of it. Command lines
Evaluation
With command line 2) on an arbitrary video: |
Thank you @cubicibo , we will verify from our end and get back to you |
|
Hi @cubicibo , |
b7ac8ef to
f32ac41
Compare
| H0(" Format of each line: framenum ffo picstruct.\n"); | ||
| H0(" ffo is the frame field order (0: progressive, 1: bff, 2: tff) and shall match the encode settings.\n"); | ||
| H0(" picstruct value, from H.265 Table D.2 enumeration, shall be compatible with the encode settings.\n"); | ||
| H0(" --log2-max-poc-lsb <integer> Maximum of the picture order count\n"); |
There was a problem hiding this comment.
Hi @cubicibo ,
May I know why this line of code is repeated
|
Hi @cubicibo , |
|
Apologies, I will revert that commit. I had figured it was an easier entry-point to most users contrary to the --ps-file. |
c9d6246 to
9cfe575
Compare
ce0b5a9 to
e552e3b
Compare
|
Hi @cubicibo, Thank you for the updated PR and all the work on it. While testing, I ran into a segmentation fault with temporal layers and wanted to share it in case it helps. Command:
What I saw: master : encodes all 60 frames without problems. Where I think the problem might be (I may be wrong): for (int i = 0; i <= bframes; ++i) might then read an invalid index. With --keyint 25 and 15 B-frames, the GOP ends in a partial mini-GOP around frame 24, which seems to match where it crashes. If that’s the cause, keeping one running counter for codedFrameOrderedIndex across all sub-GOPs (separate from the per-sub-GOP pts index), and looping calculateDurations over that count, might fix it. I may well be missing something, so please correct me if this isn’t it. The existing regression test --temporal-layers 5 --b-adapt 0 --keyint 50 may also hit this path. Thank you! |
|
Thank you for the report. It should be fixed with the last push with cleaned-up commit history, in e03c6b2 |
|
Hi @cubicibo, With --psfile, a pic struct value keeps applying to every following frame until the next line in the file. For example, with: 0 0 0 the single 23 0 7 line makes frames 23–39 all use pic_struct 7. We confirmed this with trace_headers: 28 frames carry 7, although only frames 10, 21 and 23 list it. Could you confirm whether this is intended? If it is intended, i.e. each line sets the structure “from this frame onwards”, which is convenient for pulldown sections: If it is not intended, i.e. each line applies only to that one frame: With --temporal-layers 3 --hrd, the global --pic-struct 7 is correctly ignored (pic_struct is all 0, with a warning).
m_durationDone - frameNumThreads + 1 is computed in uint64_t, so for the first few frames it wraps to about 1.8e19 instead of going negative. 3. x265 --input BasketballDrive_1920x1080_50.y4m --intra-refresh --hrd --vbv-bufsize 2000 --vbv-maxrate 1500 --bitrate 1200 --keyint 30 --frames 150
The BP positions are identical, but the PR never restarts the delay. With
Suggested fix: compute the delay relative to the last BP at the point where the BP SEI is written, as master did with Related: the intra-refresh period still counts frames (
With --interlace tff --hrd --pic-struct 7, every field is signalled as pic_struct 7, and there is no warning. Could you please check the points above and let us know your thoughts? Thank you for your quick responses on the earlier fixes. Thank you |
1165c4f to
2176a19
Compare
|
Thank you very much for the exhaustive testing. I have addressed all of the above.
I went with a reset to PIC_STRUCT_AUTO for every input pic without an entry in the psfile. Carrying the structure would cause orphaned fields with interlaced content. The encoder aborts whenever psfile + temporal layers or interlacing are used together. Interlace + psfile support will come in a separate PR.
Fixed, it had to be done in encoder.cpp, not in frameencoder because those are threaded. I made PIR operate on the tick count, not frame count as suggested. I also tested with intra-refresh + qpfile with forced keyframes and auCpbRemovalDelayMinus1 looked correct.
Prevented & fixed. Only element missing is preventing structure 3,4,5,6 on field sequences. I will push that once this pipeline succeed. |
|
Hi @cubicibo, Thank you for the latest update (4d16988). The interlaced pic-struct handling and the We have a few final points to clear before we can approve: 1. Encodes with alpha or multiview layers get the wrong timing In
None of the CI jobs builds with Suggested fix: give every layer the same timestamp and advance the clock once per access unit, for example after the layer loop: 2.
The same thing happens for libx265 API users who set Suggested fix:
3. Documentation
Once these are in, please rebase on the current master (the branch is 3 commits behind) so CI runs on the final head. We'll approve after that. Thank you! |
d31de56 to
d0ee0e9
Compare
Set the frame duration based on its target pic_struct. The frame duration will affect and be used by slicetype and ratecontrol.
Set the CPB and DPB timing of each picture whenever its coded order is decided. Ratecontrol uses the CPB and display duration to improve a frame's bit budgeting.
Weight-in the CPB duration in clock tick of a picture for ratecontrol and bit budgeting. The assumption of a constant frame rate is dropped and replaced by a constant timebase in line with the VUI timing info.
Define keyframes on the clock ticks intervals rather than an absolute count of frames. It is otherwise impossible to enforce a keyframe at a reasonable time interval with VFR or pulldown. Preserves the legacy behaviour: a frame lasts a single clock tick.
mcw-Lavanya
left a comment
There was a problem hiding this comment.
Thank you for the updated code, LGTM


Internal:
User interface:
--pic-structand--frame-dupnow produce conformant bitstreams.--psfileto specify arbitrary pulldown patterns ("VFR-in-CFR" container).Limitation:
--frames(totalFrames) is defined, because this does not convey a duration.