Showing posts with label camera. Show all posts
Showing posts with label camera. Show all posts

Monday, May 28, 2018

How to send audio API HIKVISION for two-way-audio?

Leave a Comment

I need help to understand why when sending audio to the camera you hear ugly, very fast. The camera is configured audio codec G711Ulaw

The process I am doing is the following:

  • I download a wav audio and converted to the codec that the camera is configured, these are all evidence conversions.

    ffmpeg -i padrino.wav -acodec pcm_mulaw -ar 8000 -ac 1 -b:a 32k output.wav   ffmpeg -i padrino.wav -acodec pcm_mulaw -ar 8000 -ac 2 -b:a 32000 output.wav   ffmpeg -i padrino.wav -f mulaw -acodec pcm_mulaw -ac 1 output.wav   ffmpeg -i padrino.wav -ar 8000 -ac 1 -ab 64k -f mulaw output.ulaw 
  • Turned on the two-way-audio, within the "data.xml" is the xml that enables two-way-audio:

    curl -H "application/xml" -X PUT -d @data.xml USER:PASS@IPCAM/ISAPI/System/...hannels/1/open 
  • I send through a curl

    curl -H "application/binary" -X PUT -d @output.ulaw USER:PASS@IPCAM/ISAPI/System/...ls/1/audioData 

    or

    curl -H "application/binary" -X PUT -d @output.wav USER:PASS@IPCAM/ISAPI/System/...ls/1/audioData 

This is heard in camera but as I explained at the beginning is heard wrong, I distorted, very fast. What am I doing wrong?

regards

1 Answers

Answers 1

I have found out why this is - its nothing to do with the encoding. I have written a C# app to test this and if you send the data at the rate expected (8000 samples per second) then it plays correctly.

I send the audio data in packets (160 bytes currently but experimenting with optimum values but does not seem to matter much as long as the delay is correct) and delay for the appropriate amount of time before sending again so that the correct amount of samples are sent in a second.

Read More

Tuesday, April 24, 2018

OpenCV Python: cv2.VideoCapture can only find 2 of 3 cameras, Windows Camera app finds all

Leave a Comment

I'm trying to create 3 real-time capture frames with webcams into a USB hub into my laptop. Using the "camera" app on Windows, I can change the camera source one at a time and confirm that all 3 webcams are working. However, my OpenCV Python code can only ever find two.

(Quick notes on the USB - it's a USB 3.0 hub, laptop port is USB 3, and I even have an active USB female-to-male cable going into the laptop, so given this and the Windows app working, I generally trust the hardware.)

Below I did some raw testing of cv2.VideoCapture(src) with the results below:

cams_test = 10 for i in range(0, cams_test):     cap = cv2.VideoCapture(i)     test, frame = cap.read()     print("i : "+str(i)+" /// result: "+str(test)) 

That first argument, test, returns True/False depending on if the frame can be read. Results:

i : 0 /// result: True i : 1 /// result: True i : 2 /// result: False i : 3 /// result: False i : 4 /// result: False i : 5 /// result: False i : 6 /// result: False i : 7 /// result: False i : 8 /// result: False i : 9 /// result: False 

As with other sample code I tested, only 2 webcams can be registered and show frames in Python. And the Windows 10 camera app lets me scroll between all 3 working and connected webcam feeds.

I know I can create multiple, like 3+, cv2.imshow() frames if I use the caps that work. My project involves doing this to show realtime USB webcam feeds on the laptop from multiple cameras.

Any help and advice appreciated; also potentially interested in (Python-based) alternative solutions. Cheers.

4 Answers

Answers 1

Do your webcams support USB3? Based on my practical experience with webcams and OpenCV, most common cameras only transmit on the USB2 standard, at 480 MBit/s. The exact details of how many cameras you can support on one USB channel depend on the resolution, framerate, and video compression technology. In my experience, with 1080p color video at 30 fps and H.264 encoding, only one camera stream fit onto a single USB controller.

An easy test to see if you are bandwidth limited would be to modify your program to explicitly close each stream after it is tested (cap.release()), so that your test program only opens one camera at a time, like the Windows camera app. If that works, then you may very well be looking at a bandwidth limitation.

When debugging video capture issues on Windows, it can also be useful to open the camera streams with VLC. VLC can enumerate all of the cameras available from DirectShow, which is the same API that OpenCV's VideoCapture uses by default. You can also start multiple VLC instances to attempt simultaneous streams.

If you click on "Advanced Options" and then check "Device Properties," VLC will show which settings (exposure, focus, etc...) can be tweaked through DirectShow. These settings are usually accessible in OpenCV through VideoCapture.set().

Answers 2

1) btw, just as a test, did you try to start loop (range) from -1 instead of 0?

