3

Androidビデオアクティビティを作成しましたが、プレビュービデオが水平方向に引き伸ばされている理由を一生理解できません。(デバッグの目的で)値をハードコーディングしましたが、まだ正しくありません。レコードを押すと問題ないように見えますが、プレビュー中に引き伸ばされた状態に戻ります。

アスペクト比を手動で小さい値に設定すると(デバイスによって異なりますが、論理的な相関関係は見られません)、機能します。たとえば、SIIIで1.5に設定すると、チャームのように機能します。これは私には意味がありません。

また、surfaceCreatedが呼び出されていないことに気づきました。これが関係しているかどうかはわかりませんが、注目に値すると思いました。

似たような答えをたくさん見つけましたが、何もうまくいきませんでした。

更新:すべてのデバイスで拡張されますが、特定のデバイス(MotorolaRazrHDおよびGalaxyTab2)でレコードを押した場合にのみ修正され、他のデバイス(SamsungNoteおよびSamsungSIII)では修正されません。

これが私のコードです:

(参考までに、レコードをヒットするとカメラの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", "onErrorListener\nwhat:" + 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>
4

0 に答える 0