Lame编码器2-Lame编码器逻辑功能
音频编码,视频编码,lame编码,音频转码,lame转码
1、移植LAME代码 a、将不需要的文件删除,留下*.c和*.h文件 b、需要在Android.mk,将所有的*.c文件引入 LOCAL_SRC_FILES := ... c、然后有一个类型是linux下的,不支持,换成float d、然后cygwin中ndk-build,需要一定的时间 换成float: extern float fast_log2(float x); e、一般来说,测试是否移植别人成功,调用一下获取version的方法 |
2、获取lame的版本,测试是否移植成功。lame.h中有该方法的声明 //获取lame版本
JNIEXPORT jstring JNICALL Java_cn_zengfansheng_lame_MainActivity_getLameVersionFromC(
JNIEnv *env, jobject obj) {
//4、获取版本
// int CDECL lame_init_params(lame_global_flags *);
// const char* CDECL get_lame_version ( void );
return (*env)->NewStringUTF(env, get_lame_version());
}结果: |
3、调用lame进行音频转码 #include <stdio.h> #include <stdlib.h>
#include <malloc.h>
#include <jni.h>
#include <android/log.h>
#include <lame.h>
#include "cn_zengfansheng_lame_MainActivity.h"
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) //Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
char* Jstring2CStr(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env, "java/lang/String"); //String
jstring strencode = (*env)->NewStringUTF(env, "GB2312"); // 得到一个java字符串 "GB2312"
jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
"(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
strencode); // String .getByte("GB2312");
jsize alen = (*env)->GetArrayLength(env, barr); // byte数组的长度
jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
if (alen > 0) {
rtn = (char*) malloc(alen + 1); //"\0"
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
(*env)->ReleaseByteArrayElements(env, barr, ba, 0);
return rtn;
} //获取lame版本
JNIEXPORT jstring JNICALL Java_cn_zengfansheng_lame_MainActivity_getLameVersionFromC(
JNIEnv *env, jobject obj) {
//4、获取版本
// int CDECL lame_init_params(lame_global_flags *);
// const char* CDECL get_lame_version ( void );
return (*env)->NewStringUTF(env, get_lame_version());
} //转码操作
JNIEXPORT void JNICALL Java_cn_zengfansheng_lame_MainActivity_convertToMp3
(JNIEnv *env, jobject obj, jstring jstr_src , jstring jstr_dst) { //0-1、获取java代码传递过来的要转码的源文件,和转码后存放的路径,转换成c语言的char字符
char* cstr_src = Jstring2CStr(env,jstr_src);
char* cstr_dst = Jstring2CStr(env,jstr_dst); //0-2、LOGD测试下
LOGD("src=%s",cstr_src);
LOGD("dst=%s",cstr_dst); //0-3、打开wav、mp3文件
FILE* fsrc = fopen(cstr_src,"rb");
FILE* fdst = fopen(cstr_dst,"wb"); short int wav_buffer[8192*2];
unsigned char mp3_buffer[8192]; //1、初始化lame的编码器
// struct lame_global_struct;
// typedef struct lame_global_struct lame_global_flags;
// typedef lame_global_flags *lame_t;
// lame_global_flags * CDECL lame_init(void);
lame_t lame = lame_init(); //2、设置lame mp3的采样率
/* input sample rate in Hz. default = 44100hz */
//int CDECL lame_set_in_samplerate(lame_global_flags *, int);
//int CDECL lame_get_in_samplerate(const lame_global_flags *);
lame_set_in_samplerate(lame,44100); //3、设置输入频道
/* number of channels in input stream. default=2 */
//int CDECL lame_set_num_channels(lame_global_flags *, int);
//int CDECL lame_get_num_channels(const lame_global_flags *);
lame_set_num_channels(lame,2); //4、设置mp3的编码方法
/* Types of VBR. default = vbr_off = CBR */
//int CDECL lame_set_VBR(lame_global_flags *, vbr_mode);
//vbr_mode CDECL lame_get_VBR(const lame_global_flags *);
//查看typedef enum vbr_mode_e 可知:vbr_default=vbr_mtrh
lame_set_VBR(lame,vbr_default); //5、设置lame配置
/*
* REQUIRED:
* sets more internal configuration based on data provided above.
* returns -1 if something failed.
*/
//int CDECL lame_init_params(lame_global_flags *);
lame_init_params(lame);
LOGD("statrt--lame init finish"); //6、开始转换
int read = 0 ;//代表读了多少个次 和写了多少次
int write = 0;
LOGD("read=%d",read);
LOGD("write=%d",write);
do{
//读,返回读取到的字节
read = fread(wav_buffer,sizeof(short int)*2,8192,fsrc);
LOGD("read=%d,lame reading",read);
if(read!=0){
LOGD("read=%d,--lame converting...",read);
//转换,返回转换的字节
write = lame_encode_buffer_interleaved(lame,wav_buffer,read,mp3_buffer,8192);
//把转化后的mp3数据写到文件里
fwrite(mp3_buffer,sizeof(unsigned char),write,fdst);
}
if(read==0){//读到末尾
LOGD("read=%d,--lame converting...",read);
lame_encode_flush(lame,mp3_buffer,8192);
}
}while(read!=0);
LOGI("end--convert finish"); //7、关闭资源
lame_close(lame);
fclose(fsrc);
fclose(fdst);
} 结果: |
4、进度条的转化百分比实现 a) 在java代码中,设置进度条最大值,并提供修改进度条值的方法 b) 要在C代码中,在转换的过程中,获取进度值,并通过调用java中修改进度条的方法,来修改对话框进度值 |
问题1:在转换过程中,用户点击后退键,对话框消失了,但后台还在进行数据转换 解决:将ProgressDialog在转换时设置为不可取消 pd.setCancelable(false); |
问题2:如何在用户点击后退键时,将转换停止掉? 解决:在c代码中,定义一个flag,但flag= 404 ,跳出循环 然后在java代码中,提供一个可以操作该flag的native方法,stop(), 当用户按后退键时,调用该stop,将c中的flag置为404. int flag = 0 ;//跳出循环的条件:flag=404 public native void stop(); |
11-30 07:48:06.193: I/Choreographer(25721): Skipped 42 frames! The application may be doing too much work on its main thread. |