2) about cv2... Well, is there any other instances/alternatives? maybe that third cam is binded to other instance instead of cv2 ?

3) If none of the method helps you, I advise to go to Device Manager and temporarily DISABLE the individual webcam and then run your script again and see what changes. After that ENABLE webcam and see what changed. ( in worst scenario, instead of ENABLE/DISABLE, you might insall/resintall the particular webcam and then windows might resolve them correctly).

Answers 3

having two video input devices does not automatically mean that their IDs are 0 and 10. Try to access the all cameras by increasing to about 500 or more instead of 10

cams_test = 500 for i in range(0, cams_test):     cap = cv2.VideoCapture(i)     test, frame = cap.read()     if test:         print("i : "+str(i)+" /// result: "+str(test)) 

I think you are only testing

Answers 4

First,we have to test your webcam can or cannot be connect to OPENCV.

connect only one webcam,and run your program with cv2.VideoCapture(0).Parameter 0 mean there is a single camera connected. if all your webcam is ok,then it will be problem of index,there is some code which will find the deviceID assigned to the cam.

and if some webcam unfortunately fail,then it will be hard.

In this case you have to create your own function that grabs using the SDK and write the image into a cv::Mat.

Read More

Friday, August 18, 2017

How to restrict the plugin to switch rear/back camera in android / cordova

Leave a Comment

I am using media-capture plugin of cordova to capture the video only from front camera. when it opens the camera, there is option to switch the back or rear camera, can anyone please guide, how to disable switching to back camera. I have done following modification in plugin and re added to app, but no luck.

intent.putExtra("android.intent.extras.LENS_FACING_BACK", 0); intent.putExtra("android.intent.extra.USE_BACK_CAMERA", false); 

1 Answers

Answers 1

Try this instead:

intent.putExtra("android.intent.extras.CAMERA_FACING", 1);


https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html

Read More

Wednesday, March 8, 2017

How do i check for low resolution photos when using cordova camera plugin?

Leave a Comment

