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原始码流保存到文件中

 
  1. #include "stdafx.h"

  2. #include <stdio.h>

  3. #define __STDC_CONSTANT_MACROS

  4. #ifdef _WIN32

  5. //Windows

  6. extern "C"

  7. {

  8. #include "libavcodec/avcodec.h"

  9. #include "libavformat/avformat.h"

  10. #include "libswscale/swscale.h"

  11. #include "SDL2/SDL.h"

  12. };

  13. #else

  14. //Linux...

  15. #ifdef __cplusplus

  16. extern "C"

  17. {

  18. #endif

  19. #include <libavcodec/avcodec.h>

  20. #include <libavformat/avformat.h>

  21. #include <libswscale/swscale.h>

  22. #include <SDL2/SDL.h>

  23. #ifdef __cplusplus

  24. };

  25. #endif

  26. #endif

  27. int main(int argc, char* argv[])

  28. {

  29. AVFormatContext *pFormatCtx;

  30. int i, videoindex;

  31. AVCodecContext *pCodecCtx;

  32. AVCodec *pCodec;

  33. AVFrame *pFrame, *pFrameYUV;

  34. uint8_t *out_buffer;

  35. AVPacket *packet;

  36. int ret, got_picture;

  37. struct SwsContext *img_convert_ctx;

  38. // 改成你自己的 URL

  39. char filepath[] = "rtsp://192.168.2.xx:8554/1";

  40. av_register_all();

  41. avformat_network_init();

  42. pFormatCtx = avformat_alloc_context();

  43. if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0)打开网络流或文件流

  44. {

  45. printf("Couldn't open input stream.\n");

  46. return -1;

  47. }

  48. if (avformat_find_stream_info(pFormatCtx, NULL)<0)

  49. {

  50. printf("Couldn't find stream information.\n");

  51. return -1;

  52. }

  53. videoindex = -1;

  54. for (i = 0; i<pFormatCtx->nb_streams; i++)

  55. if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)

  56. {

  57. videoindex = i;

  58. break;

  59. }

  60. if (videoindex == -1)

  61. {

  62. printf("Didn't find a video stream.\n");

  63. return -1;

  64. }

  65. pCodecCtx = pFormatCtx->streams[videoindex]->codec;

  66. pCodec = avcodec_find_decoder(pCodecCtx->codec_id);

  67. if (pCodec == NULL)

  68. {

  69. printf("Codec not found.\n");

  70. return -1;

  71. }

  72. if (avcodec_open2(pCodecCtx, pCodec, NULL)<0)

  73. {

  74. printf("Could not open codec.\n");

  75. return -1;

  76. }

  77. pFrame = av_frame_alloc();

  78. pFrameYUV = av_frame_alloc();

  79. out_buffer = (uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));

  80. avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);

  81. //Output Info---输出一些文件(RTSP)信息

  82. printf("---------------- File Information ---------------\n");

  83. av_dump_format(pFormatCtx, 0, filepath, 0);

  84. printf("-------------------------------------------------\n");

  85. img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,

  86. pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

  87. packet = (AVPacket *)av_malloc(sizeof(AVPacket));

  88. FILE *fpSave;

  89. if ((fpSave = fopen("geth264.h264", "ab")) == NULL) //h264保存的文件名

  90. return 0;

  91. for (;;)

  92. {

  93. //------------------------------

  94. if (av_read_frame(pFormatCtx, packet) >= 0)

  95. {

  96. if (packet->stream_index == videoindex)

  97. {

  98. fwrite(packet->data, 1, packet->size, fpSave);//写数据到文件中

  99. }

  100. av_free_packet(packet);

  101. }

  102. }

  103. //--------------

  104. av_frame_free(&pFrameYUV);

  105. av_frame_free(&pFrame);

  106. avcodec_close(pCodecCtx);

  107. avformat_close_input(&pFormatCtx);

  108. return 0;

  109. }

调试结果显示如下:

生成 geth264.h264 文件,可播放。

三、工程下载

下载:利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中 工程

思考,这里就有两个问题未完成,一个就是怎么将 H265的裸流保存到文件,再有怎么保存成其他格式比如MP4。

