--- /dev/null
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+##
+# Build native code
+##
+
+#Build base library
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := libfilterpack_base
+LOCAL_SRC_FILES := native/geometry.cpp \
+ native/time_util.cpp
+
+LOCAL_CFLAGS := -DANDROID
+
+include external/stlport/libstlport.mk
+
+include $(BUILD_STATIC_LIBRARY)
--- /dev/null
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BASE_BASIC_TYPES_H_
+#define BASE_BASIC_TYPES_H_
+
+#include <stdint.h>
+
+// STL containers
+#include <vector>
+using std::vector;
+#include <map>
+using std::map;
+#include <string>
+using std::string;
+#include <sstream>
+using std::stringstream;
+using std::istringstream;
+using std::ostringstream;
+#include <utility>
+using std::pair;
+#include <list>
+using std::list;
+#include <set>
+using std::set;
+#include <stack>
+using std::stack;
+
+#include <memory>
+using std::auto_ptr;
+
+// Integral types
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+
+#endif // BASE_BASIC_TYPES_H_
+
--- /dev/null
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include <assert.h>
+#include <cutils/log.h>
+#include <math.h>
+
+#include "geometry.h"
+
+#define ASSERT(x) assert(x)
+
+namespace android {
+namespace mff {
+
+float Point::Length() const {
+ return sqrtf(x_ * x_ + y_ * y_);
+}
+
+bool Point::ScaleTo(float new_length) {
+ float length = Length();
+ if (length == 0.0f) {
+ return false;
+ }
+ x_ *= new_length / length;
+ y_ *= new_length / length;
+ return true;
+}
+
+float Point::Distance(const Point& p0, const Point& p1) {
+ Point diff = p1 - p0;
+ return diff.Length();
+}
+
+Point Point::operator+(const Point& other) const {
+ Point out;
+ out.x_ = x_ + other.x_;
+ out.y_ = y_ + other.y_;
+ return out;
+}
+
+Point Point::operator-(const Point& other) const {
+ Point out;
+ out.x_ = x_ - other.x_;
+ out.y_ = y_ - other.y_;
+ return out;
+}
+
+Point Point::operator*(float factor) const {
+ Point out;
+ out.x_ = factor * x_;
+ out.y_ = factor * y_;
+ return out;
+}
+
+void Point::Rotate90Clockwise() {
+ const float x = x_;
+ x_ = y_;
+ y_ = -x;
+}
+
+bool Rect::ExpandToAspectRatio(float ratio) {
+ if (width <= 0.0f || height <= 0.0f || ratio <= 0.0f) {
+ return false;
+ }
+
+ const float current_ratio = width / height;
+ if (current_ratio < ratio) {
+ const float dx = width * (ratio / current_ratio - 1.0f);
+ x -= dx / 2.0f;
+ width += dx;
+ } else {
+ const float dy = height * (current_ratio / ratio - 1.0f);
+ y -= dy / 2.0f;
+ height += dy;
+ }
+ return true;
+}
+
+bool Rect::ExpandToMinLength(float length) {
+ if (width <= 0.0f || height <= 0.0f || length <= 0.0f) {
+ return false;
+ }
+
+ const float current_length = width > height ? width : height;
+ if (length > current_length) {
+ const float dx = width * (length / current_length - 1.0f);
+ x -= dx / 2.0f;
+ width += dx;
+ const float dy = height * (length / current_length - 1.0f);
+ y -= dy / 2.0f;
+ height += dy;
+ }
+ return true;
+}
+
+bool Rect::ScaleWithLengthLimit(float factor, float max_length) {
+ if (width <= 0.0f || height <= 0.0f || factor <= 0.0f) {
+ return false;
+ }
+
+ const float current_length = width > height ? width : height;
+ if (current_length >= max_length) {
+ return true;
+ }
+
+ float f = factor;
+ if (current_length * f > max_length) {
+ f *= max_length / (current_length * f);
+ }
+
+ const float dx = width * (f - 1.0f);
+ x -= dx / 2.0f;
+ width += dx;
+ const float dy = height * (f - 1.0f);
+ y -= dy / 2.0f;
+ height += dy;
+ return true;
+}
+
+const Point& Quad::point(int ix) const {
+ ASSERT(ix < static_cast<int>(points_.size()));
+ return points_[ix];
+}
+
+bool SlantedRect::FromCenterAxisAndLengths(const Point& center,
+ const Point& vert_axis,
+ const Point& lengths) {
+ Point dy = vert_axis;
+ if (!dy.ScaleTo(lengths.y() / 2.0f)) {
+ LOGE("Illegal axis: %f %f", vert_axis.x(), vert_axis.y());
+ return false;
+ }
+
+ Point dx = dy;
+ dx.Rotate90Clockwise();
+ dx.ScaleTo(lengths.x() / 2.0f);
+
+ points_[0] = center - dx - dy;
+ points_[1] = center + dx - dy;
+ points_[2] = center - dx + dy;
+ points_[3] = center + dx + dy;
+
+ width_ = lengths.x();
+ height_ = lengths.y();
+
+ return true;
+}
+
+} // namespace mff
+} // namespace android
--- /dev/null
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VIDEO_FILTER_GEOMETRY_H__
+#define VIDEO_FILTER_GEOMETRY_H__
+
+#include "basictypes.h"
+
+namespace android {
+namespace mff {
+
+// This is an initial implementation of some geometrical structures. This is
+// likely to grow and become more sophisticated in the future.
+
+class Point {
+ public:
+ Point() : x_(0.0f), y_(0.0f) {}
+ Point(float x, float y) : x_(x), y_(y) {}
+
+ float x() const { return x_; }
+ float y() const { return y_; }
+
+ float Length() const;
+ bool ScaleTo(float new_length);
+ static float Distance(const Point& p0, const Point& p1);
+
+ // Add more of these as needed:
+ Point operator+(const Point& other) const;
+ Point operator-(const Point& other) const;
+ Point operator*(float factor) const;
+
+ void Rotate90Clockwise();
+
+ private:
+ float x_, y_;
+};
+
+class Quad {
+ public:
+ Quad() : points_(4) {}
+ virtual ~Quad() {}
+
+ Quad(const Point& p0, const Point& p1, const Point& p2, const Point& p3)
+ : points_(4) {
+ points_[0] = p0;
+ points_[1] = p1;
+ points_[2] = p2;
+ points_[3] = p3;
+ }
+
+ const vector<Point>& points() const { return points_; }
+ const Point& point(int ix) const;
+
+ protected:
+ vector<Point> points_;
+};
+
+class SlantedRect : public Quad {
+ public:
+ SlantedRect() : width_(0.0f), height_(0.0f) {}
+ virtual ~SlantedRect() {}
+
+ bool FromCenterAxisAndLengths(const Point& center,
+ const Point& vert_axis,
+ const Point& lenghts);
+
+ float width() const { return width_; }
+ float height() const { return height_; }
+
+ private:
+ float width_;
+ float height_;
+};
+
+struct Rect {
+ float x, y, width, height;
+
+ Rect() {
+ x = y = 0.0f;
+ width = height = 1.0f;
+ }
+
+ Rect(float x, float y, float width, float height) {
+ this->x = x;
+ this->y = y;
+ this->width = width;
+ this->height = height;
+ }
+
+ bool ExpandToAspectRatio(float ratio);
+ bool ExpandToMinLength(float length);
+ bool ScaleWithLengthLimit(float factor, float max_length);
+};
+
+} // namespace mff
+} // namespace android
+
+#endif
--- /dev/null
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#include "time_util.h"
+
+#include <map>
+#include <sys/time.h>
+
+#include <cutils/log.h>
+#include "utilities.h"
+
+namespace android {
+namespace mff {
+
+uint64_t getTimeUs() {
+ static long basesec;
+ struct timeval tv;
+ uint64_t nowtime;
+ gettimeofday(&tv, 0);
+ if (basesec == 0) {
+ basesec = tv.tv_sec;
+ }
+ nowtime = (uint64_t)(tv.tv_sec - basesec) * (uint64_t)1000000 +
+ (uint64_t)tv.tv_usec;
+ return nowtime;
+}
+
+const uint64_t NamedStopWatch::kDefaultLoggingPeriodInFrames = 100;
+
+NamedStopWatch::NamedStopWatch(const std::string& name)
+ : mName(name),
+ mLoggingPeriodInFrames(kDefaultLoggingPeriodInFrames),
+ mStartUSec(0),
+ mNumCalls(0),
+ mTotalUSec(0) {
+}
+
+void NamedStopWatch::Start() {
+ mStartUSec = getTimeUs();
+}
+
+void NamedStopWatch::Stop() {
+ if (!mStartUSec) {
+ return;
+ }
+ uint64_t stopUSec = getTimeUs();
+ if (stopUSec > mStartUSec) {
+ ++mNumCalls;
+ mTotalUSec += stopUSec - mStartUSec;
+ if (mNumCalls % mLoggingPeriodInFrames == 0) {
+ const float mSec = TotalUSec() * 1.0E-3f / NumCalls();
+ LOGE("%s: %f ms", Name().c_str(), mSec);
+ }
+ }
+ mStartUSec = 0;
+}
+
+namespace {
+static NamedStopWatch* GetWatchForName(const string& watch_name) {
+ // TODO: this leaks the NamedStopWatch objects. Replace it with a
+ // singleton to avoid that and make it thread safe.
+ static map<string, NamedStopWatch*> watches;
+ NamedStopWatch* watch = FindPtrOrNull(watches, watch_name);
+ if (!watch) {
+ watch = new NamedStopWatch(watch_name);
+ watches[watch_name] = watch;
+ }
+ return watch;
+};
+} // namespace
+
+ScopedTimer::ScopedTimer(const string& stop_watch_name) {
+ mWatch = GetWatchForName(stop_watch_name);
+ mWatch->Start();
+}
+
+} // namespace mff
+} // namespace android
--- /dev/null
+// Copyright 2011 Google Inc. All Rights Reserved.
+
+#ifndef VIDEO_FILTER_TIME_UTIL_H_
+#define VIDEO_FILTER_TIME_UTIL_H_
+
+#include <string>
+#include <utils/RefBase.h>
+
+#include "basictypes.h"
+
+#define LOG_MFF_RUNNING_TIMES 0
+
+namespace android {
+namespace mff {
+
+uint64_t getTimeUs();
+
+class NamedStopWatch : public RefBase {
+ public:
+ static const uint64_t kDefaultLoggingPeriodInFrames;
+
+ explicit NamedStopWatch(const string& name);
+ void Start();
+ void Stop();
+
+ void SetName(const string& name) { mName = name; }
+ void SetLoggingPeriodInFrames(uint64_t numFrames) {
+ mLoggingPeriodInFrames = numFrames;
+ }
+
+ const string& Name() const { return mName; }
+ uint64_t NumCalls() const { return mNumCalls; }
+ uint64_t TotalUSec() const { return mTotalUSec; }
+
+ private:
+ string mName;
+ uint64_t mLoggingPeriodInFrames;
+ uint64_t mStartUSec;
+ uint64_t mNumCalls;
+ uint64_t mTotalUSec;
+};
+
+class ScopedTimer {
+ public:
+ explicit ScopedTimer(const string& stop_watch_name);
+ explicit ScopedTimer(NamedStopWatch* watch)
+ : mWatch(watch) { mWatch->Start(); }
+ ~ScopedTimer() { mWatch->Stop(); }
+
+ private:
+ NamedStopWatch* mWatch;
+};
+
+} // namespace mff
+} // namespace android
+
+#endif // VIDEO_FILTER_TIME_UTIL_H_
--- /dev/null
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BASE_UTILTIES_H_
+#define BASE_UTILTIES_H_
+
+#include "basictypes.h"
+
+// Convenience Macro to make copy constructor and assignment operator private
+// (thereby disallowing copying and assigning).
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+ TypeName(); \
+ DISALLOW_COPY_AND_ASSIGN(TypeName)
+
+// STLDeleteContainerPointers()
+// For a range within a container of pointers, calls delete
+// (non-array version) on these pointers.
+// NOTE: for these three functions, we could just implement a DeleteObject
+// functor and then call for_each() on the range and functor, but this
+// requires us to pull in all of algorithm.h, which seems expensive.
+// For hash_[multi]set, it is important that this deletes behind the iterator
+// because the hash_set may call the hash function on the iterator when it is
+// advanced, which could result in the hash function trying to deference a
+// stale pointer.
+template <class ForwardIterator>
+void STLDeleteContainerPointers(ForwardIterator begin,
+ ForwardIterator end) {
+ while (begin != end) {
+ ForwardIterator temp = begin;
+ ++begin;
+ delete *temp;
+ }
+}
+
+// Given an STL container consisting of (key, value) pairs, STLDeleteValues
+// deletes all the "value" components and clears the container. Does nothing
+// in the case it's given a NULL pointer.
+template <class T>
+void STLDeleteValues(T *v) {
+ if (!v) return;
+ for (typename T::iterator i = v->begin(); i != v->end(); ++i) {
+ delete i->second;
+ }
+ v->clear();
+}
+
+// Perform a lookup in a map or hash_map.
+// If the key is present a const pointer to the associated value is returned,
+// otherwise a NULL pointer is returned.
+template <class Collection>
+const typename Collection::value_type::second_type*
+FindOrNull(const Collection& collection,
+ const typename Collection::value_type::first_type& key) {
+ typename Collection::const_iterator it = collection.find(key);
+ if (it == collection.end()) {
+ return 0;
+ }
+ return &it->second;
+}
+
+// A simple class that gives checklist functionality: There are essemtially two
+// operations defined on a CheckList:
+// - Adding a new (unchecked) item.
+// - Checking off an item.
+// When checking off the last remaining item CheckItem() returns true.
+template<typename T>
+class CheckList {
+ public:
+ // Add a new unchecked item. Does nothing if item is already in checklist.
+ void AddItem(const T& item);
+
+ // Check off an item in the checklist. Returns true if all items have been
+ // checked.
+ bool CheckItem(const T& item);
+
+ // Clear the checklist.
+ void Clear() {
+ items_.clear();
+ }
+
+ private:
+ set<T> items_;
+};
+
+template<typename T>
+void CheckList<T>::AddItem(const T& item) {
+ if (!ContainsKey(items_, item))
+ items_.insert(item);
+}
+
+template<typename T>
+bool CheckList<T>::CheckItem(const T& item) {
+ typename set<T>::iterator iter = items_.find(item);
+ if (iter != items_.end())
+ items_.erase(iter);
+ return items_.empty();
+}
+
+// Perform a lookup in a map or hash_map whose values are pointers.
+// If the key is present a const pointer to the associated value is returned,
+// otherwise a NULL pointer is returned.
+// This function does not distinguish between a missing key and a key mapped
+// to a NULL value.
+template <class Collection>
+const typename Collection::value_type::second_type
+FindPtrOrNull(const Collection& collection,
+ const typename Collection::value_type::first_type& key) {
+ typename Collection::const_iterator it = collection.find(key);
+ if (it == collection.end()) {
+ return 0;
+ }
+ return it->second;
+}
+
+// Test to see if a set, map, hash_set or hash_map contains a particular key.
+// Returns true if the key is in the collection.
+template <typename Collection, typename Key>
+bool ContainsKey(const Collection& collection, const Key& key) {
+ return collection.find(key) != collection.end();
+}
+
+// Insert a new key and value into a map or hash_map.
+// If the key is not present in the map the key and value are
+// inserted, otherwise nothing happens. True indicates that an insert
+// took place, false indicates the key was already present.
+template <class Collection, class Key, class Value>
+bool InsertIfNotPresent(Collection * const collection,
+ const Key& key, const Value& value) {
+ pair<typename Collection::iterator, bool> ret =
+ collection->insert(typename Collection::value_type(key, value));
+ return ret.second;
+}
+
+#endif // BASE_UTILTIES_H_
+
--- /dev/null
+#ifndef FILTERFW_CORE_VEC_TYPES_
+#define FILTERFW_CORE_VEC_TYPES_
+
+#include "basictypes.h"
+
+namespace android {
+namespace mff {
+
+template < class T, int dim>
+class VecBase {
+ public:
+ T data[dim];
+ VecBase() {}
+ VecBase<T,dim>& operator = (const VecBase<T, dim> &x) {
+ memcpy(data, x.data, sizeof(T)*dim);
+ return *this;
+ }
+ T & operator [] (int i) {
+ // out of boundary not checked
+ return data[i];
+ }
+ const T & operator [] (int i) const {
+ // out of boundary not checked
+ return data[i];
+ }
+ T Length() {
+ double sum = 0;
+ for (int i = 0; i < dim; ++i)
+ sum += static_cast<double> (data[i] * data[i]);
+ return static_cast<T>(sqrt(sum));
+ }
+};
+
+template < class T, int dim>
+class Vec : public VecBase<T,dim> {
+ public:
+ Vec() {}
+ Vec<T,dim>& operator = (const Vec<T, dim> &x) {
+ memcpy(this->data, x.data, sizeof(T)*dim);
+ return *this;
+ }
+};
+
+template <class T, int dim>
+Vec<T, dim> operator + (const Vec<T,dim> &x, const Vec<T,dim> &y) {
+ Vec<T, dim> out;
+ for (int i = 0; i < dim; i++)
+ out.data[i] = x.data[i] + y.data[i];
+ return out;
+}
+
+template <class T, int dim>
+Vec<T, dim> operator - (const Vec<T,dim> &x, const Vec<T,dim> &y) {
+ Vec<T, dim> out;
+ for (int i = 0; i < dim; i++)
+ out.data[i] = x.data[i] - y.data[i];
+ return out;
+}
+
+template <class T, int dim>
+Vec<T, dim> operator * (const Vec<T,dim> &x, const Vec<T,dim> &y) {
+ Vec<T, dim> out;
+ for (int i = 0; i < dim; i++)
+ out.data[i] = x.data[i] * y.data[i];
+ return out;
+}
+
+template <class T, int dim>
+Vec<T, dim> operator / (const Vec<T,dim> &x, const Vec<T,dim> &y) {
+ Vec<T, dim> out;
+ for (int i = 0; i < dim; i++)
+ out.data[i] = x.data[i] / y.data[i];
+ return out;
+}
+
+template <class T, int dim>
+T dot(const Vec<T,dim> &x, const Vec<T,dim> &y) {
+ T out = 0;
+ for (int i = 0; i < dim; i++)
+ out += x.data[i] * y.data[i];
+ return out;
+}
+
+template <class T, int dim>
+Vec<T, dim> operator * (const Vec<T,dim> &x, T scale) {
+ Vec<T, dim> out;
+ for (int i = 0; i < dim; i++)
+ out.data[i] = x.data[i] * scale;
+ return out;
+}
+
+template <class T, int dim>
+Vec<T, dim> operator / (const Vec<T,dim> &x, T scale) {
+ Vec<T, dim> out;
+ for (int i = 0; i < dim; i++)
+ out.data[i] = x.data[i] / scale;
+ return out;
+}
+
+template <class T, int dim>
+Vec<T, dim> operator + (const Vec<T,dim> &x, T val) {
+ Vec<T, dim> out;
+ for (int i = 0; i < dim; i++)
+ out.data[i] = x.data[i] + val;
+ return out;
+}
+
+// specialization for vec2, vec3, vec4 float
+template<>
+class Vec<float, 2> : public VecBase<float, 2> {
+public:
+ Vec() {}
+ Vec(float x, float y) {
+ data[0] = x;
+ data[1] = y;
+ }
+ Vec<float, 2>& operator = (const Vec<float, 2> &x) {
+ memcpy(data, x.data, sizeof(float)*2);
+ return *this;
+ }
+};
+
+template<>
+class Vec<float, 3> {
+public:
+ float data[3];
+ Vec() {}
+ Vec(float x, float y, float z) {
+ data[0] = x;
+ data[1] = y;
+ data[2] = z;
+ }
+ Vec<float, 3>& operator = (const Vec<float, 3> &x) {
+ memcpy(data, x.data, sizeof(float)*3);
+ return *this;
+ }
+};
+
+template<>
+class Vec<float, 4> {
+public:
+ float data[4];
+ Vec() {}
+ Vec(float x, float y, float z, float w) {
+ data[0] = x;
+ data[1] = y;
+ data[2] = z;
+ data[3] = w;
+ }
+ Vec<float, 4>& operator = (const Vec<float, 4> &x) {
+ memcpy(data, x.data, sizeof(float)*4);
+ return *this;
+ }
+};
+
+typedef Vec<float,2> Vec2f;
+typedef Vec<float,3> Vec3f;
+typedef Vec<float,4> Vec4f;
+
+} // namespace filterfw
+} // namespace android
+
+#endif