diff options
Diffstat (limited to 'chromium/media/renderers/yuv_util.cc')
-rw-r--r-- | chromium/media/renderers/yuv_util.cc | 245 |
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; } |