RTSP再学习 -- 利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中
如需轉載請注明出處:https://blog.csdn.net/qq_29350001/article/details/78214267
既然已經可以通過 RTSP 獲取h264 裸流了。那么通過 FFmpeg 將其保存到文件中怎么做呢?
一、首先RTSP獲取 h264 裸流
我們上面兩篇文章主要講的是通過?rtsp://Your ip:554/stream_chn0.h265 播放H.265視頻流。
PS:我剛試了一下,我的 FFmpeg 程序暫時不支持 h265 ... ??之前編譯的時候,只提供了 x264沒有x265
如果感興趣參看下面兩篇文章添加。
參看:使用VS2015添加對ffmpeg添加h265 支持。
參看:ffmpeg 編碼H265和H264對比
再結合之前講的,FFmepg 再學習系列,應該是沒問題的。不過好久沒有弄了,早忘了了。
?
那現在沒有可以播放的 H.264 視頻流了啊,怎么辦?
有辦法之前講過一篇文章,參看:LIVE555再學習 -- VLC搭建RTSP服務器(轉)?用VLC搭建一個不就完了。
?
當然還可以直接用 live555,參看:LIVE555再學習 -- live555實現RTSP直播服務器? (推薦)
二、FFmpeg 將H.264 裸流保存到文件
這個也好說,之前有講到,參看:FFmpeg再學習 -- SDL 環境搭建和視頻顯示
將其改改就可以了。
具體代碼如下:
參看:利用ffmpeg將RTSP傳輸的h264原始碼流保存到文件中
?
#include "stdafx.h"#include <stdio.h> #define __STDC_CONSTANT_MACROS #ifdef _WIN32 //Windows extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "SDL2/SDL.h" }; #else //Linux... #ifdef __cplusplus extern "C" { #endif #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswscale/swscale.h> #include <SDL2/SDL.h> #ifdef __cplusplus }; #endif #endif int main(int argc, char* argv[]) {AVFormatContext *pFormatCtx;int i, videoindex;AVCodecContext *pCodecCtx;AVCodec *pCodec;AVFrame *pFrame, *pFrameYUV;uint8_t *out_buffer;AVPacket *packet;int ret, got_picture;struct SwsContext *img_convert_ctx;// 改成你自己的 URLchar filepath[] = "rtsp://192.168.2.xx:8554/1"; av_register_all();avformat_network_init();pFormatCtx = avformat_alloc_context();if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 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;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 -1;}pCodecCtx = pFormatCtx->streams[videoindex]->codec;pCodec = avcodec_find_decoder(pCodecCtx->codec_id);if (pCodec == NULL){printf("Codec not found.\n");return -1;}if (avcodec_open2(pCodecCtx, pCodec, NULL)<0){printf("Could not open codec.\n");return -1;}pFrame = av_frame_alloc();pFrameYUV = av_frame_alloc();out_buffer = (uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//Output Info---輸出一些文件(RTSP)信息 printf("---------------- File Information ---------------\n");av_dump_format(pFormatCtx, 0, filepath, 0);printf("-------------------------------------------------\n");img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);packet = (AVPacket *)av_malloc(sizeof(AVPacket));FILE *fpSave;if ((fpSave = fopen("geth264.h264", "ab")) == NULL) //h264保存的文件名 return 0;for (;;){//------------------------------ if (av_read_frame(pFormatCtx, packet) >= 0){if (packet->stream_index == videoindex){fwrite(packet->data, 1, packet->size, fpSave);//寫數據到文件中 }av_free_packet(packet);}}//-------------- av_frame_free(&pFrameYUV);av_frame_free(&pFrame);avcodec_close(pCodecCtx);avformat_close_input(&pFormatCtx);return 0; }?
?
調試結果顯示如下:
?
生成 geth264.h264 文件,可播放。
三、工程下載
下載:利用FFmpeg 將 rtsp 獲取H264裸流并保存到文件中 工程
思考,這里就有兩個問題未完成,一個就是怎么將 H265的裸流保存到文件,再有怎么保存成其他格式比如MP4。
保存到MP4文件代碼如下:
?
#include "stdafx.h" #ifdef __cplusplus extern "C" { #endif #include <libavcodec/avcodec.h> #include <libavdevice/avdevice.h> #include <libavformat/avformat.h> #include <libavfilter/avfilter.h> #include <libavutil/avutil.h> #include <libswscale/swscale.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #ifdef __cplusplus } #endifAVFormatContext *i_fmt_ctx; AVStream *i_video_stream; AVFormatContext *o_fmt_ctx; AVStream *o_video_stream;int _tmain(int argc, char **argv) {avcodec_register_all();av_register_all();avformat_network_init();/* should set to NULL so that avformat_open_input() allocate a new one */i_fmt_ctx = NULL;char rtspUrl[] = "rtsp://192.168.2.xx:8554/H264unicast";const char *filename = "1.mp4";if (avformat_open_input(&i_fmt_ctx, rtspUrl, NULL, NULL) != 0){fprintf(stderr, "could not open input file\n");return -1;}if (avformat_find_stream_info(i_fmt_ctx, NULL)<0){fprintf(stderr, "could not find stream info\n");return -1;}//av_dump_format(i_fmt_ctx, 0, argv[1], 0);/* find first video stream */for (unsigned i = 0; i<i_fmt_ctx->nb_streams; i++){if (i_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){i_video_stream = i_fmt_ctx->streams[i];break;}}if (i_video_stream == NULL){fprintf(stderr, "didn't find any video stream\n");return -1;}avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, filename);/** since all input files are supposed to be identical (framerate, dimension, color format, ...)* we can safely set output codec values from first input file*/o_video_stream = avformat_new_stream(o_fmt_ctx, NULL);{AVCodecContext *c;c = o_video_stream->codec;c->bit_rate = 400000;c->codec_id = i_video_stream->codec->codec_id;c->codec_type = i_video_stream->codec->codec_type;c->time_base.num = i_video_stream->time_base.num;c->time_base.den = i_video_stream->time_base.den;fprintf(stderr, "time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den);c->width = i_video_stream->codec->width;c->height = i_video_stream->codec->height;c->pix_fmt = i_video_stream->codec->pix_fmt;printf("%d %d %d", c->width, c->height, c->pix_fmt);c->flags = i_video_stream->codec->flags;c->flags |= CODEC_FLAG_GLOBAL_HEADER;c->me_range = i_video_stream->codec->me_range;c->max_qdiff = i_video_stream->codec->max_qdiff;c->qmin = i_video_stream->codec->qmin;c->qmax = i_video_stream->codec->qmax;c->qcompress = i_video_stream->codec->qcompress;}avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE);avformat_write_header(o_fmt_ctx, NULL);int last_pts = 0;int last_dts = 0;int64_t pts, dts;while (1){AVPacket i_pkt;av_init_packet(&i_pkt);i_pkt.size = 0;i_pkt.data = NULL;if (av_read_frame(i_fmt_ctx, &i_pkt) <0)break;/** pts and dts should increase monotonically* pts should be >= dts*/i_pkt.flags |= AV_PKT_FLAG_KEY;pts = i_pkt.pts;i_pkt.pts += last_pts;dts = i_pkt.dts;i_pkt.dts += last_dts;i_pkt.stream_index = 0;//printf("%lld %lld\n", i_pkt.pts, i_pkt.dts);static int num = 1;printf("frame %d\n", num++);av_interleaved_write_frame(o_fmt_ctx, &i_pkt);//av_free_packet(&i_pkt);//av_init_packet(&i_pkt);}last_dts += dts;last_pts += pts;avformat_close_input(&i_fmt_ctx);av_write_trailer(o_fmt_ctx);avcodec_close(o_fmt_ctx->streams[0]->codec);av_freep(&o_fmt_ctx->streams[0]->codec);av_freep(&o_fmt_ctx->streams[0]);avio_close(o_fmt_ctx->pb);av_free(o_fmt_ctx);return 0; }?
如需轉載請注明出處:https://blog.csdn.net/qq_29350001/article/details/78214267
?
?
?
總結
以上是生活随笔為你收集整理的RTSP再学习 -- 利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 批量上传文件及进度显示
- 下一篇: 2、运行WordCount程序