保存到MP4文件代码如下:

 
  1. #include "stdafx.h"

  2. #ifdef __cplusplus

  3. extern "C" {

  4. #endif

  5. #include <libavcodec/avcodec.h>

  6. #include <libavdevice/avdevice.h>

  7. #include <libavformat/avformat.h>

  8. #include <libavfilter/avfilter.h>

  9. #include <libavutil/avutil.h>

  10. #include <libswscale/swscale.h>

  11. #include <stdlib.h>

  12. #include <stdio.h>

  13. #include <string.h>

  14. #include <math.h>

  15. #ifdef __cplusplus

  16. }

  17. #endif

  18. AVFormatContext *i_fmt_ctx;

  19. AVStream *i_video_stream;

  20. AVFormatContext *o_fmt_ctx;

  21. AVStream *o_video_stream;

  22. int _tmain(int argc, char **argv)

  23. {

  24. avcodec_register_all();

  25. av_register_all();

  26. avformat_network_init();

  27. /* should set to NULL so that avformat_open_input() allocate a new one */

  28. i_fmt_ctx = NULL;

  29. char rtspUrl[] = "rtsp://192.168.2.xx:8554/H264unicast";

  30. const char *filename = "1.mp4";

  31. if (avformat_open_input(&i_fmt_ctx, rtspUrl, NULL, NULL) != 0)

  32. {

  33. fprintf(stderr, "could not open input file\n");

  34. return -1;

  35. }

  36. if (avformat_find_stream_info(i_fmt_ctx, NULL)<0)

  37. {

  38. fprintf(stderr, "could not find stream info\n");

  39. return -1;

  40. }

  41. //av_dump_format(i_fmt_ctx, 0, argv[1], 0);

  42. /* find first video stream */

  43. for (unsigned i = 0; i<i_fmt_ctx->nb_streams; i++)

  44. {

  45. if (i_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)

  46. {

  47. i_video_stream = i_fmt_ctx->streams[i];

  48. break;

  49. }

  50. }

  51. if (i_video_stream == NULL)

  52. {

  53. fprintf(stderr, "didn't find any video stream\n");

  54. return -1;

  55. }

  56. avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, filename);

  57. /*

  58. * since all input files are supposed to be identical (framerate, dimension, color format, ...)

  59. * we can safely set output codec values from first input file

  60. */

  61. o_video_stream = avformat_new_stream(o_fmt_ctx, NULL);

  62. {

  63. AVCodecContext *c;

  64. c = o_video_stream->codec;

  65. c->bit_rate = 400000;

  66. c->codec_id = i_video_stream->codec->codec_id;

  67. c->codec_type = i_video_stream->codec->codec_type;

  68. c->time_base.num = i_video_stream->time_base.num;

  69. c->time_base.den = i_video_stream->time_base.den;

  70. fprintf(stderr, "time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den);

  71. c->width = i_video_stream->codec->width;

  72. c->height = i_video_stream->codec->height;

  73. c->pix_fmt = i_video_stream->codec->pix_fmt;

  74. printf("%d %d %d", c->width, c->height, c->pix_fmt);

  75. c->flags = i_video_stream->codec->flags;

  76. c->flags |= CODEC_FLAG_GLOBAL_HEADER;

  77. c->me_range = i_video_stream->codec->me_range;

  78. c->max_qdiff = i_video_stream->codec->max_qdiff;

  79. c->qmin = i_video_stream->codec->qmin;

  80. c->qmax = i_video_stream->codec->qmax;

  81. c->qcompress = i_video_stream->codec->qcompress;

  82. }

  83. avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE);

  84. avformat_write_header(o_fmt_ctx, NULL);

  85. int last_pts = 0;

  86. int last_dts = 0;

  87. int64_t pts, dts;

  88. while (1)

  89. {

  90. AVPacket i_pkt;

  91. av_init_packet(&i_pkt);

  92. i_pkt.size = 0;

  93. i_pkt.data = NULL;

  94. if (av_read_frame(i_fmt_ctx, &i_pkt) <0)

  95. break;

  96. /*

  97. * pts and dts should increase monotonically

  98. * pts should be >= dts

  99. */

  100. i_pkt.flags |= AV_PKT_FLAG_KEY;

  101. pts = i_pkt.pts;

  102. i_pkt.pts += last_pts;

  103. dts = i_pkt.dts;

  104. i_pkt.dts += last_dts;

  105. i_pkt.stream_index = 0;

  106. //printf("%lld %lld\n", i_pkt.pts, i_pkt.dts);

  107. static int num = 1;

  108. printf("frame %d\n", num++);

  109. av_interleaved_write_frame(o_fmt_ctx, &i_pkt);

  110. //av_free_packet(&i_pkt);

  111. //av_init_packet(&i_pkt);

  112. }

  113. last_dts += dts;

  114. last_pts += pts;

  115. avformat_close_input(&i_fmt_ctx);

  116. av_write_trailer(o_fmt_ctx);

  117. avcodec_close(o_fmt_ctx->streams[0]->codec);

  118. av_freep(&o_fmt_ctx->streams[0]->codec);

  119. av_freep(&o_fmt_ctx->streams[0]);

  120. avio_close(o_fmt_ctx->pb);

  121. av_free(o_fmt_ctx);

  122. return 0;

  123. }

