使用jni开发音频转码器

原创 2013年12月04日 13:26:30

一、程序运行效果图




二、下载链接

http://download.csdn.net/detail/caihongshijie6/6655407


三、实现

1、main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >



    <EditText
        android:id="@+id/editText1"
        android:hint="源wav文件的路径"
        android:text="/sdcard/ylzs.wav"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

    </EditText>

    <EditText
        android:id="@+id/editText2"
                android:hint="目标MP3文件的路径"
        android:layout_width="match_parent"
                android:text="/sdcard/ylzs.mp3"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="转化" 
        android:onClick="convert"
        />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="获取lame版本号"
        android:onClick="getversion"
         />

</LinearLayout>


2、MainActivity

package com.njupt.lame;

import java.io.File;

import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

public class MainActivity extends Activity {

	private EditText et_wav;
	private EditText et_mp3;
	private ProgressDialog pd;
	
	public native void convertmp3(String wav,String mp3);
	public native String getLameVersion();
	public native void stop();
	
	static{
		System.loadLibrary("Hello");
	}
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	    
		et_wav = (EditText) findViewById(R.id.editText1);
		et_mp3 = (EditText) findViewById(R.id.editText2);
		
		pd = new ProgressDialog(this);
	}

	public void convert(View view){
		final String mp3name = et_mp3.getText().toString().trim();
	    final String wavname = et_wav.getText().toString().trim();
	    
	    File file = new File(wavname);
	    int size = (int) file.length();
	    
	    System.out.println("file size: " + size);
	    
	    if("".equals(mp3name) ||"".equals(wavname)){
	    	Toast.makeText(this, "path can not be null..", 1).show();
	    	return ;
	    }
	    
	    pd.setMessage("converting....");
	    pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
	    pd.setMax(size);
	    
	    pd.show();
	    
	    
	    new Thread(){
	    	public void run() {
	    		convertmp3(wavname, mp3name);
	    		pd.dismiss();
	    	};
	    }.start();
	}
	
	public void setConvertProgress(int progress){
		pd.setProgress(progress);
	}
	
	
	public void getversion(View view){
		String version = getLameVersion();
		Toast.makeText(this, version, 1).show();
	}
	@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;
	}

}


3、Hello.c

#include <stdio.h>
#include <jni.h>
#include "com_njupt_lame_MainActivity.h"

#include <android/log.h>
#include <lame.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

int flag = 0;

char* Jstring2CStr(JNIEnv* env, jstring jstr) {
	char* rtn = NULL;
	jclass clsstring = (*env)->FindClass(env, "java/lang/String");
	jstring strencode = (*env)->NewStringUTF(env, "GB2312");
	jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
			"(Ljava/lang/String;)[B");
	jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
			strencode); // String .getByte("GB2312");
	jsize alen = (*env)->GetArrayLength(env, barr);
	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;
}

void publishJavaProgress(JNIEnv * env, jobject obj, jint progress) {
	// 调用java代码 更新程序的进度条
// 1.找到java的LameActivity的class
	//  jclass      (*FindClass)(JNIEnv*, const char*);
	jclass clazz = (*env)->FindClass(env, "com/njupt/lame/MainActivity");
	if (clazz == 0) {
		LOGI("can't find clazz");
	}
	LOGI(" find clazz");
	//2 找到class 里面的方法定义
//    jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);

	jmethodID methodid = (*env)->GetMethodID(env, clazz, "setConvertProgress",
			"(I)V");
	if (methodid == 0) {
		LOGI("can't find methodid");
	}
	LOGI(" find methodid");

	//3 .调用方法
//    void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
	(*env)->CallVoidMethod(env, obj, methodid, progress);
}

