视频兼容性问题:Android Camera的视频无法在所有设备上播放

时间:2014-06-06 06:15:38

标签: android video camera

我需要在相机拍摄的应用中上传视频。

问题是从相机录制的视频不能在所有手机和iPhone上播放。我搜索了所有支持的格式,但没有什么是正确的。我已经尝试了所有的打击和试验,但问题仍然存在。

这是我的RecorderActivity的代码。

public class RecorderActivity extends Activity implements
    SurfaceHolder.Callback, OnClickListener {

protected static final int RESULT_ERROR = 0x00000001;

private static final int MAX_VIDEO_DURATION = 9 * 1000;
private static final int ID_TIME_COUNT = 0x1006;

private static final String MP4_FILE_PREFIX = "Video_";
private static final String MP4_FILE_SUFIX = ".mp4";

private SurfaceView mSurfaceView;
private ImageView iv_cancel, iv_ok, iv_record;
private TextView tv_counter;

private SurfaceHolder mSurfaceHolder;
private MediaRecorder mMediaRecorder;
private Camera mCamera;

String filePath = "";

private boolean mIsRecording = false;
EmBazaarApplicationGlobal objectGlobal;
BaseAlbumDirFactory mAlbumStorageDirFactory;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.recorderactivity_layout);

    objectGlobal = (EmBazaarApplicationGlobal) getApplicationContext();
    mAlbumStorageDirFactory = new BaseAlbumDirFactory();

    initView();
}

@SuppressWarnings("deprecation")
private void initView() {

    mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
    mSurfaceView.getLayoutParams().width = getWindowManager()
            .getDefaultDisplay().getWidth();
    mSurfaceView.getLayoutParams().height = getWindowManager()
            .getDefaultDisplay().getWidth();

    iv_record = (ImageView) findViewById(R.id.iv_record);
    iv_cancel = (ImageView) findViewById(R.id.iv_cancel);
    iv_ok = (ImageView) findViewById(R.id.iv_ok);
    iv_record.setImageResource(R.drawable.btn_video_start);

    tv_counter = (TextView) findViewById(R.id.timer);
    tv_counter.setVisibility(View.GONE);

    iv_cancel.setOnClickListener(this);
    iv_ok.setOnClickListener(this);
    iv_record.setOnClickListener(this);

    mSurfaceHolder = mSurfaceView.getHolder();
    mSurfaceHolder.addCallback(this);

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        try {
            mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

private void exit(final int resultCode, final Intent data) {
    if (mIsRecording) {
        new AlertDialog.Builder(RecorderActivity.this)
                .setTitle("Video Recorder")
                .setMessage("Do you want to exit?")
                .setPositiveButton("yes",
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog,
                                    int which) {
                                stopRecord();
                                if (resultCode == RESULT_CANCELED) {
                                    deleteFile(new File(objectGlobal
                                            .getFilepath()));
                                }
                                setResult(resultCode, data);
                                finish();
                            }
                        })
                .setNegativeButton("no",
                        new DialogInterface.OnClickListener() {

                            @Override
                            public void onClick(DialogInterface dialog,
                                    int which) {

                            }
                        }).show();
        return;
    }
    if (resultCode == RESULT_CANCELED) {
        deleteFile(new File(objectGlobal.getFilepath()));
    }
    setResult(resultCode, data);
    finish();
}

private void deleteFile(File delFile) {
    if (delFile == null) {
        return;
    }
    final File file = new File(delFile.getAbsolutePath());
    delFile = null;
    new Thread() {
        @Override
        public void run() {
            super.run();
            if (file.exists()) {
                file.delete();
            }
        }
    }.start();
}

@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {

    @Override
    public void handleMessage(android.os.Message msg) {
        switch (msg.what) {
        case ID_TIME_COUNT:
            if (mIsRecording) {
                if (msg.arg1 > msg.arg2) {
                    // mTvTimeCount.setVisibility(View.INVISIBLE);
                    tv_counter.setText("00:00");
                    stopRecord();
                } else {
                    tv_counter.setText("00:0" + (msg.arg2 - msg.arg1));
                    Message msg2 = mHandler.obtainMessage(ID_TIME_COUNT,
                            msg.arg1 + 1, msg.arg2);
                    mHandler.sendMessageDelayed(msg2, 1000);
                }
            }
            break;

        default:
            break;
        }
    };

};