音视频开发(17)---RTSP再学习 -- 利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中相关推荐

  1. RTSP再学习 -- 利用FFmpeg 将 rtsp 获取H264裸流并保存到文件中

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/78214267 既然已经可以通过 RTSP 获取h264 裸流了.那么通过 F ...

  2. 【音视频开发系列】一学就会,快速掌握音视频开发的第一个开源项目FFmpeg

    快速掌握音视频开发的第一个开源项目:FFmpeg 1.为什么要学FFmpeg 2.FFmpeg面向对象思想分析 3.FFmpeg各种组件剖析 视频讲解如下,点击观看: [音视频开发系列]一学就会,快速 ...

  3. 2019.11.12-最新大华摄像机SDK开发,预览实时视频并指定码流格式保存到文件中(可观看)

    大华摄像机SDK开发,预览实时视频并指定码流格式保存到文件中 由于本人最近在开发大华摄像机,特此分享一些经验给到各位开发朋友,本次实例是关于大华摄像机的实时预览视频码流保存到文件中的Demo,本人还开 ...

  4. C/C++音视频开发技术要点与学习路线

    总体来讲,音视频开发是有一定的技术门槛的,我觉得至少需要在这个领域踏踏实实积累个3-5年,才能对音视频相关的开发知识有一个整体.深刻的理解. 从技术上来讲,需要从如下两个大类知识点上去积累: 1. C ...

  5. 音视频开发之旅(34) - 基于FFmpeg实现简单的视频解码器

    目录 FFmpeg解码过程流程图和关键的数据结构 mp4通过FFmpeg解码YUV裸视频数据 遇到的问题 资料 收获 一.FFmpeg解码过程流程图和关键的数据结构 FFmpeg解码涉及的知识点比较多 ...

  6. 音视频开发(8)---nginx+nginx-rtmp-module+ffmpeg搭建流媒体服务器

    nginx+nginx-rtmp-module+ffmpeg搭建流媒体服务器 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/redstarofsle ...

  7. 音视频开发(22)---基于RTMP推送实时AAC+H264流(三)

    基于RTMP推送实时AAC+H264流(三) https://blog.csdn.net/scnu20142005027/article/details/60623670 推送 流程:初始化.连接服务 ...

  8. 音视频开发(21)---基于RTMP推送实时AAC+H264流(二)

    基于RTMP推送实时AAC+H264流(二) https://blog.csdn.net/scnu20142005027/article/details/57428107 编码 图像采用H264编码, ...

  9. 音视频开发(20)---基于RTMP推送实时AAC+H264流(一)

    基于RTMP推送实时AAC+H264流(一) https://blog.csdn.net/scnu20142005027/article/details/56847293 从整体来看,推流端大概是这么 ...

最新文章

  1. 36晋级12第四场:评委弃权 无人晋级
  2. 简述python程序结构_python架构的概念讲解
  3. 【Linux 内核】进程管理 task_struct 结构体 ② ( state 字段 | stack 字段 | pid 字段 | tgid 字段 | pid_links 字段 )
  4. android+高通平台缩写汇聚
  5. TCP/IP 网络编程 (三)
  6. C++ string assign()赋值常用方法
  7. mysql超大sql怎么还原_关于Mysql 大型SQL文件快速恢复方案
  8. 使用 Redis的SETNX命令实现分布式锁
  9. 系统运行缓慢的问题定位步骤
  10. Oracle外键级联删除和级联更新
  11. 九、面向对象三大特征(三)—— 多态
  12. 【系统分析师之路】第五章 复盘软件工程(开发模型开发方法)
  13. 百面深度学习读书笔记-视频处理
  14. 某银行Zabbix开源监控系统建设之路
  15. ubantu 黑屏_普罗菲斯触摸屏黑屏问题维修经验丰富
  16. sqlserver中,sql语句,按照汉字拼音首字母排序
  17. 云服务器可以通过远程打游戏吗,云主机能玩游戏吗_云主机安全防护措施
  18. WIN10+CGAL+VS2017配置
  19. 滤波器设计中的频率归一化问题
  20. 笔记之tomcat映射虚拟路径

热门文章

  1. 【声学基础】概述——振动学
  2. TCP 滑动窗口(已经发出等待对方确认的队列)协议
  3. Linux内核网络协议栈1- socket文件系统注册
  4. Class create, device create, device create file
  5. lcd驱动解析(一)
  6. lie group and computer vision : 李群、李代数在计算机视觉中的应用
  7. QT5开发及实例学习之十二Qt5图像坐标变换
  8. android 刷新标题栏,Android 自定义标题栏的实例详解
  9. oracle权限不足的报错,Oracle Scott创建视图权限不足解决办法
  10. win10更新后无法进入linux,双系统win10更新后无法进入linux