阅读量:0
version
#define LIBSWRESAMPLE_VERSION_MAJOR 2
#define LIBSWRESAMPLE_VERSION_MINOR 9
#define LIBSWRESAMPLE_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_MINOR 31
#define LIBAVCODEC_VERSION_MICRO 102
code
void CFfmpegOps::EncodePCMToAAC(const char *pcm_file, const char *aac_file) { AVFormatContext *fmt_ctx = nullptr; const AVOutputFormat *out_fmt = nullptr; int ret = -1; AVStream *avstream = nullptr; const AVCodec *codec = nullptr; AVCodecContext *codec_ctx = nullptr; AVFrame *avframe = nullptr; // pcm file对应的avframe AVFrame *codec_avframe = nullptr; // 编码器接收的avframe AVPacket *avpacket = nullptr; int frame_data_bytes = 0; FILE *in_fp = nullptr; size_t n = 0; int64_t pts = 0; struct SwrContext *swr_ctx = nullptr; // 音频帧转换器 AVChannelLayout src_channel_layout; AVChannelLayout dest_channel_layout; codec = avcodec_find_encoder(AV_CODEC_ID_AAC); if (!codec) { printf("avcodec_find_encoder error\n"); goto END; } codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { printf("avcodec_alloc_context3 error\n"); goto END; } codec_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP; // 编码器的接受的采样格式 codec_ctx->sample_rate = 44100; codec_ctx->channel_layout = AV_CH_LAYOUT_STEREO; codec_ctx->channels = av_get_channel_layout_nb_channels(codec_ctx->channel_layout); codec_ctx->bit_rate = 128000; codec_ctx->time_base.num = 1; codec_ctx->time_base.den = codec_ctx->sample_rate; ret = avcodec_open2(codec_ctx, codec, nullptr); if (ret < 0) { printf("avcodec_open2 error(%s)\n", GetFfmpegERR(ret)); goto END; } printf("codec_ctx->frame_size:%d\n", codec_ctx->frame_size); codec_avframe = av_frame_alloc(); if (!codec_avframe) { printf("av_frame_alloc error\n"); goto END; } codec_avframe->format = codec_ctx->sample_fmt; // pcm的采样格式 codec_avframe->sample_rate = codec_ctx->sample_rate; codec_avframe->channel_layout = codec_ctx->channel_layout; codec_avframe->channels = av_get_channel_layout_nb_channels(codec_avframe->channel_layout); codec_avframe->nb_samples = codec_ctx->frame_size; ret = av_frame_get_buffer(codec_avframe, 0); if (ret < 0) { printf("av_frame_get_buffer error(%s)\n", GetFfmpegERR(ret)); goto END; } avframe = av_frame_alloc(); if (!avframe) { printf("av_frame_alloc error\n"); goto END; } avframe->format = AV_SAMPLE_FMT_FLT; // pcm的采样格式 avframe->sample_rate = 44100; avframe->channel_layout = AV_CH_LAYOUT_STEREO; avframe->channels = av_get_channel_layout_nb_channels(avframe->channel_layout); avframe->nb_samples = 1024; ret = av_samples_get_buffer_size(nullptr, avframe->channels, avframe->nb_samples, (AVSampleFormat)(avframe->format), 1); if (ret < 0) { printf("av_samples_get_buffer_size error(%s)\n", GetFfmpegERR(ret)); goto END; } frame_data_bytes = av_get_bytes_per_sample((AVSampleFormat)(avframe->format)) * av_get_channel_layout_nb_channels(avframe->channel_layout) * avframe->nb_samples; if (frame_data_bytes != ret) { printf("frame_data_bytes != ret\n"); goto END; } ret = av_frame_get_buffer(avframe, 0); if (ret < 0) { printf("av_frame_get_buffer error(%s)\n", GetFfmpegERR(ret)); goto END; } avpacket = av_packet_alloc(); if (!avpacket) { printf("av_packet_alloc error\n"); goto END; } ret = avformat_alloc_output_context2(&fmt_ctx, nullptr, nullptr, aac_file); if (ret < 0) { printf("avformat_alloc_output_context2 error(%s)\n", GetFfmpegERR(ret)); goto END; } out_fmt = fmt_ctx->oformat; // name:adts long_name:ADTS AAC avstream = avformat_new_stream(fmt_ctx, codec); if (!avstream) { printf("avformat_new_stream error\n"); goto END; } ret = avcodec_parameters_from_context(avstream->codecpar, codec_ctx); if (ret < 0) { printf("avcodec_parameters_from_context error(%s)\n", GetFfmpegERR(ret)); goto END; } if (!(fmt_ctx->flags & AVFMT_FLAG_NOFILLIN)) { ret = avio_open(&(fmt_ctx->pb), aac_file, AVIO_FLAG_WRITE); if (ret < 0) { printf("avio_open error(%s)\n", GetFfmpegERR(ret)); goto END; } } in_fp = fopen(pcm_file, "rb"); if (!in_fp) { printf("fopen error\n"); goto END; } // int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask); ret = av_channel_layout_from_mask(&src_channel_layout, avframe->channel_layout); if (ret < 0) { printf("av_channel_layout_from_mask error(%s)\n", GetFfmpegERR(ret)); goto END; } ret = av_channel_layout_from_mask(&dest_channel_layout, codec_avframe->channel_layout); if (ret < 0) { printf("av_channel_layout_from_mask error(%s)\n", GetFfmpegERR(ret)); goto END; } // int swr_alloc_set_opts2(struct SwrContext **ps, // const AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, // const AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, // int log_offset, void *log_ctx); ret = swr_alloc_set_opts2(&swr_ctx, &dest_channel_layout, (AVSampleFormat)(codec_avframe->format), codec_avframe->sample_rate, &src_channel_layout, (AVSampleFormat)(avframe->format), avframe->sample_rate, 0, nullptr); if (ret < 0) { printf("swr_alloc_set_opts2 error(%s)\n", GetFfmpegERR(ret)); goto END; } ret = avformat_write_header(fmt_ctx, nullptr); if (ret < 0) { printf("avformat_write_header error(%s)\n", GetFfmpegERR(ret)); goto END; } while (1) { if (feof(in_fp)) { printf("feof\n"); break; } if (av_sample_fmt_is_planar((AVSampleFormat)(avframe->format))) { n = fread(avframe->data[0], sizeof(uint8_t), frame_data_bytes / 2, in_fp); if ((int)n != frame_data_bytes / 2) { printf("n != frame_data_bytes / 2\n"); } n = fread(avframe->data[1], sizeof(uint8_t), frame_data_bytes / 2, in_fp); if ((int)n != frame_data_bytes / 2) { printf("n != frame_data_bytes / 2\n"); } } else { n = fread(avframe->data[0], sizeof(uint8_t), frame_data_bytes, in_fp); if ((int)n != frame_data_bytes) { printf("n != frame_data_bytes\n"); } } ret = swr_convert_frame(swr_ctx, codec_avframe, avframe); if (ret < 0) { printf("swr_convert_frame error(%s)\n", GetFfmpegERR(ret)); goto END; } codec_avframe->pts = pts; ++pts; ret = avcodec_send_frame(codec_ctx, codec_avframe); if (ret < 0) { if (ret == AVERROR(EAGAIN)) { printf("read output first\n"); } else { printf("avcodec_send_frame error(%s)\n", GetFfmpegERR(ret)); break; } } while (1) { ret = avcodec_receive_packet(codec_ctx, avpacket); if (ret < 0) { if (ret == AVERROR(EAGAIN)) { printf("send input first\n"); break; } else { printf("avcodec_receive_packet error(%s)\n", GetFfmpegERR(ret)); break; } } ret = av_write_frame(fmt_ctx, avpacket); if (ret < 0) { printf("av_write_frame error(%s)\n", GetFfmpegERR(ret)); av_packet_unref(avpacket); goto END; } av_packet_unref(avpacket); } } ret = avcodec_send_frame(codec_ctx, nullptr); while (1) { ret = avcodec_receive_packet(codec_ctx, avpacket); if (ret < 0) { if (ret == AVERROR(EAGAIN)) { printf("send input first\n"); break; } else { printf("avcodec_receive_packet error(%s)\n", GetFfmpegERR(ret)); break; } } ret = av_write_frame(fmt_ctx, avpacket); if (ret < 0) { printf("av_write_frame error(%s)\n", GetFfmpegERR(ret)); av_packet_unref(avpacket); goto END; } av_packet_unref(avpacket); } ret = av_write_trailer(fmt_ctx); if (ret != 0) { printf("av_write_trailer error(%s)\n", GetFfmpegERR(ret)); goto END; } END: if (swr_ctx) { swr_free(&swr_ctx); swr_ctx = nullptr; } if (in_fp) { fclose(in_fp); in_fp = nullptr; } if (avpacket) { av_packet_free(&avpacket); avpacket = nullptr; } if (codec_avframe) { av_frame_free(&codec_avframe); codec_avframe = nullptr; } if (avframe) { av_frame_free(&avframe); avframe = nullptr; } if (codec_ctx) { avcodec_free_context(&codec_ctx); codec_ctx = nullptr; } if (fmt_ctx) { if (fmt_ctx->pb) { avio_close(fmt_ctx->pb); fmt_ctx->pb = nullptr; } avformat_free_context(fmt_ctx); fmt_ctx = nullptr; } }