O nome FFmpeg vem do padrão de codificação de vídeo MPEG. O "FF" na frente dele significa "Fast Forward". É um conjunto de programas de computador de código aberto que podem ser usados para gravar e converter áudio e vídeo digital e converter -los em fluxos.
Composição da biblioteca:
libavformat : utilizado para geração e análise de diversos formatos de encapsulamento de áudio e vídeo, incluindo funções como obtenção das informações necessárias para decodificação para geração de estruturas de contexto de decodificação e leitura de quadros de áudio e vídeo;
libavcodec : usado para vários tipos de codificação e decodificação de som/imagem;
libavutil : Contém algumas funções de utilidade pública;
libswscale : usado para dimensionamento de cenas de vídeo e conversão de mapeamento de cores;
libpostproc : usado para processamento pós-efeito;
ffmpeg : Ferramenta disponibilizada por este projeto, que pode ser utilizada para conversão de formato, decodificação ou codificação instantânea de placas de TV;
ffsever : um servidor HTTP de streaming de transmissão multimídia em tempo real;
ffplay : É um player simples que usa a biblioteca ffmpeg para analisar e decodificar e exibi-la por meio de SDL;
Geralmente, os fluxos de vídeo que obtemos da câmera RTSP são “naked streams”, que são fluxos de dados originais. O fluxo de código obtido é geralmente h264 ou h265. Use av_read_frame() para ler os dados de cada quadro. Os dados são armazenados na estrutura AVpack.
O processo de salvar streams de vídeo em arquivos h364 e h365:
(A função av_register_all() foi abandonada em versões acima do ffmpeg 4.0, então versões abaixo de 4.0 precisam registrar a função inicial)
avformat_alloc_context() ;usado para aplicar variáveis do tipo AVFormatContext e inicializar parâmetros padrão, e aplicar para espaço
avformat_open_input() ; abra o fluxo de rede Ou fluxo de arquivo
avformat_find_stream_info() ; Obtenha informações do arquivo de vídeo
av_malloc(sizeof(AVPacket)) ; Solicite espaço AVPacket para armazenar dados
av_read_frame() ; Leia os dados (h264, h265) de cada quadro e armazene-os no estrutura AVPack
fwrite () ; Grava arquivos, o sufixo dos arquivos codificados em h264 é escrito como .h264, e o sufixo dos arquivos codificados em h265 é escrito como .h265
av_free(packet) ; Após escrever, libere o espaço do AVPacket
avformat_free_context( ) ; Função libera espaço
avformat_close_input() ; Fecha stream rtsp
Demonstração de uso do FFmpeg para salvar stream de vídeo rtsp em um arquivo:
#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;
}