Android初探FFmpeg(1)--在Windows下编译FFmpeg

之前在博客中提到视频的裁剪和合并功能,用的是FFmpeg这块的东西,由于是从网上直接拔过来的东西,虽然功能算是实现了,但是心里总是感觉怪怪的,毕竟没有自己动手!自己也讨厌“伸手主义”,加之最近项目不是特别紧张,就自己动手编译了一遍,并在各种各样异常的情况下,总算在Android studio下跑成功了!本来打算把一些知识点再挖深一点,但是最近项目可能要迭代新版本,所以怕是要小忙一阵!为了避免把之前的忘了,所以还是需要草草的记录一下!下面开始。

准备环境:
VMware workstation 12 player
最新版下载地址:
https://my.vmware.com/cn/web/vmware/free#desktop_end_user_computing/vmware_workstation_player/12_0

Ubuntu 64(我存一份到我的云盘中了,大家可以到那下载)
下载地址:
http://pan.baidu.com/s/1bp8JG2j

安装完后打开界面如下:

这里写图片描述

OK,到这,就可以开始准备工作了!

由于之前家里的电脑也没下载NDK和FFmpeg,所以,我就打算在这个工作区间直接下载了(说到底是不会VMware的共享文件(大家可以自行谷歌或者百度,有解))

最新版的NDK下载地址:
https://dl.google.com/android/repository/android-ndk-r15b-linux-x86_64.zip

最新版的FFmpeg下载地址:
http://ffmpeg.org/releases/ffmpeg-3.3.2.tar.bz2

下载完之后,就可以开始编译了!
这里,我把两个压缩包全都放在home路径下了!

这里写图片描述

点击左键Extract File,进行解压文件夹(或者用命令行进行解压,都OK)

Ctrl+Alt+F2可打开命令行
Ctrl+Alt+F7可关闭命令行

接着打开FFmpeg的文件夹,打开configure文件,修改该属性为:

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

在接着创建文件build_android.sh文件,内容为:

#!/bin/bash
cd ffmpeg
export TMPDIR=/home/tianchuangxin/ffmpeg-3.3.2
NDK=/home/tianchuangxin/android-ndk-r15b
SYSROOT=$NDK/platforms/android-16/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
CPU=arm
PREFIX=/home/tianchuangxin/ffmpeg-3.3.2/$CPU
ADDI_CFLAGS="-marm"
function build_one
{
    ./configure \
        --prefix=$PREFIX \
        --enable-shared \
        --disable-static \
        --disable-doc \
        --disable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-ffserver \
        --disable-doc \
        --disable-symver \
        --enable-small \
        --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
        --target-os=linux \
        --arch=arm \
        --enable-cross-compile \
        --sysroot=$SYSROOT \
        --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
        --extra-ldflags="$ADDI_LDFLAGS" \
        $ADDITIONAL_CONFIGURE_FLAG
    make clean
    make
    make install
}
build_one
cd ../

创建的这个文件需要注意的是,你自己需要修改一些东西:
这里写图片描述

圈出的这三处需要改成你自己的路径。
小提示:你最好先打开自己的命令行cd一下,看看能不能到这些文件路径下面,不然会一直报文件找不到的警告

接着给build_android.sh添加执行权限命令行如下:

$chmod+x build_android.sh 

接着执行.sh文件:

$./build_android.sh 

ok ,到这里,如果的你的配置都没有问题的话,已经开始生成.so文件了!

当你再打开ffmpeg的文件夹的时候多了一个文件夹 arm!

接着把arm文件夹copy出来之后开始在Android studio中测试一下咯!

在创建新的Android项目的的时候在,首页面需勾选:

这里写图片描述
接着一路next知道创建完成新的项目!

创建好新的项目,将之前的生成的arm包中的东西复制到工程下的libs文件夹下:
这里写图片描述

注意:现在是arm架构类型的CPU

接着开始配置native_lib.cpp文件,它在main目录下
这里写图片描述

#include <jni.h>
#include <string>

extern "C"
{

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>

JNIEXPORT jstring JNICALL
Java_com_example_ffmpegtest_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());

}



JNIEXPORT jstring JNICALL
    Java_com_example_ffmpegtest_MainActivity_urlprotocolinfo(
            JNIEnv *env, jobject) {
        char info[40000] = {0};
        av_register_all();

        struct URLProtocol *pup = NULL;

        struct URLProtocol **p_temp = &pup;
        avio_enum_protocols((void **) p_temp, 0);

        while ((*p_temp) != NULL) {
            sprintf(info, "%sInput: %s\n", info, avio_enum_protocols((void **) p_temp, 0));
        }
        pup = NULL;
        avio_enum_protocols((void **) p_temp, 1);
        while ((*p_temp) != NULL) {
            sprintf(info, "%sInput: %s\n", info, avio_enum_protocols((void **) p_temp, 1));
        }
        return env->NewStringUTF(info);
    }

