自学Libyuv 音频转码以及播放

来源:互联网 发布:强矩阵式管理 编辑:程序博客网 时间:2024/06/05 05:36

libyuv
下载libyuv
新建jni目录吧libyuv下所有东西考入
修改Android.mk文件
末尾 STATIC 改为 SHARED
生成的文件名 libyuv_static 改为 libyuv
添加到压缩包 libyuv.zip
上传到linux服务器
unzip libyuv.zip
切换到libyuv目录
然后 ndk-build
把生成的so库 pull下来

在android项目中 记得导入libyuv include 下的头文件(/home/jason/libyuv/jni/include) 和 linux服务器上pull 下来的so库(/home/jason/libyuv/libs/armeabi)
====================================================================

上面都是准备工作

1.新建JasonPlayer类

    public native void sound(String input,String output);
2.javah 生成头文件  com_boom_audioplayer_JasonPlayer.h
/* DO NOT EDIT THIS FILE - it is machine generated */#include "jni.h"/* Header for class com_boom_audioplayer_JasonPlayer */#ifndef _Included_com_boom_audioplayer_JasonPlayer#define _Included_com_boom_audioplayer_JasonPlayer#ifdef __cplusplusextern "C" {#endif/* * Class:     com_boom_audioplayer_JasonPlayer * Method:    sound * Signature: (Ljava/lang/String;Ljava/lang/String;)V */JNIEXPORT void JNICALL Java_com_boom_audioplayer_JasonPlayer_sound  (JNIEnv *, jobject, jstring, jstring);#ifdef __cplusplus}#endif#endif

3.实现具体  dn_audio_player.c
#include "com_boom_audioplayer_JasonPlayer.h"#include <stdlib.h>#include <unistd.h>#include <android/log.h>#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"jason",FORMAT,##__VA_ARGS__);#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR,"jason",FORMAT,##__VA_ARGS__);#define MAX_AUDIO_FRME_SIZE 48000 * 4//封装格式#include "libavformat/avformat.h"//解码#include "libavcodec/avcodec.h"//缩放#include "libswscale/swscale.h"//重采样#include "libswresample/swresample.h"JNIEXPORT void JNICALL Java_com_boom_audioplayer_JasonPlayer_sound  (JNIEnv *env, jobject jthiz, jstring input_jstr, jstring output_jstr){const char* input_cstr = (*env)->GetStringUTFChars(env,input_jstr,NULL);const char* output_cstr = (*env)->GetStringUTFChars(env,output_jstr,NULL);LOGI("%s","sound");//注册组件av_register_all();AVFormatContext *pFormatCtx = avformat_alloc_context();//打开音频文件if(avformat_open_input(&pFormatCtx,input_cstr,NULL,NULL) != 0){LOGI("%s","无法打开音频文件");return;}//获取输入文件信息if(avformat_find_stream_info(pFormatCtx,NULL) < 0){LOGI("%s","无法获取输入文件信息");return;}//获取音频流索引位置int i = 0, audio_stream_idx = -1;for(; i < pFormatCtx->nb_streams;i++){if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){audio_stream_idx = i;break;}}//获取解码器AVCodecContext *codecCtx = pFormatCtx->streams[audio_stream_idx]->codec;AVCodec *codec = avcodec_find_decoder(codecCtx->codec_id);if(codec == NULL){LOGI("%s","无法获取解码器");return;}//打开解码器if(avcodec_open2(codecCtx,codec,NULL) < 0){LOGI("%s","无法打开解码器");return;}//压缩数据AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));//解压缩数据AVFrame *frame = av_frame_alloc();//frame->16bit 44100 PCM 统一音频采样格式与采样率SwrContext *swrCtx = swr_alloc();//重采样设置参数-------------start//输入的采样格式enum AVSampleFormat in_sample_fmt = codecCtx->sample_fmt;//输出采样格式16bit PCMenum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;//输入采样率int in_sample_rate = codecCtx->sample_rate;//输出采样率int out_sample_rate = in_sample_rate;//获取输入的声道布局//根据声道个数获取默认的声道布局(2个声道,默认立体声stereo)//av_get_default_channel_layout(codecCtx->channels);uint64_t in_ch_layout = codecCtx->channel_layout;//输出的声道布局(立体声)uint64_t out_ch_layout = AV_CH_LAYOUT_STEREO;swr_alloc_set_opts(swrCtx,  out_ch_layout,out_sample_fmt,out_sample_rate,  in_ch_layout,in_sample_fmt,in_sample_rate,  0, NULL);swr_init(swrCtx);//输出的声道个数int out_channel_nb = av_get_channel_layout_nb_channels(out_ch_layout);//重采样设置参数-------------end//JNI begin------------------//JasonPlayerjclass player_class = (*env)->GetObjectClass(env,jthiz);//AudioTrack对象jmethodID create_audio_track_mid = (*env)->GetMethodID(env,player_class,"createAudioTrack","(II)Landroid/media/AudioTrack;");jobject audio_track = (*env)->CallObjectMethod(env,jthiz,create_audio_track_mid,out_sample_rate,out_channel_nb);//调用AudioTrack.play方法jclass audio_track_class = (*env)->GetObjectClass(env,audio_track);jmethodID audio_track_play_mid = (*env)->GetMethodID(env,audio_track_class,"play","()V");(*env)->CallVoidMethod(env,audio_track,audio_track_play_mid);//AudioTrack.writejmethodID audio_track_write_mid = (*env)->GetMethodID(env,audio_track_class,"write","([BII)I");//JNI end------------------FILE *fp_pcm = fopen(output_cstr,"wb");//16bit 44100 PCM 数据uint8_t *out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRME_SIZE);int got_frame = 0,index = 0, ret;//不断读取压缩数据while(av_read_frame(pFormatCtx,packet) >= 0){//解码音频类型的Packetif(packet->stream_index == audio_stream_idx){//解码ret = avcodec_decode_audio4(codecCtx,frame,&got_frame,packet);if(ret < 0){LOGI("%s","解码完成");}//解码一帧成功if(got_frame > 0){LOGI("解码:%d",index++);swr_convert(swrCtx, &out_buffer, MAX_AUDIO_FRME_SIZE,(const uint8_t **)frame->data,frame->nb_samples);//获取sample的sizeint out_buffer_size = av_samples_get_buffer_size(NULL, out_channel_nb,frame->nb_samples, out_sample_fmt, 1);fwrite(out_buffer,1,out_buffer_size,fp_pcm);//out_buffer缓冲区数据,转成byte数组jbyteArray audio_sample_array = (*env)->NewByteArray(env,out_buffer_size);jbyte* sample_bytep = (*env)->GetByteArrayElements(env,audio_sample_array,NULL);//out_buffer的数据复制到sampe_bytepmemcpy(sample_bytep,out_buffer,out_buffer_size);//同步(*env)->ReleaseByteArrayElements(env,audio_sample_array,sample_bytep,0);//AudioTrack.write PCM数据(*env)->CallIntMethod(env,audio_track,audio_track_write_mid,audio_sample_array,0,out_buffer_size);//释放局部引用(*env)->DeleteLocalRef(env,audio_sample_array);usleep(1000 * 16);}}av_free_packet(packet);}av_frame_free(&frame);av_free(out_buffer);swr_free(&swrCtx);avcodec_close(codecCtx);avformat_close_input(&pFormatCtx);(*env)->ReleaseStringUTFChars(env,input_jstr,input_cstr);(*env)->ReleaseStringUTFChars(env,output_jstr,output_cstr);}
javap -s 类名  获取类中方法的签名 (要cd到 项目的classes目录)
添加权限
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
Application.mk
APP_ABI := allAPP_PLATFORM := android-9APP_OPIM :=debug
由于我这里是把ffmpeg和libyuv同时放在一起
 
