Hi,

For the focus / fuzzy issue try initiating auto focusing of the camera 
before you start recording your video -

http://developer.android.com/reference/android/hardware/Camera.html#autoFocus(android.hardware.Camera.AutoFocusCallback)

- you can also do this whilst the video is recording as well, although you 
will have periods of a few seconds where focus is lost before being 
regained.

Note sure about upside down video, I suspect this not the video recording 
but perhaps some Camera Preview rotation mismatch / issue in your 
CameraPreview class ? Compare the Camera Preview orientation in your app vs 
when you use the default Camera App. (NOTE also that Nexus 5X has some 
wrong camera preview orientation issues...)

Regards



On Wednesday, March 23, 2016 at 3:41:02 PM UTC+11, David Karr wrote:
>
> I've assembled a relatively small camcorder app. It only does what I need 
> it to do.  I assembled it from sample code, and some people on this forum 
> have helped me fix some of the problems with it, although some of the 
> details of interfacing with the camera are beyond me.
>
> After some usage of it, I've realized there are two problems with it:
>
> * Although the preview display is right-side up, the resulting stored 
> video is upside down.  This isn't a huge deal, as I later process this with 
> another app that lets me rotate it till its right-side up, but it's still 
> an annoyance, especially when previewing many videos to see which ones I 
> want to use.
>
> * The video it produces is just fuzzy, or out of focus.  I don't know 
> whether this is the nature of video vs. still images or whether I'm not 
> doing something I should be doing.  Is there some autofocus feature of the 
> camcorder that I'm not taking advantage of?
>
> I'd appreciate any useful advice on this.
>
> I'll provide here the entire Activity class.
>
> package com.integralsoftware.videograbber;
>
> import android.content.Intent;
> import android.media.AudioFormat;
> import android.media.AudioManager;
> import android.media.AudioTrack;
> import android.media.MediaScannerConnection;
> import android.net.Uri;
> import android.os.Bundle;
> import android.os.Environment;
> import android.util.Log;
> import android.view.View;
>
> import java.io.File;
> import java.io.IOException;
> import java.text.SimpleDateFormat;
> import java.util.Date;
>
> import android.app.Activity;
> import android.content.Context;
> import android.content.pm.PackageManager;
> import android.hardware.Camera;
> import android.hardware.Camera.CameraInfo;
> import android.media.MediaRecorder;
> import android.view.View.OnClickListener;
> import android.view.WindowManager;
> import android.view.animation.AlphaAnimation;
> import android.view.animation.Animation;
> import android.widget.Button;
> import android.widget.LinearLayout;
> import android.widget.TextView;
> import android.widget.Toast;
>
> public class VideoGrabberActivity extends Activity {
>     private Camera          mCamera;
>     private CameraPreview   mPreview;
>     private MediaRecorder   mediaRecorder;
>     private Button          capture;
>     private Context         myContext;
>     private LinearLayout    cameraPreview;
>     private TextView        countdownText;
>     private String          outputFilePath;
>     private SimpleDateFormat    simpleDateFormat    = new SimpleDateFormat
> ("yyyyMMdd_HHmmss");
>
>     private static final String VG  = "VideoGrabber";
>
>     private static final int    RS_WAITING      = 0;
>     private static final int    RS_COUNTING     = 1;
>     private static final int    RS_RECORDING    = 2;
>
>     private int recordingState  = RS_WAITING;
>
>     @Override
>     public void onCreate(Bundle savedInstanceState) {
>         super.onCreate(savedInstanceState);
>         setContentView(R.layout.activity_video_grabber);
>         getWindow().addFlags(WindowManager.LayoutParams.
> FLAG_KEEP_SCREEN_ON);
>         countdownText   = (TextView) findViewById(R.id.countdown_text);
>         myContext = this;
>         initialize();
>     }
>
>
>     private int findBackFacingCamera() {
>         int cameraId = -1;
>         int numberOfCameras = Camera.getNumberOfCameras();
>         for (int i = 0; i < numberOfCameras; i++) {
>             CameraInfo info = new CameraInfo();
>             Camera.getCameraInfo(i, info);
>             if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
>                 cameraId = i;
>                 break;
>             }
>         }
>         return cameraId;
>     }
>
>     public void onResume() {
>         super.onResume();
>         if (!hasCamera(myContext)) {
>             Toast toast = Toast.makeText(myContext, "Sorry, your phone 
> does not have a camera!", Toast.LENGTH_LONG);
>             toast.show();
>             finish();
>         }
>         if (mCamera == null) {
>             mCamera = Camera.open(findBackFacingCamera());
>             mPreview.refreshCamera(mCamera);
>             setRecordingState(RS_WAITING);
>         }
>     }
>
>     private void setRecordingState(int recordingState) {
>         if (recordingState == RS_WAITING)
>             capture.setText(getString(R.string.button_waiting));
>         else if (recordingState == RS_COUNTING)
>             capture.setText(getString(R.string.button_countdown));
>         else if (recordingState == RS_RECORDING)
>             capture.setText(getString(R.string.button_recording));
>         this.countdownText.setText("");
>         this.recordingState = recordingState;
>     }
>
>     public void initialize() {
>         cameraPreview = (LinearLayout) findViewById(R.id.camera_preview);
>
>         mPreview = new CameraPreview(myContext, mCamera);
>         cameraPreview.addView(mPreview);
>
>         capture = (Button) findViewById(R.id.button_capture);
>         capture.setOnClickListener(captureListener);
>
>     }
>
>
>
>     @Override
>     protected void onPause() {
>         super.onPause();
>         releaseCamera();
>     }
>
>     private boolean hasCamera(Context context) {
>         if (context.getPackageManager().hasSystemFeature(PackageManager.
> FEATURE_CAMERA)) {
>             return true;
>         } else {
>             return false;
>         }
>     }
>
>     OnClickListener captureListener = new OnClickListener() {
>         @Override
>         public void onClick(View v) {
>             if (recordingState == RS_COUNTING)
>                 setRecordingState(RS_WAITING);
>             else if (recordingState == RS_RECORDING) {
>                 mediaRecorder.stop(); // stop the recording
>                 releaseMediaRecorder(); // release the MediaRecorder 
> object
>                 Toast.makeText(VideoGrabberActivity.this, "Video captured 
> at " + outputFilePath, Toast.LENGTH_LONG).show();
>
>                 MediaScannerConnection.scanFile(getApplicationContext(), 
> new String[]{outputFilePath}, new String[]{"video/mp4"}, new 
> MediaScannerConnection.OnScanCompletedListener() {
>                     @Override
>                     public void onScanCompleted(String path, Uri uri) {
>                         Log.i(VG, "path[" + path + "] uri[" + uri + "] 
> urifrompath[" + Uri.fromFile(new File(path)) + "]");
>                     }
>                 });
>                 setRecordingState(RS_WAITING);
>             } else {
>                 setRecordingState(RS_COUNTING);
>                 countDown(countdownText, 10, new Runnable() { public void 
> run() { startRecording(); } });
>             }
>         }
>     };
>
>     private void startRecording() {
>         if (!prepareMediaRecorder()) {
>             Toast.makeText(VideoGrabberActivity.this, "Fail in 
> prepareMediaRecorder()!\n - Ended -", Toast.LENGTH_LONG).show();
>             finish();
>             recordingState  = RS_WAITING;
>         }
>         runOnUiThread(new Runnable() {
>             public void run() {
>
>                 try {
>                     mediaRecorder.start();
>                     setRecordingState(RS_RECORDING);
>                 } catch (final Exception ex) {
>                     setRecordingState(RS_WAITING);
>                     Log.e(VG, "Failed to start MediaRecorder", ex);
>                 }
>             }
>         });
>
>     }
>
>     private void releaseMediaRecorder() {
>         if (mediaRecorder != null) {
>             mediaRecorder.reset(); // clear recorder configuration
>             mediaRecorder.release(); // release the recorder object
>             mediaRecorder = null;
>             if (mCamera != null) {
>                 mCamera.lock(); // lock camera for later use
>             }
>         }
>     }
>
>     private boolean prepareMediaRecorder() {
>
>         mediaRecorder = new MediaRecorder();
>
>         mCamera.unlock();
>         mediaRecorder.setCamera(mCamera);
>
>         mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
>         mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
>
>
>         String  outputDir   = Environment.
> getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + 
> File.separator 
> + VG;
>         new File(outputDir).mkdirs();
>
>         outputFilePath  = outputDir + File.separator + simpleDateFormat.
> format(new Date()) + ".mp4";
>
>         mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
>         mediaRecorder.setOutputFile(outputFilePath);
>         mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
>         mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
>         mediaRecorder.setMaxDuration(600000); // Set max duration 60 sec.
>         mediaRecorder.setMaxFileSize(50000000); // Set max file size 50M
>
>         try {
>             mediaRecorder.prepare();
>         } catch (IllegalStateException ex) {
>             Log.e(VG, "Failed to prepare MediaRecorder", ex);
>             releaseMediaRecorder();
>             return false;
>         } catch (IOException ex) {
>             Log.e(VG, "Failed to prepare MediaRecorder", ex);
>             releaseMediaRecorder();
>             return false;
>         }
>         return true;
>     }
>
>     private void releaseCamera() {
>         if (mCamera != null) {
>             mCamera.release();
>             mCamera = null;
>         }
>     }
>
>     private void countDown(final TextView tv, final int count, final 
> Runnable callback) {
>         if (recordingState != RS_COUNTING)
>             return;
>
>         if (count == 0) {
>             tv.setText(""); // Note: the TextView will be visible again 
> here.
>             if (callback != null)
>                 callback.run();
>             return;
>         }
>
>         tv.setText(String.valueOf(count));
>
>         if (count < 3)
>             playTone(1600, 400, 0.7f);
>         else
>             playTone(1500, 400, 0.5f);
>
>         AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);
>         animation.setDuration(1000);
>         animation.setAnimationListener(new Animation.AnimationListener() {
>             @Override
>             public void onAnimationStart(Animation animation) { }
>
>             @Override
>             public void onAnimationEnd(Animation anim) {
>                 countDown(tv, count - 1, callback);
>             }
>
>             @Override
>             public void onAnimationRepeat(Animation animation) { }
>         });
>         tv.startAnimation(animation);
>     }
>
>     private void playTone(final int frequency, final int duration, final 
> float volume) {
>         new Thread(new Runnable() {
>             @Override
>             public void run() {
>                 try {
>                     int     sampleRate  = 8000;
>                     int     amplitude   = 32000;
>                     double  twoPI       = Math.PI * 2.0;
>                     int     sampleSize  = (sampleRate / 1000) * (int) 
> duration;
>                     short   samples[]   = new short[sampleSize];
>                     double  phase       = 0.0;
>
>                     for (int ctr = 0; ctr < sampleSize; ctr++) {
>                         phase           += twoPI * frequency / sampleRate;
>                         samples[ctr]    = (short) (amplitude * Math.sin(
> phase));
>                     }
>
>                     final AudioTrack    audioTrack  =
>                             new AudioTrack(AudioManager.STREAM_MUSIC, 
> sampleRate, AudioFormat.CHANNEL_OUT_MONO,
>                                            AudioFormat.ENCODING_PCM_16BIT, 
> sampleSize * 2, AudioTrack.MODE_STATIC);
>
>                     audioTrack.write(samples, 0, sampleSize);
>
>                     audioTrack.setStereoVolume(volume, volume);
>
>                     audioTrack.play();
>
>                     try {
>                         Thread.sleep(duration);
>                     } catch (Exception ex) {
>                     }
>
>                     audioTrack.setStereoVolume(0, 0);
>
>                     audioTrack.stop();
>
>                     audioTrack.release();
>                 }
>                 catch (IllegalArgumentException ex) {
>                     Log.e(VG, "Failed AudioTrack", ex);
>                 }
>             }
>         }).start();
>     }
>
>     public static class SingleMediaScanner implements 
> MediaScannerConnection.MediaScannerConnectionClient {
>
>         private MediaScannerConnection mMs;
>         private File mFile;
>
>         public SingleMediaScanner(Context context, File f) {
>             mFile = f;
>             mMs = new MediaScannerConnection(context, this);
>             mMs.connect();
>         }
>
>         @Override
>         public void onMediaScannerConnected() {
>             mMs.scanFile(mFile.getAbsolutePath(), "image/*");
>         }
>
>         @Override
>         public void onScanCompleted(String path, Uri uri) {
>             mMs.disconnect();
>         }
>     }
> }
>
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Android Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to android-developers+unsubscr...@googlegroups.com.
To post to this group, send email to android-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/android-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/android-developers/b299f790-e2ed-4046-93fc-c8fabacd45b5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to