video_filter改为jni宏定义调用

video_filter改为jni宏定义调用
pull/107/head
xufulong 6 years ago
parent 9631b44b71
commit 603629010e
  1. 14
      app/src/main/cpp/ffmpeg_jni_define.h
  2. 58
      app/src/main/cpp/video_filter.c
  3. 6
      app/src/main/cpp/video_player.c
  4. 2
      app/src/main/java/com/frank/ffmpeg/VideoPlayer.java

@ -18,8 +18,20 @@
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_FFmpegCmd_ ## FUNC_NAME \ JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_FFmpegCmd_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\ (JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#define VIDEOO_PLAYER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \ #define VIDEO_PLAYER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_VideoPlayer_ ## FUNC_NAME \ JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_VideoPlayer_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\ (JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#define MEDIA_PLAYER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_MediaPlayer_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#define PUSHER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_Pusher_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__);\
} \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_Pusher_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#endif //FFMPEGANDROID_FFMPEG_JNI_DEFINE_H #endif //FFMPEGANDROID_FFMPEG_JNI_DEFINE_H

@ -15,10 +15,9 @@
#include <libavfilter/avfiltergraph.h> #include <libavfilter/avfiltergraph.h>
#include <libavutil/opt.h> #include <libavutil/opt.h>
#include "libswresample/swresample.h" #include "libswresample/swresample.h"
#include "ffmpeg_jni_define.h"
#define TAG "VideoFilter" #define TAG "VideoFilter"
#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__);
AVFilterContext *buffersink_ctx; AVFilterContext *buffersink_ctx;
@ -107,7 +106,7 @@ int init_filters(const char *filters_descr) {
ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
args, NULL, filter_graph); args, NULL, filter_graph);
if (ret < 0) { if (ret < 0) {
LOGE("Cannot create buffer source\n"); LOGE(TAG, "Cannot create buffer source\n");
goto end; goto end;
} }
@ -115,14 +114,14 @@ int init_filters(const char *filters_descr) {
ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
NULL, NULL, filter_graph); NULL, NULL, filter_graph);
if (ret < 0) { if (ret < 0) {
LOGE("Cannot create buffer sink\n"); LOGE(TAG, "Cannot create buffer sink\n");
goto end; goto end;
} }
ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts, ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,
AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) { if (ret < 0) {
LOGE("Cannot set output pixel format\n"); LOGE(TAG, "Cannot set output pixel format\n");
goto end; goto end;
} }
@ -152,19 +151,19 @@ int init_filters(const char *filters_descr) {
//初始化视频解码器与播放器 //初始化视频解码器与播放器
int open_input(JNIEnv * env, const char* file_name, jobject surface){ int open_input(JNIEnv * env, const char* file_name, jobject surface){
LOGI("open file:%s\n", file_name); LOGI(TAG, "open file:%s\n", file_name);
//注册所有组件 //注册所有组件
av_register_all(); av_register_all();
//分配上下文 //分配上下文
pFormatCtx = avformat_alloc_context(); 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;
} }
//寻找视频流的第一帧 //寻找视频流的第一帧
@ -176,7 +175,7 @@ int open_input(JNIEnv * env, const char* file_name, jobject surface){
} }
} }
if(video_stream_index == -1) { if(video_stream_index == -1) {
LOGE("couldn't find a video stream."); LOGE(TAG, "couldn't find a video stream.");
return -1; return -1;
} }
@ -185,11 +184,11 @@ int open_input(JNIEnv * env, const char* file_name, jobject surface){
//寻找视频流的解码器 //寻找视频流的解码器
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
@ -201,7 +200,7 @@ int open_input(JNIEnv * env, const char* file_name, jobject surface){
pFrame = av_frame_alloc(); pFrame = av_frame_alloc();
pFrameRGBA = av_frame_alloc(); 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
@ -240,12 +239,12 @@ int init_audio(JNIEnv * env, jclass jthiz){
audioCodecCtx = pFormatCtx->streams[audio_stream_index]->codec; audioCodecCtx = pFormatCtx->streams[audio_stream_index]->codec;
AVCodec *codec = avcodec_find_decoder(audioCodecCtx->codec_id); AVCodec *codec = avcodec_find_decoder(audioCodecCtx->codec_id);
if(codec == NULL){ if(codec == NULL){
LOGI("%s","无法获取音频解码器"); LOGE(TAG, "无法获取音频解码器");
return -1; return -1;
} }
//打开音频解码器 //打开音频解码器
if(avcodec_open2(audioCodecCtx,codec,NULL) < 0){ if(avcodec_open2(audioCodecCtx,codec,NULL) < 0){
LOGI("%s","无法打开音频解码器"); LOGE(TAG, "无法打开音频解码器");
return -1; return -1;
} }
//frame->16bit 44100 PCM 统一音频采样格式与采样率 //frame->16bit 44100 PCM 统一音频采样格式与采样率
@ -275,13 +274,13 @@ int init_audio(JNIEnv * env, jclass jthiz){
jclass player_class = (*env)->GetObjectClass(env,jthiz); jclass player_class = (*env)->GetObjectClass(env,jthiz);
if(!player_class){ if(!player_class){
LOGE("player_class not found..."); LOGE(TAG, "player_class not found...");
return -1; return -1;
} }
//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...");
return -1; return -1;
} }
audio_track = (*env)->CallObjectMethod(env,jthiz,audio_track_method,out_sample_rate,out_channel_nb); audio_track = (*env)->CallObjectMethod(env,jthiz,audio_track_method,out_sample_rate,out_channel_nb);
@ -328,30 +327,29 @@ int play_audio(JNIEnv * env, AVPacket* packet, AVFrame* frame){
return 0; return 0;
} }
JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_filter VIDEO_PLAYER_FUNC(jint, filter, jstring filePath, jobject surface, jstring filterDescr){
(JNIEnv * env, jclass clazz, jstring filePath, jobject surface, jstring filterDescr){
int ret; int ret;
const char * file_name = (*env)->GetStringUTFChars(env, filePath, JNI_FALSE); const char * file_name = (*env)->GetStringUTFChars(env, filePath, JNI_FALSE);
const char *filter_descr = (*env)->GetStringUTFChars(env, filterDescr, JNI_FALSE); const char *filter_descr = (*env)->GetStringUTFChars(env, filterDescr, JNI_FALSE);
//打开输入文件 //打开输入文件
if(!is_playing){ if(!is_playing){
LOGI("open_input..."); LOGI(TAG, "open_input...");
if((ret = open_input(env, file_name, surface)) < 0){ if((ret = open_input(env, file_name, surface)) < 0){
LOGE("Couldn't allocate video frame."); LOGE(TAG, "Couldn't allocate video frame.");
goto end; goto end;
} }
//注册滤波器 //注册滤波器
avfilter_register_all(); avfilter_register_all();
filter_frame = av_frame_alloc(); filter_frame = av_frame_alloc();
if(filter_frame == NULL) { if(filter_frame == NULL) {
LOGE("Couldn't allocate filter frame."); LOGE(TAG, "Couldn't allocate filter frame.");
ret = -1; ret = -1;
goto end; goto end;
} }
//初始化音频解码器 //初始化音频解码器
if ((ret = init_audio(env, clazz)) < 0){ if ((ret = init_audio(env, thiz)) < 0){
LOGE("Couldn't init_audio."); LOGE(TAG, "Couldn't init_audio.");
goto end; goto end;
} }
@ -359,7 +357,7 @@ JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_filter
//初始化滤波器 //初始化滤波器
if ((ret = init_filters(filter_descr)) < 0){ if ((ret = init_filters(filter_descr)) < 0){
LOGE("init_filter error, ret=%d\n", ret); LOGE(TAG, "init_filter error, ret=%d\n", ret);
goto end; goto end;
} }
@ -380,7 +378,7 @@ JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_filter
if (frameFinished) { if (frameFinished) {
//把解码后视频帧添加到filter_graph //把解码后视频帧添加到filter_graph
if (av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { if (av_buffersrc_add_frame_flags(buffersrc_ctx, pFrame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) {
LOGE("Error while feeding the filter_graph\n"); LOGE(TAG, "Error while feeding the filter_graph\n");
break; break;
} }
//把滤波后的视频帧从filter graph取出来 //把滤波后的视频帧从filter graph取出来
@ -440,21 +438,21 @@ JNIEXPORT jint JNICALL Java_com_frank_ffmpeg_VideoPlayer_filter
ANativeWindow_release(nativeWindow); ANativeWindow_release(nativeWindow);
(*env)->ReleaseStringUTFChars(env, filePath, file_name); (*env)->ReleaseStringUTFChars(env, filePath, file_name);
(*env)->ReleaseStringUTFChars(env, filterDescr, filter_descr); (*env)->ReleaseStringUTFChars(env, filterDescr, filter_descr);
LOGE("do release..."); LOGE(TAG, "do release...");
again: again:
again = 0; again = 0;
LOGE("play again..."); LOGE(TAG, "play again...");
return ret; return ret;
} }
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_VideoPlayer_again(JNIEnv * env, jclass clazz) { VIDEO_PLAYER_FUNC(void, again) {
again = 1; again = 1;
} }
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_VideoPlayer_release(JNIEnv * env, jclass clazz) { VIDEO_PLAYER_FUNC(void, release) {
release = 1; release = 1;
} }
JNIEXPORT void JNICALL Java_com_frank_ffmpeg_VideoPlayer_playAudio(JNIEnv * env, jclass clazz, jboolean play_audio) { VIDEO_PLAYER_FUNC(void, playAudio, jboolean play_audio) {
playAudio = play_audio; playAudio = play_audio;
} }

@ -19,7 +19,7 @@ float play_rate = 1;
//视频总时长 //视频总时长
long duration = 0; long duration = 0;
VIDEOO_PLAYER_FUNC(jint, play, jstring filePath, jobject surface){ VIDEO_PLAYER_FUNC(jint, play, 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); LOGE(TAG, "open file:%s\n", file_name);
@ -148,11 +148,11 @@ VIDEOO_PLAYER_FUNC(jint, play, jstring filePath, jobject surface){
} }
//设置播放速率 //设置播放速率
VIDEOO_PLAYER_FUNC(jint, setPlayRate, jfloat playRate){ VIDEO_PLAYER_FUNC(void, setPlayRate, jfloat playRate){
play_rate = playRate; play_rate = playRate;
} }
//获取视频总时长 //获取视频总时长
VIDEOO_PLAYER_FUNC(jint, getDuration){ VIDEO_PLAYER_FUNC(jint, getDuration){
return duration; return duration;
} }

@ -15,7 +15,7 @@ public class VideoPlayer {
} }
public native int play(String filePath, Object surface); public native int play(String filePath, Object surface);
public native int setPlayRate(float playRate); public native void setPlayRate(float playRate);
public native int filter(String filePath, Object surface, String filterType); public native int filter(String filePath, Object surface, String filterType);
public native void again(); public native void again();

Loading…
Cancel
Save