美文网首页
FFmpeg 解码音频 重采样 生成wav文件

FFmpeg 解码音频 重采样 生成wav文件

作者: 贼噶人 | 来源:发表于2019-08-11 11:30 被阅读0次

//  main.c
//  ffmpeg
//
//  Created by gang.zhou on 2019-08-10.
//  Copyright © 2019 jove. All rights reserved.
//

#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>

#define MAX_AUDIO_FRAME_SIZE 192000

static void encodeAudio(AVCodecContext *ctx, AVPacket *pkt, AVFrame *frame, FILE *accF) {
    if (NULL == ctx || NULL == pkt && NULL == frame && NULL == accF) {
        exit(0);
    }
    int ret;
    ret = avcodec_send_frame(ctx, frame);
    printf("111\n");
    if (ret < 0) {
        fprintf(stderr, "Error sending the frame to the encoder\n");
        exit(1);
    }
    while (ret >= 0) {
        ret = avcodec_receive_packet(ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error encoding audio frame\n");
            exit(1);
        }
        fwrite(pkt->data, 1, pkt->size, accF);
        av_packet_unref(pkt);
    }
}

static void decodeAudio(int out_buffer_size, SwrContext *swrContext, uint8_t *buffer, AVCodecContext *avCodecContext, AVPacket *avPacket, AVFrame *avFrame, FILE *pcmF) {
    if (avcodec_send_packet(avCodecContext, avPacket) < 0) {
        printf("avcodec_send_packet error \n");
        exit(0);
    }
    for (;;) {
        int ret = avcodec_receive_frame(avCodecContext, avFrame);
        if (0 == ret) {
            if (avFrame->pts >= 0) {
                int data_size = av_get_bytes_per_sample(avCodecContext->sample_fmt);
                if (data_size < 0) {
                    printf("av_get_bytes_per_sample error\n");
                    exit(0);
                }
                swr_convert(swrContext, &buffer, MAX_AUDIO_FRAME_SIZE
                        , (const uint8_t **) avFrame->data, avFrame->nb_samples);
                fwrite(buffer, 1, out_buffer_size, pcmF);
                av_frame_unref(avFrame);
            }
        } else if (AVERROR_EOF == ret) {
            break;
        } else if (AVERROR(EAGAIN) == ret) {
            break;
        } else {
            printf("avcodec_receive_frame error \n");
            exit(0);
        }
    }
    av_packet_unref(avPacket);
}

