The screen flickers and changes when the video starts.

I integrate photo / video in my application and I have a problem with video capture. When the video starts, the screen flickers, I get a short pause, then the video capture starts. However, using the phoneโ€™s camera app, thereโ€™s no flicker / pause at all.

In addition, my camera preview screen changes as soon as recorder.start() called. I do not understand why this is so. This makes the preview distorted (everything looks wider and wider).

My questions: How to prevent flicker / pause when starting video recording? How to prevent recorder.start() from resizing the preview screen?

Whenever "video mode" is activated, initRecording() is called immediately. As soon as the user clicks the button, startRecording() called. Finally, when the button is pressed again, stopRecording() called. Less important, when you switch to "image mode", destroyRecorder() called.

 @Override public void onResume() { super.onResume(); Camera camera = null; try { camera = Camera.open(); } catch (Exception e) { // Camera isn't available Toast.makeText( getActivity(), "Camera is not available at this time.", Toast.LENGTH_SHORT ).show(); getActivity().finish(); return; } if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD ) { setCameraDisplayOrientation( camera ); } else { camera.setDisplayOrientation( 90 ); } setCamera( camera ); setCameraZoomDisplay( camera ); if ( getSurfaceHolder() != null ) { startPreview(); if ( getMode() == MODE_VIDEO ) { initRecording(); } } } private void setCameraDisplayOrientation( Camera camera ) { CameraInfo info = new CameraInfo(); Camera.getCameraInfo( 0, info ); int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result = ( info.orientation - degrees + 360 ) % 360; camera.setDisplayOrientation( result ); } private void initRecording() { MediaRecorder recorder = new MediaRecorder(); setRecorder( recorder ); Camera camera = getCamera(); camera.unlock(); recorder.setCamera( camera ); recorder.setAudioSource( MediaRecorder.AudioSource.MIC ); recorder.setVideoSource( MediaRecorder.VideoSource.CAMERA ); CamcorderProfile cp = CamcorderProfile.get( CamcorderProfile.QUALITY_HIGH ); recorder.setProfile( cp ); String extension; switch (cp.fileFormat) { case MediaRecorder.OutputFormat.MPEG_4: extension = "mp4"; break; case MediaRecorder.OutputFormat.THREE_GPP: extension = "3gp"; break; default: extension = "tmp"; } setVideoMimeType( MimeTypeMap.getSingleton().getMimeTypeFromExtension( extension ) ); File toFile = new File( getActivity().getCacheDir(), "tempvideo.tmp" ); if ( toFile.exists() ) { toFile.delete(); } setTempFile( toFile ); recorder.setOutputFile( toFile.getPath() ); recorder.setPreviewDisplay( getSurfaceHolder().getSurface() ); try { recorder.prepare(); setRecorderInitialized( true ); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private boolean startRecording() { try { getRecorder().start(); setRecording( true ); ImageView actionImageView = getActionImageView(); actionImageView.setImageResource( R.drawable.record_red ); } catch (Exception e) { getCamera().lock(); } return true; } private void stopRecording() { MediaRecorder recorder = getRecorder(); if ( recorder != null && isRecording() ) { recorder.stop(); setRecording( false ); setRecorderInitialized( false ); try { insertVideo(); } catch (IOException e) { e.printStackTrace(); } initRecording(); ImageView actionImageView = getActionImageView(); actionImageView.setImageResource( R.drawable.record_green ); } } private void destroyRecorder() { MediaRecorder recorder = getRecorder(); recorder.release(); setRecorder( null ); getCamera().lock(); } 
+4
source share
1 answer

The reason for the small scaling when calling MediaRecorder.start () is to change the size of the camera preview in accordance with the resolution of the recorded video. This problem can be fixed by setting the preview and video recovery during setup. I think I also found a way to stop the flicker, although I found that when working with Camera and MediaRecorder, a little lag or flicker can come from any of several places, so it can be a bit harder to track. The documentation for Android on setting up the camera / VCR is a good place to start, so that the main parts are set up correctly, but I found that you need to delve into some of the api class documentation for debugging and make the work really smooth.

The Camera.Parameters class is the key to maintaining smooth video recording. When you have a Camera object, you can use Camera.getParameters() to get the current parameters to change them. Camera.setParameters(Camera.Parameters) can then be used to trigger any changes that have been made.

To prevent video resizing, we need to make sure that the size of the parameter preview matches the recorded video resolution. To get a list of supported video / preview sizes, we can use Camera.Parameters.getSupportedPreviewSizes() in our current Parameters object, which will return a list of Camera.Size objects. Each of these objects will have the width and height property, accessed directly through Camera.Size.width and Camera.Size.height (without getter methods). The getSupportedPreviewSizes() method guarantees the return of at least one result , and it seems that the results are ordered from the highest resolution to the lowest.

(For API level> 11, there is also a getSupportedVideoSizes() method, but it seems that only if the device has some video sizes that differ from the preview sizes, otherwise it returns null. I have not had success with this method, so I will stick with using PreviewSizes for now, as it guarantees returning a size suitable for both video and preview, but this is what you need to know about promotion.)

Once we have Camera.Size that matches the desired video resolution, we can set this size using Camera.Parameters.setPreviewSize(width, height). Also, to help flicker, I use Camera.Parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO). . These steps are performed, use Camera.setParameters() to notify the camera of your changes. I had success setting these parameters immediately after receiving the camera, since the settings when the user interacts with this action caused some lag. If you use the same operation to capture video and images, you can also set image parameters here, the camera object will process using the appropriate parameters for each mode.

Almost done! Now that the preview has taken care, all that remains is to make sure that MediaRecorder uses the same resolution as the preview. When preparing a media recorder between calls to MediaRecorder.setProfile() (or setting encoders, for API level <8) and MediaRecorder.setOutputFile() place the call on MediaRecorder.setVideoSize(width, height) using the same values โ€‹โ€‹as your preview. Now the transition from preview to recording using MediaRecorder.start() should be seamless, as they both use the same resolution.

Here are some quick snippets of code so you can see everything in action:

Getting and setting parameters:

 Camera.Parameters params = camera.getParameters(); params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); //myVideoSize is an instance of Camera.Size List<Camera.Size> previewSizes = params.getSupportedPreviewSizes(); myVideoSize = previewSizes.get(0); params.setPreviewSize(myVideoSize.width, myVideoSize.height); camera.setParameters(params); 

Then set the size on the media recorder:

 //After setting the profile.... mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); //Use myVideoSize from above mediaRecorder.setVideoSize(myVideoSize.width, myVideoSize.height); //Before setting the output file mediaRecorder.setOutputFile(myFile); 
+7
source

Source: https://habr.com/ru/post/1411432/


All Articles