JNIEXPORT jstring JNICALL
    Java_com_example_ffmpegtest_MainActivity_avformatinfo(
            JNIEnv *env, jobject) {
        char info[40000] = {0};

        av_register_all();

        AVInputFormat *if_temp = av_iformat_next(NULL);
        AVOutputFormat *of_temp = av_oformat_next(NULL);
        while (if_temp != NULL) {
            sprintf(info, "%sInput: %s\n", info, if_temp->name);
            if_temp = if_temp->next;
        }
        while (of_temp != NULL) {
            sprintf(info, "%sOutput: %s\n", info, of_temp->name);
            of_temp = of_temp->next;
        }
        return env->NewStringUTF(info);
    }

JNIEXPORT jstring JNICALL
    Java_com_example_ffmpegtest_MainActivity_avcodecinfo(
            JNIEnv *env, jobject) {
        char info[40000] = {0};

        av_register_all();

        AVCodec *c_temp = av_codec_next(NULL);

        while (c_temp != NULL) {
            if (c_temp->decode != NULL) {
                sprintf(info, "%sdecode:", info);
            } else {
                sprintf(info, "%sencode:", info);
            }
            switch (c_temp->type) {
                case AVMEDIA_TYPE_VIDEO:
                    sprintf(info, "%s(video):", info);
                    break;
                case AVMEDIA_TYPE_AUDIO:
                    sprintf(info, "%s(audio):", info);
                    break;
                default:
                    sprintf(info, "%s(other):", info);
                    break;
            }
            sprintf(info, "%s[%10s]\n", info, c_temp->name);
            c_temp = c_temp->next;
        }

        return env->NewStringUTF(info);
    }

JNIEXPORT jstring JNICALL
    Java_com_example_ffmpegtest_MainActivity_avfilterinfo(
            JNIEnv *env, jobject) {
        char info[40000] = {0};
        avfilter_register_all();

        AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
        while(f_temp != NULL) {
            sprintf(info, "%s%s\n", info, f_temp->name);
            f_temp = f_temp->next;
        }
        return env->NewStringUTF(info);
    }
}

注意的是native的写法,你的函数名称可能跟我的不太一样哦!

接着配置CMakeLists.txt文件:

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

find_library( # Sets the name of the path variable.
             log-lib

             # Specifies the name of the NDK library that
             # you want CMake to locate.
             log )

set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)

add_library( avutil-55
            SHARED
            IMPORTED )
set_target_properties( avutil-55
             PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libavutil-55.so )

add_library( swresample-2
             SHARED
             IMPORTED )
set_target_properties( swresample-2
             PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libswresample-2.so )
add_library( avcodec-57
             SHARED
             IMPORTED )
set_target_properties( avcodec-57
             PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libavcodec-57.so )
add_library( avfilter-6
             SHARED
             IMPORTED)
set_target_properties( avfilter-6
             PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libavfilter-6.so )
add_library( swscale-4
            SHARED
             IMPORTED)
set_target_properties( swscale-4
            PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libswscale-4.so )
add_library( avdevice-57
            SHARED
            IMPORTED)
set_target_properties( avdevice-57
            PROPERTIES IMPORTED_LOCATION
            ../../../../libs/armeabi-v7a/libavdevice-57.so )
add_library( avformat-57
            SHARED
            IMPORTED)
set_target_properties( avformat-57
            PROPERTIES IMPORTED_LOCATION
             ../../../../libs/armeabi-v7a/libavformat-57.so )

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

add_library( native-lib
            SHARED
             src/main/cpp/native-lib.cpp )

include_directories(libs/include)

             #target_include_directories(native-lib PRIVATE libs/include)

target_link_libraries( native-lib swresample-2 avcodec-57 avfilter-6 swscale-4 avdevice-57 avformat-57
             ${log-lib} )

接着是build.gradle的文件配置:

这里写图片描述

这里写图片描述

这两个千万别忘了,不然就跑不起来了!

哈哈,到这基本就完了!

这是跑出来的结果图:

这里写图片描述

文章参考:
http://blog.csdn.net/gobitan/article/details/22750719
http://blog.csdn.net/eastmoon502136/article/details/52806640
感谢作者的无私技术分享!

如有问题请指正,共同进步,谢谢!

每天进步一点点,时间会让你成为巨人!加油!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值