Index: webrtc/media/engine/webrtcvideoframefactory.cc |
diff --git a/webrtc/media/engine/webrtcvideoframefactory.cc b/webrtc/media/engine/webrtcvideoframefactory.cc |
index 2c08c63129c6c28303a743d5122bf69d6e0f57d3..b7b4fd9c9bf7ea917910d020552bba71afd31575 100644 |
--- a/webrtc/media/engine/webrtcvideoframefactory.cc |
+++ b/webrtc/media/engine/webrtcvideoframefactory.cc |
@@ -10,12 +10,106 @@ |
#include <memory> |
+#include "libyuv/convert.h" |
+#include "libyuv/scale.h" |
+ |
#include "webrtc/base/logging.h" |
#include "webrtc/media/engine/webrtcvideoframe.h" |
#include "webrtc/media/engine/webrtcvideoframefactory.h" |
+// TODO(nisse): Needed for the struct CapturedFrame. Move declaration |
+// to videoframefactory.h instead? |
+#include "webrtc/media/base/videocapturer.h" |
+ |
namespace cricket { |
+std::unique_ptr<VideoFrame> WebRtcVideoFrameFactory::CreateScaledFrame( |
+ const CapturedFrame* input_frame, |
+ int dst_width, |
+ int dst_height) const { |
+ // Size of the used portion of the input frame, updated for |
+ // cropping, but pre-rotation. |
+ int crop_width = input_frame->width; |
+ int crop_height = input_frame->height; |
+ |
+ // Cropp the input frame, if needed to preserve aspect ratio. |
+ long aspect_diff = static_cast<long>(crop_width) * dst_height - |
+ static_cast<long>(crop_height) * dst_width; |
+ if (aspect_diff > 0) { |
magjed_webrtc
2016/05/09 13:44:55
This code will be the same for all implementations
nisse-webrtc
2016/05/10 07:56:22
It used to be a helper function in videocommon. I
|
+ // Horizontal crop. |
+ |
+ // TODO(nisse): Old code carried a comment saying that MJPG can |
+ // only be cropped vertically, and disabled horizontal cropping in |
+ // that case. Still needed? |
+ crop_width -= aspect_diff / dst_height; |
+ RTC_DCHECK(crop_width > 0); |
+ } else if (aspect_diff > 0) { |
+ // Vertical crop. |
+ crop_height -= (-aspect_diff) / dst_width; |
+ RTC_DCHECK(crop_height > 0); |
+ } |
+ |
+ webrtc::VideoRotation rotation = input_frame->rotation; |
+ // The size of the input frame, after cropping and rotation. |
+ int src_width = crop_width; |
+ int src_height = crop_height; |
+ if (apply_rotation_ && (rotation == webrtc::kVideoRotation_90 || |
+ rotation == webrtc::kVideoRotation_270)) { |
+ std::swap(dst_width, dst_height); |
+ std::swap(src_width, src_height); |
+ } |
+ |
+ rtc::scoped_refptr<webrtc::I420Buffer> buffer( |
+ new rtc::RefCountedObject<webrtc::I420Buffer>(src_width, src_height)); |
+ |
+ // Color space conversion, cropping, and rotation. |
+ uint32_t format = CanonicalFourCC(input_frame->fourcc); |
+ int r = libyuv::ConvertToI420( |
+ static_cast<const uint8_t*>(input_frame->data), input_frame->data_size, |
+ buffer->MutableDataY(), buffer->StrideY(), |
+ buffer->MutableDataU(), buffer->StrideU(), |
+ buffer->MutableDataV(), buffer->StrideV(), |
+ // Cropping coordinates, and width and height, are pre-rotation values. |
+ (input_frame->width - crop_width) / 2, |
+ (input_frame->height - crop_height) / 2, |
+ input_frame->width, input_frame->height, |
+ crop_width, crop_height, |
+ static_cast<libyuv::RotationMode>( |
+ apply_rotation_ ? rotation : webrtc::kVideoRotation_0), |
+ format); |
+ if (r) { |
+ LOG(LS_ERROR) << "Error parsing format: " << GetFourccName(format) |
+ << " return code : " << r; |
+ return nullptr; |
+ } |
+ |
+ // Scaling, if needed. |
+ if (src_width != dst_width || src_height != dst_height) { |
+ rtc::scoped_refptr<webrtc::I420Buffer> scaled( |
+ new rtc::RefCountedObject<webrtc::I420Buffer>(dst_width, dst_height)); |
+ |
+ if (libyuv::I420Scale(buffer->DataY(), buffer->StrideY(), |
+ buffer->DataU(), buffer->StrideU(), |
+ buffer->DataV(), buffer->StrideV(), |
+ buffer->width(), buffer->height(), |
+ scaled->MutableDataY(), scaled->StrideY(), |
+ scaled->MutableDataU(), scaled->StrideU(), |
+ scaled->MutableDataV(), scaled->StrideV(), |
+ scaled->width(), scaled->height(), |
+ libyuv::kFilterBox) < 0) { |
+ LOG(LS_ERROR) << "I420Scale failed: src size " |
+ << buffer->width() << " x " << buffer->height() |
+ << ", dst size: " |
+ << scaled->width() << " x " << scaled->height(); |
+ return nullptr; |
+ } |
+ buffer = scaled; |
+ } |
+ return std::unique_ptr<VideoFrame>(new WebRtcVideoFrame( |
+ buffer, apply_rotation_ ? webrtc::kVideoRotation_0 : rotation, |
+ input_frame->time_stamp / rtc::kNumNanosecsPerMicrosec)); |
+} |
+ |
VideoFrame* WebRtcVideoFrameFactory::CreateAliasedFrame( |
const CapturedFrame* aliased_frame, int width, int height) const { |
std::unique_ptr<WebRtcVideoFrame> frame(new WebRtcVideoFrame()); |