OSDN Git Service

Moving Contexts out of Filters and other bugfixes.
authorMarius Renn <renn@google.com>
Fri, 8 Jul 2011 01:26:21 +0000 (18:26 -0700)
committerMarius Renn <renn@google.com>
Fri, 8 Jul 2011 01:26:21 +0000 (18:26 -0700)
Change-Id: I14ba6c5e9702d8a5629db1119fefbd7a83254d51

mca/filterfw/java/android/filterfw/basefilters/FrameSource.java [moved from mca/filterfw/java/android/filterfw/basefilters/StaticFrameFilter.java with 60% similarity]
mca/filterfw/java/android/filterfw/basefilters/InputStreamSource.java [moved from mca/filterfw/java/android/filterfw/basefilters/FileReadFilter.java with 54% similarity]
mca/filterfw/java/android/filterfw/basefilters/ObjectSource.java
mca/filterfw/java/android/filterfw/basefilters/OutputStreamTarget.java [moved from mca/filterfw/java/android/filterfw/basefilters/FileWriteFilter.java with 52% similarity]
mca/filterfw/java/android/filterfw/core/FilterFunction.java
mca/filterfw/jni/jni_gl_frame.cpp
mca/filterpacks/imageproc/java/BitmapSource.java [moved from mca/filterpacks/imageproc/java/ImageDecoder.java with 76% similarity]
mca/filterpacks/imageproc/java/ImageEncoder.java
mca/filterpacks/ui/java/SurfaceRenderFilter.java

@@ -21,34 +21,43 @@ import android.filterfw.core.Filter;
 import android.filterfw.core.FilterContext;
 import android.filterfw.core.Frame;
 import android.filterfw.core.FrameFormat;
+import android.filterfw.core.GenerateFieldPort;
 import android.filterfw.core.GenerateFinalPort;
-import android.filterfw.core.KeyValueMap;
 
-// TODO: Rename to FixedFrameSource and also add a (dynamic) FrameSource?
 /**
  * @hide
  */
