Skip to content

Commit

Permalink
AV1-in-MP4 codec string not shown in Show Media Stats
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=265405
rdar://118850797

Reviewed by Eric Carlson.

Support extracting AV1 codec configuration information from the FormatDescription.

* Source/WebCore/platform/graphics/AV1Utilities.cpp:
(WebCore::parseAV1DecoderConfigurationRecord):
* Source/WebCore/platform/graphics/AV1Utilities.h:
* Source/WebCore/platform/graphics/avfoundation/FormatDescriptionUtilities.cpp:
(WebCore::codecFromFormatDescription):

Canonical link: https://commits.webkit.org/271187@main
  • Loading branch information
jernoble committed Nov 28, 2023
1 parent e1b3b68 commit e5529df
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 0 deletions.
85 changes: 85 additions & 0 deletions Source/WebCore/platform/graphics/AV1Utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,89 @@ bool validateAV1PerLevelConstraints(const AV1CodecConfigurationRecord& record, c
&& configuration.bitrate <= maxBitrate;
}

std::optional<AV1CodecConfigurationRecord> parseAV1DecoderConfigurationRecord(const SharedBuffer& buffer)
{
// Ref: https://aomediacodec.github.io/av1-isobmff/
// Section 2.3: AV1 Codec Configuration Box

// AV1CodecConfigurationRecord is at least 4 bytes long
if (buffer.size() < 4)
return std::nullopt;

AV1CodecConfigurationRecord record;

// aligned(8) class AV1CodecConfigurationRecord
// {
// unsigned int(1) marker = 1;
// unsigned int(7) version = 1;
// unsigned int(3) seq_profile;
// unsigned int(5) seq_level_idx_0;
// unsigned int(1) seq_tier_0;
// unsigned int(1) high_bitdepth;
// unsigned int(1) twelve_bit;
// unsigned int(1) monochrome;
// unsigned int(1) chroma_subsampling_x;
// unsigned int(1) chroma_subsampling_y;
// unsigned int(2) chroma_sample_position;
// unsigned int(3) reserved = 0;
//
// unsigned int(1) initial_presentation_delay_present;
// if(initial_presentation_delay_present) {
// unsigned int(4) initial_presentation_delay_minus_one;
// } else {
// unsigned int(4) reserved = 0;
// }
//
// unsigned int(8) configOBUs[];
// }

auto arrayBuffer = buffer.tryCreateArrayBuffer();
if (!arrayBuffer)
return std::nullopt;

bool status = true;
auto view = JSC::DataView::create(WTFMove(arrayBuffer), 0, buffer.size());

auto profileLevel = view->get<uint8_t>(1, false, &status);
if (!status)
return std::nullopt;

if (!isValidEnum<AV1ConfigurationProfile>((profileLevel & 0b11100000) >> 5))
return std::nullopt;
record.profile = static_cast<AV1ConfigurationProfile>((profileLevel & 0b11100000) >> 5);

if (!isValidEnum<AV1ConfigurationLevel>(profileLevel & 0b00011111))
return std::nullopt;
record.level = static_cast<AV1ConfigurationLevel>(profileLevel & 0b00011111);


auto tierBitdepthAndColorFlags = view->get<uint8_t>(2, false, &status);
if (!status)
return std::nullopt;

record.tier = tierBitdepthAndColorFlags & 0b10000000 ? AV1ConfigurationTier::High : AV1ConfigurationTier::Main;
bool highBitDepth = tierBitdepthAndColorFlags & 0b01000000;
bool twelveBit = tierBitdepthAndColorFlags & 0b00100000;
if (!highBitDepth && twelveBit)
return std::nullopt;

if (highBitDepth && twelveBit)
record.bitDepth = 12;
else if (highBitDepth)
record.bitDepth = 10;
else
record.bitDepth = 8;

record.monochrome = tierBitdepthAndColorFlags & 0b00010000;
uint8_t chromaSubsamplingValue = 0;
if (tierBitdepthAndColorFlags & 0b00001000)
chromaSubsamplingValue += 100;
if (tierBitdepthAndColorFlags & 0b00000100)
chromaSubsamplingValue += 10;
chromaSubsamplingValue += tierBitdepthAndColorFlags & 0b00000010;
record.chromaSubsampling = chromaSubsamplingValue;

return record;
}

}
2 changes: 2 additions & 0 deletions Source/WebCore/platform/graphics/AV1Utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ WEBCORE_EXPORT String createAV1CodecParametersString(const AV1CodecConfiguration

WEBCORE_EXPORT bool validateAV1PerLevelConstraints(const AV1CodecConfigurationRecord&, const VideoConfiguration&);

std::optional<AV1CodecConfigurationRecord> parseAV1DecoderConfigurationRecord(const SharedBuffer&);

}

namespace WTF {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "config.h"
#include "FormatDescriptionUtilities.h"

#import "AV1Utilities.h"
#import "FloatSize.h"
#import "FourCC.h"
#import "HEVCUtilities.h"
Expand Down Expand Up @@ -183,6 +184,22 @@ String codecFromFormatDescription(CMFormatDescriptionRef formatDescription)
return "ec-3"_s;
case 'dts ':
return "dts"_s;
#if ENABLE(AV1)
case kCMVideoCodecType_AV1:
{
auto sampleExtensionsDict = static_cast<CFDictionaryRef>(PAL::CMFormatDescriptionGetExtension(formatDescription, PAL::get_CoreMedia_kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms()));
if (!sampleExtensionsDict)
return "av01"_s;
auto sampleExtensions = static_cast<CFDataRef>(CFDictionaryGetValue(sampleExtensionsDict, CFSTR("av1C")));
if (!sampleExtensions)
return "av01"_s;
auto configurationRecordBuffer = SharedBuffer::create(sampleExtensions);
auto parameters = parseAV1DecoderConfigurationRecord(configurationRecordBuffer);
if (!parameters)
return "av01"_s;
return createAV1CodecParametersString(*parameters);
}
#endif
}

return emptyString();
Expand Down

0 comments on commit e5529df

Please sign in to comment.