Android: видео растягивается во время предварительного просмотра, но не во время записи (на некоторых устройствах)

Вопрос:Я создал активность в Android-видео, и я не могу за всю жизнь понять, почему мое предварительное видео растянуто горизонтально. У меня есть жестко закодированные значения (только для целей отладки), и это все еще неверно. Он выглядит нормально, когда я нажимаю запись, но он возвращается к растягиванию во время предварительного просмотра. Если я вручную установил соотношение

Вопрос:

Я создал активность в Android-видео, и я не могу за всю жизнь понять, почему мое предварительное видео растянуто горизонтально. У меня есть жестко закодированные значения (только для целей отладки), и это все еще неверно. Он выглядит нормально, когда я нажимаю запись, но он возвращается к растягиванию во время предварительного просмотра.

Если я вручную установил соотношение сторон к чему-то меньшему (зависит от устройства, но я не вижу никакой логической корреляции), он работает. Например, на SIII, если я устанавливаю его в 1.5, он работает как шарм. Для меня это не имеет смысла.

Кроме того, я заметил, что surfaceCreated никогда не вызывается. Я не знаю, связано ли это, но я думал, что стоит отметить.

Я нашел много похожих ответов, но ничего не работало для меня.

UPDATE: он растянут на всех устройствах, но исправляется только при нажатии на записи на некоторых устройствах (Motorola Razr HD и Galaxy Tab 2), но не на других (Samsung Note и Samsung SIII).

Вот мой код:

(FYI, он падает с NPE на камере, когда вы нажимаете на запись. Он работает нормально в моем приложении, но мне пришлось удалить какой-то код, прежде чем я смог бы разместить его здесь.)

