最简单的基于FFmpeg的移动端例子:Android 视频转码器

本文记录一个安卓平台下基于FFmpeg的视频转码器。该转码器实际上移植自ffmpeg工程中的ffmpeg.c源代码。有关ffmpeg.c的源代码可以参考文章《ffmpeg.c函数结构简单分析(画图)》,在这里就不重复记录了。源代码

项目的目录结构如图所示。Java源代码位于src目录,而C代码位于jni目录。

Android程序Java端代码位于src\com\leixiaohua1020\sffmpegandroidtranscoder\MainActivity.java,如下所示。/** * 最简单的基于FFmpeg的转码器-安卓 * Simplest FFmpeg Android Transcoder * * 雷霄骅 Lei Xiaohua * leixiaohua1020@126.com * 马小雨 Ma Xiaoyu * maxiaoyucuc@163.com * 中国传媒大学/数字电视技术 * Communication University of China / Digital TV Technology * * * * 本程序是安卓平台下的转码器。它移植于ffmpeg.c命令行工具。 * * This software is a Transcoder in Android. * It is transplanted from ffmpeg.c command line tools. * */package com.leixiaohua1020.sffmpegandroidtranscoder;import android.os.Bundle;import android.os.Environment;import android.app.Activity;import android.util.Log;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final EditText cmdEdittext= (EditText) this.findViewById(R.id.editText_cmd);Button startButton= (Button) this.findViewById(R.id.button_start);startButton.setOnClickListener(new OnClickListener() {public void onClick(View arg0){String cmdline=cmdEdittext.getText().toString();String[] argv=cmdline.split(" ");Integer argc=argv.length;ffmpegcore(argc,argv);}});}public native int ffmpegcore(int argc,String[] argv);static{System.loadLibrary("avutil-54");System.loadLibrary("swresample-1");System.loadLibrary("avcodec-56");System.loadLibrary("avformat-56");System.loadLibrary("swscale-3");System.loadLibrary("postproc-53");System.loadLibrary("avfilter-5");System.loadLibrary("avdevice-56");System.loadLibrary("sfftranscoder");}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}}C语言端源代码包含多个文件。其中下面文件拷贝自FFmpeg源代码:cmdutils.ccmdutils.hcmdutils_common_opts.hconfig.hffmpeg.hffmpeg_filter.cffmpeg_opt.c

在编译ffmpeg.c的时候,除了需要FFmpeg SDK中的头文件之外,还需要从源代码中拷贝下面头文件。

libavformat/ffm.hlibavformat/network.hlibavformat/os_support.hlibavformat/url.hlibavutil/libm.h

ffmpeg_mod.c是修改后的ffmpeg.c文件。ffmpeg.c本身是用于命令行使用的程序,因此在改为类库调用的时候需要对源代码做一些修改。例如去掉一些exit(0),释放一些变量,main()函数改名为ffmpegmain()等。

ffmpeg_jni.c是ffmpeg.c和Android系统之间的接口。该部分的源代码如下所示。

/** * 最简单的基于FFmpeg的转码器-安卓 * Simplest FFmpeg Android Transcoder * * 雷霄骅 Lei Xiaohua * leixiaohua1020@126.com * 马小雨 Ma Xiaoyu * maxiaoyucuc@163.com * 中国传媒大学/数字电视技术 * Communication University of China / Digital TV Technology * * * * 本程序是安卓平台下的转码器。它移植于ffmpeg.c命令行工具。 * * This software is a Transcoder in Android. * It is transplanted from ffmpeg.c command line tools. * */#include <string.h>#include <jni.h>#include <ffmpeg.h>#ifdef ANDROID#include <jni.h>#include <android/log.h>#define LOGE(format, …) __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)#define LOGI(format, …) __android_log_print(ANDROID_LOG_INFO, "(^_^)", format, ##__VA_ARGS__)#else#define LOGE(format, …) printf("(>_<) " format "\n", ##__VA_ARGS__)#define LOGI(format, …) printf("(^_^) " format "\n", ##__VA_ARGS__)#endifint ffmpegmain(int argc, char **argv);//Output FFmpeg’s av_log()void custom_log(void *ptr, int level, const char* fmt, va_list vl){//To TXT fileFILE *fp=fopen("/storage/emulated/0/av_log.txt","a+");if(fp){vfprintf(fp,fmt,vl);fflush(fp);fclose(fp);}//To Logcat//LOGE(fmt, vl);}JNIEXPORT jint JNICALL Java_com_leixiaohua1020_sffmpegandroidtranscoder_MainActivity_ffmpegcore( JNIEnv * env, jobject thiz, jint cmdnum, jobjectArray cmdline){ //FFmpeg av_log() callback 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); }ffmpegmain(argc,argv); for(i=0;i<argc;i++){free(argv[i]); } free(argv); return 0;}生气是拿别人做错的事来惩罚自己

最简单的基于FFmpeg的移动端例子:Android 视频转码器

相关文章:

你感兴趣的文章:

标签云: