Android Camera Without Preview - android

I've seen many threads on this but cannot figure out what is the best possible way of doing camera capture without having a preview.
The way that I am doing it now is that I create a SurfaceTexture like this:
SurfaceTexture fakePreview = new SurfaceTexture(10);
The fakePreview object is not used for any other purpose and is just set as the preview texture, and disposed of when finished with the Activity.
The fakePreview SurfaceTexture is set and the preview then started like this:
mCamera.setPreviewTexture(fakePreview);
mCamera.startPreview();
This seems to work fine, but I'm using a rather low-quality sensor and would like to get the highest possible capture quality out of it. So I'm always looking for ways to improve upon this.
I've seen a few methods other than this for starting the camera without showing preview such as setting up a preview normally but setting it's size to 0x0dp: https://stackoverflow.com/a/9745780/593340
As well as using a dummy surfaceholder.callback: https://stackoverflow.com/a/23621826/593340
My question is is there any advantages or disadvantages by using the method I described above?
If my method has issues, do the two other examples posted represent a better answer or are they just as bad?
Thirdly, am I gaining any performance by neglecting to show preview or am I just causing potential bugs by doing this?
Thanks for looking!
-Rob

Related

Making delay in camera - kotlin

I'm trying to make application with camera delay. It should work like this:
user see preview of live camera
user choose for example delay 5 sec
after waiting delay time user see that what camera saw 5 sec ago.
I thought about taking frames from preview and showing them after this delay time, but I'm not sure how to take them and make "movie" from them. I was thinking about CameraX but I'm not sure that this is the best option. I will really appreciate every help.
You can use CameraX as well for your project. Of course I won't go into so much detail but you can follow a path like:
Do not bind a preview use case and do not use preview view.
Instead use an Image view or equivalent in which you can set/draw an image.
Do bind ImageAnalysis use case.
Get the frames for ImageAnalysis and then send it directly to be drawn onto the view mentioned above. (Image view might be too expensive, not sure)
In the above step you can add a delay function to delay drawing as much as you wish.
Of course this is probably not the most effective or elegant way to solve this, but it would work.

Does mirroring the (front) camera affect MLKit with CameraX?

You might consider this question a sequel to this other one I've recently asked. I have a custom device with a front camera that is mirrored by default and I would like it to always behave like it was flipped horizontally. Note that the end goal of my app is to perform face, barcode and facemask detection (the last one with a custom .tflite model), and I'm trying to understand if it's possible with the current state of CameraX and the quirks of the device I'm using.
For the preview, I can force PreviewView to use a TextureView by calling PreviewView#implementationMode = PreviewView.ImplementationMode.COMPATIBLE so I can just call PreviewView#setScaleX(-1) and it gets displayed like I want.
For taking pictures, I haven't tried yet but I know I can pass setReversedHorizontal(true) to the ImageCapture.OutputFileOptions used in the ImageCapture.Builder, so the image should be saved in reverse.
For image analysis I really don't know. If the input image is taken directly from the preview stream, then it should still be in its default state because PreviewView#setScaleX(-1) only flips the View on screen, right? So in my Analyzer's analyze() I would need to convert the ImageProxy#image to bitmap, then flip it and pass the result to InputImage.fromBitmap().
Is this everything I need? Is there a better way to do this?

Use MediaCodec to record 720p video but fps of encoding video is too low

