Param 'high-tier' ignores my intention at lower bitrates

Issue #103 resolved
Former user created an issue

Specifying 'high-tier' and having a bitrate that is under Main-tier's ceiling signals Main in the PTL. I believe it's acceptable to have a low bitrate High tier video.

I'm not sure if encoding is performed as per High tier or not in this case.

I'm not reading the docs as if this is intended behavior too. Example case, I want Main10, 5.1, high tier, 40Mbps.

--high-tier If --level-idc has been specified, the option adds the intention to support the High tier of that level. If your specified level does not support a High tier, a warning is issued and this modifier flag is ignored.

level.cpp

if (bitrate > levels[i].maxBitrateMain && bitrate <= levels[i].maxBitrateHigh &&
      levels[i].maxBitrateHigh != MAX_UINT)
      vps.ptl.tierFlag = Level::HIGH;
else
      vps.ptl.tierFlag = Level::MAIN;

Comments (12)

  1. Deepthi Nandakumar

    "I'm not sure if encoding is performed as per High tier or not in this case." Not sure what you mean by encoding performed per high tier.

    Let me see if I understand the issue correctly. Since you've specified --high-tier, you would like VPS to also set the High Tier Flag, regardless of the bitrate settings. There is no reason for x265 or any other encoder to mark a bitstream as belonging to a higher tier than it actually does, since this will now increase the decoder specifications unnecessarily.

  2. Former user Account Deleted

    No worries, let me try again, I have new information now.

    I had a feeling that the param section might have diverged where some code would use ptl=main-tier and others param=high-tier. For example, SPS would signal cpb parameters for main-tier and the video used up to high-tier. I hadn't check and thought it important enough to note. This is where my debugging began, a bitstream had failed general tier and level limit A.4.1.(i), see below.

    I understand marking at lowest tier possible and I will not argue. This ticket is more for the confusion of one user rather than to support forcing "high-tier". However, I would prefer to be able to force high tier anyway and the docs read as if you'll get high-tier as long as your level supports it. I don't see how this would impact the decoder specifications.

    Here's the new information:

    • Params
      • Main10
      • 5.1
      • Main
      • bitrate = 40000
      • vbv-bufsize = 45000
      • vbv-maxrate = 40000
    • Signaled
      • Main10
      • 5.1
      • Main
      • CpbSize (cpb_size_value, cpb_scale) = 45M
    • Issues
      • General tier and level limit A.4.1.(i):
      • CpbSize shall be <= CpbBrNalFactor * MaxCPB = 1100 * 40M = 44M (failed)

    I'm able to specify a high-tier vbv-bufsize when the video is signaled as main-tier (ptl.tierFlag).

    I'm not triggering the "lowering VBV buffer size" warning in level.cpp because I've specified the high-tier directive. The tier flag is set after and independent of the high-tier directive in determineLevel() based upon the specified bitrate. I think the ptl.tierFlag should take vbv parameters into account, tier is more than bitrate.

    I think the assignment in the second 'if' in the code below should be param.rc.vbvBufferSize instead of vbvMaxBitrate.

    Let me know if I've completely lost you!

    level.cpp
    #!c++
        if ((uint32_t)param.rc.vbvMaxBitrate > (highTier ? l.maxBitrateHigh : l.maxBitrateMain))
        {
            param.rc.vbvMaxBitrate = highTier ? l.maxBitrateHigh : l.maxBitrateMain;
            x265_log(&param, X265_LOG_INFO, "lowering VBV max bitrate to %dKbps\n", param.rc.vbvMaxBitrate);
        }
        if ((uint32_t)param.rc.vbvBufferSize > (highTier ? l.maxCpbSizeHigh : l.maxCpbSizeMain))
        {
            param.rc.vbvMaxBitrate = highTier ? l.maxCpbSizeHigh : l.maxCpbSizeMain;
            x265_log(&param, X265_LOG_INFO, "lowering VBV buffer size to %dKb\n", param.rc.vbvBufferSize);
        }   
    
  3. Former user Account Deleted

    It also appears that the levelIdc signaled in the parameter sets is independent of --level-idc and the actual level selected is always automatically detected (apt.cpp::determineLevel()). The lower level (combined with the tier) has priority and one can be given 5 high-tier when 5.1 main-tier is specified via CLI/API parameters, for instance.

  4. Deepthi Nandakumar

    " However, I would prefer to be able to force high tier anyway and the docs read as if you'll get high-tier as long as your level supports it. I don't see how this would impact the decoder specifications."

    Both the level-idc and high-tier options function as additional information to the encoder, describing the decoder specifications. They are not treated as encoder directives to encode the video at that level/tier, and this is clear in the documents (IMO, but please point me to any specific comments that are confusing).

    In case the user specified a lower decoder level than what was detected, the encoder will attempt to reduce parameters to adhere to that level, but this attempt could fail. In case the user specified a higher level/tier than what was detected for that encode, the encoder will do nothing. What is signaled in VPS is always the actual (detected) level, not level-idc.

    The tier and level limit failed issue you mentioned looks like a bug. Let me look into this.

  5. Deepthi Nandakumar

    Fixed the first bug you'd reported that was causing tier/level violations.

    Also emailed a patch for low-level, high-tier, being given preference over higher level main-tier. I'll wait for some review comments before pushing this in.

  6. Alex Bishop

    Roger, only actual/detected is signaled.

    The conformance failure is most important, I think, and is the root cause for reporting this ticket.

    Please let me know what comes out of preference-patch email, this is still a concern of mine. My use case is often not to generate the "cheapest" video but rather a specified PTL one so, auto-downgrading is problematic if not caught. I have fight with x265 to agree to signal my target PTL, too many degrees of freedom. I'm beginning to worry that there are unreachable PTL tuples, likely connected to the low-level/high-tier preference.

    Do you know if information matching Encoder::m_vps.ptl.{tierFlag, levelIdc} is accessible while using the API? I would like to implement a trip wire for mismatches (user intention vs. x265's decision) on my end (without having to link in a bitstream parser.)

    "If --level-idc has been specified, the option adds the intention to support the High tier of that level. If your specified level does not support a High tier, a warning is issued and this modifier flag is ignored."
    

    For --high-tier, it reads to me that the only case high-tier will be ignored is when the level does not support a high-tier.

    "If the requested requirement level is higher than the actual level, the actual requirement level is signaled."
    

    On the other hand, --level-idc is clear to me (which applies to --high-tier by association?):

    Would x265 be receptive/permit adding a --force-ptl directive? Checking for completeness for management on my end.

  7. Deepthi Nandakumar

    Hi, the conformance failure has been fixed, and we've also pushed the preference patch, now x265 chooses high tier only if the determined level is equal to or greater than levelIdc.

  8. Former user Account Deleted
    • changed status to open

    Resolution does not completely cover issue.

    Instance below shows a Main10, Level 4, Main Tier signaling:

    • CPBSize = 45M (MaxCPBSize = 12M)
    • BR = 20M (MaxBR = 12M)

    Would prefer x265 to not automatically select level and tier but rather provide warning, recommendation and then exit. I suspect there are more corner cases.

    x265 
    --input park_joy_420_720p50.y4m 
    --input-res 1280x720 
    --fps 59.94 
    -o out.265 
    --preset 1 
    --high-tier 
    --log-level 2 
    --profile main10 
    --level-idc 4.1 
    --keyint 20 
    --vbv-bufsize 45000 
    --vbv-maxrate 20000 
    --repeat-headers 
    --hrd 
    --aud 
    --sar 1 
    --bitrate 20000
    
    y4m  [info]: 1280x720 fps 59940/1000 i420p8 sar 1:1 frames 0 - 499 of 500
    x265 [info]: HEVC encoder version 1.5+24-89f5e1f88d40
    x265 [info]: build info [Windows][MSVC 1600][64 bit] 16bpp
    x265 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX
    x265 [info]: Main 10 profile, Level-4 (Main tier)
    x265 [info]: WPP streams / frame threads / pool  : 23 / 3 / 12
    x265 [info]: Internal bit depth                  : 10
    x265 [info]: Coding QT: max CU size, min CU size : 32 / 8
    x265 [info]: Residual QT: max TU size, max depth : 32 / 1 inter / 1 intra
    x265 [info]: ME / range / subpel / merge         : hex / 44 / 1 / 2
    x265 [info]: Keyframe min / max / scenecut       : 2 / 20 / 40
    x265 [info]: Lookahead / bframes / badapt        : 10 / 4 / 0
    x265 [info]: b-pyramid / weightp / weightb / refs: 1 / 0 / 0 / 1
    x265 [info]: Rate Control / AQ-Strength / CUTree : ABR-20000 kbps / 0.0 / 0
    x265 [info]: VBV/HRD buffer / max-rate / init    : 45000 / 20000 / 0.900
    x265 [info]: tools: rd=2 psy-rd=0.30 early-skip deblock signhide fast-intra tmvp
    x265 [info]: frame I:     25, Avg QP:28.23  kb/s: 89890.67
    x265 [info]: frame P:     76, Avg QP:29.92  kb/s: 45628.52
    x265 [info]: frame B:    399, Avg QP:31.71  kb/s: 11769.47
    x265 [info]: global :    500, Avg QP:31.27  kb/s: 20822.10
    x265 [info]: consecutive B-frames: 1.0% 0.0% 0.0% 1.0% 98.0%
    
    encoded 500 frames in 19.56s (25.57 fps), 20822.10 kb/s
    
  9. Log in to comment