git-svn-id: http://webrtc.googlecode.com/svn/trunk@4 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/modules/utility/source/frame_scaler.cc b/modules/utility/source/frame_scaler.cc
new file mode 100644
index 0000000..e3ec0b0
--- /dev/null
+++ b/modules/utility/source/frame_scaler.cc
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifdef WEBRTC_MODULE_UTILITY_VIDEO
+#include "frame_scaler.h"
+
+#include "trace.h"
+#include "vplib.h"
+
+#ifndef NO_INTERPOLATOR
+ #include "InterpolatorInterface.h"
+#endif
+
+namespace webrtc {
+FrameScaler::FrameScaler()
+ : _ptrVideoInterpolator(0),
+ _outWidth(0),
+ _outHeight(0),
+ _inWidth(0),
+ _inHeight(0)
+{
+}
+
+FrameScaler::~FrameScaler( )
+{
+#ifndef NO_INTERPOLATOR
+ if( _ptrVideoInterpolator != 0)
+ {
+ deleteInterpolator(_ptrVideoInterpolator);
+ }
+ #endif
+}
+
+WebRtc_Word32 FrameScaler::ResizeFrameIfNeeded(VideoFrame& videoFrame,
+ WebRtc_UWord32 outWidth,
+ WebRtc_UWord32 outHeight)
+{
+ if( videoFrame.Length( ) == 0)
+ {
+ return -1;
+ }
+
+ if((videoFrame.Width() != outWidth) || ( videoFrame.Height() != outHeight))
+ {
+ // Scale down by factor 2-4.
+ if(videoFrame.Width() % outWidth == 0 &&
+ videoFrame.Height() % outHeight == 0 &&
+ (videoFrame.Width() / outWidth) == (videoFrame.Height() / outHeight))
+ {
+ const WebRtc_Word32 multiple = videoFrame.Width() / outWidth;
+ WebRtc_UWord32 scaledWidth;
+ WebRtc_UWord32 scaledHeight;
+ switch(multiple)
+ {
+ case 2:
+ ScaleI420FrameQuarter(videoFrame.Width(), videoFrame.Height(),
+ videoFrame.Buffer());
+
+ videoFrame.SetLength(outWidth * outHeight * 3 / 2);
+ videoFrame.SetWidth( outWidth);
+ videoFrame.SetHeight(outHeight);
+ return 0;
+ case 3:
+ ScaleI420Down1_3(videoFrame.Width(), videoFrame.Height(),
+ videoFrame.Buffer(), videoFrame.Size(),
+ scaledWidth, scaledHeight);
+ videoFrame.SetLength((outWidth * outHeight * 3) / 2);
+ videoFrame.SetWidth(outWidth);
+ videoFrame.SetHeight(outHeight);
+ return 0;
+ case 4:
+ ScaleI420FrameQuarter(videoFrame.Width(), videoFrame.Height(),
+ videoFrame.Buffer());
+
+ ScaleI420FrameQuarter(videoFrame.Width() >> 1,
+ videoFrame.Height() >> 1,
+ videoFrame.Buffer());
+
+ videoFrame.SetLength((outWidth * outHeight * 3)/ 2);
+ videoFrame.SetWidth(outWidth);
+ videoFrame.SetHeight(outHeight);
+ return 0;
+ default:
+ break;
+ }
+ }
+ // Scale up by factor 2-4.
+ if(outWidth % videoFrame.Width() == 0 &&
+ outHeight % videoFrame.Height() == 0 &&
+ (outWidth / videoFrame.Width()) == (outHeight / videoFrame.Height()))
+ {
+ const WebRtc_Word32 multiple = outWidth / videoFrame.Width();
+ WebRtc_UWord32 scaledWidth = 0;
+ WebRtc_UWord32 scaledHeight = 0;
+ switch(multiple)
+ {
+ case 2:
+ videoFrame.VerifyAndAllocate((outHeight * outWidth * 3) / 2);
+ ScaleI420Up2(videoFrame.Width(), videoFrame.Height(),
+ videoFrame.Buffer(), videoFrame.Size(),
+ scaledWidth, scaledHeight);
+ videoFrame.SetLength((outWidth * outHeight * 3) / 2);
+ videoFrame.SetWidth(outWidth);
+ videoFrame.SetHeight(outHeight);
+ return 0;
+ case 3:
+ videoFrame.VerifyAndAllocate((outWidth * outHeight * 3) / 2);
+ ScaleI420Up2(videoFrame.Width(), videoFrame.Height(),
+ videoFrame.Buffer(), videoFrame.Size(),
+ scaledWidth, scaledHeight);
+
+ ScaleI420Up3_2(scaledWidth, scaledHeight, videoFrame.Buffer(),
+ videoFrame.Size(), scaledWidth, scaledHeight);
+ videoFrame.SetLength((outWidth * outHeight * 3) / 2);
+ videoFrame.SetWidth(outWidth);
+ videoFrame.SetHeight(outHeight);
+ return 0;
+ case 4:
+ videoFrame.VerifyAndAllocate((outWidth * outHeight * 3) / 2);
+ ScaleI420Up2(videoFrame.Width(), videoFrame.Height(),
+ videoFrame.Buffer(), videoFrame.Size(),
+ scaledWidth, scaledHeight);
+ ScaleI420Up2(scaledWidth, scaledHeight, videoFrame.Buffer(),
+ videoFrame.Size(), scaledWidth, scaledHeight);
+ videoFrame.SetLength((outWidth * outHeight * 3) / 2);
+ videoFrame.SetWidth(outWidth);
+ videoFrame.SetHeight(outHeight);
+ return 0;
+ default:
+ break;
+ }
+ }
+ // Use interpolator
+#ifdef NO_INTERPOLATOR
+ assert(!"Interpolation not available");
+#else
+ // Create new interpolator if the scaling changed.
+ if((_outWidth != outWidth) || (_outHeight != outHeight) ||
+ (_inWidth != videoFrame.Width()) ||
+ (_inHeight != videoFrame.Height()))
+ {
+ if(_ptrVideoInterpolator != 0)
+ {
+ deleteInterpolator(_ptrVideoInterpolator);
+ _ptrVideoInterpolator = 0;
+ }
+
+ _outWidth = outWidth;
+ _outHeight = outHeight;
+ _inWidth = videoFrame.Width();
+ _inHeight = videoFrame.Height();
+ }
+
+
+ if (!_ptrVideoInterpolator)
+ {
+ InterpolatorType interpolator = BiCubicBSpline;
+
+ if((_inWidth > ( _outWidth * 2)) ||
+ (_inWidth < ( _outWidth / 2)) ||
+ (_inHeight > ( _outHeight * 2)) ||
+ (_inHeight < ( _outHeight / 2)))
+
+ {
+ interpolator = BiCubicSine;
+ }
+
+ VideoFrameFormat inputFormat;
+ VideoFrameFormat outputFormat;
+
+ inputFormat.videoType = YUV420P;
+ inputFormat.xChannels = static_cast<short>(_inWidth);
+ inputFormat.yChannels = static_cast<short>(_inHeight);
+
+ outputFormat.videoType = YUV420P;
+ outputFormat.xChannels = static_cast<short>(_outWidth);
+ outputFormat.yChannels = static_cast<short>(_outHeight);
+
+ _interpolatorBuffer.VerifyAndAllocate(_outWidth * _outHeight *
+ 3 / 2);
+
+ _ptrVideoInterpolator = createInterpolator(
+ interpolator,
+ &inputFormat,
+ &outputFormat);
+ if (_ptrVideoInterpolator == NULL)
+ {
+ WEBRTC_TRACE(
+ kTraceError,
+ kTraceVideo,
+ -1,
+ "FrameScaler::ResizeFrame(): Could not create\
+ interpolator");
+ return -1;
+ }
+ }
+
+ interpolateFrame(_ptrVideoInterpolator, videoFrame.Buffer(),
+ _interpolatorBuffer.Buffer());
+
+ videoFrame.VerifyAndAllocate(_interpolatorBuffer.Size());
+ videoFrame.SetLength(_outWidth * _outHeight * 3 / 2);
+ videoFrame.CopyFrame(videoFrame.Length(), _interpolatorBuffer.Buffer());
+ videoFrame.SetWidth(_outWidth);
+ videoFrame.SetHeight(_outHeight);
+#endif // NO_INTERPOLATOR
+ }
+ return 0;
+}
+} // namespace webrtc
+
+#endif // WEBRTC_MODULE_UTILITY_VIDEO