int main(int argc, const char *argv[]) {
    avformat_network_init();
    AVFormatContext *avFormatContext = NULL;
    if (avformat_open_input(&avFormatContext, "/Users/gang.zhou/ffmpeg/ffmpeg/zaojiaoji.mp4", NULL, NULL)) {
        printf("avformat_open_input error\n");
        exit(0);
    }
    if (avformat_find_stream_info(avFormatContext, NULL) < 0) {
        printf("avformat_find_stream_in\n");
        exit(0);
    }
    int aStreamIndex = -1;
    int vStreamIndex = -1;
    int sStreamIndex = -1;
    for (int i = 0; i < avFormatContext->nb_streams; ++i) {
        if (avFormatContext->streams[i]->codecpar->codec_type
                == AVMEDIA_TYPE_VIDEO) {
            vStreamIndex = i;
            printf("Find Video Stream : %d \n", i);
        } else if (avFormatContext->streams[i]->codecpar->codec_type
                == AVMEDIA_TYPE_AUDIO) {
            aStreamIndex = i;
            printf("Find Audio Stream : %d \n", i);
        } else if (avFormatContext->streams[i]->codecpar->codec_type
                == AVMEDIA_TYPE_SUBTITLE) {
            sStreamIndex = i;
            printf("Find Subtitle Stream : %d \n", i);
        }
    }

    if (-1 != aStreamIndex) {
        AVCodec *avCodec =
                avcodec_find_decoder(avFormatContext->streams[aStreamIndex]->codecpar->codec_id);
        if (NULL == avCodec) {
            printf("avcodec_find_decoder error \n");
            exit(0);
        }
        printf("open decoder :%s\n", avCodec->name);
        AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
        printf("%s\n", codec->name);
        AVCodecContext *avCodecContext = avFormatContext->streams[aStreamIndex]->codec;
        printf("channels = %d\n", avCodecContext->channels);
        printf("channel_layout = %lld\n", avCodecContext->channel_layout);
        printf("bit_rate = %lld\n", avCodecContext->bit_rate);
        printf("sample_rate = %d\n", avCodecContext->sample_rate);
        printf("sample_fmt = %d\n", avCodecContext->sample_fmt);
        printf("%d\n", avCodecContext->sample_fmt == AV_SAMPLE_FMT_FLTP);
        avcodec_open2(avCodecContext, avCodec, NULL);
        AVPacket *avPacket = av_packet_alloc();
        if (NULL == avPacket) {
            exit(0);
        }
        AVFrame *avFrame = av_frame_alloc();
        if (NULL == avFrame) {
            exit(0);
        }
        uint64_t out_channel_layout = AV_CH_LAYOUT_STEREO;
        int out_nb_samples = avCodecContext->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);
        int64_t in_channel_layout = av_get_default_channel_layout(avCodecContext->channels);
        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, avCodecContext->sample_fmt, avCodecContext->sample_rate, 0, NULL);
        swr_init(au_convert_ctx);
        FILE *pcmF = fopen("/Users/gang.zhou/ffmpeg/ffmpeg/wk.pcm", "wb");
        FILE *aacF = fopen("/Users/gang.zhou/ffmpeg/ffmpeg/wk.aac", "wb");
        while (!av_read_frame(avFormatContext, avPacket)) {
            if (avPacket->stream_index == aStreamIndex) {
                if (avPacket->pts >= 0) {
                    decodeAudio(out_buffer_size, au_convert_ctx, out_buffer, avCodecContext, avPacket, avFrame, pcmF);
                }
            }
        }
        if (avPacket->stream_index == aStreamIndex) {
            decodeAudio(out_buffer_size, au_convert_ctx, out_buffer, avCodecContext, avPacket, avFrame, pcmF);
        }
        fflush(pcmF);
        fclose(pcmF);
        pcmF = fopen("/Users/gang.zhou/ffmpeg/ffmpeg/wk.pcm", "rb");
        FILE *wavF = fopen("/Users/gang.zhou/ffmpeg/ffmpeg/wk.wav", "wb");
        fseek(pcmF, 0L, SEEK_END);
        int totalDataLen = ftell(pcmF) + 44 - 8;
        fseek(pcmF, 0L, SEEK_SET);
        unsigned char wavHeader[44] = {0};
        wavHeader[0] = 'R';
        wavHeader[1] = 'I';
        wavHeader[2] = 'F';
        wavHeader[3] = 'F';
        wavHeader[4] = (totalDataLen & 0xff);
        wavHeader[5] = (totalDataLen >> 8 & 0xff);
        wavHeader[6] = (totalDataLen >> 16 & 0xff);
        wavHeader[7] = (totalDataLen >> 24 & 0xff);
        wavHeader[8] = 'W';
        wavHeader[9] = 'A';
        wavHeader[10] = 'V';
        wavHeader[11] = 'E';
        wavHeader[12] = 'f';
        wavHeader[13] = 'm';
        wavHeader[14] = 't';
        wavHeader[15] = ' ';
        wavHeader[16] = 0x10;
        wavHeader[17] = 0;
        wavHeader[18] = 0;
        wavHeader[19] = 0;
        wavHeader[20] = 1;
        wavHeader[21] = 0;
        wavHeader[22] = 2;
        wavHeader[23] = 0;
        wavHeader[24] = (44100 & 0xff);
        wavHeader[25] = (44100 >> 8 & 0xff);
        wavHeader[26] = (44100 >> 16 & 0xff);
        wavHeader[27] = (44100 >> 24 & 0xff);
        wavHeader[28] = (44100 * 4 & 0xff);
        wavHeader[29] = (44100 * 4 >> 8 & 0xff);
        wavHeader[30] = (44100 * 4 >> 16 & 0xff);
        wavHeader[31] = (44100 * 4 >> 24 & 0xff);
        wavHeader[32] = 4;
        wavHeader[33] = 0;
        wavHeader[34] = 16;
        wavHeader[35] = 0;
        wavHeader[36] = 'd';
        wavHeader[37] = 'a';
        wavHeader[38] = 't';
        wavHeader[39] = 'a';
        wavHeader[40] = ((totalDataLen - 36) & 0xff);
        wavHeader[41] = ((totalDataLen - 36) >> 8 & 0xff);
        wavHeader[42] = ((totalDataLen - 36) >> 16 & 0xff);
        wavHeader[43] = ((totalDataLen - 36) >> 24 & 0xff);
        fwrite(wavHeader, 1, 44, wavF);
        u_int8_t buffer[1024] = {0};
        int readBytes;
        while ((readBytes = fread(buffer, 1, 1024, pcmF)) > 0) {
            fwrite(buffer, 1, readBytes, wavF);
        }
        fflush(wavF);
        fclose(pcmF);
        fclose(wavF);
        avcodec_close(avCodecContext);
        av_frame_free(&avFrame);
        av_packet_free(&avPacket);
        avformat_free_context(avFormatContext);
    }
    return 0;
}

相关文章

  • FFmpeg 解码音频 重采样 生成wav文件

  • FFmpeg4Android:音频解码

    6 FFmpeg4Android:音频解码 音频解码,就是将视频文件中的音频部分抽离出来,生成PCM文件,并使用A...

  • iOS wav文件头详解

    最近在做音频采样这部分的内容,涉及录制、转码、降频、重采样等内容。 在处理wav音频文件时发现,iOS的”AVAu...

  • FFmpeg-多线程解码播放

    数据音频重采样 在上篇文章FFmpeg - 初探ffmepg并解码数据我们已经可以获取到音频的数据了,也解决内存上...

  • 5-2 如何处理二进制文件?

    实际案例: wav是一种音频文件的格式,音频文件为二进制文件. wav文件由头部信息和音频采样数据构成.前44个字...

  • PCM文件转wav文件

    PCM是采样的原始音频数据, 是无压缩的原始数据, 给pcm添加wav的文件头, 就是wav文件, 所以wav也是...

  • 如何处理二进制文件

    实际案例 WAV是一种音频文件的格式,音频文件为二进制文件。WAV文件由头部信息和音频采样数据构成。前44个字节为...

  • FFmpeg音频解码

    FFmpeg音频解码和上一章的视频解码流程差不多。区别在视频有像素格(YUV RGB)式而音频有采样格式(PCM ...

  • ffmpeg音频文件格式转换(支持重采样采样位数为24位)

    ffmpeg将音频文件重采样为8位、16位、32位的命令比较容易查找,但是重采样为24位却非常非常的少。 ffmp...

  • FFmpeg音频重采样

    一、什么是音频重采样 音频重采样就是改变音频的采样率、采样格式、声道数等参数,使之按照我们期望的参数输出。比如我们...

网友评论

      本文标题:FFmpeg 解码音频 重采样 生成wav文件

      本文链接:https://www.haomeiwen.com/subject/zobjjctx.html