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

ffmpeg音频的解码和编码

音频和视频其实是一样的,在文件中寻找音频流,然后解压出来,得到音频帧的数据,同样也可以按照设定的编码格式进行压缩࿰

        音频和视频其实是一样的,在文件中寻找音频流,然后解压出来,得到音频帧的数据,同样也可以按照设定的编码格式进行压缩,我这里把音频的解码和编码做成了两个工程,也是直接上代码:

#include
#include
extern "C"
{
#include
#include
#include
}
int main(char arg,char *argv[])
{
char *filename = argv[1];
av_register_all(); //注册所有可解码类型
AVFormatContext *pInFmtCtx=NULL; //文件格式
AVCodecContext *pInCodecCtx=NULL; //编码格式
if (av_open_input_file(&pInFmtCtx, filename, NULL, 0, NULL)!=0) //获取文件格式
printf("av_open_input_file error\n");
if (av_find_stream_info(pInFmtCtx) <0) //获取文件内音视频流的信息
printf("av_find_stream_info error\n");
unsigned int j;
// Find the first audio stream
int audioStream &#61; -1;
for (j&#61;0; jnb_streams; j&#43;&#43;) //找到音频对应的stream
{
if (pInFmtCtx->streams[j]->codec->codec_type &#61;&#61; CODEC_TYPE_AUDIO)
{
audioStream &#61; j;
break;
}
}
if (audioStream &#61;&#61; -1)
{
printf("input file has no audio stream\n");
return 0; // Didn&#39;t find a audio stream
}
printf("audio stream num: %d\n",audioStream);
pInCodecCtx &#61; pInFmtCtx->streams[audioStream]->codec; //音频的编码上下文
AVCodec *pInCodec &#61; NULL;
pInCodec &#61; avcodec_find_decoder(pInCodecCtx->codec_id); //根据编码ID找到用于解码的结构体
if (pInCodec &#61;&#61; NULL)
{
printf("error no Codec found\n");
return -1 ; // Codec not found
}
if(avcodec_open(pInCodecCtx, pInCodec)<0)//将两者结合以便在下面的解码函数中调用pInCodec中的对应解码函数
{
printf("error avcodec_open failed.\n");
return -1; // Could not open codec
}
static AVPacket packet;
printf(" bit_rate &#61; %d \r\n", pInCodecCtx->bit_rate);
printf(" sample_rate &#61; %d \r\n", pInCodecCtx->sample_rate);
printf(" channels &#61; %d \r\n", pInCodecCtx->channels);
printf(" code_name &#61; %s \r\n", pInCodecCtx->codec->name);
printf(" block_align &#61; %d\n",pInCodecCtx->block_align);
uint8_t *pktdata;
int pktsize;
int out_size &#61; AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
uint8_t * inbuf &#61; (uint8_t *)malloc(out_size);
FILE* pcm;
pcm &#61; fopen("result.pcm","wb");
long start &#61; clock();
while (av_read_frame(pInFmtCtx, &packet) >&#61; 0)//pInFmtCtx中调用对应格式的packet获取函数
{
if(packet.stream_index&#61;&#61;audioStream)//如果是音频
{
pktdata &#61; packet.data;
pktsize &#61; packet.size;
while(pktsize>0)
{
out_size &#61; AVCODEC_MAX_AUDIO_FRAME_SIZE*100;
//解码
int len &#61; avcodec_decode_audio2(pInCodecCtx, (short*)inbuf, &out_size, pktdata, pktsize);
if (len <0)
{
printf("Error while decoding.\n");
break;
}
if(out_size > 0)
{
fwrite(inbuf,1,out_size,pcm);//pcm记录
fflush(pcm);
}
pktsize -&#61; len;
pktdata &#43;&#61; len;
}
}
av_free_packet(&packet);
}
long end &#61; clock();
printf("cost time :%f\n",double(end-start)/(double)CLOCKS_PER_SEC);
free(inbuf);
fclose(pcm);
if (pInCodecCtx!&#61;NULL)
{
avcodec_close(pInCodecCtx);
}
av_close_input_file(pInFmtCtx);
return 0;
}


       文件保存为result.pcm中&#xff0c;现在用这个文件压缩出新的音频文件&#xff0c;代码如下&#xff1a;

void main()
{
int16_t *samples;
uint8_t *audio_outbuf;
int audio_outbuf_size;
int audio_input_frame_size;
double audio_pts;
const char* filename &#61; "test.wav";
FILE *fin &#61; fopen("result.pcm", "rb"); //音频源文件
AVOutputFormat *fmt;
AVFormatContext *oc;
AVStream * audio_st;
av_register_all();
fmt &#61; guess_format(NULL, filename, NULL);
oc &#61; av_alloc_format_context();
oc->oformat &#61; fmt;
snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
audio_st &#61; NULL;
if (fmt->audio_codec !&#61; CODEC_ID_NONE)
{
AVCodecContext *c;
audio_st &#61; av_new_stream(oc, 1);
c &#61; audio_st->codec;
c->codec_id &#61; fmt->audio_codec;
c->codec_type &#61; CODEC_TYPE_AUDIO;
c->bit_rate &#61; 128000;
c->sample_rate &#61; 44100;
c->channels &#61; 2;
}
if (av_set_parameters(oc, NULL) <0)
{
return;
}
dump_format(oc, 0, filename, 1);
if (audio_st)
{
AVCodecContext* c;
AVCodec* codec;
c &#61; audio_st->codec;
codec &#61; avcodec_find_encoder(c->codec_id);
avcodec_open(c, codec);
audio_outbuf_size &#61; 10000;
audio_outbuf &#61; (uint8_t*)av_malloc(audio_outbuf_size);
if (c->frame_size <&#61; 1)
{
audio_input_frame_size &#61; audio_outbuf_size / c->channels;
switch (audio_st->codec->codec_id)
{
case CODEC_ID_PCM_S16LE:
case CODEC_ID_PCM_S16BE:
case CODEC_ID_PCM_U16LE:
case CODEC_ID_PCM_U16BE:
audio_input_frame_size >>&#61; 1;
break;
default:
break;
}
}
else
{
audio_input_frame_size &#61; c->frame_size;
}
samples &#61; (int16_t*)av_malloc(audio_input_frame_size*2*c->channels);
}
if (!fmt->flags & AVFMT_NOFILE)
{
if (url_fopen(&oc->pb, filename, URL_WRONLY) <0)
{
return;
}
}
av_write_header(oc);
for (;;)
{
if (audio_st)
{
audio_pts &#61; (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
}
else
{
audio_pts &#61; 0.0;
}
if (!audio_st || audio_pts >&#61; 360.0)
{
break;
}
if (fread(samples, 1, audio_input_frame_size*2*audio_st->codec->channels, fin) <&#61; 0)
{
break;
}
AVCodecContext* c;
AVPacket pkt;
av_init_packet(&pkt);
c &#61; audio_st->codec;
pkt.size &#61; avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
pkt.pts &#61; av_rescale_q(c->coded_frame->pts, c->time_base, audio_st->time_base);
pkt.flags |&#61; PKT_FLAG_KEY;
pkt.stream_index &#61; audio_st->index;
pkt.data &#61; audio_outbuf;
if (av_write_frame(oc, &pkt) !&#61; 0)
{
return;
}
}
if (audio_st)
{
avcodec_close(audio_st->codec);
av_free(samples);
av_free(audio_outbuf);
}
av_write_trailer(oc);
for (int i&#61;0; inb_streams; i&#43;&#43;)
{
av_freep(&oc->streams[i]->codec);
av_freep(&oc->streams[i]);
}
if (!(fmt->flags & AVFMT_NOFILE))
{
url_fclose(oc->pb);
}
av_free(oc);
fclose(fin);
}


 


推荐阅读
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
author-avatar
又ettl_329
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有