package com.yixia.camera;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.util.Log;
import com.yixia.camera.model.MediaObject.MediaPart;
import com.yixia.camera.util.FileUtils;
import com.yixia.videoeditor.adapter.UtilityAdapter;
import java.io.IOException;
/**
* 使用系统MediaRecorder录制,适合低端机
*
* @author yixia.com
*
*/
public class MediaRecorderSystem extends MediaRecorderBase implements android.media.MediaRecorder.OnErrorListener {
/** 系统MediaRecorder对象 */
private android.media.MediaRecorder mMediaRecorder;
public MediaRecorderSystem() {
}
/** 开始录制 */
@Override
public MediaPart startRecord() {
if (mMediaObject != null && mSurfaceHolder != null && !mRecording) {
MediaPart result = mMediaObject.buildMediaPart(mCameraId, ".mp4");
try {
if (mMediaRecorder == null) {
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setOnErrorListener(this);
} else {
mMediaRecorder.reset();
}
// Step 1: Unlock and set camera to MediaRecorder
camera.unlock();
mMediaRecorder.setCamera(camera);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
// Step 2: Set sources
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//before setOutputFormat()
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//before setOutputFormat()
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
//设置视频输出的格式和编码
CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
// mMediaRecorder.setProfile(mProfile);
mMediaRecorder.setVideoSize(640, 480);//after setVideoSource(),after setOutFormat()
mMediaRecorder.setAudioEncodingBitRate(44100);
if (mProfile.videoBitRate > 2 * 1024 * 1024)
mMediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024);
else
mMediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate);
mMediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);//after setVideoSource(),after setOutFormat()
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//after setOutputFormat()
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);//after setOutputFormat()
//mMediaRecorder.setVideoEncodingBitRate(800);
// Step 4: Set output file
mMediaRecorder.setOutputFile(result.mediaPath);
// Step 5: Set the preview output
// mMediaRecorder.setOrientationHint(90);//加了HTC的手机会有问题
Log.e("Yixia", "OutputFile:" + result.mediaPath);
mMediaRecorder.prepare();
mMediaRecorder.start();
mRecording = true;
return result;
} catch (IllegalStateException e) {
e.printStackTrace();
Log.e("Yixia", "startRecord", e);
} catch (IOException e) {
e.printStackTrace();
Log.e("Yixia", "startRecord", e);
} catch (Exception e) {
e.printStackTrace();
Log.e("Yixia", "startRecord", e);
}
}
return null;
}
/** 停止录制 */
@Override
public void stopRecord() {
long endTime = System.currentTimeMillis();
if (mMediaRecorder != null) {
//设置后不会崩
mMediaRecorder.setOnErrorListener(null);
mMediaRecorder.setPreviewDisplay(null);
try {
mMediaRecorder.stop();
} catch (IllegalStateException e) {
Log.w("Yixia", "stopRecord", e);
} catch (RuntimeException e) {
Log.w("Yixia", "stopRecord", e);
} catch (Exception e) {
Log.w("Yixia", "stopRecord", e);
}
}
if (camera != null) {
try {
camera.lock();
} catch (RuntimeException e) {
Log.e("Yixia", "stopRecord", e);
}
}
// 判断数据是否处理完,处理完了关闭输出流
if (mMediaObject != null) {
MediaPart part = mMediaObject.getCurrentPart();
if (part != null && part.recording) {
part.recording = false;
part.endTime = endTime;
part.duration = (int) (part.endTime - part.startTime);
part.cutStartTime = 0;
part.cutEndTime = part.duration;
}
}
mRecording = false;
}
/** 释放资源 */
@Override
public void release() {
super.release();
if (mMediaRecorder != null) {
mMediaRecorder.setOnErrorListener(null);
try {
mMediaRecorder.release();
} catch (IllegalStateException e) {
Log.w("Yixia", "stopRecord", e);
} catch (Exception e) {
Log.w("Yixia", "stopRecord", e);
}
}
mMediaRecorder = null;
}
@Override
public void onError(MediaRecorder mr, int what, int extra) {
try {
if (mr != null)
mr.reset();
} catch (IllegalStateException e) {
Log.w("Yixia", "stopRecord", e);
} catch (Exception e) {
Log.w("Yixia", "stopRecord", e);
}
if (mOnErrorListener != null)
mOnErrorListener.onVideoError(what, extra);
}
/** 不需要视频数据回调 */
@Override
protected void setPreviewCallback() {
//super.setPreviewCallback();
}
/** 合并视频文件 */
@Override
protected void concatVideoParts() {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected Boolean doInBackground(Void... params) {
String cmd = "";
int cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
//将mp4转成ts
for (int i = 0, j = mMediaObject.getMedaParts().size(); i < j; i++) {
MediaPart part = mMediaObject.getMedaParts().get(i);
if (FileUtils.checkFile(part.mediaPath)) {
String ts = part.mediaPath.replace(".mp4", ".ts");
FileUtils.deleteFile(ts);//删除
cameraId = part.cameraId;
cmd = String.format("ffmpeg %s -i \"%s\" -r 25 -vcodec copy -acodec copy -vbsf h264_mp4toannexb \"%s\"", FFMpegUtils.getLogCommand(), part.mediaPath, ts);
if (UtilityAdapter.FFmpegRun("", cmd) == 0) {
part.mediaPath = ts;//修改后缀名
continue;
}
}
//文件不存在或者转码失败,直接跳过
part.mediaPath = "";
}
//处理翻转信息
String vf = cameraId == Camera.CameraInfo.CAMERA_FACING_BACK ? "transpose=1" : "transpose=2,hflip";
//合并ts流
cmd = String.format("ffmpeg %s -i \"%s\" -vf \"%s\" %s -acodec copy -absf aac_adtstoasc -f mp4 -movflags faststart \"%s\"", FFMpegUtils.getLogCommand(), mMediaObject.getConcatYUV(), vf, FFMpegUtils.getVCodecCommand(), mMediaObject.getOutputTempVideoPath());
android.util.Log.e("MediaRecorderSystem", cmd);
return UtilityAdapter.FFmpegRun("", cmd) == 0;
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
mEncodeHanlder.sendEmptyMessage(MESSAGE_ENCODE_COMPLETE);
} else {
mEncodeHanlder.sendEmptyMessage(MESSAGE_ENCODE_ERROR);
}
}
}.execute();
}
}