ffmpeg: FFmpeg という名前は、MPEG ビデオ エンコード規格に由来しています。その前の「FF」は「Fast Forward」を表します。これは、デジタル オーディオとビデオの記録と変換に使用できるオープン ソース コンピューター プログラムのセットです。そしてそれらをストリームに変換します。
ライブラリ構成:
libavformat: さまざまなオーディオおよびビデオのカプセル化フォーマットの生成および解析に使用されます。これには、デコードに必要な情報を取得してデコード コンテキスト構造を生成したり、オーディオおよびビデオ フレームを読み取ったりする機能が含まれます。
libavcodec: さまざまな種類のサウンド/画像のエンコードおよびデコードに使用されます。
libavutil: いくつかの公共ユーティリティ関数が含まれています。
libswscale: ビデオ シーンのスケーリングとカラー マッピングの変換に使用されます。
libpostproc: ポストエフェクト処理に使用されます。
ffmpeg: このプロジェクトによって提供されるツール。TV カードのフォーマット変換、デコード、またはリアルタイム エンコードに使用できます。
ffsever: HTTP マルチメディア リアルタイム ブロードキャスト ストリーミング サーバー。
ffplay: ffmpeg ライブラリを使用して解析およびデコードし、SDL を通じて表示する単純なプレーヤーです。
一般に、カメラの RTSP から取得するビデオ ストリームは、オリジナルのデータ ストリームである「ネイキッド ストリーム」です。結果として得られるコード ストリームは通常 h264 または h265 です。av_read_frame() を使用して各フレームのデータを読み取ります。データは構造体 AVpack に格納されます。
ビデオ ストリームを h264 および h265 ファイルに保存するプロセス:
( av_register_all() 函数在ffmpeg4.0以上版本已经被废弃,所以4.0以下版本就需要注册初始函数)
avformat_alloc_context( );用来申请AVFormatContext类型变量并初始化默认参数,申请的空间
avformat_open_input();打开网络流或文件流
avformat_find_stream_info();获取视频文件信息
av_malloc(sizeof( AVPacket )); 申请 AVPacket 空间,以便存放数据
av_read_frame();读取每一帧的(h264、h265)数据,存放在结构体AVPack里面
fwrite();写入文件,h264编码的文件的后缀写.h264,h265编码的文件的后缀写.h265,
av_free( packet ); 写完之后释放 AVPacket 的空间
avformat_free_context( );函数释放空间
avformat_close_input();关闭rtsp流
用FFmpeg将rtsp视频流保存成文件的demo:
#include #include #ifdef __cplusplus
extern "C"
{
#endif
/*Include ffmpeg header file*/
#include #ifdef __cplusplus
}
#endif
int main()
{
AVFormatContext *pFormatCtx = NULL;
AVDictionary *options = NULL;
AVPacket *packet = NULL;
char filepath[] = "rtsp://172.168.0.161:554/11";
//av_register_all(); //函数在ffmpeg4.0以上版本已经被废弃,所以4.0以下版本就需要注册初始函数
av_dict_set(&options, "buffer_size", "1024000", 0); //设置缓存大小,1080p可将值跳到最大
av_dict_set(&options, "rtsp_transport", "tcp", 0); //以tcp的方式打开,
av_dict_set(&options, "stimeout", "5000000", 0); //设置超时断开链接时间,单位us
av_dict_set(&options, "max_delay", "500000", 0); //设置最大时延
pFormatCtx = avformat_alloc_context(); //用来申请AVFormatContext类型变量并初始化默认参数,申请的空间
//打开网络流或文件流
if (avformat_open_input(&pFormatCtx, filepath, NULL, &options) != 0)
{
printf("Couldn't open input stream.\n");
return 0;
}
//获取视频文件信息
if (avformat_find_stream_info(pFormatCtx, NULL)<0)
{
printf("Couldn't find stream information.\n");
return 0;
}
//查找码流中是否有视频流
int videoindex = -1;
unsigned i = 0;
for (i = 0; inb_streams; i++)
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoindex = i;
break;
}
if (videoindex == -1)
{
printf("Didn't find a video stream.\n");
return 0;
}
packet = (AVPacket *)av_malloc(sizeof(AVPacket)); // 申请空间,存放的每一帧数据 (h264、h265)
FILE *fpSave;
fpSave = fopen("geth264_test.h264", "wb");
//这边可以调整i的大小来改变文件中的视频时间,每 +1 就是一帧数据
for (i = 0; i < 200; i++)
{
if (av_read_frame(pFormatCtx, packet) >= 0)
{
if (packet->stream_index == videoindex)
{
fwrite(packet->data, 1, packet->size, fpSave);
}
av_packet_unref(packet);
}
}
fclose(fpSave);
av_free(packet);
avformat_close_input(&pFormatCtx);
return 0;
}