summaryrefslogtreecommitdiff
path: root/chromium/media/renderers/yuv_util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/renderers/yuv_util.cc')
-rw-r--r--chromium/media/renderers/yuv_util.cc245
1 files changed, 171 insertions, 74 deletions
diff --git a/chromium/media/renderers/yuv_util.cc b/chromium/media/renderers/yuv_util.cc
index 3a66d63bd94..91ede20c4ee 100644
--- a/chromium/media/renderers/yuv_util.cc
+++ b/chromium/media/renderers/yuv_util.cc
@@ -9,7 +9,9 @@
#include "components/viz/common/gpu/raster_context_provider.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/raster_interface.h"
+#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
#include "media/base/video_frame.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/gpu/GrContext.h"
@@ -18,72 +20,165 @@ namespace media {
namespace {
-static constexpr size_t kNumNV12Planes = 2;
-static constexpr size_t kNumYUVPlanes = 3;
-using YUVMailboxes = std::array<gpu::MailboxHolder, kNumYUVPlanes>;
-
-YUVMailboxes GetYUVMailboxes(const VideoFrame* video_frame,
- gpu::raster::RasterInterface* ri) {
- YUVMailboxes mailboxes;
-
- for (size_t i = 0; i < video_frame->NumTextures(); ++i) {
- mailboxes[i] = video_frame->mailbox_holder(i);
- DCHECK(mailboxes[i].texture_target == GL_TEXTURE_2D ||
- mailboxes[i].texture_target == GL_TEXTURE_EXTERNAL_OES ||
- mailboxes[i].texture_target == GL_TEXTURE_RECTANGLE_ARB)
- << "Unsupported texture target " << std::hex << std::showbase
- << mailboxes[i].texture_target;
- ri->WaitSyncTokenCHROMIUM(mailboxes[i].sync_token.GetConstData());
- }
-
- return mailboxes;
-}
+enum YUVIndex : size_t {
+ kYIndex = 0,
+ kUIndex = 1,
+ kVIndex = 2,
+};
+static constexpr size_t kNumNV12Planes = kUIndex + 1;
+static constexpr size_t kNumYUVPlanes = kVIndex + 1;
+using YUVMailboxes = std::array<gpu::MailboxHolder, kNumYUVPlanes>;
struct YUVPlaneTextureInfo {
GrGLTextureInfo texture = {0, 0};
bool is_shared_image = false;
};
using YUVTexturesInfo = std::array<YUVPlaneTextureInfo, kNumYUVPlanes>;
-YUVTexturesInfo GetYUVTexturesInfo(
- const VideoFrame* video_frame,
- viz::RasterContextProvider* raster_context_provider) {
- gpu::raster::RasterInterface* ri = raster_context_provider->RasterInterface();
- DCHECK(ri);
- YUVMailboxes mailboxes = GetYUVMailboxes(video_frame, ri);
- YUVTexturesInfo yuv_textures_info;
-
- GrGLenum skia_texture_format =
- video_frame->format() == PIXEL_FORMAT_NV12 ? GL_RGB8 : GL_R8_EXT;
- for (size_t i = 0; i < video_frame->NumTextures(); ++i) {
- yuv_textures_info[i].texture.fID =
- ri->CreateAndConsumeForGpuRaster(mailboxes[i].mailbox);
- if (mailboxes[i].mailbox.IsSharedImage()) {
- yuv_textures_info[i].is_shared_image = true;
- ri->BeginSharedImageAccessDirectCHROMIUM(
- yuv_textures_info[i].texture.fID,
- GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
+class VideoFrameYUVMailboxesHolder {
+ public:
+ VideoFrameYUVMailboxesHolder(const VideoFrame* video_frame,
+ viz::RasterContextProvider* provider,
+ bool import_textures)
+ : provider_(provider) {
+ DCHECK(video_frame);
+ DCHECK(video_frame->HasTextures() || video_frame->IsMappable());
+ DCHECK(video_frame->format() == PIXEL_FORMAT_I420 |
+ video_frame->format() == PIXEL_FORMAT_NV12)
+ << "VideoFrame has an unsupported YUV format " << video_frame->format();
+ is_nv12_ = video_frame->format() == PIXEL_FORMAT_NV12;
+
+ DCHECK(provider_);
+ auto* ri = provider_->RasterInterface();
+ DCHECK(ri);
+
+ if (video_frame->HasTextures()) {
+ video_frame_owns_holders_ = true;
+ for (size_t plane = 0; plane < video_frame->NumTextures(); ++plane) {
+ holders_[plane] = video_frame->mailbox_holder(plane);
+ DCHECK(holders_[plane].texture_target == GL_TEXTURE_2D ||
+ holders_[plane].texture_target == GL_TEXTURE_EXTERNAL_OES ||
+ holders_[plane].texture_target == GL_TEXTURE_RECTANGLE_ARB)
+ << "Unsupported texture target " << std::hex << std::showbase
+ << holders_[plane].texture_target;
+ ri->WaitSyncTokenCHROMIUM(holders_[plane].sync_token.GetConstData());
+ }
+ } else {
+ DCHECK(!is_nv12_) << "NV12 CPU backed VideoFrames aren't supported.";
+ video_frame_owns_holders_ = false;
+ gfx::Size y_size = video_frame->coded_size();
+ gfx::Size uv_size = gfx::Size(y_size.width() / 2, y_size.height() / 2);
+
+ auto* sii = provider_->SharedImageInterface();
+ DCHECK(sii);
+ uint32_t mailbox_usage;
+ if (provider_->ContextCapabilities().supports_oop_raster) {
+ mailbox_usage = gpu::SHARED_IMAGE_USAGE_RASTER |
+ gpu::SHARED_IMAGE_USAGE_OOP_RASTERIZATION;
+ } else {
+ mailbox_usage = gpu::SHARED_IMAGE_USAGE_GLES2;
+ }
+ for (size_t plane = 0; plane < kNumYUVPlanes; ++plane) {
+ gfx::Size tex_size = plane == kYIndex ? y_size : uv_size;
+ holders_[plane].mailbox =
+ sii->CreateSharedImage(viz::ResourceFormat::LUMINANCE_8, tex_size,
+ video_frame->ColorSpace(), mailbox_usage);
+ holders_[plane].texture_target = GL_TEXTURE_2D;
+ }
+
+ // Split up shared image creation from upload so we only have to wait on
+ // one sync token.
+ ri->WaitSyncTokenCHROMIUM(sii->GenUnverifiedSyncToken().GetConstData());
+ for (size_t plane = 0; plane < kNumYUVPlanes; ++plane) {
+ gfx::Size tex_size = plane == kYIndex ? y_size : uv_size;
+ SkImageInfo info =
+ SkImageInfo::Make(tex_size.width(), tex_size.height(),
+ kGray_8_SkColorType, kUnknown_SkAlphaType);
+ ri->WritePixels(holders_[plane].mailbox, 0, 0, GL_TEXTURE_2D,
+ video_frame->stride(plane), info,
+ video_frame->data(plane));
+ }
}
- yuv_textures_info[i].texture.fTarget = mailboxes[i].texture_target;
- yuv_textures_info[i].texture.fFormat = skia_texture_format;
+ if (import_textures) {
+ ImportTextures();
+ }
}
- return yuv_textures_info;
-}
+ ~VideoFrameYUVMailboxesHolder() {
+ auto* ri = provider_->RasterInterface();
+ DCHECK(ri);
+ if (imported_textures_) {
+ for (auto& tex_info : textures_) {
+ if (!tex_info.texture.fID)
+ continue;
+
+ if (tex_info.is_shared_image)
+ ri->EndSharedImageAccessDirectCHROMIUM(tex_info.texture.fID);
+ ri->DeleteGpuRasterTexture(tex_info.texture.fID);
+ }
+ }
-void DeleteYUVTextures(const VideoFrame* video_frame,
- viz::RasterContextProvider* raster_context_provider,
- const YUVTexturesInfo& yuv_textures_info) {
- gpu::raster::RasterInterface* ri = raster_context_provider->RasterInterface();
- DCHECK(ri);
+ // Don't destroy shared images we don't own.
+ if (video_frame_owns_holders_)
+ return;
- for (size_t i = 0; i < video_frame->NumTextures(); ++i) {
- if (yuv_textures_info[i].is_shared_image)
- ri->EndSharedImageAccessDirectCHROMIUM(yuv_textures_info[i].texture.fID);
- ri->DeleteGpuRasterTexture(yuv_textures_info[i].texture.fID);
+ gpu::SyncToken token;
+ ri->GenUnverifiedSyncTokenCHROMIUM(token.GetData());
+
+ auto* sii = provider_->SharedImageInterface();
+ DCHECK(sii);
+ for (auto& mailbox_holder : holders_) {
+ if (!mailbox_holder.mailbox.IsZero())
+ sii->DestroySharedImage(token, mailbox_holder.mailbox);
+ mailbox_holder.mailbox.SetZero();
+ }
}
-}
+
+ bool is_nv12() { return is_nv12_; }
+
+ const gpu::Mailbox& mailbox(size_t plane) {
+ DCHECK_LE(plane, is_nv12_ ? kNumNV12Planes : kNumYUVPlanes);
+ return holders_[plane].mailbox;
+ }
+
+ const GrGLTextureInfo& texture(size_t plane) {
+ DCHECK_LE(plane, is_nv12_ ? kNumNV12Planes : kNumYUVPlanes);
+ DCHECK(imported_textures_);
+ return textures_[plane].texture;
+ }
+
+ private:
+ void ImportTextures() {
+ auto* ri = provider_->RasterInterface();
+ GrGLenum skia_texture_format = is_nv12_ ? GL_RGB8 : GL_LUMINANCE8_EXT;
+ for (size_t plane = 0; plane < NumPlanes(); ++plane) {
+ textures_[plane].texture.fID =
+ ri->CreateAndConsumeForGpuRaster(holders_[plane].mailbox);
+ if (holders_[plane].mailbox.IsSharedImage()) {
+ textures_[plane].is_shared_image = true;
+ ri->BeginSharedImageAccessDirectCHROMIUM(
+ textures_[plane].texture.fID,
+ GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
+ }
+
+ textures_[plane].texture.fTarget = holders_[plane].texture_target;
+ textures_[plane].texture.fFormat = skia_texture_format;
+ }
+
+ imported_textures_ = true;
+ }
+
+ size_t NumPlanes() { return is_nv12_ ? kNumNV12Planes : kNumYUVPlanes; }
+
+ viz::RasterContextProvider* provider_ = nullptr;
+ bool imported_textures_ = false;
+ bool video_frame_owns_holders_ = false;
+ bool is_nv12_ = false;
+
+ YUVMailboxes holders_;
+ YUVTexturesInfo textures_;
+};
void ConvertFromVideoFrameYUVWithGrContext(
const VideoFrame* video_frame,
@@ -99,9 +194,8 @@ void ConvertFromVideoFrameYUVWithGrContext(
dest_tex_id, GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
}
// Let the SkImage fall out of scope and track the result using dest_tex_id
- NewSkImageFromVideoFrameYUVTexturesWithExternalBackend(
- video_frame, raster_context_provider, dest_mailbox_holder.texture_target,
- dest_tex_id);
+ NewSkImageFromVideoFrameYUV(video_frame, raster_context_provider,
+ dest_mailbox_holder.texture_target, dest_tex_id);
if (dest_mailbox_holder.mailbox.IsSharedImage())
ri->EndSharedImageAccessDirectCHROMIUM(dest_tex_id);
ri->DeleteGpuRasterTexture(dest_tex_id);
@@ -132,28 +226,33 @@ void ConvertFromVideoFrameYUV(
auto* ri = raster_context_provider->RasterInterface();
DCHECK(ri);
ri->WaitSyncTokenCHROMIUM(dest_mailbox_holder.sync_token.GetConstData());
- YUVMailboxes mailboxes = GetYUVMailboxes(video_frame, ri);
SkYUVColorSpace color_space =
ColorSpaceToSkYUVColorSpace(video_frame->ColorSpace());
- if (video_frame->format() == PIXEL_FORMAT_I420) {
+
+ VideoFrameYUVMailboxesHolder yuv_mailboxes(video_frame,
+ raster_context_provider, false);
+
+ if (yuv_mailboxes.is_nv12()) {
+ ri->ConvertNV12MailboxesToRGB(dest_mailbox_holder.mailbox, color_space,
+ yuv_mailboxes.mailbox(kYIndex),
+ yuv_mailboxes.mailbox(kUIndex));
+ } else {
DCHECK_EQ(video_frame->NumTextures(), kNumYUVPlanes);
ri->ConvertYUVMailboxesToRGB(dest_mailbox_holder.mailbox, color_space,
- mailboxes[0].mailbox, mailboxes[1].mailbox,
- mailboxes[2].mailbox);
- } else {
- DCHECK_EQ(video_frame->format(), PIXEL_FORMAT_NV12);
- DCHECK_EQ(video_frame->NumTextures(), kNumNV12Planes);
- ri->ConvertNV12MailboxesToRGB(dest_mailbox_holder.mailbox, color_space,
- mailboxes[0].mailbox, mailboxes[1].mailbox);
+ yuv_mailboxes.mailbox(kYIndex),
+ yuv_mailboxes.mailbox(kUIndex),
+ yuv_mailboxes.mailbox(kVIndex));
}
}
-sk_sp<SkImage> NewSkImageFromVideoFrameYUVTexturesWithExternalBackend(
+sk_sp<SkImage> NewSkImageFromVideoFrameYUV(
const VideoFrame* video_frame,
viz::RasterContextProvider* raster_context_provider,
unsigned int texture_target,
unsigned int texture_id) {
- DCHECK(video_frame->HasTextures());
+ DCHECK(video_frame->HasTextures() ||
+ (video_frame->IsMappable() &&
+ video_frame->format() == PIXEL_FORMAT_I420));
GrContext* gr_context = raster_context_provider->GrContext();
DCHECK(gr_context);
// TODO: We should compare the DCHECK vs when UpdateLastImage calls this
@@ -167,16 +266,16 @@ sk_sp<SkImage> NewSkImageFromVideoFrameYUVTexturesWithExternalBackend(
GrGLTextureInfo backend_texture{};
- YUVTexturesInfo yuv_textures_info =
- GetYUVTexturesInfo(video_frame, raster_context_provider);
+ VideoFrameYUVMailboxesHolder yuv_textures_info(video_frame,
+ raster_context_provider, true);
GrBackendTexture yuv_textures[3] = {
GrBackendTexture(ya_tex_size.width(), ya_tex_size.height(),
- GrMipMapped::kNo, yuv_textures_info[0].texture),
+ GrMipMapped::kNo, yuv_textures_info.texture(kYIndex)),
GrBackendTexture(uv_tex_size.width(), uv_tex_size.height(),
- GrMipMapped::kNo, yuv_textures_info[1].texture),
+ GrMipMapped::kNo, yuv_textures_info.texture(kUIndex)),
GrBackendTexture(uv_tex_size.width(), uv_tex_size.height(),
- GrMipMapped::kNo, yuv_textures_info[2].texture),
+ GrMipMapped::kNo, yuv_textures_info.texture(kVIndex)),
};
backend_texture.fID = texture_id;
backend_texture.fTarget = texture_target;
@@ -188,9 +287,7 @@ sk_sp<SkImage> NewSkImageFromVideoFrameYUVTexturesWithExternalBackend(
sk_sp<SkImage> img = YUVGrBackendTexturesToSkImage(
gr_context, video_frame->ColorSpace(), video_frame->format(),
yuv_textures, result_texture);
- gr_context->flush();
-
- DeleteYUVTextures(video_frame, raster_context_provider, yuv_textures_info);
+ gr_context->flushAndSubmit();
return img;
}