android解碼庫
1. 在Android系統中如何調用系統自帶的視頻解碼器
對需要用FF解碼的視頻類型去掉內部解碼勾選
2.在外部解碼器中對所選視頻選擇FF解碼器即可
2. 如何在 android 設備上使用 pjsip G.729 編解碼的功能
第一步是生成 pjsip 為 Android (步驟為 Ubuntu linux) 的源代碼:
設置 ANDROID_NDK_ROOT 環境變數設置為您 NDK 根文件夾。
2.轉到 pjsip 2.x 文件夾並創建 pjlib/include/pj/config_site.h 包括 config_site_sample.h ( #include <pj/config_site_sample.h> )
3.運行./configure-android
4.運行make clean make depend make
之後這些步驟,你將有幾個靜態庫中的幾個文件夾。我建議將它們分組相同的文件夾 (最好在您的項目中) 中的:
mkdir <your_project_path>/pjsip_libs
find . -name *.a | xargs -I % cp % <your_project_path>/pjsip_libs/
一旦你的所有庫,您需要將這些庫添加到您的項目 Android.mk 文件,這是由包括一個新的模塊節每個圖書館。此模塊部分應該是一樣的東西:
include $(CLEAR_VARS)
LOCAL_MODULE := pjsua-arm-unknown-linux-androideabi
LOCAL_SRC_FILES := $(MY_PJLIB_PATH)/libpjsua-arm-unknown-linux-androideabi.a
include $(PREBUILT_STATIC_LIBRARY)
,你其實是一節中構建您的 JNI 項目的源代碼,所有模塊都添加到您的靜態庫的引用:
LOCAL_STATIC_LIBRARIES := pjsua-arm-unknown-linux-androideabi
這將包括 pjsip 的引用加入您的 JNI 庫。現在,您需要配置 pjsip UA 實例。
你有一個關於 init 和開始的解釋 pjsip 的 UA (pjsua) 在 pjsip/include/pjsua-lib/pjsua.h 但要遵循的主要步驟是:
創建一個具有 UA 實例pjsua_create
2.創建一個工作線程與pj_thread_create
3.UA 實例的設置的默認配置:
pjsua_config cfg 樁 ;pjsua_logging_config log_cfg ;pjsua_media_config media_cfg ;
pj_cli_cfg_default(app_config.cli_cfg.cfg) ;pjsua_logging_config_default(log_cfg) ;pjsua_media_config_default(media_cfg) ;
4.初始化堆棧與pjsua_init
5.啟動與堆棧pjsua_start
從這里,你有充足的配置選項 (日誌、 媒體、 交通工具等)
您可以找到基本 PJSIP 教程在這里,和裡面 pjsip 的源的根路徑,你有一個基本 (但不夠完整,基本的 SIP 使用情況) 在:pjsip-apps/src/samples/simple_pjsua.c
編輯:在生成時在 pjsip 應用程序的 android 項目,你可以面臨一個問題,因為 pjsua app 不生成默認情況下,對一般生成 (更具體地說,pjsua: 目標不包括所有上: 在 pjsip-應用程序/生成/生成文件的目標)。若要修復這只是轉到 pjsip-應用程序/創建和運行:
使 pjsua
這將創建在正確的對象文件: pjsip-apps/build/output/pjsua-arm-unknown-linux-androideabi/ (需要構建 android 樣本時)。
一旦你所有相應的對象文件,您可以在 pjsip-應用程序/src/pjsua/android 系統再次運行 ndk 生成
3. 怎樣用AACLib V1.0在Android上音頻編碼解碼
這幾天在 android上的音頻項目,順便把用到的aac編解碼庫封裝了一下,有需要的可以從上面下載。當然是沒有本事自己寫編解碼器的,還是用FFmpeg + FDK_aac來做。下面介紹一下其java介面的使用。java庫見libaac.jar文件,把libaac.jar加到 libs目錄下,把libaac.so加到 libs/armeabi目錄即可使用。
AAC編碼:
(1) 創建一個Encoder對象作為成員變數
aac.Encoder encoder;
(2) 初始化它
encoder = new aac.Encoder();
if(! encoder.open(11025, 1))
{
Log.d("mylog", "failed to open encoder !\n");
encoder = null;
}
這里要指定輸入音頻源(PCM格式)的sampe_rate和channel個數,如果為CHANNEL_OUT_MONO,則channel=1,否則為2。 sample_rate一般設置為11025,因為手機性能有限,設置太高的話也處理不過來,而且處理人聲的話11025也是足夠了。
(3) 編碼
把接收到PCM數據交給encoder來處理即可,要求輸入源為ENCODING_PCM_16BIT,即每個sample是16BIT的。這個encoder對象內有2個緩沖區:inbuf, outbuf。顯然,在編碼時,inbuf就是用於存儲接收到的PCM數據,outbuf就是存編碼後得到的數據。
int out_size = encoder.encode(in_size);
其返回值out_size,表示在outbuf里的有效數據長度。此時可以把outbuf里的aac數據通過網路發送或其他用途。
其中,用戶需要知道encoder每次處理多長的數據,即一個frame的大小。對於單聲道MONO來說,每次應該輸入2048byte的數據。對於雙聲道STEREO來說,應該輸入4096byte的數據。下面這一行可以根據聲道數來計算輸入的frame的大小:
int in_size = aac.Encoder.frameSize(1);
AAC解碼:
(1) 創建一個Decoder對象作為成員變數
aac.Decoder decoder;
(2) 初始化
decoder = new aac.Decoder();
if( ! decoder.open())
{
Log.d("mylog", "failed to open decoder !\n");
decoder = null;
}
(3) 解碼
Decoder對象也有inbuf和outbuf,把待解碼的aac frame放到inbuf里
int pcm_size = decoder.decode(aac_size);
解得到數據在outbuf里,其有效長度為上述函數的返回值pcm_size,此時可以把outbuf里的PCM數據取出來播放或其他用途。
4. 有哪些常用或優秀的 Android 第三方類庫
Android開發第三方類庫分類:
gifview 、 gifview2
這兩個項目是同一人開發的,用於顯示gif動畫,純java解碼 ,gif圖片過大會產生OOM。
android-gif-drawable
一個也是用於解碼顯示gif的類庫,採用jni解碼,大GIF也不會產生oom,完美運行。
PhotoView
PhotoView 是一款擴展自Android ImageView ,支持通過單點/多點觸摸來進行圖片縮放的智能控制項。使用比較簡單,提供了一個名為PhotoView的控制項,可以直接像普通ImageView那樣使用。
特性:支持單點/多點觸摸,即時縮放圖片;支持平滑滾動;在滑動父控制項下能夠運行良好;(例如:ViewPager)
不同的環境使用不同的類庫,不同的系統也是同樣的道理。
5. 在Android開發中有哪些支持無損音頻的第三方音頻解碼器可以使用
Android開發第三方類庫分類:gifview、gifview2這兩個項目是同一人開發的,用於顯示gif動畫,純java解碼,gif圖片過大會產生OOM。android-gif-drawable一個也是用於解碼顯示gif的類庫,採用jni解碼,大GIF也不會產生oom,完美運行。PhotoViewPhotoView是一款擴展自AndroidImageView,支持通過單點/多點觸摸來進行圖片縮放的智能控制項。使用比較簡單,提供了一個名為PhotoView的控制項,可以直接像普通ImageView那樣使用。特性:支持單點/多點觸摸,即時縮放圖片;支持平滑滾動;在滑動父控制項下能夠運行良好;(例如:ViewPager)不同的環境使用不同的類庫,不同的系統也是同樣的道理。
6. android如何使用fdk-aac編碼庫來把aac轉成pcm
線性PCM就是WAV。
AAC-LC是AAC的一個規格,你下載到或者轉換的這些高碼率的AAC都是AAC-LC的。
擴展名是.m4a。
.aac 是aac的音頻數據流,m4a是aac的一個封裝方式。其內容本身是一樣的。
我用s754,和e453功能是一樣的。m4a和wav的我都放了,沒問題,只是.aac的我還沒試過。
但我相信lz沒有.aac的。。因為這年頭你下載到的或者轉換出來的都是m4a的
7. android使用mediacodec進行編解碼 常用嗎
應該還是比較常用的。示例如下:
privatefinalStringTAG="MediaCodeSample";
/**用來解碼*/
privateMediaCodecmMediaCodec;
/**用來讀取音頻文件*/
;
privateMediaFormatformat;
privateStringmime=null;
privateintsampleRate=0,channels=0,bitrate=0;
privatelongpresentationTimeUs=0,ration=0;
publicvoiddecode(Stringurl)
{
extractor=newMediaExtractor();
//根據路徑獲取源文件
try
{
extractor.setDataSource(url);
}catch(Exceptione)
{
Log.e(TAG,"設置文件路徑錯誤"+e.getMessage());
}
try
{
//音頻文件信息
format=extractor.getTrackFormat(0);
mime=format.getString(MediaFormat.KEY_MIME);
sampleRate=format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
//聲道個數:單聲道或雙聲道
channels=format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
//ifrationis0,
ration=format.getLong(MediaFormat.KEY_DURATION);
//System.out.println("歌曲總時間秒:"+ration/1000000);
bitrate=format.getInteger(MediaFormat.KEY_BIT_RATE);
}catch(Exceptione)
{
Log.e(TAG,"音頻文件信息讀取出錯:"+e.getMessage());
//不要退出,下面進行判斷
}
Log.d(TAG,"Trackinfo:mime:"+mime+"采樣率sampleRate:"+sampleRate+"channels:"+channels+"bitrate:"
+bitrate+"ration:"+ration);
//檢查是否為音頻文件
if(format==null||!mime.startsWith("audio/"))
{
Log.e(TAG,"不是音頻文件end!");
return;
}
//實例化一個指定類型的解碼器,提供數據輸出
//
mMediaCodec=MediaCodec.createDecoderByType(mime);
if(mMediaCodec==null)
{
Log.e(TAG,"創建解碼器失敗!");
return;
}
mMediaCodec.configure(format,null,null,0);
mMediaCodec.start();
//用來存放目標文件的數據
ByteBuffer[]inputBuffers=mMediaCodec.getInputBuffers();
//解碼後的數據
ByteBuffer[]outputBuffers=mMediaCodec.getOutputBuffers();
//設置聲道類型:AudioFormat.CHANNEL_OUT_MONO單聲道,AudioFormat.CHANNEL_OUT_STEREO雙聲道
intchannelConfiguration=channels==1?AudioFormat.CHANNEL_OUT_MONO:AudioFormat.CHANNEL_OUT_STEREO;
Log.i(TAG,"channelConfiguration="+channelConfiguration);
extractor.selectTrack(0);
//==========開始解碼=============
booleansawInputEOS=false;
booleansawOutputEOS=false;
finallongkTimeOutUs=10;
MediaCodec.BufferInfoinfo=newMediaCodec.BufferInfo();
while(!sawOutputEOS)
{
try
{
if(!sawInputEOS)
{
intinputBufIndex=mMediaCodec.dequeueInputBuffer(kTimeOutUs);
if(inputBufIndex>=0)
{
ByteBufferdstBuf=inputBuffers[inputBufIndex];
intsampleSize=extractor.readSampleData(dstBuf,0);
if(sampleSize<0)
{
Log.d(TAG,"sawinputEOS.Stoppingplayback");
sawInputEOS=true;
sampleSize=0;
}else
{
presentationTimeUs=extractor.getSampleTime();
}
mMediaCodec.queueInputBuffer(inputBufIndex,0,sampleSize,presentationTimeUs,
sawInputEOS?MediaCodec.BUFFER_FLAG_END_OF_STREAM:0);
if(!sawInputEOS)
{
extractor.advance();
}
}else
{
Log.e(TAG,"inputBufIndex"+inputBufIndex);
}
}//!sawInputEOS
//
intres=mMediaCodec.dequeueOutputBuffer(info,kTimeOutUs);
if(res>=0)
{
intoutputBufIndex=res;
ByteBufferbuf=outputBuffers[outputBufIndex];
finalbyte[]chunk=newbyte[info.size];
buf.get(chunk);
buf.clear();
if(chunk.length>0)
{
//chunk解碼後的音頻流
//TODO:處理...
}
mMediaCodec.releaseOutputBuffer(outputBufIndex,false);
if((info.flags&MediaCodec.BUFFER_FLAG_END_OF_STREAM)!=0)
{
Log.d(TAG,"sawoutputEOS.");
sawOutputEOS=true;
}
}elseif(res==MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
{
outputBuffers=mMediaCodec.getOutputBuffers();
Log.w(TAG,"[AudioDecoder]outputbuffershavechanged.");
}elseif(res==MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
{
MediaFormatoformat=mMediaCodec.getOutputFormat();
Log.w(TAG,"[AudioDecoder]outputformathaschangedto"+oformat);
}else
{
Log.w(TAG,"[AudioDecoder]dequeueOutputBufferreturned"+res);
}
}catch(RuntimeExceptione)
{
Log.e(TAG,"[decodeMP3]error:"+e.getMessage());
}
}
//=================================================================================
if(mMediaCodec!=null)
{
mMediaCodec.stop();
mMediaCodec.release();
mMediaCodec=null;
}
if(extractor!=null)
{
extractor.release();
extractor=null;
}
//clearsourceandtheotherglobals
ration=0;
mime=null;
sampleRate=0;
channels=0;
bitrate=0;
presentationTimeUs=0;
ration=0;
}
8. 如何在Android用FFmpeg+SDL2.0解碼聲音
一、創建一個VideoPicture結構體用來保存解碼出來的圖像;
二、添加數據隊列的初始化、添加以及讀取的函數;
三、audio_decode_frame():解碼音頻;
四、audio_callback(): 回調函數,向SDL緩沖區填充數據;
五、創建視頻刷新相關的函數;
六、添加視頻顯示函數;
七、分配顯示輸出內存空間;
八、解碼線程,將解碼器,建立音頻線,保存重要信息到數據結構中;
九、編寫Main函數用來調用解碼線程。
知識點延伸:
FFmpeg是一個開源免費跨平台的視頻和音頻流方案,屬於自由軟體,採用LGPL或GPL許可證(依據你選擇的組件)。它提供了錄制、轉換以及流化音視頻的完整解決方案。它包含了非常先進的音頻/視頻編解碼庫libavcodec,為了保證高可移植性和編解碼質量,libavcodec里很多codec都是從頭開發的。FFmpeg在Linux平台下開發,但它同樣也可以在其它操作系統環境中編譯運行。
SDL2.0(Simple DirectMedia Layer)是一套開放源代碼的跨平台多媒體開發庫,使用C語言寫成。SDL多用於開發游戲、模擬器、媒體播放器等多媒體應用領域。SDL內置了調用OpenGL的函數。SDL提供了數種控制圖像、聲音、輸出入的函數,讓開發者只要用相同或是相似的代碼就可以開發出跨多個平台(Linux、Windows、Mac OS X等)的應用軟體。
9. android下視頻文件從解碼到播放需要哪幾步,請簡述
Android通過軟解碼播放視頻
1, 一般情況下Android的平台都是硬解碼視頻的,尤其是在Arm平台這種成熟的硬體平台上面(硬解碼代碼由晶元廠商提供)。但是Android移植到
2, MIPS平台時間還不長,還不成熟,還需要自己實現硬體解碼的工作。為了早日讓Android在MIPS平台運行起來,我選擇了先用軟解碼播放視頻。
3,Android代碼是從Android on MIPS社區獲得的代碼。發現軟解碼視頻播放過程中會發生崩潰。經過分析好像是內存分配的問題。
4, 經過研究OpenCore庫(Android框架是通過OpenCore來播放視頻的,網上有很多關於OpenCore的介紹,這里就不多說了),並參考Android平台——Surfaceflinger機制。發現問題出在源文件:
frameworks/base/libs/surfaceflinger/LayerBuffer.cpp的LayerBuffer::BufferSource::postBuffer方法中:
............
buffer = new LayerBuffer::Buffer(buffers, offset);
............類LayerBuffer::Buffer的構造函數代碼如下:
LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset)
: mBufferHeap(buffers)
{
NativeBuffer& src(mNativeBuffer);
g.handle = 0;
gralloc_mole_t const * mole = LayerBuffer::getGrallocMole();
if (mole && mole->perform) {
int err = mole->perform(mole,
GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER,
buffers.heap->heapID(), buffers.heap->getSize(),
offset, buffers.heap->base(),
& g.handle);
if (err == NO_ERROR) {
op.l = 0;
op.t = 0;
op.r = buffers.w;
op.b = buffers.h;
g.w = buffers.hor_stride ?: buffers.w;
g.h = r_stride ?: buffers.h;
rmat = rmat;
se = (void*)(intptr_t(buffers.heap->base()) + offset);
}
}
}LayerBuffer::getGrallocMole方法的調用到的Gralloc為:
hardware/libhardware/moles/gralloc/gralloc.cpp因為的沒有實現在自己的硬體只能用通用的Gralloc,經過分析發現通用的Gralloc沒有實現
5, mole->perform函數指針,mole->perform為NULL,所以不會對Buffer進行必要的初始化(我覺得應該是一個疏忽,只是不知道是谷歌的疏忽,還是MIPS移植人員的疏忽,最起碼應該能夠讓通用硬體能跑起來)。參考其他的硬體實現一個perform函數指針到通用Gralloc中。
在源文件:
hardware/libhardware/moles/gralloc/mapper.cpp增加如下的函數定義:
int gralloc_perform(struct gralloc_mole_t const* mole,
int operation, ... )
{
int res = -EINVAL;
va_list args;
va_start(args, operation);
switch (operation) {
case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
int fd = va_arg(args, int);
size_t size = va_arg(args, size_t);
size_t offset = va_arg(args, size_t);
void* base = va_arg(args, void*);
native_handle_t** handle = va_arg(args, native_handle_t**);
private_handle_t* hnd = (private_handle_t*)native_handle_create(
private_handle_t::sNumFds, private_handle_t::sNumInts);
hnd->magic = private_handle_t::sMagic;
hnd->fd = fd;
hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
hnd->size = size;
hnd->offset = offset;
hnd->base = intptr_t(base) + offset;
hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
*handle = (native_handle_t *)hnd;
res = 0;
break;
}
}
va_end(args);
return res;
}然後在gralloc.cpp中增加,gralloc_perform的聲明:
extern int gralloc_perform(struct gralloc_mole_t const* mole,
int operation, ... );並修改HAL_MODULE_INFO_SYM的定義,增加perform欄位的定義:
struct private_mole_t HAL_MODULE_INFO_SYM = {
base: {
.......
perform: gralloc_perform,
},
......
}; 重新編譯gralloc模塊,再次用Gallary應用程序通過軟解碼播放視頻,就可以流暢的播放了,軟解碼的效率挺高的,沒有卡的感覺!
10. android ffmpeg 解碼前需要編碼嗎
近弄了下android ffmpeg解碼,下面把流程總結一下方便大家參考
1.ffmpeg移植
網上有一些關於ffmpeg移植的文章,試了很多次但是最後生成的libffmpeg.so就只有幾KB所以這里換一種方式,網上也有文章說到了,其實我覺得這種方式反而要好一點,只需要生成一個庫就行了。
我修改好的ffmpeg下載地址:http://download.csdn.net/detail/hcly/6865961
下載後,解壓進入ffmpeg-1.2.4-android目錄,裡面有一個mkconfig.sh文件,打開這個文件,你需要修改幾個地方.
mkconfig.sh內容如下:
[python] view plain
#!/bin/sh
export PREBUILT=//work/tools/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3
export PLATFORM=//work/tools/android-ndk-r5b/platforms/android-9/arch-arm
export TMPDIR=//tmp
./configure \
--target-os=linux \
--arch=arm \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-avfilter \
--disable-postproc \
--disable-swresample \
--disable-avresample \
--disable-symver \
--disable-debug \
--disable-stripping \
--disable-yasm \
--disable-asm \
--enable-gpl \
--enable-version3 \
--enable-nonfree \
--disable-doc \
--enable-static \
--disable-shared \
--enable-cross-compile \
--prefix=//_install \
--cc=$PREBUILT/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/prebuilt/linux-x86/bin/arm-linux-androideabi- \
--nm=$PREBUILT/prebuilt/linux-x86/bin/arm-linux-androideabi-nm \
--extra-cflags="-fPIC -DANDROID -I$PLATFORM/usr/include" \
--extra-ldflags="-L$PLATFORM/usr/lib -nostdlib"
sed -i 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h
sed -i 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h
sed -i 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h
sed -i 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h
sed -i 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h
sed -i 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
sed -i 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
sed -i 's/HAVE_CBRTF 0/HAVE_CBRTF 1/g' config.h
sed -i 's/HAVE_ISINF 0/HAVE_ISINF 1/g' config.h
sed -i 's/HAVE_ISNAN 0/HAVE_ISNAN 1/g' config.h
sed -i 's/HAVE_SINF 0/HAVE_SINF 1/g' config.h
sed -i 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h
sed -i 's/#define av_restrict restrict/#define av_restrict/g' config.h
最開始的環境變數要設置一下:
[python] view plain
export PREBUILT=//work/tools/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3
export PLATFORM=//work/tools/android-ndk-r5b/platforms/android-9/arch-arm
export TMPDIR=//tmp
這個為你的NDK的路徑,以及臨時目錄
還有一個地方需要修改:
[python] view plain
--prefix=//_install \
這個為安裝目錄,請改成你自己的。
然後執行./mkconfig.sh
應該會有一個警告,不用管。直接執行make幾分鍾左右應該就會編譯完成了,然後執行make install
在你的安裝目錄下就會生成兩個目錄include和llib到這里 我們移植就完成了,先把這些文件放在這,後面我們需要用到。
2.jni的編寫
在你的android工程目錄下新建一個jni的目錄(其實我是在另一個工程里新建的,前面我試了一次執行ndk-build的時候把工程里的東西給刪除了),把前面我們安裝的include整個目錄拷貝到jni目錄下,把lib目錄里的所有.a文件拷貝到jni目錄下,新建Android.mk文件,內容如下:
[java] view plain
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := avformat
LOCAL_SRC_FILES := libavformat.a
LOCAL_CFLAGS :=-Ilibavformat
LOCAL_EXPORT_C_INCLUDES := libavformat
LOCAL_EXPORT_CFLAGS := -Ilibavformat
LOCAL_EXPORT_LDLIBS := -llog
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := libavcodec.a
LOCAL_CFLAGS :=-Ilibavcodec
LOCAL_EXPORT_C_INCLUDES := libavcodec
LOCAL_EXPORT_CFLAGS := -Ilibavcodec
LOCAL_EXPORT_LDLIBS := -llog
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avutil
LOCAL_SRC_FILES := libavutil.a
LOCAL_CFLAGS :=-Ilibavutil
LOCAL_EXPORT_C_INCLUDES := libavutil
LOCAL_EXPORT_CFLAGS := -Ilibavutil
LOCAL_EXPORT_LDLIBS := -llog
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swscale
LOCAL_SRC_FILES :=libswscale.a
LOCAL_CFLAGS :=-Ilibavutil -Ilibswscale
LOCAL_EXPORT_C_INCLUDES := libswscale
LOCAL_EXPORT_CFLAGS := -Ilibswscale
LOCAL_EXPORT_LDLIBS := -llog -lavutil
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpegutils
LOCAL_SRC_FILES := native.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_LDLIBS := -L$(LOCAL_PATH) -lm -lz
LOCAL_STATIC_LIBRARIES := avformat avcodec avutil swscale
include $(BUILD_SHARED_LIBRARY)
新建native.c文件,這個是我們最終要調用到的文件,內容如下:
[java] view plain
/*
* Copyright 2011 - Churn Labs, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This is mostly based off of the FFMPEG tutorial:
* http://dranger.com/ffmpeg/
* With a few updates to support Android output mechanisms and to update
* places where the APIs have shifted.
*/
#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <android/log.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#define LOG_TAG "FFMPEGSample"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
AVCodecContext * pCodecCtx = NULL;
AVFrame * pFrame=NULL;
AVPacket avpkt;
struct SwsContext *swsctx = NULL;
AVFrame * picture=NULL;
JNIEXPORT jint JNICALL Java_com__iclient_FfmpegIF_getffmpegv(JNIEnv * env, jclass obj)
{
LOGI("getffmpegv");
return avformat_version();
}
JNIEXPORT jint JNICALL Java_com__iclient_FfmpegIF_DecodeInit(JNIEnv * env, jclass obj,jint width,jint height)
{
LOGI("Decode_init");
AVCodec * pCodec=NULL;
avcodec_register_all();
//av_register_all();
//avcodec_init();
av_init_packet(&avpkt);
pCodec=avcodec_find_decoder(CODEC_ID_H264);
if(NULL!=pCodec)
{
pCodecCtx=avcodec_alloc_context3(pCodec);
if(avcodec_open2(pCodecCtx,pCodec,NULL)>=0)
{
pCodecCtx->height = height;
pCodecCtx->width = width;
pFrame=avcodec_alloc_frame();
}
return 1;
}
else
return 0;
}
JNIEXPORT jint JNICALL Java_com__iclient_FfmpegIF_Decoding(JNIEnv * env, jclass obj,const jbyteArray pSrcData,const jint DataLen,const jbyteArray pDeData)
{
//LOGI("Decoding");
int frameFinished;
int i,j;
int consumed_bytes;
jbyte * Buf = (jbyte*)(*env)->GetByteArrayElements(env, pSrcData, 0);
jbyte * Pixel= (jbyte*)(*env)->GetByteArrayElements(env, pDeData, 0);
avpkt.data = Buf;