From 51960d6815d619a1c5787f0137b6917cd146887d Mon Sep 17 00:00:00 2001 From: xufuji456 Date: Thu, 8 Sep 2022 10:54:33 +0800 Subject: [PATCH] Feature: change filter when playing --- app/src/main/cpp/audio_player.cpp | 6 +-- app/src/main/cpp/audio_player_jni.cpp | 31 +++++++++++----- app/src/main/cpp/ff_audio_player.cpp | 53 ++++++++++++++++++--------- app/src/main/cpp/ff_audio_player.h | 7 ++++ 4 files changed, 67 insertions(+), 30 deletions(-) diff --git a/app/src/main/cpp/audio_player.cpp b/app/src/main/cpp/audio_player.cpp index 23f88a9..4c17f5d 100644 --- a/app/src/main/cpp/audio_player.cpp +++ b/app/src/main/cpp/audio_player.cpp @@ -103,7 +103,7 @@ end: return ret; } -AUDIO_PLAYER_FUNC(void, play, jstring input_jstr, jstring filter_jstr) { +AUDIO_PLAYER_FUNC(void, play111, jstring input_jstr, jstring filter_jstr) { int got_frame = 0, ret; AVPacket packet; AVFilterGraph *audioFilterGraph; @@ -262,13 +262,13 @@ end: LOGE(TAG, "audio release..."); } -AUDIO_PLAYER_FUNC(void, again, jstring filter_jstr) { +AUDIO_PLAYER_FUNC(void, again111, jstring filter_jstr) { if (!filter_jstr) return; filter_again = 1; filter_desc = env->GetStringUTFChars(filter_jstr, nullptr); } -AUDIO_PLAYER_FUNC(void, release) { +AUDIO_PLAYER_FUNC(void, release111) { filter_release = 1; } diff --git a/app/src/main/cpp/audio_player_jni.cpp b/app/src/main/cpp/audio_player_jni.cpp index dcffe05..75c12ef 100644 --- a/app/src/main/cpp/audio_player_jni.cpp +++ b/app/src/main/cpp/audio_player_jni.cpp @@ -8,28 +8,31 @@ #define SLEEP_TIME (16000) +FFAudioPlayer *audioPlayer; + AUDIO_PLAYER_FUNC(void, play, jstring path) { if (path == nullptr) return; int result = 0; const char* native_path = env->GetStringUTFChars(path, JNI_FALSE); - auto *audioPlayer = new FFAudioPlayer(); - // 打开输入流 + audioPlayer = new FFAudioPlayer(); + // open stream, and init work audioPlayer->open(native_path); - // 初始化AudioTrack + // init AudioTrack jclass audio_class = env->GetObjectClass(thiz); jmethodID audio_track_method = env->GetMethodID(audio_class, "createAudioTrack", "(II)Landroid/media/AudioTrack;"); - jobject audio_track = env->CallObjectMethod(thiz, audio_track_method, audioPlayer->getSampleRate(), audioPlayer->getChannel()); - // 调用play函数 + jobject audio_track = env->CallObjectMethod(thiz, audio_track_method, + audioPlayer->getSampleRate(), audioPlayer->getChannel()); + // play function jclass audio_track_class = env->GetObjectClass(audio_track); jmethodID play_method = env->GetMethodID(audio_track_class, "play", "()V"); env->CallVoidMethod(audio_track, play_method); - // 获取write方法id + // method if of write jmethodID write_method = env->GetMethodID(audio_track_class, "write", "([BII)I"); - // 解码音频zhen + // demux decode and play while (result >= 0) { result = audioPlayer->decodeAudio(); if (result == 0) { @@ -38,7 +41,7 @@ AUDIO_PLAYER_FUNC(void, play, jstring path) { break; } int size = result; - // 调用AudioTrack播放(可优化:数组复用) + // call AudioTrack to play(should be reused array) jbyteArray audio_array = env->NewByteArray(size); jbyte *data_address = env->GetByteArrayElements(audio_array, JNI_FALSE); memcpy(data_address, audioPlayer->getDecodeFrame(), size); @@ -46,7 +49,7 @@ AUDIO_PLAYER_FUNC(void, play, jstring path) { env->CallIntMethod(audio_track, write_method, audio_array, 0, size); env->DeleteLocalRef(audio_array); - // 延时等待 + // audio sync usleep(SLEEP_TIME); } @@ -55,4 +58,12 @@ AUDIO_PLAYER_FUNC(void, play, jstring path) { env->CallVoidMethod(thiz, release_method); audioPlayer->close(); delete audioPlayer; -} \ No newline at end of file +} + +AUDIO_PLAYER_FUNC(void, again, jstring filter_jstr) { + if (!filter_jstr) return; + audioPlayer->setFilterAgain(true); + const char *desc = env->GetStringUTFChars(filter_jstr, nullptr); + audioPlayer->setFilterDesc(desc); +} + diff --git a/app/src/main/cpp/ff_audio_player.cpp b/app/src/main/cpp/ff_audio_player.cpp index f124a7d..b8fb658 100644 --- a/app/src/main/cpp/ff_audio_player.cpp +++ b/app/src/main/cpp/ff_audio_player.cpp @@ -87,15 +87,15 @@ int FFAudioPlayer::open(const char *path) { packet = av_packet_alloc(); out_buffer = new uint8_t [BUFFER_SIZE]; - // 打开输入流 + // open input stream ret = avformat_open_input(&formatContext, path, nullptr, nullptr); if (ret < 0) { LOGE(AUDIO_TAG, "avformat_open_input error=%s", av_err2str(ret)); return ret; } - // 查找stream信息 + // (if need)find info: width、height、sample_rate、duration avformat_find_stream_info(formatContext, nullptr); - // 找到音频index + // find audio index for (int i=0; inb_streams; i++) { if (AVMEDIA_TYPE_AUDIO == formatContext->streams[i]->codecpar->codec_type) { audio_index = i; @@ -105,30 +105,30 @@ int FFAudioPlayer::open(const char *path) { if (audio_index == -1) { return -1; } - // 找到codec + // find audio decoder codec = avcodec_find_decoder(formatContext->streams[audio_index]->codecpar->codec_id); codecContext = avcodec_alloc_context3(codec); avcodec_parameters_to_context(codecContext, formatContext->streams[audio_index]->codecpar); - // 打开解码器 + // open decoder ret = avcodec_open2(codecContext, codec, nullptr); if (ret < 0) { LOGE(AUDIO_TAG, "avcodec_open2 error=%s", av_err2str(ret)); return ret; } - // 输入:采样率、声道布局、音频格式 + // input and output params int in_sample_rate = codecContext->sample_rate; auto in_sample_fmt = codecContext->sample_fmt; int in_ch_layout = (int)codecContext->channel_layout; - out_sample_rate = in_sample_rate; // 输出采样率等于输入采样率 - out_sample_fmt = AV_SAMPLE_FMT_S16; // 16位 - out_ch_layout = AV_CH_LAYOUT_STEREO; // 双声道 + out_sample_rate = in_sample_rate; + out_sample_fmt = AV_SAMPLE_FMT_S16; + out_ch_layout = AV_CH_LAYOUT_STEREO; out_channel = codecContext->channels; - // 初始化音频格式转换上下文swrContext + // init resample context swrContext = swr_alloc(); swr_alloc_set_opts(swrContext, out_ch_layout, out_sample_fmt, out_sample_rate, in_ch_layout, in_sample_fmt, in_sample_rate, 0, nullptr); swr_init(swrContext); - + // init filter graph filterFrame = av_frame_alloc(); initFilter(FILTER_DESC, codecContext, &audioFilterGraph, &audioSrcContext, &audioSinkContext); @@ -146,16 +146,16 @@ int FFAudioPlayer::getSampleRate() const { int FFAudioPlayer::decodeAudio() { int ret; - // 读取音频数据(解封装) + // demux: read a frame(should be demux thread) ret = av_read_frame(formatContext, packet); if (ret < 0) { return ret; } - // 判断是否位音频帧 + // see if audio packet if (packet->stream_index != audio_index) { return 0; } - // 解码音频帧 + // decode audio frame(should be decode thread) ret = avcodec_send_packet(codecContext, packet); if (ret < 0) { LOGE(AUDIO_TAG, "avcodec_send_packet=%s", av_err2str(ret)); @@ -168,6 +168,17 @@ int FFAudioPlayer::decodeAudio() { return ret; } } + + if (filterAgain) { + filterAgain = false; + avfilter_graph_free(&audioFilterGraph); + if ((ret = initFilter(filterDesc, codecContext, &audioFilterGraph, &audioSrcContext, &audioSinkContext)) < 0) { + LOGE(AUDIO_TAG, "init_filter error, ret=%d\n", ret); + return ret; + } + LOGE(AUDIO_TAG, "play again,filter_descr=_=%s", filterDesc); + } + // put into filter ret = av_buffersrc_add_frame(audioSrcContext, inputFrame); if (ret < 0) { @@ -185,13 +196,13 @@ int FFAudioPlayer::decodeAudio() { return ret; } - // 音频格式转换 + // convert audio format and sample_rate swr_convert(swrContext, &out_buffer, BUFFER_SIZE, (const uint8_t **)(filterFrame->data), filterFrame->nb_samples); - // 获取转换后缓冲区大小 + // get buffer size after converting int buffer_size = av_samples_get_buffer_size(nullptr, out_channel, filterFrame->nb_samples, out_sample_fmt, 1); - LOGI(AUDIO_TAG, "buffer_size=%d", buffer_size); + av_frame_unref(inputFrame); av_frame_unref(filterFrame); av_packet_unref(packet); @@ -203,6 +214,14 @@ uint8_t *FFAudioPlayer::getDecodeFrame() const { return out_buffer; } +void FFAudioPlayer::setFilterAgain(bool again) { + filterAgain = again; +} + +void FFAudioPlayer::setFilterDesc(const char *filterDescription) { + filterDesc = filterDescription; +} + void FFAudioPlayer::close() { if (formatContext) { avformat_close_input(&formatContext); diff --git a/app/src/main/cpp/ff_audio_player.h b/app/src/main/cpp/ff_audio_player.h index 62d2024..61b1163 100644 --- a/app/src/main/cpp/ff_audio_player.h +++ b/app/src/main/cpp/ff_audio_player.h @@ -37,6 +37,9 @@ private: AVFrame *filterFrame; uint8_t *out_buffer; + bool filterAgain; + const char *filterDesc; + AVFilterGraph *audioFilterGraph; AVFilterContext *audioSrcContext; AVFilterContext *audioSinkContext; @@ -52,6 +55,10 @@ public: uint8_t *getDecodeFrame() const; + void setFilterAgain(bool again); + + void setFilterDesc(const char *filterDescription); + void close(); }; #endif //LEARNINGMEDIA_FF_AUDIO_PLAYER_H