Android.mk
LOCAL_PATH := $(call my-dir)#ffmpeg libinclude $(CLEAR_VARS)LOCAL_MODULE := avcodecLOCAL_SRC_FILES := libavcodec-56.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := avdeviceLOCAL_SRC_FILES := libavdevice-56.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := avfilterLOCAL_SRC_FILES := libavfilter-5.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := avformatLOCAL_SRC_FILES := libavformat-56.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := avutilLOCAL_SRC_FILES := libavutil-54.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := postprocLOCAL_SRC_FILES := libpostproc-53.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := swresampleLOCAL_SRC_FILES := libswresample-1.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := swscaleLOCAL_SRC_FILES := libswscale-3.soinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := yuvLOCAL_SRC_FILES := libyuv.soinclude $(PREBUILT_SHARED_LIBRARY)#myappinclude $(CLEAR_VARS)LOCAL_MODULE := myffmpegLOCAL_SRC_FILES := dn_video_player.c dn_audio_player.cLOCAL_C_INCLUDES += $(LOCAL_PATH)/include/ffmpegLOCAL_C_INCLUDES += $(LOCAL_PATH)/include/libyuvLOCAL_LDLIBS := -llog -landroidLOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale yuvinclude $(BUILD_SHARED_LIBRARY)
2.openssl es
自学还没学到..




阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 630箱变价格 高低温交变湿热试验箱 100kva箱变价格 交变盐雾试验箱 500kva箱变价格多少钱 800kva箱变价格 400kva箱变价格 耐黄变试验箱 箱变生产厂家 1250kva箱变价格 箱变厂家 欧式箱变价格 箱变基础现场图片 箱变图片 箱唛 黑暗之魂3宝箱头 箱娘手机版 箱娘攻略 箱娘汉化 3d箱娘手机版下载 3d箱娘汉化手机版 3d箱娘汉化手机版下载 3d箱娘中文版 v1.0 箱娘下载地址 3d箱娘中文版v1.0 手机版 3d箱娘中文版下载地址 3d箱娘中文版下载 推箱子 推箱子图解 箱子密码锁 箱子里男人 箱子尺寸 箱子英文 箱子图片 纸箱子 箱子英语 透明箱子 密码箱子 斯金纳箱子 20寸箱子 复古箱子