diff --git a/README.md b/README.md
index 5f88b41..9dc7c53 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@ android端基于FFmpeg库的使用。
- #### 视频转GIF动图
- #### 视频添加水印
- #### 视频画面拼接
+- #### 视频反序倒播
- #### 图片合成视频
- #### 视频解码播放
- #### 本地直播推流
@@ -52,7 +53,10 @@ android端基于FFmpeg库的使用。
![静态图片](https://github.com/xufuji456/FFmpegAndroid/blob/master/picture/filter_grid.png)
视频画面拼接:
-![视频](https://github.com/xufuji456/FFmpegAndroid/blob/master/gif/horizontal.gif)
+![动态图片](https://github.com/xufuji456/FFmpegAndroid/blob/master/gif/horizontal.gif)
+
+视频倒播:
+![动态图片](https://github.com/xufuji456/FFmpegAndroid/blob/master/gif/reverse.gif)
***
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b578eea..9800fb3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -36,26 +36,31 @@
+ android:screenOrientation="landscape"
+ android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
+ android:screenOrientation="landscape"
+ android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
-
+
-
+ android:screenOrientation="landscape"
+ android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
+
+ android:screenOrientation="landscape"
+ android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/frank/ffmpeg/activity/MainActivity.java b/app/src/main/java/com/frank/ffmpeg/activity/MainActivity.java
index 3bf5f65..f1b40e4 100644
--- a/app/src/main/java/com/frank/ffmpeg/activity/MainActivity.java
+++ b/app/src/main/java/com/frank/ffmpeg/activity/MainActivity.java
@@ -38,6 +38,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
findViewById(R.id.btn_push).setOnClickListener(this);
findViewById(R.id.btn_live).setOnClickListener(this);
findViewById(R.id.btn_filter).setOnClickListener(this);
+ findViewById(R.id.btn_reverse).setOnClickListener(this);
}
@Override
@@ -65,6 +66,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case R.id.btn_filter://滤镜特效
intent.setClass(MainActivity.this, FilterActivity.class);
break;
+ case R.id.btn_reverse://视频倒播
+ intent.setClass(MainActivity.this, VideoReverseActivity.class);
+ break;
default:
break;
}
diff --git a/app/src/main/java/com/frank/ffmpeg/activity/VideoReverseActivity.java b/app/src/main/java/com/frank/ffmpeg/activity/VideoReverseActivity.java
new file mode 100644
index 0000000..74fc7af
--- /dev/null
+++ b/app/src/main/java/com/frank/ffmpeg/activity/VideoReverseActivity.java
@@ -0,0 +1,118 @@
+package com.frank.ffmpeg.activity;
+
+import android.annotation.SuppressLint;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.VideoView;
+import com.frank.ffmpeg.FFmpegCmd;
+import com.frank.ffmpeg.R;
+import com.frank.ffmpeg.util.FFmpegUtil;
+import com.frank.ffmpeg.util.FileUtil;
+import java.io.File;
+
+/**
+ * 先处理视频反序,再视频倒播
+ * Created by frank on 2018/9/12.
+ */
+
+public class VideoReverseActivity extends AppCompatActivity {
+
+ private final static String TAG = VideoReverseActivity.class.getSimpleName();
+ private final static String ROOT_PATH = Environment.getExternalStorageDirectory().getPath();
+ private final static String VIDEO_NORMAL_PATH = ROOT_PATH + File.separator + "beyond.mp4";
+ private final static String VIDEO_REVERSE_PATH = ROOT_PATH + File.separator + "reverse.mp4";
+
+ private LinearLayout loading;
+ private VideoView videoNormal;
+ private VideoView videoReverse;
+
+ private final static int MSG_PLAY = 7777;
+ @SuppressLint("HandlerLeak")
+ private Handler mHandler = new Handler(){
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ if (msg.what == MSG_PLAY){
+ changeVisibility();
+ startPlay();
+ }
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_video_reverse);
+
+ initView();
+ initPlayer();
+ videoReverse();
+
+ }
+
+ private void initView() {
+ loading = (LinearLayout) findViewById(R.id.layout_loading);
+ videoNormal = (VideoView) findViewById(R.id.video_normal);
+ videoReverse = (VideoView) findViewById(R.id.video_reverse);
+ }
+
+ private void changeVisibility(){
+ loading.setVisibility(View.GONE);
+ videoNormal.setVisibility(View.VISIBLE);
+ videoReverse.setVisibility(View.VISIBLE);
+ }
+
+ private void initPlayer(){
+ videoNormal.setVideoPath(VIDEO_NORMAL_PATH);
+ videoReverse.setVideoPath(VIDEO_REVERSE_PATH);
+ }
+
+ /**
+ * 开始视频正序、反序播放
+ */
+ private void startPlay(){
+ videoNormal.start();
+ videoReverse.start();
+ }
+
+
+ /**
+ * 执行ffmpeg命令行
+ * @param commandLine commandLine
+ */
+ private void executeFFmpegCmd(final String[] commandLine){
+ if(commandLine == null){
+ return;
+ }
+ FFmpegCmd.execute(commandLine, new FFmpegCmd.OnHandleListener() {
+ @Override
+ public void onBegin() {
+ Log.i(TAG, "handle video onBegin...");
+ }
+
+ @Override
+ public void onEnd(int result) {
+ Log.i(TAG, "handle video onEnd...");
+ mHandler.sendEmptyMessage(MSG_PLAY);
+ }
+ });
+ }
+
+ /**
+ * 视频反序处理
+ */
+ private void videoReverse(){
+ if (!FileUtil.checkFileExist(VIDEO_NORMAL_PATH)){
+ return;
+ }
+ String[] commandLine = FFmpegUtil.reverseVideo(VIDEO_NORMAL_PATH, VIDEO_REVERSE_PATH);
+ executeFFmpegCmd(commandLine);
+ }
+
+}
diff --git a/app/src/main/java/com/frank/ffmpeg/util/FileUtil.java b/app/src/main/java/com/frank/ffmpeg/util/FileUtil.java
index fc97a00..4db0264 100644
--- a/app/src/main/java/com/frank/ffmpeg/util/FileUtil.java
+++ b/app/src/main/java/com/frank/ffmpeg/util/FileUtil.java
@@ -66,4 +66,20 @@ public class FileUtil {
return true;
}
+ /**
+ * 判断文件是否存在
+ * @param path 文件路径
+ * @return 文件是否存在
+ */
+ public static boolean checkFileExist(String path){
+ if (TextUtils.isEmpty(path)) {
+ throw new NullPointerException(path + "is null!");
+ }
+ File file = new File(path);
+ if(!file.exists()){
+ throw new NullPointerException(path + " is not exist!");
+ }
+ return true;
+ }
+
}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index ea74cf6..0c2eefd 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -7,7 +7,7 @@
android:id="@+id/btn_audio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="80dp"
+ android:layout_marginTop="10dp"
android:layout_centerHorizontal="true"
android:text="@string/audio_handle"/>
@@ -65,4 +65,13 @@
android:layout_centerHorizontal="true"
android:layout_below="@+id/btn_live"/>
+
+
diff --git a/app/src/main/res/layout/activity_video_reverse.xml b/app/src/main/res/layout/activity_video_reverse.xml
new file mode 100644
index 0000000..70ddf02
--- /dev/null
+++ b/app/src/main/res/layout/activity_video_reverse.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gif/reverse.gif b/gif/reverse.gif
new file mode 100644
index 0000000..1802ac5
Binary files /dev/null and b/gif/reverse.gif differ