音视频实践学习

  • android全平台编译ffmpeg以及x264与fdk-aac实践
  • ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器
  • android全平台编译ffmpeg合并为单个库实践
  • android-studio使用cmake编译ffmpeg实践
  • android全平台编译ffmpeg视频解码器实践
  • android全平台编译ffmpeg支持命令行实践
  • android全平台编译ffmpeg视频推流实践
  • android平台下音频编码之编译LAME库转码PCM为MP3
  • ubuntu平台下编译vlc-android视频播放器实践
  • 图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别
  • 图解RGB565、RGB555、RGB16、RGB24、RGB32、ARGB32等格式的区别
  • YUV420P、YUV420SP、NV12、NV21和RGB互相转换并存储为JPEG以及PNG图片
  • android全平台编译libyuv库实现YUV和RGB的转换

本例基于 android全平台编译ffmpeg合并为单个库实践 进行的

目录

  • 环境准备
  • 新建cmd工程
  • 修改源文件
  • 运行输出

环境准备

操作系统 ubuntu 16.05

编译准备好libffmpeg库和需要include头文件,我们还需要抽取ffmpeg-3.3.8中的部分头文件和源文件

笔者整理了一个copy_ffmpeg_files.sh脚本

FFMPEG_DIR=ffmpeg-3.3.8mkdir includemkdir include/compatmkdir include/libavcodecmkdir include/libavformatmkdir include/libavutilmkdir include/libavdevicemkdir include/libpostproccp $FFMPEG_DIR/compat/va_copy.h include/compat/va_copy.hcp $FFMPEG_DIR/libavcodec/mathops.h include/libavcodec/mathops.hcp $FFMPEG_DIR/libavdevice/avdevice.h include/libavdevice/avdevice.hcp $FFMPEG_DIR/libavdevice/version.h include/libavdevice/version.hcp $FFMPEG_DIR/libavformat/ffm.h include/libavformat/ffm.hcp $FFMPEG_DIR/libavformat/network.h include/libavformat/network.hcp $FFMPEG_DIR/libavformat/os_support.h include/libavformat/os_support.hcp $FFMPEG_DIR/libavformat/url.h include/libavformat/url.hcp $FFMPEG_DIR/libavutil/libm.h include/libavutil/libm.hcp $FFMPEG_DIR/libavutil/internal.h include/libavutil/internal.hcp $FFMPEG_DIR/libavutil/reverse.h include/libavutil/reverse.hcp $FFMPEG_DIR/libavutil/timer.h include/libavutil/timer.hcp $FFMPEG_DIR/libpostproc/postprocess.h include/libpostproc/postprocess.hcp $FFMPEG_DIR/libpostproc/version.h include/libpostproc/version.h#cppmkdir cppcp $FFMPEG_DIR/cmdutils.c cpp/cmdutils.ccp $FFMPEG_DIR/cmdutils.h cpp/cmdutils.hcp $FFMPEG_DIR/cmdutils_common_opts.h cpp/cmdutils_common_opts.h#cp $FFMPEG_DIR/config.h cpp/config.hcp $FFMPEG_DIR/ffmpeg.h cpp/ffmpeg.hcp $FFMPEG_DIR/ffmpeg.c cpp/ffmpeg_mod.ccp $FFMPEG_DIR/ffmpeg_filter.c cpp/ffmpeg_filter.ccp $FFMPEG_DIR/ffmpeg_opt.c cpp/ffmpeg_opt.c
  • 文件目录结构如下:

android全平台编译ffmpeg支持命令行实践_第1张图片

将生成之后的include文件夹覆盖到项目中的include目录
本例中即覆盖到ffmpeg-single组件下的libs/armeabi-v7ainclude目录

新建ffmpeg-single-cmd工程

android全平台编译ffmpeg支持命令行实践_第2张图片

将生成的cpp目录复制到src/main目录下

  • 新建FFmpegCmd类
public class FFmpegCmd {    static {        System.loadLibrary("ffmpeg");        System.loadLibrary("ffmpeg-cmd");    }    public native int exec(int argc, String[] argv);}
  • 新建ffmpeg_cmd.c文件
