音视频学习-------任意格式音频文件转码成MP3文件(使用ffmpeg转码实现)

源代码

void ConvertAuidoToPCMWithPath(const char *inputPath, const char *outputPath)
{
  AVFormatContext *pFormatCtx=NULL;
    
    
    FILE *pFile = fopen(outputPath,"wb");
    if (!pFile){
        fprintf(stderr, "could not open %s\n", outputPath);
        return;
    }
    
    
    av_register_all();
    
    avformat_network_init();
    
    pFormatCtx = avformat_alloc_context();
    
    if (avformat_open_input(&pFormatCtx, inputPath, NULL, NULL)!=0){
        printf("Couldn't open input stream.");
        return ;
    }
    
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0){
        printf("Couldn't find stream information.");
        return ;
    }
    
    //是一个手工调试的函数,能使我们看到pFormatCtx->streams里面有什么内容。
    av_dump_format(pFormatCtx, 0, inputPath, false);
    
    int audioStreamIndex=-1;
    
    for (int i = 0; i < pFormatCtx->nb_streams; ++i){
        
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){
            audioStreamIndex = i;
            break;
        }
    }
    if (audioStreamIndex == -1){
        printf("Didn't find a audio stream .");
        return ;
    }
    
    AVCodecContext *pCodecCtx = pFormatCtx->streams[audioStreamIndex]->codec;
    
    AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if (NULL == pCodec){
        printf("Codec not found .");
        return ;
    }
    
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0){
        printf("Could not open codec.");
        return ;
    }
    
    AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
    av_init_packet(packet);
    
    uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
    int out_nb_samples = pCodecCtx->frame_size;
    
    enum AVSampleFormat out_sample_fmt = AV_SAMPLE_FMT_S16;
    int out_sample_rate = 44100;
    int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);
    
    int out_buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, out_sample_fmt, 1);
    uint8_t *out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);
    
    AVFrame *pFrame = av_frame_alloc();
    int64_t in_channel_layout = av_get_default_channel_layout(pCodecCtx->channels);
    
    struct SwrContext *au_convert_ctx = swr_alloc();
    au_convert_ctx = swr_alloc_set_opts(au_convert_ctx, out_channel_layout, out_sample_fmt, out_sample_rate, in_channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0, NULL);
    
    swr_init(au_convert_ctx);
    
    int index= 0;
    int ret=0;
    int got_picture=0;
    
    while (av_read_frame(pFormatCtx, packet) >=0)
    {
        if (packet->stream_index == audioStreamIndex)
        {
            ret = avcodec_decode_audio4( pCodecCtx, pFrame, &got_picture, packet);
            
            if (ret < 0)
            {
                printf("Error in decoding audio frame.");
                return ;
            }
            if (got_picture > 0)
            {
                swr_convert(au_convert_ctx, &out_buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)pFrame->data, pFrame->nb_samples);
                
                printf("index:  %d pts: %lld packet size: %d\n",index,packet->pts,packet->size);
                
                fwrite(out_buffer, 1, out_buffer_size, pFile);
                ++ index;
            }
        }
        
        av_free_packet(packet);
    }
    
    swr_free(&au_convert_ctx);
    fclose(pFile);
    
    av_free(out_buffer);
    avcodec_close(pCodecCtx);
    avformat_close_input(&pFormatCtx);
    
    printf("END...");
}

可以把原来的格式看成一个穿上衣服的PCM格式文件。先使用ffpmeg成pcm,然后再穿上MP3文件的衣服完成转码
使用的ffmpge为2.2版本的,高版本有些API弃用。

发布了23 篇原创文章 · 获赞 9 · 访问量 1680

猜你喜欢

转载自blog.csdn.net/weixin_42590177/article/details/103813037