| Index: cc/resources/video_resource_updater.cc
|
| diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
|
| index 7a775d9fe69d8be1bd0897e49d15c8f3fe8a9e54..2c9a688619adeb0087018be964281b8f9d17dcb8 100644
|
| --- a/cc/resources/video_resource_updater.cc
|
| +++ b/cc/resources/video_resource_updater.cc
|
| @@ -20,7 +20,6 @@ namespace cc {
|
|
|
| namespace {
|
|
|
| -const ResourceFormat kYUVResourceFormat = LUMINANCE_8;
|
| const ResourceFormat kRGBResourceFormat = RGBA_8888;
|
|
|
| class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
|
| @@ -40,6 +39,37 @@ class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
|
|
|
| } // namespace
|
|
|
| +VideoResourceUpdater::PlaneResource::PlaneResource(
|
| + unsigned int resource_id,
|
| + const gfx::Size& resource_size,
|
| + ResourceFormat resource_format,
|
| + gpu::Mailbox mailbox)
|
| + : resource_id(resource_id),
|
| + resource_size(resource_size),
|
| + resource_format(resource_format),
|
| + mailbox(mailbox),
|
| + frame_ptr(nullptr),
|
| + plane_index(0) {
|
| +}
|
| +
|
| +bool VideoResourceUpdater::PlaneResourceMatchesUniqueID(
|
| + const PlaneResource& plane_resource,
|
| + const media::VideoFrame* video_frame,
|
| + int plane_index) {
|
| + return plane_resource.frame_ptr == video_frame &&
|
| + plane_resource.plane_index == plane_index &&
|
| + plane_resource.timestamp == video_frame->timestamp();
|
| +}
|
| +
|
| +void VideoResourceUpdater::SetPlaneResourceUniqueId(
|
| + const media::VideoFrame* video_frame,
|
| + int plane_index,
|
| + PlaneResource* plane_resource) {
|
| + plane_resource->frame_ptr = video_frame;
|
| + plane_resource->plane_index = plane_index;
|
| + plane_resource->timestamp = video_frame->timestamp();
|
| +}
|
| +
|
| VideoFrameExternalResources::VideoFrameExternalResources() : type(NONE) {}
|
|
|
| VideoFrameExternalResources::~VideoFrameExternalResources() {}
|
| @@ -104,14 +134,12 @@ bool VideoResourceUpdater::VerifyFrame(
|
| // each plane in the frame.
|
| static gfx::Size SoftwarePlaneDimension(
|
| const scoped_refptr<media::VideoFrame>& input_frame,
|
| - ResourceFormat output_resource_format,
|
| + bool software_compositor,
|
| size_t plane_index) {
|
| - if (output_resource_format == kYUVResourceFormat) {
|
| + if (!software_compositor) {
|
| return media::VideoFrame::PlaneSize(
|
| input_frame->format(), plane_index, input_frame->coded_size());
|
| }
|
| -
|
| - DCHECK_EQ(output_resource_format, kRGBResourceFormat);
|
| return input_frame->coded_size();
|
| }
|
|
|
| @@ -145,7 +173,8 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
|
|
| bool software_compositor = context_provider_ == NULL;
|
|
|
| - ResourceFormat output_resource_format = kYUVResourceFormat;
|
| + ResourceFormat output_resource_format =
|
| + resource_provider_->yuv_resource_format();
|
| size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format);
|
|
|
| // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB
|
| @@ -163,7 +192,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
|
|
| for (size_t i = 0; i < output_plane_count; ++i) {
|
| gfx::Size output_plane_resource_size =
|
| - SoftwarePlaneDimension(video_frame, output_resource_format, i);
|
| + SoftwarePlaneDimension(video_frame, software_compositor, i);
|
| if (output_plane_resource_size.IsEmpty() ||
|
| output_plane_resource_size.width() > max_resource_size ||
|
| output_plane_resource_size.height() > max_resource_size) {
|
| @@ -171,57 +200,56 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| break;
|
| }
|
|
|
| - ResourceProvider::ResourceId resource_id = 0;
|
| - gpu::Mailbox mailbox;
|
| -
|
| // Try recycle a previously-allocated resource.
|
| - for (size_t i = 0; i < recycled_resources_.size(); ++i) {
|
| - bool resource_matches =
|
| - recycled_resources_[i].resource_format == output_resource_format &&
|
| - recycled_resources_[i].resource_size == output_plane_resource_size;
|
| - bool not_in_use =
|
| - !software_compositor || !resource_provider_->InUseByConsumer(
|
| - recycled_resources_[i].resource_id);
|
| - if (resource_matches && not_in_use) {
|
| - resource_id = recycled_resources_[i].resource_id;
|
| - mailbox = recycled_resources_[i].mailbox;
|
| - recycled_resources_.erase(recycled_resources_.begin() + i);
|
| - break;
|
| + auto recycled_it = recycled_resources_.end();
|
| + for (auto it = recycled_resources_.begin(); it != recycled_resources_.end();
|
| + ++it) {
|
| + const bool resource_matches =
|
| + it->resource_format == output_resource_format &&
|
| + it->resource_size == output_plane_resource_size;
|
| + const bool in_use = software_compositor &&
|
| + resource_provider_->InUseByConsumer(it->resource_id);
|
| + if (resource_matches && !in_use) {
|
| + // We found a recycled resource with the allocation size and format we
|
| + // are looking for.
|
| + recycled_it = it;
|
| + // Keep looking for a recycled resource that also contains the data we
|
| + // are planning to put in it.
|
| + if (PlaneResourceMatchesUniqueID(*it, video_frame.get(), i))
|
| + break;
|
| }
|
| }
|
|
|
| - if (resource_id == 0) {
|
| - // TODO(danakj): Abstract out hw/sw resource create/delete from
|
| - // ResourceProvider and stop using ResourceProvider in this class.
|
| - resource_id = resource_provider_->CreateResource(
|
| - output_plane_resource_size,
|
| - GL_CLAMP_TO_EDGE,
|
| - ResourceProvider::TextureHintImmutable,
|
| - output_resource_format);
|
| -
|
| - DCHECK(mailbox.IsZero());
|
| -
|
| - if (!software_compositor) {
|
| - DCHECK(context_provider_);
|
| -
|
| - gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
|
| -
|
| - GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name));
|
| - ResourceProvider::ScopedWriteLockGL lock(resource_provider_,
|
| - resource_id);
|
| - GLC(gl,
|
| - gl->ProduceTextureDirectCHROMIUM(
|
| - lock.texture_id(), GL_TEXTURE_2D, mailbox.name));
|
| - }
|
| -
|
| - if (resource_id)
|
| - all_resources_.push_back(resource_id);
|
| + // Check if we can avoid allocating a new resource.
|
| + if (recycled_it != recycled_resources_.end()) {
|
| + plane_resources.push_back(*recycled_it);
|
| + recycled_resources_.erase(recycled_it);
|
| + continue;
|
| }
|
|
|
| + // TODO(danakj): Abstract out hw/sw resource create/delete from
|
| + // ResourceProvider and stop using ResourceProvider in this class.
|
| + const ResourceProvider::ResourceId resource_id =
|
| + resource_provider_->CreateResource(
|
| + output_plane_resource_size, GL_CLAMP_TO_EDGE,
|
| + ResourceProvider::TextureHintImmutable, output_resource_format);
|
| if (resource_id == 0) {
|
| allocation_success = false;
|
| break;
|
| }
|
| + all_resources_.push_back(resource_id);
|
| +
|
| + gpu::Mailbox mailbox;
|
| + if (!software_compositor) {
|
| + DCHECK(context_provider_);
|
| +
|
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL();
|
| +
|
| + GLC(gl, gl->GenMailboxCHROMIUM(mailbox.name));
|
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider_, resource_id);
|
| + GLC(gl, gl->ProduceTextureDirectCHROMIUM(lock.texture_id(), GL_TEXTURE_2D,
|
| + mailbox.name));
|
| + }
|
|
|
| DCHECK(software_compositor || !mailbox.IsZero());
|
| plane_resources.push_back(PlaneResource(resource_id,
|
| @@ -243,26 +271,23 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| DCHECK_EQ(plane_resources[0].resource_format, kRGBResourceFormat);
|
| DCHECK(plane_resources[0].mailbox.IsZero());
|
|
|
| - if (!video_renderer_)
|
| - video_renderer_.reset(new media::SkCanvasVideoRenderer);
|
| + if (!PlaneResourceMatchesUniqueID(plane_resources[0], video_frame.get(),
|
| + 0)) {
|
| + // We need to transfer data from |video_frame| to the plane resource.
|
| + if (!video_renderer_)
|
| + video_renderer_.reset(new media::SkCanvasVideoRenderer);
|
|
|
| - {
|
| ResourceProvider::ScopedWriteLockSoftware lock(
|
| resource_provider_, plane_resources[0].resource_id);
|
| SkCanvas canvas(lock.sk_bitmap());
|
| video_renderer_->Copy(video_frame, &canvas);
|
| + SetPlaneResourceUniqueId(video_frame.get(), 0, &plane_resources[0]);
|
| }
|
|
|
| - RecycleResourceData recycle_data = {
|
| - plane_resources[0].resource_id,
|
| - plane_resources[0].resource_size,
|
| - plane_resources[0].resource_format,
|
| - gpu::Mailbox()
|
| - };
|
| external_resources.software_resources.push_back(
|
| plane_resources[0].resource_id);
|
| external_resources.software_release_callback =
|
| - base::Bind(&RecycleResource, AsWeakPtr(), recycle_data);
|
| + base::Bind(&RecycleResource, AsWeakPtr(), plane_resources[0]);
|
| external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
|
|
|
| return external_resources;
|
| @@ -270,32 +295,27 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
|
|
| for (size_t i = 0; i < plane_resources.size(); ++i) {
|
| // Update each plane's resource id with its content.
|
| - DCHECK_EQ(plane_resources[i].resource_format, kYUVResourceFormat);
|
| -
|
| - const uint8_t* input_plane_pixels = video_frame->data(i);
|
| -
|
| - gfx::Rect image_rect(0,
|
| - 0,
|
| - video_frame->stride(i),
|
| - plane_resources[i].resource_size.height());
|
| - gfx::Rect source_rect(plane_resources[i].resource_size);
|
| - resource_provider_->SetPixels(plane_resources[i].resource_id,
|
| - input_plane_pixels,
|
| - image_rect,
|
| - source_rect,
|
| - gfx::Vector2d());
|
| -
|
| - RecycleResourceData recycle_data = {
|
| - plane_resources[i].resource_id,
|
| - plane_resources[i].resource_size,
|
| - plane_resources[i].resource_format,
|
| - plane_resources[i].mailbox
|
| - };
|
| + DCHECK_EQ(plane_resources[i].resource_format,
|
| + resource_provider_->yuv_resource_format());
|
| +
|
| + if (!PlaneResourceMatchesUniqueID(plane_resources[i], video_frame.get(),
|
| + i)) {
|
| + // We need to transfer data from |video_frame| to the plane resource.
|
| + const uint8_t* input_plane_pixels = video_frame->data(i);
|
| +
|
| + gfx::Rect image_rect(0, 0, video_frame->stride(i),
|
| + plane_resources[i].resource_size.height());
|
| + gfx::Rect source_rect(plane_resources[i].resource_size);
|
| + resource_provider_->SetPixels(plane_resources[i].resource_id,
|
| + input_plane_pixels, image_rect, source_rect,
|
| + gfx::Vector2d());
|
| + SetPlaneResourceUniqueId(video_frame.get(), i, &plane_resources[i]);
|
| + }
|
|
|
| external_resources.mailboxes.push_back(
|
| TextureMailbox(plane_resources[i].mailbox, GL_TEXTURE_2D, 0));
|
| external_resources.release_callbacks.push_back(
|
| - base::Bind(&RecycleResource, AsWeakPtr(), recycle_data));
|
| + base::Bind(&RecycleResource, AsWeakPtr(), plane_resources[i]));
|
| }
|
|
|
| external_resources.type = VideoFrameExternalResources::YUV_RESOURCE;
|
| @@ -362,7 +382,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForHardwarePlanes(
|
| // static
|
| void VideoResourceUpdater::RecycleResource(
|
| base::WeakPtr<VideoResourceUpdater> updater,
|
| - RecycleResourceData data,
|
| + PlaneResource data,
|
| uint32 sync_point,
|
| bool lost_resource,
|
| BlockingTaskRunner* main_thread_task_runner) {
|
| @@ -385,16 +405,12 @@ void VideoResourceUpdater::RecycleResource(
|
| // Drop recycled resources that are the wrong format.
|
| while (!updater->recycled_resources_.empty() &&
|
| updater->recycled_resources_.back().resource_format !=
|
| - data.resource_format) {
|
| + data.resource_format) {
|
| updater->DeleteResource(updater->recycled_resources_.back().resource_id);
|
| updater->recycled_resources_.pop_back();
|
| }
|
|
|
| - PlaneResource recycled_resource(data.resource_id,
|
| - data.resource_size,
|
| - data.resource_format,
|
| - data.mailbox);
|
| - updater->recycled_resources_.push_back(recycled_resource);
|
| + updater->recycled_resources_.push_back(data);
|
| }
|
|
|
| } // namespace cc
|
|
|