JNIEXPORT void JNICALL Java_com_njupt_lame_MainActivity_convertmp3
  (JNIEnv * env, jobject obj, jstring jwav, jstring jmp3){
	char* cwav =Jstring2CStr(env,jwav) ;
		char* cmp3=Jstring2CStr(env,jmp3);
		LOGI("wav = %s", cwav);LOGI("mp3 = %s", cmp3);

//1.打开 wav,MP3文件
FILE* fwav = fopen(cwav,"rb");
		FILE* fmp3 = fopen(cmp3,"wb");

		short int wav_buffer[8192*2];
		unsigned char mp3_buffer[8192];

		//1.初始化lame的编码器
		lame_t lame =  lame_init();
		//2. 设置lame mp3编码的采样率
		lame_set_in_samplerate(lame , 44100);
		lame_set_num_channels(lame,2);
		// 3. 设置MP3的编码方式
		lame_set_VBR(lame, vbr_default);

		lame_init_params(lame);

		LOGI("lame init finish");int read ; int write; //代表读了多少个次 和写了多少次
		int total=0; // 当前读的wav文件的byte数目
		do{
			if(flag==404){
				return;
			}
			read = fread(wav_buffer,sizeof(short int)*2, 8192,fwav);
			total +=  read* sizeof(short int)*2;
			LOGI("converting ....%d", total);publishJavaProgress(env,obj,total);
			// 调用java代码 完成进度条的更新
			if(read!=0){

				write = lame_encode_buffer_interleaved(lame,wav_buffer,read,mp3_buffer,8192);
				//把转化后的mp3数据写到文件里
				fwrite(mp3_buffer,sizeof(unsigned char),write,fmp3);
			}
			if(read==0){
				lame_encode_flush(lame,mp3_buffer,8192);
			}

		}while(read!=0);
		LOGI(
		"convert  finish");

lame_close(lame);
fclose(fwav);
fclose(fmp3);
}

JNIEXPORT jstring JNICALL Java_com_njupt_lame_MainActivity_getLameVersion(
	JNIEnv * env, jobject obj){
	return (*env)->NewStringUTF(env,get_lame_version());
}

JNIEXPORT void JNICALL Java_com_njupt_lame_MainActivity_stop
(JNIEnv * env, jobject obj){

}

4、Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := Hello
LOCAL_SRC_FILES := bitstream.c fft.c id3tag.c mpglib_interface.c presets.c  quantize.c   reservoir.c tables.c  util.c  VbrTag.c encoder.c  gain_analysis.c lame.c  newmdct.c   psymodel.c quantize_pvt.c set_get.c  takehiro.c vbrquantize.c version.c Hello.c
LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)


5、移植lame

主要是做好以下几步:

1)将include目录下的lame.h文件拷到jni目录下

2)将libmp3lame中的东西都拷到jni目录下。并删除一些不是以.rc 、.ico、MakeFile..文件

、删除i386那个目录

3)将util.h文件中的第374行左右的类型改成float





版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

使用FFmpeg实现的转码器

FFmpeg转码器,原本目的是rtsp视频流转mp4,也可以经过一点修改完成其他转码处理...

iOS 基于FFmpeg的移动端Demo:IOS 视频转码器

最简单的基于FFmpeg的移动端例子:IOS 视频解码器 最简单的基于FFmpeg的移动端例子:IOS 推流器 最简单的基于FFmpeg的移动端例子:IOS 视频转码器 最简单的基于...

Babel 转码器

es6 babel

FFmpeg内存操作(三)内存转码器

本文代码来自于自雷霄骅的《最简单的基于FFmpeg的内存读写的例子:内存转码器》  /** * This software convert video bitstream (Such as MPEG...

traceur.js转码器

  • 2017年11月15日 23:50
  • 1.24MB
  • 下载

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

===================================================== 最简单的基于FFmpeg的移动端例子系列文章列表: 最简单的基于FFmpeg的移动端例子...

转码器(WAP应用)

  • 2006年02月23日 09:05
  • 284KB
  • 下载

转码器源代码

  • 2008年01月31日 16:27
  • 1.31MB
  • 下载

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

本文记录一个安卓平台下基于FFmpeg的视频转码器。该转码器实际上移植自ffmpeg工程中的ffmpeg.c源代码。有关ffmpeg.c的源代码可以参考文章《ffmpeg.c函数结构简单分析(画图)》...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用jni开发音频转码器
举报原因:
原因补充:

(最多只允许输入30个字)