打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
ffmpeg学习(二) 通过rtsp获取H264裸流并保存到mp4文件
  • 本篇将使用上节http://www.cnblogs.com/wenjingu/p/3977015.html中编译好的库文件通过rtsp获取网络上的h464裸流并保存到mp4文件中。

    1、VS2010建立VC++  win32控制台项目

    2、在工程目录下建立lib目录和include目录,将已编译好的lib拷打lib下,include拷到include下,dll拷到Debug目录下

    3、工程属性--配置属性--VC++目录--包含目录,添加ffmpeg头文件目录及其他第三方头文件目录

                                                 链接器--常规--附加库目录,添加lib目录

                                                 链接器--输入--附加依赖项,添加各个lib名

    4、设计和实现:

    4.1 设计思路:

           组件和网络初始化——>打开网络流——>获取网络流信息——>根据网络流信息初始化输出流信息——>创建并打开mp4文件——>写mp4文件头

                        ——>循环读取输入流并写入mp4文件——>写文件尾——>关闭流,关闭文件

    4.2 关键数据结构:

           AVFormatContext,AVStream,AVCodecContext,AVPacket,AVFrame等,它们的关系解释如下:

           一个AVFormatContext包含多个AVStream,每个码流包含了AVCodec和AVCodecContext,AVPicture是AVFrame的一个子集,

    他们都是数据流在编解过程中用来保存数据缓存的对像,从数据流读出的数据首先是保存在AVPacket里,也可以理解为一个AVPacket最多只包含一个AVFrame,

    而一个AVFrame可能包含好几个AVPacket,AVPacket是种数据流分包的概念。

    4.3 关键函数:

    int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options); //打开网络流或文件流

    int avformat_write_header(AVFormatContext *s, AVDictionary **options);//根据文件名的后缀写相应格式的文件头

    int av_read_frame(AVFormatContext *s, AVPacket *pkt);//从输入流中读取一个分包

    int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);//往输出流中写一个分包

    int av_write_trailer(AVFormatContext *s);//写输出流(文件)的文件尾

    4.4 代码:

    001.#include "stdafx.h"
    002. 
    003.#ifdef __cplusplus
    004.extern "C" {
    005.#endif
    006. 
    007.#include <libavcodec/avcodec.h>
    008.#include <libavdevice/avdevice.h>
    009.#include <libavformat/avformat.h>
    010.#include <libavfilter/avfilter.h>
    011.#include <libavutil/avutil.h>
    012.#include <libswscale/swscale.h>
    013. 
    014.#include <stdlib.h>
    015.#include <stdio.h>
    016.#include <string.h>
    017.#include <math.h>
    018. 
    019.#ifdef __cplusplus
    020.}
    021.#endif
    022. 
    023.AVFormatContext *i_fmt_ctx;
    024.AVStream *i_video_stream;
    025. 
    026.AVFormatContext *o_fmt_ctx;
    027.AVStream *o_video_stream;
    028. 
    029.int _tmain(int argc, char **argv)
    030.{
    031.avcodec_register_all();
    032.av_register_all();
    033.avformat_network_init();
    034. 
    035./* should set to NULL so that avformat_open_input() allocate a new one */
    036.i_fmt_ctx = NULL;
    037.char rtspUrl[] = "rtsp://admin:12345@192.168.10.76:554";
    038.const char *filename = "1.mp4";
    039.if (avformat_open_input(&i_fmt_ctx, rtspUrl, NULL, NULL)!=0)
    040.{
    041.fprintf(stderr, "could not open input file\n");
    042.return -1;
    043.}
    044. 
    045.if (avformat_find_stream_info(i_fmt_ctx, NULL)<0)
    046.{
    047.fprintf(stderr, "could not find stream info\n");
    048.return -1;
    049.}
    050. 
    051.//av_dump_format(i_fmt_ctx, 0, argv[1], 0);
    052. 
    053./* find first video stream */
    054.for (unsigned i=0; i<i_fmt_ctx->nb_streams; i++)
    055.{
    056.if (i_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
    057.{
    058.i_video_stream = i_fmt_ctx->streams[i];
    059.break;
    060.}
    061.}
    062.if (i_video_stream == NULL)
    063.{
    064.fprintf(stderr, "didn't find any video stream\n");
    065.return -1;
    066.}
    067. 
    068.avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, filename);
    069. 
    070./*
    071.* since all input files are supposed to be identical (framerate, dimension, color format, ...)
    072.* we can safely set output codec values from first input file
    073.*/
    074.o_video_stream = avformat_new_stream(o_fmt_ctx, NULL);
    075.{
    076.AVCodecContext *c;
    077.c = o_video_stream->codec;
    078.c->bit_rate = 400000;
    079.c->codec_id = i_video_stream->codec->codec_id;
    080.c->codec_type = i_video_stream->codec->codec_type;
    081.c->time_base.num = i_video_stream->time_base.num;
    082.c->time_base.den = i_video_stream->time_base.den;
    083.fprintf(stderr, "time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den);
    084.c->width = i_video_stream->codec->width;
    085.c->height = i_video_stream->codec->height;
    086.c->pix_fmt = i_video_stream->codec->pix_fmt;
    087.printf("%d %d %d", c->width, c->height, c->pix_fmt);
    088.c->flags = i_video_stream->codec->flags;
    089.c->flags |= CODEC_FLAG_GLOBAL_HEADER;
    090.c->me_range = i_video_stream->codec->me_range;
    091.c->max_qdiff = i_video_stream->codec->max_qdiff;
    092. 
    093.c->qmin = i_video_stream->codec->qmin;
    094.c->qmax = i_video_stream->codec->qmax;
    095. 
    096.c->qcompress = i_video_stream->codec->qcompress;
    097.}
    098. 
    099.avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE);
    100. 
    101.avformat_write_header(o_fmt_ctx, NULL);
    102. 
    103.int last_pts = 0;
    104.int last_dts = 0;
    105. 
    106.int64_t pts, dts;
    107.while (1)
    108.{
    109.AVPacket i_pkt;
    110.av_init_packet(&i_pkt);
    111.i_pkt.size = 0;
    112.i_pkt.data = NULL;
    113.if (av_read_frame(i_fmt_ctx, &i_pkt) <0 )
    114.break;
    115./*
    116.* pts and dts should increase monotonically
    117.* pts should be >= dts
    118.*/
    119.i_pkt.flags |= AV_PKT_FLAG_KEY;
    120.pts = i_pkt.pts;
    121.i_pkt.pts += last_pts;
    122.dts = i_pkt.dts;
    123.i_pkt.dts += last_dts;
    124.i_pkt.stream_index = 0;
    125. 
    126.//printf("%lld %lld\n", i_pkt.pts, i_pkt.dts);
    127.static int num = 1;
    128.printf("frame %d\n", num++);
    129.av_interleaved_write_frame(o_fmt_ctx, &i_pkt);
    130.//av_free_packet(&i_pkt);
    131.//av_init_packet(&i_pkt);
    132.}
    133.last_dts += dts;
    134.last_pts += pts;
    135. 
    136.avformat_close_input(&i_fmt_ctx);
    137. 
    138.av_write_trailer(o_fmt_ctx);
    139. 
    140.avcodec_close(o_fmt_ctx->streams[0]->codec);
    141.av_freep(&o_fmt_ctx->streams[0]->codec);
    142.av_freep(&o_fmt_ctx->streams[0]);
    143. 
    144.avio_close(o_fmt_ctx->pb);
    145.av_free(o_fmt_ctx);
    146. 
    147.return 0;
    148.}

    5、测试

    如上图为存储过程中程序的打印结果。生成的mp4文件可以用任意支持该格式的播放器播放。


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
FFmpeg 学习(七):FFmpeg 学习整理总结
FFMpeg 中比较重要的函数以及数据结构
FFMPEG解码流程1(转)
FFMPEG
基于AM57x+Artix-7开发板——GStreamer视频开发案例(3)
FFMpeg框架代码阅读
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服