先附上代码,测试通过

#include <stdio.h>
#include <math.h>
#include "libavutil/avstring.h"
//修改colorspace.h中的inline为__inline
#include "libavutil/colorspace.h"
#include "libavutil/pixdesc.h"
#include "libavutil/imgutils.h"
#include "libavutil/dict.h"
#include "libavutil/parseutils.h"
#include "libavutil/samplefmt.h"
#include "libavutil/avassert.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavcodec/audioconvert.h"
#include "libavutil/opt.h"
#include "libavcodec/avfft.h"
#include "cmdutils.h"
#include "pthread.h" static AVPacket flush_pkt;//暂时不知道flush_pkt有什么作用,暂时先放这里。 //#define DEBUG_SYNC #define MAX_QUEUE_SIZE (15 * 1024 * 1024)
#define MIN_AUDIOQ_SIZE (20 * 16 * 1024)
#define MIN_FRAMES 5 /* SDL audio buffer size, in samples. Should be small to have precise
A/V sync as SDL does not have hardware buffer fullness info. */
#define SDL_AUDIO_BUFFER_SIZE 1024 /* no AV sync correction is done if below the AV sync threshold */
#define AV_SYNC_THRESHOLD 0.01
/* no AV correction is done if too big error */
#define AV_NOSYNC_THRESHOLD 10.0 #define FRAME_SKIP_FACTOR 0.05 /* maximum audio speed change to get correct sync */
#define SAMPLE_CORRECTION_PERCENT_MAX 10 /* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */
#define AUDIO_DIFF_AVG_NB 20 /* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
#define SAMPLE_ARRAY_SIZE (2*65536) typedef struct PacketQueue {
AVPacketList *first_pkt, *last_pkt;
int nb_packets;
int size;
int abort_request;
pthread_mutex_t *mutex;//互斥锁
pthread_cond_t *cond;//条件变量
} PacketQueue; #define VIDEO_PICTURE_QUEUE_SIZE 2
#define SUBPICTURE_QUEUE_SIZE 4 typedef struct VideoPicture {
double pts; ///<presentation time stamp for this picture
double target_clock; ///<av_gettime() time at which this should be displayed ideally
int64_t pos; ///<byte position in file
// SDL_Overlay *bmp;
int width, height; /* source height & width */
int allocated;
enum PixelFormat pix_fmt; #if CONFIG_AVFILTER
AVFilterBufferRef *picref;
#endif
} VideoPicture; typedef struct SubPicture {
double pts; /* presentation time stamp for this picture */
AVSubtitle sub;
} SubPicture; enum {
AV_SYNC_AUDIO_MASTER, /* default choice */
AV_SYNC_VIDEO_MASTER,
AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */
}; typedef struct VideoState {
pthread_t *parse_tid;
//SDL_Thread *parse_tid;
pthread_t *video_tid;
//SDL_Thread *video_tid;
pthread_t *refresh_tid;
//SDL_Thread *refresh_tid;
AVInputFormat *iformat;
int no_background;
int abort_request;
int paused;
int last_paused;
int seek_req;
int seek_flags;
int64_t seek_pos;
int64_t seek_rel;
int read_pause_return;
AVFormatContext *ic;
int dtg_active_format; int audio_stream; int av_sync_type;
double external_clock; /* external clock base */
int64_t external_clock_time; double audio_clock;
double audio_diff_cum; /* used for AV difference average computation */
double audio_diff_avg_coef;
double audio_diff_threshold;
int audio_diff_avg_count;
AVStream *audio_st;
PacketQueue audioq;
int audio_hw_buf_size;
/* samples output by the codec. we reserve more space for avsync
compensation */
DECLARE_ALIGNED(,uint8_t,audio_buf1)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * ) / ];
DECLARE_ALIGNED(,uint8_t,audio_buf2)[(AVCODEC_MAX_AUDIO_FRAME_SIZE * ) / ];
uint8_t *audio_buf;
unsigned int audio_buf_size; /* in bytes */
int audio_buf_index; /* in bytes */
AVPacket audio_pkt_temp;
AVPacket audio_pkt;
enum AVSampleFormat audio_src_fmt;
AVAudioConvert *reformat_ctx; enum ShowMode {
SHOW_MODE_NONE = -, SHOW_MODE_VIDEO = , SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB
} show_mode;
int16_t sample_array[SAMPLE_ARRAY_SIZE];
int sample_array_index;
int last_i_start;
RDFTContext *rdft;
int rdft_bits;
FFTSample *rdft_data;
int xpos; pthread_t *subtitle_tid;
//SDL_Thread *subtitle_tid;
int subtitle_stream;
int subtitle_stream_changed;
AVStream *subtitle_st;
PacketQueue subtitleq;
SubPicture subpq[SUBPICTURE_QUEUE_SIZE];
int subpq_size, subpq_rindex, subpq_windex; pthread_mutex_t *subpq_mutex;
pthread_cond_t *subpq_cond;
//SDL_mutex *subpq_mutex;
//SDL_cond *subpq_cond; double frame_timer;
double frame_last_pts;
double frame_last_delay;
double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
int video_stream;
AVStream *video_st;
PacketQueue videoq;
double video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)
double video_current_pts_drift; ///<video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts
int64_t video_current_pos; ///<current displayed file pos
VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
int pictq_size, pictq_rindex, pictq_windex;
pthread_mutex_t *pictq_mutex;
//SDL_mutex *pictq_mutex;
pthread_cond_t *pictq_cond;
//SDL_cond *pictq_cond; struct SwsContext *img_convert_ctx; // QETimer *video_timer;
char filename[];
int width, height, xleft, ytop; //PtsCorrectionContext pts_ctx; float skip_frames;
float skip_frames_index;
int refresh;
} VideoState; static int opt_help(const char *opt, const char *arg); /* options specified by the user */
static AVInputFormat *file_iformat;
static const char *input_filename;
static const char *window_title;
static int fs_screen_width;
static int fs_screen_height;
static int screen_width = ;
static int screen_height = ;
static int frame_width = ;
static int frame_height = ;
static enum PixelFormat frame_pix_fmt = PIX_FMT_NONE;
static int audio_disable;
static int video_disable;
/*
static int wanted_stream[AVMEDIA_TYPE_NB]={
[AVMEDIA_TYPE_AUDIO]=-1,
[AVMEDIA_TYPE_VIDEO]=-1,
[AVMEDIA_TYPE_SUBTITLE]=-1,
};
*/
static int wanted_stream[AVMEDIA_TYPE_NB]={-,-,,-,};
static int seek_by_bytes=-;
static int display_disable;
static int show_status = ;
static int av_sync_type = AV_SYNC_AUDIO_MASTER;
static int64_t start_time = AV_NOPTS_VALUE;
static int64_t duration = AV_NOPTS_VALUE;
static int step = ;
static int thread_count = ;
static int workaround_bugs = ;
static int fast = ;
static int genpts = ;
static int lowres = ;
static int idct = FF_IDCT_AUTO;
static enum AVDiscard skip_frame= AVDISCARD_DEFAULT;
static enum AVDiscard skip_idct= AVDISCARD_DEFAULT;
static enum AVDiscard skip_loop_filter= AVDISCARD_DEFAULT;
static int error_recognition = FF_ER_CAREFUL;
static int error_concealment = ;
static int decoder_reorder_pts= -;
static int autoexit;
static int exit_on_keydown;
static int exit_on_mousedown;
static int loop=;
static int framedrop=-;
static enum ShowMode show_mode = SHOW_MODE_NONE; static int rdftspeed=;
#if CONFIG_AVFILTER
static char *vfilters = NULL;
#endif /* current context */
static int is_full_screen;
static VideoState *cur_stream;
static int64_t audio_callback_time;
static AVPacket flush_pkt;//暂时不知道flush_pkt有什么作用,暂时先放这里。 static int packet_queue_put(PacketQueue *q, AVPacket *pkt); /* packet queue handling */
//初始化队列
static void packet_queue_init(PacketQueue *q)
{
memset(q, , sizeof(PacketQueue));
pthread_mutex_init(q->mutex,NULL);
pthread_cond_init(q->cond,NULL);
//q->mutex = SDL_CreateMutex();
//q->cond = SDL_CreateCond();
packet_queue_put(q, &flush_pkt);
} //清空队列
static void packet_queue_flush(PacketQueue *q)
{
AVPacketList *pkt, *pkt1; pthread_mutex_lock(q->mutex);
//SDL_LockMutex(q->mutex);
for(pkt = q->first_pkt; pkt != NULL; pkt = pkt1) {
pkt1 = pkt->next;
av_free_packet(&pkt->pkt);
av_freep(&pkt);
}
q->last_pkt = NULL;
q->first_pkt = NULL;
q->nb_packets = ;
q->size = ;
pthread_mutex_unlock(q->mutex);
//SDL_UnlockMutex(q->mutex);
} static void packet_queue_end(PacketQueue *q)
{
packet_queue_flush(q);
pthread_mutex_destroy(q->mutex);
pthread_cond_destroy(q->cond);
//SDL_DestroyMutex(q->mutex);
//SDL_DestroyCond(q->cond);
} static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
{
AVPacketList *pkt1; /* duplicate the packet */
if (pkt!=&flush_pkt && av_dup_packet(pkt) < )
return -; pkt1 = av_malloc(sizeof(AVPacketList));
if (!pkt1)
return -;
pkt1->pkt = *pkt;
pkt1->next = NULL; pthread_mutex_lock(q->mutex);
// SDL_LockMutex(q->mutex); if (!q->last_pkt) q->first_pkt = pkt1;
else
q->last_pkt->next = pkt1;
q->last_pkt = pkt1;
q->nb_packets++;
q->size += pkt1->pkt.size + sizeof(*pkt1);
/* XXX: should duplicate packet data in DV case */
pthread_cond_signal(q->cond);
// SDL_CondSignal(q->cond); // SDL_UnlockMutex(q->mutex);
pthread_mutex_unlock(q->mutex);
return ;
} static void packet_queue_abort(PacketQueue *q)
{
pthread_mutex_lock(q->mutex);
//SDL_LockMutex(q->mutex); q->abort_request = ; pthread_cond_signal(q->cond);
//SDL_CondSignal(q->cond); pthread_mutex_unlock(q->mutex);
//SDL_UnlockMutex(q->mutex);
} //packet_queue_get 函数被调用的地方是audio_decode_frame,subtitle_thread,get_video_frame中,
//作用是从队列q中读取block(一般为)个packet,留待下一次进行解码
//avcodec_decode_audio3,avcodec_decode_video2
/* return < 0 if aborted, 0 if no packet and > 0 if packet. */
static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
{
AVPacketList *pkt1;
int ret; pthread_mutex_lock(q->mutex);
//SDL_LockMutex(q->mutex); for(;;) {
if (q->abort_request) {
ret = -;
break;
} pkt1 = q->first_pkt;
if (pkt1) {
q->first_pkt = pkt1->next;
if (!q->first_pkt)
q->last_pkt = NULL;
q->nb_packets--;
q->size -= pkt1->pkt.size + sizeof(*pkt1);
*pkt = pkt1->pkt;
av_free(pkt1);
ret = ;
break;
} else if (!block) {
ret = ;
break;
} else {
pthread_cond_wait(q->cond,q->mutex);
//SDL_CondWait(q->cond, q->mutex);
}
}
pthread_mutex_unlock(q->mutex);
//SDL_UnlockMutex(q->mutex);
return ret;
} //声明了一个内联函数,写wav头
static __inline void writeWavHeader(AVCodecContext *pCodecCtx,AVFormatContext *pFormatCtx,FILE *audioFile) {
//wav文件有44字节的wav头,所以要写44字节的wav头
int8_t *data;
int32_t long_temp;
int16_t short_temp;
int16_t BlockAlign;
int bits=;
int32_t fileSize;
int32_t audioDataSize; switch(pCodecCtx->sample_fmt) {
case AV_SAMPLE_FMT_S16:
bits=;
break;
case AV_SAMPLE_FMT_S32:
bits=;
break;
case AV_SAMPLE_FMT_U8:
bits=;
break;
default:
bits=;
break;
}
audioDataSize=(pFormatCtx->duration)*(bits/)*(pCodecCtx->sample_rate)*(pCodecCtx->channels);
fileSize=audioDataSize+;
data="RIFF";
fwrite(data,sizeof(char),,audioFile);
fwrite(&fileSize,sizeof(int32_t),,audioFile); //"WAVE"
data="WAVE";
fwrite(data,sizeof(char),,audioFile);
data="fmt ";
fwrite(data,sizeof(char),,audioFile);
long_temp=;
fwrite(&long_temp,sizeof(int32_t),,audioFile);
short_temp=0x01;
fwrite(&short_temp,sizeof(int16_t),,audioFile);
short_temp=(pCodecCtx->channels);
fwrite(&short_temp,sizeof(int16_t),,audioFile);
long_temp=(pCodecCtx->sample_rate);
fwrite(&long_temp,sizeof(int32_t),,audioFile);
long_temp=(bits/)*(pCodecCtx->channels)*(pCodecCtx->sample_rate);
fwrite(&long_temp,sizeof(int32_t),,audioFile);
BlockAlign=(bits/)*(pCodecCtx->channels);
fwrite(&BlockAlign,sizeof(int16_t),,audioFile);
short_temp=(bits);
fwrite(&short_temp,sizeof(int16_t),,audioFile);
data="data";
fwrite(data,sizeof(char),,audioFile);
fwrite(&audioDataSize,sizeof(int32_t),,audioFile); fseek(audioFile,,SEEK_SET); } int main()
{
// char *filename="rtsp://192.168.20.112/Love_You.mp4";
//char *filename="E:\\flv\\3d.mp3";
char *filename="E:\\flv\\MY.aac";
// char *filename="mms://mms.cnr.cn/cnr003";
// char *filename="mms://mms.cnr.cn/cnr001";
// char *filename="rtsp://livewm.orange.fr/live-multicanaux";
// char *filename="mms://211.167.102.66/ch-01";
AVFormatContext *pFormatCtx;
int audioStream=-;
int i;
int iFrame=;
AVCodecContext *pCodecCtx;
AVCodec *pCodec=NULL;
static AVPacket packet;
uint8_t *pktData=NULL;
int pktSize;
int outSize=AVCODEC_MAX_AUDIO_FRAME_SIZE;
// FILE *wavfile=NULL; //这里必须使用av_malloc
uint8_t *inbuf=(uint8_t *)av_malloc(outSize); FILE *wavFile=NULL;
int32_t audioFileSize=; //注册所有的编解码器
av_register_all(); //打开文件
if(av_open_input_file(&pFormatCtx,filename,NULL,,NULL)!=)
{
printf("Could not open input file %s\n",filename);
return ;
}
if(av_find_stream_info(pFormatCtx)<)
{
printf("Could not find stream information\n");
} //输出文件的音视频流信息
av_dump_format(pFormatCtx,,filename,); //找到音频流
for(i=;i<pFormatCtx->nb_streams;i++) {
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO) {
audioStream=i;
break;
}
} //找到解码器
pCodecCtx=pFormatCtx->streams[audioStream]->codec;
pCodec=avcodec_find_decoder(pCodecCtx->codec_id); //打开解码器
if(avcodec_open(pCodecCtx,pCodec)<) {
printf("Error avcodec_open failed.\n");
return ;
} printf("\tbit_rate=%d\n \
bytes_per_secondes=%d\n \
sample_rate=%d\n \
channels=%d\n \
codec_name=%s\n",pCodecCtx->bit_rate,(pCodecCtx->codec_id==CODEC_ID_PCM_U8)?8:16,
pCodecCtx->sample_rate,pCodecCtx->channels,pCodecCtx->codec->name); //wavFile=fopen("E:\\flv\\saveWav.wav","wb");
wavFile=fopen("E:\\flv\\MY.wav","wb");
//wavFile=fopen("E:\\flv\\test.wav","wb");
if (wavFile==NULL)
{
printf("open error\n");
return ;
} //写入wav文件头
writeWavHeader(pCodecCtx,pFormatCtx,wavFile); //开始解码音频流
av_free_packet(&packet);
while(av_read_frame(pFormatCtx,&packet)>=) {
if(packet.stream_index==audioStream) {
int len=;
if((iFrame++)>=)
break;
pktData=packet.data;
pktSize=packet.size;
while(pktSize>) {
outSize=AVCODEC_MAX_AUDIO_FRAME_SIZE;
len=avcodec_decode_audio3(pCodecCtx,(short *)inbuf,&outSize,&packet);
if(len<){
printf("Error while decoding\n");
break;
}
if(outSize>) {
audioFileSize+=outSize;
fwrite(inbuf,,outSize,wavFile);
fflush(wavFile);
}
pktSize-=len;
pktData+=len;
}
}
av_free_packet(&packet);
} //wav文件的第40个字节开始的4个字节存放的是wav文件的有效数据长度
fseek(wavFile,,SEEK_SET);
fwrite(&audioFileSize,,sizeof(int32_t),wavFile);
//wav文件的第4个字节开始的4个字节存放的是wav文件的文件长度(audioFileSize+44-8),44表示44个字节的头,8表示"RIFF"和"WAVE"
audioFileSize+=;
fseek(wavFile,,SEEK_SET);
fwrite(&audioFileSize,,sizeof(int32_t),wavFile); //关闭文件
fclose(wavFile); //释放内存
av_free(inbuf);
if(pCodecCtx!=NULL){
avcodec_close(pCodecCtx);
}
av_close_input_file(pFormatCtx);
return ;
}

