Android多媒体开发(3)————使用Android(安卓)NKD编译havlenapetr-FFMpeg
Android多媒体开发(3)————使用Android NKD编译havlenapetr-FFMpeg-7c27aa2
http://blog.csdn.net/conowen/article/details/7526398
分类: Android多媒体&流媒体开发/********************************************************************************************
* author:conowen@大钟
* E-mail:conowen@hotmail.com
* http://blog.csdn.net/conowen
* 注:本文为原创,仅作为学习交流使用,转载请标明作者及出处。
********************************************************************************************/
1、
使用NDK去编译官方的FFmpeg原版的话,还得自己实现JNI层与java层,工程量比较大。所以移植FFmpeg到Android平台时,可以移植一些已经实现JNI与JAVA层的开源项目,毕竟软件行业从来都是站在巨人肩膀上发展的。
2、 /FFMpeg
havlenapetr的开源项目是比较出名的一个FFmpeg工程,很多Android多媒体项目都是在此基础上面修改的。
下载地址:https://github.com/havlenapetr/FFMpeg
可以直接ZIP包:https://github.com/havlenapetr/FFMpeg/zipball/debug
或者通过git方式下载,新建一个目录,然后在linux的终端下执行,当然了,你要事情安装git的相关工具
- gitclonehttps://github.com/havlenapetr/FFMpeg.git
git clone https://github.com/havlenapetr/FFMpeg.git
3、利用NDK编译生成so库
下载后直接在havlenapetr-FFMpeg-7c27aa2的顶级目录下执行
[java] view plain copy print ?- $ndk/ndk-build
$ndk/ndk-build
是可以编译通过的,不会提示任何error。
关于如何利用NDK编译,可以参考我之前的博文:http://blog.csdn.net/conowen/article/details/7518870
4、导入java工程,实现播放
然后把在eclipse里面,把havlenapetr-FFMpeg-7c27aa2这个项目import进来,就可以播放视频了。
4.1、需要注意的是:这个版本的havlenapetr FFmpeg工程只能在Android 2.2上面运行,因为havlenapetr采用的是音视频直接在JNI层输入。可以注意到havlenapetr-FFMpeg-7c27aa2目录下有prebuilt这样一个目录,此目录下有Android 2.2版本的libjniaudio.so和libjnivideo.so两个库文件。
4.2、Android版本不同导致不能播放:
havlenapetr的FFmpeg项目音视频输出如下
音频:采用Android底层的audiotrack输出。
视频:在FFmpeg解码之后,得到YUV信号,然后转换成RGB信号,最终通过Android底层的surface输出。
提示:可以移植SDL开源库实现音视频输出,因为SDL的视频输出机制是通过OPenGL呈现画面,这样就可以兼容所有的Android平台。
但是问题就来了,Android每个版本的framework都是不大一样的,所以要在底层使用Android的audiotrack和surface来输入音视频信号,就要在相应版本的Android源代码中,重新编译生成libjniaudio.so和libjnivideo.so两个库文件了。
5、编译havlenapetr FFmpeg工程Android 2.3版本的libjniaudio.so和libjnivideo.so
首先要明白一点,Android的官方源代码编译之后,是不会生成libjniaudio.so和libjnivideo.so的。所以要自己添加audiotrack.cpp、surface.cpp和Android.mk文件到Android源代码里面编译生成。(每次编译libjniaudio.so和libjnivideo.so都要重新编译这个Android源代码,时间比较长。)
5.1下载audio与video文件夹
可以在https://github.com/havlenapetr/android_frameworks_base下载audiotrack.cpp、surface.cpp和Android.mk,注意要选择正确的branch(分支)
froyo---->Android 2.2
gingerbread---->Android 2.3
ICS---->Android 4.0
关于havlenapetr-FFMpeg在Android 4.0(ICS)的补充说明
5.2、编译Android系统源代码
下载之后,然后找到里面的native文件夹,把里面的audio和video文件夹拖进Android源代码的frameworks/base/native目录下。
绿色的是新加入的文件
需要注意的一点是:
gingerbread下载之后,里面是没有audio和video文件夹的,但是可以用froyo版本的audio和video文件夹。(也就是下载gingerbread感觉也没啥用Orz~~~)
但是我们可以使用froyo的audio和video文件夹,编译Android源代码是可以成功通过的,ndk-build也可以通过,但是在Android的java工程里面使用就会有以下错误信息。
[cpp] view plain copy print ?- java.lang.NoSuchFieldError:nofieldwithname='mSurface'signature='I'inclassLandroid/view/Surface;
java.lang.NoSuchFieldError: no field with name='mSurface' signature='I' in class Landroid/view/Surface;
加载库时,找不到mSruface类
修改方法是:
将surface.cpp中mSurface改为 mNativeSurface ,然后重新编译即可。当然了,你也可以用ICS的surface.cpp文件,这个版本是没有问题的。
另外编译havlenapetr FFmpeg工程Android 4.0版本的libjniaudio.so和libjnivideo.so与上面步骤差不多。
/************************************************************************/
附上我所使用的audio与video(来源havlenapetr的项目)
video/jni/surface.cpp(注意目录结构)
- /*
- *Copyright(C)2009TheAndroidOpenSourceProject
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- #include<android/surface.h>
- #include<surfaceflinger/Surface.h>
- #include<utils/Log.h>
- #include<SkBitmap.h>
- #include<SkCanvas.h>
- #defineTAG"SurfaceWrapper"
- usingnamespaceandroid;
- staticSurface*sSurface;
- staticSkBitmapsBitmapClient;
- staticSkBitmapsBitmapSurface;
- staticSurface*getNativeSurface(JNIEnv*env,jobjectjsurface){
- jclassclazz=env->FindClass("android/view/Surface");
- jfieldIDfield_surface=env->GetFieldID(clazz,"mNativeSurface","I");
- if(field_surface==NULL){
- returnNULL;
- }
- return(Surface*)env->GetIntField(jsurface,field_surface);
- }
- staticintinitBitmap(SkBitmap*bitmap,intformat,intwidth,intheight,boolallocPixels){
- switch(format){
- casePIXEL_FORMAT_RGBA_8888:
- bitmap->setConfig(SkBitmap::kARGB_8888_Config,width,height);
- break;
- casePIXEL_FORMAT_RGBA_4444:
- bitmap->setConfig(SkBitmap::kARGB_4444_Config,width,height);
- break;
- casePIXEL_FORMAT_RGB_565:
- bitmap->setConfig(SkBitmap::kRGB_565_Config,width,height);
- break;
- casePIXEL_FORMAT_A_8:
- bitmap->setConfig(SkBitmap::kA8_Config,width,height);
- break;
- default:
- bitmap->setConfig(SkBitmap::kNo_Config,width,height);
- break;
- }
- if(allocPixels){
- bitmap->setIsOpaque(true);
- //--allocarrayofpixels
- if(!bitmap->allocPixels()){
- return-1;
- }
- }
- return0;
- }
- intAndroidSurface_register(JNIEnv*env,jobjectjsurface){
- __android_log_print(ANDROID_LOG_INFO,TAG,"registeringvideosurface");
- sSurface=getNativeSurface(env,jsurface);
- if(sSurface==NULL){
- returnANDROID_SURFACE_RESULT_JNI_EXCEPTION;
- }
- __android_log_print(ANDROID_LOG_INFO,TAG,"registered");
- returnANDROID_SURFACE_RESULT_SUCCESS;
- }
- intAndroidSurface_getPixels(intwidth,intheight,void**pixels){
- __android_log_print(ANDROID_LOG_INFO,TAG,"gettingsurface'spixels%ix%i",width,height);
- if(sSurface==NULL){
- returnANDROID_SURFACE_RESULT_JNI_EXCEPTION;
- }
- if(initBitmap(&sBitmapClient,PIXEL_FORMAT_RGB_565,width,height,true)<0){
- returnANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_CLIENT;
- }
- *pixels=sBitmapClient.getPixels();
- __android_log_print(ANDROID_LOG_INFO,TAG,"getted");
- returnANDROID_SURFACE_RESULT_SUCCESS;
- }
- staticvoiddoUpdateSurface(){
- SkCanvascanvas(sBitmapSurface);
- SkRectsurface_sBitmapClient;
- SkRectsurface_sBitmapSurface;
- SkMatrixmatrix;
- surface_sBitmapSurface.set(0,0,sBitmapSurface.width(),sBitmapSurface.height());
- surface_sBitmapClient.set(0,0,sBitmapClient.width(),sBitmapClient.height());
- matrix.setRectToRect(surface_sBitmapClient,surface_sBitmapSurface,SkMatrix::kFill_ScaleToFit);
- canvas.drawBitmapMatrix(sBitmapClient,matrix);
- }
- staticintprepareSurfaceBitmap(Surface::SurfaceInfo*info){
- if(initBitmap(&sBitmapSurface,info->format,info->w,info->h,false)<0){
- return-1;
- }
- sBitmapSurface.setPixels(info->bits);
- return0;
- }
- intAndroidSurface_updateSurface(){
- staticSurface::SurfaceInfosurfaceInfo;
- if(sSurface==NULL){
- returnANDROID_SURFACE_RESULT_JNI_EXCEPTION;
- }
- if(!Surface::isValid(sSurface)){
- returnANDROID_SURFACE_RESULT_NOT_VALID;
- }
- if(sSurface->lock(&surfaceInfo)<0){
- returnANDROID_SURFACE_RESULT_COULDNT_LOCK;
- }
- if(prepareSurfaceBitmap(&surfaceInfo)<0){
- returnANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_SURFACE;
- }
- doUpdateSurface();
- if(sSurface->unlockAndPost()<0){
- returnANDROID_SURFACE_RESULT_COULDNT_UNLOCK_AND_POST;
- }
- returnANDROID_SURFACE_RESULT_SUCCESS;
- }
- intAndroidSurface_unregister(){
- __android_log_print(ANDROID_LOG_INFO,TAG,"unregisteringvideosurface");
- __android_log_print(ANDROID_LOG_INFO,TAG,"unregistered");
- returnANDROID_SURFACE_RESULT_SUCCESS;
- }
/* * Copyright (C) 2009 The Android Open Source Project * * 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 copy 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. */#include <android/surface.h>#include <surfaceflinger/Surface.h>#include <utils/Log.h>#include <SkBitmap.h>#include <SkCanvas.h>#define TAG "SurfaceWrapper"using namespace android;static Surface*sSurface;static SkBitmapsBitmapClient;static SkBitmapsBitmapSurface;static Surface* getNativeSurface(JNIEnv* env, jobject jsurface) {jclass clazz = env->FindClass("android/view/Surface");jfieldID field_surface = env->GetFieldID(clazz, "mNativeSurface", "I");if(field_surface == NULL) {return NULL;}return (Surface *) env->GetIntField(jsurface, field_surface);}static int initBitmap(SkBitmap *bitmap, int format, int width, int height, bool allocPixels) {switch (format) { case PIXEL_FORMAT_RGBA_8888: bitmap->setConfig(SkBitmap::kARGB_8888_Config, width, height); break; case PIXEL_FORMAT_RGBA_4444: bitmap->setConfig(SkBitmap::kARGB_4444_Config, width, height); break; case PIXEL_FORMAT_RGB_565: bitmap->setConfig(SkBitmap::kRGB_565_Config, width, height); break; case PIXEL_FORMAT_A_8: bitmap->setConfig(SkBitmap::kA8_Config, width, height); break; default: bitmap->setConfig(SkBitmap::kNo_Config, width, height); break; }if(allocPixels) {bitmap->setIsOpaque(true);//-- alloc array of pixelsif(!bitmap->allocPixels()) {return -1;}}return 0;}int AndroidSurface_register(JNIEnv* env, jobject jsurface) {__android_log_print(ANDROID_LOG_INFO, TAG, "registering video surface");sSurface = getNativeSurface(env, jsurface);if(sSurface == NULL) { return ANDROID_SURFACE_RESULT_JNI_EXCEPTION;}__android_log_print(ANDROID_LOG_INFO, TAG, "registered");return ANDROID_SURFACE_RESULT_SUCCESS;}int AndroidSurface_getPixels(int width, int height, void** pixels) {__android_log_print(ANDROID_LOG_INFO, TAG, "getting surface's pixels %ix%i", width, height);if(sSurface == NULL) {return ANDROID_SURFACE_RESULT_JNI_EXCEPTION;}if(initBitmap(&sBitmapClient, PIXEL_FORMAT_RGB_565, width, height, true) < 0) {return ANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_CLIENT;}*pixels = sBitmapClient.getPixels();__android_log_print(ANDROID_LOG_INFO, TAG, "getted");return ANDROID_SURFACE_RESULT_SUCCESS;}static void doUpdateSurface() {SkCanvascanvas(sBitmapSurface);SkRectsurface_sBitmapClient;SkRectsurface_sBitmapSurface;SkMatrixmatrix;surface_sBitmapSurface.set(0, 0, sBitmapSurface.width(), sBitmapSurface.height());surface_sBitmapClient.set(0, 0, sBitmapClient.width(), sBitmapClient.height());matrix.setRectToRect(surface_sBitmapClient, surface_sBitmapSurface, SkMatrix::kFill_ScaleToFit);canvas.drawBitmapMatrix(sBitmapClient, matrix);}static int prepareSurfaceBitmap(Surface::SurfaceInfo* info) {if(initBitmap(&sBitmapSurface, info->format, info->w, info->h, false) < 0) {return -1;}sBitmapSurface.setPixels(info->bits);return 0;}int AndroidSurface_updateSurface() {static Surface::SurfaceInfo surfaceInfo;if(sSurface == NULL) {return ANDROID_SURFACE_RESULT_JNI_EXCEPTION;}if (!Surface::isValid (sSurface)){return ANDROID_SURFACE_RESULT_NOT_VALID;}if (sSurface->lock(&surfaceInfo) < 0) {return ANDROID_SURFACE_RESULT_COULDNT_LOCK;}if(prepareSurfaceBitmap(&surfaceInfo) < 0) {return ANDROID_SURFACE_RESULT_COULDNT_INIT_BITMAP_SURFACE;}doUpdateSurface();if (sSurface->unlockAndPost() < 0) {return ANDROID_SURFACE_RESULT_COULDNT_UNLOCK_AND_POST;}return ANDROID_SURFACE_RESULT_SUCCESS;}int AndroidSurface_unregister() {__android_log_print(ANDROID_LOG_INFO, TAG, "unregistering video surface");__android_log_print(ANDROID_LOG_INFO, TAG, "unregistered"); return ANDROID_SURFACE_RESULT_SUCCESS;}
video/jni/Android.mk (注意目录结构)
[cpp] view plain copy print ?
- LOCAL_PATH:=$(callmy-dir)
- include$(CLEAR_VARS)
- #oursourcefiles
- #
- LOCAL_SRC_FILES:=\
- surface.cpp
- LOCAL_SHARED_LIBRARIES:=\
- libskia\
- libsurfaceflinger_client\
- libutils\
- liblog
- LOCAL_C_INCLUDES+=\
- $(JNI_H_INCLUDE)\
- external/skia/src/core\
- external/skia/include/core\
- frameworks/base/include\
- frameworks/base/native/include
- #Optionaltagwouldmeanitdoesn'tgetinstalledbydefault
- LOCAL_MODULE_TAGS:=optional
- LOCAL_PRELINK_MODULE:=false
- LOCAL_MODULE:=libjnivideo
- include$(BUILD_SHARED_LIBRARY)
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)# our source files#LOCAL_SRC_FILES:= \ surface.cppLOCAL_SHARED_LIBRARIES := \ libskia \ libsurfaceflinger_client \ libutils \ liblogLOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ external/skia/src/core \ external/skia/include/core \ frameworks/base/include \ frameworks/base/native/include# Optional tag would mean it doesn't get installed by defaultLOCAL_MODULE_TAGS := optionalLOCAL_PRELINK_MODULE := falseLOCAL_MODULE:= libjnivideoinclude $(BUILD_SHARED_LIBRARY)
/audio/jni/audiotrack.cpp(注意目录结构)
[cpp] view plain copy print ?
- /*
- *Copyright(C)2009TheAndroidOpenSourceProject
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- #include<android/audiotrack.h>
- #include<utils/Log.h>
- #include<media/AudioTrack.h>
- #include<media/AudioSystem.h>
- #include<utils/Errors.h>
- #include<binder/MemoryHeapBase.h>
- #include<binder/MemoryBase.h>
- #defineTAG"AudioTrackWrapper"
- usingnamespaceandroid;
- //structaudiotrack_fields_t{
- staticAudioTrack*track;
- //sp<MemoryHeapBase>memHeap;
- //sp<MemoryBase>memBase;
- //};
- //staticstructaudiotrack_fields_taudio;
- staticAudioTrack*getNativeAudioTrack(JNIEnv*env,jobjectjaudioTrack){
- jclassclazz=env->FindClass("android/media/AudioTrack");
- jfieldIDfield_track=env->GetFieldID(clazz,"mNativeTrackInJavaObj","I");
- if(field_track==NULL){
- returnNULL;
- }
- return(AudioTrack*)env->GetIntField(jaudioTrack,field_track);
- }
- /*
- staticboolallocSharedMem(intsizeInBytes){
- memHeap=newMemoryHeapBase(sizeInBytes);
- if(memHeap->getHeapID()<0){
- returnfalse;
- }
- memBase=newMemoryBase(memHeap,0,sizeInBytes);
- returntrue;
- }
- */
- intAndroidAudioTrack_register(){
- __android_log_print(ANDROID_LOG_INFO,TAG,"registeringaudiotrack");
- track=newAudioTrack();
- if(track==NULL){
- returnANDROID_AUDIOTRACK_RESULT_JNI_EXCEPTION;
- }
- __android_log_print(ANDROID_LOG_INFO,TAG,"registered");
- returnANDROID_AUDIOTRACK_RESULT_SUCCESS;
- }
- intAndroidAudioTrack_start(){
- //__android_log_print(ANDROID_LOG_INFO,TAG,"startingaudiotrack");
- if(track==NULL){
- returnANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED;
- }
- track->start();
- returnANDROID_AUDIOTRACK_RESULT_SUCCESS;
- }
- intAndroidAudioTrack_set(intstreamType,
- uint32_tsampleRate,
- intformat,
- intchannels){
- if(track==NULL){
- returnANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED;
- }
- __android_log_print(ANDROID_LOG_INFO,TAG,"settingaudiotrack");
- status_tret=track->set(streamType,
- sampleRate,
- format,
- channels,
- 0,
- 0,
- 0,
- 0,
- false);
- if(ret!=NO_ERROR){
- returnANDROID_AUDIOTRACK_RESULT_ERRNO;
- }
- returnANDROID_AUDIOTRACK_RESULT_SUCCESS;
- }
- intAndroidAudioTrack_flush(){
- if(track==NULL){
- returnANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED;
- }
- track->flush();
- returnANDROID_AUDIOTRACK_RESULT_SUCCESS;
- }
- intAndroidAudioTrack_stop(){
- if(track==NULL){
- returnANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED;
- }
- track->stop();
- returnANDROID_AUDIOTRACK_RESULT_SUCCESS;
- }
- intAndroidAudioTrack_reload(){
- if(track==NULL){
- returnANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED;
- }
- if(track->reload()!=NO_ERROR){
- returnANDROID_AUDIOTRACK_RESULT_ERRNO;
- }
- returnANDROID_AUDIOTRACK_RESULT_SUCCESS;
- }
- intAndroidAudioTrack_unregister(){
- __android_log_print(ANDROID_LOG_INFO,TAG,"unregisteringaudiotrack");
- if(!track->stopped()){
- track->stop();
- }
- //memBase.clear();
- //memHeap.clear();
- free(track);
- //track=NULL;
- __android_log_print(ANDROID_LOG_INFO,TAG,"unregistered");
- returnANDROID_AUDIOTRACK_RESULT_SUCCESS;
- }
- intAndroidAudioTrack_write(void*buffer,intbuffer_size){
- //givethedatatothenativeAudioTrackobject(thedatastartsattheoffset)
- ssize_twritten=0;
- //regularwrite()orcopythedatatotheAudioTrack'ssharedmemory?
- if(track->sharedBuffer()==0){
- written=track->write(buffer,buffer_size);
- }else{
- //writingtosharedmemory,checkforcapacity
- if((size_t)buffer_size>track->sharedBuffer()->size()){
- __android_log_print(ANDROID_LOG_INFO,TAG,"buffersizewastoosmall");
- buffer_size=track->sharedBuffer()->size();
- }
- memcpy(track->sharedBuffer()->pointer(),buffer,buffer_size);
- written=buffer_size;
- }
- returnwritten;
- }
/** Copyright (C) 2009 The Android Open Source Project** 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 copy 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.*/#include <android/audiotrack.h>#include <utils/Log.h>#include <media/AudioTrack.h>#include <media/AudioSystem.h>#include <utils/Errors.h>#include <binder/MemoryHeapBase.h>#include <binder/MemoryBase.h>#define TAG "AudioTrackWrapper"using namespace android;//struct audiotrack_fields_t {static AudioTrack* track;//sp<MemoryHeapBase> memHeap;//sp<MemoryBase> memBase;//};//static struct audiotrack_fields_t audio;static AudioTrack* getNativeAudioTrack(JNIEnv* env, jobject jaudioTrack) { jclass clazz = env->FindClass("android/media/AudioTrack"); jfieldID field_track = env->GetFieldID(clazz, "mNativeTrackInJavaObj", "I"); if(field_track == NULL) { return NULL; } return (AudioTrack *) env->GetIntField(jaudioTrack, field_track);}/*static bool allocSharedMem(int sizeInBytes) { memHeap = new MemoryHeapBase(sizeInBytes); if (memHeap->getHeapID() < 0) { return false; } memBase = new MemoryBase(memHeap, 0, sizeInBytes); return true;}*/int AndroidAudioTrack_register() { __android_log_print(ANDROID_LOG_INFO, TAG, "registering audio track"); track = new AudioTrack(); if(track == NULL) { return ANDROID_AUDIOTRACK_RESULT_JNI_EXCEPTION; } __android_log_print(ANDROID_LOG_INFO, TAG, "registered"); return ANDROID_AUDIOTRACK_RESULT_SUCCESS;}int AndroidAudioTrack_start() { //__android_log_print(ANDROID_LOG_INFO, TAG, "starting audio track"); if(track == NULL) { return ANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED; } track->start(); return ANDROID_AUDIOTRACK_RESULT_SUCCESS;}int AndroidAudioTrack_set(int streamType, uint32_t sampleRate, int format, int channels) { if(track == NULL) { return ANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED; } __android_log_print(ANDROID_LOG_INFO, TAG, "setting audio track"); status_t ret = track->set(streamType, sampleRate, format, channels, 0, 0, 0, 0, false); if (ret != NO_ERROR) { return ANDROID_AUDIOTRACK_RESULT_ERRNO; } return ANDROID_AUDIOTRACK_RESULT_SUCCESS;}int AndroidAudioTrack_flush() { if(track == NULL) { return ANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED; } track->flush(); return ANDROID_AUDIOTRACK_RESULT_SUCCESS;}int AndroidAudioTrack_stop() { if(track == NULL) { return ANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED; } track->stop(); return ANDROID_AUDIOTRACK_RESULT_SUCCESS;}int AndroidAudioTrack_reload() { if(track == NULL) { return ANDROID_AUDIOTRACK_RESULT_ALLOCATION_FAILED; } if(track->reload() != NO_ERROR) { return ANDROID_AUDIOTRACK_RESULT_ERRNO; } return ANDROID_AUDIOTRACK_RESULT_SUCCESS;}int AndroidAudioTrack_unregister() { __android_log_print(ANDROID_LOG_INFO, TAG, "unregistering audio track"); if(!track->stopped()) { track->stop(); } //memBase.clear(); //memHeap.clear(); free(track); //track = NULL; __android_log_print(ANDROID_LOG_INFO, TAG, "unregistered"); return ANDROID_AUDIOTRACK_RESULT_SUCCESS;}int AndroidAudioTrack_write(void *buffer, int buffer_size) { // give the data to the native AudioTrack object (the data starts at the offset) ssize_t written = 0; // regular write() or copy the data to the AudioTrack's shared memory? if (track->sharedBuffer() == 0) { written = track->write(buffer, buffer_size); } else { // writing to shared memory, check for capacity if ((size_t)buffer_size > track->sharedBuffer()->size()) { __android_log_print(ANDROID_LOG_INFO, TAG, "buffer size was too small"); buffer_size = track->sharedBuffer()->size(); } memcpy(track->sharedBuffer()->pointer(), buffer, buffer_size); written = buffer_size; } return written;}
/audio/jni/Android.mk(注意目录结构)
[cpp] view plain copy print ?
- LOCAL_PATH:=$(callmy-dir)
- include$(CLEAR_VARS)
- #oursourcefiles
- #
- LOCAL_SRC_FILES:=\
- audiotrack.cpp
- LOCAL_SHARED_LIBRARIES:=\
- libbinder\
- libmedia\
- libutils\
- liblog
- LOCAL_C_INCLUDES+=\
- $(JNI_H_INCLUDE)\
- frameworks/base/include\
- frameworks/base/native/include
- #Optionaltagwouldmeanitdoesn'tgetinstalledbydefault
- LOCAL_MODULE_TAGS:=optional
- LOCAL_PRELINK_MODULE:=false
- LOCAL_MODULE:=libjniaudio
- include$(BUILD_SHARED_LIBRARY)
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)# our source files#LOCAL_SRC_FILES:= \ audiotrack.cppLOCAL_SHARED_LIBRARIES := \ libbinder \ libmedia \ libutils \ liblogLOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ frameworks/base/include \ frameworks/base/native/include# Optional tag would mean it doesn't get installed by defaultLOCAL_MODULE_TAGS := optionalLOCAL_PRELINK_MODULE := falseLOCAL_MODULE:= libjniaudioinclude $(BUILD_SHARED_LIBRARY)
更多相关文章
- Android版本检测\自动更新 (转的别人的)
- android 编译内核
- Android(安卓)日常报错之 Android(安卓)dependency 'com.android
- 开机不锁屏
- Android(安卓)Studio : Rendering Problems
- Android最新版本号与API级别对应关系
- NDK各版本下载
- android studio SDK版本的调节
- compileSdkVersion、buildToolsVersion、targetSdkVersion 、Fai