File_Stream_deal.c 7.1 KB
#include "AudioDeal/FF_Statement.h"
#include "../Resample/pcm_Resample.h"
#include "AudioDeal/AudioDeal.h"
#include "AudioDeal/Filter/FF_Filter.h"

#include "JZsdkLib.h"
#include "AudioDeal/Alsa/pcm_AlsaPlay.h"

/******************************
 * 
 *  用于处理mp3流的.c
 *   输入mp3数据 → 解码成pcm → pcm流处理模块
 * 
 * ******************************/

static AVCodecParserContext *parser = NULL;
static AVCodecContext *cdc_ctx = NULL;
static AVPacket *pkt;
static AVFrame *decoded_frame = NULL;
static const AVCodec *codec;

T_JZsdkReturnCode Stream_Player_decode(struct AudioDealInfo *AD_Info, AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame);

T_JZsdkReturnCode File_Stream_deal_Init(enum AVCodecID id)
{
    //注册包
    pkt = av_packet_alloc();
    if(!pkt)
    {
        JZSDK_LOG_ERROR("av_packet_alloc failed.");
    }

    //寻找解码器
    codec = avcodec_find_decoder(id);
    if (!codec) {
        JZSDK_LOG_ERROR("Codec not found\n");
    }

    //获得裸流的解析器
    parser = av_parser_init(codec->id);
    if (!parser) {
        JZSDK_LOG_ERROR("Parser not found\n");
    }

    //分配解码上下文
    cdc_ctx = avcodec_alloc_context3(codec);
    if (!cdc_ctx) {
        JZSDK_LOG_ERROR("Could not allocate audio codec context\n");
    }

    //将解码器和解码上下文绑定
    if (avcodec_open2(cdc_ctx, codec, NULL) < 0) 
    {
        JZSDK_LOG_ERROR("Could not open codec\n");
    }

    JZSDK_LOG_INFO("file stream init complete");

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

//输入mp3的实时数据,以及本次数据的长度
T_JZsdkReturnCode mp3_Stream_Interface_Mp3Data(struct AudioDealInfo *AD_Info, unsigned int in_sampleRate, unsigned char *data, int dataSize)
{
    //JZSDK_LOG_DEBUG("mp3_Stream_Interface_Mp3Data");

    T_JZsdkReturnCode ret = JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;

    //将数据输入到
    while(dataSize > 0 && (AD_Info->AudioDeal_ResampleAndFilter_Execute_Flag == JZ_FLAGCODE_ON)) 
    {
        //printf("开始解码\n");

        //如果解码器不存在,初始化解码器
        if (!decoded_frame) 
        {
            if (!(decoded_frame = av_frame_alloc())) 
            {
                JZSDK_LOG_ERROR("Could not allocate audio frame\n");
                return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
            }
        }

        //printf("alloc后\n");

        //检查参数,并将正确的数据输入到pkt中
        //parser 解析器
        //cdc_ctx 上下文
        //pkt输出的数据指针
        //data datasize 输入的数据指针
        //pts、dts、pos:时间戳和位置信息,一般可以设置为AV_NOPTS_VALUE和0。
        int ret = av_parser_parse2(parser, cdc_ctx, &pkt->data, &pkt->size, data, dataSize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
        if (ret < 0) {
            JZSDK_LOG_ERROR("Error while parsing\n");
            return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
        }

        //printf("av_parser_parse2\n");

        //重置重采样器
        FF_Resample_Reset(AD_Info, in_sampleRate, (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO, AV_SAMPLE_FMT_S16);

        //printf("FF_Resample_Reset\n");
     
        //检查滤波器
        FF_Filter_Init(AD_Info, 0x01);

        //printf("FF_Filter_Init %d \n", pkt->size );
        
        //数据指针 往后一个解析长度
        //长度指针 减少一个被解析数据的长度
        data     += ret;
        dataSize -= ret;
        
        //如果输出有长度 解码输出的数据
        if (pkt->size > 0) 
        {
            ret = Stream_Player_decode(AD_Info, cdc_ctx, pkt, decoded_frame);
            if(ret == JZ_ERROR_SYSTEM_MODULE_CODE_HARDLY_FAILURE)
            {
                return JZ_ERROR_SYSTEM_MODULE_CODE_HARDLY_FAILURE;
            }
        }
    }

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}


//

T_JZsdkReturnCode Stream_Player_decode(struct AudioDealInfo *AD_Info, AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame)
{
    int ret;

    //JZSDK_LOG_DEBUG("Stream_Player_decode");

    //发送数据包给解码器解码,已将数据解码为pcm原始数据
    ret = avcodec_send_packet(dec_ctx, pkt);
    if (ret < 0) 
    {
        JZSDK_LOG_ERROR("Error submitting the packet to the decoder, ret=%d\n",ret);
        //return JZ_ERROR_SYSTEM_MODULE_CODE_HARDLY_FAILURE;
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }

    //申请内存
    AVFrame *eq_frame = av_frame_alloc();
    AVFrame *temp_frame = av_frame_alloc();

    //JZSDK_LOG_DEBUG("alloc");

    /* read all the output frames (in general there may be any number of them */
    //读取输出的帧
    while ( (ret >= 0) && (AD_Info->AudioDeal_ResampleAndFilter_Execute_Flag == JZ_FLAGCODE_ON) ) 
    {
        //从解码器中读取解码后的音频帧数据
        ret = avcodec_receive_frame(dec_ctx, frame);
        //输出帧不可用 、 输出帧 已用完
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) 
        {   
            continue;
        }
        else if (ret < 0) 
        {
            JZSDK_LOG_ERROR("Error during decoding\n");

            //释放掉输出的变量
            av_frame_free(&eq_frame);
            av_frame_free(&temp_frame);

            //JZSDK_LOG_DEBUG("提前释放后\n");

            return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
        }
        
        int out_nb_samples = 0;

        //JZSDK_LOG_DEBUG("播放前");
        
        //重采样解码后的数据
        void* resampledData = FF_Resample_Send_And_Get_ResampleData(AD_Info, frame->data, frame->nb_samples, &out_nb_samples);

        //滤波
        if(AD_Info->FilterMode != JZ_FLAGCODE_OFF)
        {
            temp_frame->data[0] = (unsigned char*)resampledData;
            temp_frame->nb_samples = out_nb_samples;

            //将临时帧 放入 均衡滤波器
            FF_Filter_push_frame_to_fliter(AD_Info, temp_frame);

            while(AD_Info->AudioDeal_ResampleAndFilter_Execute_Flag == JZ_FLAGCODE_ON)
            {
                //得到滤波器输出的音频帧 eq_frame
                int fret = FF_Filter_get_frame_from_filter(AD_Info, eq_frame);
                if (fret != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
                {
                    break;
                }

                //播放改滤波后的帧
                Pcm_AlsaPlay(AD_Info, (unsigned char*)eq_frame->data[0], eq_frame->nb_samples);

                av_frame_unref(eq_frame);
            }

            av_frame_unref(temp_frame);
        }
        else //不滤波
        {
            //直接播放
            //JZSDK_LOG_INFO("播放 %d 数据",out_nb_samples);
            Pcm_AlsaPlay(AD_Info ,resampledData, out_nb_samples);
        }

        FF_Resample_freeReasmpleData(resampledData);
    }

    //JZSDK_LOG_DEBUG("怀疑释放前\n");

    //释放掉输出的变量
    av_frame_unref(temp_frame);
    av_frame_unref(eq_frame);

    //JZSDK_LOG_DEBUG("怀疑释放后\n");
}

T_JZsdkReturnCode mp3_Stream_Interface_Mp3Data_Stop(struct AudioDealInfo *AD_Info)
{
    // pkt->data = NULL;
    // pkt->size = 0;
    // Stream_Player_decode(AD_Info, cdc_ctx, pkt, decoded_frame);
}