需要用到的音视频解码静态库文件包括以下几个:

avcodec-53.lib,avdevice-53.lib,avfilter-2.lib,avformat-53.lib,avutil-51.lib,pthreadVC2.lib,swscale-2.lib

Windwos平台上ffmpeg解码音频并且保存到wav文件中的更多相关文章

  1. 使用scrapy爬取的数据保存到CSV文件中,不使用命令

    pipelines.py文件中 import codecs import csv # 保存到CSV文件中 class CsvPipeline(object): def __init__(self): ...

  2. Sql数据保存到Excel文件中

    public string ExportExcel( DataSet ds,string saveFileName) { try { if (ds == null) return "数据库为 ...

  3. 爬虫-----爬取所有国家的首都、面积 ,并保存到txt文件中

    # -*- coding:utf-8 -*- import urllib2import lxml.htmlfrom lxml import etree def main(): file = open( ...

  4. 根据导出的查询结果拼接字符串,生成sql语句并保存到txt文件中

    import os os.chdir("C:/") path = os.getcwd() print(path) f = open("sql.csv") # p ...

  5. Java读取接口中的数据,并保存到txt文件中!

    //创建读取接口中数据的方法 public static String read() { URL url = null; BufferedReader reader = null; HttpURLCo ...

  6. 保存到Excel文件中

    OLEObject ole_object , ole_workbooks ole_object = CREATE OLEObjectIF ole_object.ConnectToNewObject(& ...

  7. Windows/Ubuntu下,将所有文件名字列举出来并保存到txt文件中

    Windows下 使用如下的DOS命令来实现: dir /s /b > lists.txt 可以将当前路径下的所有文件的"文件路径+文件名"存储在lists.txt中. 其中 ...

  8. Python 过滤a文件中每一行内容,保存到b文件中

    #coding=utf-8print 1#初始化文件crash_log.log with open('e:/1/crash_log.log','w')as f: f.close() def fw(se ...

  9. c# 将datatable中的数据保存到excel文件中

    using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Lin ...

随机推荐

  1. 枚举在c与c++中定义的不同

    众所周知的,枚举是在运行期才决定枚举变量的值的,而不是像宏一样在预编译的时候就进行值得替换. 而且c标准规定: size(int) <= size(enum)<=系统所能表示的最大范围的值 ...

  2. Apache mod_wsgi部署Django项目

    学习python web开发,Django部署备忘 1.下载mod_wsgi,下载路径如下:http://code.google.com/p/modwsgi/downloads/list挑选For 2 ...

  3. jqGrid 设置列宽

    在jqgrid显示出来之后,需要手动调整列宽. 1. 经过调查jqgrid本身不支持指定列宽,当然这个是说的的初始化完成后. 2. 经过调查手动是可以调整列宽,所以进行了事件的查看resizestop ...

  4. json.net json转换神器

    json.nethttps://json.codeplex.com/ api documenthttp://james.newtonking.com/json/help/index.html#

  5. 群赛 ZOJ3741(dp) ZOJ3911(线段树)

    zoj3741 简单dp.wa了两个小时,中间改了好多细节.后来还是不对,参考了别人的代码,发现一个致命问题,初始化的时候,不是每种状态都能直接达到的.初始化成-1. (题目有个小坑,0<=L& ...

  6. 程序员需要掌握哪些IT技能

    据Foote Partners的最新调查:如今,你掌握的 IT 技能的多少决定了你薪资的多少,但你不一定非要比开源架构师或Certified Secure Software Life Cycle Pr ...

  7. WPF的MVVM模式

    Model->數據模型View->視圖View-Model->連接數據模型和視圖

  8. nyoj 27 水池数目

    水池数目 时间限制:3000 ms  |  内存限制:65535 KB 难度:4   描述 南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地 ...

  9. HTML的id,name,class

    HTML中的id是给JavaScript用的(document.getElementById()) HTML中的name是给JavaScript用的(formUploadFile.submit()) ...

  10. CSS3:clip-path具体解释

    我的一个学生,Heather Banks,想要实现他在Squarespace看到的一个效果: 依据她的以往经验,这个站点的HTML和CSS是全然在她的能力范围以内,于是我帮助她完毕了这个效果.显示na ...