展示型网站建设模板,自己可以创建公司网站吗,仿做网站,四川省商投建设公司官网文章目录 音频解码流程API分析#xff1a;伪代码code: 音频解码流程
aac—音频解码器–pcm数据
API
avcodec_find_decoder#xff1a;根据指定的AVCodecID查找注册的解码器 av_parser_init#xff1a;初始化AVCodecParserContext avcodec_alloc_context3#xff1a;为AV… 文章目录 音频解码流程API分析伪代码code: 音频解码流程
aac—音频解码器–pcm数据
API
avcodec_find_decoder根据指定的AVCodecID查找注册的解码器 av_parser_init初始化AVCodecParserContext avcodec_alloc_context3为AVCodecContext分配内存 avcodec_open2打开解码器 av_parser_parse2解析获得⼀个Packet
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt); // 将AVPacket压缩数据给解码器
int avcodec_receive_frame ( AVCodecContext * avctx, AVFrame * frame ) // 获取到解码后的AVFrame数据 分析
首先读文件原始码流将原始码流解析为Packet, 通过解码器获得AVFrame 最后写文件 循环获取Packet写文件
伪代码
// 读文件
data_size fread(inbuf, 1, AUDIO_INBUF_SIZE, infile); // data_size 20480 while(data_size) {av_parser_parse2() //解析获得⼀个Packetdecode(); // (压缩AVPacket,解码AVFrame数据之后写数据)// data_size 减少
}void decode() {ret avcodec_send_packet //将AVPacket压缩数据给解码器 while (ret ) {ret avcodec_receive_frame; // 获取到解码后的AVFrame数据if (ret AVERROR(EAGAIN) || ret AVERROR_EOF)return; // fwrite 结束后 ret AVERROR(EAGAIN,需要新的输⼊, 返回av_get_bytes_per_sample //获取每个sample中的字节数fwrite();}
}code:
#define AUDIO_INBUF_SIZE 20480
#define AUDIO_REFILL_THRESH 4096static char err_buf[128] {0};
static char* av_get_err(int errnum)
{av_strerror(errnum, err_buf, 128);return err_buf;
}static void print_sample_format(const AVFrame *frame)
{printf(ar-samplerate: %uHz\n, frame-sample_rate);printf(ac-channel: %u\n, frame-channels);printf(f-format: %u\n, frame-format);// 格式需要注意实际存储到本地文件时已经改成交错模式
}static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame,FILE *outfile)
{int i, ch;int ret, data_size;/* send the packet with the compressed data to the decoder */ret avcodec_send_packet(dec_ctx, pkt);if(ret AVERROR(EAGAIN)){fprintf(stderr, Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n);}else if (ret 0){fprintf(stderr, Error submitting the packet to the decoder, err:%s, pkt_size:%d\n,av_get_err(ret), pkt-size)return;}/* read all the output frames (infile general there may be any number of them */while (ret 0){// 对于frame, avcodec_receive_frame内部每次都先调用ret avcodec_receive_frame(dec_ctx, frame);if (ret AVERROR(EAGAIN) || ret AVERROR_EOF)return;else if (ret 0){fprintf(stderr, Error during decoding\n);exit(1);}data_size av_get_bytes_per_sample(dec_ctx-sample_fmt);if (data_size 0){fprintf(stderr, Failed to calculate data size\n);exit(1);}static int s_print_format 0;if(s_print_format 0){s_print_format 1;print_sample_format(frame);}for (i 0; i frame-nb_samples; i){for (ch 0; ch dec_ctx-channels; ch) // 交错的方式写入, 大部分float的格式输出fwrite(frame-data[ch] data_size*i, 1, data_size, outfile);}}
}int main(int argc, char **argv)
{const char *outfilename;const char *filename;const AVCodec *codec;AVCodecContext *codec_ctx NULL;AVCodecParserContext *parser NULL;int len 0;int ret 0;FILE *infile NULL;FILE *outfile NULL;uint8_t inbuf[AUDIO_INBUF_SIZE AV_INPUT_BUFFER_PADDING_SIZE];uint8_t *data NULL;size_t data_size 0;AVPacket *pkt NULL;AVFrame *decoded_frame NULL;if (argc 2){fprintf(stderr, Usage: %s input file output file\n, argv[0]);exit(0);}filename argv[1];outfilename argv[2];pkt av_packet_alloc();enum AVCodecID audio_codec_id AV_CODEC_ID_AAC;if(strstr(filename, aac) ! NULL){audio_codec_id AV_CODEC_ID_AAC;}else if(strstr(filename, mp3) ! NULL){audio_codec_id AV_CODEC_ID_MP3;}else{printf(default codec id:%d\n, audio_codec_id);}// 查找解码器codec avcodec_find_decoder(audio_codec_id); // AV_CODEC_ID_AACif (!codec) {fprintf(stderr, Codec not found\n);exit(1);}// 获取裸流的解析器 AVCodecParserContext(数据) AVCodecParser(方法)parser av_parser_init(codec-id);if (!parser) {fprintf(stderr, Parser not found\n);exit(1);}// 分配codec上下文codec_ctx avcodec_alloc_context3(codec);if (!codec_ctx) {fprintf(stderr, Could not allocate audio codec context\n);exit(1);}// 将解码器和解码器上下文进行关联if (avcodec_open2(codec_ctx, codec, NULL) 0) {fprintf(stderr, Could not open codec\n);exit(1);}// 打开输入文件infile fopen(filename, rb);if (!infile) {fprintf(stderr, Could not open %s\n, filename);exit(1);}// 打开输出文件outfile fopen(outfilename, wb);if (!outfile) {av_free(codec_ctx);exit(1);}// 读取文件进行解码data inbuf;data_size fread(inbuf, 1, AUDIO_INBUF_SIZE, infile);while (data_size 0){if (!decoded_frame){if (!(decoded_frame av_frame_alloc())){fprintf(stderr, Could not allocate audio frame\n);exit(1);}}ret av_parser_parse2(parser, codec_ctx, pkt-data, pkt-size,data, data_size,AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);if (ret 0){fprintf(stderr, Error while parsing\n);exit(1);}data ret; // 跳过已经解析的数据data_size - ret; // 对应的缓存大小也做相应减小if (pkt-size)decode(codec_ctx, pkt, decoded_frame, outfile);if (data_size AUDIO_REFILL_THRESH) // 如果数据少了则再次读取{memmove(inbuf, data, data_size); // 把之前剩的数据拷贝到buffer的起始位置data inbuf;// 读取数据 长度: AUDIO_INBUF_SIZE - data_sizelen fread(data data_size, 1, AUDIO_INBUF_SIZE - data_size, infile);if (len 0)data_size len;}}/* 冲刷解码器 */pkt-data NULL; // 让其进入drain modepkt-size 0;decode(codec_ctx, pkt, decoded_frame, outfile);fclose(outfile);fclose(infile);avcodec_free_context(codec_ctx);av_parser_close(parser);av_frame_free(decoded_frame);av_packet_free(pkt);printf(main finish, please enter Enter and exit\n);return 0;
}