-public class StaticFrameFilter extends Filter {
+public class FrameSource extends Filter {
 
-    @GenerateFinalPort(name = "frame")
-    private Frame mFrame;
+    @GenerateFinalPort(name = "format")
+    private FrameFormat mFormat;
 
-    public StaticFrameFilter(String name) {
+    @GenerateFieldPort(name = "frame", hasDefault = true)
+    private Frame mFrame = null;
+
+    @GenerateFieldPort(name = "repeatFrame", hasDefault = true)
+    private boolean mRepeatFrame = false;
+
+    public FrameSource(String name) {
         super(name);
     }
 
     @Override
     public void setupPorts() {
-        addOutputPort("frame", mFrame.getFormat());
+        addOutputPort("frame", mFormat);
     }
 
     @Override
     public void process(FilterContext context) {
-        // Push output
-        pushOutput("frame", mFrame);
-
-        // Close output port as we are done here
-        closeOutputPort("frame");
+        if (mFrame != null) {
+            // Push output
+            pushOutput("frame", mFrame);
+        }
+
+        if (!mRepeatFrame) {
+            // Close output port as we are done here
+            closeOutputPort("frame");
+        }
     }
 
 }
@@ -17,9 +17,6 @@
 
 package android.filterpacks.base;
 
-import android.content.Context;
-import android.content.res.Resources;
-
 import android.filterfw.core.Filter;
 import android.filterfw.core.FilterContext;
 import android.filterfw.core.Frame;
@@ -32,79 +29,34 @@ import android.filterfw.format.PrimitiveFormat;
 
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Set;
-
-import android.util.Log;
 
 /**
  * @hide
  */
-public class FileReadFilter extends Filter {
+public class InputStreamSource extends Filter {
 
     @GenerateFinalPort(name = "target")
     private String mTarget;
 
-    @GenerateFieldPort(name = "context")
-    private Context mActivityContext;
-
-    @GenerateFieldPort(name = "format")
-    private FrameFormat mFrameFormat;
-
-    // TODO: Split this into two (subclass) filters: FileReadFilter and ResourceReadFilter.
-    @GenerateFieldPort(name = "resourceId", hasDefault = true)
-    private int mResourceId = -1;
-
-    @GenerateFieldPort(name = "fileName", hasDefault = true)
-    private String mFileInputName;
-
-    private final int FILE_MODE_FILE      = 0;
-    private final int FILE_MODE_RESOURCE  = 1;
-
-    private MutableFrameFormat mOutputFormat;
-
+    @GenerateFieldPort(name = "stream")
     private InputStream mInputStream;
-    private int mFileMode = FILE_MODE_FILE;
 
-    public FileReadFilter(String name) {
+    @GenerateFinalPort(name = "format", hasDefault = true)
+    private MutableFrameFormat mOutputFormat = null;
+
+    public InputStreamSource(String name) {
         super(name);
     }
 
     @Override
     public void setupPorts() {
         int target = FrameFormat.readTargetString(mTarget);
-        mOutputFormat = PrimitiveFormat.createByteFormat(target);
-        addOutputPort("data", mOutputFormat);
-    }
-
-    @Override
-    public void open(FilterContext context) {
-        // Read file input parameter
-        if (mFileInputName != null) {
-            mFileMode = FILE_MODE_FILE;
-        } else if (mResourceId >= 0) {
-            mFileMode = FILE_MODE_RESOURCE;
-        } else {
-            throw new RuntimeException("No input file specified! Please set fileName or resourceId!");
-        }
-
-        // Open the file
-        try {
-            switch (mFileMode) {
-                case FILE_MODE_FILE:
-                    mInputStream = mActivityContext.openFileInput(mFileInputName);
-                    break;
-                case FILE_MODE_RESOURCE:
-                    mInputStream = mActivityContext.getResources().openRawResource(mResourceId);
-                    break;
-            }
-            Log.i("FileReadFilter", "InputStream = " + mInputStream);
-        } catch (FileNotFoundException exception) {
-            throw new RuntimeException("FileReader: Could not open file: " + mFileInputName + "!");
+        if (mOutputFormat == null) {
+            mOutputFormat = PrimitiveFormat.createByteFormat(target);
         }
+        addOutputPort("data", mOutputFormat);
     }
 
     @Override
@@ -123,8 +75,8 @@ public class FileReadFilter extends Filter {
             }
             byteBuffer = ByteBuffer.wrap(byteStream.toByteArray());
         } catch (IOException exception) {
-            throw new RuntimeException("FileReader: Could not read from file: " +
-                                       mFileInputName + "!");
+            throw new RuntimeException(
+                "InputStreamSource: Could not read stream: " + exception.getMessage() + "!");
         }
 
         // Put it into a frame
@@ -147,7 +99,7 @@ public class FileReadFilter extends Filter {
         try {
             mInputStream.close();
         } catch (IOException exception) {
-            throw new RuntimeException("FileReader: Could not close file!");
+            throw new RuntimeException("InputStreamSource: Could not close stream!");
         }
     }
 }
index 409e687..58222c2 100644 (file)
@@ -24,6 +24,7 @@ import android.filterfw.core.FilterContext;
 import android.filterfw.core.Frame;
 import android.filterfw.core.FrameFormat;
 import android.filterfw.core.GenerateFieldPort;
+import android.filterfw.core.GenerateFinalPort;
 import android.filterfw.core.MutableFrameFormat;
 import android.filterfw.format.ObjectFormat;
 
@@ -35,6 +36,9 @@ public class ObjectSource extends Filter {
     @GenerateFieldPort(name = "object")
     private Object mObject;
 
+    @GenerateFinalPort(name = "format", hasDefault = true)
+    private FrameFormat mOutputFormat = FrameFormat.unspecified();
+
     @GenerateFieldPort(name = "repeatFrame", hasDefault = true)
     boolean mRepeatFrame = false;
 
@@ -46,7 +50,7 @@ public class ObjectSource extends Filter {
 
     @Override
     public void setupPorts() {
-        addOutputPort("frame", FrameFormat.unspecified());
+        addOutputPort("frame", mOutputFormat);
     }
 
     @Override
 
 package android.filterpacks.base;
 
-import android.content.Context;
-
 import android.filterfw.core.Filter;
 import android.filterfw.core.FilterContext;
 import android.filterfw.core.Frame;
 import android.filterfw.core.FrameFormat;
-import android.filterfw.core.KeyValueMap;
 import android.filterfw.core.GenerateFieldPort;
 
-import java.io.BufferedOutputStream;
-import java.io.FileOutputStream;
-import java.io.FileNotFoundException;
+import java.io.OutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.Set;
 
 /**
  * @hide
  */
-public class FileWriteFilter extends Filter {
-
-    @GenerateFieldPort(name = "fileName")
-    private String mOutputName;
-
-    @GenerateFieldPort(name = "context")
-    private Context mActivityContext;
+public class OutputStreamTarget extends Filter {
 
-    private BufferedOutputStream mWriter;
+    @GenerateFieldPort(name = "stream")
+    private OutputStream mOutputStream;
 
-    public FileWriteFilter(String name) {
+    public OutputStreamTarget(String name) {
         super(name);
     }
 
@@ -56,25 +45,6 @@ public class FileWriteFilter extends Filter {
     }
 
     @Override
-    public void fieldPortValueUpdated(String name, FilterContext context) {
-        if (isOpen()) {
-            throw new RuntimeException("Cannot update parameters while filter is open!");
-        }
-    }
-
-    @Override
-    public void open(FilterContext context) {
-        FileOutputStream outStream = null;
-        try {
-            outStream = mActivityContext.openFileOutput(mOutputName, Context.MODE_PRIVATE);
-        } catch (FileNotFoundException exception) {
-            throw new RuntimeException("FileWriter: Could not open file: " + mOutputName + ": " +
-                                       exception.getMessage());
-        }
-        mWriter = new BufferedOutputStream(outStream);
-    }
-
-    @Override
     public void process(FilterContext context) {
         Frame input = pullInput("data");
         ByteBuffer data;
@@ -86,19 +56,20 @@ public class FileWriteFilter extends Filter {
             data = input.getData();
         }
         try {
-            mWriter.write(data.array(), 0, data.limit());
-            mWriter.flush();
+            mOutputStream.write(data.array(), 0, data.limit());
+            mOutputStream.flush();
         } catch (IOException exception) {
-            throw new RuntimeException("FileWriter: Could not write to file: " + mOutputName + "!");
+            throw new RuntimeException(
+                "OutputStreamTarget: Could not write to stream: " + exception.getMessage() + "!");
         }
     }
 
     @Override
     public void close(FilterContext context) {
         try {
-            mWriter.close();
+            mOutputStream.close();
         } catch (IOException exception) {
-            throw new RuntimeException("FileWriter: Could not close file!");
+            throw new RuntimeException("OutputStreamTarget: Could not close stream!");
         }
     }
 }
index 94d2054..c379097 100644 (file)
@@ -56,8 +56,11 @@ public class FilterFunction {
         }
 
         // Make sure GL environment is active
-        if (mFilterContext.getGLEnvironment() != null) {
-            mFilterContext.getGLEnvironment().activate();
+        boolean didActivateGLEnv = false;
+        GLEnvironment glEnv = mFilterContext.getGLEnvironment();
+        if (glEnv != null && !glEnv.isActive()) {
+            glEnv.activate();
+            didActivateGLEnv = true;
         }
 
         // Setup the inputs
@@ -81,6 +84,11 @@ public class FilterFunction {
             result = mResultHolders[0].pullFrame();
         }
 
+        // Deactivate GL environment if activated
+        if (didActivateGLEnv) {
+            glEnv.deactivate();
+        }
+
         return result;
     }
 
index 86893e2..3a2e581 100644 (file)
 using android::filterfw::GLFrame;
 using android::filterfw::NativeFrame;
 
+// Helper functions ////////////////////////////////////////////////////////////////////////////////
+void ConvertFloatsToRGBA(const float* floats, int length, uint8_t* result) {
+  for (int i = 0; i < length; ++i) {
+    result[i] = static_cast<uint8_t>(floats[i] * 255.0);
+  }
+}
+
+void ConvertRGBAToFloats(const uint8_t* rgba, int length, float* result) {
+  for (int i = 0; i < length; ++i) {
+    result[i] = rgba[i] / 255.0;
+  }
+}
+
+void ConvertIntsToRGBA(const int* ints, int length, uint8_t* result) {
+  for (int i = 0; i < length; ++i) {
+    result[i] = static_cast<uint8_t>(ints[i]);
+  }
+}
+
+void ConvertRGBAToInts(const uint8_t* rgba, int length, int* result) {
+  for (int i = 0; i < length; ++i) {
+    result[i] = rgba[i];
+  }
+}
+// GLFrame JNI implementation //////////////////////////////////////////////////////////////////////
 jboolean Java_android_filterfw_core_GLFrame_allocate(JNIEnv* env,
                                                      jobject thiz,
                                                      jint width,
@@ -85,10 +110,10 @@ jboolean Java_android_filterfw_core_GLFrame_deallocate(JNIEnv* env, jobject thiz
 }
 
 jboolean Java_android_filterfw_core_GLFrame_setNativeData(JNIEnv* env,
-                                                              jobject thiz,
-                                                              jbyteArray data,
-                                                              jint offset,
-                                                              jint length) {
+                                                          jobject thiz,
+                                                          jbyteArray data,
+                                                          jint offset,
+                                                          jint length) {
   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
   if (frame && data) {
     jbyte* bytes = env->GetByteArrayElements(data, NULL);
@@ -121,9 +146,16 @@ jboolean Java_android_filterfw_core_GLFrame_setNativeInts(JNIEnv* env,
     jint* int_ptr = env->GetIntArrayElements(ints, NULL);
     const int length = env->GetArrayLength(ints);
     if (int_ptr) {
-      const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(int_ptr),
-                                            length * sizeof(jint));
+      // Convert ints to RGBA buffer
+      uint8_t* rgba_buffer = new uint8_t[length];
+      ConvertIntsToRGBA(int_ptr, length, rgba_buffer);
       env->ReleaseIntArrayElements(ints, int_ptr, JNI_ABORT);
+
+      // Write RGBA buffer to frame
+      const bool success = frame->WriteData(rgba_buffer, length);
+
+      // Clean-up
+      delete[] rgba_buffer;
       return ToJBool(success);
     }
   }
@@ -132,11 +164,21 @@ jboolean Java_android_filterfw_core_GLFrame_setNativeInts(JNIEnv* env,
 
 jintArray Java_android_filterfw_core_GLFrame_getNativeInts(JNIEnv* env, jobject thiz) {
   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
-  if (frame && frame->Size() > 0 && (frame->Size() % sizeof(jint) == 0)) {
-    jintArray result = env->NewIntArray(frame->Size() / sizeof(jint));
-    jint* data = env->GetIntArrayElements(result, NULL);
-    frame->CopyDataTo(reinterpret_cast<uint8_t*>(data), frame->Size());
-    env->ReleaseIntArrayElements(result, data, 0);
+  if (frame && frame->Size() > 0) {
+    // Create the result array
+    jintArray result = env->NewIntArray(frame->Size());
+    jint* int_array = env->GetIntArrayElements(result, NULL);
+
+    // Read the frame pixels
+    uint8_t* pixels = new uint8_t[frame->Size()];
+    frame->CopyDataTo(pixels, frame->Size());
+
+    // Convert them to integers
+    ConvertRGBAToInts(pixels, frame->Size(), int_array);
+
+    // Clean-up
+    delete[] pixels;
+    env->ReleaseIntArrayElements(result, int_array, 0);
     return result;
   }
   return NULL;
@@ -150,9 +192,16 @@ jboolean Java_android_filterfw_core_GLFrame_setNativeFloats(JNIEnv* env,
     jfloat* float_ptr = env->GetFloatArrayElements(floats, NULL);
     const int length = env->GetArrayLength(floats);
     if (float_ptr) {
-      const bool success = frame->WriteData(reinterpret_cast<const uint8_t*>(float_ptr),
-                                            length * sizeof(jfloat));
+      // Convert floats to RGBA buffer
+      uint8_t* rgba_buffer = new uint8_t[length];
+      ConvertFloatsToRGBA(float_ptr, length, rgba_buffer);
       env->ReleaseFloatArrayElements(floats, float_ptr, JNI_ABORT);
+
+      // Write RGBA buffer to frame
+      const bool success = frame->WriteData(rgba_buffer, length);
+
+      // Clean-up
+      delete[] rgba_buffer;
       return ToJBool(success);
     }
   }
@@ -161,11 +210,21 @@ jboolean Java_android_filterfw_core_GLFrame_setNativeFloats(JNIEnv* env,
 
 jfloatArray Java_android_filterfw_core_GLFrame_getNativeFloats(JNIEnv* env, jobject thiz) {
   GLFrame* frame = ConvertFromJava<GLFrame>(env, thiz);
-  if (frame && frame->Size() > 0 && (frame->Size() % sizeof(jfloat) == 0)) {
-    jfloatArray result = env->NewFloatArray(frame->Size() / sizeof(jfloat));
-    jfloat* data = env->GetFloatArrayElements(result, NULL);
-    frame->CopyDataTo(reinterpret_cast<uint8_t*>(data), frame->Size());
-    env->ReleaseFloatArrayElements(result, data, 0);
+  if (frame && frame->Size() > 0) {
+    // Create the result array
+    jfloatArray result = env->NewFloatArray(frame->Size());
+    jfloat* float_array = env->GetFloatArrayElements(result, NULL);
+
+    // Read the frame pixels
+    uint8_t* pixels = new uint8_t[frame->Size()];
+    frame->CopyDataTo(pixels, frame->Size());
+
+    // Convert them to floats
+    ConvertRGBAToFloats(pixels, frame->Size(), float_array);
+
+    // Clean-up
+    delete[] pixels;
+    env->ReleaseFloatArrayElements(result, float_array, 0);
     return result;
   }
   return NULL;
@@ -30,21 +30,17 @@ import android.filterfw.core.MutableFrameFormat;
 import android.filterfw.core.NativeFrame;
 import android.filterfw.format.ImageFormat;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 
 /**
  * @hide
  */
-public class ImageDecoder extends Filter {
+public class BitmapSource extends Filter {
 
     @GenerateFinalPort(name = "target")
     String mTargetString;
 
-    @GenerateFieldPort(name = "resourceName")
-    String mResourceName;
-
-    @GenerateFieldPort(name = "context")
-    Context mContext;
+    @GenerateFieldPort(name = "bitmap")
+    private Bitmap mBitmap;
 
     @GenerateFieldPort(name = "repeatFrame", hasDefault = true)
     boolean mRepeatFrame = false;
@@ -52,7 +48,7 @@ public class ImageDecoder extends Filter {
     private int mTarget;
     private Frame mImageFrame;
 
-    public ImageDecoder(String name) {
+    public BitmapSource(String name) {
         super(name);
     }
 
@@ -68,25 +64,19 @@ public class ImageDecoder extends Filter {
     }
 
     public void loadImage(FilterContext filterContext) {
-        // Load image
-        int resourceId = mContext.getResources().getIdentifier(mResourceName,
-                                                               null,
-                                                               mContext.getPackageName());
-        Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), resourceId);
-
-        // Wrap in frame
-        FrameFormat outputFormat = ImageFormat.create(bitmap.getWidth(),
-                                                      bitmap.getHeight(),
+        FrameFormat outputFormat = ImageFormat.create(mBitmap.getWidth(),
+                                                      mBitmap.getHeight(),
                                                       ImageFormat.COLORSPACE_RGBA,
                                                       mTarget);
         mImageFrame = filterContext.getFrameManager().newFrame(outputFormat);
-        mImageFrame.setBitmap(bitmap);
+        mImageFrame.setBitmap(mBitmap);
+        mBitmap = null;
     }
 
     @Override
     public void fieldPortValueUpdated(String name, FilterContext context) {
         // Clear image (to trigger reload) in case parameters have been changed
-        if (name.equals("resourceName") || name.equals("context")) {
+        if (name.equals("bitmap") || name.equals("target")) {
             if (mImageFrame != null) {
                 mImageFrame.release();
                 mImageFrame = null;
index 0d9e97e..a5405cb 100644 (file)
@@ -30,9 +30,7 @@ import android.graphics.Bitmap.CompressFormat;
 
 import android.util.Log;
 
-import java.io.FileOutputStream;
-import java.io.BufferedOutputStream;
-import java.io.FileNotFoundException;
+import java.io.OutputStream;
 import java.io.IOException;
 
 /**
@@ -40,11 +38,11 @@ import java.io.IOException;
  */
 public class ImageEncoder extends Filter {
 
-    @GenerateFieldPort(name = "fileName")
-    private String mOutputName;
+    @GenerateFieldPort(name = "stream")
+    private OutputStream mOutputStream;
 
-    @GenerateFieldPort(name = "context")
-    private Context mContext;
+    @GenerateFieldPort(name = "quality", hasDefault = true)
+    private int mQuality = 80;
 
     public ImageEncoder(String name) {
         super(name);
@@ -60,24 +58,7 @@ public class ImageEncoder extends Filter {
     public void process(FilterContext env) {
         Frame input = pullInput("image");
         Bitmap bitmap = input.getBitmap();
-        FileOutputStream outStream = null;
-
-        try {
-            outStream = mContext.openFileOutput(mOutputName, Context.MODE_PRIVATE);
-        } catch (FileNotFoundException exception) {
-            throw new RuntimeException("ImageEncoder: Could not open file: " + mOutputName + "!");
-        }
-
-        BufferedOutputStream bufferedStream = new BufferedOutputStream(outStream);
-        bitmap.compress(CompressFormat.JPEG, 80, bufferedStream);
-
-        try {
-            bufferedStream.flush();
-            bufferedStream.close();
-        } catch (IOException exception) {
-            throw new RuntimeException("ImageEncoder: Could not write to file: " +
-                                       mOutputName + "!");
-        }
+        bitmap.compress(CompressFormat.JPEG, mQuality, mOutputStream);
     }
 
 }
index 764eccc..b623ad9 100644 (file)
@@ -172,11 +172,10 @@ public class SurfaceRenderFilter extends Filter implements FilterSurfaceRenderer
         // See if we need to copy to GPU
         Frame gpuFrame = null;
         if (mLogVerbose) Log.v("SurfaceRenderFilter", "Got input format: " + input.getFormat());
-        if (input.getFormat().getTarget() == FrameFormat.TARGET_NATIVE) {
-            MutableFrameFormat gpuFormat = input.getFormat().mutableCopy();
-            gpuFormat.setTarget(FrameFormat.TARGET_GPU);
-            gpuFrame = context.getFrameManager().newFrame(gpuFormat);
-            gpuFrame.setData(input.getData());
+        int target = input.getFormat().getTarget();
+        if (target != FrameFormat.TARGET_GPU) {
+            gpuFrame = context.getFrameManager().duplicateFrameToTarget(input,
+                                                                        FrameFormat.TARGET_GPU);
             createdFrame = true;
         } else {
             gpuFrame = input;