Index: content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc |
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc |
index 10ad8578a99c1842800841ff7697afa1518a4e01..2df4c6ef5a94db6187b5e6551d280487807f79e4 100644 |
--- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc |
+++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc |
@@ -9,14 +9,11 @@ |
#include "base/trace_event/trace_event.h" |
#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h" |
#include "media/base/timestamp_constants.h" |
-#include "media/base/video_frame.h" |
-#include "media/base/video_frame_pool.h" |
#include "media/base/video_util.h" |
#include "third_party/libyuv/include/libyuv/convert_from.h" |
#include "third_party/libyuv/include/libyuv/scale.h" |
#include "third_party/webrtc/common_video/include/video_frame_buffer.h" |
#include "third_party/webrtc/common_video/rotation.h" |
-#include "third_party/webrtc/media/base/videoframefactory.h" |
#include "third_party/webrtc/media/engine/webrtcvideoframe.h" |
namespace content { |
@@ -29,132 +26,10 @@ void ReleaseOriginalFrame(const scoped_refptr<media::VideoFrame>& frame) { |
} // anonymous namespace |
-// A cricket::VideoFrameFactory for media::VideoFrame. The purpose of this |
-// class is to avoid a premature frame copy. A media::VideoFrame is injected |
-// with SetFrame, and converted into a cricket::VideoFrame with |
-// CreateAliasedFrame. SetFrame should be called before CreateAliasedFrame |
-// for every frame. |
-class WebRtcVideoCapturerAdapter::MediaVideoFrameFactory |
- : public cricket::VideoFrameFactory { |
- public: |
- void SetFrame(const scoped_refptr<media::VideoFrame>& frame) { |
- DCHECK(frame.get()); |
- // Create a CapturedFrame that only contains header information, not the |
- // actual pixel data. |
- captured_frame_.width = frame->natural_size().width(); |
- captured_frame_.height = frame->natural_size().height(); |
- captured_frame_.time_stamp = frame->timestamp().InMicroseconds() * |
- base::Time::kNanosecondsPerMicrosecond; |
- captured_frame_.pixel_height = 1; |
- captured_frame_.pixel_width = 1; |
- captured_frame_.rotation = webrtc::kVideoRotation_0; |
- captured_frame_.data = NULL; |
- captured_frame_.data_size = cricket::CapturedFrame::kUnknownDataSize; |
- captured_frame_.fourcc = static_cast<uint32_t>(cricket::FOURCC_ANY); |
- |
- frame_ = frame; |
- } |
- |
- void ReleaseFrame() { frame_ = NULL; } |
- |
- const cricket::CapturedFrame* GetCapturedFrame() const { |
- return &captured_frame_; |
- } |
- |
- cricket::VideoFrame* CreateAliasedFrame( |
- const cricket::CapturedFrame* input_frame, |
- int cropped_input_width, |
- int cropped_input_height, |
- int output_width, |
- int output_height) const override { |
- // Check that captured_frame is actually our frame. |
- DCHECK(input_frame == &captured_frame_); |
- DCHECK(frame_.get()); |
- |
- const int64_t timestamp_ns = frame_->timestamp().InMicroseconds() * |
- base::Time::kNanosecondsPerMicrosecond; |
- |
- // Return |frame_| directly if it is texture backed, because there is no |
- // cropping support for texture yet. See http://crbug/503653. |
- // Return |frame_| directly if it is GpuMemoryBuffer backed, as we want to |
- // keep the frame on native buffers. |
- if (frame_->HasTextures() || |
- frame_->storage_type() == |
- media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS) { |
- return new cricket::WebRtcVideoFrame( |
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame_), |
- timestamp_ns, webrtc::kVideoRotation_0); |
- } |
- |
- // Create a centered cropped visible rect that preservers aspect ratio for |
- // cropped natural size. |
- gfx::Rect visible_rect = frame_->visible_rect(); |
- visible_rect.ClampToCenteredSize(gfx::Size( |
- visible_rect.width() * cropped_input_width / input_frame->width, |
- visible_rect.height() * cropped_input_height / input_frame->height)); |
- |
- const gfx::Size output_size(output_width, output_height); |
- scoped_refptr<media::VideoFrame> video_frame = |
- media::VideoFrame::WrapVideoFrame(frame_, frame_->format(), |
- visible_rect, output_size); |
- if (!video_frame) |
- return nullptr; |
- video_frame->AddDestructionObserver( |
- base::Bind(&ReleaseOriginalFrame, frame_)); |
- |
- // If no scaling is needed, return a wrapped version of |frame_| directly. |
- if (video_frame->natural_size() == video_frame->visible_rect().size()) { |
- return new cricket::WebRtcVideoFrame( |
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(video_frame), |
- timestamp_ns, webrtc::kVideoRotation_0); |
- } |
- |
- // We need to scale the frame before we hand it over to cricket. |
- scoped_refptr<media::VideoFrame> scaled_frame = |
- scaled_frame_pool_.CreateFrame(media::PIXEL_FORMAT_I420, output_size, |
- gfx::Rect(output_size), output_size, |
- frame_->timestamp()); |
- libyuv::I420Scale(video_frame->visible_data(media::VideoFrame::kYPlane), |
- video_frame->stride(media::VideoFrame::kYPlane), |
- video_frame->visible_data(media::VideoFrame::kUPlane), |
- video_frame->stride(media::VideoFrame::kUPlane), |
- video_frame->visible_data(media::VideoFrame::kVPlane), |
- video_frame->stride(media::VideoFrame::kVPlane), |
- video_frame->visible_rect().width(), |
- video_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), |
- output_width, output_height, libyuv::kFilterBilinear); |
- return new cricket::WebRtcVideoFrame( |
- new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(scaled_frame), |
- timestamp_ns, webrtc::kVideoRotation_0); |
- } |
- |
- cricket::VideoFrame* CreateAliasedFrame( |
- const cricket::CapturedFrame* input_frame, |
- int output_width, |
- int output_height) const override { |
- return CreateAliasedFrame(input_frame, input_frame->width, |
- input_frame->height, output_width, output_height); |
- } |
- |
- private: |
- scoped_refptr<media::VideoFrame> frame_; |
- cricket::CapturedFrame captured_frame_; |
- // This is used only if scaling is needed. |
- mutable media::VideoFramePool scaled_frame_pool_; |
-}; |
- |
WebRtcVideoCapturerAdapter::WebRtcVideoCapturerAdapter(bool is_screencast) |
: is_screencast_(is_screencast), |
running_(false) { |
thread_checker_.DetachFromThread(); |
- // The base class takes ownership of the frame factory. |
- set_frame_factory(new MediaVideoFrameFactory); |
} |
WebRtcVideoCapturerAdapter::~WebRtcVideoCapturerAdapter() { |
@@ -218,32 +93,108 @@ bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat( |
} |
void WebRtcVideoCapturerAdapter::OnFrameCaptured( |
- const scoped_refptr<media::VideoFrame>& video_frame) { |
+ const scoped_refptr<media::VideoFrame>& input_frame) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
TRACE_EVENT0("video", "WebRtcVideoCapturerAdapter::OnFrameCaptured"); |
- if (!(video_frame->IsMappable() && |
- (video_frame->format() == media::PIXEL_FORMAT_I420 || |
- video_frame->format() == media::PIXEL_FORMAT_YV12 || |
- video_frame->format() == media::PIXEL_FORMAT_YV12A))) { |
+ if (!(input_frame->IsMappable() && |
+ (input_frame->format() == media::PIXEL_FORMAT_I420 || |
+ input_frame->format() == media::PIXEL_FORMAT_YV12 || |
+ input_frame->format() == media::PIXEL_FORMAT_YV12A))) { |
// Since connecting sources and sinks do not check the format, we need to |
// just ignore formats that we can not handle. |
NOTREACHED(); |
return; |
} |
- scoped_refptr<media::VideoFrame> frame = video_frame; |
+ scoped_refptr<media::VideoFrame> frame = input_frame; |
// Drop alpha channel since we do not support it yet. |
if (frame->format() == media::PIXEL_FORMAT_YV12A) |
- frame = media::WrapAsI420VideoFrame(video_frame); |
+ frame = media::WrapAsI420VideoFrame(input_frame); |
+ |
+ const int orig_width = frame->natural_size().width(); |
+ const int orig_height = frame->natural_size().height(); |
+ int adapted_width; |
+ int adapted_height; |
+ // The VideoAdapter is only used for cpu-adaptation downscaling, no |
+ // aspect changes. So we ignore these crop-related outputs. |
+ int crop_width; |
+ int crop_height; |
+ int crop_x; |
+ int crop_y; |
+ int64_t translated_camera_time_us; |
+ |
+ if (!AdaptFrame(orig_width, orig_height, |
+ frame->timestamp().InMicroseconds(), |
+ rtc::TimeMicros(), |
+ &adapted_width, &adapted_height, |
+ &crop_width, &crop_height, &crop_x, &crop_y, |
+ &translated_camera_time_us)) { |
+ return; |
+ } |
- // Inject the frame via the VideoFrameFactory of base class. |
- MediaVideoFrameFactory* media_video_frame_factory = |
- reinterpret_cast<MediaVideoFrameFactory*>(frame_factory()); |
- media_video_frame_factory->SetFrame(frame); |
+ // Return |frame| directly if it is texture backed, because there is no |
+ // cropping support for texture yet. See http://crbug/503653. |
+ // Return |frame| directly if it is GpuMemoryBuffer backed, as we want to |
+ // keep the frame on native buffers. |
+ if (frame->HasTextures() || |
+ frame->storage_type() == |
+ media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS) { |
+ OnFrame(cricket::WebRtcVideoFrame( |
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame), |
+ webrtc::kVideoRotation_0, translated_camera_time_us), |
perkj_chrome
2016/08/23 18:29:31
scary bug.
|
+ orig_width, orig_height); |
+ return; |
+ } |
- // This signals to libJingle that a new VideoFrame is available. |
- SignalFrameCaptured(this, media_video_frame_factory->GetCapturedFrame()); |
+ // Create a centered cropped visible rect that preservers aspect ratio for |
+ // cropped natural size. |
+ gfx::Rect visible_rect = frame->visible_rect(); |
+ visible_rect.ClampToCenteredSize(gfx::Size( |
+ visible_rect.width() * adapted_width / orig_width, |
+ visible_rect.height() * adapted_height / orig_height)); |
+ |
+ const gfx::Size adapted_size(adapted_width, adapted_height); |
+ scoped_refptr<media::VideoFrame> video_frame = |
+ media::VideoFrame::WrapVideoFrame(frame, frame->format(), |
+ visible_rect, adapted_size); |
+ if (!video_frame) |
+ return; |
+ |
+ video_frame->AddDestructionObserver(base::Bind(&ReleaseOriginalFrame, frame)); |
+ |
+ // If no scaling is needed, return a wrapped version of |frame| directly. |
+ if (video_frame->natural_size() == video_frame->visible_rect().size()) { |
+ OnFrame(cricket::WebRtcVideoFrame( |
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(video_frame), |
+ webrtc::kVideoRotation_0, translated_camera_time_us), |
+ orig_width, orig_height); |
+ return; |
+ } |
- media_video_frame_factory->ReleaseFrame(); // Release the frame ASAP. |
+ // We need to scale the frame before we hand it over to webrtc. |
+ scoped_refptr<media::VideoFrame> scaled_frame = |
+ scaled_frame_pool_.CreateFrame(media::PIXEL_FORMAT_I420, adapted_size, |
+ gfx::Rect(adapted_size), adapted_size, |
+ frame->timestamp()); |
+ libyuv::I420Scale(video_frame->visible_data(media::VideoFrame::kYPlane), |
+ video_frame->stride(media::VideoFrame::kYPlane), |
+ video_frame->visible_data(media::VideoFrame::kUPlane), |
+ video_frame->stride(media::VideoFrame::kUPlane), |
+ video_frame->visible_data(media::VideoFrame::kVPlane), |
+ video_frame->stride(media::VideoFrame::kVPlane), |
+ video_frame->visible_rect().width(), |
+ video_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), |
+ adapted_width, adapted_height, libyuv::kFilterBilinear); |
+ |
+ OnFrame(cricket::WebRtcVideoFrame( |
+ new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(scaled_frame), |
+ webrtc::kVideoRotation_0, translated_camera_time_us), |
+ orig_width, orig_height); |
} |
} // namespace content |