#include <jni.h>#include <stdio.h>#include <time.h>#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"#include "libavfilter/avfilter.h"#include "libavutil/log.h"#ifdef ANDROID#include <android/log.h>#define LOG_TAG    "HelloFFmpeg"#define LOGE(format, ...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, format, ##__VA_ARGS__)#define LOGI(format, ...)  __android_log_print(ANDROID_LOG_INFO,  LOG_TAG, format, ##__VA_ARGS__)#else#define LOGE(format, ...)  printf(LOG_TAG format "\n", ##__VA_ARGS__)#define LOGI(format, ...)  printf(LOG_TAG format "\n", ##__VA_ARGS__)#endifint exec(int argc, char **argv);void custom_log(void *ptr, int level, const char *fmt, va_list vl) {    FILE *fp=fopen("/storage/emulated/0/Android/data/com.onzhou.ffmpeg.cmd/files/av_log.txt""a+");    if(fp){        vfprintf(fp,fmt,vl);        fflush(fp);        fclose(fp);    }}JNIEXPORT jint JNICALL Java_com_onzhou_ffmpeg_cmd_FFmpegCmd_exec        (JNIEnv *env, jobject obj, jint cmdnum, jobjectArray cmdline) {    av_log_set_callback(custom_log);    int argc = cmdnum;    char **argv = (char **) malloc(sizeof(char *) * argc);    int i = 0;    for (i = 0; i < argc; i++) {        jstring string = (*env)->GetObjectArrayElement(env, cmdline, i);        const char *tmp = (*env)->GetStringUTFChars(env, string, 0);        argv[i] = (char *) malloc(sizeof(char) * 1024);        strcpy(argv[i], tmp);    }    exec(argc, argv);    for (i = 0; i < argc; i++) {        free(argv[i]);    }    free(argv);    return 0;}
  • 新建ffmpeg_cmd.h头文件
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_onzhou_ffmpeg_cmd_FFmpegCmd */#ifndef _Included_com_onzhou_ffmpeg_cmd_FFmpegCmd#define _Included_com_onzhou_ffmpeg_cmd_FFmpegCmd#ifdef __cplusplusextern "C" {#endif/* * Class:     com_onzhou_ffmpeg_cmd_FFmpegCmd * Method:    exec * Signature: (I[Ljava/lang/String;)V */JNIEXPORT jint JNICALL Java_com_onzhou_ffmpeg_cmd_FFmpegCmd_exec        (JNIEnv *, jobject, jint, jobjectArray);#ifdef __cplusplus}#endif#endif

build.gradle中的配置不多说了,可以参考之前的实践配置

  • 配置CMakeLists.txt文件
cmake_minimum_required(VERSION 3.4.1)add_library(ffmpeg-cmd           SHARED           src/main/cpp/ffmpeg_cmd.c           src/main/cpp/cmdutils.c           src/main/cpp/ffmpeg_filter.c           src/main/cpp/ffmpeg_opt.c           src/main/cpp/ffmpeg_mod.c)find_library(log-lib            log)#获取上级目录get_filename_component(PARENT_DIR ${CMAKE_SOURCE_DIR} PATH)set(LIBRARY_DIR ${PARENT_DIR}/ffmpeg-single)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")set(CMAKE_VERBOSE_MAKEFILE on)add_library(ffmpeg-single           SHARED           IMPORTED)set_target_properties(ffmpeg-single                    PROPERTIES IMPORTED_LOCATION                    ${LIBRARY_DIR}/libs/${ANDROID_ABI}/libffmpeg.so                    )#头文件include_directories(${LIBRARY_DIR}/libs/${ANDROID_ABI}/include src/main/cpp)target_link_libraries(ffmpeg-cmd ffmpeg-single ${log-lib})

修改源文件

  • 修改cmdutils.c文件
void exit_program(int ret){    if (program_exit)        program_exit(ret);    exit(ret);}

#改为

int exit_program(int ret){    if (program_exit)        program_exit(ret);    //exit(ret);    return ret;}
  • 修改cmdutils.h头文件
void exit_program(int ret) av_noreturn;

#改为

int exit_program(int ret) av_noreturn;
  • 修改ffmpeg_mod.c文件
int main(int argc, char **argv)

#改为

int exec(int argc, char **argv)

return main_return_code;之前加上如下代码:

nb_filtergraphs = 0;progress_avio = NULL;input_streams = NULL;nb_input_streams = 0;input_files = NULL;nb_input_files = 0;output_streams = NULL;nb_output_streams = 0;output_files = NULL;nb_output_files = 0;
  • 测试执行命令行进行转码
public void onCmdClick(View view) {    if (fFmpegCmd == null) {        fFmpegCmd = new FFmpegCmd();    }    btnTransfer.setEnabled(false);    File outputFile = new File(getExternalFilesDir(null)"output.mkv");    if (outputFile.exists()) {        outputFile.delete();    }    Schedulers.newThread().scheduleDirect(new Runnable() {        @Override        public void run() {            String filePath = getExternalFilesDir(null).getAbsolutePath();            String cmdline = String.format("ffmpeg -i %s/input.mp4 %s/output.mkv", filePath, filePath);            String[] argv = cmdline.split(" ");            Integer argc = argv.length;            fFmpegCmd.exec(argc, argv);        }    });}

运行输出

android全平台编译ffmpeg支持命令行实践_第3张图片

项目地址
https://github.com/byhook/ffmpeg4android

参考雷神:
https://blog.csdn.net/leixiaohua1020/article/details/47056365

更多相关文章

  1. Android 平台简介
  2. Visual Studio 跨平台开发实战(4) - Xamarin Android 基本控制项
  3. android中编译资源文件的相关问题
  4. moodle手机版在android平台上的安装配置
  5. 写TextView的Selector了解到的android读取xml文件的几点规则
  6. android私有目录直接读取
  7. Android基础知识之Manifest文件的组织结构
  8. android中一些配置文件的参数的意义

随机推荐

  1. Android(安卓)GWES之窗口管理之基本构架
  2. Android——《Android第一行代码》中使用
  3. 集成第三方库到android程序方法
  4. listView的item中有checkbox,导致setOnIte
  5. Android之基于BaseAdapter和SimpleAdapte
  6. Android 菜单(OptionMenu)大全 建立你自
  7. 【Android】 导入项目报错的解决方案
  8. apk多渠道自动打包
  9. Android零碎知识
  10. Android中ListView.getCount()与ListView