Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

Commit

Permalink
Mac Overlays: Enable h264 overlays
Browse files Browse the repository at this point in the history
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 7ed442b)

Review URL: https://codereview.chromium.org/1307863010 .

Cr-Commit-Position: refs/branch-heads/2490@{#199}
Cr-Branched-From: 7790a35-refs/heads/master@{#344925}
  • Loading branch information
ccameron-chromium committed Sep 9, 2015
1 parent 4b0be58 commit 3ffaac7
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 23 deletions.
14 changes: 8 additions & 6 deletions content/browser/compositor/gpu_process_transport_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()));
}
}

Expand Down
4 changes: 3 additions & 1 deletion content/common/gpu/media/gpu_video_decode_accelerator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
61 changes: 51 additions & 10 deletions content/common/gpu/media/vt_video_decode_accelerator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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),
Expand All @@ -305,6 +319,7 @@ VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
}

VTVideoDecodeAccelerator::~VTVideoDecodeAccelerator() {
DCHECK(gpu_thread_checker_.CalledOnValidThread());
}

bool VTVideoDecodeAccelerator::Initialize(
Expand Down Expand Up @@ -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
Expand All @@ -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();
Expand Down Expand Up @@ -985,17 +1007,21 @@ 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";
NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
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(
Expand All @@ -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;
}

Expand Down
34 changes: 28 additions & 6 deletions content/common/gpu/media/vt_video_decode_accelerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 {

Expand All @@ -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.
Expand Down Expand Up @@ -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_|.
//
Expand Down Expand Up @@ -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_;

Expand Down Expand Up @@ -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.
//
Expand Down

0 comments on commit 3ffaac7

Please sign in to comment.