jni方法改为宏定义

jni方法改为宏定义
pull/107/head
xufulong 6 years ago
parent 2e7d905393
commit 4e122f2ca1
  1. 32
      app/src/main/cpp/audio_lame.c
  2. 30
      app/src/main/cpp/audio_player.c
  3. 4
      app/src/main/cpp/ffmpeg_cmd.c
  4. 25
      app/src/main/cpp/ffmpeg_jni_define.h
  5. 31
      app/src/main/cpp/video_player.c

@ -1,6 +1,7 @@
#include "include/lame/lame.h" #include "include/lame/lame.h"
#include <jni.h> #include <jni.h>
#include "ffmpeg_jni_define.h"
lame_global_flags *glf; lame_global_flags *glf;
@ -180,18 +181,16 @@ void close_lame(lame_global_flags *glf) {
} }
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameInitDefault AUDIO_PLAYER_FUNC(void, lameInitDefault) {
(JNIEnv *env, jclass jclazz) {
glf = initializeDefault(env); glf = initializeDefault(env);
} }
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameInit( AUDIO_PLAYER_FUNC(void, lameInit,
JNIEnv *env, jclass cls, jint inSampleRate, jint outChannel, jint inSampleRate, jint outChannel, jint outSampleRate, jint outBitrate,
jint outSampleRate, jint outBitrate, jfloat scaleInput, jint mode, jint vbrMode, jfloat scaleInput, jint mode, jint vbrMode, jint quality, jint vbrQuality,
jint quality, jint vbrQuality, jint abrMeanBitrate, jint lowPassFreq, jint highPassFreq, jint abrMeanBitrate, jint lowPassFreq, jint highPassFreq, jstring id3tagTitle,
jstring id3tagTitle, jstring id3tagArtist, jstring id3tagAlbum, jstring id3tagArtist, jstring id3tagAlbum, jstring id3tagYear, jstring id3tagComment) {
jstring id3tagYear, jstring id3tagComment) {
glf = initialize(env, inSampleRate, outChannel, outSampleRate, outBitrate, scaleInput, mode, glf = initialize(env, inSampleRate, outChannel, outSampleRate, outBitrate, scaleInput, mode,
vbrMode, vbrMode,
@ -201,24 +200,21 @@ JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameInit(
id3tagComment); id3tagComment);
} }
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameEncode( AUDIO_PLAYER_FUNC(jint, lameEncode,
JNIEnv *env, jclass cls, jshortArray buffer_l, jshortArray buffer_l, jshortArray buffer_r, jint samples, jbyteArray mp3buf) {
jshortArray buffer_r, jint samples, jbyteArray mp3buf) {
return encode(env, glf, buffer_l, buffer_r, samples, mp3buf); return encode(env, glf, buffer_l, buffer_r, samples, mp3buf);
} }
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_AudioPlayer_encodeBufferInterleaved( AUDIO_PLAYER_FUNC(jint, encodeBufferInterleaved,
JNIEnv *env, jclass cls, jshortArray pcm, jshortArray pcm, jint samples, jbyteArray mp3buf) {
jint samples, jbyteArray mp3buf) {
return encodeBufferInterleaved(env, glf, pcm, samples, mp3buf); return encodeBufferInterleaved(env, glf, pcm, samples, mp3buf);
} }
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameFlush( AUDIO_PLAYER_FUNC(jint, lameFlush,
JNIEnv *env, jclass cls, jbyteArray mp3buf) { jbyteArray mp3buf) {
return flush(env, glf, mp3buf); return flush(env, glf, mp3buf);
} }
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_lameClose( AUDIO_PLAYER_FUNC(void, lameClose) {
JNIEnv *env, jclass cls) {
close_lame(glf); close_lame(glf);
} }

@ -13,28 +13,26 @@
//重采样 //重采样
#include "libswresample/swresample.h" #include "libswresample/swresample.h"
#include <android/log.h> #include <android/log.h>
#include "ffmpeg_jni_define.h"
#define TAG "MediaPlayer" #define TAG "AudioPlayer"
#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO, TAG, FORMAT, ##__VA_ARGS__);
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR, TAG, FORMAT, ##__VA_ARGS__);
#define MAX_AUDIO_FRAME_SIZE 48000 * 4 #define MAX_AUDIO_FRAME_SIZE 48000 * 4
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_play AUDIO_PLAYER_FUNC(void, play, jstring input_jstr) {
(JNIEnv *env, jobject jthiz, jstring input_jstr){
const char* input_cstr = (*env)->GetStringUTFChars(env,input_jstr,NULL); const char* input_cstr = (*env)->GetStringUTFChars(env,input_jstr,NULL);
LOGI("input_cstr=%s", input_cstr); LOGI(TAG, "input_cstr=%s", input_cstr);
//注册组件 //注册组件
av_register_all(); av_register_all();
AVFormatContext *pFormatCtx = avformat_alloc_context(); AVFormatContext *pFormatCtx = avformat_alloc_context();
//打开音频文件 //打开音频文件
if(avformat_open_input(&pFormatCtx,input_cstr,NULL,NULL) != 0){ if(avformat_open_input(&pFormatCtx,input_cstr,NULL,NULL) != 0){
LOGI("%s","无法打开音频文件"); LOGE(TAG, "无法打开音频文件");
return; return;
} }
//获取输入文件信息 //获取输入文件信息
if(avformat_find_stream_info(pFormatCtx,NULL) < 0){ if(avformat_find_stream_info(pFormatCtx,NULL) < 0){
LOGI("%s","无法获取输入文件信息"); LOGE(TAG, "无法获取输入文件信息");
return; return;
} }
//获取音频流索引位置 //获取音频流索引位置
@ -50,12 +48,12 @@ JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_play
AVCodecContext *codecCtx = pFormatCtx->streams[audio_stream_idx]->codec; AVCodecContext *codecCtx = pFormatCtx->streams[audio_stream_idx]->codec;
AVCodec *codec = avcodec_find_decoder(codecCtx->codec_id); AVCodec *codec = avcodec_find_decoder(codecCtx->codec_id);
if(codec == NULL){ if(codec == NULL){
LOGI("%s","无法获取解码器"); LOGE(TAG, "无法获取解码器");
return; return;
} }
//打开解码器 //打开解码器
if(avcodec_open2(codecCtx,codec,NULL) < 0){ if(avcodec_open2(codecCtx,codec,NULL) < 0){
LOGI("%s","无法打开解码器"); LOGE(TAG, "无法打开解码器");
return; return;
} }
//压缩数据 //压缩数据
@ -87,16 +85,16 @@ JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_play
//输出的声道个数 //输出的声道个数
int out_channel_nb = av_get_channel_layout_nb_channels(out_ch_layout); int out_channel_nb = av_get_channel_layout_nb_channels(out_ch_layout);
jclass player_class = (*env)->GetObjectClass(env,jthiz); jclass player_class = (*env)->GetObjectClass(env,thiz);
if(!player_class){ if(!player_class){
LOGE("player_class not found..."); LOGE(TAG, "player_class not found...");
} }
//AudioTrack对象 //AudioTrack对象
jmethodID audio_track_method = (*env)->GetMethodID(env,player_class,"createAudioTrack","(II)Landroid/media/AudioTrack;"); jmethodID audio_track_method = (*env)->GetMethodID(env,player_class,"createAudioTrack","(II)Landroid/media/AudioTrack;");
if(!audio_track_method){ if(!audio_track_method){
LOGE("audio_track_method not found..."); LOGE(TAG, "audio_track_method not found...");
} }
jobject audio_track = (*env)->CallObjectMethod(env,jthiz,audio_track_method,out_sample_rate,out_channel_nb); jobject audio_track = (*env)->CallObjectMethod(env,thiz,audio_track_method,out_sample_rate,out_channel_nb);
//调用play方法 //调用play方法
jclass audio_track_class = (*env)->GetObjectClass(env,audio_track); jclass audio_track_class = (*env)->GetObjectClass(env,audio_track);
@ -121,7 +119,7 @@ JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_play
} }
//解码一帧成功 //解码一帧成功
if(got_frame > 0){ if(got_frame > 0){
LOGI("decode frame count=%d",index++); LOGI(TAG, "decode frame count=%d", index++);
//音频格式转换 //音频格式转换
swr_convert(swrCtx, &out_buffer, MAX_AUDIO_FRAME_SIZE,(const uint8_t **)frame->data,frame->nb_samples); swr_convert(swrCtx, &out_buffer, MAX_AUDIO_FRAME_SIZE,(const uint8_t **)frame->data,frame->nb_samples);
int out_buffer_size = av_samples_get_buffer_size(NULL, out_channel_nb, int out_buffer_size = av_samples_get_buffer_size(NULL, out_channel_nb,
@ -143,7 +141,7 @@ JNIEXPORT void JNICALL Java_com_frank_ffmpeg_AudioPlayer_play
} }
av_free_packet(packet); av_free_packet(packet);
} }
LOGI("decode audio finish"); LOGI(TAG, "decode audio finish");
av_frame_free(&frame); av_frame_free(&frame);
av_free(out_buffer); av_free(out_buffer);
swr_free(&swrCtx); swr_free(&swrCtx);

@ -1,8 +1,8 @@
#include <jni.h> #include <jni.h>
#include "ffmpeg/ffmpeg.h" #include "ffmpeg/ffmpeg.h"
#include "ffmpeg_jni_define.h"
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_FFmpegCmd_handle FFMPEG_FUNC(jint, handle, jobjectArray commands) {
(JNIEnv *env, jclass obj, jobjectArray commands){
int argc = (*env)->GetArrayLength(env, commands); int argc = (*env)->GetArrayLength(env, commands);
char **argv = (char**)malloc(argc * sizeof(char*)); char **argv = (char**)malloc(argc * sizeof(char*));
int i; int i;

@ -0,0 +1,25 @@
//
// Created by frank on 2019/11/9.
//
#ifndef FFMPEGANDROID_FFMPEG_JNI_DEFINE_H
#define FFMPEGANDROID_FFMPEG_JNI_DEFINE_H
#include <android/log.h>
#define LOGI(TAG, FORMAT, ...) __android_log_print(ANDROID_LOG_INFO, TAG, FORMAT, ##__VA_ARGS__);
#define LOGE(TAG, FORMAT,...) __android_log_print(ANDROID_LOG_ERROR, TAG, FORMAT, ##__VA_ARGS__);
#define AUDIO_PLAYER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_AudioPlayer_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#define FFMPEG_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_FFmpegCmd_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#define VIDEOO_PLAYER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_VideoPlayer_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#endif //FFMPEGANDROID_FFMPEG_JNI_DEFINE_H

@ -10,32 +10,31 @@
#include <unistd.h> #include <unistd.h>
#include <libavutil/imgutils.h> #include <libavutil/imgutils.h>
#include <android/log.h> #include <android/log.h>
#include "ffmpeg_jni_define.h"
#define TAG "MediaPlayer" #define TAG "VideoPlayer"
#define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO, TAG, FORMAT, ##__VA_ARGS__);
#define LOGE(FORMAT,...) __android_log_print(ANDROID_LOG_ERROR, TAG, FORMAT, ##__VA_ARGS__);
//播放倍率 //播放倍率
float play_rate = 1; float play_rate = 1;
//视频总时长 //视频总时长
long duration = 0; long duration = 0;
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_play VIDEOO_PLAYER_FUNC(jint, play, jstring filePath, jobject surface){
(JNIEnv * env, jclass clazz, jstring filePath, jobject surface){
const char * file_name = (*env)->GetStringUTFChars(env, filePath, JNI_FALSE); const char * file_name = (*env)->GetStringUTFChars(env, filePath, JNI_FALSE);
LOGE(TAG, "open file:%s\n", file_name);
//注册所有组件 //注册所有组件
av_register_all(); av_register_all();
//分配上下文 //分配上下文
AVFormatContext * pFormatCtx = avformat_alloc_context(); AVFormatContext * pFormatCtx = avformat_alloc_context();
//打开视频文件 //打开视频文件
if(avformat_open_input(&pFormatCtx, file_name, NULL, NULL)!=0) { if(avformat_open_input(&pFormatCtx, file_name, NULL, NULL)!=0) {
LOGE("Couldn't open file:%s\n", file_name); LOGE(TAG, "Couldn't open file:%s\n", file_name);
return -1; return -1;
} }
//检索多媒体流信息 //检索多媒体流信息
if(avformat_find_stream_info(pFormatCtx, NULL)<0) { if(avformat_find_stream_info(pFormatCtx, NULL)<0) {
LOGE("Couldn't find stream information."); LOGE(TAG, "Couldn't find stream information.");
return -1; return -1;
} }
//寻找视频流的第一帧 //寻找视频流的第一帧
@ -47,14 +46,14 @@ JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_play
} }
} }
if(videoStream==-1) { if(videoStream==-1) {
LOGE("couldn't find a video stream."); LOGE(TAG, "couldn't find a video stream.");
return -1; return -1;
} }
//获取视频总时长 //获取视频总时长
if (pFormatCtx->duration != AV_NOPTS_VALUE) { if (pFormatCtx->duration != AV_NOPTS_VALUE) {
duration = (long) (pFormatCtx->duration / AV_TIME_BASE); duration = (long) (pFormatCtx->duration / AV_TIME_BASE);
LOGE("duration=%d", duration); LOGE(TAG, "duration==%ld", duration);
} }
//获取codec上下文指针 //获取codec上下文指针
@ -62,11 +61,11 @@ JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_play
//寻找视频流的解码器 //寻找视频流的解码器
AVCodec * pCodec = avcodec_find_decoder(pCodecCtx->codec_id); AVCodec * pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL) { if(pCodec==NULL) {
LOGE("couldn't find Codec."); LOGE(TAG, "couldn't find Codec.");
return -1; return -1;
} }
if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
LOGE("Couldn't open codec."); LOGE(TAG, "Couldn't open codec.");
return -1; return -1;
} }
// 获取native window // 获取native window
@ -78,14 +77,14 @@ JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_play
ANativeWindow_setBuffersGeometry(nativeWindow, videoWidth, videoHeight, WINDOW_FORMAT_RGBA_8888); ANativeWindow_setBuffersGeometry(nativeWindow, videoWidth, videoHeight, WINDOW_FORMAT_RGBA_8888);
ANativeWindow_Buffer windowBuffer; ANativeWindow_Buffer windowBuffer;
if(avcodec_open2(pCodecCtx, pCodec, NULL)<0) { if(avcodec_open2(pCodecCtx, pCodec, NULL)<0) {
LOGE("Couldn't open codec."); LOGE(TAG, "Couldn't open codec.");
return -1; return -1;
} }
//申请内存 //申请内存
AVFrame * pFrame = av_frame_alloc(); AVFrame * pFrame = av_frame_alloc();
AVFrame * pFrameRGBA = av_frame_alloc(); AVFrame * pFrameRGBA = av_frame_alloc();
if(pFrameRGBA == NULL || pFrame == NULL) { if(pFrameRGBA == NULL || pFrame == NULL) {
LOGE("Couldn't allocate video frame."); LOGE(TAG, "Couldn't allocate video frame.");
return -1; return -1;
} }
// buffer中数据用于渲染,且格式为RGBA // buffer中数据用于渲染,且格式为RGBA
@ -149,13 +148,11 @@ JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_play
} }
//设置播放速率 //设置播放速率
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_setPlayRate VIDEOO_PLAYER_FUNC(jint, setPlayRate, jfloat playRate){
(JNIEnv * env, jclass clazz, jfloat playRate){
play_rate = playRate; play_rate = playRate;
} }
//获取视频总时长 //获取视频总时长
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_getDuration VIDEOO_PLAYER_FUNC(jint, getDuration){
(JNIEnv * env, jclass clazz){
return duration; return duration;
} }
Loading…
Cancel
Save