AndroidStudio集成FFmpeg,实现音视频同步--FFmpeg实现音频播放

上篇学习了视频的播放,这篇学习音频的播放;关于音频还需要了解音频的一些知识,这里推荐一篇博客:https://blog.csdn.net/fireroll/article/details/83032025

音频播放大致流程和视频是同样的;

代码中只是将MP3文件解码后转换为原数据保存到文件了并没有做播放功能,这里只贴出音频转化代码,详细代码上传GitHub:https://github.com/YWeiY/MyPlayer



Java_com_yan_myplayer2_AudioPlayer_native_1start(JNIEnv *env, jobject instance, jstring input_,

                                                jstring output_) {

    const char *input = env->GetStringUTFChars(input_, 0);

    const char *output = env->GetStringUTFChars(output_, 0);

    // 初始化网络模块

    avformat_network_init();

    // 打开音频文件

    AVFormatContext *avFormatContext = avformat_alloc_context();

    if (avformat_open_input(&avFormatContext, input, NULL, NULL) != 0) {

        LOGI("%s","无法打开音频文件");

        return;

    }

    // 获取输入文件信息

    if (avformat_find_stream_info(avFormatContext, NULL) < 0) {

        LOGI("%s","无法获取输入文件信息");

        return;

    }

    // 获取音频时长

    int audio_stream_idx = -1;

    for (int i = 0; i < avFormatContext->nb_streams; ++i) {

        if (avFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {

            audio_stream_idx = i;

            break;

        }

    }

    // 获取解码参数

    AVCodecParameters *avCodecParameters = avFormatContext->streams[audio_stream_idx]->codecpar;

    //获取解码器

    AVCodec *avCodec = avcodec_find_decoder(avCodecParameters->codec_id);

    // 解码器上下文

    AVCodecContext *avCodecContext = avcodec_alloc_context3(avCodec);

    // 将解码参数和解码器上下文绑定

    avcodec_parameters_to_context(avCodecContext, avCodecParameters);

    avcodec_open2(avCodecContext, avCodec, NULL);

    // 读取音频数据包

    AVPacket *avPacket = av_packet_alloc();

    // 设置数据转换配置

    SwrContext *swrContext = swr_alloc();

    int64_t out_ch_layout = AV_CH_LAYOUT_STEREO;//输出声道布局

    AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;//输出采样格式

    int out_sample_rate = 44100;//输出采样率

    int64_t in_ch_layout = avCodecContext->channel_layout; // 输入声道布局

    AVSampleFormat in_sample_fmt = avCodecContext->sample_fmt;// 输入采样格式

    int in_sample_rate = avCodecContext->sample_rate;// 输入采样率

    swr_alloc_set_opts(swrContext, out_ch_layout, out_sample_fmt, out_sample_rate, in_ch_layout,

                      in_sample_fmt, in_sample_rate, 0, NULL);

    // 初始化转化器默认参数

    swr_init(swrContext);

    int count = 0;

    // 初始化一个缓存区容器

    uint8_t *out_buffer = (uint8_t *) (av_malloc(2 * 44100));

    // 打开

    FILE *file = fopen(output, "wb");

    while (av_read_frame(avFormatContext, avPacket) >= 0) {

        avcodec_send_packet(avCodecContext, avPacket);

        AVFrame *avFrame = av_frame_alloc();

        int ret = avcodec_receive_frame(avCodecContext, avFrame);

        if (ret == AVERROR(EAGAIN)) {

            continue;

        } else if (ret < 0) {

            LOGE("解码完成");

            break;

        }

        if (avPacket->stream_index != audio_stream_idx) {

            continue;

        }

        LOGE("正在解码%d",count++);

        // frame --> 转换为统一格式

        swr_convert(swrContext, &out_buffer, 2 * 44100,

                    (const uint8_t **) (avFrame->data), avFrame->nb_samples);

        int nb_channels = av_get_channel_layout_nb_channels(out_ch_layout);

        // 计算缓冲区大小

        int buffer_count = av_samples_get_buffer_size(NULL, nb_channels, avFrame->nb_samples,

                                                      out_sample_fmt, 1);

        // out_buffer --> FILE 输出到文件

        fwrite(out_buffer, 1, buffer_count, file);

    }

    // 关闭

    fclose(file);

    av_free(out_buffer);

    swr_free(&swrContext);

    avcodec_close(avCodecContext);

    avformat_close_input(&avFormatContext);

    env->ReleaseStringUTFChars(input_, input);

    env->ReleaseStringUTFChars(output_, output);

}

你可能感兴趣的:(AndroidStudio集成FFmpeg,实现音视频同步--FFmpeg实现音频播放)