Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Write colr atom to muxed MP4 when present in input AV1 file #1251

2 changes: 1 addition & 1 deletion packager/hls/base/master_playlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ void BuildMediaTag(const MediaPlaylist& playlist,
if (is_default) {
tag.AddString("DEFAULT", "YES");
} else {
tag.AddString("DEFAULT", "NO");
tag.AddString("DEFAULT", "NO");
}

if (is_autoselect) {
Expand Down
37 changes: 20 additions & 17 deletions packager/media/formats/mp4/box_definitions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1470,26 +1470,28 @@ FourCC ColorParameters::BoxType() const {
}

bool ColorParameters::ReadWriteInternal(BoxBuffer* buffer) {
if (buffer->reader()) {
RCHECK((buffer->reader())->ReadFourCC(&color_parameter_type) &&
(buffer->reader())->Read2(&color_primaries) &&
(buffer->reader())->Read2(&transfer_characteristics) &&
(buffer->reader())->Read2(&matrix_coefficients));
// Type nclc does not contain video_full_range_flag data, and thus, it has 1
// less byte than nclx. Only extract video_full_range_flag if of type nclx.
if (color_parameter_type == FOURCC_nclx) {
RCHECK((buffer->reader())->Read1(&video_full_range_flag));
}
RCHECK(ReadWriteHeaderInternal(buffer) &&
buffer->ReadWriteFourCC(&color_parameter_type) &&
buffer->ReadWriteUInt16(&color_primaries) &&
buffer->ReadWriteUInt16(&transfer_characteristics) &&
buffer->ReadWriteUInt16(&matrix_coefficients));
// Type nclc does not contain video_full_range_flag data, and thus, it has 1
// less byte than nclx. Only extract video_full_range_flag if of type nclx.
if (color_parameter_type == FOURCC_nclx) {
RCHECK(buffer->ReadWriteUInt8(&video_full_range_flag));
}
// TODO(caitlinocallaghan) Add the ability to write the colr atom and include
// it in the muxed mp4.
return true;
}

size_t ColorParameters::ComputeSizeInternal() {
// This box is optional. Skip it if it is not initialized.
if (color_parameter_type == FOURCC_NULL)
if (color_parameter_type == FOURCC_NULL) {
// This box is optional. Skip it if it is not initialized.
return 0;
} else if (color_parameter_type == FOURCC_nclc) {
// Type nclc does not contain video_full_range_flag data.
return HeaderSize() + kFourCCSize + sizeof(color_primaries) +
sizeof(transfer_characteristics) + sizeof(matrix_coefficients);
}
return HeaderSize() + kFourCCSize + sizeof(color_primaries) +
sizeof(transfer_characteristics) + sizeof(matrix_coefficients) +
sizeof(video_full_range_flag);
Expand Down Expand Up @@ -1652,9 +1654,10 @@ size_t VideoSampleEntry::ComputeSizeInternal() {
size_t size = HeaderSize() + sizeof(data_reference_index) + sizeof(width) +
sizeof(height) + sizeof(kVideoResolution) * 2 +
sizeof(kVideoFrameCount) + sizeof(kVideoDepth) +
pixel_aspect.ComputeSize() + sinf.ComputeSize() +
codec_configuration.ComputeSize() + kCompressorNameSize + 6 +
4 + 16 + 2; // 6 + 4 bytes reserved, 16 + 2 bytes predefined.
colr.ComputeSize() + pixel_aspect.ComputeSize() +
sinf.ComputeSize() + codec_configuration.ComputeSize() +
kCompressorNameSize + 6 + 4 + 16 +
2; // 6 + 4 bytes reserved, 16 + 2 bytes predefined.
for (CodecConfiguration& codec_config : extra_codec_configs)
size += codec_config.ComputeSize();
return size;
Expand Down
31 changes: 31 additions & 0 deletions packager/media/formats/mp4/mp4_muxer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <algorithm>

#include "packager/base/strings/string_number_conversions.h"
#include "packager/base/strings/string_split.h"
#include "packager/base/time/clock.h"
#include "packager/base/time/time.h"
#include "packager/file/file.h"
Expand Down Expand Up @@ -429,6 +430,36 @@ bool MP4Muxer::GenerateVideoTrak(const VideoStreamInfo* video_info,
VideoSampleEntry video;
video.format =
CodecToFourCC(video_info->codec(), video_info->h26x_stream_format());
if (video.format == FOURCC_av01) {
auto av1_color_info =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having to parse these back out of the codec string doesn't feel like the right solution

base::SplitString(video_info->codec_string(), ".",
base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (av1_color_info.size() == 10) {
// Extract colr atom info if the full AV1 codec string is available.
// https://aomediacodec.github.io/av1-isobmff/#codecsparam
// <sample entry 4CC>.<profile>.<level><tier>.<bitDepth>.<monochrome>.
// <chromaSubsampling>.<colorPrimaries>.<transferCharacteristics>.
// <matrixCoefficients>.<videoFullRangeFlag>
unsigned int color_primaries;
unsigned int transfer_characteristics;
unsigned int matrix_coefficients;
unsigned int video_full_range_flag;
video.colr.color_parameter_type = FOURCC_nclx;
if (base::StringToUint(av1_color_info[6], &color_primaries)) {
video.colr.color_primaries = color_primaries;
}
if (base::StringToUint(av1_color_info[7], &transfer_characteristics)) {
video.colr.transfer_characteristics = transfer_characteristics;
}
if (base::StringToUint(av1_color_info[8], &matrix_coefficients)) {
video.colr.matrix_coefficients = matrix_coefficients;
}
if (base::StringToUint(av1_color_info[9], &video_full_range_flag)) {
video.colr.video_full_range_flag = video_full_range_flag;
}
}
}

video.width = video_info->width();
video.height = video_info->height();
video.codec_configuration.data = video_info->codec_config();
Expand Down
Loading