blob: 0954dd8fda511c8601d913b033ac392d15c0fa78 [file] [log] [blame]
// 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.
#include "media/gpu/chromeos/gpu_memory_buffer_video_frame_mapper.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "media/gpu/macros.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace media {
// static
std::unique_ptr<GpuMemoryBufferVideoFrameMapper>
GpuMemoryBufferVideoFrameMapper::Create(VideoPixelFormat format) {
return base::WrapUnique(new GpuMemoryBufferVideoFrameMapper(format));
}
GpuMemoryBufferVideoFrameMapper::GpuMemoryBufferVideoFrameMapper(
VideoPixelFormat format)
: VideoFrameMapper(format) {}
scoped_refptr<VideoFrame> GpuMemoryBufferVideoFrameMapper::Map(
scoped_refptr<const VideoFrame> video_frame) const {
if (!video_frame) {
LOG(ERROR) << "Video frame is nullptr";
return nullptr;
}
if (video_frame->storage_type() !=
VideoFrame::StorageType::STORAGE_GPU_MEMORY_BUFFER) {
VLOGF(1) << "VideoFrame's storage type is not GPU_MEMORY_BUFFER: "
<< video_frame->storage_type();
return nullptr;
}
if (video_frame->format() != format_) {
VLOGF(1) << "Unexpected format: " << video_frame->format()
<< ", expected: " << format_;
return nullptr;
}
gfx::GpuMemoryBuffer* gmb = video_frame->GetGpuMemoryBuffer();
if (!gmb)
return nullptr;
if (!gmb->Map()) {
VLOGF(1) << "Failed to map GpuMemoryBuffer";
return nullptr;
}
const size_t num_planes = VideoFrame::NumPlanes(format_);
uint8_t* plane_addrs[VideoFrame::kMaxPlanes] = {};
for (size_t i = 0; i < num_planes; i++)
plane_addrs[i] = static_cast<uint8_t*>(gmb->memory(i));
scoped_refptr<VideoFrame> mapped_frame;
if (IsYuvPlanar(format_)) {
mapped_frame = VideoFrame::WrapExternalYuvDataWithLayout(
video_frame->layout(), video_frame->visible_rect(),
video_frame->natural_size(), plane_addrs[0], plane_addrs[1],
plane_addrs[2], video_frame->timestamp());
} else if (num_planes == 1) {
size_t buffer_size = VideoFrame::AllocationSize(
format_, gfx::Size(gmb->stride(0), gmb->GetSize().height()));
mapped_frame = VideoFrame::WrapExternalDataWithLayout(
video_frame->layout(), video_frame->visible_rect(),
video_frame->natural_size(), plane_addrs[0], buffer_size,
video_frame->timestamp());
}
if (!mapped_frame) {
gmb->Unmap();
return nullptr;
}
mapped_frame->set_color_space(video_frame->ColorSpace());
mapped_frame->metadata().MergeMetadataFrom(video_frame->metadata());
// Pass |video_frame| so that it outlives |mapped_frame| and the mapped buffer
// is unmapped on destruction.
mapped_frame->AddDestructionObserver(base::BindOnce(
[](scoped_refptr<const VideoFrame> frame) {
DCHECK(frame->HasGpuMemoryBuffer());
frame->GetGpuMemoryBuffer()->Unmap();
},
std::move(video_frame)));
return mapped_frame;
}
} // namespace media