FFmpeg は rtsp ビデオ ストリームを H264、h265 ファイルに保存します

FFmpeg という名前は、MPEG ビデオ エンコード規格に由来しています。その前の「FF」は「Fast Forward」を表します。これは、デジタル オーディオとビデオの記録と変換に使用できるオープン ソースのコンピューター プログラムのセットです。それらをストリームに流し込みます。

ライブラリ構成:

libavformat : さまざまなオーディオおよびビデオのカプセル化形式の生成と解析に使用されます。これには、デコードに必要な情報を取得してデコード コンテキスト構造を生成したり、オーディオおよびビデオ フレームを読み取ったりする機能が含まれます。

libavcodec : さまざまな種類のサウンド/画像のエンコードおよびデコードに使用されます。

libavutil : いくつかの公共ユーティリティ関数が含まれています。

libswscale : ビデオシーンのスケーリングとカラーマッピングの変換に使用されます。

libpostproc : ポストエフェクト処理に使用されます。

ffmpeg : このプロジェクトによって提供されるツール。TV カードのフォーマット変換、デコード、またはインスタント エンコードに使用できます。

ffsever : HTTP マルチメディア リアルタイム ブロードキャスト ストリーミング サーバー。

ffplay : ffmpeg ライブラリを使用して解析およびデコードし、SDL を通じて表示する単純なプレーヤーです。

一般に、カメラの RTSP から取得するビデオ ストリームは、オリジナルのデータ ストリームである「ネイキッド ストリーム」です。取得されたコードストリームは通常 h264 または h265 であり、av_read_frame() を使用して各フレームのデータを読み取り、データは構造体 AVpack に格納されます。

ビデオ ストリームを h364 および h365 ファイルに保存するプロセス:

(av_register_all() 関数は ffmpeg 4.0 より上のバージョンでは廃止されたため、4.0 より前のバージョンでは初期関数を登録する必要があります)
avformat_alloc_context() ; AVFormatContext 型変数の適用とデフォルト パラメータの初期化、およびスペースの適用に使用されます
avformat_open_input() ;ネットワークストリームまたはファイルストリームを開く
avformat_find_stream_info() ; ビデオファイル情報を取得する
av_malloc(sizeof(AVPacket)) ; データを保存するために AVPacket スペースを申請する
av_read_frame() ; 各フレームの (h264, h265) データを読み取り、 Structure AVPack
fwrite () ; ファイルを書き込み、h264 エンコードされたファイルのサフィックスは .h264 として書き込まれ、h265 エンコードされたファイルのサフィックスは .h265 として書き込まれます av_free
(packet) ; 書き込み後、AVPacket のスペースを解放します
avformat_free_context( ) ; 関数はスペースを解放します
avformat_close_input() ; rtsp ストリームを閉じます

FFmpeg を使用して rtsp ビデオ ストリームをファイルに保存するデモ:

#include <stdio.h>
#include <stdlib.h>
 
#ifdef __cplusplus 
extern "C"
{
#endif
	/*Include ffmpeg header file*/
#include <libavformat/avformat.h> 
#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; i<pFormatCtx->nb_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;
}

おすすめ

転載: blog.csdn.net/xiehuanbin/article/details/133159703