@SuppressLint("NewApi")
private void openCamera() {
    // Open camera
    try {
        this.mCamera = Camera.open();
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setRotation(90);
        parameters.set("orientation", "portrait");
        // parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        mCamera.setParameters(parameters);
        mCamera.lock();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
            try {
                mCamera.setDisplayOrientation(90);
            } catch (NoSuchMethodError e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@SuppressLint("NewApi")
private boolean initVideoRecorder() {

    mCamera.unlock();
    mMediaRecorder = new MediaRecorder();

    mMediaRecorder.setCamera(mCamera);

    try {
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    } catch (Exception e) {
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        e.printStackTrace();
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
        try {
            CamcorderProfile lowProfile = CamcorderProfile
                    .get(CamcorderProfile.QUALITY_LOW);
            CamcorderProfile hightProfile = CamcorderProfile
                    .get(CamcorderProfile.QUALITY_HIGH);
            if (lowProfile != null && hightProfile != null) {
                int audioBitRate = lowProfile.audioBitRate > 128000 ? 128000
                        : lowProfile.audioBitRate;
                lowProfile.audioBitRate = audioBitRate > hightProfile.audioBitRate ? hightProfile.audioBitRate
                        : audioBitRate;
                lowProfile.audioSampleRate = 48000 > hightProfile.audioSampleRate ? hightProfile.audioSampleRate
                        : 48000;

                lowProfile.duration = hightProfile.duration;
                lowProfile.videoFrameRate = hightProfile.videoFrameRate;
                lowProfile.videoBitRate = 1500000 > hightProfile.videoBitRate ? hightProfile.videoBitRate
                        : 1500000;
                ;

                mMediaRecorder.setProfile(lowProfile);
            }
        } catch (Exception e) {
            try {
                mMediaRecorder
                        .setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
                mMediaRecorder
                        .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                mMediaRecorder.setVideoSize(640, 480);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        }
    } else {
        try {
            mMediaRecorder
                    .setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
            mMediaRecorder
                    .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mMediaRecorder.setVideoSize(640, 480);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    File f = null;
    try {
        f = setUpVideoFile();
        filePath = f.getAbsolutePath();
    } catch (IOException e) {
        e.printStackTrace();
        f = null;
        filePath = null;
    }
    objectGlobal.setFilepath(filePath);
    mMediaRecorder.setOutputFile(filePath);

    mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        try {
            mMediaRecorder.setOrientationHint(90);
        } catch (NoSuchMethodError e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    try {
        mMediaRecorder.prepare();
    } catch (IllegalStateException e) {
        Log.d("VideoPreview",
                "IllegalStateException preparing MediaRecorder: "
                        + e.getMessage());
        releaseMediaRecorder();
        return false;
    } catch (IOException e) {
        Log.d("VideoPreview",
                "IOException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
    } catch (Exception e) {
        releaseMediaRecorder();
        e.printStackTrace();
    }
    return true;
}

private void releaseMediaRecorder() {
    if (mMediaRecorder != null) {
        mMediaRecorder.reset();
        mMediaRecorder.release();
        mMediaRecorder = null;
        mCamera.lock();
    }
}

private void releaseCamera() {
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

private void startRecord() {
    try {
        if (initVideoRecorder()) {
            mMediaRecorder.start();
            iv_record.setImageResource(R.drawable.btn_video_stop);
        } else {
            releaseMediaRecorder();
            iv_record.setImageResource(R.drawable.btn_video_start);
        }
        tv_counter.setVisibility(View.VISIBLE);
        tv_counter.setText("00:0" + (MAX_VIDEO_DURATION / 1000));
        Message msg = mHandler.obtainMessage(ID_TIME_COUNT, 1,
                MAX_VIDEO_DURATION / 1000);
        mHandler.sendMessage(msg);
        mIsRecording = true;
    } catch (Exception e) {
        showShortToast("problem while capturing video");
        e.printStackTrace();
        exit(RESULT_ERROR, null);
    }
}

private void stopRecord() {
    try {
        mMediaRecorder.stop();
    } catch (Exception e) {
        if (new File(objectGlobal.getFilepath()) != null
                && new File(objectGlobal.getFilepath()).exists()) {
            new File(objectGlobal.getFilepath()).delete();
        }
    }
    releaseMediaRecorder();
    mCamera.lock();
    iv_record.setImageResource(R.drawable.btn_video_start);
    mIsRecording = false;

    iv_record.setVisibility(View.GONE);
    iv_cancel.setVisibility(View.VISIBLE);
    iv_ok.setVisibility(View.VISIBLE);
}

@Override
protected void onResume() {
    super.onResume();
    openCamera();
}

@Override
protected void onPause() {
    super.onPause();
    releaseCamera();
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    if (mCamera != null) {
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (Exception e) {
        }
    }
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if (mCamera != null) {
        try {
            mCamera.stopPreview();
        } catch (Exception e) {
        }
    }
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        exit(RESULT_CANCELED, null);
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public void onClick(View arg0) {
    switch (arg0.getId()) {
    case R.id.iv_ok:
        Intent data = new Intent();
        if (objectGlobal.getFilepath() != null) {
            data.putExtra("videopath", objectGlobal.getFilepath());
        }
        exit(RESULT_OK, data);
        break;
    case R.id.iv_cancel:
        exit(RESULT_CANCELED, null);
        break;
    case R.id.iv_record:
        if (mIsRecording) {
            stopRecord();
        } else {
            startRecord();
        }
        break;
    default:
        break;
    }
}

protected void showShortToast(String text) {
    Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}

private File setUpVideoFile() throws IOException {

    File f = createVideoFile();
    filePath = f.getAbsolutePath();

    return f;
}

@SuppressLint("SimpleDateFormat")
private File createVideoFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
            .format(new Date());
    String videoFileName = MP4_FILE_PREFIX + timeStamp + "_";
    File albumF = getAlbumDir();
    File videoF = File
            .createTempFile(videoFileName, MP4_FILE_SUFIX, albumF);
    return videoF;
}

private File getAlbumDir() {
    File storageDir = null;

    if (Environment.MEDIA_MOUNTED.equals(Environment
            .getExternalStorageState())) {

        storageDir = mAlbumStorageDirFactory
                .getAlbumStorageDir(getAlbumName());
        // storageDir = Environment.getExternalStorageDirectory();
        if (storageDir != null) {
            if (!storageDir.mkdirs()) {
                if (!storageDir.exists()) {
                    Log.d("CameraSample", "failed to create directory");
                    return null;
                }
            }
        }
    } else {
        Log.v(getString(R.string.app_name),
                "External storage is not mounted READ/WRITE.");
    }

    return storageDir;
}

private String getAlbumName() {
    return "Embazaar";
}
}

1 个答案:

答案 0 :(得分:2)

好吧..在Android和iOS下载相机拍摄的视频之后..我发现iPhone使用的编解码器和视频大小与android不同。因此我在Android中捕获视频时改变了编解码器和视频大小,类似于iOS。简而言之,这些线条将起到作用。

mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setVideoSize(640, 480);