Chromium Code Reviews| Index: content/renderer/pepper/pepper_video_source_host.cc |
| diff --git a/content/renderer/pepper/pepper_video_source_host.cc b/content/renderer/pepper/pepper_video_source_host.cc |
| index 49efee24b1944f6c17bcb3ce16028df6485d7e50..fe06194da0d4f5856fe71d67b08696d30738e9db 100644 |
| --- a/content/renderer/pepper/pepper_video_source_host.cc |
| +++ b/content/renderer/pepper/pepper_video_source_host.cc |
| @@ -19,6 +19,7 @@ |
| #include "ppapi/thunk/enter.h" |
| #include "ppapi/thunk/ppb_image_data_api.h" |
| #include "third_party/libyuv/include/libyuv/convert.h" |
| +#include "third_party/libyuv/include/libyuv/scale.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| using ppapi::host::HostMessageContext; |
| @@ -115,19 +116,15 @@ void PepperVideoSourceHost::SendGetFrameReply() { |
| get_frame_pending_ = false; |
| DCHECK(last_frame_.get()); |
| - scoped_refptr<media::VideoFrame> frame(last_frame_); |
| - last_frame_ = NULL; |
| - |
| - const int dst_width = frame->visible_rect().width(); |
| - const int dst_height = frame->visible_rect().height(); |
| + const gfx::Size dst_size = last_frame_->natural_size(); |
| // Note: We try to reuse the shared memory for the previous frame here. This |
| // means that the previous frame may be overwritten and is no longer valid |
| // after calling this function again. |
| IPC::PlatformFileForTransit image_handle; |
| uint32_t byte_count; |
| - if (shared_image_.get() && dst_width == shared_image_->width() && |
| - dst_height == shared_image_->height()) { |
| + if (shared_image_.get() && dst_size.width() == shared_image_->width() && |
| + dst_size.height() == shared_image_->height()) { |
| // We have already allocated the correct size in shared memory. We need to |
| // duplicate the handle for IPC however, which will close down the |
| // duplicated handle when it's done. |
| @@ -162,7 +159,7 @@ void PepperVideoSourceHost::SendGetFrameReply() { |
| pp_instance(), |
| ppapi::PPB_ImageData_Shared::SIMPLE, |
| PP_IMAGEDATAFORMAT_BGRA_PREMUL, |
| - PP_MakeSize(dst_width, dst_height), |
| + PP_MakeSize(dst_size.width(), dst_size.height()), |
| false /* init_to_zero */, |
| &shared_image_desc_, |
| &image_handle, |
| @@ -206,23 +203,49 @@ void PepperVideoSourceHost::SendGetFrameReply() { |
| return; |
| } |
| - // Calculate that portion of the |frame| that should be copied into |
| - // |bitmap|. If |frame| has been cropped, |
| - // frame->coded_size() != frame->visible_rect(). |
| - const int src_width = frame->coded_size().width(); |
| - const int src_height = frame->coded_size().height(); |
| - DCHECK(src_width >= dst_width && src_height >= dst_height); |
| - |
| - const int horiz_crop = frame->visible_rect().x(); |
| - const int vert_crop = frame->visible_rect().y(); |
| - |
| - const uint8* src_y = frame->data(media::VideoFrame::kYPlane) + |
| - (src_width * vert_crop + horiz_crop); |
| - const int center = (src_width + 1) / 2; |
| - const uint8* src_u = frame->data(media::VideoFrame::kUPlane) + |
| - (center * vert_crop + horiz_crop) / 2; |
| - const uint8* src_v = frame->data(media::VideoFrame::kVPlane) + |
| - (center * vert_crop + horiz_crop) / 2; |
| + // Calculate the portion of the |last_frame_| that should be copied into |
| + // |bitmap|. If |last_frame_| is lazily scaled, then |
| + // last_frame_->visible_rect()._size() != last_frame_.natural_size(). |
| + scoped_refptr<media::VideoFrame> frame; |
| + if (dst_size == last_frame_->visible_rect().size()) { |
| + // No scaling is needed, convert directly from last_frame_. |
| + frame = last_frame_; |
| + // The resolution of the frames don't change frequently, so don't keep any |
|
bbudge
2014/11/20 15:21:55
nit: awkward grammar. How about this?
// Frame res
magjed_chromium
2014/11/20 15:38:44
Done.
|
| + // unnecessary buffers around. |
| + scaled_frame_ = NULL; |
|
bbudge
2014/11/20 15:21:55
This comment makes me wonder why you keep scaled_f
magjed_chromium
2014/11/20 15:38:44
Yes exactly. last_frame_->visible_rect().size and
|
| + } else { |
| + // We need to create an intermediate scaled frame. Make sure we have |
| + // allocated one of correct size. |
| + if (!scaled_frame_.get() || scaled_frame_->coded_size() != dst_size) { |
| + scaled_frame_ = media::VideoFrame::CreateFrame( |
| + media::VideoFrame::I420, dst_size, gfx::Rect(dst_size), dst_size, |
| + last_frame_->timestamp()); |
| + if (!scaled_frame_.get()) { |
| + LOG(ERROR) << "Failed to allocate a media::VideoFrame"; |
| + SendGetFrameErrorReply(PP_ERROR_FAILED); |
| + return; |
| + } |
| + } |
| + libyuv::I420Scale(last_frame_->visible_data(media::VideoFrame::kYPlane), |
| + last_frame_->stride(media::VideoFrame::kYPlane), |
| + last_frame_->visible_data(media::VideoFrame::kUPlane), |
| + last_frame_->stride(media::VideoFrame::kUPlane), |
| + last_frame_->visible_data(media::VideoFrame::kVPlane), |
| + last_frame_->stride(media::VideoFrame::kVPlane), |
| + last_frame_->visible_rect().width(), |
| + last_frame_->visible_rect().height(), |
| + scaled_frame_->data(media::VideoFrame::kYPlane), |
| + scaled_frame_->stride(media::VideoFrame::kYPlane), |
| + scaled_frame_->data(media::VideoFrame::kUPlane), |
| + scaled_frame_->stride(media::VideoFrame::kUPlane), |
| + scaled_frame_->data(media::VideoFrame::kVPlane), |
| + scaled_frame_->stride(media::VideoFrame::kVPlane), |
| + dst_size.width(), |
| + dst_size.height(), |
| + libyuv::kFilterBilinear); |
| + frame = scaled_frame_; |
| + } |
| + last_frame_ = NULL; |
| // TODO(magjed): Chrome OS is not ready for switching from BGRA to ARGB. |
| // Remove this once http://crbug/434007 is fixed. We have a corresponding |
| @@ -232,16 +255,16 @@ void PepperVideoSourceHost::SendGetFrameReply() { |
| #else |
| auto libyuv_i420_to_xxxx = &libyuv::I420ToARGB; |
| #endif |
| - libyuv_i420_to_xxxx(src_y, |
| + libyuv_i420_to_xxxx(frame->visible_data(media::VideoFrame::kYPlane), |
| frame->stride(media::VideoFrame::kYPlane), |
| - src_u, |
| + frame->visible_data(media::VideoFrame::kUPlane), |
| frame->stride(media::VideoFrame::kUPlane), |
| - src_v, |
| + frame->visible_data(media::VideoFrame::kVPlane), |
| frame->stride(media::VideoFrame::kVPlane), |
| bitmap_pixels, |
| bitmap->rowBytes(), |
| - dst_width, |
| - dst_height); |
| + dst_size.width(), |
| + dst_size.height()); |
| ppapi::HostResource host_resource; |
| host_resource.SetHostResource(pp_instance(), shared_image_->GetReference()); |