[media] Add aspect ratio to VideoDecoderConfig
This CL introduces VideoAspectRatio, which contains either a display aspect ratio or a pixel aspect ratio. VideoDecoderConfig gains a new aspect_ratio() method replacing GetPixelAspectRatio(), and all callers of GetNaturalSize() are converted to use it. Bug: 1213667 Change-Id: I0d1226e7dfedf62e45ef8e11aa1485bdad76d59d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2923231 Commit-Queue: Dan Sanders <sandersd@chromium.org> Reviewed-by: Dale Curtis <dalecurtis@chromium.org> Reviewed-by: Chrome Cunningham <chcunningham@chromium.org> Cr-Commit-Position: refs/heads/master@{#889466}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
edc3e86f1d
commit
068c5a4fbf
media
base
BUILD.gnvideo_aspect_ratio.ccvideo_aspect_ratio.hvideo_aspect_ratio_unittest.ccvideo_decoder_config.ccvideo_decoder_config.hvideo_decoder_config_unittest.ccvideo_util.ccvideo_util.hvideo_util_unittest.cc
cdm
ffmpeg
filters
dav1d_video_decoder.ccffmpeg_video_decoder.cc
fuchsia
gav1_video_decoder.ccgav1_video_decoder.hvpx_video_decoder.ccformats
gpu
@ -313,6 +313,8 @@ source_set("base") {
|
||||
"use_after_free_checker.h",
|
||||
"user_input_monitor.cc",
|
||||
"user_input_monitor.h",
|
||||
"video_aspect_ratio.cc",
|
||||
"video_aspect_ratio.h",
|
||||
"video_bitrate_allocation.cc",
|
||||
"video_bitrate_allocation.h",
|
||||
"video_codecs.cc",
|
||||
@ -612,6 +614,7 @@ source_set("unit_tests") {
|
||||
"unaligned_shared_memory_unittest.cc",
|
||||
"user_input_monitor_unittest.cc",
|
||||
"vector_math_unittest.cc",
|
||||
"video_aspect_ratio_unittest.cc",
|
||||
"video_bitrate_allocation_unittest.cc",
|
||||
"video_codecs_unittest.cc",
|
||||
"video_color_space_unittest.cc",
|
||||
|
81
media/base/video_aspect_ratio.cc
Normal file
81
media/base/video_aspect_ratio.cc
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2021 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/video_aspect_ratio.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
namespace media {
|
||||
|
||||
VideoAspectRatio::VideoAspectRatio(Type type, int width, int height) {
|
||||
type_ = type;
|
||||
aspect_ratio_ = height ? double{width} / height : 0.0;
|
||||
}
|
||||
|
||||
// static
|
||||
VideoAspectRatio VideoAspectRatio::PAR(int width, int height) {
|
||||
return VideoAspectRatio(Type::kPixel, width, height);
|
||||
}
|
||||
|
||||
// static
|
||||
VideoAspectRatio VideoAspectRatio::DAR(int width, int height) {
|
||||
return VideoAspectRatio(Type::kDisplay, width, height);
|
||||
}
|
||||
|
||||
VideoAspectRatio::VideoAspectRatio(const gfx::Rect& visible_rect,
|
||||
const gfx::Size& natural_size) {
|
||||
// The size of a pixel is:
|
||||
// (natural_width / visible_width) by (natural_height / visible_height).
|
||||
// Both are multiplied by (visible_width * visible_height) to avoid division.
|
||||
double w = double{visible_rect.height()} * natural_size.width();
|
||||
double h = double{visible_rect.width()} * natural_size.height();
|
||||
|
||||
type_ = Type::kPixel;
|
||||
aspect_ratio_ = h != 0.0 ? w / h : 0.0;
|
||||
}
|
||||
|
||||
bool VideoAspectRatio::IsValid() const {
|
||||
return std::isfinite(aspect_ratio_) && aspect_ratio_ > 0.0;
|
||||
}
|
||||
|
||||
gfx::Size VideoAspectRatio::GetNaturalSize(
|
||||
const gfx::Rect& visible_rect) const {
|
||||
if (!IsValid() || visible_rect.IsEmpty())
|
||||
return visible_rect.size();
|
||||
|
||||
double w = visible_rect.width();
|
||||
double h = visible_rect.height();
|
||||
switch (type_) {
|
||||
case Type::kDisplay:
|
||||
if (aspect_ratio_ >= w / h) {
|
||||
// Display aspect is wider, grow width.
|
||||
w = h * aspect_ratio_;
|
||||
} else {
|
||||
// Display aspect is narrower, grow height.
|
||||
h = w / aspect_ratio_;
|
||||
}
|
||||
break;
|
||||
|
||||
case Type::kPixel:
|
||||
if (aspect_ratio_ >= 1.0) {
|
||||
// Wide pixels, grow width.
|
||||
w = w * aspect_ratio_;
|
||||
} else {
|
||||
// Narrow pixels, grow height.
|
||||
h = h / aspect_ratio_;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
w = std::round(w);
|
||||
h = std::round(h);
|
||||
if (w < 1.0 || w > std::numeric_limits<int>::max() || h < 1.0 ||
|
||||
h > std::numeric_limits<int>::max()) {
|
||||
return visible_rect.size();
|
||||
}
|
||||
return gfx::Size(w, h);
|
||||
}
|
||||
|
||||
} // namespace media
|
61
media/base/video_aspect_ratio.h
Normal file
61
media/base/video_aspect_ratio.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2021 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_VIDEO_ASPECT_RATIO_H_
|
||||
#define MEDIA_BASE_VIDEO_ASPECT_RATIO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "media/base/media_export.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
namespace media {
|
||||
|
||||
class MEDIA_EXPORT VideoAspectRatio {
|
||||
public:
|
||||
// Create a pixel aspect ratio (PAR). |width| and |height| describe the
|
||||
// shape of a pixel. For example, an anamorphic video has regtangular pixels
|
||||
// with a 2:1 PAR, that is they are twice as wide as they are tall.
|
||||
//
|
||||
// Note that this is also called a sample aspect ratio (SAR), but SAR can also
|
||||
// mean storage aspect ratio (which is the coded size).
|
||||
static VideoAspectRatio PAR(int width, int height);
|
||||
|
||||
// Create a display aspect ratio (DAR). |width| and |height| describe the
|
||||
// shape of the rendered picture. For example a 1920x1080 video with square
|
||||
// pixels has a 1920:1080 = 16:9 DAR.
|
||||
static VideoAspectRatio DAR(int width, int height);
|
||||
|
||||
// A default-constructed VideoAspectRatio is !IsValid().
|
||||
VideoAspectRatio() = default;
|
||||
|
||||
// Create a VideoAspectRatio from a known |natural_size|.
|
||||
// TODO(crbug.com/1214061): Remove.
|
||||
VideoAspectRatio(const gfx::Rect& visible_rect,
|
||||
const gfx::Size& natural_size);
|
||||
|
||||
// An aspect ratio is invalid if it was default constructed, had nonpositive
|
||||
// components, or exceeds implementation limits.
|
||||
bool IsValid() const;
|
||||
|
||||
// Computes the expected display size for a given visible size.
|
||||
// Returns visible_rect.size() if !IsValid().
|
||||
gfx::Size GetNaturalSize(const gfx::Rect& visible_rect) const;
|
||||
|
||||
private:
|
||||
enum class Type {
|
||||
kDisplay,
|
||||
kPixel,
|
||||
};
|
||||
|
||||
VideoAspectRatio(Type type, int width, int height);
|
||||
|
||||
Type type_ = Type::kDisplay;
|
||||
double aspect_ratio_ = 0.0;
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
|
||||
#endif // MEDIA_BASE_VIDEO_ASPECT_RATIO_H_
|
73
media/base/video_aspect_ratio_unittest.cc
Normal file
73
media/base/video_aspect_ratio_unittest.cc
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2021 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/video_aspect_ratio.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
namespace media {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr gfx::Rect kRect_4_3(0, 0, 4, 3);
|
||||
constexpr gfx::Rect kRect_16_9(0, 0, 16, 9);
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(VideoAspectRatioTest, DefaultConstruction) {
|
||||
VideoAspectRatio aspect_ratio;
|
||||
EXPECT_FALSE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(16, 9));
|
||||
}
|
||||
|
||||
TEST(VideoAspectRatioTest, FromNaturalSize) {
|
||||
VideoAspectRatio aspect_ratio;
|
||||
|
||||
aspect_ratio = VideoAspectRatio(kRect_16_9, gfx::Size(16, 9));
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(16, 9));
|
||||
|
||||
aspect_ratio = VideoAspectRatio(kRect_4_3, gfx::Size(16, 9));
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_4_3), gfx::Size(5, 3));
|
||||
|
||||
aspect_ratio = VideoAspectRatio(kRect_16_9, gfx::Size(4, 3));
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(16, 12));
|
||||
}
|
||||
|
||||
TEST(VideoAspectRatioTest, Pixel) {
|
||||
VideoAspectRatio aspect_ratio;
|
||||
|
||||
aspect_ratio = VideoAspectRatio::PAR(1, 1);
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(16, 9));
|
||||
|
||||
aspect_ratio = VideoAspectRatio::PAR(1, 2);
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(16, 18));
|
||||
|
||||
aspect_ratio = VideoAspectRatio::PAR(2, 1);
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(32, 9));
|
||||
}
|
||||
|
||||
TEST(VideoAspectRatioTest, Display) {
|
||||
VideoAspectRatio aspect_ratio;
|
||||
|
||||
aspect_ratio = VideoAspectRatio::DAR(1, 1);
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(16, 16));
|
||||
|
||||
aspect_ratio = VideoAspectRatio::DAR(1, 2);
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(16, 32));
|
||||
|
||||
aspect_ratio = VideoAspectRatio::DAR(2, 1);
|
||||
EXPECT_TRUE(aspect_ratio.IsValid());
|
||||
EXPECT_EQ(aspect_ratio.GetNaturalSize(kRect_16_9), gfx::Size(18, 9));
|
||||
}
|
||||
|
||||
} // namespace media
|
@ -62,6 +62,7 @@ void VideoDecoderConfig::Initialize(VideoCodec codec,
|
||||
coded_size_ = coded_size;
|
||||
visible_rect_ = visible_rect;
|
||||
natural_size_ = natural_size;
|
||||
aspect_ratio_ = VideoAspectRatio(visible_rect, natural_size);
|
||||
extra_data_ = extra_data;
|
||||
encryption_scheme_ = encryption_scheme;
|
||||
color_space_info_ = color_space;
|
||||
@ -131,10 +132,6 @@ std::string VideoDecoderConfig::GetHumanReadableCodecName() const {
|
||||
return GetCodecName(codec());
|
||||
}
|
||||
|
||||
double VideoDecoderConfig::GetPixelAspectRatio() const {
|
||||
return ::media::GetPixelAspectRatio(visible_rect_, natural_size_);
|
||||
}
|
||||
|
||||
void VideoDecoderConfig::SetExtraData(const std::vector<uint8_t>& extra_data) {
|
||||
extra_data_ = extra_data;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "base/macros.h"
|
||||
#include "media/base/encryption_scheme.h"
|
||||
#include "media/base/media_export.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_codecs.h"
|
||||
#include "media/base/video_color_space.h"
|
||||
#include "media/base/video_transformation.h"
|
||||
@ -99,33 +100,20 @@ class MEDIA_EXPORT VideoDecoderConfig {
|
||||
// aperture. Usually, but not always, origin-aligned (top-left).
|
||||
const gfx::Rect& visible_rect() const { return visible_rect_; }
|
||||
|
||||
// DEPRECATED: Use aspect_ratio().GetNaturalSize().
|
||||
// TODO(crbug.com/1214061): Remove.
|
||||
// Final visible width and height of a video frame with aspect ratio taken
|
||||
// into account. Image data in the visible_rect() should be scaled to this
|
||||
// size for display.
|
||||
const gfx::Size& natural_size() const { return natural_size_; }
|
||||
|
||||
// The shape of encoded pixels. Given visible_rect() and a pixel aspect ratio,
|
||||
// it is possible to compute natural_size() (see video_util.h).
|
||||
//
|
||||
// SUBTLE: "pixel aspect ratio" != "display aspect ratio". *Pixel* aspect
|
||||
// ratio describes the shape of a *pixel* as the ratio of its width to its
|
||||
// height (ex: anamorphic video may have rectangular pixels). *Display* aspect
|
||||
// ratio is natural_width / natural_height.
|
||||
//
|
||||
// CONTRACT: Dynamic changes to *pixel* aspect ratio are not supported unless
|
||||
// done with explicit signal (new init-segment in MSE). Streams may still
|
||||
// change their frame sizes dynamically, including their *display* aspect
|
||||
// ratio. But, at this time (2019) changes to pixel aspect ratio are not
|
||||
// surfaced by all platform decoders (ex: MediaCodec), so non-support is
|
||||
// chosen for cross platform consistency. Hence, natural size should always be
|
||||
// computed by scaling visbilte_size by the *pixel* aspect ratio from the
|
||||
// container metadata. See GetNaturalSize() in video_util.h.
|
||||
//
|
||||
// TODO(crbug.com/837337): This should be explicitly set (replacing
|
||||
// |natural_size|). Alternatively, this could be replaced by
|
||||
// GetNaturalSize(visible_rect), with pixel aspect ratio being an internal
|
||||
// detail of the config.
|
||||
double GetPixelAspectRatio() const;
|
||||
// The aspect ratio parsed from the container. Decoders may override using
|
||||
// in-band metadata only if !aspect_ratio().IsValid().
|
||||
const VideoAspectRatio& aspect_ratio() const { return aspect_ratio_; }
|
||||
|
||||
void set_aspect_ratio(const VideoAspectRatio& aspect_ratio) {
|
||||
aspect_ratio_ = aspect_ratio;
|
||||
}
|
||||
|
||||
// Optional video decoder initialization data, such as H.264 AVCC.
|
||||
//
|
||||
@ -185,10 +173,11 @@ class MEDIA_EXPORT VideoDecoderConfig {
|
||||
|
||||
// Deprecated. TODO(wolenetz): Remove. See https://crbug.com/665539.
|
||||
gfx::Size coded_size_;
|
||||
|
||||
gfx::Rect visible_rect_;
|
||||
gfx::Size natural_size_;
|
||||
|
||||
VideoAspectRatio aspect_ratio_;
|
||||
|
||||
std::vector<uint8_t> extra_data_;
|
||||
|
||||
EncryptionScheme encryption_scheme_ = EncryptionScheme::kUnencrypted;
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "media/base/limits.h"
|
||||
#include "media/base/media_util.h"
|
||||
#include "media/base/video_decoder_config.h"
|
||||
#include "media/base/video_util.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace media {
|
||||
@ -30,67 +29,6 @@ TEST(VideoDecoderConfigTest, AlphaModeSetCorrectly) {
|
||||
EXPECT_EQ(config.alpha_mode(), VideoDecoderConfig::AlphaMode::kHasAlpha);
|
||||
}
|
||||
|
||||
TEST(VideoDecoderConfigTest, Invalid_AspectRatioNumeratorZero) {
|
||||
gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 0, 1);
|
||||
VideoDecoderConfig config(
|
||||
kCodecVP8, VP8PROFILE_ANY, VideoDecoderConfig::AlphaMode::kIsOpaque,
|
||||
VideoColorSpace(), kNoTransformation, kCodedSize, kVisibleRect,
|
||||
natural_size, EmptyExtraData(), EncryptionScheme::kUnencrypted);
|
||||
EXPECT_FALSE(config.IsValidConfig());
|
||||
}
|
||||
|
||||
TEST(VideoDecoderConfigTest, Invalid_AspectRatioDenominatorZero) {
|
||||
gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 1, 0);
|
||||
VideoDecoderConfig config(
|
||||
kCodecVP8, VP8PROFILE_ANY, VideoDecoderConfig::AlphaMode::kIsOpaque,
|
||||
VideoColorSpace(), kNoTransformation, kCodedSize, kVisibleRect,
|
||||
natural_size, EmptyExtraData(), EncryptionScheme::kUnencrypted);
|
||||
EXPECT_FALSE(config.IsValidConfig());
|
||||
}
|
||||
|
||||
TEST(VideoDecoderConfigTest, Invalid_AspectRatioNumeratorNegative) {
|
||||
gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), -1, 1);
|
||||
VideoDecoderConfig config(
|
||||
kCodecVP8, VP8PROFILE_ANY, VideoDecoderConfig::AlphaMode::kIsOpaque,
|
||||
VideoColorSpace(), kNoTransformation, kCodedSize, kVisibleRect,
|
||||
natural_size, EmptyExtraData(), EncryptionScheme::kUnencrypted);
|
||||
EXPECT_FALSE(config.IsValidConfig());
|
||||
}
|
||||
|
||||
TEST(VideoDecoderConfigTest, Invalid_AspectRatioDenominatorNegative) {
|
||||
gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 1, -1);
|
||||
VideoDecoderConfig config(
|
||||
kCodecVP8, VP8PROFILE_ANY, VideoDecoderConfig::AlphaMode::kIsOpaque,
|
||||
VideoColorSpace(), kNoTransformation, kCodedSize, kVisibleRect,
|
||||
natural_size, EmptyExtraData(), EncryptionScheme::kUnencrypted);
|
||||
EXPECT_FALSE(config.IsValidConfig());
|
||||
}
|
||||
|
||||
TEST(VideoDecoderConfigTest, Invalid_AspectRatioNumeratorTooLarge) {
|
||||
int width = kVisibleRect.size().width();
|
||||
int num = ceil(static_cast<double>(limits::kMaxDimension + 1) / width);
|
||||
gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), num, 1);
|
||||
VideoDecoderConfig config(
|
||||
kCodecVP8, VP8PROFILE_ANY, VideoDecoderConfig::AlphaMode::kIsOpaque,
|
||||
VideoColorSpace(), kNoTransformation, kCodedSize, kVisibleRect,
|
||||
natural_size, EmptyExtraData(), EncryptionScheme::kUnencrypted);
|
||||
EXPECT_FALSE(config.IsValidConfig());
|
||||
}
|
||||
|
||||
TEST(VideoDecoderConfigTest, Invalid_AspectRatioDenominatorVeryLarge) {
|
||||
// This test makes sure that highly skewed pixel ratios arent counted as valid
|
||||
// configurations.
|
||||
int den = 2 * kVisibleRect.size().width() + 1;
|
||||
gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 1, den);
|
||||
EXPECT_EQ(320, natural_size.width());
|
||||
EXPECT_EQ(240 * 641, natural_size.height());
|
||||
VideoDecoderConfig config(
|
||||
kCodecVP8, VP8PROFILE_ANY, VideoDecoderConfig::AlphaMode::kIsOpaque,
|
||||
VideoColorSpace(), kNoTransformation, kCodedSize, kVisibleRect,
|
||||
natural_size, EmptyExtraData(), EncryptionScheme::kUnencrypted);
|
||||
EXPECT_FALSE(config.IsValidConfig());
|
||||
}
|
||||
|
||||
TEST(VideoDecoderConfigTest, SetProfile) {
|
||||
VideoDecoderConfig config(
|
||||
kCodecVP9, VP9PROFILE_PROFILE0, VideoDecoderConfig::AlphaMode::kIsOpaque,
|
||||
|
@ -258,45 +258,6 @@ scoped_refptr<VideoFrame> ReadbackTextureBackedFrameToMemorySyncOOP(
|
||||
|
||||
} // namespace
|
||||
|
||||
double GetPixelAspectRatio(const gfx::Rect& visible_rect,
|
||||
const gfx::Size& natural_size) {
|
||||
double visible_width = visible_rect.width();
|
||||
double visible_height = visible_rect.height();
|
||||
double natural_width = natural_size.width();
|
||||
double natural_height = natural_size.height();
|
||||
return (visible_height * natural_width) / (visible_width * natural_height);
|
||||
}
|
||||
|
||||
gfx::Size GetNaturalSize(const gfx::Rect& visible_rect,
|
||||
double pixel_aspect_ratio) {
|
||||
// TODO(sandersd): Also handle conversion back to integers overflowing.
|
||||
if (!std::isfinite(pixel_aspect_ratio) || pixel_aspect_ratio <= 0.0)
|
||||
return gfx::Size();
|
||||
|
||||
// The HTML spec requires that we always grow a dimension to match aspect
|
||||
// ratio, rather than modify just the width:
|
||||
// github.com/whatwg/html/commit/2e94aa64fcf9adbd2f70d8c2aecd192c8678e298
|
||||
if (pixel_aspect_ratio >= 1.0) {
|
||||
return gfx::Size(std::round(visible_rect.width() * pixel_aspect_ratio),
|
||||
visible_rect.height());
|
||||
}
|
||||
|
||||
return gfx::Size(visible_rect.width(),
|
||||
std::round(visible_rect.height() / pixel_aspect_ratio));
|
||||
}
|
||||
|
||||
gfx::Size GetNaturalSize(const gfx::Size& visible_size,
|
||||
int aspect_ratio_numerator,
|
||||
int aspect_ratio_denominator) {
|
||||
if (aspect_ratio_denominator <= 0 || aspect_ratio_numerator <= 0)
|
||||
return gfx::Size();
|
||||
|
||||
double pixel_aspect_ratio =
|
||||
aspect_ratio_numerator / static_cast<double>(aspect_ratio_denominator);
|
||||
|
||||
return GetNaturalSize(gfx::Rect(visible_size), pixel_aspect_ratio);
|
||||
}
|
||||
|
||||
void FillYUV(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v) {
|
||||
// Fill the Y plane.
|
||||
uint8_t* y_plane = frame->data(VideoFrame::kYPlane);
|
||||
|
@ -30,37 +30,6 @@ namespace media {
|
||||
class VideoFramePool;
|
||||
class VideoFrame;
|
||||
|
||||
// Computes the pixel aspect ratio of a given |visible_rect| from its
|
||||
// |natural_size|.
|
||||
//
|
||||
// See https://en.wikipedia.org/wiki/Pixel_aspect_ratio for a detailed
|
||||
// definition.
|
||||
//
|
||||
// Returns NaN or Infinity if |visible_rect| or |natural_size| are empty.
|
||||
//
|
||||
// Note: Something has probably gone wrong if you need to call this function;
|
||||
// pixel aspect ratios should be the source of truth.
|
||||
//
|
||||
// TODO(crbug.com/837337): Decide how to encode 'not provided' for pixel aspect
|
||||
// ratios, and return that if one of the inputs is empty.
|
||||
MEDIA_EXPORT double GetPixelAspectRatio(const gfx::Rect& visible_rect,
|
||||
const gfx::Size& natural_size);
|
||||
|
||||
// Increases (at most) one of the dimensions of |visible_rect| to produce
|
||||
// a |natural_size| with the given pixel aspect ratio.
|
||||
//
|
||||
// Returns gfx::Size() if |pixel_aspect_ratio| is not finite and positive.
|
||||
MEDIA_EXPORT gfx::Size GetNaturalSize(const gfx::Rect& visible_rect,
|
||||
double pixel_aspect_ratio);
|
||||
|
||||
// Overload that takes the pixel aspect ratio as an integer fraction (and
|
||||
// |visible_size| instead of |visible_rect|).
|
||||
//
|
||||
// Returns gfx::Size() if numerator or denominator are not positive.
|
||||
MEDIA_EXPORT gfx::Size GetNaturalSize(const gfx::Size& visible_size,
|
||||
int aspect_ratio_numerator,
|
||||
int aspect_ratio_denominator);
|
||||
|
||||
// Fills |frame| containing YUV data to the given color values.
|
||||
MEDIA_EXPORT void FillYUV(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v);
|
||||
|
||||
|
@ -189,84 +189,6 @@ class VideoUtilTest : public testing::Test {
|
||||
scoped_refptr<VideoFrame> destination_frame_;
|
||||
};
|
||||
|
||||
TEST_F(VideoUtilTest, GetPixelAspectRatio) {
|
||||
gfx::Rect visible_rect(320, 240);
|
||||
|
||||
// Test empty or invalid combinations.
|
||||
EXPECT_TRUE(std::isnan(GetPixelAspectRatio(gfx::Rect(), gfx::Size())));
|
||||
EXPECT_TRUE(std::isnan(GetPixelAspectRatio(gfx::Rect(1, 1), gfx::Size())));
|
||||
EXPECT_TRUE(std::isnan(GetPixelAspectRatio(gfx::Rect(), gfx::Size(1, 1))));
|
||||
EXPECT_TRUE(
|
||||
std::isinf(GetPixelAspectRatio(gfx::Rect(1, 1), gfx::Size(1, 0))));
|
||||
EXPECT_EQ(0.0, GetPixelAspectRatio(gfx::Rect(1, 1), gfx::Size(0, 1)));
|
||||
EXPECT_EQ(0.0, GetPixelAspectRatio(gfx::Rect(1, 0), gfx::Size(1, 1)));
|
||||
EXPECT_TRUE(
|
||||
std::isinf(GetPixelAspectRatio(gfx::Rect(0, 1), gfx::Size(1, 1))));
|
||||
|
||||
// Some normal ratios.
|
||||
EXPECT_DOUBLE_EQ(1.0, GetPixelAspectRatio(visible_rect, gfx::Size(320, 240)));
|
||||
EXPECT_DOUBLE_EQ(2.0, GetPixelAspectRatio(visible_rect, gfx::Size(640, 240)));
|
||||
EXPECT_DOUBLE_EQ(0.5, GetPixelAspectRatio(visible_rect, gfx::Size(320, 480)));
|
||||
}
|
||||
|
||||
TEST_F(VideoUtilTest, GetNaturalSize_Double) {
|
||||
gfx::Rect visible_rect(320, 240);
|
||||
|
||||
// Test 0 sizes.
|
||||
EXPECT_EQ(gfx::Size(0, 0), GetNaturalSize(gfx::Rect(0, 0), 1.0));
|
||||
EXPECT_EQ(gfx::Size(0, 1), GetNaturalSize(gfx::Rect(0, 1), 1.0));
|
||||
EXPECT_EQ(gfx::Size(1, 0), GetNaturalSize(gfx::Rect(1, 0), 1.0));
|
||||
|
||||
// Test abnormal ratios.
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_rect, NAN));
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_rect, 0.0));
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_rect, INFINITY));
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_rect, -INFINITY));
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_rect, -1.0));
|
||||
|
||||
// Test normal sizes and ratios.
|
||||
EXPECT_EQ(gfx::Size(320, 240), GetNaturalSize(visible_rect, 1.0 / 1.0));
|
||||
EXPECT_EQ(gfx::Size(640, 240), GetNaturalSize(visible_rect, 2.0 / 1.0));
|
||||
EXPECT_EQ(gfx::Size(320, 480), GetNaturalSize(visible_rect, 1.0 / 2.0));
|
||||
EXPECT_EQ(gfx::Size(427, 240), GetNaturalSize(visible_rect, 4.0 / 3.0));
|
||||
EXPECT_EQ(gfx::Size(320, 320), GetNaturalSize(visible_rect, 3.0 / 4.0));
|
||||
EXPECT_EQ(gfx::Size(569, 240), GetNaturalSize(visible_rect, 16.0 / 9.0));
|
||||
EXPECT_EQ(gfx::Size(320, 427), GetNaturalSize(visible_rect, 9.0 / 16.0));
|
||||
|
||||
// Test some random ratios.
|
||||
EXPECT_EQ(gfx::Size(495, 240), GetNaturalSize(visible_rect, 17.0 / 11.0));
|
||||
EXPECT_EQ(gfx::Size(320, 371), GetNaturalSize(visible_rect, 11.0 / 17.0));
|
||||
}
|
||||
|
||||
TEST_F(VideoUtilTest, GetNaturalSize_Fraction) {
|
||||
gfx::Size visible_size(320, 240);
|
||||
|
||||
// Test 0 sizes.
|
||||
EXPECT_EQ(gfx::Size(0, 0), GetNaturalSize(gfx::Size(0, 0), 1, 1));
|
||||
EXPECT_EQ(gfx::Size(0, 1), GetNaturalSize(gfx::Size(0, 1), 1, 1));
|
||||
EXPECT_EQ(gfx::Size(1, 0), GetNaturalSize(gfx::Size(1, 0), 1, 1));
|
||||
|
||||
// Test abnormal ratios.
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_size, 0, 0));
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_size, 0, 1));
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_size, 1, 0));
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_size, 1, -1));
|
||||
EXPECT_EQ(gfx::Size(), GetNaturalSize(visible_size, -1, 1));
|
||||
|
||||
// Test normal sizes and ratios.
|
||||
EXPECT_EQ(gfx::Size(320, 240), GetNaturalSize(visible_size, 1, 1));
|
||||
EXPECT_EQ(gfx::Size(640, 240), GetNaturalSize(visible_size, 2, 1));
|
||||
EXPECT_EQ(gfx::Size(320, 480), GetNaturalSize(visible_size, 1, 2));
|
||||
EXPECT_EQ(gfx::Size(427, 240), GetNaturalSize(visible_size, 4, 3));
|
||||
EXPECT_EQ(gfx::Size(320, 320), GetNaturalSize(visible_size, 3, 4));
|
||||
EXPECT_EQ(gfx::Size(569, 240), GetNaturalSize(visible_size, 16, 9));
|
||||
EXPECT_EQ(gfx::Size(320, 427), GetNaturalSize(visible_size, 9, 16));
|
||||
|
||||
// Test some random ratios.
|
||||
EXPECT_EQ(gfx::Size(495, 240), GetNaturalSize(visible_size, 17, 11));
|
||||
EXPECT_EQ(gfx::Size(320, 371), GetNaturalSize(visible_size, 11, 17));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
uint8_t src6x4[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
|
@ -525,7 +525,7 @@ void CdmAdapter::InitializeVideoDecoder(const VideoDecoderConfig& config,
|
||||
return;
|
||||
}
|
||||
|
||||
pixel_aspect_ratio_ = config.GetPixelAspectRatio();
|
||||
aspect_ratio_ = config.aspect_ratio();
|
||||
is_video_encrypted_ = config.is_encrypted();
|
||||
|
||||
if (status == cdm::kDeferredInitialization) {
|
||||
@ -605,7 +605,7 @@ void CdmAdapter::DecryptAndDecodeVideo(scoped_refptr<DecoderBuffer> encrypted,
|
||||
|
||||
gfx::Rect visible_rect(video_frame->Size().width, video_frame->Size().height);
|
||||
scoped_refptr<VideoFrame> decoded_frame = video_frame->TransformToVideoFrame(
|
||||
GetNaturalSize(visible_rect, pixel_aspect_ratio_));
|
||||
aspect_ratio_.GetNaturalSize(visible_rect));
|
||||
if (!decoded_frame) {
|
||||
DLOG(ERROR) << __func__ << ": TransformToVideoFrame failed.";
|
||||
std::move(video_decode_cb).Run(Decryptor::kError, nullptr);
|
||||
@ -640,7 +640,7 @@ void CdmAdapter::DeinitializeDecoder(StreamType stream_type) {
|
||||
audio_channel_layout_ = CHANNEL_LAYOUT_NONE;
|
||||
break;
|
||||
case Decryptor::kVideo:
|
||||
pixel_aspect_ratio_ = 0.0;
|
||||
aspect_ratio_ = VideoAspectRatio();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "media/base/content_decryption_module.h"
|
||||
#include "media/base/decryptor.h"
|
||||
#include "media/base/media_export.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/cdm/api/content_decryption_module.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
@ -241,7 +242,7 @@ class MEDIA_EXPORT CdmAdapter final : public ContentDecryptionModule,
|
||||
ChannelLayout audio_channel_layout_ = CHANNEL_LAYOUT_NONE;
|
||||
|
||||
// Keep track of aspect ratio from the latest configuration.
|
||||
double pixel_aspect_ratio_ = 0.0;
|
||||
VideoAspectRatio aspect_ratio_;
|
||||
|
||||
// Whether the current video config is encrypted.
|
||||
bool is_video_encrypted_ = false;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "media/base/decoder_buffer.h"
|
||||
#include "media/base/encryption_scheme.h"
|
||||
#include "media/base/media_util.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_decoder_config.h"
|
||||
#include "media/base/video_util.h"
|
||||
#include "media/formats/mp4/box_definitions.h"
|
||||
@ -491,17 +492,26 @@ bool AVStreamToVideoDecoderConfig(const AVStream* stream,
|
||||
gfx::Rect visible_rect(codec_context->width, codec_context->height);
|
||||
gfx::Size coded_size = visible_rect.size();
|
||||
|
||||
AVRational aspect_ratio = {1, 1};
|
||||
if (stream->sample_aspect_ratio.num)
|
||||
aspect_ratio = stream->sample_aspect_ratio;
|
||||
else if (codec_context->sample_aspect_ratio.num)
|
||||
aspect_ratio = codec_context->sample_aspect_ratio;
|
||||
// In some cases a container may have a DAR but no PAR, but FFmpeg translates
|
||||
// everything to PAR. It is possible to get the render width and height, but I
|
||||
// didn't find a way to determine whether that should be preferred to the PAR.
|
||||
VideoAspectRatio aspect_ratio;
|
||||
if (stream->sample_aspect_ratio.num) {
|
||||
aspect_ratio = VideoAspectRatio::PAR(stream->sample_aspect_ratio.num,
|
||||
stream->sample_aspect_ratio.den);
|
||||
} else if (codec_context->sample_aspect_ratio.num) {
|
||||
aspect_ratio =
|
||||
VideoAspectRatio::PAR(codec_context->sample_aspect_ratio.num,
|
||||
codec_context->sample_aspect_ratio.den);
|
||||
}
|
||||
|
||||
// Used to guess color space and to create the config. The first use should
|
||||
// probably change to coded size, and the second should be removed as part of
|
||||
// crbug.com/1214061.
|
||||
gfx::Size natural_size = aspect_ratio.GetNaturalSize(visible_rect);
|
||||
|
||||
VideoCodec codec = CodecIDToVideoCodec(codec_context->codec_id);
|
||||
|
||||
gfx::Size natural_size =
|
||||
GetNaturalSize(visible_rect.size(), aspect_ratio.num, aspect_ratio.den);
|
||||
|
||||
// Without the ffmpeg decoder configured, libavformat is unable to get the
|
||||
// profile, format, or coded size. So choose sensible defaults and let
|
||||
// decoders fail later if the configuration is actually unsupported.
|
||||
@ -649,6 +659,8 @@ bool AVStreamToVideoDecoderConfig(const AVStream* stream,
|
||||
color_space, VideoTransformation(video_rotation),
|
||||
coded_size, visible_rect, natural_size, extra_data,
|
||||
GetEncryptionScheme(stream));
|
||||
// Set the aspect ratio explicitly since our version hasn't been rounded.
|
||||
config->set_aspect_ratio(aspect_ratio);
|
||||
|
||||
if (stream->nb_side_data) {
|
||||
for (int i = 0; i < stream->nb_side_data; ++i) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "media/base/decoder_buffer.h"
|
||||
#include "media/base/limits.h"
|
||||
#include "media/base/media_log.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_util.h"
|
||||
|
||||
extern "C" {
|
||||
@ -441,7 +442,7 @@ scoped_refptr<VideoFrame> Dav1dVideoDecoder::BindImageToVideoFrame(
|
||||
|
||||
auto frame = VideoFrame::WrapExternalYuvData(
|
||||
pixel_format, visible_size, gfx::Rect(visible_size),
|
||||
GetNaturalSize(gfx::Rect(visible_size), config_.GetPixelAspectRatio()),
|
||||
config_.aspect_ratio().GetNaturalSize(gfx::Rect(visible_size)),
|
||||
pic->stride[0], uv_plane_stride, uv_plane_stride,
|
||||
static_cast<uint8_t*>(pic->data[0]), u_plane, v_plane,
|
||||
base::TimeDelta::FromMicroseconds(pic->m.timestamp));
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "media/base/limits.h"
|
||||
#include "media/base/media_log.h"
|
||||
#include "media/base/timestamp_constants.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_frame.h"
|
||||
#include "media/base/video_util.h"
|
||||
#include "media/ffmpeg/ffmpeg_common.h"
|
||||
@ -139,15 +140,13 @@ int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
gfx::Size natural_size;
|
||||
if (codec_context->sample_aspect_ratio.num > 0) {
|
||||
natural_size = GetNaturalSize(size,
|
||||
codec_context->sample_aspect_ratio.num,
|
||||
codec_context->sample_aspect_ratio.den);
|
||||
} else {
|
||||
natural_size =
|
||||
GetNaturalSize(gfx::Rect(size), config_.GetPixelAspectRatio());
|
||||
VideoAspectRatio aspect_ratio = config_.aspect_ratio();
|
||||
if (!aspect_ratio.IsValid() && codec_context->sample_aspect_ratio.num > 0) {
|
||||
aspect_ratio =
|
||||
VideoAspectRatio::PAR(codec_context->sample_aspect_ratio.num,
|
||||
codec_context->sample_aspect_ratio.den);
|
||||
}
|
||||
gfx::Size natural_size = aspect_ratio.GetNaturalSize(gfx::Rect(size));
|
||||
|
||||
// FFmpeg has specific requirements on the allocation size of the frame. The
|
||||
// following logic replicates FFmpeg's allocation strategy to ensure buffers
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "media/base/bind_to_current_loop.h"
|
||||
#include "media/base/cdm_context.h"
|
||||
#include "media/base/media_switches.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_decoder.h"
|
||||
#include "media/base/video_decoder_config.h"
|
||||
#include "media/base/video_frame.h"
|
||||
@ -268,9 +269,8 @@ class FuchsiaVideoDecoder : public VideoDecoder,
|
||||
OutputCB output_cb_;
|
||||
WaitingCB waiting_cb_;
|
||||
|
||||
// Aspect ratio specified in container, or 1.0 if it's not specified. This
|
||||
// value is used only if the aspect ratio is not specified in the bitstream.
|
||||
float container_pixel_aspect_ratio_ = 1.0;
|
||||
// Aspect ratio specified in container.
|
||||
VideoAspectRatio container_aspect_ratio_;
|
||||
|
||||
std::unique_ptr<SysmemBufferStream> sysmem_buffer_stream_;
|
||||
|
||||
@ -362,7 +362,7 @@ void FuchsiaVideoDecoder::Initialize(const VideoDecoderConfig& config,
|
||||
|
||||
output_cb_ = output_cb;
|
||||
waiting_cb_ = waiting_cb;
|
||||
container_pixel_aspect_ratio_ = config.GetPixelAspectRatio();
|
||||
container_aspect_ratio_ = config.aspect_ratio();
|
||||
|
||||
// Keep decoder and decryptor if the configuration hasn't changed.
|
||||
if (decoder_ && current_config_.is_encrypted() == config.codec() &&
|
||||
@ -646,13 +646,11 @@ void FuchsiaVideoDecoder::OnStreamProcessorOutputPacket(
|
||||
auto display_rect = gfx::Rect(output_format_.primary_display_width_pixels,
|
||||
output_format_.primary_display_height_pixels);
|
||||
|
||||
float pixel_aspect_ratio;
|
||||
if (output_format_.has_pixel_aspect_ratio) {
|
||||
pixel_aspect_ratio =
|
||||
static_cast<float>(output_format_.pixel_aspect_ratio_width) /
|
||||
static_cast<float>(output_format_.pixel_aspect_ratio_height);
|
||||
} else {
|
||||
pixel_aspect_ratio = container_pixel_aspect_ratio_;
|
||||
VideoAspectRatio aspect_ratio = container_aspect_ratio_;
|
||||
if (!aspect_ratio.IsValid() && output_format_.has_pixel_aspect_ratio) {
|
||||
aspect_ratio =
|
||||
VideoAspectRatio::PAR(output_format_.pixel_aspect_ratio_width,
|
||||
output_format_.pixel_aspect_ratio_height);
|
||||
}
|
||||
|
||||
auto timestamp = output_packet.timestamp();
|
||||
@ -670,7 +668,7 @@ void FuchsiaVideoDecoder::OnStreamProcessorOutputPacket(
|
||||
|
||||
auto frame = output_mailboxes_[buffer_index]->CreateFrame(
|
||||
pixel_format, coded_size, display_rect,
|
||||
GetNaturalSize(display_rect, pixel_aspect_ratio), timestamp,
|
||||
aspect_ratio.GetNaturalSize(display_rect), timestamp,
|
||||
base::BindOnce(&FuchsiaVideoDecoder::ReleaseOutputPacket,
|
||||
base::Unretained(this), std::move(output_packet)));
|
||||
|
||||
|
@ -303,7 +303,7 @@ void Gav1VideoDecoder::Initialize(const VideoDecoderConfig& config,
|
||||
output_cb_ = output_cb;
|
||||
state_ = DecoderState::kDecoding;
|
||||
color_space_ = config.color_space_info();
|
||||
pixel_aspect_ratio_ = config.GetPixelAspectRatio();
|
||||
aspect_ratio_ = config.aspect_ratio();
|
||||
std::move(bound_init_cb).Run(OkStatus());
|
||||
}
|
||||
|
||||
@ -442,9 +442,9 @@ scoped_refptr<VideoFrame> Gav1VideoDecoder::CreateVideoFrame(
|
||||
// The buffer for the new frame will be zero initialized. Reused frames
|
||||
// will not be zero initialized.
|
||||
// The zero initialization is necessary for FFmpeg but not for libgav1.
|
||||
return frame_pool_.CreateFrame(
|
||||
format, coded_size, visible_rect,
|
||||
GetNaturalSize(visible_rect, pixel_aspect_ratio_), kNoTimestamp);
|
||||
return frame_pool_.CreateFrame(format, coded_size, visible_rect,
|
||||
aspect_ratio_.GetNaturalSize(visible_rect),
|
||||
kNoTimestamp);
|
||||
}
|
||||
|
||||
void Gav1VideoDecoder::CloseDecoder() {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "base/sequence_checker.h"
|
||||
#include "media/base/media_export.h"
|
||||
#include "media/base/supported_video_decoder_config.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_decoder_config.h"
|
||||
#include "media/base/video_frame_pool.h"
|
||||
#include "media/filters/offloading_video_decoder.h"
|
||||
@ -73,7 +74,7 @@ class MEDIA_EXPORT Gav1VideoDecoder : public OffloadableVideoDecoder {
|
||||
|
||||
// Info configured in Initialize(). These are used in outputting frames.
|
||||
VideoColorSpace color_space_;
|
||||
double pixel_aspect_ratio_;
|
||||
VideoAspectRatio aspect_ratio_;
|
||||
|
||||
DecoderState state_ = DecoderState::kUninitialized;
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "media/base/decoder_buffer.h"
|
||||
#include "media/base/limits.h"
|
||||
#include "media/base/media_switches.h"
|
||||
#include "media/base/video_util.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/filters/frame_buffer_pool.h"
|
||||
#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
|
||||
#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h"
|
||||
@ -547,7 +547,7 @@ bool VpxVideoDecoder::CopyVpxImageToVideoFrame(
|
||||
// vpx_video_decoder inconsistent with decoders where changes to
|
||||
// pixel aspect ratio are not surfaced (e.g. Android MediaCodec).
|
||||
const gfx::Size natural_size =
|
||||
GetNaturalSize(gfx::Rect(visible_size), config_.GetPixelAspectRatio());
|
||||
config_.aspect_ratio().GetNaturalSize(gfx::Rect(visible_size));
|
||||
|
||||
if (memory_pool_) {
|
||||
DCHECK_EQ(kCodecVP9, config_.codec());
|
||||
|
@ -504,16 +504,16 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
|
||||
|
||||
// If PASP is available, use the coded size and PASP to calculate the
|
||||
// natural size. Otherwise, use the size in track header for natural size.
|
||||
gfx::Size natural_size(visible_rect.size());
|
||||
VideoAspectRatio aspect_ratio;
|
||||
if (entry.pixel_aspect.h_spacing != 1 ||
|
||||
entry.pixel_aspect.v_spacing != 1) {
|
||||
natural_size =
|
||||
GetNaturalSize(visible_rect.size(), entry.pixel_aspect.h_spacing,
|
||||
entry.pixel_aspect.v_spacing);
|
||||
aspect_ratio = VideoAspectRatio::PAR(entry.pixel_aspect.h_spacing,
|
||||
entry.pixel_aspect.v_spacing);
|
||||
} else if (track->header.width && track->header.height) {
|
||||
natural_size =
|
||||
gfx::Size(track->header.width, track->header.height);
|
||||
aspect_ratio =
|
||||
VideoAspectRatio::DAR(track->header.width, track->header.height);
|
||||
}
|
||||
gfx::Size natural_size = aspect_ratio.GetNaturalSize(visible_rect);
|
||||
|
||||
uint32_t video_track_id = track->header.track_id;
|
||||
if (video_track_ids_.find(video_track_id) != video_track_ids_.end()) {
|
||||
@ -537,6 +537,7 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
|
||||
// No decoder-specific buffer needed for AVC;
|
||||
// SPS/PPS are embedded in the video stream
|
||||
EmptyExtraData(), scheme);
|
||||
video_config.set_aspect_ratio(aspect_ratio);
|
||||
video_config.set_level(entry.video_codec_level);
|
||||
|
||||
if (entry.video_color_space.IsSpecified())
|
||||
|
@ -27,10 +27,10 @@
|
||||
#include "media/base/scoped_async_trace.h"
|
||||
#include "media/base/status.h"
|
||||
#include "media/base/supported_video_decoder_config.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_codecs.h"
|
||||
#include "media/base/video_decoder_config.h"
|
||||
#include "media/base/video_frame.h"
|
||||
#include "media/base/video_util.h"
|
||||
#include "media/gpu/android/android_video_surface_chooser.h"
|
||||
#include "media/gpu/android/codec_allocator.h"
|
||||
#include "media/media_buildflags.h"
|
||||
@ -980,7 +980,7 @@ bool MediaCodecVideoDecoder::DequeueOutput() {
|
||||
}
|
||||
video_frame_factory_->CreateVideoFrame(
|
||||
std::move(output_buffer), presentation_time,
|
||||
GetNaturalSize(visible_rect, decoder_config_.GetPixelAspectRatio()),
|
||||
decoder_config_.aspect_ratio().GetNaturalSize(visible_rect),
|
||||
CreatePromotionHintCB(),
|
||||
base::BindOnce(&MediaCodecVideoDecoder::ForwardVideoFrame,
|
||||
weak_factory_.GetWeakPtr(), reset_generation_,
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "base/thread_annotations.h"
|
||||
#include "components/viz/common/resources/resource_format_utils.h"
|
||||
#include "gpu/command_buffer/common/mailbox_holder.h"
|
||||
#include "media/base/video_util.h"
|
||||
|
||||
namespace media {
|
||||
|
||||
@ -219,10 +218,7 @@ class PictureBufferManagerImpl : public PictureBufferManager {
|
||||
DLOG(WARNING) << "visible_rect " << visible_rect.ToString()
|
||||
<< " exceeds coded_size "
|
||||
<< picture_buffer_data.texture_size.ToString();
|
||||
double pixel_aspect_ratio =
|
||||
GetPixelAspectRatio(visible_rect, natural_size);
|
||||
visible_rect.Intersect(gfx::Rect(picture_buffer_data.texture_size));
|
||||
natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio);
|
||||
}
|
||||
|
||||
// Record the output.
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "media/base/bitstream_buffer.h"
|
||||
#include "media/base/decoder_buffer.h"
|
||||
#include "media/base/media_log.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_codecs.h"
|
||||
#include "media/base/video_types.h"
|
||||
#include "media/base/video_util.h"
|
||||
@ -635,7 +636,7 @@ void VdaVideoDecoder::PictureReadyOnParentThread(Picture picture) {
|
||||
// Create a VideoFrame for the picture.
|
||||
scoped_refptr<VideoFrame> frame = picture_buffer_manager_->CreateVideoFrame(
|
||||
picture, timestamp, visible_rect,
|
||||
GetNaturalSize(visible_rect, config_.GetPixelAspectRatio()));
|
||||
config_.aspect_ratio().GetNaturalSize(visible_rect));
|
||||
if (!frame) {
|
||||
EnterErrorState();
|
||||
return;
|
||||
|
@ -173,7 +173,7 @@ void V4L2VideoDecoder::Initialize(const VideoDecoderConfig& config,
|
||||
DCHECK(!output_queue_);
|
||||
|
||||
profile_ = config.profile();
|
||||
pixel_aspect_ratio_ = config.GetPixelAspectRatio();
|
||||
aspect_ratio_ = config.aspect_ratio();
|
||||
|
||||
if (profile_ == VIDEO_CODEC_PROFILE_UNKNOWN) {
|
||||
VLOGF(1) << "Unknown profile.";
|
||||
@ -376,7 +376,7 @@ bool V4L2VideoDecoder::SetupOutputFormat(const gfx::Size& size,
|
||||
if (pool) {
|
||||
absl::optional<GpuBufferLayout> layout = pool->Initialize(
|
||||
fourcc, adjusted_size, visible_rect,
|
||||
GetNaturalSize(visible_rect, pixel_aspect_ratio_), num_output_frames_,
|
||||
aspect_ratio_.GetNaturalSize(visible_rect), num_output_frames_,
|
||||
/*use_protected=*/false);
|
||||
if (!layout) {
|
||||
VLOGF(1) << "Failed to setup format to VFPool";
|
||||
@ -683,7 +683,7 @@ void V4L2VideoDecoder::OutputFrame(scoped_refptr<VideoFrame> frame,
|
||||
|
||||
if (frame->visible_rect() != visible_rect ||
|
||||
frame->timestamp() != timestamp) {
|
||||
gfx::Size natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio_);
|
||||
gfx::Size natural_size = aspect_ratio_.GetNaturalSize(visible_rect);
|
||||
scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame(
|
||||
frame, frame->format(), visible_rect, natural_size);
|
||||
wrapped_frame->set_timestamp(timestamp);
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "base/time/time.h"
|
||||
#include "media/base/cdm_context.h"
|
||||
#include "media/base/supported_video_decoder_config.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_types.h"
|
||||
#include "media/gpu/chromeos/gpu_buffer_layout.h"
|
||||
#include "media/gpu/chromeos/video_decoder_pipeline.h"
|
||||
@ -170,8 +171,9 @@ class MEDIA_GPU_EXPORT V4L2VideoDecoder
|
||||
// The default value is only used at the first time of
|
||||
// DmabufVideoFramePool::Initialize() during Initialize().
|
||||
size_t num_output_frames_ = 1;
|
||||
// Ratio of natural_size to visible_rect of the output frame.
|
||||
double pixel_aspect_ratio_ = 0.0;
|
||||
|
||||
// Aspect ratio from config to use for output frames.
|
||||
VideoAspectRatio aspect_ratio_;
|
||||
|
||||
// Callbacks passed from Initialize().
|
||||
OutputCB output_cb_;
|
||||
|
@ -287,7 +287,7 @@ void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
|
||||
DCHECK(client_);
|
||||
frame_pool_ = client_->GetVideoFramePool();
|
||||
|
||||
pixel_aspect_ratio_ = config.GetPixelAspectRatio();
|
||||
aspect_ratio_ = config.aspect_ratio();
|
||||
|
||||
output_cb_ = std::move(output_cb);
|
||||
waiting_cb_ = std::move(waiting_cb);
|
||||
@ -588,7 +588,7 @@ void VaapiVideoDecoder::SurfaceReady(scoped_refptr<VASurface> va_surface,
|
||||
|
||||
if (video_frame->visible_rect() != visible_rect ||
|
||||
video_frame->timestamp() != timestamp) {
|
||||
gfx::Size natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio_);
|
||||
gfx::Size natural_size = aspect_ratio_.GetNaturalSize(visible_rect);
|
||||
scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame(
|
||||
video_frame, video_frame->format(), visible_rect, natural_size);
|
||||
wrapped_frame->set_timestamp(timestamp);
|
||||
@ -774,7 +774,7 @@ void VaapiVideoDecoder::ApplyResolutionChangeWithScreenSizes(
|
||||
}
|
||||
}
|
||||
const gfx::Size natural_size =
|
||||
GetNaturalSize(output_visible_rect, pixel_aspect_ratio_);
|
||||
aspect_ratio_.GetNaturalSize(output_visible_rect);
|
||||
if (!frame_pool_->Initialize(
|
||||
*format_fourcc, output_pic_size, output_visible_rect, natural_size,
|
||||
decoder_->GetRequiredNumOfPictures(), !!cdm_context_ref_)) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "media/base/cdm_context.h"
|
||||
#include "media/base/status.h"
|
||||
#include "media/base/supported_video_decoder_config.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_codecs.h"
|
||||
#include "media/base/video_frame_layout.h"
|
||||
#include "media/gpu/chromeos/video_decoder_pipeline.h"
|
||||
@ -172,8 +173,8 @@ class VaapiVideoDecoder : public DecoderInterface,
|
||||
VideoColorSpace color_space_;
|
||||
absl::optional<gfx::HDRMetadata> hdr_metadata_;
|
||||
|
||||
// Ratio of natural size to |visible_rect_| of the output frames.
|
||||
double pixel_aspect_ratio_ = 0.0;
|
||||
// Aspect ratio from the config.
|
||||
VideoAspectRatio aspect_ratio_;
|
||||
|
||||
// Video frame pool used to allocate and recycle video frames.
|
||||
DmabufVideoFramePool* frame_pool_ = nullptr;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "media/base/decoder_buffer.h"
|
||||
#include "media/base/media_log.h"
|
||||
#include "media/base/media_switches.h"
|
||||
#include "media/base/video_aspect_ratio.h"
|
||||
#include "media/base/video_codecs.h"
|
||||
#include "media/base/video_decoder_config.h"
|
||||
#include "media/base/video_frame.h"
|
||||
@ -825,8 +826,8 @@ bool D3D11VideoDecoder::OutputResult(const CodecPicture* picture,
|
||||
visible_rect = config_.visible_rect();
|
||||
|
||||
// TODO(https://crbug.com/843150): Use aspect ratio from decoder (SPS) if
|
||||
// stream metadata doesn't overrride it.
|
||||
double pixel_aspect_ratio = config_.GetPixelAspectRatio();
|
||||
// the config's aspect ratio isn't valid.
|
||||
gfx::Size natural_size = config_.aspect_ratio().GetNaturalSize(visible_rect);
|
||||
|
||||
base::TimeDelta timestamp = picture_buffer->timestamp_;
|
||||
|
||||
@ -843,7 +844,7 @@ bool D3D11VideoDecoder::OutputResult(const CodecPicture* picture,
|
||||
scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
|
||||
texture_selector_->PixelFormat(), mailbox_holders,
|
||||
VideoFrame::ReleaseMailboxCB(), picture_buffer->size(), visible_rect,
|
||||
GetNaturalSize(visible_rect, pixel_aspect_ratio), timestamp);
|
||||
natural_size, timestamp);
|
||||
|
||||
if (!frame) {
|
||||
// This can happen if, somehow, we get an unsupported combination of
|
||||
|
Reference in New Issue
Block a user