1. 程式人生 > >最簡單的基於FFmpeg的移動端例子:Android 視訊轉碼器

最簡單的基於FFmpeg的移動端例子:Android 視訊轉碼器

=====================================================

最簡單的基於FFmpeg的移動端例子系列文章列表:

=====================================================


本文記錄一個安卓平臺下基於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
 * 
[email protected]
* 馬小雨 Ma Xiaoyu * [email protected] * 中國傳媒大學/數字電視技術 * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * * 本程式是安卓平臺下的轉碼器。它移植於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 { @Override protected 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"); } @Override public 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.c
cmdutils.h
cmdutils_common_opts.h
config.h
ffmpeg.h
ffmpeg_filter.c
ffmpeg_opt.c

在編譯ffmpeg.c的時候,除了需要FFmpeg SDK中的標頭檔案之外,還需要從原始碼中拷貝下面標頭檔案。

libavformat/ffm.h
libavformat/network.h
libavformat/os_support.h
libavformat/url.h
libavutil/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
 * [email protected]
 * 馬小雨  Ma Xiaoyu
 * [email protected]
 * 中國傳媒大學/數字電視技術
 * Communication University of China / Digital TV Technology
 * http://blog.csdn.net/leixiaohua1020
 *
 *
 * 本程式是安卓平臺下的轉碼器。它移植於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__)
#endif


int 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 file

	FILE *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;

}

Android.mk檔案位於jni/Android.mk,如下所示。

# Android.mk for FFmpeg
#
# Lei Xiaohua 雷霄驊
# [email protected]
# http://blog.csdn.net/leixiaohua1020
# 

LOCAL_PATH := $(call my-dir)

# FFmpeg library
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := libavcodec-56.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := avdevice
LOCAL_SRC_FILES := libavdevice-56.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := avfilter
LOCAL_SRC_FILES := libavfilter-5.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := avformat
LOCAL_SRC_FILES := libavformat-56.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := avutil
LOCAL_SRC_FILES := libavutil-54.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := postproc
LOCAL_SRC_FILES := libpostproc-53.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := swresample
LOCAL_SRC_FILES := libswresample-1.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := swscale
LOCAL_SRC_FILES := libswscale-3.so
include $(PREBUILT_SHARED_LIBRARY)

# Program
include $(CLEAR_VARS)
LOCAL_MODULE := sfftranscoder
LOCAL_SRC_FILES :=ffmpeg_jni.c ffmpeg_mod.c ffmpeg_opt.c ffmpeg_filter.c cmdutils.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale
include $(BUILD_SHARED_LIBRARY)

執行結果

App在手機上執行後的結果如下圖所示。


注意需要把等待轉碼的視訊檔案拷貝至儲存卡相應的目錄中。例如對於上述截圖的情況,需要將sintel.mp4拷貝至儲存卡的根目錄中。

單擊“Start”按鈕開始轉碼,將儲存卡中的sintel.mp4轉碼為sintel.mkv。



下載


simplest ffmpeg mobile

專案主頁

CSDN工程下載地址:http://download.csdn.net/detail/leixiaohua1020/8924391
本解決方案包含了使用FFmpeg在移動端處理多媒體的各種例子:
[Android]
simplest_android_player: 基於安卓介面的視訊播放器
simplest_ffmpeg_android_helloworld: 安卓平臺下基於FFmpeg的HelloWorld程式
simplest_ffmpeg_android_decoder: 安卓平臺下最簡單的基於FFmpeg的視訊解碼器
simplest_ffmpeg_android_decoder_onelib: 安卓平臺下最簡單的基於FFmpeg的視訊解碼器-單庫版
simplest_ffmpeg_android_streamer: 安卓平臺下最簡單的基於FFmpeg的推流器
simplest_ffmpeg_android_transcoder: 安卓平臺下移植的FFmpeg命令列工具
simplest_sdl_android_helloworld: 移植SDL到安卓平臺的最簡單程式
[IOS]
simplest_ios_player: 基於IOS介面的視訊播放器
simplest_ffmpeg_ios_helloworld: IOS平臺下基於FFmpeg的HelloWorld程式
simplest_ffmpeg_ios_decoder: IOS平臺下最簡單的基於FFmpeg的視訊解碼器
simplest_ffmpeg_ios_streamer: IOS平臺下最簡單的基於FFmpeg的推流器
simplest_ffmpeg_ios_transcoder: IOS平臺下移植的ffmpeg.c命令列工具
simplest_sdl_ios_helloworld: 移植SDL到IOS平臺的最簡單程式

相關推薦

簡單基於FFmpeg移動例子Android 視訊

=====================================================最簡單的基於FFmpeg的移動端例子系列文章列表:=====================================================本文記錄一個安

簡單基於FFmpeg移動例子IOS HelloWorld

=====================================================最簡單的基於FFmpeg的移動端例子系列文章列表:=====================================================本文記錄IOS

用java做一個簡單視訊