I have the following code. It pretty much works for hte most part. I'd like to catch people with crappy cameras and some how warn them their pictures will stink. (using "cordova-plugin-camera" version 2.3.0)

           var cameraOpts = {                 quality: 100,                 // destinationType: Camera.DestinationType.FILE_URI,                 destinationType: Camera.DestinationType.DATA_URL,                 sourceType: $scope.sourceType,                 allowEdit: false,                 encodingType: Camera.EncodingType.JPEG,                 // popoverOptions: CameraPopoverOptions,                 targetWidth: 186,                 targetHeight: 1024,                 saveToPhotoAlbum: true,                 correctOrientation: true             };              $cordovaCamera.getPicture(cameraOpts).then(function(imageData) {                 var image = "data:image/jpeg;base64," + imageData;                 $scope.setUpImage(index,image);              }, function(err) {                 // error                 $scope.showAlert('Warning!', 'Camera cancelled!');             }); 

Any ideas would be appreciated. I'm looking for a way to catch low resolution photos, and message the user.

2 Answers

Answers 1

cordova camera plugin provide quality camera option but it does not provide any information about resolution(default is 100) (enter link description here)

Answers 2

You should create an Image object (this is standard HTML5 API)

Relevant snippet copied from this answer:

HTML5 - how to get image dimension

From plugin doc: "The image is passed to the success callback as a Base64-encoded String, or as the URI for the image file"

If you choose base64 format in the camera plugin, the data URI would be

'data:image/jpg;base64,' + imageData 

However, the plugin doc recommends the file format, which will return a file URL that you can assign directly to your image.src

var image = new Image();         image.onload = function(evt) {             var width = this.width;             var height = this.height;             alert (width); // will produce something like 198         };          //here is where you pass the camera data to create the image image.src = imageData;  

As you can see, the method is asynchronous, you can wrap it in a Promise or emit an event when the image has been loaded and you have the width x height

Read More

Saturday, March 4, 2017

Choose camera in file upload in cordova application on android without using cordova camera

Leave a Comment

So i made a cordova app, i added android platform and made a simple html with an imput field

<input type="file" capture="camera" accept="image/*" id="takePictureField"> 

I have added

<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <feature name="http://api.phonegap.com/1.0/camera" /> 

to the manifest file.

but when i press the button I cannot choose to take a new picture with the camera. are there any permission i miss, or anything else ??

I cannot use the cordova take picture functions, it has to be done in pure html.

3 Answers

Answers 1

An old question but I just faced this problem. It turns out that the simplest way to achieve what you want is include these cordova plugins in you app, even if you don't need to use them

cordova-plugin-camera cordova-plugin-media-capture cordova-plugin-device cordova-plugin-file cordova-plugin-media 

With these loaded I found this behaviour

Clicking on

<input type="file" /> 

Ask you to choose from camera, camcorder, microphone or documents

Clicking on

<input type="file" accept="image/*" /> 

Ask you to choose from camera or documents

Clicking on

<input type="file" accept="image/*" capture="capture" /> 

Immediatly start the camera.

Answers 2

After a bit of Googling, this is what I could conclude:

Media capture in mobile browsers still seems to have some issues. Check out this link. The excerpt says:

Actually, it seems that current implementations don’t rely on the capture attribute at all, but only on the type and accept attributes: the browser displays a dialog box in which the user can choose where the file has to be taken, and the capture attribute is not taken into consideration. For example, iOS Safari relies on the accept attribute (not capture) for images and videos (not audio). Even if you don’t use the accept attribute, the browser will let you choose between “Take Photo or Video” and “Choose Existing”

So looks like capture attribute does not make any impact.

Also, suggest you look at this SO post for more info on making this work. Hope it helps. Cheers.

UPDATE: After downvoting, I dig further deep regarding the issue. Most of the searches resulted in no success as the optimum solution for this issue is to use Cordova camera plugin. Finally stumbled on this SO post which is exactly duplicate of this question. The user was able to resolve the issue (using crosswalk web view, though). The answer in that post is mentioned here already by @Fabio. But instead of adding the plugin just for including the permissions, you can make use of cordova-custom-plugin to add the required permissions.

Also as per @jcesarmobile's comment (who is a Cordova expert) in the post without crosswalk web view plugin, input type works fine only on iOS and not on Android. So using camera plugin is the only way to make it work without using crosswalk plugin.Hopefully, it helps.

UPDATE 2: After the updated question, I dug bit more deep for the resolution of this issue. But now I can assure that this issue is still not resolved for Android Webview. Looks like it is not a Cordova issue but issue with Chromium web view.

For detailed info, request you to please look at these issues in Apache Cordova Issue Tracker:

Both these issues are unresolved till date. So I m sure that for now, you cannot make it work on Android unless you use Cordova camera plugin. Hope you agree with me and accept the resolution. Cheers

Answers 3

Here one cool guy uses some new HTML tags to access the camera without phonegap functions and he has a code sample to share.

Read More

Saturday, February 11, 2017

How to write file into DCIM directory exactly where camera does?

Leave a Comment

Suppose I am writing an alternative Camera application and wish to write images exactly into the same place as Camera does and name them exactly in the same name Camera does.

How would I accomplish this?

How to know the location of camera files?

How to know current naming convention?

How to gain permissions to that directory?

Any of answer would be appreciated.

UPDATE

Okay, suppose it is not really camera alternative. Suppose I would like to write formats other than images, like audio, video, or something else.

UPDATE 2

Please explain, why the hell you are downvoting??

UPDATE 3

Time came to try all advices and I found they all incorrect. Just incredible how many legends walking here on Stackoverflow...

4 Answers

Answers 1

You cannot write exactly into the same folder as default camera app does. But you can make use of Environment.getExternalStoragePublicDirectory(Environment.DI‌​‌​RECTORY_DCIM)

mediaStorageDir = newFile(Environment.getExternalStorageDirectory(),FOLDER_NAME) Intent takePictureFromCameraIntent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE);   takePictureFromCameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(mediaStorageDir)); startActivityForResult(takePictureFromCameraIntent,100); 

