AudioFile_PlayDeal.c 6.2 KB
#include "libavutil/opt.h"
#include "libavutil/channel_layout.h"
#include "libavutil/samplefmt.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavcodec/avcodec.h"



#include <stdio.h>
#include "JZsdkLib.h"
#include "Megaphone/Megaphone.h"

#include "AudioDeal/AudioDeal.h"
#include "./AudioFile_PlayDeal.h"
#include "AudioDeal/FF_Statement.h"

//音频文件直接播放
T_JZsdkReturnCode AudioFile_StartPlay_Interface(unsigned char* FilePath)
{
    T_JZsdkReturnCode jzret;

    //1、检测这个文件是否存在
    jzret = JZsdk_check_file_exists((const char *)FilePath);
    if (jzret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
    {
        JZSDK_LOG_INFO("播放文件不存在");
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }

    //2、创建音频解码器
    const AVCodec *codec;  
    AVCodecContext *codec_ctx = NULL;  
    
    double total_duration = 0; // 累计播放时间(秒)  
    int last_printed_second = -1; // 上次打印的秒数,初始化为-1表示还没有打印过  
    
    //3、创建一个音频上下文
    AVFormatContext *fmt_ctx = avformat_alloc_context();
    if (!fmt_ctx) {
        JZSDK_LOG_ERROR("无法分配AVFormatContext");
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }

    //4、打开输出的音频文件
    int ret = avformat_open_input(&fmt_ctx, FilePath, NULL, NULL);
    if (ret < 0) {
        JZSDK_LOG_ERROR("歌曲播放文件打开失败");
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }

    //5、检索音频的流信息  
    if (avformat_find_stream_info(fmt_ctx, NULL) < 0) 
    {
        JZSDK_LOG_ERROR("检索音频的流信息失败");
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }

    //6、找到音频流信息
    ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
    if (ret < 0) {
        JZSDK_LOG_ERROR("无法从文件中找到音频流信息 %d",ret);
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }
    int audio_stream_index = ret;

    // //7、查找解码器  
    // codec = avcodec_find_decoder(fmt_ctx->streams[audio_stream_index]->codecpar->codec_id);  
    // if (!codec) 
    // {  
    //     JZSDK_LOG_ERROR("无法找到解码器");
    //     return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    // }  
  
    //8、分配解码器上下文
    codec_ctx = avcodec_alloc_context3(codec);  
    if (!codec_ctx) {  
        JZSDK_LOG_ERROR("Could not allocate audio codec context");  
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }  
    if (avcodec_parameters_to_context(codec_ctx, fmt_ctx->streams[audio_stream_index]->codecpar) < 0) 
    {  
        JZSDK_LOG_ERROR("Could not copy codec parameters to decoder context");  
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }  
    codec_ctx->pkt_timebase = fmt_ctx->streams[audio_stream_index]->time_base;

    //9、打开解码器  
    if (avcodec_open2(codec_ctx, codec, NULL) < 0) {  
        JZSDK_LOG_ERROR("Could not open codec");  
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }  

    //10、分配AVPacket和AVFrame
    AVPacket *packet = av_packet_alloc();
    AVFrame *frame = av_frame_alloc();
    
    if (!packet || !frame) 
    {  
        JZSDK_LOG_ERROR("Could not allocate packet or frame");  
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }  

    //如果此次输入的音频数据不同于采样的当前设置,重设采样
    AudioDeal_ResampleRest(codec_ctx->sample_rate, codec_ctx->ch_layout, codec_ctx->sample_fmt);

    printf("开始读取内容\n");
    int Last_duration = 0;

    //读取,并解码歌曲数据
	while (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_ON)
    {  
        //读取音频内容
        if (av_read_frame(fmt_ctx, packet) < 0) //没有正常取出数据包
        {
            //执行读取数据完毕之类的操作
            JZSDK_LOG_ERROR("没有正常取出数据包");  
            break;
        }

        //如果音频流指引值不相同
        if (packet->stream_index != audio_stream_index)
        {
            av_packet_unref(packet);  
            continue;
        }
        
        // 发送数据包到解码器  
        ret = avcodec_send_packet(codec_ctx, packet);  
        if (ret < 0) 
        {  
            char errbuf[128];  
            av_strerror(ret, errbuf, sizeof(errbuf));
            JZSDK_LOG_ERROR("Error while sending a packet to the decoder %s",errbuf);  
            break;  
        }  

        while ((ret >= 0) && (Megaphone_MegDataGenFlag(JZ_FLAGCODE_GET, 0) == JZ_FLAGCODE_ON))
        {
            ret = avcodec_receive_frame(codec_ctx, frame);  
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)  
            {
                //JZSDK_LOG_ERROR("解码完毕");
                break; 
            }     

            else if (ret < 0) 
            {  
                JZSDK_LOG_ERROR("Error while receiving a frame from the decoder\n");  
                break;  
            }      

            // 计算当前帧的持续时间(秒)  
            double frame_duration = (double)frame->nb_samples / codec_ctx->sample_rate;  

            // 累计总持续时间  
            total_duration += frame_duration;  
            //JZSDK_LOG_INFO("当前播放时间%f",total_duration);


            // 检查是否需要打印  
            int current_second = (int)floor(total_duration); // 获取当前总时间的整数秒部分  
            if (current_second > last_printed_second)  
            {  
                printf("nb:%d rate:%d duration:%f total_duration:%f\n", frame->nb_samples, codec_ctx->sample_rate, frame_duration, current_second);  
                last_printed_second = current_second; // 更新上次打印的秒数  
            }  
            
            AudioFile_Stream_DataInput(frame);
        }
        
        av_packet_unref(packet);
    
    }

    printf("歌曲数据处理完毕 total_duration %f\n",total_duration);

    // 清理资源  
    av_frame_free(&frame);  
    av_packet_free(&packet);  
    avcodec_free_context(&codec_ctx);  
    avformat_close_input(&fmt_ctx);  

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}