public class Video extends Activity implements SurfaceHolder.Callback { VideoView videoView; MediaRecorder recorder; Camera camera; SurfaceHolder holder; MediaPlayer player; private Handler handler; Size maxPreviewSize; private boolean finishing; private boolean firstRun; private boolean isRecording; private Object file; public static final int MEDIA_TYPE_VIDEO = 2; @Override public void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.video_layout); releaseCameraAndPreview(); videoView = (VideoView) findViewById(R.id.videoView); } //******************************** onPause() ************************************* /** * Task: Releases the camera and nulls it out when the Activity is paused */ @Override public void onPause() { super.onPause(); finishing = true; // Releases the Media Recorder object so that it can be used the next time the app // is launched. releaseMediaRecorder(); // Releases the camera so that it can be used after the app is paused. Otherwise // the camera will not be available to other apps or this app when resumed. releaseCamera(); } // ***************************** onDestroy() **************************************** /** * task: called by the system when destroying this activity. stop all * threads, stop recording comair, explicity recycle all bitmap images from * each row, and remove all callbacks from each view, to free up the memory. * Request the garbage collector to run. */ @Override protected void onDestroy() { finishing = true; super.onDestroy(); }// end onDestroy() //************************** onWindowFocusChanged() ******************************** /** Task: layout data cannot be accessed from onCreate, so use this method to load anything * that has layout data. */ @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); LayoutParams params = (LayoutParams) videoView.getLayoutParams(); params.width = 960; params.height = 540; videoView.setLayoutParams(params); if(finishing) { Log.d(«Video», «oWFC, finishing is true»); return; } firstRun = false; // Use mCurrentCamera to select the camera desired to safely restore // the fragment after the camera has been changed boolean opened = safeCameraOpen(); // Install a SurfaceHolder that will give information about the VideoView installHolder(); createPreview(); }//end onWindowFocusChanged() //******************************** installHolder() ************************************* /** * Task: Install a SurfaceHolder. Callback so we get notified when the * underlying surface is created and destroyed. */ private void installHolder() { holder = videoView.getHolder(); holder.setFixedSize(960, 540); holder.addCallback(this); } //*************************** surfaceCreated() ******************************** /** * Task: Connects the camera to the Preview and starts the Preview in the VideoView * * @param SurfaceHolder the holder that holds the callback for the camera so that we * know when it is stopped and started */ @Override public void surfaceCreated(SurfaceHolder holder) { Log.d(«Video», «\\\\\\\\\\\\ surfaceCreated() ////////////////////////»); } //*************************** createPreview() ******************************** /** * Task: Creates the preview by setting the VideoView to display the images from the * camera. * * @param SurfaceHolder the holder that holds the callback for the camera so that we * know when it is stopped and started */ private void createPreview() { try { // STEP 2: Connect Preview — Prepare a live camera image preview by connecting a // SurfaceView to the camera using Camera.setPreviewDisplay(). camera.setPreviewDisplay(holder); Rect r = holder.getSurfaceFrame(); Log.e(«Video», «rectangle (holder): » + r.width() + «,» + r.height()); // STEP 3: Start Preview — Call Camera.startPreview() to begin displaying the // live camera images. camera.startPreview(); } catch (IOException e) { Log.d(«Video», «Could not start the preview»); e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(«Video», «\\\\\\\\\\\\ surfaceChanged() ////////////////////////»); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.d(«Video», «\\\\\\\\\\\\ surfaceDestroyed() ////////////////////////»); // camera.setPreviewCallback(null); // camera.stopPreview(); // handler = null; } //*************************** safeCameraOpen() ********************************** /** * Task: opens the first back-facing camera. Checks to see if the camera is open before * attempting to open it * * @return Whether or not the camera was opened */ // TODO: choose the camera to open private boolean safeCameraOpen() { Log.d(«Video», «\\\\\\\\\\\\ safeCameraOpen() ////////////////////////»); boolean opened = false; try { releaseCameraAndPreview(); camera = Camera.open(); opened = (camera != null); Camera.Parameters param = camera.getParameters(); Log.e(«Video», «Camera.Parameters: » + param.flatten()); List<Size> previewSize = param.getSupportedPreviewSizes(); String str = «»; maxPreviewSize = previewSize.get(0); for(Size s:previewSize) { if(s.width > maxPreviewSize.width && s.width > s.height) { maxPreviewSize = s; } str += s.width + «x» + s.height+ «t»; } Log.e(«Video», «previewSizes:t» + str); } catch (Exception e) { Log.e(getString(R.string.app_name), «failed to open Camera»); e.printStackTrace(); } if(opened) Log.d(«Video», «I haz camera!!!!!!!»); else Log.d(«Video», «I can haz camera??????? Noooooo!!!!»); return opened; } //********************* releaseCameraAndPreview() ************************** /** * Task: releases the camera and the preview so that other apps can use the resources and to * avoid a memory leak * */ private void releaseCameraAndPreview() { Log.d(«Video», «\\\\\\\\\\\\ releaseCameraAndPreview() ////////////////////////»); if (camera != null) { // Call stopPreview() to stop updating the preview surface. camera.stopPreview(); // Important: Call release() to release the camera for use by other applications. // Applications should release the camera immediately in onPause() (and re-open() it in // onResume()). camera.release(); camera = null; } } //*************************** getCameraInstance() ************************************ /** * Task: A safe way to get the instance of a Camera object * * @return Returns the camera or null if a camera is unavailable */ public Camera getCameraInstance() { Log.d(«Video», «\\\\\\\\\\\\ getCameraInstance() ////////////////////////»); Camera c = null; try { c = Camera.open(); // attempt to get a Camera instance } catch (Exception e) { // Camera is not available (in use or does not exist) } return c; // returns null if camera is unavailable } private void releaseMediaRecorder() { Log.d(«Video», «\\\\\\\\\\\\ releaseMediaRecorder() ////////////////////////»); if (recorder != null) { recorder.reset(); // clear recorder configuration recorder.release(); // release the recorder object recorder = null; camera.lock(); // lock camera for later use } } private void releaseCamera() { Log.d(«Video», «\\\\\\\\\\\\ releaseCamera() ////////////////////////»); if (camera != null) { camera.release(); // release the camera for other applications camera = null; } } //////////////////////////////////////////////////////////////////////////////////////////////// ///////////////// Set up MediaRecorder //////////////// //////////////////////////////////////////////////////////////////////////////////////////////// private void stopRecording() { // stop recording and release camera // recorder.stop(); // stop the recording releaseMediaRecorder(); // release the MediaRecorder object camera.lock(); // take camera access back from MediaRecorder camera.stopPreview(); releaseCamera(); boolean opened = safeCameraOpen(); createPreview(); // inform the user that recording has stopped isRecording = false; } private boolean prepareVideoRecorder() { Log.d(«Video», «\\\\\\\\\\\\ prepareVideoRecorder() ////////////////////////»); recorder = new MediaRecorder(); recorder.setOnInfoListener(new MediaRecorder.OnInfoListener() { @Override public void onInfo(MediaRecorder recorder, int what, int extra) { if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { Log.e(«VIDEOCAPTURE»,»Maximum Duration Reached»); stopRecording(); } } }); recorder.setOnErrorListener(new MediaRecorder.OnErrorListener() { @Override public void onError(MediaRecorder recorder, int what, int extra) { Log.e(«Video», «onErrorListenernwhat:» + what + «extra: » + extra); } }); // Step 1: Unlock and set camera to recorder camera.unlock(); recorder.setCamera(camera); // Step 2: Set sources recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // Step 3: Set output format and encoding (for versions prior to API Level 8) // recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); // recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); // recorder.setVideoSize(maxPreviewSize.width, maxPreviewSize.height); // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) CamcorderProfile cp; Log.d(«Video», «setProfile QUALITY_HIGH»); cp = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); Log.e(«Video», «CamcorderProfile.QUALITY_HIGH: » + «cp.quality:» + cp.quality + «, cp.videoFrameWidth:» + cp.videoFrameHeight + «, cp.videoFrameWidth:» + cp.videoFrameWidth); recorder.setProfile(cp); recorder.setVideoSize(960, 540); // recorder.setVideoSize(maxPreviewSize.width, maxPreviewSize.height); // recorder.setVideoSize(cp.videoFrameWidth, cp.videoFrameHeight); recorder.setMaxDuration(60000); // Step 4: Set output file // file = getOutputMediaFile(MEDIA_TYPE_VIDEO); // // if(file != null) // { // recorder.setOutputFile(file.toString()); // } // Step 5: Set the preview output recorder.setPreviewDisplay(videoView.getHolder().getSurface()); // Step 6: Prepare configured recorder try { recorder.prepare(); } catch (IllegalStateException e) { Log.d(«Video», «IllegalStateException preparing recorder: » + e.getMessage()); releaseMediaRecorder(); return false; } catch (IOException e) { Log.d(«Video», «IOException preparing recorder: » + e.getMessage()); releaseMediaRecorder(); return false; } return true; } private void releaseMediaPlayer() { player.stop(); player.release(); player = null; } public void onRecordClicked(View v) { if (isRecording) { Log.d(«Video», «\\\\\\\\\\\\ onRecordClicked() — stop ////////////////////////»); stopRecording(); } else { Log.d(«Video», «\\\\\\\\\\\\ onRecordClicked() — start ////////////////////////»); // initialize video camera if (prepareVideoRecorder()) { Log.d(«Video», «prepareVideoRecorder — true»); // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording recorder.start(); // inform the user that recording has started isRecording = true; } else { // prepare didn’t work, release the camera releaseMediaRecorder(); releaseCamera(); } } } }

Вот мой XML:

<RelativeLayout xmlns:android=»http://schemas.android.com/apk/res/android» xmlns:tools=»http://schemas.android.com/tools» android:id=»@+id/wholeDarnThing» android:layout_width=»match_parent» android:layout_height=»match_parent» android:background=»@color/black» tools:context=».Video» > <VideoView android:id=»@+id/videoView» android:layout_width=»wrap_content» android:layout_height=»wrap_content»/> </RelativeLayout>

Оцените статью
Добавить комментарий