/*
============================================================================
Name : test_ffmpeg.c
Author : cj
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
#include <stdio.h>
#include <stdlib.h>
#include "clog.h"
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
//https://blog.csdn.net/qq_29350001/article/details/78214267
int main(void) {
AVFormatContext *pFormatCtx;
int videoindex;
AVCodecContext *pCodecCtx;
AVFrame *pFrame;
AVPacket *packet;
// 改成你自己的 URL
//-rtsp_transport tcp
// SETUP rtsp://192.168.0.86:8880/hg.mp4/track1 RTSP/1.0
// Transport: RTP/AVP/TCP;unicast;interleaved=0-1
// CSeq: 3
// User-Agent: Lavf58.12.100
//
char filepath[] = "rtsp://192.168.2.1:8880/hg.264";
av_register_all();
avformat_network_init();
//avformat_network_deinit(); //thread_queue_size
pFormatCtx = avformat_alloc_context();
AVDictionary* options = NULL;
av_dict_set(&options, "buffer_size", "1024000", 0);
av_dict_set(&options, "max_delay", "500000", 0);
av_dict_set(&options, "stimeout", "20000000", 0); //设置超时断开连接时间
av_dict_set(&options, "rtsp_transport", "tcp", 0); //以udp方式打开,如果以tcp方式打开将udp替换为tcp
if (avformat_open_input(&pFormatCtx, filepath, NULL, &options) != 0) 打开网络流或文件流
{
printf("Couldn't open input stream.\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
printf("Couldn't find stream information.\n");
return -1;
}
videoindex = -1;
videoindex = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1,
NULL, 0);
if (videoindex == -1) {
printf("Didn't find a video stream.\n");
return -1;
}
pCodecCtx = pFormatCtx->streams[videoindex]->codec;
pFrame = av_frame_alloc();
//Output Info---输出一些文件(RTSP)信息
log_d("---------------- File Information (%s)---------------\n",
avcodec_get_name(pCodecCtx->codec_id));
av_dump_format(pFormatCtx, 0, filepath, 0);
log_d("-------------------------------------------------\n");
packet = (AVPacket *) av_malloc(sizeof(AVPacket));
FILE *fpSave;
if ((fpSave = fopen("/tmp/geth264.h264", "wb")) == NULL) //h264保存的文件名
return 0;
while(1) {
//------------------------------
if (av_read_frame(pFormatCtx, packet) >= 0) {
if (packet->stream_index == videoindex) {
fwrite(packet->data, 1, packet->size, fpSave); //写数据到文件中
}
av_free_packet(packet);
} else {
break;
}
}
//--------------
//av_frame_free(&pFrameYUV);
av_free(packet);
av_frame_free(&pFrame);
avformat_close_input(&pFormatCtx);
log_d("quit");
return EXIT_SUCCESS;
}
ffmpeg 保存原始视频(H264/H265)到Mp4
先拥有视频数据, 且知道视频的分辨率
AVStream* o_video_stream = avformat_new_stream(oc, NULL);
o_video_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
o_video_stream->codecpar->codec_id = (enum AVCodecID)_video_code_id;
o_video_stream->codecpar->width = _width;
o_video_stream->codecpar->height = _height;
o_video_stream->codecpar->format = AV_PIX_FMT_YUVJ420P;
o_video_stream->codecpar->bit_rate = _width * _height;
o_video_stream->avg_frame_rate.den=1;
o_video_stream->avg_frame_rate.num=25;
o_video_stream->r_frame_rate = o_video_stream->avg_frame_rate;
o_video_stream->start_time = 3600;
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
o_video_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
/*增加extradata可以在windows文件夹中显示mp4预览图片*/
//需要提取出sps/pps(包含nal头0x00 00 00 01) 不写出来
o_video_stream->codecpar->params->extradata = (uint8_t*)av_mallocz(sps_len + pps_len + AV_INPUT_BUFFER_PADDING_SIZE);
memcpy(extradata, sps_data, sps_len);
memcpy(extradata + sps_len, pps_data, pps_len);