661 lines
28 KiB
Diff
661 lines
28 KiB
Diff
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
|
|||
|
|
index 3acfcf5749..45b18d4203 100644
|
||
|
|
--- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
|
||
|
|
+++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
|
||
|
|
@@ -183,6 +183,9 @@ void GpuVideoAcceleratorFactoriesImpl::DestroyContext() {
|
||
|
|
}
|
||
|
|
|
||
|
|
bool GpuVideoAcceleratorFactoriesImpl::IsGpuVideoDecodeAcceleratorEnabled() {
|
||
|
|
+#if BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
+ return true;
|
||
|
|
+#endif
|
||
|
|
return video_decode_accelerator_enabled_;
|
||
|
|
}
|
||
|
|
bool GpuVideoAcceleratorFactoriesImpl::IsGpuVideoEncodeAcceleratorEnabled() {
|
||
|
|
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
|
||
|
|
index c848b7f8f7..e2b5215d17 100644
|
||
|
|
--- a/content/renderer/render_thread_impl.cc
|
||
|
|
+++ b/content/renderer/render_thread_impl.cc
|
||
|
|
@@ -1,3 +1,4 @@
|
||
|
|
+#include "media/mojo/buildflags.h"
|
||
|
|
// Copyright 2012 The Chromium Authors
|
||
|
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
|
// found in the LICENSE file.
|
||
|
|
@@ -1026,8 +1027,10 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
|
||
|
|
// Currently, VideoResourceUpdater can't convert hardware resources to
|
||
|
|
// software resources in software compositing mode. So, fall back to software
|
||
|
|
// video decoding if gpu compositing is off.
|
||
|
|
+#if !BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
if (is_gpu_compositing_disabled_)
|
||
|
|
return nullptr;
|
||
|
|
+#endif
|
||
|
|
// This context is only used to create textures and mailbox them, so
|
||
|
|
// use lower limits than the default.
|
||
|
|
gpu::SharedMemoryLimits limits = gpu::SharedMemoryLimits::ForMailboxContext();
|
||
|
|
@@ -1045,6 +1048,9 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
|
||
|
|
viz::command_buffer_metrics::ContextType::MEDIA,
|
||
|
|
kGpuStreamIdMedia, kGpuStreamPriorityMedia);
|
||
|
|
|
||
|
|
+#if BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
+ const bool enable_video_decode_accelerator = true;
|
||
|
|
+#else
|
||
|
|
const bool enable_video_decode_accelerator =
|
||
|
|
#if BUILDFLAG(IS_LINUX)
|
||
|
|
base::FeatureList::IsEnabled(media::kAcceleratedVideoDecodeLinux) &&
|
||
|
|
@@ -1053,6 +1059,7 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
|
||
|
|
(gpu_channel_host->gpu_feature_info()
|
||
|
|
.status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE] ==
|
||
|
|
gpu::kGpuFeatureStatusEnabled);
|
||
|
|
+#endif
|
||
|
|
|
||
|
|
const bool enable_video_encode_accelerator =
|
||
|
|
#if BUILDFLAG(IS_LINUX)
|
||
|
|
diff --git a/media/base/format_utils.cc b/media/base/format_utils.cc
|
||
|
|
index 0e1080e0a6..98a221b2f4 100644
|
||
|
|
--- a/media/base/format_utils.cc
|
||
|
|
+++ b/media/base/format_utils.cc
|
||
|
|
@@ -65,6 +65,9 @@ std::optional<gfx::BufferFormat> VideoPixelFormatToGfxBufferFormat(
|
||
|
|
case PIXEL_FORMAT_NV12:
|
||
|
|
return gfx::BufferFormat::YUV_420_BIPLANAR;
|
||
|
|
|
||
|
|
+ case PIXEL_FORMAT_NV21:
|
||
|
|
+ return gfx::BufferFormat::YUV_420_BIPLANAR;
|
||
|
|
+
|
||
|
|
case PIXEL_FORMAT_NV12A:
|
||
|
|
return gfx::BufferFormat::YUVA_420_TRIPLANAR;
|
||
|
|
|
||
|
|
diff --git a/media/base/supported_types.cc b/media/base/supported_types.cc
|
||
|
|
index 34e1ecb868..bc0cd98fee 100644
|
||
|
|
--- a/media/base/supported_types.cc
|
||
|
|
+++ b/media/base/supported_types.cc
|
||
|
|
@@ -315,7 +315,7 @@ bool IsDecoderAACSupported(const AudioType& type) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
#if BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) && \
|
||
|
|
- (BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN))
|
||
|
|
+ (BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_AMLOGIC_MEDIA))
|
||
|
|
return GetSupplementalDecoderAudioTypeCache()->IsProfileSupported(type);
|
||
|
|
#else
|
||
|
|
return false;
|
||
|
|
@@ -350,12 +350,13 @@ bool IsDecoderDolbyAc3Eac3Supported(const AudioType& type) {
|
||
|
|
|
||
|
|
bool IsDecoderDolbyAc4Supported(const AudioType& type) {
|
||
|
|
#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO) && \
|
||
|
|
- BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) && BUILDFLAG(IS_WIN)
|
||
|
|
+ BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) && (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_AMLOGIC_MEDIA))
|
||
|
|
return GetSupplementalDecoderAudioTypeCache()->IsProfileSupported(type);
|
||
|
|
#else
|
||
|
|
return false;
|
||
|
|
#endif // BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO) &&
|
||
|
|
- // BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) && BUILDFLAG(IS_WIN)
|
||
|
|
+ // BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) && (BUILDFLAG(IS_WIN) ||
|
||
|
|
+ // BUILDFLAG(IS_AMLOGIC_MEDIA))
|
||
|
|
}
|
||
|
|
|
||
|
|
bool IsEncoderH264ProfileSupported(const VideoType& type) {
|
||
|
|
@@ -579,6 +580,11 @@ bool IsDefaultEncoderSupportedVideoType(const VideoType& type) {
|
||
|
|
}
|
||
|
|
|
||
|
|
bool IsDecoderBuiltInVideoCodec(VideoCodec codec) {
|
||
|
|
+#if BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
+ // On Amlogic platforms, all codecs are treated as built-in since the
|
||
|
|
+ // hardware decoders are used.
|
||
|
|
+ return true;
|
||
|
|
+#endif // BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) && BUILDFLAG(USE_PROPRIETARY_CODECS)
|
||
|
|
if (codec == VideoCodec::kH264 &&
|
||
|
|
base::FeatureList::IsEnabled(kBuiltInH264Decoder)) {
|
||
|
|
diff --git a/media/gpu/chromeos/mailbox_video_frame_converter.cc b/media/gpu/chromeos/mailbox_video_frame_converter.cc
|
||
|
|
index 6cbc6d89f5..21994b5f34 100644
|
||
|
|
--- a/media/gpu/chromeos/mailbox_video_frame_converter.cc
|
||
|
|
+++ b/media/gpu/chromeos/mailbox_video_frame_converter.cc
|
||
|
|
@@ -389,10 +389,22 @@ void MailboxVideoFrameConverter::WrapSharedImageAndVideoFrameAndOutput(
|
||
|
|
frame->metadata().needs_detiling
|
||
|
|
? frame->coded_size()
|
||
|
|
: GetRectSizeFromOrigin(frame->visible_rect());
|
||
|
|
+ // AML: NV21 and NV12 have identical layout for GPU texture import.
|
||
|
|
+ // WrapSharedImage doesn't support NV21, so use NV12 instead.
|
||
|
|
+ VideoPixelFormat wrap_format = frame->format();
|
||
|
|
+ if (wrap_format == PIXEL_FORMAT_NV21)
|
||
|
|
+ wrap_format = PIXEL_FORMAT_NV12;
|
||
|
|
scoped_refptr<VideoFrame> mailbox_frame = VideoFrame::WrapSharedImage(
|
||
|
|
- frame->format(), shared_image, shared_image_sync_token,
|
||
|
|
+ wrap_format, shared_image, shared_image_sync_token,
|
||
|
|
std::move(release_mailbox_cb), coded_size, frame->visible_rect(),
|
||
|
|
frame->natural_size(), frame->timestamp());
|
||
|
|
+ if (!mailbox_frame) {
|
||
|
|
+ DVLOG(3) << "[AML-CONV] WrapSharedImage returned null! format="
|
||
|
|
+ << VideoPixelFormatToString(frame->format())
|
||
|
|
+ << " coded=" << coded_size.ToString()
|
||
|
|
+ << " visible=" << frame->visible_rect().ToString();
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
mailbox_frame->set_color_space(frame->ColorSpace());
|
||
|
|
mailbox_frame->set_hdr_metadata(frame->hdr_metadata());
|
||
|
|
mailbox_frame->set_metadata(frame->metadata());
|
||
|
|
@@ -496,8 +508,13 @@ bool MailboxVideoFrameConverter::GenerateSharedImageOnGPUThread(
|
||
|
|
}
|
||
|
|
|
||
|
|
auto gpu_memory_buffer_handle = origin_frame->CreateGpuMemoryBufferHandle();
|
||
|
|
- DCHECK(!gpu_memory_buffer_handle.is_null());
|
||
|
|
- DCHECK_EQ(gpu_memory_buffer_handle.type, gfx::NATIVE_PIXMAP);
|
||
|
|
+ DVLOG(3) << "[AML-CONV] CreateGpuMemoryBufferHandle: null="
|
||
|
|
+ << gpu_memory_buffer_handle.is_null()
|
||
|
|
+ << " type=" << gpu_memory_buffer_handle.type
|
||
|
|
+ << " planes=" << gpu_memory_buffer_handle.native_pixmap_handle.planes.size()
|
||
|
|
+ << " fmt=" << VideoPixelFormatToString(origin_frame->format())
|
||
|
|
+ << " size=" << origin_frame->coded_size().ToString();
|
||
|
|
+ if (gpu_memory_buffer_handle.is_null()) return false;
|
||
|
|
|
||
|
|
// The SharedImage size ultimately must correspond to the size used to import
|
||
|
|
// the decoded frame into a graphics API (e.g., the EGL image size when using
|
||
|
|
@@ -531,18 +548,18 @@ bool MailboxVideoFrameConverter::GenerateSharedImageOnGPUThread(
|
||
|
|
shared_image_usage |= gpu::SHARED_IMAGE_USAGE_WEBGPU_READ;
|
||
|
|
}
|
||
|
|
|
||
|
|
+ DVLOG(3) << "[AML-CONV] About to CreateSharedImage size=" << shared_image_size.ToString();
|
||
|
|
scoped_refptr<gpu::ClientSharedImage> client_shared_image =
|
||
|
|
gpu_delegate_->CreateSharedImage(std::move(gpu_memory_buffer_handle),
|
||
|
|
GetSharedImageFormat(*buffer_format),
|
||
|
|
shared_image_size, src_color_space,
|
||
|
|
kTopLeft_GrSurfaceOrigin,
|
||
|
|
kPremul_SkAlphaType, shared_image_usage);
|
||
|
|
+ DVLOG(3) << "[AML-CONV] CreateSharedImage result: " << (client_shared_image ? "OK" : "FAIL");
|
||
|
|
if (!client_shared_image) {
|
||
|
|
OnError(FROM_HERE, "Failed to create shared image.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
- // There's no need to UpdateSharedImage() after CreateSharedImage().
|
||
|
|
-
|
||
|
|
shared_image->Reset(std::move(client_shared_image));
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
diff --git a/media/gpu/chromeos/native_pixmap_frame_resource.cc b/media/gpu/chromeos/native_pixmap_frame_resource.cc
|
||
|
|
index 09c763a7e8..5ac815656b 100644
|
||
|
|
--- a/media/gpu/chromeos/native_pixmap_frame_resource.cc
|
||
|
|
+++ b/media/gpu/chromeos/native_pixmap_frame_resource.cc
|
||
|
|
@@ -3,6 +3,7 @@
|
||
|
|
// found in the LICENSE file.
|
||
|
|
|
||
|
|
#include "media/gpu/chromeos/native_pixmap_frame_resource.h"
|
||
|
|
+#include <drm_fourcc.h>
|
||
|
|
|
||
|
|
#include "atomic"
|
||
|
|
|
||
|
|
@@ -130,10 +131,8 @@ scoped_refptr<NativePixmapFrameResource> NativePixmapFrameResource::Create(
|
||
|
|
std::move(dmabuf_fds[i]));
|
||
|
|
}
|
||
|
|
|
||
|
|
- // This is only ever called with V4L2-allocated buffers, so |layout.modifier|
|
||
|
|
- // is expected to be kNoModifier.
|
||
|
|
- CHECK_EQ(layout.modifier(), gfx::NativePixmapHandle::kNoModifier);
|
||
|
|
- handle.modifier = layout.modifier();
|
||
|
|
+ // Keep kNoModifier for V4L2 MMAP buffers.
|
||
|
|
+ handle.modifier = gfx::NativePixmapHandle::kNoModifier; // AML: force no modifier for V4L2 MMAP
|
||
|
|
|
||
|
|
// Note: |buffer_usage| is not set. As a result, the constructed
|
||
|
|
// NativePixmapFrameResource cannot be converted to a VideoFrame with the
|
||
|
|
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc
|
||
|
|
--- a/media/gpu/chromeos/video_decoder_pipeline.cc
|
||
|
|
+++ b/media/gpu/chromeos/video_decoder_pipeline.cc
|
||
|
|
@@ -3,6 +3,7 @@
|
||
|
|
// found in the LICENSE file.
|
||
|
|
|
||
|
|
#include "media/gpu/chromeos/video_decoder_pipeline.h"
|
||
|
|
+#include "media/mojo/buildflags.h"
|
||
|
|
|
||
|
|
#include <memory>
|
||
|
|
#include <optional>
|
||
|
|
@@ -571,6 +572,7 @@
|
||
|
|
|
||
|
|
// Make sure that the configuration requested is supported by the driver,
|
||
|
|
// which must provide such information.
|
||
|
|
+#if !BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
const auto supported_configs =
|
||
|
|
supported_configs_for_testing_.empty()
|
||
|
|
? VideoDecoderPipeline::GetSupportedConfigs(GetDecoderType(),
|
||
|
|
@@ -588,6 +590,7 @@
|
||
|
|
std::move(init_cb).Run(DecoderStatus::Codes::kUnsupportedConfig);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
+#endif // !BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
constexpr auto kVideoCodecProfileCount = media::VIDEO_CODEC_PROFILE_MAX + 1;
|
||
|
|
base::UmaHistogramEnumeration(
|
||
|
|
"Media.PlatformVideoDecoding.VideoCodecProfile", config.profile(),
|
||
|
|
@@ -647,8 +650,10 @@
|
||
|
|
get_original_frame_cb = base::BindRepeating(
|
||
|
|
&OOPVideoDecoder::GetOriginalFrame,
|
||
|
|
base::Unretained(static_cast<OOPVideoDecoder*>(decoder_.get())));
|
||
|
|
+ } else if (!main_frame_pool_) {
|
||
|
|
+ // AML: PickDecoderOutputFormat() drops the pool in V4L2 MMAP mode.
|
||
|
|
+ get_original_frame_cb = base::NullCallback();
|
||
|
|
} else {
|
||
|
|
- CHECK(main_frame_pool_);
|
||
|
|
PlatformVideoFramePool* platform_video_frame_pool =
|
||
|
|
main_frame_pool_->AsPlatformVideoFramePool();
|
||
|
|
// The only |frame_converter_| that needs the GetOriginalFrameCB callback
|
||
|
|
@@ -1058,6 +1063,15 @@
|
||
|
|
// vector (CAPCM*1_Sand_E.h264).
|
||
|
|
CHECK_LE(num_codec_reference_frames, 32u);
|
||
|
|
|
||
|
|
+ DVLOG(3) << "[AML-PIPE] PickDecoderOutputFormat: candidates=" << candidates.size()
|
||
|
|
+ << " renderable=" << renderable_fourccs_.size();
|
||
|
|
+ for (const auto& c : candidates) {
|
||
|
|
+ DVLOG(3) << "[AML-PIPE] candidate: " << c.fourcc.ToString()
|
||
|
|
+ << " size=" << c.size.ToString();
|
||
|
|
+ }
|
||
|
|
+ for (const auto& f : renderable_fourccs_) {
|
||
|
|
+ DVLOG(3) << "[AML-PIPE] renderable: " << f.ToString();
|
||
|
|
+ }
|
||
|
|
if (candidates.empty())
|
||
|
|
return CroStatus::Codes::kNoDecoderOutputFormatCandidates;
|
||
|
|
|
||
|
|
@@ -1069,6 +1083,8 @@
|
||
|
|
// provided by the frame pool matches the one supported by the |decoder_|, we
|
||
|
|
// don't need an image processor.
|
||
|
|
std::optional<PixelLayoutCandidate> viable_candidate;
|
||
|
|
+ DVLOG(3) << "[AML-PIPE] output_size=" << (output_size ? output_size->ToString() : "none")
|
||
|
|
+ << " decoder_visible=" << decoder_visible_rect.ToString();
|
||
|
|
if (!output_size || *output_size == decoder_visible_rect.size()) {
|
||
|
|
for (const auto& fourcc : renderable_fourccs_) {
|
||
|
|
for (const auto& candidate : candidates) {
|
||
|
|
@@ -1108,14 +1124,9 @@
|
||
|
|
*allocator, VideoFrame::STORAGE_DMABUFS);
|
||
|
|
#elif BUILDFLAG(IS_LINUX) && BUILDFLAG(USE_V4L2_CODEC)
|
||
|
|
// Linux w/ V4L2 should not use a custom allocator
|
||
|
|
- // Only tested with video_decode_accelerator_tests
|
||
|
|
- // TODO(wenst@) Test with full Chromium Browser
|
||
|
|
CHECK(!allocator.has_value());
|
||
|
|
if (viable_candidate) {
|
||
|
|
- // Instead, let V4L2 allocate the buffers if it can decode directly
|
||
|
|
- // to the preferred formats. There's no need to allocate frames.
|
||
|
|
- // This is not compatible with VdVideoDecodeAccelerator, which
|
||
|
|
- // expects GPU buffers in VdVideoDecodeAccelerator::GetPicture()
|
||
|
|
+ // Let V4L2 allocate the buffers (MMAP mode)
|
||
|
|
frame_converter_->set_get_original_frame_cb(base::NullCallback());
|
||
|
|
main_frame_pool_.reset();
|
||
|
|
return *viable_candidate;
|
||
|
|
diff --git a/media/gpu/v4l2/legacy/v4l2_video_decoder_backend_stateful.cc b/media/gpu/v4l2/legacy/v4l2_video_decoder_backend_stateful.cc
|
||
|
|
--- a/media/gpu/v4l2/legacy/v4l2_video_decoder_backend_stateful.cc
|
||
|
|
+++ b/media/gpu/v4l2/legacy/v4l2_video_decoder_backend_stateful.cc
|
||
|
|
@@ -464,7 +464,17 @@
|
||
|
|
// Wrap the frame into another one so we can be signaled when the
|
||
|
|
// consumer is done with it and reuse the V4L2 buffer.
|
||
|
|
scoped_refptr<FrameResource> origin_frame = buffer->GetFrameResource();
|
||
|
|
+ DVLOG(3) << "[AML-V4L2] OnOutputBufferDequeued: origin_frame="
|
||
|
|
+ << (origin_frame ? "valid" : "NULL")
|
||
|
|
+ << " memory=" << output_queue_->GetMemoryType();
|
||
|
|
+ if (!origin_frame) {
|
||
|
|
+ // Queue was reset (resolution change). Skip this buffer.
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
frame = origin_frame->CreateWrappingFrame();
|
||
|
|
+ if (!frame) {
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
frame->AddDestructionObserver(base::BindOnce(
|
||
|
|
&V4L2StatefulVideoDecoderBackend::ReuseOutputBufferThunk,
|
||
|
|
task_runner_, weak_this_, buffer));
|
||
|
|
@@ -761,6 +771,8 @@
|
||
|
|
#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||
|
|
V4L2_PIX_FMT_VP8,
|
||
|
|
V4L2_PIX_FMT_VP9,
|
||
|
|
+ // AML: without AV01 here every AV1 stream is rejected in Initialize().
|
||
|
|
+ V4L2_PIX_FMT_AV1,
|
||
|
|
};
|
||
|
|
auto device = base::MakeRefCounted<V4L2Device>();
|
||
|
|
VideoDecodeAccelerator::SupportedProfiles profiles =
|
||
|
|
diff --git a/media/gpu/v4l2/v4l2_queue.cc b/media/gpu/v4l2/v4l2_queue.cc
|
||
|
|
index bd6b3f5278..4242e06e38 100644
|
||
|
|
--- a/media/gpu/v4l2/v4l2_queue.cc
|
||
|
|
+++ b/media/gpu/v4l2/v4l2_queue.cc
|
||
|
|
@@ -133,13 +133,12 @@ std::vector<base::ScopedFD> GetDmabufsForV4L2Buffer(
|
||
|
|
expbuf.type = buf_type;
|
||
|
|
expbuf.index = index;
|
||
|
|
expbuf.plane = i;
|
||
|
|
- expbuf.flags = O_CLOEXEC;
|
||
|
|
+ expbuf.flags = O_CLOEXEC | O_RDWR; // AML: Mali needs RW access
|
||
|
|
if (ioctl_cb.Run(VIDIOC_EXPBUF, &expbuf) != 0) {
|
||
|
|
RecordVidiocIoctlErrorUMA(VidiocIoctlRequests::kVidiocExpbuf);
|
||
|
|
dmabuf_fds.clear();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
-
|
||
|
|
dmabuf_fds.push_back(base::ScopedFD(expbuf.fd));
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -268,6 +267,15 @@ bool V4L2Buffer::Query() {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
+ // Log actual plane info from QUERYBUF
|
||
|
|
+ for (size_t pi = 0; pi < v4l2_buffer_.length; pi++) {
|
||
|
|
+ LOG(ERROR) << "[AML-QB] buf=" << v4l2_buffer_.index
|
||
|
|
+ << " plane" << pi
|
||
|
|
+ << " length=" << v4l2_planes_[pi].length
|
||
|
|
+ << " offset=" << v4l2_planes_[pi].m.mem_offset
|
||
|
|
+ << " bytesused=" << v4l2_planes_[pi].bytesused;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
DCHECK(plane_mappings_.size() == v4l2_buffer_.length);
|
||
|
|
|
||
|
|
return true;
|
||
|
|
@@ -314,7 +322,10 @@ size_t V4L2Buffer::GetMemoryUsage() const {
|
||
|
|
scoped_refptr<FrameResource> V4L2Buffer::CreateFrame() {
|
||
|
|
auto layout = V4L2FormatToVideoFrameLayout(format_);
|
||
|
|
if (!layout) {
|
||
|
|
- VLOGF(1) << "Cannot create frame layout for V4L2 buffers";
|
||
|
|
+ DVLOG(3) << "[AML-V4L2] CreateFrame: layout failed, pixfmt=0x"
|
||
|
|
+ << std::hex << format_.fmt.pix_mp.pixelformat << std::dec
|
||
|
|
+ << " " << format_.fmt.pix_mp.width << "x" << format_.fmt.pix_mp.height
|
||
|
|
+ << " num_planes=" << format_.fmt.pix_mp.num_planes;
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -322,7 +333,8 @@ scoped_refptr<FrameResource> V4L2Buffer::CreateFrame() {
|
||
|
|
ioctl_cb_, v4l2_buffer_.index, v4l2_buffer_.length,
|
||
|
|
static_cast<enum v4l2_buf_type>(v4l2_buffer_.type));
|
||
|
|
if (dmabuf_fds.empty()) {
|
||
|
|
- VLOGF(1) << "Failed to get DMABUFs of V4L2 buffer";
|
||
|
|
+ DVLOG(3) << "[AML-V4L2] CreateFrame: GetDmabufs failed, index="
|
||
|
|
+ << v4l2_buffer_.index << " length=" << v4l2_buffer_.length;
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -355,15 +367,19 @@ scoped_refptr<FrameResource> V4L2Buffer::CreateFrame() {
|
||
|
|
const scoped_refptr<FrameResource>& V4L2Buffer::GetFrameResource() {
|
||
|
|
// We can create the FrameResource only when using MMAP buffers.
|
||
|
|
if (v4l2_buffer_.memory != V4L2_MEMORY_MMAP) {
|
||
|
|
- VLOGF(1) << "Cannot create video frame from non-MMAP buffer";
|
||
|
|
- // Allow NOTREACHED() on invalid argument because this is an internal
|
||
|
|
- // method.
|
||
|
|
- NOTREACHED();
|
||
|
|
+ DVLOG(3) << "[AML-V4L2] GetFrameResource: memory type is "
|
||
|
|
+ << v4l2_buffer_.memory << " (not MMAP=" << V4L2_MEMORY_MMAP << ")"
|
||
|
|
+ << " index=" << v4l2_buffer_.index;
|
||
|
|
+ static const scoped_refptr<FrameResource> null_res;
|
||
|
|
+ return null_res;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create the video frame instance if requiring it for the first time.
|
||
|
|
if (!frame_) {
|
||
|
|
frame_ = CreateFrame();
|
||
|
|
+ if (!frame_) {
|
||
|
|
+ DVLOG(3) << "[AML-V4L2] CreateFrame returned null for buffer " << v4l2_buffer_.index;
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
|
||
|
|
return frame_;
|
||
|
|
@@ -1178,6 +1194,12 @@ size_t V4L2Queue::AllocateBuffers(size_t count,
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
planes_count_ = format->fmt.pix_mp.num_planes;
|
||
|
|
+ // AML 6.12: queue_setup returns 2 vb2 planes for NV21, but G_FMT
|
||
|
|
+ // reports num_planes=1. Force 2 so QUERYBUF gets correct length.
|
||
|
|
+ if (type_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && planes_count_ < 2) {
|
||
|
|
+ planes_count_ = 2;
|
||
|
|
+ format->fmt.pix_mp.num_planes = 2;
|
||
|
|
+ }
|
||
|
|
DCHECK_LE(planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES));
|
||
|
|
|
||
|
|
__u8 flags = incoherent ? V4L2_MEMORY_FLAG_NON_COHERENT : 0;
|
||
|
|
diff --git a/media/gpu/v4l2/v4l2_utils.cc b/media/gpu/v4l2/v4l2_utils.cc
|
||
|
|
--- a/media/gpu/v4l2/v4l2_utils.cc
|
||
|
|
+++ b/media/gpu/v4l2/v4l2_utils.cc
|
||
|
|
@@ -17,6 +17,10 @@
|
||
|
|
#if BUILDFLAG(IS_CHROMEOS)
|
||
|
|
#include <linux/media/av1-ctrls.h>
|
||
|
|
#endif
|
||
|
|
+// AML: the Debian uAPI headers predate the AV1 controls.
|
||
|
|
+#ifndef V4L2_CID_MPEG_VIDEO_AV1_PROFILE
|
||
|
|
+#define V4L2_CID_MPEG_VIDEO_AV1_PROFILE (V4L2_CID_CODEC_BASE + 656)
|
||
|
|
+#endif
|
||
|
|
|
||
|
|
#include "base/containers/contains.h"
|
||
|
|
#include "base/metrics/histogram_functions.h"
|
||
|
|
@@ -264,8 +268,17 @@
|
||
|
|
planes.reserve(num_color_planes);
|
||
|
|
for (size_t i = 0; i < num_buffers; ++i) {
|
||
|
|
const v4l2_plane_pix_format& plane_format = pix_mp.plane_fmt[i];
|
||
|
|
- planes.emplace_back(static_cast<int32_t>(plane_format.bytesperline), 0u,
|
||
|
|
- plane_format.sizeimage);
|
||
|
|
+ int32_t stride = static_cast<int32_t>(plane_format.bytesperline);
|
||
|
|
+ size_t sizeimage = plane_format.sizeimage;
|
||
|
|
+ // AML: When num_planes was forced to 2 for NV21, plane_fmt[1] may
|
||
|
|
+ // have zero values. Fill stride/size from plane0.
|
||
|
|
+ // Each vb2 plane is a separate DMA-BUF allocation, so offset=0 for all.
|
||
|
|
+ if (i > 0 && stride == 0 && num_buffers == 2) {
|
||
|
|
+ stride = static_cast<int32_t>(pix_mp.plane_fmt[0].bytesperline);
|
||
|
|
+ sizeimage = stride * pix_mp.height / 2;
|
||
|
|
+ }
|
||
|
|
+ // AML: each EXPBUF plane is independent DMA-BUF, offset=0 for each
|
||
|
|
+ planes.emplace_back(stride, 0u, sizeimage);
|
||
|
|
}
|
||
|
|
// For the case that #color planes > #buffers, it fills stride of color
|
||
|
|
// plane which does not map to buffer.
|
||
|
|
@@ -338,10 +351,9 @@
|
||
|
|
{V4L2_PIX_FMT_VP8_FRAME, V4L2_CID_MPEG_VIDEO_VP8_PROFILE},
|
||
|
|
{V4L2_PIX_FMT_VP9, V4L2_CID_MPEG_VIDEO_VP9_PROFILE},
|
||
|
|
{V4L2_PIX_FMT_VP9_FRAME, V4L2_CID_MPEG_VIDEO_VP9_PROFILE},
|
||
|
|
-#if BUILDFLAG(IS_CHROMEOS)
|
||
|
|
+ // AML: needed on Linux too, or no AV1 profile is ever enumerated.
|
||
|
|
{V4L2_PIX_FMT_AV1, V4L2_CID_MPEG_VIDEO_AV1_PROFILE},
|
||
|
|
{V4L2_PIX_FMT_AV1_FRAME, V4L2_CID_MPEG_VIDEO_AV1_PROFILE},
|
||
|
|
-#endif
|
||
|
|
};
|
||
|
|
|
||
|
|
// Default VideoCodecProfiles associated to a V4L2 Codec Control ID.
|
||
|
|
@@ -359,9 +371,8 @@
|
||
|
|
#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||
|
|
{V4L2_CID_MPEG_VIDEO_VP8_PROFILE, {VP8PROFILE_ANY}},
|
||
|
|
{V4L2_CID_MPEG_VIDEO_VP9_PROFILE, {VP9PROFILE_PROFILE0}},
|
||
|
|
-#if BUILDFLAG(IS_CHROMEOS)
|
||
|
|
+ // AML: fallback used when the driver has no AV1 profile control.
|
||
|
|
{V4L2_CID_MPEG_VIDEO_AV1_PROFILE, {AV1PROFILE_PROFILE_MAIN}},
|
||
|
|
-#endif
|
||
|
|
};
|
||
|
|
|
||
|
|
// Correspondence from a VideoCodecProfiles to V4L2 codec described
|
||
|
|
@@ -379,10 +390,9 @@
|
||
|
|
{VP8PROFILE_ANY, MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_VP8, FRAME)},
|
||
|
|
{VP9PROFILE_PROFILE0, MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_VP9, FRAME)},
|
||
|
|
{VP9PROFILE_PROFILE2, MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_VP9, FRAME)},
|
||
|
|
-#if BUILDFLAG(IS_CHROMEOS)
|
||
|
|
+ // AML: the fourcc -> profile direction is not IS_CHROMEOS gated.
|
||
|
|
{AV1PROFILE_PROFILE_MAIN,
|
||
|
|
MAKE_V4L2_CODEC_PAIR(V4L2_PIX_FMT_AV1, FRAME)},
|
||
|
|
-#endif
|
||
|
|
};
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
@@ -545,8 +555,11 @@
|
||
|
|
|
||
|
|
uint32_t VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
|
||
|
|
bool slice_based) {
|
||
|
|
- CHECK(base::Contains(kVideoCodecProfileToV4L2CodecPixFmt, profile))
|
||
|
|
- << "Unsupported profile: " << GetProfileName(profile);
|
||
|
|
+ // AML: the header contract is INVALID for unmapped profiles, not a crash.
|
||
|
|
+ if (!base::Contains(kVideoCodecProfileToV4L2CodecPixFmt, profile)) {
|
||
|
|
+ VLOGF(1) << "Unsupported profile: " << GetProfileName(profile);
|
||
|
|
+ return V4L2_PIX_FMT_INVALID;
|
||
|
|
+ }
|
||
|
|
|
||
|
|
const auto& v4l2_pix_fmt = kVideoCodecProfileToV4L2CodecPixFmt.at(profile);
|
||
|
|
return slice_based ? v4l2_pix_fmt.first : v4l2_pix_fmt.second;
|
||
|
|
diff --git a/media/gpu/v4l2/v4l2_vda_helpers.cc b/media/gpu/v4l2/v4l2_vda_helpers.cc
|
||
|
|
--- a/media/gpu/v4l2/v4l2_vda_helpers.cc
|
||
|
|
+++ b/media/gpu/v4l2/v4l2_vda_helpers.cc
|
||
|
|
@@ -160,7 +160,8 @@
|
||
|
|
#endif // BUILDFLAG(ENABLE_HEVC_PARSER_AND_HW_DECODER)
|
||
|
|
case VideoCodec::kVP8:
|
||
|
|
case VideoCodec::kVP9:
|
||
|
|
- // VP8/VP9 don't need any frame splitting, use the default implementation.
|
||
|
|
+ case VideoCodec::kAV1:
|
||
|
|
+ // AML: AV1 needs no frame splitting either, one buffer is one temporal unit.
|
||
|
|
return std::make_unique<v4l2_vda_helpers::InputBufferFragmentSplitter>();
|
||
|
|
default:
|
||
|
|
LOG(ERROR) << "Unhandled profile: " << profile;
|
||
|
|
diff --git a/media/media_options.gni b/media/media_options.gni
|
||
|
|
index e235287ebb..36e13c3e91 100644
|
||
|
|
--- a/media/media_options.gni
|
||
|
|
+++ b/media/media_options.gni
|
||
|
|
@@ -347,6 +347,14 @@ declare_args() {
|
||
|
|
chrome_wide_echo_cancellation_supported = is_win || is_mac || is_linux
|
||
|
|
}
|
||
|
|
|
||
|
|
+declare_args() {
|
||
|
|
+ is_amlogic_media=false
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+declare_args() {
|
||
|
|
+ widevine_version=0
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
# Do not expand this list without double-checking with OWNERS, this is a list of
|
||
|
|
# all targets which roll up into the //media component. It controls visibility
|
||
|
|
# of subcomponent targets and public_deps for //media.
|
||
|
|
diff --git a/media/mojo/BUILD.gn b/media/mojo/BUILD.gn
|
||
|
|
index 9573d77ba8..92ecf99112 100644
|
||
|
|
--- a/media/mojo/BUILD.gn
|
||
|
|
+++ b/media/mojo/BUILD.gn
|
||
|
|
@@ -55,6 +55,7 @@ buildflag_header("buildflags") {
|
||
|
|
"ENABLE_MOJO_VIDEO_DECODER=$enable_mojo_video_decoder",
|
||
|
|
"ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS=$enable_mojo_media_in_browser_process",
|
||
|
|
"ENABLE_MOJO_MEDIA_IN_GPU_PROCESS=$enable_mojo_media_in_gpu_process",
|
||
|
|
+ "IS_AMLOGIC_MEDIA=$is_amlogic_media",
|
||
|
|
]
|
||
|
|
}
|
||
|
|
|
||
|
|
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn
|
||
|
|
index 3e2dac7991..b3911dcf35 100644
|
||
|
|
--- a/media/mojo/services/BUILD.gn
|
||
|
|
+++ b/media/mojo/services/BUILD.gn
|
||
|
|
@@ -119,6 +119,11 @@ component("services") {
|
||
|
|
sources += [ "gpu_mojo_media_client_mac.cc" ]
|
||
|
|
} else if (is_win) {
|
||
|
|
sources += [ "gpu_mojo_media_client_win.cc" ]
|
||
|
|
+ } else if (is_amlogic_media) {
|
||
|
|
+ sources += [ "gpu_mojo_media_client_amlogic.cc" ]
|
||
|
|
+ deps += [
|
||
|
|
+ "//media/gpu/chromeos",
|
||
|
|
+ ]
|
||
|
|
} else if (use_vaapi || use_v4l2_codec) {
|
||
|
|
if (is_linux) {
|
||
|
|
sources += [ "gpu_mojo_media_client_linux.cc" ]
|
||
|
|
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc
|
||
|
|
index 7a739e1d73..0475c34757 100644
|
||
|
|
--- a/media/mojo/services/gpu_mojo_media_client.cc
|
||
|
|
+++ b/media/mojo/services/gpu_mojo_media_client.cc
|
||
|
|
@@ -3,6 +3,7 @@
|
||
|
|
// found in the LICENSE file.
|
||
|
|
|
||
|
|
#include "media/mojo/services/gpu_mojo_media_client.h"
|
||
|
|
+#include "media/mojo/buildflags.h"
|
||
|
|
|
||
|
|
#include <optional>
|
||
|
|
#include <utility>
|
||
|
|
@@ -156,12 +157,16 @@ GpuMojoMediaClient::GetSupportedVideoDecoderConfigs() {
|
||
|
|
if (!supported_config_cache_) {
|
||
|
|
// Only bother to query if accelerated video decoding is enabled.
|
||
|
|
// (RenderMediaClient does not know about GPU features before it asks.)
|
||
|
|
+#if BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
+ {
|
||
|
|
+#else
|
||
|
|
if (gpu_preferences_.disable_accelerated_video_decode ||
|
||
|
|
(gpu_feature_info_
|
||
|
|
.status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE] !=
|
||
|
|
gpu::kGpuFeatureStatusEnabled)) {
|
||
|
|
supported_config_cache_ = SupportedVideoDecoderConfigs();
|
||
|
|
} else {
|
||
|
|
+#endif
|
||
|
|
supported_config_cache_ = GetPlatformSupportedVideoDecoderConfigs();
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -230,12 +235,14 @@ std::unique_ptr<VideoDecoder> GpuMojoMediaClient::CreateVideoDecoder(
|
||
|
|
const gfx::ColorSpace& target_color_space,
|
||
|
|
mojo::PendingRemote<stable::mojom::StableVideoDecoder> oop_video_decoder) {
|
||
|
|
// Always respect GPU features.
|
||
|
|
+#if !BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
if (gpu_preferences_.disable_accelerated_video_decode ||
|
||
|
|
(gpu_feature_info_
|
||
|
|
.status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE] !=
|
||
|
|
gpu::kGpuFeatureStatusEnabled)) {
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
+#endif
|
||
|
|
// All implementations require a command buffer.
|
||
|
|
if (!command_buffer_id)
|
||
|
|
return nullptr;
|
||
|
|
diff --git a/ui/ozone/common/BUILD.gn b/ui/ozone/common/BUILD.gn
|
||
|
|
index 7ce40f68de..1036e37a91 100644
|
||
|
|
--- a/ui/ozone/common/BUILD.gn
|
||
|
|
+++ b/ui/ozone/common/BUILD.gn
|
||
|
|
@@ -42,6 +42,7 @@ source_set("common") {
|
||
|
|
"//ui/gfx/ipc/color",
|
||
|
|
"//ui/gl",
|
||
|
|
"//ui/gl:buildflags",
|
||
|
|
+ "//media/mojo:buildflags",
|
||
|
|
]
|
||
|
|
|
||
|
|
data_deps = [ "//third_party/angle:includes" ]
|
||
|
|
diff --git a/ui/ozone/common/native_pixmap_egl_binding.cc b/ui/ozone/common/native_pixmap_egl_binding.cc
|
||
|
|
index b945e14226..b1b0dda89b 100644
|
||
|
|
--- a/ui/ozone/common/native_pixmap_egl_binding.cc
|
||
|
|
+++ b/ui/ozone/common/native_pixmap_egl_binding.cc
|
||
|
|
@@ -8,6 +8,7 @@
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#include "ui/ozone/common/native_pixmap_egl_binding.h"
|
||
|
|
+#include "media/mojo/buildflags.h"
|
||
|
|
|
||
|
|
#include "base/logging.h"
|
||
|
|
#include "base/memory/scoped_refptr.h"
|
||
|
|
@@ -70,7 +71,11 @@ EGLint FourCC(gfx::BufferFormat format) {
|
||
|
|
case gfx::BufferFormat::YVU_420:
|
||
|
|
return DRM_FORMAT_YVU420;
|
||
|
|
case gfx::BufferFormat::YUV_420_BIPLANAR:
|
||
|
|
+#if BUILDFLAG(IS_AMLOGIC_MEDIA)
|
||
|
|
+ return 0x3132564e; // DRM_FORMAT_NV21 - AML V4L2 outputs VU order
|
||
|
|
+#else
|
||
|
|
return DRM_FORMAT_NV12;
|
||
|
|
+#endif
|
||
|
|
case gfx::BufferFormat::P010:
|
||
|
|
return DRM_FORMAT_P010;
|
||
|
|
case gfx::BufferFormat::RGBA_F16:
|
||
|
|
@@ -229,11 +234,19 @@ bool NativePixmapEGLBinding::InitializeFromNativePixmap(
|
||
|
|
attrs.push_back(kPlaneOffsetAttrs[attrs_plane]);
|
||
|
|
attrs.push_back(pixmap->GetDmaBufOffset(attrs_plane));
|
||
|
|
attrs.push_back(kPlanePitchAttrs[attrs_plane]);
|
||
|
|
- attrs.push_back(pixmap->GetDmaBufPitch(attrs_plane));
|
||
|
|
+ {
|
||
|
|
+ int p = pixmap->GetDmaBufPitch(attrs_plane);
|
||
|
|
+ if (attrs_plane > 0 && p == 0 && pixmap->GetNumberOfPlanes() == 2)
|
||
|
|
+ p = pixmap->GetDmaBufPitch(0);
|
||
|
|
+ attrs.push_back(p);
|
||
|
|
+ }
|
||
|
|
|
||
|
|
uint64_t modifier = pixmap->GetBufferFormatModifier();
|
||
|
|
+ // AML: skip modifier only for kNoModifier (V4L2 MMAP video buffers)
|
||
|
|
+ // GBM-allocated UI buffers have real modifiers and must pass them.
|
||
|
|
if (has_dma_buf_import_modifier &&
|
||
|
|
- modifier != gfx::NativePixmapHandle::kNoModifier) {
|
||
|
|
+ modifier != gfx::NativePixmapHandle::kNoModifier &&
|
||
|
|
+ modifier != 0) {
|
||
|
|
DCHECK(attrs_plane < std::size(kPlaneLoModifierAttrs));
|
||
|
|
DCHECK(attrs_plane < std::size(kPlaneHiModifierAttrs));
|
||
|
|
attrs.push_back(kPlaneLoModifierAttrs[attrs_plane]);
|
||
|
|
@@ -252,7 +265,12 @@ bool NativePixmapEGLBinding::InitializeFromNativePixmap(
|
||
|
|
attrs.push_back(EGL_DMA_BUF_PLANE0_OFFSET_EXT);
|
||
|
|
attrs.push_back(pixmap->GetDmaBufOffset(pixmap_plane));
|
||
|
|
attrs.push_back(EGL_DMA_BUF_PLANE0_PITCH_EXT);
|
||
|
|
- attrs.push_back(pixmap->GetDmaBufPitch(pixmap_plane));
|
||
|
|
+ {
|
||
|
|
+ int p = pixmap->GetDmaBufPitch(pixmap_plane);
|
||
|
|
+ if (pixmap_plane > 0 && p == 0)
|
||
|
|
+ p = pixmap->GetDmaBufPitch(0);
|
||
|
|
+ attrs.push_back(p);
|
||
|
|
+ }
|
||
|
|
attrs.push_back(EGL_NONE);
|
||
|
|
}
|
||
|
|
|