package com.yixia.camera.model;
import com.yixia.camera.util.FileUtils;
import com.yixia.camera.util.StringUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.LinkedList;
@SuppressWarnings("serial")
public class MediaObject implements Serializable {
/** 拍摄 */
public final static int MEDIA_PART_TYPE_RECORD = 0;
/** 导入视频 */
public final static int MEDIA_PART_TYPE_IMPORT_VIDEO = 1;
/** 导入图片 */
public final static int MEDIA_PART_TYPE_IMPORT_IMAGE = 2;
/** 使用系统拍摄mp4 */
public final static int MEDIA_PART_TYPE_RECORD_MP4 = 3;
/** 默认最大时长 */
public final static int DEFAULT_MAX_DURATION = 10 * 1000;
/** 默认码率 */
public final static int DEFAULT_VIDEO_BITRATE = 800;
/** 视频最大时长,默认10秒 */
private int mMaxDuration;
/** 视频目录 */
private String mOutputDirectory;
/** 对象文件 */
private String mOutputObjectPath;
/** 视频码率 */
private int mVideoBitrate;
/** 最终视频输出路径 */
private String mOutputVideoPath;
/** 最终视频截图输出路径 */
private String mOutputVideoThumbPath;
/** 文件夹、文件名 */
private String mKey;
/** 当前分块 */
private volatile transient MediaPart mCurrentPart;
/** 获取所有分块 */
private LinkedList<MediaPart> mMediaList = new LinkedList<MediaPart>();
/** 主题 */
public MediaThemeObject mThemeObject;
public MediaObject(String key, String path) {
this(key, path, DEFAULT_VIDEO_BITRATE);
}
public MediaObject(String key, String path, int videoBitrate) {
this.mKey = key;
this.mOutputDirectory = path;
this.mVideoBitrate = videoBitrate;
this.mOutputObjectPath = mOutputDirectory + File.separator + mKey + ".obj";
this.mOutputVideoPath = mOutputDirectory + ".mp4";
this.mOutputVideoThumbPath = mOutputDirectory + ".jpg";
this.mMaxDuration = DEFAULT_MAX_DURATION;
}
/** 获取视频码率 */
public int getVideoBitrate() {
return mVideoBitrate;
}
/** 获取视频最大长度 */
public int getMaxDuration() {
return mMaxDuration;
}
/** 设置最大时长,必须大于1秒 */
public void setMaxDuration(int duration) {
if (duration >= 1000) {
mMaxDuration = duration;
}
}
/** 获取视频临时文件夹 */
public String getOutputDirectory() {
return mOutputDirectory;
}
/** 获取视频临时输出播放 */
public String getOutputTempVideoPath() {
return mOutputDirectory + File.separator + mKey + ".mp4";
}
/** 清空主题 */
public void cleanTheme() {
mThemeObject = null;
if (mMediaList != null) {
for (MediaPart part : mMediaList) {
part.cutStartTime = 0;
part.cutEndTime = part.duration;
}
}
}
/** 获取视频信息春促路径 */
public String getObjectFilePath() {
if (StringUtils.isEmpty(mOutputObjectPath)) {
File f = new File(mOutputVideoPath);
String obj = mOutputDirectory + File.separator + f.getName() + ".obj";
mOutputObjectPath = obj;
}
return mOutputObjectPath;
}
/** 获取视频最终输出地址 */
public String getOutputVideoPath() {
return mOutputVideoPath;
}
/** 获取视频截图最终输出地址 */
public String getOutputVideoThumbPath() {
return mOutputVideoThumbPath;
}
/** 获取录制的总时长 */
public int getDuration() {
int duration = 0;
if (mMediaList != null) {
for (MediaPart part : mMediaList) {
duration += part.getDuration();
}
}
return duration;
}
/** 获取剪切后的总时长 */
public int getCutDuration() {
int duration = 0;
if (mMediaList != null) {
for (MediaPart part : mMediaList) {
int cut = (part.cutEndTime - part.cutStartTime);
if (part.speed != 10) {
cut = (int) (cut * (10F / part.speed));
}
duration += cut;
}
}
return duration;
}
/** 删除分块 */
public void removePart(MediaPart part, boolean deleteFile) {
if (mMediaList != null)
mMediaList.remove(part);
if (part != null) {
part.stop();
// 删除文件
if (deleteFile) {
part.delete();
}
mMediaList.remove(part);
}
}
/**
* 生成分块信息,主要用于拍摄
*
* @param cameraId 记录摄像头是前置还是后置
* @return
*/
public MediaPart buildMediaPart(int cameraId) {
mCurrentPart = new MediaPart();
mCurrentPart.position = getDuration();
mCurrentPart.index = mMediaList.size();
mCurrentPart.mediaPath = mOutputDirectory + File.separator + mCurrentPart.index + ".v";
mCurrentPart.audioPath = mOutputDirectory + File.separator + mCurrentPart.index + ".a";
mCurrentPart.thumbPath = mOutputDirectory + File.separator + mCurrentPart.index + ".jpg";
mCurrentPart.cameraId = cameraId;
mCurrentPart.prepare();
mCurrentPart.recording = true;
mCurrentPart.startTime = System.currentTimeMillis();
mCurrentPart.type = MEDIA_PART_TYPE_IMPORT_VIDEO;
mMediaList.add(mCurrentPart);
return mCurrentPart;
}
public MediaPart buildMediaPart(int cameraId, String videoSuffix) {
mCurrentPart = new MediaPart();
mCurrentPart.position = getDuration();
mCurrentPart.index = mMediaList.size();
mCurrentPart.mediaPath = mOutputDirectory + File.separator + mCurrentPart.index + videoSuffix;
mCurrentPart.audioPath = mOutputDirectory + File.separator + mCurrentPart.index + ".a";
mCurrentPart.thumbPath = mOutputDirectory + File.separator + mCurrentPart.index + ".jpg";
mCurrentPart.recording = true;
mCurrentPart.cameraId = cameraId;
mCurrentPart.startTime = System.currentTimeMillis();
mCurrentPart.type = MEDIA_PART_TYPE_IMPORT_VIDEO;
mMediaList.add(mCurrentPart);
return mCurrentPart;
}
/**
* 生成分块信息,主要用于视频导入
*
* @param path
* @param duration
* @param type
* @return
*/
public MediaPart buildMediaPart(String path, int duration, int type) {
mCurrentPart = new MediaPart();
mCurrentPart.position = getDuration();
mCurrentPart.index = mMediaList.size();
mCurrentPart.mediaPath = mOutputDirectory + File.separator + mCurrentPart.index + ".v";
mCurrentPart.audioPath = mOutputDirectory + File.separator + mCurrentPart.index + ".a";
mCurrentPart.thumbPath = mOutputDirectory + File.separator + mCurrentPart.index + ".jpg";
mCurrentPart.duration = duration;
mCurrentPart.startTime = 0;
mCurrentPart.endTime = duration;
mCurrentPart.cutStartTime = 0;
mCurrentPart.cutEndTime = duration;
mCurrentPart.tempPath = path;
mCurrentPart.type = type;
mMediaList.add(mCurrentPart);
return mCurrentPart;
}
public String getConcatYUV() {
StringBuilder yuv = new StringBuilder();
if (mMediaList != null && mMediaList.size() > 0) {
if (mMediaList.size() == 1) {
if (StringUtils.isEmpty(mMediaList.get(0).tempMediaPath))
yuv.append(mMediaList.get(0).mediaPath);
else
yuv.append(mMediaList.get(0).tempMediaPath);
} else {
yuv.append("concat:");
for (int i = 0, j = mMediaList.size(); i < j; i++) {
MediaPart part = mMediaList.get(i);
if (StringUtils.isEmpty(part.tempMediaPath))
yuv.append(part.mediaPath);
else
yuv.append(part.tempMediaPath);
if (i + 1 < j) {
yuv.append("|");
}
}
}
}
return yuv.toString();
}
public String getConcatPCM() {
StringBuilder yuv = new StringBuilder();
if (mMediaList != null && mMediaList.size() > 0) {
if (mMediaList.size() == 1) {
if (StringUtils.isEmpty(mMediaList.get(0).tempAudioPath))
yuv.append(mMediaList.get(0).audioPath);
else
yuv.append(mMediaList.get(0).tempAudioPath);
} else {
yuv.append("concat:");
for (int i = 0, j = mMediaList.size(); i < j; i++) {
MediaPart part = mMediaList.get(i);
if (StringUtils.isEmpty(part.tempAudioPath))
yuv.append(part.audioPath);
else
yuv.append(part.tempAudioPath);
if (i + 1 < j) {
yuv.append("|");
}
}
}
}
return yuv.toString();
}
/** 获取当前分块 */
public MediaPart getCurrentPart() {
if (mCurrentPart != null)
return mCurrentPart;
if (mMediaList != null && mMediaList.size() > 0)
mCurrentPart = mMediaList.get(mMediaList.size() - 1);
return mCurrentPart;
}
public int getCurrentIndex() {
MediaPart part = getCurrentPart();
if (part != null)
return part.index;
return 0;
}
public MediaPart getPart(int index) {
if (mCurrentPart != null && index < mMediaList.size())
return mMediaList.get(index);
return null;
}
/** 取消拍摄 */
public void delete() {
if (mMediaList != null) {
for (MediaPart part : mMediaList) {
part.stop();
}
}
FileUtils.deleteDir(mOutputDirectory);
}
public LinkedList<MediaPart> getMedaParts() {
return mMediaList;
}
/** 预处理数据对象 */
public static void preparedMediaObject(MediaObject mMediaObject) {
if (mMediaObject != null && mMediaObject.mMediaList != null) {
int duration = 0;
for (MediaPart part : mMediaObject.mMediaList) {
part.startTime = duration;
part.endTime = part.startTime + part.duration;
duration += part.duration;
}
}
}
@Override
public String toString() {
StringBuffer result = new StringBuffer();
if (mMediaList != null) {
result.append("[" + mMediaList.size() + "]");
for (MediaPart part : mMediaList) {
result.append(part.mediaPath + ":" + part.duration + "\n");
}
}
return result.toString();
}
public static class MediaPart implements Serializable {
/** 索引 */
public int index;
/** 视频路径 */
public String mediaPath;
/** 音频路径 */
public String audioPath;
/** 临时视频路径 */
public String tempMediaPath;
/** 临时音频路径 */
public String tempAudioPath;
/** 截图路径 */
public String thumbPath;
/** 存放导入的视频和图片 */
public String tempPath;
/** 类型 */
public int type = MEDIA_PART_TYPE_RECORD;
/** 剪切视频(开始时间) */
public int cutStartTime;
/** 剪切视频(结束时间) */
public int cutEndTime;
/** 分段长度 */
public int duration;
/** 总时长中的具体位置 */
public int position;
/** 0.2倍速-3倍速(取值2~30) */
public int speed = 10;
/** 摄像头 */
public int cameraId;
/** 视频尺寸 */
public int yuvWidth;
/** 视频高度 */
public int yuvHeight;
public transient boolean remove;
public transient long startTime;
public transient long endTime;
public transient FileOutputStream mCurrentOutputVideo;
public transient FileOutputStream mCurrentOutputAudio;
public transient volatile boolean recording;
public MediaPart() {
}
public void delete() {
FileUtils.deleteFile(mediaPath);
FileUtils.deleteFile(audioPath);
FileUtils.deleteFile(thumbPath);
FileUtils.deleteFile(tempMediaPath);
FileUtils.deleteFile(tempAudioPath);
}
/** 写入音频数据 */
public void writeAudioData(byte[] buffer) throws IOException {
if (mCurrentOutputAudio != null)
mCurrentOutputAudio.write(buffer);
}
/** 写入视频数据 */
public void writeVideoData(byte[] buffer) throws IOException {
if (mCurrentOutputVideo != null)
mCurrentOutputVideo.write(buffer);
}
public void prepare() {
try {
mCurrentOutputVideo = new FileOutputStream(mediaPath);
} catch (IOException e) {
e.printStackTrace();
}
prepareAudio();
}
public void prepareAudio() {
try {
mCurrentOutputAudio = new FileOutputStream(audioPath);
} catch (IOException e) {
e.printStackTrace();
}
}
public int getDuration() {
return duration > 0 ? duration : (int) (System.currentTimeMillis() - startTime);
}
public void stop() {
if (mCurrentOutputVideo != null) {
try {
mCurrentOutputVideo.flush();
mCurrentOutputVideo.close();
} catch (IOException e) {
e.printStackTrace();
}
mCurrentOutputVideo = null;
}
if (mCurrentOutputAudio != null) {
try {
mCurrentOutputAudio.flush();
mCurrentOutputAudio.close();
} catch (IOException e) {
e.printStackTrace();
}
mCurrentOutputAudio = null;
}
}
}
}