采用FFmpeg实现视频倒播

最近发现抖音特效里有视频倒播,看起来比较酷。于是自己用FFmpeg在Android平台做了一遍,现在方案是先用FFmpeg把视频反序,再进行视频倒放。最终效果长这样:

主要用到的是FFmpeg的filter_complex来实现,拼接命令行:

    /**
     * 视频反序倒播
     * @param inputFile 输入文件
     * @param targetFile 反序文件
     *
     * @return 视频反序的命令行
     */
    public static  String[] reverseVideo(String inputFile, String targetFile){
        String reverseVideo = "ffmpeg -i %s -filter_complex [0:v]reverse[v] -map [v] %s";
        reverseVideo = String.format(reverseVideo, inputFile, targetFile);
        return reverseVideo.split(" ");
    }

执行FFmpeg命令行:

    /**
     * 执行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);
            }
        });
    }

开启子线程在JNI层执行FFmpeg命令行:

    //开子线程调用native方法进行音视频处理
    public static void execute(final String[] commands, final OnHandleListener onHandleListener){
        new Thread(new Runnable() {
            @Override
            public void run() {
                if(onHandleListener != null){
                    onHandleListener.onBegin();
                }
                //调用ffmpeg进行处理
                int result = handle(commands);
                if(onHandleListener != null){
                    onHandleListener.onEnd(result);
                }
            }
        }).start();
    }
    private native static int handle(String[] commands);

最终是在JNI层调用ffmpeg.c源码执行FFmpeg命令行:

JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_FFmpegCmd_handle
(JNIEnv *env, jclass obj, jobjectArray commands){
    int argc = (*env)->GetArrayLength(env, commands);
    char **argv = (char**)malloc(argc * sizeof(char*));
    int i;
    int result;
    for (i = 0; i < argc; i++) {
        jstring jstr = (jstring) (*env)->GetObjectArrayElement(env, commands, i);
        char* temp = (char*) (*env)->GetStringUTFChars(env, jstr, 0);
        argv[i] = malloc(1024);
        strcpy(argv[i], temp);
        (*env)->ReleaseStringUTFChars(env, jstr, temp);
    }
    //执行ffmpeg命令
    result =  run(argc, argv);
    //释放内存
    for (i = 0; i < argc; i++) {
        free(argv[i]);
    }
    free(argv);
    return result;
}

等待视频反序处理完毕,使用VideoView开始播放。不够完美的是需要等待,如果能做到在线倒播那就好了。视频的在线倒播就是从最后一帧反序播放,需要解决的问题是I帧、P帧解码时间,甚至还有B帧。后续有待研究......

相关源码Git地址:https://github.com/xufuji456/FFmpegAndroid

你可能感兴趣的:(android开发,音视频开发)