package lzf.video.edit;
import android.Manifest;
import android.annotation.TargetApi;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;
import com.afollestad.materialcamera.MaterialCamera;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import lzf.video.edit.adapter.CurrentVideoBitmapAdapter;
import lzf.video.edit.decoder.VideoDecoder;
public class MainActivity extends AppCompatActivity implements
View.OnClickListener,
MediaPlayer.OnCompletionListener,
Runnable,
MediaPlayer.OnPreparedListener {
private VideoView videoView;
private ImageView play;
private ImageView select;
private String videoPath = null;
private static final String TAG = "MainActivity";
private static final int CAMERA_RQ = 8001;
private static final int PERMISSION_CAMERA_RQ = 8002;
private static final int LOCAL_RQ = 8003;
private static final int PERMISSION_LOCAL_RQ = 8004;
private Thread getVideoBitmap;
private List<String> videoBitmapPath;
private RecyclerView recycler_bitmap;
private CurrentVideoBitmapAdapter adapter;
private static final String VIDEO_FROM_LOCAL = "local";
private static final String VIDEO_FROM_RECORD = "record";
private static final String VIDEO_FROM_CUT = "cut";
private String videoFrom = null;//拍摄 本地
private EditText start_time;
private EditText end_time;
private LinearLayout bottom;
private LinearLayout finish_decode;
private TextView cancel;
private TextView done;
private TextView start;
private TextView video_info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initListener();
videoBitmapPath = new ArrayList<>();
adapter = new CurrentVideoBitmapAdapter(this, videoBitmapPath);
recycler_bitmap.addItemDecoration(new MyItemDecoration());
recycler_bitmap.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
recycler_bitmap.setAdapter(adapter);
}
private void initListener() {
play.setOnClickListener(this);
select.setOnClickListener(this);
videoView.setOnCompletionListener(this);
videoView.setOnPreparedListener(this);
start.setOnClickListener(this);
cancel.setOnClickListener(this);
done.setOnClickListener(this);
}
private void initView() {
videoView = (VideoView) findViewById(R.id.videoView);
play = (ImageView) findViewById(R.id.play);
select = (ImageView) findViewById(R.id.selectVideo);
recycler_bitmap = (RecyclerView) findViewById(R.id.recycler_bitmap);
start_time = (EditText) findViewById(R.id.start_time);
end_time = (EditText) findViewById(R.id.end_time);
bottom = (LinearLayout) findViewById(R.id.bottom);
cancel = (TextView) findViewById(R.id.cancel);
done = (TextView) findViewById(R.id.done);
finish_decode = (LinearLayout) findViewById(R.id.finish);
start = (TextView) findViewById(R.id.start);
video_info= (TextView) findViewById(R.id.video_info);
bottom.setVisibility(View.GONE);
finish_decode.setVisibility(View.GONE);
play.setVisibility(View.GONE);
videoView.setMediaController(null);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//播放视频
case R.id.play:
if (videoView != null && videoPath != null) {
// videoView.setVideoPath(videoPath);
videoView.setVideoURI(Uri.parse(videoPath));
videoView.start();
} else {
Toast.makeText(MainActivity.this, "打开视频失败", Toast.LENGTH_SHORT).show();
}
break;
//选择视频
case R.id.selectVideo:
selectVideo();
break;
//开始剪切视频
case R.id.start:
startDecodeVideo();
break;
//取消
case R.id.cancel:
finish_decode.setVisibility(View.GONE);
videoView.setVideoPath(videoPath);
videoView.start();
break;
//完成
case R.id.done:
Intent intent=new Intent(MainActivity.this,ChangeBackgroundAudioActivity.class);
//Environment.getExternalStorageDirectory().getPath() + "/lzf_decoder_video.mp4"
intent.putExtra("video_path",Environment.getExternalStorageDirectory().getPath() + "/lzf_decoder_video.mp4");
startActivity(intent);
break;
}
}
private void startDecodeVideo() {
//起始时间 截取时长
if (start_time.getText() != null) {
if (Integer.parseInt(start_time.getText().toString()) * 1000 > videoView.getDuration()) {
Toast.makeText(MainActivity.this, "开始时间错误", Toast.LENGTH_SHORT).show();
} else {
if (end_time.getText() != null) {
if (Integer.parseInt(start_time.getText().toString()) * 1000 + Integer.parseInt(end_time.getText().toString()) * 1000 > videoView.getDuration()) {
Toast.makeText(MainActivity.this, "错误的截取时长", Toast.LENGTH_SHORT).show();
} else {
boolean finish = new VideoDecoder().decodeVideo(videoPath, Integer.parseInt(start_time.getText().toString()) * 1000 * 1000, Integer.parseInt(end_time.getText().toString()) * 1000 * 1000);
if (finish) {
videoPath=Environment.getExternalStorageDirectory().getPath() + "/lzf_decoder_video.mp4";
// videoView.setVideoPath(videoPath);
videoView.setVideoURI(Uri.parse(videoPath));
// videoView.setRotation(-90);
videoView.start();
//拍摄的视频有个角度 剪切的时候视频角度信息给剪切没了
if(videoFrom.equals(VIDEO_FROM_RECORD)){
resizeVideo();
}
videoFrom=VIDEO_FROM_CUT;
finish_decode.setVisibility(View.VISIBLE);
} else {
Log.e("lzf_decoder_video", "视频剪切失败");
}
}
} else {
Toast.makeText(MainActivity.this, "请输入截取时长", Toast.LENGTH_SHORT).show();
}
}
} else {
Toast.makeText(MainActivity.this, "请输入开始时间", Toast.LENGTH_SHORT).show();
}
}
private void resizeVideo() {
RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(480,640);
layoutParams.addRule(Gravity.CENTER);
videoView.setLayoutParams(layoutParams);
// videoView.setRotation(-90);
}
private void selectVideo() {
//本地视频或拍摄
final AlertDialog selectVideoDialog = new AlertDialog.Builder(this).create();
View view = LayoutInflater.from(this).inflate(R.layout.dialog_select_video_type, null);
TextView local = (TextView) view.findViewById(R.id.local);
TextView record = (TextView) view.findViewById(R.id.record);
local.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (selectVideoDialog != null) {
selectVideoDialog.dismiss();
}
Intent intent = new Intent(MainActivity.this, SelectLocalVideoActivity.class);
MainActivity.this.startActivityForResult(intent, LOCAL_RQ);
}
});
record.setOnClickListener(new View.OnClickListener() {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onClick(View v) {
//关闭dialog
if (selectVideoDialog != null) {
selectVideoDialog.dismiss();
}
//检验权限
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {
File saveDir = new File(Environment.getExternalStorageDirectory(), "lzf");
saveDir.mkdirs();
startRecord(saveDir);
} else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO
}, PERMISSION_CAMERA_RQ);
}
}
});
selectVideoDialog.setView(view);
selectVideoDialog.show();
}
@Override
public void onPrepared(MediaPlayer mp) {
videoView.requestLayout();
videoView.invalidate();
Log.e("lzf_video_角度",videoView.getRotation()+" ");
video_info.setText("视频时长"+videoView.getDuration()+"毫秒");
int degree= (int) videoView.getRotation();
play.setVisibility(View.GONE);
getVideoBitmap = new Thread(MainActivity.this);
getVideoBitmap.start();
}
@Override
public void onCompletion(MediaPlayer mp) {
play.setVisibility(View.VISIBLE);
getVideoBitmap.interrupt();
}
public void startRecord(File file) {
MaterialCamera materialCamera = new MaterialCamera(MainActivity.this)
.saveDir(file)
.showPortraitWarning(true)
.allowRetry(true)
.defaultToFrontFacing(true)
.allowRetry(true)
.autoSubmit(false)
.labelConfirm(R.string.mcam_use_video);
materialCamera.start(CAMERA_RQ, true);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISSION_CAMERA_RQ:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED
&& grantResults[2] == PackageManager.PERMISSION_GRANTED
&& grantResults[3] == PackageManager.PERMISSION_GRANTED) {
//用户同意授权
File saveDir = new File(Environment.getExternalStorageDirectory(), "lzf");
saveDir.mkdirs();
startRecord(saveDir);
} else {
//用户拒绝授权
Toast.makeText(MainActivity.this, "获取权限失败", Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case CAMERA_RQ:
//拍摄
String filePath = data.getStringExtra("videoUrl");
if (filePath != null) {
videoPath = filePath;
Log.e("lzf_activity_result", "视频路径" + videoPath);
videoFrom = VIDEO_FROM_RECORD;
videoView.setVideoURI(Uri.parse(filePath));
videoView.start();
} else {
Log.e("lzf_activity_result", "返回失败");
}
break;
case LOCAL_RQ:
//本地
String filePath_local = data.getStringExtra("videoUrl");
if (filePath_local != null) {
videoPath = filePath_local;
Log.e("lzf_activity_result", "视频路径" + filePath_local);
// requestVideoWH(480,640);
videoFrom = VIDEO_FROM_LOCAL;
videoView.setVideoURI(Uri.parse(filePath_local));
videoView.start();
} else {
Log.e("lzf_activity_result", "选择本地视频返回失败");
}
break;
}
}
}
@Override
public void run() {
//获取视频帧图
ArrayList<String> list = new ArrayList<>();
// String [] array=new String[]{};
MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
Log.i(TAG, Environment.getExternalStorageDirectory().getPath() + "/video.mp4" + " " + videoPath);
Log.i(TAG, Environment.getExternalStorageDirectory() + "/video.mp4" + " " + videoPath.substring(7, videoPath.length()));
// metadataRetriever.setDataSource(videoPath);
if (videoFrom.equals(VIDEO_FROM_RECORD)) {
metadataRetriever.setDataSource(videoPath.substring(7, videoPath.length()));
} else if (videoFrom.equals(VIDEO_FROM_LOCAL)||videoFrom.equals(VIDEO_FROM_CUT)) {
metadataRetriever.setDataSource(videoPath);
}
String rotation = metadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
Log.e("lzf_duration", videoView.getDuration() + " "+" 旋转角度 "+rotation);
for (int i = 500 * 1000; i <= videoView.getDuration() * 1000; i += 1000 * 1000) {
Bitmap bitmap = metadataRetriever.
getFrameAtTime(videoView.getCurrentPosition() * 1000, MediaMetadataRetriever.OPTION_CLOSEST);
if (bitmap!=null) {
Log.i(TAG, "bitmap---i: " + i / 1000);
Log.e(TAG, videoView.getCurrentPosition() + " ");
String path = Environment.getExternalStorageDirectory() + "/bitmap_" + i + ".png";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(path);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fileOutputStream);
Log.i(TAG, "i: " + i / 1000);
list.add(path);
// array[i]=path;
} catch (Exception e) {
Log.i(TAG, "Error: " + i / 1000 + " " + e.getMessage());
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
bitmap.recycle();
}else {
Log.i(TAG, "Error: " + i / 1000 + "获取bitmap失败");
}
}
Message msg = new Message();
msg.what = 0;
handler.obtainMessage();
//将msg发送到目标对象,所谓的目标对象,就是生成该msg对象的handler对象
Bundle b = new Bundle();
b.putStringArrayList("array", list);
msg.setData(b);
// msg.sendToTarget();
handler.sendMessage(msg);
metadataRetriever.release();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO 接收消息并且去更新UI线程上的控件内容
if (msg.what == 0) {
Bundle b = msg.getData();
Log.e("lzf_video_bitmap_path", videoBitmapPath.size() + " ");
if (b.getStringArrayList("array") != null) {
ArrayList<String> list = b.getStringArrayList("array");
if (list != null) {
videoBitmapPath.addAll(list);
}
}
Log.e("lzf_video_bitmap_path", videoBitmapPath.size() + " ");
adapter.notifyDataSetChanged();
bottom.setVisibility(View.VISIBLE);
}
super.handleMessage(msg);
}
};
}