热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

FFMEPGPCM编码为AAC

流程下面附一张使用FFmpeg编码音频的流程图。使用该流程,不仅可以编码AAC的音频,而且可以编码MP3,MP2等等各种FFmpeg支持

流程

下面附一张使用FFmpeg编码音频的流程图。使用该流程,不仅可以编码AAC的音频,而且可以编码MP3,MP2等等各种FFmpeg支持的音频。图中蓝色背景的函数是实际输出数据的函数。浅绿色的函数是音频编码的函数。
在这里插入图片描述

简单介绍一下流程中各个函数的意义:

av_register_all():注册FFmpeg所有编解码器。avformat_alloc_output_context2():初始化输出码流的AVFormatContext。avio_open():打开输出文件。av_new_stream():创建输出码流的AVStream。avcodec_find_encoder():查找编码器。avcodec_open2():打开编码器。avformat_write_header():写文件头(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。avcodec_encode_audio2():编码音频。即将AVFrame(存储PCM采样数据)编码为AVPacket(存储AAC,MP3等格式的码流数据)。av_write_frame():将编码后的视频码流写入文件。av_write_trailer():写文件尾(对于某些没有文件头的封装格式,不需要此函数。比如说MPEG2TS)。

代码

/***最简单的基于FFmpeg的音频编码器*Simplest FFmpeg Audio Encoder**雷霄骅 Lei Xiaohua*leixiaohua1020@126.com*中国传媒大学/数字电视技术*Communication University of China / Digital TV Technology*http://blog.csdn.net/leixiaohua1020**本程序实现了音频PCM采样数据编码为压缩码流(MP3,WMA,AAC等)。*是最简单的FFmpeg音频编码方面的教程。*通过学习本例子可以了解FFmpeg的编码流程。*This software encode PCM data to AAC bitstream.*It's the simplest audio encoding software based on FFmpeg.*Suitable for beginner of FFmpeg*/#include // 包含ffmpeg头文件
#include "libavutil/avutil.h"#include "libavcodec/avcodec.h"#include "libavformat/avformat.h"int flush_encoder(AVFormatContext *fmt_ctx,unsigned int stream_index){int ret;int got_frame;AVPacket enc_pkt;if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &AV_CODEC_CAP_DELAY))return 0;while (1) {enc_pkt.data &#61; NULL;enc_pkt.size &#61; 0;av_init_packet(&enc_pkt);ret &#61; avcodec_encode_audio2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,NULL, &got_frame);av_frame_free(NULL);if (ret < 0)break;if (!got_frame){ret&#61;0;break;}printf("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);/* mux encoded frame */ret &#61; av_write_frame(fmt_ctx, &enc_pkt);if (ret < 0)break;}return ret;
}int main(int argc, char* argv[])
{AVFormatContext* pFormatCtx;AVOutputFormat* fmt;AVStream* audio_st;AVCodecContext* pCodecCtx;AVCodec* pCodec;uint8_t* frame_buf;AVFrame* pFrame;AVPacket pkt;int got_frame&#61;0;int ret&#61;0;int size&#61;0;FILE *in_file&#61;NULL; //Raw PCM dataint framenum&#61;1000; //Audio frame numberconst char* out_file &#61; "tdjm.aac"; //Output URLint i;in_file&#61; fopen("2000-01-01_015202.pcm", "rb");av_register_all();//Method 1.pFormatCtx &#61; avformat_alloc_context();fmt &#61; av_guess_format(NULL, out_file, NULL);pFormatCtx->oformat &#61; fmt;//Method 2.//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);//fmt &#61; pFormatCtx->oformat;//Open output URLif (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){printf("Failed to open output file!\n");return -1;}audio_st &#61; avformat_new_stream(pFormatCtx, 0);if (audio_st&#61;&#61;NULL){return -1;}//根据需要转化的pcm数据进行设置pCodecCtx &#61; audio_st->codec;pCodecCtx->codec_id &#61; fmt->audio_codec;pCodecCtx->codec_type &#61; AVMEDIA_TYPE_AUDIO;pCodecCtx->sample_fmt &#61; AV_SAMPLE_FMT_FLT;pCodecCtx->sample_rate&#61; 16000;pCodecCtx->channel_layout&#61;AV_CH_LAYOUT_MONO;pCodecCtx->channels &#61; av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);pCodecCtx->bit_rate &#61; 32000;//Show some informationav_dump_format(pFormatCtx, 0, out_file, 1);pCodec &#61; avcodec_find_encoder(pCodecCtx->codec_id);if (!pCodec){printf("Can not find encoder!\n");return -1;}if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){printf("Failed to open encoder!\n");return -1;}pFrame &#61; av_frame_alloc();pFrame->nb_samples&#61; pCodecCtx->frame_size;pFrame->format&#61; pCodecCtx->sample_fmt;size &#61; av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1);frame_buf &#61; (uint8_t *)av_malloc(size);avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1);//Write Headeravformat_write_header(pFormatCtx,NULL);av_new_packet(&pkt,size);for (i&#61;0; i<framenum; i&#43;&#43;){//Read PCMif (fread(frame_buf, 1, size, in_file) <&#61; 0){printf("Failed to read raw data! \n");return -1;}else if(feof(in_file)){break;}pFrame->data[0] &#61; frame_buf; //PCM DatapFrame->pts&#61;i*100;got_frame&#61;0;//Encoderet &#61; avcodec_encode_audio2(pCodecCtx, &pkt,pFrame, &got_frame);if(ret < 0){printf("Failed to encode!\n");//return -1;}if (got_frame&#61;&#61;1){printf("Succeed to encode 1 frame! \tsize:%5d\n",pkt.size);pkt.stream_index &#61; audio_st->index;ret &#61; av_write_frame(pFormatCtx, &pkt);av_free_packet(&pkt);}}//Flush Encoderret &#61; flush_encoder(pFormatCtx,0);if (ret < 0) {printf("Flushing encoder failed\n");return -1;}//Write Trailerav_write_trailer(pFormatCtx);//Cleanif (audio_st){avcodec_close(audio_st->codec);av_free(pFrame);av_free(frame_buf);}avio_close(pFormatCtx->pb);avformat_free_context(pFormatCtx);fclose(in_file);return 0;
}

参考文献

1、https://blog.csdn.net/leixiaohua1020/article/details/25430449


推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
  • 本文介绍了在Cpp中将字符串形式的数值转换为int或float等数值类型的方法,主要使用了strtol、strtod和strtoul函数。这些函数可以将以null结尾的字符串转换为long int、double或unsigned long类型的数值,且支持任意进制的字符串转换。相比之下,atoi函数只能转换十进制数值且没有错误返回。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
author-avatar
海and云
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有