Android 在特定设备上使用摄像头录制视频失败

Android 在特定设备上使用摄像头录制视频失败,android,android-camera,android-mediarecorder,Android,Android Camera,Android Mediarecorder,录音会在某些设备上生成有效的mp4文件,但在我当前使用的设备上生成损坏的mp4文件。这个损坏的文件以绿色为特征,每个看到它的人都评论说它看起来像是编解码器问题。即使在录制过程中,您也可以看到当前帧中的某些对象在该帧消失并显示下一帧时不会被删除 public class Record_activity extends ActionBarActivity { RecordFragment m_recordFragment=new RecordFragment(this); @Ove

录音会在某些设备上生成有效的mp4文件,但在我当前使用的设备上生成损坏的mp4文件。这个损坏的文件以绿色为特征,每个看到它的人都评论说它看起来像是编解码器问题。即使在录制过程中,您也可以看到当前帧中的某些对象在该帧消失并显示下一帧时不会被删除

public class Record_activity extends ActionBarActivity {
    RecordFragment m_recordFragment=new RecordFragment(this); 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_record_activity);


        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
            .add(R.id.container,m_recordFragment ).commit();
        }
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        m_recordFragment.onPause();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.record_activity, menu);
        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    /** Check if this device has a camera */
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }
    /**
     * A placeholder fragment containing a simple view.
     */
    public static class RecordFragment extends Fragment {
        public static final int MEDIA_TYPE_IMAGE = 1;
        public static final int MEDIA_TYPE_VIDEO = 2;
        private static Camera mCamera;
        private CameraPreview mPreview;
        Context m_context;
        private MediaRecorder mMediaRecorder;

        private boolean isRecording = false;
        private Button m_captureButton;
        private int ScreenWidth;
        private int ScreenHeight;

        public RecordFragment(Context aContext) {
            m_context=aContext;
        }
        @Override
        public void onPause() {
            // TODO Auto-generated method stub
            super.onPause();

            releaseMediaRecorder();       // if you are using MediaRecorder, release it first
            releaseCamera();              // release the camera immediately on pause event
        }
        /** A safe way to get an instance of the Camera object. */
        public static Camera getCameraInstance(boolean aIsBackCamera){
            if(mCamera==null)
            {
                int numCameras=Camera.getNumberOfCameras();
                try {
                    if(aIsBackCamera)
                        mCamera = Camera.open(0); // attempt to get a Camera instance
                    else mCamera=Camera.open(numCameras-1); // attempt to get a Camera instance
                }
                catch (Exception e){
                    Log.d("record", "open camera exception:"+e.getMessage());
                    // Camera is not available (in use or does not exist)
                }
            }

            return mCamera; // returns null if camera is unavailable
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_record_activity,
                    container, false);

            // Create an instance of Camera
            mCamera = getCameraInstance(true);

            Display display =((Activity)m_context).getWindowManager().getDefaultDisplay(); 
            ScreenWidth = display.getWidth();  // deprecated
            ScreenHeight = display.getHeight();  // deprecated
            Log.d("record", "screenWidth:"+ScreenWidth+"screenHeight:"+ScreenHeight);

            // Create our Preview view and set it as the content of our activity.
            mPreview = new CameraPreview(m_context, mCamera);
            FrameLayout preview = (FrameLayout) rootView.findViewById(R.id.camera_preview);
            preview.addView(mPreview);

            // Add a listener to the Capture button
            m_captureButton = (Button) rootView.findViewById(R.id.button_capture);
            m_captureButton.setOnClickListener(
                    new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (isRecording) {
                                // stop recording and release camera
                                mMediaRecorder.stop();  // stop the recording
                                releaseMediaRecorder(); // release the MediaRecorder object
                                mCamera.lock();         // take camera access back from MediaRecorder

                                // inform the user that recording has stopped
                                setCaptureButtonText("Capture");
                                isRecording = false;
                            } else {
                                // initialize video camera
                                if (prepareVideoRecorder()) {
                                    // Camera is available and unlocked, MediaRecorder is prepared,
                                    // now you can start recording
                                    mMediaRecorder.start();

                                    // inform the user that recording has started
                                    setCaptureButtonText("Stop");
                                    isRecording = true;
                                } else {
                                    // prepare didn't work, release the camera
                                    releaseMediaRecorder();
                                    // inform user
                                }
                            }
                        }

                        private void setCaptureButtonText(String string) {
                            m_captureButton.setText(string);

                        }
                    }
                    );
            return rootView;
        }
        private boolean prepareVideoRecorder(){

            mCamera = getCameraInstance(true);
            mMediaRecorder = new MediaRecorder();

            // Step 1: Unlock and set camera to MediaRecorder
            mCamera.unlock();
            mMediaRecorder.setCamera(mCamera);

            // Step 2: Set sources
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
            mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

            // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
            mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

            // Step 4: Set output file
            mMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());

            // Step 5: Set the preview output
            mMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

            // Step 6: Prepare configured MediaRecorder
            try {
                mMediaRecorder.prepare();
            } catch (IllegalStateException e) {
                Log.d("record", "IllegalStateException preparing MediaRecorder: " + e.getMessage());
                releaseMediaRecorder();
                return false;
            } catch (IOException e) {
                Log.d("record", "IOException preparing MediaRecorder: " + e.getMessage());
                releaseMediaRecorder();
                return false;
            }
            return true;
        }
        private void releaseMediaRecorder(){
            if (mMediaRecorder != null) {
                mMediaRecorder.reset();   // clear recorder configuration
                mMediaRecorder.release(); // release the recorder object
                mMediaRecorder = null;
                mCamera.lock();           // lock camera for later use
            }
        }
        private void releaseCamera(){
            if (mCamera != null){
                mCamera.release();        // release the camera for other applications
                mCamera = null;
            }
        }
        /** Create a File for saving an image or video */
        private static File getOutputMediaFile(int type){
            // To be safe, you should check that the SDCard is mounted
            // using Environment.getExternalStorageState() before doing this.

            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES), "MyCameraApp");
            // This location works best if you want the created images to be shared
            // between applications and persist after your app has been uninstalled.

            // Create the storage directory if it does not exist
            if (! mediaStorageDir.exists()){
                if (! mediaStorageDir.mkdirs()){
                    Log.d("MyCameraApp", "failed to create directory");
                    return null;
                }
            }

            // Create a media file name
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            File mediaFile;
            if (type == MEDIA_TYPE_IMAGE){
                mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                        "IMG_"+ timeStamp + ".jpg");
            } else if(type == MEDIA_TYPE_VIDEO) {
                mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                        "VID_"+ timeStamp + ".mp4");
            } else {
                return null;
            }

            return mediaFile;
        }

        public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback 
        {
            private SurfaceHolder mHolder;
            private Camera mCamera;

            public CameraPreview(Context context, Camera camera) {
                super(context);
                mCamera = camera;

                // Install a SurfaceHolder.Callback so we get notified when the
                // underlying surface is created and destroyed.
                mHolder = getHolder();
                mHolder.addCallback(this);
                // deprecated setting, but required on Android versions prior to 3.0
                mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            }
            @Override
            protected void onSizeChanged(int w, int h, int oldw, int oldh) {
                // TODO Auto-generated method stub
                super.onSizeChanged(w, h, oldw, oldh);
            }
            public void surfaceCreated(SurfaceHolder holder) {
                // The Surface has been created, now tell the camera where to draw the preview.
                try {
                    mCamera = getCameraInstance(true);
                    mCamera.setPreviewDisplay(holder);
                    // mCamera.startPreview();
                } catch (IOException e) {
                    Log.d("record", "Error setting camera preview: " + e.getMessage());
                }
            }

            public void surfaceDestroyed(SurfaceHolder holder) {
                // empty. Take care of releasing the Camera preview in your activity.
            }
            private Camera.Size getBestPreviewSize(int width, int height,
                    Camera.Parameters parameters) {
                Camera.Size result=null;

                for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
                    if (size.width<=width && size.height<=height) {
                        if (result==null) {
                            result=size;
                        }
                        else {
                            int resultArea=result.width*result.height;
                            int newArea=size.width*size.height;

                            if (newArea>resultArea) {
                                result=size;
                            }
                        }
                    }
                }

                return(result);
            }
            public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
                // If your preview can change or rotate, take care of those events here.
                // Make sure to stop the preview before resizing or reformatting it.

                if (mHolder.getSurface() == null){
                    // preview surface does not exist
                    return;
                }

                // stop preview before making changes
                try {
                    //  mCamera.stopPreview();
                } catch (Exception e){
                    // ignore: tried to stop a non-existent preview
                }

                Parameters params=mCamera.getParameters();
                Size size=getBestPreviewSize(w, h,params );
                Log.d("record", "surface width:"+w+"surface height"+h+"previewWidth:"+size.width+"previewHeight:"+size.height);
                params.setPreviewSize(size.width,size.height);
                // start preview with new settings
                try {
                    mCamera.setPreviewDisplay(mHolder);

                    // set preview size and make any resize, rotate or
                    // reformatting changes here



                    mCamera.startPreview();

                } catch (Exception e){
                    Log.d("record", "Error starting camera preview: " + e.getMessage());
                }
            }
        }

    }

    /** A basic Camera preview class */
}
片段\记录\活动.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.recordapp.RecordFragment" >

    <FrameLayout
        android:id="@+id/camera_preview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        />

    <Button
        android:id="@+id/button_capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Capture" />

</LinearLayout>

好的,我找到了一个答案,我用了,它有一个编解码器的支持和问题的答案