将模拟信号转化为数字信号,隔段时间进行采样
Fmpeg 是领先的多媒体框架,能够解码、编码、转码、混合、解密、流媒体、过滤和播放人类和机器创造的几乎所有东西
。它支持最晦涩的古老格式,直到最尖端的格式。无论它们是由某个标准委员会、社区还是公司设计的。它还具有高度的便携性。
FFmpeg 可以在 多个平台构建环境、机器架构和配置下编译、运行,并通过测试基础设施 FATE。
命令格式
功能
ffmpeg.exe用于视频的转码
最简单的命令
ffmpeg -i input.avi -b:v 640k output.ts
该命令将当前文件夹下的input.avi转换为output.ts文件,并将其文件视频的码率设置为640kbps。
命令格式
ffmpeg -i (输入文件路径) -b:v (输出视频码率) (输出文件路径)
命令参数
参数 | 说明 |
---|---|
-h | 帮助 |
-i filename | 输入文件 |
-t duration | 设置处理时间,格式为hh:mm:ss |
-ss duration | 设置起始时间,格式为hh:mm:ss |
-b:v bltrate | 设置视频码率 |
-b:a bitrate | 设置音频码率 |
-r fps | 设置帧率 |
-s wxh | 设置分辨率,格式为WxH(用*也可以) |
-c:v codec | 设置视频编码器 |
-c:a codec | 设置音频编码器 |
-ar freq | 设置音频采样率 |
如: ffmpeg -i video.mkv video.mp4 将video从MKV格式转码为MP4格式并另外保存
命令格式
功能
用于视频的播放
最简单的命令
ffplay input.avi
该命令将播放当前文件夹下的input.avi文件。
命令格式
ffmpeg (输入文件路径)
命令参数
快捷键 | 说明 |
---|---|
q,ESC | 退出 |
p,空格 | 暂停 |
鼠标右键屏幕 | 跳转到指定位置 |
av+register_all():注册所有组件
avformat_network_init()
avformat_open_input(…):打开输入视频文件
avformat_find_stream_info(…):获取视频文件信息
avcodec_find_decoder():查找解码器
avcodec_open2():打开解码器
av_find_best_stream(…)
AVFormatContext (封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息)
AVInputFormat (每种封装格式(例如FLV,MKV,MP4,AVI)对应一个结构体)
AVStream (视频文件中每个视频(音频)流对应一个结构体)
av_read_frame(…):从输入文件读取一帧压缩数据
avcodec_decode_video2():解码一帧压缩数据
avcodec_close():关闭解码器
PCM音频数据
视频播放器原理
可以使用软件mediainfo进行读取。
配置ffmpeg所依赖的文件(此处是VS的配置,Qt Creator单独配置):
extern "C"{#include "libacformat/avformat.h"
}
#include
#include
extern "C" {#include "libacformat/avformat.h"
}#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")static double FractionToDouble(AVRational fraction)//AVRational为分数表示,其目的为避免精度损失,分数表示为分子除以分母
{return fraction.den == 0?0:(double)fraction.num/(double)fraction.den;
}int main(int argc,char *argv[])
{QCoreApplication a(argc,argv);const char* path &#61; "test.mp4";//初始化封装库av_register_all();//打开输入视频文件AVFormatContext *avfc &#61; NULL;int ret &#61; avformat_open_input(&avfc,path,NULL,NULL); //传二级指针一般是对指针进行赋值的时候if(ret !&#61; 0){qDebug()<<"OPen"<<path<<"failed!";exit(-1);}//获取流信息ret &#61; avformat_find_stream_info(avfc,NULL);if(ret < 0){qDebug()<<"avformat_find_stream_info_failed!";exit(-1);}//总时长-秒数qDebug()<<(avfc->duration / AV_TIME_BASE);//avfc->streamsqDebug()<<"streams number is:"<<avfc->nb_streams;for(int i &#61; 0; i < avfc->nb->streams;i&#43;&#43;){qDebug()<<"i is "<<i;AVStream* as &#61; avfc->streams[i];qDebug()<<as->codecpar->codec_id; //AV_CODEC_ID_H264(解码)qDebug()<<as->codecpar->format;qDebug();//音频 AVMEDIA_TYPE_AUDIOif(as->codecpar->codec_type &#61;&#61; AVMEDIA_TYPE_AUDIO){qDebug()<<i<<"audio info";qDebug()<<"sample_rate&#61;"<<as->codecpar->sample_rate;qDebug()<<"Channels&#61;"<<as->codecpar->channels;}//视频 AVMEDIA_TYPE_VIDEOelse if(as->codecpar->codec_type &#61;&#61; AVMEDIA_TYPE_VIDEO){qDebug()<<i<<"video info";qDebug()<<"width&#61;"<<as->codecpar->width;qDebug()<<"height&#61;"<<as->codecpar->height;//帧率fpsqDebug()<<"video fps&#61;"<<FractionToDouble(as->avg_frame_rate);}}return a.exec();
}
#include
#include
extern "C" {#include "libacformat/avformat.h"#include "libavcodec/avcodec.h" //解码
}#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")static double FractionToDouble(AVRational fraction)
{return fraction.den &#61;&#61; 0?0:(double)fraction.num/(double)fraction.den;
}int main(int argc,char *argv[])
{QCoreApplication a(argc,argv);const char* path &#61; "test.mp4";av_register_all();//初始化解码器avcodec_register_all();//音视频索引&#xff0c;读取时可以区别音视频int videoStream &#61; 0; //int audioStream &#61; 1; //AVFormatContext *avfc &#61; NULL;int ret &#61; avformat_open_input(&avfc,path,NULL,NULL);if(ret !&#61; 0){qDebug()<<"OPen"<<path<<"failed!";exit(-1);}ret &#61; avformat_find_stream_info(avfc,NULL);if(ret < 0){qDebug()<<"avformat_find_stream_info_failed!";exit(-1);}qDebug()<<(avfc->duration / AV_TIME_BASE);//avfc->streamsqDebug()<<"streams number is:"<<avfc->nb_streams;for(int i &#61; 0; i < avfc->nb->streams;i&#43;&#43;){qDebug()<<"i is "<<i;AVStream* as &#61; avfc->streams[i];qDebug()<<as->codecpar->codec_id;qDebug()<<as->codecpar->format;qDebug();if(as->codecpar->codec_type &#61;&#61; AVMEDIA_TYPE_AUDIO){audioStream &#61; i; //qDebug()<<"sample_rate&#61;"<<as->codecpar->sample_rate;qDebug()<<"Channels&#61;"<<as->codecpar->channels;}else if(as->codecpar->codec_type &#61;&#61; AVMEDIA_TYPE_VIDEO){videoStream &#61; i; //qDebug()<<"width&#61;"<<as->codecpar->width;qDebug()<<"height&#61;"<<as->codecpar->height;qDebug()<<"video fps&#61;"<<FractionToDouble(as->avg_frame_rate);}}//找到视频解码器&#xff0c;创建并打开解码器AVCodec* vcodec &#61; avcodec_find_decoder(avfc->streams[videoStream]->codecpar->code_id);if (vcodec){qDebug()<<"video Can&#39;t find the video codec";}//上下文AVCodecCOntext* vc &#61; avcodec_alloc_context3(vcodec);//参数ret &#61; avcodec_parameters_to_context(vc,avfc->streams[videoStream]->codecpar);if (ret < 0){qDebug()<<"video avcodec_parameters_to_context failed";}//8线程同时解码vc->thread_count &#61; 8;avcodec_open2(vc,NULL,NULL);if (ret < 0){qDebug()<<"video avcodec_open2 failed";}//找到音频解码器&#xff0c;创建并打开解码器AVCodec* acodec &#61; avcodec_find_decoder(avfc->streams[audiooStream]->codecpar->code_id);if (acodec){qDebug()<<"audio Can&#39;t find the video codec";}//上下文AVCodecCOntext* ac &#61; avcodec_alloc_context3(acodec);//参数ret &#61; avcodec_parameters_to_context(ac,avfc->streams[audiooStream]->codecpar);if (ret < 0){qDebug()<<"audio avcodec_parameters_to_context failed";}//8线程同时解码ac->thread_count &#61; 8;avcodec_open2(ac,NULL,NULL);if (ret < 0){qDebug()<<"audio accodec_open2 failed";}//Packet,FrameAVPacket* pkt &#61; av_packet_alloc(); //using av_packet_free()AVFrame* frame &#61; av_frame_alloc(); //using av_frame_free()ret &#61; 0;while(ret >&#61; 0){ret &#61; av_read_frame(avfc,pkt); //一帧帧的读qDebug()<<"pkt->size&#61;"<<pkt->size;qDebug()<<"pkt->pts&#61;"<<pkt->pts;qDebug()<<"pkt->dts&#61;"<<pkt->dts;//完成解码操作AVCodecContext* cc &#61; NULL;if(pkt->stream_index &#61;&#61; videoStream){qDebug()<<"视频数据";cc &#61; vc;}else if(pkt->stream_index &#61;&#61; audeoStream){qDebug()<<"音频数据";cc &#61; ac;}int ret2 &#61; avcodec_send_packet(cc,pkt);//以frame形式输出av_packet_unref(pkt);//引用计数-1if(ret2 !&#61; 0){qDebug<<"Send packet failed";}//接受framewhile(true){//有可能多处接受decode发过来的frameint ret3 &#61; avcodec_receive_frame(cc,frame);if(ret3 !&#61; 0){break;}qDebug<<"recv frame"<<frame->format<<" "<<frame->linesize[0];}}//释放资源av_frame_free(&frame);av_packet_free(&pkt);if(avfc){avformat_close_input(&avfc);}avfc &#61; NULL;return a.exec();
}