diff options
author | Christopher Cameron <ccameron@chromium.org> | 2015-09-09 11:59:32 -0700 |
---|---|---|
committer | Christopher Cameron <ccameron@chromium.org> | 2015-09-09 19:00:50 +0000 |
commit | 3ffaac7291241cb501afa8996c9a5fb3cfbff842 (patch) | |
tree | 5555115e32a495890ff3476ef28fc05ffb9c64d8 | |
parent | 4b0be58dce5fc85e93d461c9a5023caff1bb2870 (diff) | |
download | chromium_src-3ffaac7291241cb501afa8996c9a5fb3cfbff842.zip chromium_src-3ffaac7291241cb501afa8996c9a5fb3cfbff842.tar.gz chromium_src-3ffaac7291241cb501afa8996c9a5fb3cfbff842.tar.bz2 |
Mac Overlays: Enable h264 overlays
Punch a hole from GpuVideoDecodeAccelerator to VTVideoDecodeAccelerator
via a callback to BindImage, following the model found in
VaapiVideoDecodeAccelerator. If successful, set allow_overlay on the
frame's resource.
BUG=527650
Review URL: https://codereview.chromium.org/1320893004
Cr-Commit-Position: refs/heads/master@{#347546}
(cherry picked from commit 7ed442bbaf3a5038ce6b9d712200557a0854f888)
Review URL: https://codereview.chromium.org/1307863010 .
Cr-Commit-Position: refs/branch-heads/2490@{#199}
Cr-Branched-From: 7790a3535f2a81a03685eca31a32cf69ae0c114f-refs/heads/master@{#344925}
4 files changed, 90 insertions, 23 deletions
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index 7bfccf7..a5b1433 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc @@ -316,12 +316,14 @@ void GpuProcessTransportFactory::EstablishedGpuChannel( CreateOverlayCandidateValidator(compositor->widget()), target, format, BrowserGpuMemoryBufferManager::current())); } else { - if (!surface) { - surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface( - context_provider, shared_worker_context_provider_, - compositor->vsync_manager(), - CreateOverlayCandidateValidator(compositor->widget()))); - } + scoped_ptr<BrowserCompositorOverlayCandidateValidator> validator; +#if !defined(OS_MACOSX) + // Overlays are only supported on surfaceless output surfaces on Mac. + validator = CreateOverlayCandidateValidator(compositor->widget()); +#endif + surface = make_scoped_ptr(new GpuBrowserCompositorOutputSurface( + context_provider, shared_worker_context_provider_, + compositor->vsync_manager(), validator.Pass())); } } diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc index 9f78d23..a0321c5a 100644 --- a/content/common/gpu/media/gpu_video_decode_accelerator.cc +++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc @@ -358,7 +358,9 @@ scoped_ptr<media::VideoDecodeAccelerator> GpuVideoDecodeAccelerator::CreateVTVDA() { scoped_ptr<media::VideoDecodeAccelerator> decoder; #if defined(OS_MACOSX) - decoder.reset(new VTVideoDecodeAccelerator(make_context_current_)); + decoder.reset(new VTVideoDecodeAccelerator( + make_context_current_, base::Bind(&GpuVideoDecodeAccelerator::BindImage, + base::Unretained(this)))); #endif return decoder.Pass(); } diff --git a/content/common/gpu/media/vt_video_decode_accelerator.cc b/content/common/gpu/media/vt_video_decode_accelerator.cc index f7e5264..c98853d 100644 --- a/content/common/gpu/media/vt_video_decode_accelerator.cc +++ b/content/common/gpu/media/vt_video_decode_accelerator.cc @@ -21,6 +21,7 @@ #include "content/public/common/content_switches.h" #include "media/base/limits.h" #include "ui/gl/gl_context.h" +#include "ui/gl/gl_image_io_surface.h" #include "ui/gl/scoped_binders.h" using content_common_gpu_media::kModuleVt; @@ -274,6 +275,16 @@ VTVideoDecodeAccelerator::Frame::Frame(int32_t bitstream_id) VTVideoDecodeAccelerator::Frame::~Frame() { } +VTVideoDecodeAccelerator::PictureInfo::PictureInfo(uint32_t client_texture_id, + uint32_t service_texture_id) + : client_texture_id(client_texture_id), + service_texture_id(service_texture_id) {} + +VTVideoDecodeAccelerator::PictureInfo::~PictureInfo() { + if (gl_image) + gl_image->Destroy(false); +} + bool VTVideoDecodeAccelerator::FrameOrder::operator()( const linked_ptr<Frame>& lhs, const linked_ptr<Frame>& rhs) const { @@ -287,8 +298,11 @@ bool VTVideoDecodeAccelerator::FrameOrder::operator()( } VTVideoDecodeAccelerator::VTVideoDecodeAccelerator( - const base::Callback<bool(void)>& make_context_current) + const base::Callback<bool(void)>& make_context_current, + const base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)>& + bind_image) : make_context_current_(make_context_current), + bind_image_(bind_image), client_(nullptr), state_(STATE_DECODING), format_(nullptr), @@ -305,6 +319,7 @@ VTVideoDecodeAccelerator::VTVideoDecodeAccelerator( } VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() { + DCHECK(gpu_thread_checker_.CalledOnValidThread()); } bool VTVideoDecodeAccelerator::Initialize( @@ -810,10 +825,12 @@ void VTVideoDecodeAccelerator::AssignPictureBuffers( DCHECK(gpu_thread_checker_.CalledOnValidThread()); for (const media::PictureBuffer& picture : pictures) { - DCHECK(!texture_ids_.count(picture.id())); + DCHECK(!picture_info_map_.count(picture.id())); assigned_picture_ids_.insert(picture.id()); available_picture_ids_.push_back(picture.id()); - texture_ids_[picture.id()] = picture.texture_id(); + picture_info_map_.insert(picture.id(), make_scoped_ptr(new PictureInfo( + picture.internal_texture_id(), + picture.texture_id()))); } // Pictures are not marked as uncleared until after this method returns, and @@ -825,8 +842,13 @@ void VTVideoDecodeAccelerator::AssignPictureBuffers( void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) { DCHECK(gpu_thread_checker_.CalledOnValidThread()); - DCHECK_EQ(CFGetRetainCount(picture_bindings_[picture_id]), 1); - picture_bindings_.erase(picture_id); + DCHECK(picture_info_map_.count(picture_id)); + PictureInfo* picture_info = picture_info_map_.find(picture_id)->second; + DCHECK_EQ(CFGetRetainCount(picture_info->cv_image), 1); + picture_info->cv_image.reset(); + picture_info->gl_image->Destroy(false); + picture_info->gl_image = nullptr; + if (assigned_picture_ids_.count(picture_id) != 0) { available_picture_ids_.push_back(picture_id); ProcessWorkQueues(); @@ -985,7 +1007,10 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) { return false; int32_t picture_id = available_picture_ids_.back(); - IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame.image.get()); + DCHECK(picture_info_map_.count(picture_id)); + PictureInfo* picture_info = picture_info_map_.find(picture_id)->second; + DCHECK(!picture_info->cv_image); + DCHECK(!picture_info->gl_image); if (!make_context_current_.Run()) { DLOG(ERROR) << "Failed to make GL context current"; @@ -993,9 +1018,10 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) { return false; } + IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame.image.get()); glEnable(GL_TEXTURE_RECTANGLE_ARB); - gfx::ScopedTextureBinder - texture_binder(GL_TEXTURE_RECTANGLE_ARB, texture_ids_[picture_id]); + gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_RECTANGLE_ARB, + picture_info->service_texture_id); CGLContextObj cgl_context = static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle()); CGLError status = CGLTexImageIOSurface2D( @@ -1014,15 +1040,30 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) { return false; } + bool allow_overlay = false; + scoped_refptr<gfx::GLImageIOSurface> gl_image(new gfx::GLImageIOSurface( + gfx::GenericSharedMemoryId(), frame.coded_size, GL_BGRA_EXT)); + if (gl_image->Initialize(surface, gfx::BufferFormat::BGRA_8888)) { + allow_overlay = true; + } else { + gl_image = nullptr; + } + bind_image_.Run(picture_info->client_texture_id, GL_TEXTURE_RECTANGLE_ARB, + gl_image); + + // Assign the new image(s) to the the picture info. + picture_info->gl_image = gl_image; + picture_info->cv_image = frame.image; available_picture_ids_.pop_back(); - picture_bindings_[picture_id] = frame.image; + // TODO(sandersd): Currently, the size got from // CMVideoFormatDescriptionGetDimensions is visible size. We pass it to // GpuVideoDecoder so that GpuVideoDecoder can use correct visible size in // resolution changed. We should find the correct API to get the real // coded size and fix it. client_->PictureReady(media::Picture(picture_id, frame.bitstream_id, - gfx::Rect(frame.coded_size), false)); + gfx::Rect(frame.coded_size), + allow_overlay)); return true; } diff --git a/content/common/gpu/media/vt_video_decode_accelerator.h b/content/common/gpu/media/vt_video_decode_accelerator.h index 44f563b..0a38509 100644 --- a/content/common/gpu/media/vt_video_decode_accelerator.h +++ b/content/common/gpu/media/vt_video_decode_accelerator.h @@ -10,6 +10,7 @@ #include <map> #include <queue> +#include "base/containers/scoped_ptr_map.h" #include "base/mac/scoped_cftyperef.h" #include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" @@ -22,6 +23,7 @@ #include "media/video/video_decode_accelerator.h" #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_context_cgl.h" +#include "ui/gl/gl_image_io_surface.h" namespace content { @@ -33,7 +35,9 @@ bool InitializeVideoToolbox(); class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator { public: explicit VTVideoDecodeAccelerator( - const base::Callback<bool(void)>& make_context_current); + const base::Callback<bool(void)>& make_context_current, + const base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)>& + bind_image); ~VTVideoDecodeAccelerator() override; // VideoDecodeAccelerator implementation. @@ -113,6 +117,26 @@ class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator { linked_ptr<Frame> frame; }; + struct PictureInfo { + PictureInfo(uint32_t client_texture_id, uint32_t service_texture_id); + ~PictureInfo(); + + // Image buffer, kept alive while they are bound to pictures. + base::ScopedCFTypeRef<CVImageBufferRef> cv_image; + + // The GLImage representation of |cv_image|. This is kept around to ensure + // that Destroy is called on it before it hits its destructor (there is a + // DCHECK that requires this). + scoped_refptr<gfx::GLImageIOSurface> gl_image; + + // Texture IDs for the image buffer. + const uint32_t client_texture_id; + const uint32_t service_texture_id; + + private: + DISALLOW_COPY_AND_ASSIGN(PictureInfo); + }; + // // Methods for interacting with VideoToolbox. Run on |decoder_thread_|. // @@ -163,6 +187,7 @@ class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator { // GPU thread state. // base::Callback<bool(void)> make_context_current_; + base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)> bind_image_; media::VideoDecodeAccelerator::Client* client_; State state_; @@ -200,15 +225,12 @@ class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator { // released immediately because we need the reuse event to free the binding.) std::set<int32_t> assigned_picture_ids_; - // Texture IDs of assigned pictures. - std::map<int32_t, uint32_t> texture_ids_; + // Texture IDs and image buffers of assigned pictures. + base::ScopedPtrMap<int32_t, scoped_ptr<PictureInfo>> picture_info_map_; // Pictures ready to be rendered to. std::vector<int32_t> available_picture_ids_; - // Image buffers kept alive while they are bound to pictures. - std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_; - // // Decoder thread state. // |