| // Copyright 2018 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "media/video/h264_level_limits.h" | 
 |  | 
 | #include "base/logging.h" | 
 | #include "media/video/h264_parser.h" | 
 |  | 
 | namespace media { | 
 | namespace { | 
 | struct LevelLimits { | 
 |   // All names and abbreviations are as in table A-1 in spec. | 
 |   // MaxMBPS, Max. macroblock processing rate (MB/s) | 
 |   uint32_t max_mbps; | 
 |   // MaxFS, Max. frame size (MBs) | 
 |   uint32_t max_fs; | 
 |   // MaxDpbMbs, Max. decoded picture buffer size (MBs) | 
 |   uint32_t max_dpb_mbs; | 
 |   // MaxBR, Max. video bitrate for Baseline and Main Profiles (kbit/s) | 
 |   uint32_t max_main_br; | 
 | }; | 
 |  | 
 | LevelLimits LevelToLevelLimits(uint8_t level) { | 
 |   // See table A-1 in spec | 
 |   // { MaxMBPS, MaxFS, MaxDpbMbs, MaxBR} | 
 |   switch (level) { | 
 |     case H264SPS::kLevelIDC1p0: | 
 |       return {1485, 99, 396, 64};  // Level 1.0 | 
 |     case H264SPS::kLevelIDC1B: | 
 |       return {1485, 99, 396, 128};  // Level 1b | 
 |     case H264SPS::kLevelIDC1p1: | 
 |       return {3000, 396, 900, 192};  // Level 1.1 | 
 |     case H264SPS::kLevelIDC1p2: | 
 |       return {6000, 396, 2376, 384};  // Level 1.2 | 
 |     case H264SPS::kLevelIDC1p3: | 
 |       return {11800, 396, 2376, 768};  // Level 1.3 | 
 |     case H264SPS::kLevelIDC2p0: | 
 |       return {11880, 396, 2376, 2000};  // Level 2.0 | 
 |     case H264SPS::kLevelIDC2p1: | 
 |       return {19800, 792, 4752, 4000};  // Level 2.1 | 
 |     case H264SPS::kLevelIDC2p2: | 
 |       return {20250, 1620, 8100, 4000};  // Level 2.2 | 
 |     case H264SPS::kLevelIDC3p0: | 
 |       return {40500, 1620, 8100, 10000};  // Level 3.0 | 
 |     case H264SPS::kLevelIDC3p1: | 
 |       return {108000, 3600, 18000, 14000};  // Level 3.1 | 
 |     case H264SPS::kLevelIDC3p2: | 
 |       return {216000, 5120, 20480, 20000};  // Level 3.2 | 
 |     case H264SPS::kLevelIDC4p0: | 
 |       return {245760, 8192, 32768, 20000};  // Level 4.0 | 
 |     case H264SPS::kLevelIDC4p1: | 
 |       return {245760, 8192, 32768, 50000};  // Level 4.1 | 
 |     case H264SPS::kLevelIDC4p2: | 
 |       return {522240, 8704, 34816, 50000};  // Level 4.2 | 
 |     case H264SPS::kLevelIDC5p0: | 
 |       return {589824, 22080, 110400, 135000};  // Level 5.0 | 
 |     case H264SPS::kLevelIDC5p1: | 
 |       return {983040, 36864, 184320, 240000};  // Level 5.1 | 
 |     case H264SPS::kLevelIDC5p2: | 
 |       return {2073600, 36864, 184320, 240000};  // Level 5.2 | 
 |     case H264SPS::kLevelIDC6p0: | 
 |       return {4177920, 139264, 696320, 240000};  // Level 6.0 | 
 |     case H264SPS::kLevelIDC6p1: | 
 |       return {8355840, 139264, 696320, 480000};  // Level 6.1 | 
 |     case H264SPS::kLevelIDC6p2: | 
 |       return {16711680, 139264, 696320, 800000};  // Level 6.2 | 
 |     default: | 
 |       DVLOG(1) << "Invalid codec level (" << static_cast<int>(level) << ")"; | 
 |       return {0, 0, 0, 0}; | 
 |   } | 
 | } | 
 | }  // namespace | 
 |  | 
 | uint32_t H264LevelToMaxMBPS(uint8_t level) { | 
 |   return LevelToLevelLimits(level).max_mbps; | 
 | } | 
 |  | 
 | uint32_t H264LevelToMaxFS(uint8_t level) { | 
 |   return LevelToLevelLimits(level).max_fs; | 
 | } | 
 |  | 
 | uint32_t H264LevelToMaxDpbMbs(uint8_t level) { | 
 |   return LevelToLevelLimits(level).max_dpb_mbs; | 
 | } | 
 |  | 
 | uint32_t H264ProfileLevelToMaxBR(VideoCodecProfile profile, uint8_t level) { | 
 |   uint32_t max_main_br = LevelToLevelLimits(level).max_main_br; | 
 |  | 
 |   // See table A-2 in spec | 
 |   // The maximum bit rate for High Profile is 1.25 times that of the | 
 |   // Base/Extended/Main Profiles, 3 times for Hi10P, and 4 times for | 
 |   // Hi422P/Hi444PP. | 
 |   switch (profile) { | 
 |     case H264PROFILE_BASELINE: | 
 |     case H264PROFILE_MAIN: | 
 |     case H264PROFILE_EXTENDED: | 
 |       return max_main_br; | 
 |     case H264PROFILE_HIGH: | 
 |       return max_main_br * 5 / 4; | 
 |     case H264PROFILE_HIGH10PROFILE: | 
 |       return max_main_br * 3; | 
 |     case H264PROFILE_HIGH422PROFILE: | 
 |     case H264PROFILE_HIGH444PREDICTIVEPROFILE: | 
 |       return max_main_br * 4; | 
 |     default: | 
 |       DVLOG(1) << "Failed to query MaxBR for profile: " | 
 |                << GetProfileName(profile); | 
 |       return 0; | 
 |   } | 
 | } | 
 |  | 
 | bool CheckH264LevelLimits(VideoCodecProfile profile, | 
 |                           uint8_t level, | 
 |                           uint32_t bitrate, | 
 |                           uint32_t framerate, | 
 |                           uint32_t framesize_in_mbs) { | 
 |   uint32_t max_bitrate_kbs = H264ProfileLevelToMaxBR(profile, level); | 
 |   DCHECK(base::IsValueInRangeForNumericType<uint32_t>(max_bitrate_kbs * 1000)); | 
 |  | 
 |   uint32_t max_bitrate = max_bitrate_kbs * 1000; | 
 |   if (bitrate > max_bitrate) { | 
 |     DVLOG(1) << "Target bitrate: " << bitrate << " exceeds Max: " << max_bitrate | 
 |              << " bit/s"; | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (framesize_in_mbs > H264LevelToMaxFS(level)) { | 
 |     DVLOG(1) << "Target frame size: " << framesize_in_mbs | 
 |              << " exceeds Max: " << H264LevelToMaxFS(level) << " Macroblocks"; | 
 |     return false; | 
 |   } | 
 |  | 
 |   uint32_t mbps = framesize_in_mbs * framerate; | 
 |   if (mbps > H264LevelToMaxMBPS(level)) { | 
 |     DVLOG(1) << "Target macroblock processing rate: " << mbps | 
 |              << " exceeds Max: " << H264LevelToMaxMBPS(level) << "Macroblock/s"; | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | absl::optional<uint8_t> FindValidH264Level(VideoCodecProfile profile, | 
 |                                            uint32_t bitrate, | 
 |                                            uint32_t framerate, | 
 |                                            uint32_t framesize_in_mbs) { | 
 |   constexpr uint8_t kH264Levels[] = { | 
 |       H264SPS::kLevelIDC1p0, H264SPS::kLevelIDC1B,  H264SPS::kLevelIDC1p1, | 
 |       H264SPS::kLevelIDC1p2, H264SPS::kLevelIDC1p3, H264SPS::kLevelIDC2p0, | 
 |       H264SPS::kLevelIDC2p1, H264SPS::kLevelIDC2p2, H264SPS::kLevelIDC3p0, | 
 |       H264SPS::kLevelIDC3p1, H264SPS::kLevelIDC3p2, H264SPS::kLevelIDC4p0, | 
 |       H264SPS::kLevelIDC4p1, H264SPS::kLevelIDC4p2, H264SPS::kLevelIDC5p0, | 
 |       H264SPS::kLevelIDC5p1, H264SPS::kLevelIDC5p2, H264SPS::kLevelIDC6p0, | 
 |       H264SPS::kLevelIDC6p1, H264SPS::kLevelIDC6p2, | 
 |   }; | 
 |  | 
 |   for (const uint8_t level : kH264Levels) { | 
 |     if (CheckH264LevelLimits(profile, level, bitrate, framerate, | 
 |                              framesize_in_mbs)) { | 
 |       return level; | 
 |     } | 
 |   } | 
 |   return absl::nullopt; | 
 | } | 
 |  | 
 | }  // namespace media |