泰安企业网站建设公司,徐州网络排名优化,企业网站优化暴肃湖南岚鸿很好,做网站建设的好处aac 介绍
aac 简单说就是音频的一种压缩编码器#xff0c;相同音质下压缩比 mp3好#xff0c;目前比较常用。
aac 编码支持的格式
aac 支持的 sample_fmts: 8
aac 支持的 samplerates: 96000 88200 64000 48000 44100 32000 24000 22050 16000 12000 11025 8000 7350
通…aac 介绍
aac 简单说就是音频的一种压缩编码器相同音质下压缩比 mp3好目前比较常用。
aac 编码支持的格式
aac 支持的 sample_fmts: 8
aac 支持的 samplerates: 96000 88200 64000 48000 44100 32000 24000 22050 16000 12000 11025 8000 7350
通过 AVCodec 中的 supported_xx 字段来获取 具体代码
static int check_sample_fmt(const AVCodec* codec, enum AVSampleFormat sample_fmt)
{const enum AVSampleFormat* p codec-sample_fmts;cout sample_fmts: ;while (*p ! AV_SAMPLE_FMT_NONE){cout *p ;p;}cout endl;p codec-sample_fmts;while (*p ! AV_SAMPLE_FMT_NONE) {if (*p sample_fmt)return 1;p;}return 0;
}也可以用命令行获取支持格式以及可设置的额外参数
具体实现
编码步骤
// 1. 通过名字或者 id 找到编码器(相当于找到了那个能力结构体指针)获取的结构体会有些编码器的简单介绍以及编码器支持的能力
// 2. 通过编码器创建上下文相当于创建上下文实例并将 codec 指针保存在上下文中并根据编码器能力初始化一些参数// 3. 根据用户需要以及编码器支持的能力将编码参数设置到编码器上下文中// 4. 根据编码器上下文初始化编码器// 5. 创建 avframe 并把编码器上下文中的参数赋值给他// 6. avframe 根据参数算出每次编码需要的内部大小并分配// 7. 将编码数据传给 avframe// 8. 将 avframe 传给 avcodec_send_frame// 9. 通过 avcodec_receive_packet 获取 avpacket 数据具体代码
目前直接拿了 fffmpeg demo后面有空按照步骤规整一下。
/** Copyright (c) 2001 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the Software), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.*//*** file* audio encoding with libavcodec API example.** example encode_audio.c*/#include stdint.h
#include stdio.h
#include stdlib.h
#include iostream
using namespace std;
externC
{
#include libavcodec/avcodec.h
#include libavutil/channel_layout.h
#include libavutil/common.h
#include libavutil/frame.h
#include libavutil/samplefmt.h
}const int sampling_frequencies[] {96000, // 0x088200, // 0x164000, // 0x248000, // 0x344100, // 0x432000, // 0x524000, // 0x622050, // 0x716000, // 0x812000, // 0x911025, // 0xa8000 // 0xb// 0xc d e f是保留的
};int adts_header(char* const p_adts_header, const int data_length,const int profile, const int samplerate,const int channels)
{int sampling_frequency_index 3; // 默认使用48000hzint adtsLen data_length 7;int frequencies_size sizeof(sampling_frequencies) / sizeof(sampling_frequencies[0]);int i 0;for (i 0; i frequencies_size; i){if (sampling_frequencies[i] samplerate){sampling_frequency_index i;break;}}if (i frequencies_size){printf(unsupport samplerate:%d\n, samplerate);return -1;}p_adts_header[0] 0xff; //syncword:0xfff 高8bitsp_adts_header[1] 0xf0; //syncword:0xfff 低4bitsp_adts_header[1] | (0 3); //MPEG Version:0 for MPEG-4,1 for MPEG-2 1bitp_adts_header[1] | (0 1); //Layer:0 2bitsp_adts_header[1] | 1; //protection absent:1 1bitp_adts_header[2] (profile) 6; //profile:profile 2bitsp_adts_header[2] | (sampling_frequency_index 0x0f) 2; //sampling frequency index:sampling_frequency_index 4bitsp_adts_header[2] | (0 1); //private bit:0 1bitp_adts_header[2] | (channels 0x04) 2; //channel configuration:channels 高1bitp_adts_header[3] (channels 0x03) 6; //channel configuration:channels 低2bitsp_adts_header[3] | (0 5); //original0 1bitp_adts_header[3] | (0 4); //home0 1bitp_adts_header[3] | (0 3); //copyright id bit0 1bitp_adts_header[3] | (0 2); //copyright id start0 1bitp_adts_header[3] | ((adtsLen 0x1800) 11); //frame lengthvalue 高2bitsp_adts_header[4] (uint8_t)((adtsLen 0x7f8) 3); //frame length:value 中间8bitsp_adts_header[5] (uint8_t)((adtsLen 0x7) 5); //frame length:value 低3bitsp_adts_header[5] | 0x1f; //buffer fullness:0x7ff 高5bitsp_adts_header[6] 0xfc; // //buffer fullness:0x7ff 低6bits// number_of_raw_data_blocks_in_frame// 表示ADTS帧中有number_of_raw_data_blocks_in_frame 1个AAC原始帧。return 0;
}/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec* codec, AVChannelLayout* dst)
{const AVChannelLayout* p, * best_ch_layout;int best_nb_channels 0;if (!codec-ch_layouts){AVChannelLayout layout AV_CHANNEL_LAYOUT_STEREO;return av_channel_layout_copy(dst, layout);}p codec-ch_layouts;while (p-nb_channels) {int nb_channels p-nb_channels;if (nb_channels best_nb_channels) {best_ch_layout p;best_nb_channels nb_channels;}p;}return av_channel_layout_copy(dst, best_ch_layout);
}static void encode(AVCodecContext* ctx, AVFrame* frame, AVPacket* pkt,FILE* output)
{int ret;/* send the frame for encoding */ret avcodec_send_frame(ctx, frame);if (ret 0) {fprintf(stderr, Error sending the frame to the encoder\n);exit(1);}/* read all the available output packets (in general there may be any* number of them */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);}char adts_header_buf[7] { 0 };adts_header(adts_header_buf, pkt-size, ctx-profile, ctx-sample_rate, ctx-ch_layout.nb_channels);fwrite(adts_header_buf, 1, 7, output);fwrite(pkt-data, 1, pkt-size, output);av_packet_unref(pkt);}
}int main(int argc, char** argv)
{// 1. 通过名字或者 id 找到编码器(相当于找到了那个能力结构体指针)获取的结构体会有些编码器的简单介绍以及编码器支持的能力// 2. 通过编码器创建上下文相当于创建上下文实例并将 codec 指针保存在上下文中并根据编码器能力初始化一些参数// 3. 根据用户需要以及编码器支持的能力将编码参数设置到编码器上下文中// 4. 根据编码器上下文初始化编码器// 5. 创建 avframe 并把编码器上下文中的参数赋值给他// 6. avframe 根据参数算出每次编码需要的内部大小并分配// 7. 将编码数据传给 avframe// 8. 将 avframe 传给 avcodec_send_frame// 9. 通过 avcodec_receive_packet 获取 avpacket 数据const char* filename;const AVCodec* codec;AVCodecContext* c NULL;AVFrame* frame;AVPacket* pkt;int i, j, k, ret;FILE* f;float* samples;float t, tincr;if (argc 1) {fprintf(stderr, Usage: %s output file\n, argv[0]);return 0;}filename argv[1];codec avcodec_find_encoder(AV_CODEC_ID_AAC);if (!codec) {fprintf(stderr, Codec not found\n);exit(1);}c avcodec_alloc_context3(codec);if (!c) {fprintf(stderr, Could not allocate audio codec context\n);exit(1);}c-bit_rate 64000;c-sample_fmt AV_SAMPLE_FMT_FLTP;c-sample_rate 48000;ret select_channel_layout(codec, c-ch_layout);if (ret 0)exit(1);/* open it */if (avcodec_open2(c, codec, NULL) 0) {fprintf(stderr, Could not open codec\n);exit(1);}f fopen(filename, wb);if (!f) {fprintf(stderr, Could not open %s\n, filename);exit(1);}/* packet for holding encoded output */pkt av_packet_alloc();if (!pkt) {fprintf(stderr, could not allocate the packet\n);exit(1);}/* frame containing input raw audio */frame av_frame_alloc();if (!frame) {fprintf(stderr, Could not allocate audio frame\n);exit(1);}frame-nb_samples c-frame_size;frame-format c-sample_fmt;ret av_channel_layout_copy(frame-ch_layout, c-ch_layout);if (ret 0)exit(1);/* allocate the data buffers */ret av_frame_get_buffer(frame, 0);if (ret 0) {fprintf(stderr, Could not allocate audio data buffers\n);exit(1);}/* encode a single tone sound */t 0;tincr 2 * M_PI * 440.0 / c-sample_rate;for (i 0; i 200; i) {/* make sure the frame is writable -- makes a copy if the encoder* kept a reference internally */ret av_frame_make_writable(frame);if (ret 0)exit(1);for (k 0; k c-ch_layout.nb_channels; k){samples (float*)frame-data[k];for (j 0; j c-frame_size; j) {samples[j] sin(t) * 10000;t tincr;}}encode(c, frame, pkt, f);}encode(c, NULL, pkt, f);fclose(f);av_frame_free(frame);av_packet_free(pkt);avcodec_free_context(c);return 0;
}
备注
ffmpeg demo 在 c 环境不能直接编译通过
添加头文件需要加上 extern “C”
externC
{
#include libavcodec/avcodec.h
#include libavutil/channel_layout.h
#include libavutil/common.h
#include libavutil/frame.h
#include libavutil/samplefmt.h
}另一个报错不清楚ffmpeg是怎么编译通过的c这边会报错
av_channel_layout_copy(dst, (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);需要改成
AVChannelLayout layout AV_CHANNEL_LAYOUT_STEREO;
av_channel_layout_copy(dst, layout);