How to conver PCM to aac @ 071's blog :: 隨意窩 Xuite日誌
    1. 沒有新回應!
  • 201903281044How to conver PCM to aac

    reference to follow url:

    【FFmpeg(2016)】PCM编码AAC

    http://www.voidcn.com/article/p-qrukcans-gc.html

    【FFmpeg(2016)】SwrContext重采样结构体

    http://www.voidcn.com/article/p-wcfuzehy-gc.html

    int convert_pcm2aac()
    {
    fprintf(stderr,"convert_pcm2aac ...\n");
    //char *padts = (char *)malloc(sizeof(char) * 7);
    //int profile = 2; //AAC LC
    //int freqIdx = 4; //44.1KHz
    //int chanCfg = 2; //MPEG-4 Audio Channel Configuration. 1 Channel front-center
    //padts[0] = (char)0xFF; // 11111111 = syncword
    //padts[1] = (char)0xF1; // 1111 1 00 1 = syncword MPEG-2 Layer CRC
    //padts[2] = (char)(((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2));
    //padts[6] = (char)0xFC;

    AVCodec *pCodec;
    AVCodecContext *pCodecCtx = NULL;
    int i, ret, got_output;
    FILE *fp_in;
    FILE *fp_out;

    AVFrame *pFrame;
    uint8_t* frame_buf;
    int size = 0;

    AVPacket pkt;
    //int y_size;
    int framecnt = 0;

    char filename_in[] = "audio.pcm";

    //AVCodecID codec_id = AV_CODEC_ID_AAC;
    char filename_out[] = "audio.aac";

    int framenum = 100000;

    //avcodec_register_all();

    pCodec = avcodec_find_encoder(AV_CODEC_ID_AAC); //codec_id
    if (!pCodec) {
    printf("Codec not found\n");
    return -1;
    }

    pCodecCtx = avcodec_alloc_context3(pCodec);
    if (!pCodecCtx) {
    fprintf(stderr,"Could not allocate video codec context \n");
    return -1;
    }

    pCodecCtx->codec_id = AV_CODEC_ID_AAC;
    pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;

    pCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
    pCodecCtx->sample_rate = 48000; //44100
    pCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
    pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
    //qDebug() << av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
    pCodecCtx->bit_rate = 32000;
    pCodecCtx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
    pCodecCtx->profile = FF_PROFILE_AAC_LOW;
    pCodecCtx->flags |= AV_CODEC_FLAG_BITEXACT | AV_CODEC_FLAG_QSCALE;

    if ((ret = avcodec_open2(pCodecCtx, pCodec, NULL)) < 0) {
    char error_text[255];
    av_strerror(ret, error_text, sizeof(error_text));
    fprintf(stderr, "Could not open codec failed: %s\n", error_text);
    return -1;
    }

    pFrame = av_frame_alloc();

    pFrame->nb_samples = pCodecCtx->frame_size; //1024,默认每一帧的采样个数是frame_size,貌似也改变不了
    pFrame->format = pCodecCtx->sample_fmt;
    pFrame->channels = 2;
    #ifdef SW_CONVERT
    /* 由 AV_SAMPLE_FMT_S16 转为AV_SAMPLE_FMT_FLTP */
    SwrContext *swr_ctx = NULL;
    swr_ctx = swr_alloc_set_opts(
    NULL,
    av_get_default_channel_layout(pCodecCtx->channels),
    pCodecCtx->sample_fmt, //在编码前,我希望的采样格式
    pCodecCtx->sample_rate,
    av_get_default_channel_layout(pCodecCtx->channels),
    AV_SAMPLE_FMT_S16, //PCM源文件的采样格式 , AV_SAMPLE_FMT_S16
    pCodecCtx->sample_rate,
    0, NULL);

    swr_init(swr_ctx);
    /* 分配空间 */
    uint8_t **convert_data; //存储转换后的数据,再编码AAC
    convert_data = (uint8_t**)calloc(pCodecCtx->channels,
    sizeof(*convert_data));
    av_samples_alloc(convert_data, NULL,
    pCodecCtx->channels, pCodecCtx->frame_size,
    pCodecCtx->sample_fmt, 0);
    #endif

    size = av_samples_get_buffer_size(NULL, pCodecCtx->channels, pCodecCtx->frame_size, pCodecCtx->sample_fmt, 0);
    frame_buf = (uint8_t *)av_malloc(size);
    /**
    * avcodec_fill_audio_frame 实现:
    * frame_buf是根据声道数、采样率和采样格式决定大小的。
    * 调用次函数后,AVFrame存储音频数据的成员有以下变化:data[0]指向frame_buf,data[1]指向frame_buf长度的一半位置
    * data[0] == frame_buf , data[1] == frame_buf + pCodecCtx->frame_size * av_get_bytes_per_sample(pCodecCtx->sample_fmt)
    */
    ret = avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt, (const uint8_t*)frame_buf, size, 0);

    if (ret < 0)
    {
    //qDebug() << "avcodec_fill_audio_frame error ";
    fprintf(stderr,"avcodec_fill_audio_frame error \n");
    return 0;
    }

    //Input raw data
    fp_in = fopen(filename_in, "rb");
    if (!fp_in) {
    //printf("Could not open %s\n", filename_in);
    fprintf(stderr,"Could not open %s \n",filename_in);
    return -1;
    }

    //Output bitstream
    fp_out = fopen(filename_out, "wb+");
    if (!fp_out) {
    //printf("Could not open %s\n", filename_out);
    fprintf(stderr,"Could not open %s \n",filename_out);
    return -1;
    }

    //Encode
    for (i = 0; i < framenum; i++) {
    av_init_packet(&pkt);
    pkt.data = NULL; // packet data will be allocated by the encoder
    pkt.size = 0;
    //Read raw data
    #ifdef SW_CONVERT
    if (fread(frame_buf, 1, size/2, fp_in) <= 0) { // read AV_SAMPLE_FMT_S16 data (2bytes per sample)
    #else
    if (fread(frame_buf, 1, size, fp_in) <= 0) { // read AV_SAMPLE_FMT_FLTP data (4bytes per sample)
    #endif
    //printf("Failed to read raw data! \n");
    fprintf(stderr,"Failed to read raw data! \n");
    return -1;
    }
    else if (feof(fp_in)) {
    break;
    }

    #ifdef SW_CONVERT
    /* 转换数据,令各自声道的音频数据存储在不同的数组(分别由不同指针指向)*/
    swr_convert(swr_ctx, convert_data, pCodecCtx->frame_size,
    (const uint8_t**)pFrame->data, pCodecCtx->frame_size);

    /* 将转换后的数据复制给pFrame */
    int length = pCodecCtx->frame_size * av_get_bytes_per_sample(pCodecCtx->sample_fmt);
    //fprintf(stderr,"pCodecCtx->frame_size:%d, bytes_per_sample:%d ==> %d\n",pCodecCtx->frame_size,av_get_bytes_per_sample(pCodecCtx->sample_fmt),length);
    //int j=0;
    int k=0;
    for ( k = 0; k < 2; ++k)
    memcpy(&pFrame->data[k][0],&convert_data[k][0],length);
    #endif

    pFrame->pts = i;

    ret = avcodec_encode_audio2(pCodecCtx, &pkt, pFrame, &got_output);

    if (ret < 0) {
    //qDebug() << "error encoding";
    fprintf(stderr,"error encoding ! \n");
    return -1;
    }

    if (pkt.data == NULL)
    {
    av_free_packet(&pkt);
    continue;
    }

    //qDebug() << "got_ouput = " << got_output;
    //fprintf(stderr,"got_ouput : %d \n", got_output);
    if (got_output) {
    //qDebug() << "Succeed to encode frame : " << framecnt << " size :" << pkt.size;
    fprintf(stderr,"xxx Succeed to encode frame : %d , size : %d\n", framecnt,pkt.size);

    framecnt++;

    //padts[3] = (char)(((chanCfg & 3) << 6) + ((7 + pkt.size) >> 11));
    //padts[4] = (char)(((7 + pkt.size) & 0x7FF) >> 3);
    //padts[5] = (char)((((7 + pkt.size) & 7) << 5) + 0x1F);
    //fwrite(padts, 7, 1, fp_out);
    fwrite(pkt.data, 1, pkt.size, fp_out);

    av_free_packet(&pkt);
    }
    }
    //Flush Encoder
    for (got_output = 1; got_output; i++) {
    ret = avcodec_encode_audio2(pCodecCtx, &pkt, NULL, &got_output);
    if (ret < 0) {
    //printf("Error encoding frame\n");
    fprintf(stderr,"error encoding frame! \n");
    return -1;
    }
    if (got_output) {
    //printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n", pkt.size);
    fprintf(stderr,"Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n", pkt.size);
    //padts[3] = (char)(((chanCfg & 3) << 6) + ((7 + pkt.size) >> 11));
    //padts[4] = (char)(((7 + pkt.size) & 0x7FF) >> 3);
    //padts[5] = (char)((((7 + pkt.size) & 7) << 5) + 0x1F);

    //fwrite(padts, 7, 1, fp_out);
    fwrite(pkt.data, 1, pkt.size, fp_out);
    av_free_packet(&pkt);
    }
    }

    fclose(fp_out);
    avcodec_close(pCodecCtx);
    av_free(pCodecCtx);
    av_freep(&pFrame->data[0]);
    av_frame_free(&pFrame);

    av_freep(&convert_data[0]);
    free(convert_data);
    return 0;
    }

    cv22 ambausb (no GUI)|日誌首頁|struct , initia...上一篇cv22 ambausb (no GUI)下一篇struct , initial value when declare it....
    回應