I managed to write a video recording demo, my implementation is the same as ContinuousCaptureActivity of Grafika.
In ContinuousCaptureActivity.java, The author create egl object in SurfaceCreated which run in UI thread and call drawFrame also in UI thread. He did 2 things in drawFrame, draw frame to screen and push data to encoder.
See the code here: ContinuousCaptureActivity
Because I set the encoding video size to 1280*720 which is large, the camera preview is not smooth and fps of target video is low.
I plan to create a new thread to do the encoding work but I do not know how to handle with multithread of opengl es. Who can give some advice?
Add: I found that drawFrame of Texture2dProgram use GLES20.glDrawArrays, Will GLES20.glDrawElements get a better performance?
First, 1280x720 shouldn't be an issue for mainstream devices. Some super-cheap low-end devices might struggle, but there isn't really anything you can do if the hardware simply can't handle 1280x720x30fps.
The most common reasons I've seen for low FPS at 720p are failure to configure the Camera with a reasonable fps value (using setPreviewFpsRange() with a value from getSupportedPreviewFpsRange()), and failing to call setRecordingHint(true) (or the Camera2 equivalent). The latter can take you from 15fps to 30fps, but may affect the aspect ratio of the preview.
The video encoding is performed in a separate process, called mediaserver, which manages all interaction with the video encoder hardware. There are already multiple threads in play, so adding another won't help.
The GLES code is drawing two textured triangles. Using a different API won't change the difference.
If you think there is a performance bottleneck, you need to use tools like systrace to narrow it down.
I finally found a way to make drawing frame to screen faster which eventually save the time of processing each frame.
The detail is as follows:
mPreviewWidth = mCamera.getParameters().getPreviewSize().width;
mPreviewHeight = mCamera.getParameters().getPreviewSize().height;
holder.setFixedSize(mPreviewWidth, mPreviewHeight);
add these code to https://github.com/google/grafika/blob/master/src/com/android/grafika/ContinuousCaptureActivity.java#L352
then use GLES20.glViewport(0, 0, mPreviewWidth, mPreviewHeight); to replace https://github.com/google/grafika/blob/master/src/com/android/grafika/ContinuousCaptureActivity.java#L436
This modification will reduce data size of frame to draw a lot.
But it will make preview image not so smooth if we use TextureView, and we can use setScaleX(1.00001f); setScaleY(1.00001f); to resolve it.

Android blur surfaceview used in camera

I have a camera preview in my android app. As you all probably know it is implemented by a surfaceview in android.
In my photo app, which allows users to take pictures, I want to blur the camera preview (the surface view) if the user has not logged in yet if the user is logged in, I will display the normal preview (without blur)
Blur as something like
But there seems to be no way to do it
Couple things come to mind but I am not sure how to achieve it
use a blur overlay and place it on top of the surface view, but how do u create such blur overlay?
another approach is to change the attribute of the window, but I can't do it to surfaceview,
getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
So can we create a window overlay the surfaceview and set the flag like that? I don't think so
can someone tell me how to blur a camera preview, which is a surface view
note: I am trying to blur an area which is the output from camera preview, so it is not like I am blurring a static image, the blur area will change depending on where you point your phone camera
The best way to do this is to take a screen shot of the control, apply a blur to it, and then show that image over the top of the original control. This is how the yahoo weather app does it and its how google suggest you do things like this.
Render script does bluring fast. I've also got some code, but it's not currently at hand right now.
These might help:
http://blog.neteril.org/blog/2013/08/12/blurring-images-on-android
http://docs.xamarin.com/recipes/android/other_ux/drawing/blur_an_image_with_renderscript/
I've also read that there are methods built into Android that do this, but the API isn't public so we cannot use it... which sucks.
Although your 2nd option is losing support in later versions of the Android OS, it may be a good option. I would think to bring a window IN FRONT of your surfaceview, and use the blur_behind property of your now new IN FRONT window.
Android API documentation
"
This constant was deprecated in API level 14.
Blurring is no longer supported.
Window flag: blur everything behind this window.
Constant Value: 4 (0x00000004)"
I do have to admit, Im not 100% sure this would work, but its definitely worth a try.
You have to change the camera parameters; in this case with Camera.Parameters.setPictureSize().
The basic workflow here is :
Camera.Parameters cp = mCamera.getParameters(); // get the current params
cp.set...(); // change something
mCamera.setParameters(cp); // write the params back
Make sure that every resolution that you set via this function is supported. You can get a list of the resolutions that are supported on a device via Camera.Parameters.getSupportedPictureSizes(). and check this Camera documentation.

Android: onPreviewFrame never called without SurfaceView

On some devices, onPreviewFrame is not called if no SurfaceView was set to display the camera preview.
However, I handle the camera in a service, so I can't set a SurfaceView but I don't want to have visible preview anyway.
How can this be done? Can I programmatically create a SurfaceView and set it with Camera::setPreviewDisplay?
This must be possible or not?
It works on almost every phone without a SurfaceView but not on HTC One X and Google Nexus One...
According to this question, creating a SurfaceView in code works fine. Though I don't think you can create it through a service.
Another approach is to create a 1px-1px SurfaceView inside a RelativeLayout and hiding it with some other view on top of it. (visibility should still be VISIBLE). We use this trick for Path camera UI where we render preview buffers through OpenGL and it works fine.
According to documentation readily configured, visible and displayed surface view is necessary to activate camera preview. It may be overlayued though
From API 11 on, you can use a SurfaceTexture instead of a SurfaceView to get frames from the camera. Then, instead of using Camera.setPreviewDisplay, simply use Camera.setPreviewTexture.
This answer as well as this one discuss this point.

Categories

Resources