But please note that this will create only a sub folder in DCIM directory and will not store exactly where default camera stores. But you can always create sub folders with any your required folder name.

`

Answers 2

Things to keep in mind for this answer:

  • Every phone producer creates it's own Camera App, tailored to their hardware.

  • With the right permissions, App's can write (almost) everywhere they want...

Now to your question(s):

First, we don't know where the photo's are stored, and what the naming convention is. Every one and their mother has a different idea about what is best. So no "Hey it's always there".

Those who seek will find: get read & write permissions for the whole device. With that search the whole device to find in what folders the images are in. Now subtract the folders that come from "social media". My guess would be that the folder with the most and or latest images is the one that you want. To be sure, you will need testers, that trust you.

All that are found were not unorganized: just find the pattern used. There may be a standard for this. The big companies will surely have one. You can ask the device what maker it has. Note, that that answer might not be correct.

Ain't that a picture, no, it's a photo: And then you get the fun part of accessing the camera. Good times. Remember: request picture => get location of picture in memory => save picture as file. Best part, there is no enforcement of all parts of this API, so different devices need different instructions...

Have fun & Good luck!

ps, the downvotes are probably for the lack of code

Answers 3

How would I accomplish this?

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + "You Dir. Name"; 

if you append any string to end this

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)

it will create dir inside the folder

How to know the location of camera files?

By default camera uses this location

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)

How to know current naming convention?

IMG_yyyyMMDD_timeStamp

How to gain permissions to that directory?

Using permission manager for Camera and External Storage permissions

Answers 4

Try using this code you can save the image bitmap to the directory using insert query

String imgSaved = MediaStore.Images.Media.insertImage(                 getContentResolver(), bitmap,                 System.currentTimeMillis() + ".jpg", "DESCRIPTION HERE"); 

For more details see the link

Read More

Monday, September 26, 2016

Camera and video control with HTML5 form android webview

Leave a Comment

I use this guide : Camera and video control with HTML5

This example work excellent on Google Chrome but i can not make it work on Android webview. I also use permission : android.permission.CAMERA.

1 Answers

Answers 1

Did you remember to add this to your onCreate

WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true); webSettings.setAllowFileAccessFromFileURLs(true); webSettings.setAllowUniversalAccessFromFileURLs(true); 

You are probably missing the last two lines in your code.

Here is a working example

Read More

Monday, April 25, 2016

Bug recording videos android

Leave a Comment

I'm trying to reocord many videos of 30 seconds in background but, after 20 or 30 videos my service wich is stoping and launching the process to record go slowly.

I have try with a service in the same process and the problem was the same.

My video handler:

@Override public void onCreate() {     super.onCreate();     isRunning = true;     idAlerta = Common.getStorage().getString(Constants.ID_ALERTA_SERVICE, "");     videoCount = 1;     mIntentRecorder = new Intent(VideoHandlerService.this, RecorderService.class);     mIntentSend = new Intent(VideoHandlerService.this, SendVideoService.class);     updateVideoTime();     mIntentRecorder.putExtra(Constants.VIDEO_TIME, videoTime);     mIntentRecorder.putExtra(Constants.ID_ALERTA_SERVICE, idAlerta);     mIntentRecorder.putExtra(Constants.COUNT_ALERTA, videoCount);     startService(mIntentRecorder);     newVideo(); } public void newVideo() {     Common.log("new Video");     new Handler().postDelayed(new Runnable() {         @Override         public void run() {             videoCount++;             startNewVideo();             if (videoCount == 2)                 sendVideo(4000);         }     }, videoTime + 2000);  }   public void startNewVideo() {     final Intent intentRecorder = new Intent(VideoHandlerService.this, RecorderService.class);     intentRecorder.putExtra(Constants.VIDEO_TIME, videoTime);     Common.log("idAlerta " + idAlerta);     intentRecorder.putExtra(Constants.ID_ALERTA_SERVICE, idAlerta);     intentRecorder.putExtra(Constants.COUNT_ALERTA, videoCount);     stopService(intentRecorder);     if (Common.getStorage().getBoolean(Constants.RECORDER_ACTIVE, false)) {         if (Common.getStorage().getString(Constants.ID_ALERTA_SERVICE, "") != null && Common.getStorage().getString(Constants.ID_ALERTA_SERVICE, "").length() > 0) {              new Handler().postDelayed(new Runnable() {                 @Override                 public void run() {                     Common.log("Start service recorder");                     startService(intentRecorder);                     newVideo();                 }             }, 5000);         }     } else         new Handler().postDelayed(new Runnable() {             @Override             public void run() {                 startNewVideo();             }         }, 5000); } 

And this is the process to record:

@Override public int onStartCommand(Intent intent, int flags, int startId) {     Common.log("onStartCommand");     if (intent != null && ((Common.getStorage().getString(Constants.ID_ALERTA_SERVICE, "") != null && Common.getStorage().getString(Constants.ID_ALERTA_SERVICE, "").length() > 0))) {         windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);         mLayoutParams = new WindowManager.LayoutParams(                 1, 1,                 WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,                 WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,                 PixelFormat.TRANSLUCENT         );         mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;         //Cojo Información del videohandler         Common.log("Intent distinto de null");         mVideoTime = intent.getIntExtra(Constants.VIDEO_TIME, 15000);         mIdAlerta = intent.getStringExtra(Constants.ID_ALERTA_SERVICE);         mVideoCount = intent.getIntExtra(Constants.COUNT_ALERTA, 1);         Common.log("Video time" + mVideoTime);         Common.getStorage().putBoolean(Constants.RECORDER_ACTIVE, true);         initRecording();     }     return START_NOT_STICKY; }  public void initRecording() {     Common.log("INIT RECORDING IN");     surfaceView = new SurfaceView(this);     windowManager.addView(surfaceView, mLayoutParams);     surfaceView.getHolder().addCallback(this);     Common.log("INIT RECORDING OUT"); }  @Nullable @Override public IBinder onBind(Intent intent) {     return null; }   @Override public void onDestroy() {     Common.log("onDestroy Video");     PreferenceHelper preferenceHelper = PreferenceHelper.newInstance(RecorderService.this, Constants.USER_PREFERENCES);     preferenceHelper.setBoolean(Constants.IS_RECORDING, false);     try {         camera.setPreviewCallback(null);     } catch (Exception e){         Common.log("error setPrevieCallback" + (e.getMessage() != null ? e.getMessage() : "sin mensaje"));     }      try {         muteSounds(false);     } catch (Exception e) {         Common.log(e.getMessage());     }     try {         Common.log("media recorder stop");         mediaRecorder.stop();         Common.log("media recorder reset");         mediaRecorder.reset();         Common.log("media recorder release");         mediaRecorder.release();         Common.log("media camera lock");         camera.lock();         Common.log("media camera release");         camera.release();     } catch (Exception e) {      }      Common.log("onDestroy Video");     Common.getStorage().putBoolean(Constants.RECORDER_ACTIVE, false);     RecorderService.super.onDestroy();     System.exit(0); }   @Override public void surfaceCreated(SurfaceHolder holder) {     mSurfaceHolder = holder;     Common.log("SurfaceCreated");     try {         try {             muteSounds(true);         } catch (Exception e) {             Common.log(e.getMessage());         }         Common.log("CAMERA OPEN 1");         try {             camera = Camera.open(1);         } catch (RuntimeException e) {             Common.log(e.getMessage());         }         Common.log("CAMERA OPEN 2");          ///////////////////////////         mCamCoderProfile = CamcorderProfile.get(1, CamcorderProfile.QUALITY_LOW);         mCamCoderProfile.videoCodec = MediaRecorder.VideoEncoder.MPEG_4_SP;         mCamCoderProfile.audioCodec = MediaRecorder.AudioEncoder.AAC;         ///////////////////////////          startRecorder();      } catch (Exception e) {         if (e.getMessage() != null)             Common.log(e.getMessage());     } }   public void muteSounds(boolean mute) {     Common.log("MUTE SOUNDS IN");     AudioManager mgr = ((AudioManager) getSystemService(Context.AUDIO_SERVICE));     mgr.setStreamMute(AudioManager.STREAM_SYSTEM, true);     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {         if (mute) {             mgr.adjustStreamVolume(AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_MUTE, 0);             mgr.adjustVolume(AudioManager.ADJUST_MUTE, 0);             mgr.adjustVolume(AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE, 0);         } else {             mgr.adjustStreamVolume(AudioManager.STREAM_SYSTEM, AudioManager.ADJUST_UNMUTE, 0);             mgr.adjustVolume(AudioManager.ADJUST_UNMUTE, 0);         }     } else {         mgr.setStreamMute(AudioManager.STREAM_SYSTEM, mute);         mgr.setStreamMute(AudioManager.STREAM_MUSIC, mute);         if (mute) {             mOlderVolumen = mgr.getStreamVolume(AudioManager.STREAM_RING);             mgr.setStreamVolume(AudioManager.STREAM_RING, 0, 0);         } else             mgr.setStreamVolume(AudioManager.STREAM_RING, mOlderVolumen, 0);          mgr.adjustVolume(AudioManager.ADJUST_LOWER, 0);     }     Common.log("MUTE SOUNDS OUT"); }   public void startRecorder() {     mediaRecorder = new MediaRecorder();     camera.unlock();     mediaRecorder.setCamera(camera);     mediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());     mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);     mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);     mediaRecorder.setProfile(mCamCoderProfile);     videoFile = new File(Environment.getExternalStorageDirectory() + "/" +             "wbunker_" + mIdAlerta + "_" + mVideoCount + ".mp4");     Common.log("Video rercorder name file " + videoRecording);     mediaRecorder.setOutputFile(videoFile.getPath());     mediaRecorder.setOrientationHint(270);     try {         Common.log("mediaRecorder prepare");         mediaRecorder.prepare();         Common.log("mediaRecorder prepare");     } catch (Exception e) {     }     Common.log("mediaRecorder start");     mediaRecorder.start();     Common.log("mediaRecorder start");     Common.log("Estoy grabando macho"); } 

When I try to stop the service the services stops, but the camera isn't released even killing the app. Can someone help me?? thanks in advance.

1 Answers

Answers 1

In the onDestroy() method of your service replace the camera.lock() with camera.unLock() and in the startRecorder() method replace the camera.unLock() with camera.lock()

Read More

Friday, March 25, 2016

How to configure AVCaptureSession for high res still images and low res (video) preview?

Leave a Comment

I'd like to capture high resolution still images using AVCaptureSession. Therefore AVCaptureSession preset is set to Photo.

This is working well so far. On an iPhone 4 the final still image resolution is at its maximum of 2448x3264 pixels and the preview (video) resolution is 852x640 pixels.

Now, because the preview frames are analyzed to detect objects in the scene, I'd like to lower their resolution. How can this be done? I've tried to set AVVideoSettings with a lower width/height to AVCaptureVideoDataOutput, but this leads to the following error message:

AVCaptureVideoDataOutput setVideoSettings:] - videoSettings dictionary contains one or more unsupported (ignored) keys: (AVVideoHeightKey, AVVideoWidthKey 

So it seems this is not the right approach to configure the size of the preview frames received by AVCaptureVideoDataOutput / AVCaptureVideoDataOutputSampleBufferDelegate. Do you have any ideas how the resolution of the preview frames can be configured?

Any advise is welcome, Thank you.

2 Answers

Answers 1

If you want to specify the settings manually, you need to set activeFormat on the AVCaptureDevice. This will be implicitly set the session preset to AVCaptureSessionPresetInputPriority.

The activeFormat takes a AVCaptureDeviceFormat but you can only take one from the list of AVCaptureDevice.formats. You'll need to go through the list and find one that fits your needs. Specifically, check that highResolutionStillImageDimensions is high enough for desired still capture and formatDescription (which needs to be inspected with CMFormatDescription* functions, e.g., CMVideoFormatDescriptionGetDimensions) matches your desired preview settings.

Answers 2

To lower the size of the output of AVCaptureVideoDataOutput you can set the bitrate to be lower thus producing a small sample size.

commonly used keys for AVCaptureVideoDataOutput are:

AVVideoAverageBitRateKey AVVideoProfileLevelKey AVVideoExpectedSourceFrameRateKey AVVideoMaxKeyFrameIntervalKey 

For example:

private static let videoCompressionOptionsMedium = [AVVideoAverageBitRateKey : 1750000,                                                     AVVideoProfileLevelKey : AVVideoProfileLevelH264BaselineAutoLevel,                                                     AVVideoExpectedSourceFrameRateKey : Int(30),                                                     AVVideoMaxKeyFrameIntervalKey : Int(30)] 
Read More

Tuesday, March 8, 2016

Camera not overriding old image if orientation changes

Leave a Comment

I have a RecyclerView adapter with many different ViewHolders. One of the ViewHolders contains an ImageView, which needs to be able to take a picture, resize it, then display it. For modularity, I want the ViewHolder to be self-contained: it and not the parent activity should handle everything concerning the photo taking and displaying process. Also the file path is constant (it will never change). In fact, it is /storage/emulated/0/com.company.app/myst/cat.jpg. As a result, here is my implementation of the ImageView’s onClick method.

@Override public void onClick(View v) {     final FragmentManager fm = ((MyActivity) getContext()).getSupportFragmentManager();     Fragment auxiliary = new Fragment() {         @Override         public void onActivityResult(int requestCode, int resultCode, Intent data) {             resizeResaveAndDisplayPhoto();             super.onActivityResult(requestCode, resultCode, data);             fm.beginTransaction().remove(this).commit();         }     };     fm.beginTransaction().add(auxiliary, "FRAGMENT_TAG").commit();     fm.executePendingTransactions();      Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);     if (null != takePictureIntent.resolveActivity(view.getContext().getPackageManager())) {         ((MyActivity)view.getContext()).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);         takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));          auxFragment.startActivityForResult(takePictureIntent, Constants.REQUEST_CODE_PHOTO);     } } 

When resizeResaveAndDisplayPhoto is called it executes the following AsyncTask

public static class ResizeThenLoadImageTask extends AsyncTask<String, Void, Bitmap> {      private final WeakReference<ImageView> imageViewWeakReference;     private final WeakReference<File> fileWeakReference;     private final WeakReference<Context> weakContext;     private final int reqHeight;     private final int reqWidth;      public ResizeThenLoadImageTask(Context context, ImageView imageView, File file, int reqHeight, int reqWidth) {         weakContext = new WeakReference<Context>(context);         imageViewWeakReference = new WeakReference<>(imageView);         fileWeakReference = new WeakReference(file);         this.reqHeight = reqHeight;         this.reqWidth = reqWidth;     }      @Override     public Bitmap doInBackground(String... params) {         File file = fileWeakReference.get();         Bitmap bitmap = null;         if (null != file) {             bitmap = ImageUtils.reduceImageSize(file, reqHeight, reqWidth);             ImageUtils.saveBitmapToGivenFile(bitmap, file);         }         return bitmap;     }      @Override     public void onPostExecute(Bitmap bitmap) {         if (null != imageViewWeakReference && null != fileWeakReference) {             ImageView imageView = imageViewWeakReference.get();             File file = fileWeakReference.get();             if (null != imageView) {                 if (null != bitmap) {                     imageView.setImageBitmap(bitmap);                 }                 else {                     imageView.setImageResource(R.drawable.photo);                 }                 imageView.postDelayed(new Runnable() {                     @Override                     public void run() {                         if (null != weakContext.get()) {                             ((MyActivity) weakContext.get()).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);                         }                     }                 }, 10000);             }         }     } } 

You may notice that I lock the orientation before taking the photo and unlock it 10 seconds after displaying the photo. That trick is part of my troubleshooting. So here is the situation. The system described above works very well. Problems happen in the following case

  • Say I already have a photo in the ImageView but want to replace it.
  • So I click on the ImageView to take a new photo.
  • If I rotate the device to take the new photo, then when I return the new photo displays briefly before the old photo returns.
  • So I lock to orientation to see what was happening. Here is what I found.
  • The new photo displays for as long as I lock the orientation. As soon as the orientation unlocks (10 sec), the old photo returns.
  • If I leave the activity and the returns, the old photo is still displaying.
  • If I close the app completely and then return, then I see the new photo.

1 Answers

Answers 1

When the device is rotated, the running activity is recreated as well the asyncTask attached to it, probably causing a leak.

You probably need to call the asyncTask inside of a service instead in an activity so the asyncTask is going to be attached to the life cycle of the service.

Read More