视频反序倒播

视频反序倒播
pull/107/head
xufulong 6 years ago
parent 72a0760592
commit 7693db54c4
  1. 6
      README.md
  2. 27
      app/src/main/AndroidManifest.xml
  3. 4
      app/src/main/java/com/frank/ffmpeg/activity/MainActivity.java
  4. 118
      app/src/main/java/com/frank/ffmpeg/activity/VideoReverseActivity.java
  5. 16
      app/src/main/java/com/frank/ffmpeg/util/FileUtil.java
  6. 11
      app/src/main/res/layout/activity_main.xml
  7. 44
      app/src/main/res/layout/activity_video_reverse.xml
  8. BIN
      gif/reverse.gif

@ -18,6 +18,7 @@ android端基于FFmpeg库的使用。<br>
- #### 视频转GIF动图 - #### 视频转GIF动图
- #### 视频添加水印 - #### 视频添加水印
- #### 视频画面拼接 - #### 视频画面拼接
- #### 视频反序倒播
- #### 图片合成视频 - #### 图片合成视频
- #### 视频解码播放 - #### 视频解码播放
- #### 本地直播推流 - #### 本地直播推流
@ -52,7 +53,10 @@ android端基于FFmpeg库的使用。<br>
![静态图片](https://github.com/xufuji456/FFmpegAndroid/blob/master/picture/filter_grid.png) ![静态图片](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)
*** ***

@ -36,26 +36,31 @@
<!-- 视频解码播放 --> <!-- 视频解码播放 -->
<activity <activity
android:name=".activity.VideoPlayerActivity" android:name=".activity.VideoPlayerActivity"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" android:screenOrientation="landscape"
android:screenOrientation="landscape" /> android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
<!-- 音视频解码播放 --> <!-- 音视频解码播放 -->
<activity <activity
android:name=".activity.MediaPlayerActivity" android:name=".activity.MediaPlayerActivity"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" android:screenOrientation="landscape"
android:screenOrientation="landscape" /> android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
<!-- 本地推流直播 --> <!-- 本地推流直播 -->
<activity android:name=".activity.PushActivity" <activity
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar"/> android:name=".activity.PushActivity"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
<!-- 实时推流直播 --> <!-- 实时推流直播 -->
<activity <activity
android:name=".activity.LiveActivity" android:name=".activity.LiveActivity"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" android:screenOrientation="landscape"
android:screenOrientation="landscape" /> android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
<!--滤镜特效--> <!-- 滤镜特效 -->
<activity <activity
android:name=".activity.FilterActivity" android:name=".activity.FilterActivity"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" android:screenOrientation="landscape"
android:screenOrientation="landscape" /> android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
<!--视频倒播-->
<activity android:name=".activity.VideoReverseActivity"
android:screenOrientation="landscape"
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar" />
</application> </application>
</manifest> </manifest>

@ -38,6 +38,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
findViewById(R.id.btn_push).setOnClickListener(this); findViewById(R.id.btn_push).setOnClickListener(this);
findViewById(R.id.btn_live).setOnClickListener(this); findViewById(R.id.btn_live).setOnClickListener(this);
findViewById(R.id.btn_filter).setOnClickListener(this); findViewById(R.id.btn_filter).setOnClickListener(this);
findViewById(R.id.btn_reverse).setOnClickListener(this);
} }
@Override @Override
@ -65,6 +66,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case R.id.btn_filter://滤镜特效 case R.id.btn_filter://滤镜特效
intent.setClass(MainActivity.this, FilterActivity.class); intent.setClass(MainActivity.this, FilterActivity.class);
break; break;
case R.id.btn_reverse://视频倒播
intent.setClass(MainActivity.this, VideoReverseActivity.class);
break;
default: default:
break; break;
} }

@ -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);
}
}

@ -66,4 +66,20 @@ public class FileUtil {
return true; 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;
}
} }

@ -7,7 +7,7 @@
android:id="@+id/btn_audio" android:id="@+id/btn_audio"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="80dp" android:layout_marginTop="10dp"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:text="@string/audio_handle"/> android:text="@string/audio_handle"/>
@ -65,4 +65,13 @@
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_below="@+id/btn_live"/> android:layout_below="@+id/btn_live"/>
<Button
android:id="@+id/btn_reverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/video_reverse"
android:layout_marginTop="10dp"
android:layout_centerHorizontal="true"
android:layout_below="@+id/btn_filter"/>
</RelativeLayout> </RelativeLayout>

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.frank.ffmpeg.activity.VideoReverseActivity"
android:orientation="horizontal">
<VideoView
android:id="@+id/video_normal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="10dp"
android:visibility="invisible"/>
<LinearLayout
android:id="@+id/layout_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="视频转换中..."
android:textColor="@color/colorPrimary"
android:textSize="18dp"/>
</LinearLayout>
<VideoView
android:id="@+id/video_reverse"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="10dp"
android:visibility="invisible"/>
</LinearLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Loading…
Cancel
Save