用java做一個視訊轉碼器 本Markdown編輯器使用[StackEdit][6]修改而來,用它寫部落格,將會帶來全新的體驗哦: 用java做一個視訊轉碼器,首先實現視訊格式轉換,需要用到兩個軟體”ffmpeg”和”mencoder”話不多說,直接上程式碼

簡單基於FFmpeg移動例子附件SDL Android HelloWorld

=====================================================最簡單的基於FFmpeg的移動端例子系列文章列表:=====================================================本文記錄一個安

簡單基於FFmpeg移動例子附件Android 自帶播放

=====================================================最簡單的基於FFmpeg的移動端例子系列文章列表:=====================================================前幾篇文章記錄

簡單基於FFmpeg的AVfilter例子(水印疊加

                =====================================================最簡單的基於FFmpeg的AVfilter例子系列文章:=====================================================FFMPE

簡單基於FFmpeg的AVDevice例子 讀取攝像頭

                =====================================================最簡單的基於FFmpeg的AVDevice例子文章列表:最簡單的基於FFmpeg的AVDevice例子(螢幕錄製)=============================

簡單基於FFmpeg的AVDevice例子(讀取攝像頭)解讀

本文轉載自最簡單的基於FFmpeg的AVDevice例子(讀取攝像頭) 在此基礎上對程式的流程進行解讀,閱讀前請先閱讀原文。 ============================= /** * 最簡單的基於FFmpeg的AVDevice例子(讀取攝像頭) * Simplest F

簡單基於FFmpeg的封裝格式處理 視音訊複用 muxer

                =====================================================最簡單的基於FFmpeg的封裝格式處理系列文章列表:=====================================================簡介打算記錄一

簡單基於FFmpeg的libswscale的示例(YUVRGB)

=====================================================最簡單的基於FFmpeg的libswscale的示例系列文章列表:====================================================

ffmpeg簡單的解碼保存YUV數據 <>

context 陣列 log fop content const www. += fopen video的raw data一般都是YUV420p的格式,簡單的記錄下這個格式的細節,如有不對希望大家能指出。 YUV圖像通常有兩種格式,一種是packet 還有一種是plan

移動頁面viewport與分辨率的坑

效果 span idt 分辨 name col 移動端 use init <meta name="viewport" content="width=device-width, user-scalable=no"> <meta name=‘

[]Netty入門(簡單的Netty客戶/服務程序)

serve exc new final 綁定 title graceful 關閉連接 listener  Java中的NIO是一種解決阻塞式IO問題的基本技術,但是NIO的編寫對java程序員是有比較高的要求的。那麽Netty就是一種簡化操作的一個成熟的網絡IO編程框架。這

vue2 + iview-admin 1.3 + django 2.0 一個簡單的增刪改查例子

iview-admin axios django 前後端分離 api 以下為利用iview-admin + django 做的一個最基本的增刪改查例子。 前端iview-admin git clone https://github.com/iview/iview-admin.git cd

基於VUE移動UI好用框架

1. vonic 一個基於 vue.js 和 ionic 樣式的 UI 框架,用於快速構建移動端單頁應用,很簡約,是我喜歡的風格 star 2.3k 中文文件 線上預覽 2.vux 基於WeUI和Vue(2.x)開發的移動端UI元件庫 star 10k 基於webpack+vue-loader+v

分享幾個簡單的bat指令碼的例子

兩個小時後自動關機 echo off shutdown /s /t 7200 進入C盤一個資料夾執行一個程式,接收使用者兩個輸入,一個是百度文庫某一個文件的連結,一個是該文件的型別,然後根據該程式執行的規則:FreeForWenku.exe + URL + 型

MongoDB簡單的入門教程之四使用Spring Boot操作MongoDB

Spring Boot 是一個輕量級框架,可以完成基於 Spring 的應用程式的大部分配置工作。Spring Boot的目的是提供一組工具,以便快速構建容易配置的Spring應用程式,省去大量傳統Spring專案的繁瑣配置。 MongoDB是一個基於分散式檔

基於vue移動UI框架

1.vux 基於WeUI和Vue(2.x)開發的移動端UI元件庫 基於webpack+vue-loader+vux可以快速開發移動端頁面,配合vux-loader方便你在WeUI的基礎上定製需要的樣式。 中文文件 線上預覽 特性 star數最多 這可能跟

移動網頁給body設定 overflowhidden 無效的解決辦法

做移動端網頁的時候,總會遇到一些奇葩的問題,在PC端瀏覽器做模擬除錯時,都是完美顯示的,但是一到真機除錯就是各種坑; 我在做移動端網頁時的需求是這樣的: 頁面背景圖片是自適應螢幕大小的,頁面上有輸入框和按鈕,當點選輸入框時,移動端的軟鍵盤彈出,但是背景圖片不能受影響而被壓縮,且頁面不能應為軟

史上簡單的 SpringCloud 教程 | 第一篇 服務的註冊與發現(Eureka)

一、spring cloud簡介 spring cloud 為開發人員提供了快速構建分散式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理