Commit 4229e51a authored by Ted Meyer's avatar Ted Meyer Committed by Commit Bot

Uncouple the serializer functions from media_log_properties_helper.

MediaError will take advantage of this change, (which will help explain
the separation of media_serializers_base.h). In the followup CL.

Change-Id: I0048b1d8e8670e62f895d4519bc81ddb6aaf18f2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1979354
Commit-Queue: Ted Meyer <tmathmeyer@chromium.org>
Reviewed-by: default avatarFrank Liberato <liberato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#727281}
parent 9c975776
......@@ -186,6 +186,8 @@ jumbo_source_set("base") {
"media_permission.h",
"media_resource.cc",
"media_resource.h",
"media_serializers.h",
"media_serializers_base.h",
"media_status.cc",
"media_status.h",
"media_status_observer.h",
......@@ -524,6 +526,7 @@ source_set("unit_tests") {
"feedback_signal_accumulator_unittest.cc",
"key_systems_unittest.cc",
"media_log_unittest.cc",
"media_serializers_unittest.cc",
"media_url_demuxer_unittest.cc",
"mime_util_unittest.cc",
"moving_average_unittest.cc",
......
......@@ -8,159 +8,12 @@
#include <string>
#include <vector>
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/video_decoder_config.h"
#include "media/base/media_serializers.h"
#include "ui/gfx/geometry/size.h"
namespace media {
namespace internal {
// Converter struct.
template <typename T>
struct MediaLogPropertyTypeConverter {};
// Some types can be passed to the base::Value constructor.
#define _VALUE_CONSTRUCTOR_TYPE(TEMPLATE_TYPE, PARAM_TYPE) \
template <> \
struct MediaLogPropertyTypeConverter<TEMPLATE_TYPE> { \
static base::Value Convert(PARAM_TYPE value) { \
return base::Value(value); \
} \
}
_VALUE_CONSTRUCTOR_TYPE(std::string, const std::string&);
_VALUE_CONSTRUCTOR_TYPE(bool, bool);
_VALUE_CONSTRUCTOR_TYPE(int, int);
#undef _VALUE_CONSTRUCTOR_TYPE
// Can't send non-finite double values to a base::Value.
template <>
struct MediaLogPropertyTypeConverter<double> {
static base::Value Convert(double value) {
return std::isfinite(value) ? base::Value(value) : base::Value("unknown");
}
};
// Just upcast this to get the NaN check.
template <>
struct MediaLogPropertyTypeConverter<float> {
static base::Value Convert(float value) {
return MediaLogPropertyTypeConverter<double>::Convert(value);
}
};
/* Support serializing for a selection of types */
// support 64 bit ints, this is a weird workaround for the base::Value
// int type only being 32 bit, as specified in the base/values.h header comment.
template <>
struct MediaLogPropertyTypeConverter<int64_t> {
static base::Value Convert(int64_t value) {
return base::Value(static_cast<double>(value));
}
};
// Support gfx::Size -> "{x}x{y}"
template <>
struct MediaLogPropertyTypeConverter<gfx::Size> {
static base::Value Convert(const gfx::Size& value) {
return base::Value(value.ToString());
}
};
// Support vectors of anything else thiat can be serialized
template <typename T>
struct MediaLogPropertyTypeConverter<std::vector<T>> {
static base::Value Convert(const std::vector<T>& value) {
base::Value result(base::Value::Type::LIST);
for (const auto& entry : value)
result.Append(MediaLogPropertyTypeConverter<T>::Convert(entry));
return result;
}
};
// Specializer for sending AudioDecoderConfigs to the media tab in devtools.
template <>
struct internal::MediaLogPropertyTypeConverter<media::AudioDecoderConfig> {
static base::Value Convert(const AudioDecoderConfig& value) {
base::Value result(base::Value::Type::DICTIONARY);
result.SetStringKey("codec", GetCodecName(value.codec()));
result.SetIntKey("bytes per channel", value.bytes_per_channel());
result.SetStringKey("channel layout",
ChannelLayoutToString(value.channel_layout()));
result.SetIntKey("channels", value.channels());
result.SetIntKey("samples per second", value.samples_per_second());
result.SetStringKey("sample format",
SampleFormatToString(value.sample_format()));
result.SetIntKey("bytes per frame", value.bytes_per_frame());
// TODO(tmathmeyer) drop the units, let the frontend handle it.
// use ostringstreams because windows & linux have _different types_
// defined for int64_t, (long vs long long) so format specifiers dont work.
std::ostringstream preroll;
preroll << value.seek_preroll().InMicroseconds() << "us";
result.SetStringKey("seek preroll", preroll.str());
result.SetIntKey("codec delay", value.codec_delay());
result.SetBoolKey("has extra data", !value.extra_data().empty());
std::ostringstream encryptionSchemeString;
encryptionSchemeString << value.encryption_scheme();
result.SetStringKey("encryption scheme", encryptionSchemeString.str());
result.SetBoolKey("discard decoder delay",
value.should_discard_decoder_delay());
return result;
}
};
// Specializer for sending VideoDecoderConfigs to the media tab in devtools.
template <>
struct internal::MediaLogPropertyTypeConverter<VideoDecoderConfig> {
static base::Value Convert(const VideoDecoderConfig& value) {
base::Value result(base::Value::Type::DICTIONARY);
result.SetStringKey("codec", GetCodecName(value.codec()));
result.SetStringKey("profile", GetProfileName(value.profile()));
result.SetStringKey(
"alpha mode",
(value.alpha_mode() == VideoDecoderConfig::AlphaMode::kHasAlpha
? "has_alpha"
: "is_opaque"));
result.SetStringKey("coded size", value.coded_size().ToString());
result.SetStringKey("visible rect", value.visible_rect().ToString());
result.SetStringKey("natural size", value.natural_size().ToString());
result.SetBoolKey("has_extra_data", !value.extra_data().empty());
std::ostringstream encryptionSchemeString;
encryptionSchemeString << value.encryption_scheme();
result.SetStringKey("encryption scheme", encryptionSchemeString.str());
result.SetStringKey("rotation", VideoRotationToString(
value.video_transformation().rotation));
result.SetBoolKey("flipped", value.video_transformation().mirrored);
result.SetStringKey("color space",
value.color_space_info().ToGfxColorSpace().ToString());
if (value.hdr_metadata().has_value()) {
result.SetKey(
"luminance range",
MediaLogPropertyTypeConverter<float>::Convert(
value.hdr_metadata()->mastering_metadata.luminance_min));
result.SetStringKey(
"primaries",
base::StringPrintf(
"[r:%.4f,%.4f, g:%.4f,%.4f, b:%.4f,%.4f, wp:%.4f,%.4f]",
value.hdr_metadata()->mastering_metadata.primary_r.x(),
value.hdr_metadata()->mastering_metadata.primary_r.y(),
value.hdr_metadata()->mastering_metadata.primary_g.x(),
value.hdr_metadata()->mastering_metadata.primary_g.y(),
value.hdr_metadata()->mastering_metadata.primary_b.x(),
value.hdr_metadata()->mastering_metadata.primary_b.y(),
value.hdr_metadata()->mastering_metadata.white_point.x(),
value.hdr_metadata()->mastering_metadata.white_point.y()));
}
return result;
}
};
} // namespace internal
// Forward declare the enum.
enum class MediaLogProperty;
......@@ -173,7 +26,7 @@ struct MediaLogPropertyTypeSupport {};
template <> \
struct MediaLogPropertyTypeSupport<MediaLogProperty::PROPERTY, TYPE> { \
static base::Value Convert(const TYPE& type) { \
return internal::MediaLogPropertyTypeConverter<TYPE>::Convert(type); \
return MediaSerialize<TYPE>(type); \
} \
}
......
// Copyright 2019 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.
#ifndef MEDIA_BASE_MEDIA_SERIALIZERS_H_
#define MEDIA_BASE_MEDIA_SERIALIZERS_H_
#include <vector>
#include "base/strings/stringprintf.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/media_serializers_base.h"
#include "media/base/video_decoder_config.h"
#include "ui/gfx/geometry/size.h"
namespace media {
namespace internal {
// Serializing any const or reference combination.
template <typename T>
struct MediaSerializer<const T> {
static base::Value Serialize(const T& value) {
return MediaSerializer<T>::Serialize(value);
}
};
template <typename T>
struct MediaSerializer<T&> {
static base::Value Serialize(const T& value) {
return MediaSerializer<T>::Serialize(value);
}
};
// Serialize default value.
template <>
struct MediaSerializer<base::Value> {
static base::Value Serialize(const base::Value& value) {
return value.Clone();
}
};
// Serialize vectors of things
template <typename VecType>
struct MediaSerializer<std::vector<VecType>> {
static base::Value Serialize(const std::vector<VecType>& vec) {
base::Value result(base::Value::Type::LIST);
for (const VecType& value : vec)
result.Append(MediaSerializer<VecType>::Serialize(value));
return result;
}
};
// serialize optional types
template <typename OptType>
struct MediaSerializer<base::Optional<OptType>> {
static base::Value Serialize(const base::Optional<OptType>& opt) {
return opt ? MediaSerializer<OptType>::Serialize(opt.value())
: base::Value("unset"); // TODO(tmathmeyer) maybe empty string?
}
};
// Sometimes raw strings wont template match to a char*.
template <int len>
struct MediaSerializer<char[len]> {
static inline base::Value Serialize(const char* code) {
return base::Value(code);
}
};
// Can't send non-finite double values to a base::Value.
template <>
struct MediaSerializer<double> {
static inline base::Value Serialize(double value) {
return std::isfinite(value) ? base::Value(value) : base::Value("unknown");
}
};
template <>
struct MediaSerializer<int64_t> {
static inline base::Value Serialize(int64_t value) {
return MediaSerializer<double>::Serialize(static_cast<double>(value));
}
};
// Just upcast this to get the NaN check.
template <>
struct MediaSerializer<float> {
static inline base::Value Serialize(float value) {
return MediaSerializer<double>::Serialize(value);
}
};
// Serialization for chromium-specific types.
// Each serializer should be commented like:
// Class/Enum (simple/complex)
// where Classes should take constref arguments, and "simple" methods should
// be declared inline.
// the FIELD_SERIALIZE method can be used whenever the result is a dict named
// |result|.
#define FIELD_SERIALIZE(NAME, CONSTEXPR) \
result.SetKey(NAME, MediaSerialize(CONSTEXPR))
// Class (simple)
template <>
struct MediaSerializer<gfx::Size> {
static inline base::Value Serialize(const gfx::Size& value) {
return base::Value(value.ToString());
}
};
// Class (simple)
template <>
struct MediaSerializer<gfx::Rect> {
static inline base::Value Serialize(const gfx::Rect& value) {
return base::Value(value.ToString());
}
};
// Enum (simple)
template <>
struct MediaSerializer<media::AudioCodec> {
static inline base::Value Serialize(media::AudioCodec value) {
return base::Value(GetCodecName(value));
}
};
// Enum (simple)
template <>
struct MediaSerializer<media::VideoCodec> {
static inline base::Value Serialize(media::VideoCodec value) {
return base::Value(GetCodecName(value));
}
};
// Enum (simple)
template <>
struct MediaSerializer<media::VideoCodecProfile> {
static inline base::Value Serialize(media::VideoCodecProfile value) {
return base::Value(GetProfileName(value));
}
};
// Enum (simple)
template <>
struct MediaSerializer<media::ChannelLayout> {
static inline base::Value Serialize(media::ChannelLayout value) {
return base::Value(ChannelLayoutToString(value));
}
};
// Enum (simple)
template <>
struct MediaSerializer<media::SampleFormat> {
static inline base::Value Serialize(media::SampleFormat value) {
return base::Value(SampleFormatToString(value));
}
};
// Enum (complex)
template <>
struct MediaSerializer<media::EncryptionScheme> {
static base::Value Serialize(const media::EncryptionScheme& value) {
std::ostringstream encryptionSchemeString;
encryptionSchemeString << value;
return base::Value(encryptionSchemeString.str());
}
};
// Class (complex)
template <>
struct MediaSerializer<media::VideoTransformation> {
static base::Value Serialize(const media::VideoTransformation& value) {
std::string rotation = VideoRotationToString(value.rotation);
if (value.mirrored)
rotation += ", mirrored";
return base::Value(rotation);
}
};
// Class (simple)
template <>
struct MediaSerializer<media::VideoColorSpace> {
static inline base::Value Serialize(const media::VideoColorSpace& value) {
return base::Value(value.ToGfxColorSpace().ToString());
}
};
// Class (complex)
template <>
struct MediaSerializer<media::HDRMetadata> {
static base::Value Serialize(const media::HDRMetadata& value) {
// TODO(tmathmeyer) serialize more fields here potentially.
base::Value result(base::Value::Type::DICTIONARY);
FIELD_SERIALIZE("luminance range",
base::StringPrintf("%.2f => %.2f",
value.mastering_metadata.luminance_min,
value.mastering_metadata.luminance_max));
FIELD_SERIALIZE("primaries",
base::StringPrintf(
"[r:%.4f,%.4f, g:%.4f,%.4f, b:%.4f,%.4f, wp:%.4f,%.4f]",
value.mastering_metadata.primary_r.x(),
value.mastering_metadata.primary_r.y(),
value.mastering_metadata.primary_g.x(),
value.mastering_metadata.primary_g.y(),
value.mastering_metadata.primary_b.x(),
value.mastering_metadata.primary_b.y(),
value.mastering_metadata.white_point.x(),
value.mastering_metadata.white_point.y()));
return result;
}
};
// Class (complex)
template <>
struct MediaSerializer<media::AudioDecoderConfig> {
static base::Value Serialize(const media::AudioDecoderConfig& value) {
base::Value result(base::Value::Type::DICTIONARY);
FIELD_SERIALIZE("codec", value.codec());
FIELD_SERIALIZE("bytes per channel", value.bytes_per_channel());
FIELD_SERIALIZE("channel layout", value.channel_layout());
FIELD_SERIALIZE("channels", value.channels());
FIELD_SERIALIZE("samples per second", value.samples_per_second());
FIELD_SERIALIZE("sample format", value.sample_format());
FIELD_SERIALIZE("bytes per frame", value.bytes_per_frame());
FIELD_SERIALIZE("codec delay", value.codec_delay());
FIELD_SERIALIZE("has extra data", !value.extra_data().empty());
FIELD_SERIALIZE("encryption scheme", value.encryption_scheme());
FIELD_SERIALIZE("discard decoder delay",
value.should_discard_decoder_delay());
// TODO(tmathmeyer) drop the units, let the frontend handle it.
// use ostringstreams because windows & linux have _different types_
// defined for int64_t, (long vs long long) so format specifiers dont work.
std::ostringstream preroll;
preroll << value.seek_preroll().InMicroseconds() << "us";
result.SetStringKey("seek preroll", preroll.str());
return result;
}
};
// Enum (simple)
template <>
struct MediaSerializer<media::VideoDecoderConfig::AlphaMode> {
static inline base::Value Serialize(
media::VideoDecoderConfig::AlphaMode value) {
return base::Value(value == VideoDecoderConfig::AlphaMode::kHasAlpha
? "has_alpha"
: "is_opaque");
}
};
// Class (complex)
template <>
struct MediaSerializer<media::VideoDecoderConfig> {
static base::Value Serialize(const media::VideoDecoderConfig& value) {
base::Value result(base::Value::Type::DICTIONARY);
FIELD_SERIALIZE("codec", value.codec());
FIELD_SERIALIZE("profile", value.profile());
FIELD_SERIALIZE("alpha mode", value.alpha_mode());
FIELD_SERIALIZE("coded size", value.coded_size());
FIELD_SERIALIZE("visible rect", value.visible_rect());
FIELD_SERIALIZE("natural size", value.natural_size());
FIELD_SERIALIZE("has extra data", !value.extra_data().empty());
FIELD_SERIALIZE("encryption scheme", value.encryption_scheme());
FIELD_SERIALIZE("orientation", value.video_transformation());
FIELD_SERIALIZE("color space", value.color_space_info());
FIELD_SERIALIZE("hdr metadata", value.hdr_metadata());
return result;
}
};
#undef FIELD_SERIALIZE
} // namespace internal
} // namespace media
#endif // MEDIA_BASE_MEDIA_SERIALIZERS_H_
// Copyright 2019 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.
#ifndef MEDIA_BASE_MEDIA_SERIALIZERS_BASE_H_
#define MEDIA_BASE_MEDIA_SERIALIZERS_BASE_H_
#include <vector>
#include "base/values.h"
#include "media/base/media_export.h"
namespace media {
namespace internal {
// Serializer specializer struct.
// All the types that base::Value's constructor can take should be passed
// by non-const values. (int, bool, std::string, char*, etc).
template <typename T>
struct MediaSerializer {
static inline base::Value Serialize(T value) { return base::Value(value); }
};
} // namespace internal
template <typename T>
base::Value MediaSerialize(const T& t) {
return internal::MediaSerializer<T>::Serialize(t);
}
} // namespace media
#endif // MEDIA_BASE_MEDIA_SERIALIZERS_BASE_H_
// Copyright 2016 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/base/media_serializers.h"
#include <memory>
#include "base/json/json_writer.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
std::string ToString(const base::Value& value) {
if (value.is_string()) {
return value.GetString();
}
std::string output_str;
base::JSONWriter::Write(value, &output_str);
return output_str;
}
TEST(MediaSerializersTest, BaseTypes) {
int a = 1;
int64_t b = 2;
bool c = false;
double d = 100;
float e = 4523;
std::string f = "foo";
const char* g = "bar";
ASSERT_EQ(ToString(MediaSerialize(a)), "1");
ASSERT_EQ(ToString(MediaSerialize(b)), "2.0");
ASSERT_EQ(ToString(MediaSerialize(c)), "false");
ASSERT_EQ(ToString(MediaSerialize(d)), "100.0");
ASSERT_EQ(ToString(MediaSerialize(e)), "4523.0");
ASSERT_EQ(ToString(MediaSerialize(f)), "foo");
ASSERT_EQ(ToString(MediaSerialize(g)), "bar");
ASSERT_EQ(ToString(MediaSerialize("raw string")), "raw string");
}
TEST(MediaSerializersTest, Optional) {
base::Optional<int> foo;
ASSERT_EQ(ToString(MediaSerialize(foo)), "unset");
foo = 1;
ASSERT_EQ(ToString(MediaSerialize(foo)), "1");
}
TEST(MediaSerializersTest, Vector) {
std::vector<int> foo = {1, 2, 3, 6, 78, 8};
ASSERT_EQ(ToString(MediaSerialize(foo)), "[1,2,3,6,78,8]");
std::vector<std::string> bar = {"1", "3"};
ASSERT_EQ(ToString(MediaSerialize(bar)), "[\"1\",\"3\"]");
}
} // namespace media
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment