| Index: media/base/video_codecs.cc
|
| diff --git a/media/base/video_codecs.cc b/media/base/video_codecs.cc
|
| index 7b3f77f04ecc451e2b831f010c47ea7a6ab26030..9e60cb66e900f4bfe92b4bc82c51b479f70962a8 100644
|
| --- a/media/base/video_codecs.cc
|
| +++ b/media/base/video_codecs.cc
|
| @@ -5,6 +5,8 @@
|
| #include "media/base/video_codecs.h"
|
|
|
| #include "base/logging.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_util.h"
|
|
|
| namespace media {
|
|
|
| @@ -69,4 +71,96 @@ std::string GetProfileName(VideoCodecProfile profile) {
|
| return "";
|
| }
|
|
|
| +bool ParseAVCCodecId(const std::string& codec_id,
|
| + VideoCodecProfile* profile,
|
| + uint8_t* level_idc) {
|
| + // Make sure we have avc1.xxxxxx or avc3.xxxxxx , where xxxxxx are hex digits
|
| + if (!base::StartsWith(codec_id, "avc1.", base::CompareCase::SENSITIVE) &&
|
| + !base::StartsWith(codec_id, "avc3.", base::CompareCase::SENSITIVE)) {
|
| + return false;
|
| + }
|
| + uint32_t elem = 0;
|
| + if (codec_id.size() != 11 ||
|
| + !base::HexStringToUInt(base::StringPiece(codec_id).substr(5), &elem)) {
|
| + DVLOG(4) << __FUNCTION__ << ": invalid avc codec id (" << codec_id << ")";
|
| + return false;
|
| + }
|
| +
|
| + uint8_t level_byte = elem & 0xFF;
|
| + uint8_t constraints_byte = (elem >> 8) & 0xFF;
|
| + uint8_t profile_idc = (elem >> 16) & 0xFF;
|
| +
|
| + // Check that the lower two bits of |constraints_byte| are zero (those are
|
| + // reserved and must be zero according to ISO IEC 14496-10).
|
| + if (constraints_byte & 3) {
|
| + DVLOG(4) << __FUNCTION__ << ": non-zero reserved bits in codec id "
|
| + << codec_id;
|
| + return false;
|
| + }
|
| +
|
| + VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
|
| + // profile_idc values for each profile are taken from ISO IEC 14496-10 and
|
| + // https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles
|
| + switch (profile_idc) {
|
| + case 66:
|
| + out_profile = H264PROFILE_BASELINE;
|
| + break;
|
| + case 77:
|
| + out_profile = H264PROFILE_MAIN;
|
| + break;
|
| + case 83:
|
| + out_profile = H264PROFILE_SCALABLEBASELINE;
|
| + break;
|
| + case 86:
|
| + out_profile = H264PROFILE_SCALABLEHIGH;
|
| + break;
|
| + case 88:
|
| + out_profile = H264PROFILE_EXTENDED;
|
| + break;
|
| + case 100:
|
| + out_profile = H264PROFILE_HIGH;
|
| + break;
|
| + case 110:
|
| + out_profile = H264PROFILE_HIGH10PROFILE;
|
| + break;
|
| + case 118:
|
| + out_profile = H264PROFILE_MULTIVIEWHIGH;
|
| + break;
|
| + case 122:
|
| + out_profile = H264PROFILE_HIGH422PROFILE;
|
| + break;
|
| + case 128:
|
| + out_profile = H264PROFILE_STEREOHIGH;
|
| + break;
|
| + case 244:
|
| + out_profile = H264PROFILE_HIGH444PREDICTIVEPROFILE;
|
| + break;
|
| + default:
|
| + DVLOG(1) << "Warning: unrecognized AVC/H.264 profile " << profile_idc;
|
| + return false;
|
| + }
|
| +
|
| + // TODO(servolk): Take into account also constraint set flags 3 through 5.
|
| + uint8_t constraint_set0_flag = (constraints_byte >> 7) & 1;
|
| + uint8_t constraint_set1_flag = (constraints_byte >> 6) & 1;
|
| + uint8_t constraint_set2_flag = (constraints_byte >> 5) & 1;
|
| + if (constraint_set2_flag && out_profile > H264PROFILE_EXTENDED) {
|
| + out_profile = H264PROFILE_EXTENDED;
|
| + }
|
| + if (constraint_set1_flag && out_profile > H264PROFILE_MAIN) {
|
| + out_profile = H264PROFILE_MAIN;
|
| + }
|
| + if (constraint_set0_flag && out_profile > H264PROFILE_BASELINE) {
|
| + out_profile = H264PROFILE_BASELINE;
|
| + }
|
| +
|
| + if (level_idc)
|
| + *level_idc = level_byte;
|
| +
|
| + if (profile)
|
| + *profile = out_profile;
|
| +
|
| + return true;
|
| +}
|
| +
|
| } // namespace media
|
|
|