From 7693db54c4b234186ddee221d9a57fa113513f9a Mon Sep 17 00:00:00 2001 From: xufulong <839789740@qq.com> Date: Wed, 12 Sep 2018 01:19:14 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=86=E9=A2=91=E5=8F=8D=E5=BA=8F=E5=80=92?= =?UTF-8?q?=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 视频反序倒播 --- README.md | 6 +- app/src/main/AndroidManifest.xml | 27 ++-- .../frank/ffmpeg/activity/MainActivity.java | 4 + .../ffmpeg/activity/VideoReverseActivity.java | 118 ++++++++++++++++++ .../java/com/frank/ffmpeg/util/FileUtil.java | 16 +++ app/src/main/res/layout/activity_main.xml | 11 +- .../res/layout/activity_video_reverse.xml | 44 +++++++ gif/reverse.gif | Bin 0 -> 1823890 bytes 8 files changed, 213 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/com/frank/ffmpeg/activity/VideoReverseActivity.java create mode 100644 app/src/main/res/layout/activity_video_reverse.xml create mode 100644 gif/reverse.gif 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"/> +