开发环境:
WINDOWS7 32bit
MINGW
eclipse juno cdt
1、首先你要编译好FFMPEG,
a) 方法一:可以去官网下载源码,用MINGW编译(编译时记得支持H264,当然,事先得下载并编译好libx264,视频技术论坛里有很多介绍)
b) 方法二:更加省心省力的方法是,下载别人已经编译好的资源,如ZeranoeFFmpeg的,下载他的dev版本,包含了头文件,链接库等必须的东西,当然,这东西已经是支持H264的了。
2、以下的就是代码部分了:
a) 先声明必要的变量:

  1. AVFormatContext *fmtctx;
  2. AVStream *video_st;
  3. AVCodec *video_codec;
  4. const int FPS = 25; /* 25 images/s */
  5. const char *RDIP = “127.0.0.1”;
  6. unsigned int  RDPORT = 5678;
  7. const unsigned int OUTWIDTH = 720;
  8. const unsigned int OUTHEIGHT = 480;
  9. av_register_all();
  10. avformat_network_init();

复制代码

b) 初始化AV容器

  1. fmtctx = avformat_alloc_context();

复制代码

c) 获得输出格式,这里是RTP网络流

  1. fmtctx->oformat = av_guess_format("rtp", NULL, NULL);

复制代码

d)打开网络流

  1. snprintf(fmtctx->filename, sizeof(fmtctx->filename),"rtp://%s:%d",RDIP,RDPORT);
  2. avio_open(&fmtctx->pb,fmtctx->filename, AVIO_FLAG_WRITE)

复制代码

e) 开始添加H264视频流

  1. video_st = NULL;video_st = add_video_stream(fmtctx, &video_codec, AV_CODEC_ID_H264);

复制代码

其中,add_video_stream函数为:

  1. add_video_stream(AVFormatContext *oc,AVCodec **codec, enum AVCodecID codec_id)
  2. {
  3. AVCodecContext *c;
  4. AVStream *st;
  5. /* find the video encoder */
  6. *codec = avcodec_find_encoder(codec_id);
  7. st = avformat_new_stream(oc, *codec);
  8. c = st->codec;
  9. avcodec_get_context_defaults3(c, *codec);
  10. c->codec_id = codec_id;
  11. c->width = OUTWIDTH;
  12. c->height = OUTHEIGHT;
  13. c->time_base.den = FPS;
  14. c->time_base.num = 1;
  15. c->pix_fmt = PIX_FMT_YUV420P;
  16. if(oc->oformat->flags & AVFMT_GLOBALHEADER)
  17. c->flags|= CODEC_FLAG_GLOBAL_HEADER;
  18. av_opt_set(c->priv_data, "preset", "ultrafast", 0);
  19. av_opt_set(c->priv_data, "tune","stillimage,fastdecode,zerolatency",0);
  20. av_opt_set(c->priv_data, "x264opts","crf=26:vbv-maxrate=728:vbv-bufsize=364:keyint=25",0);return st;}
  21. // OPEN THE CODE
  22. avcodec_open2(video_st->codec, video_codec, NULL);
  23. /* Write the stream header, if any. */
  24. avformat_write_header(fmtctx, NULL);

复制代码

f) 现在,就可以不断的编码数据,并发生数据了

  1. AVFrame* m_pYUVFrame = avcodec_alloc_frame();
  2. while(1) //这里设置成无限循环,你可以设置成250,或其他数进行测试,观看结果
  3. {
  4. fill_yuv_image(m_pYUVFrame, video_st->codec->frame_number,OUTWIDTH, OUTHEIGHT);
  5. /* encode the image */
  6. AVPacket pkt;
  7. int got_output = 0;
  8. av_init_packet(&pkt);
  9. pkt.data = NULL;    // packet data will be allocated by the encoder
  10. pkt.size = 0;
  11. pkt.pts = AV_NOPTS_VALUE;
  12. pkt.dts =AV_NOPTS_VALUE;
  13. m_pYUVFrame->pts = video_st->codec->frame_number;
  14. ret = avcodec_encode_video2(c, &pkt,frame, &got_output);
  15. if (ret < 0) {fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
  16. exit(1);
  17. }
  18. /* If size is zero, it means the image was buffered. */
  19. if (got_output)
  20. {
  21. if (c->coded_frame->key_frame)pkt.flags |= AV_PKT_FLAG_KEY;
  22. pkt.stream_index = st->index;
  23. if (pkt.pts != AV_NOPTS_VALUE )
  24. {
  25. pkt.pts = av_rescale_q(pkt.pts,video_st->codec->time_base, video_st->time_base);
  26. }
  27. if(pkt.dts !=AV_NOPTS_VALUE )
  28. {
  29. pkt.dts = av_rescale_q(pkt.dts,video_st->codec->time_base, video_st->time_base);
  30. }
  31. /* Write the compressed frame to the media file. */
  32. ret = av_interleaved_write_frame(oc,&pkt);
  33. }
  34. else {
  35. ret = 0;
  36. }
  37. }

复制代码

g) Fill_yuv_image函数:

  1. /* Prepare a dummy image. */
  2. static void fill_yuv_image(AVPicture *pict,int frame_index,int width, int height)
  3. {
  4. int x, y, i;
  5. i = frame_index;
  6. /* Y */
  7. for (y = 0; y < height; y++)
  8. for (x = 0; x < width; x++)
  9. pict->data[0][y * pict->linesize[0] +x] = x + y + i * 3;
  10. /* Cb and Cr */
  11. for (y = 0; y < height / 2; y++)
  12. {
  13. for (x = 0; x < width / 2; x++)
  14. {
  15. pict->data[1][y * pict->linesize[1] +x] = 128 + y + i * 2;
  16. pict->data[2][y * pict->linesize[2] +x] = 64 + x + i * 5;
  17. }
  18. }
  19. }

复制代码

h) 打印sdp信息,仅需一次,打印的sdp信息,用在VLC播放器结束网络视频流时用到

  1. //打印sdp信息
  2. char sdp[2048];
  3. av_sdp_create(&fmtctx,1, sdp, sizeof(sdp));
  4. printf("%s\n",sdp);
  5. fflush(stdout);

复制代码

i)最后,做一些清理工作

  1. avcodec_free_frame(&m_pYUVFrame);
  2. av_write_trailer(fmtctx);
  3. /* Free the streams. */
  4. for (unsigned int i = 0; i< fmtctx->nb_streams;i++)
  5. {
  6. av_freep(&fmtctx->streams->codec);
  7. av_freep(&fmtctx->streams);
  8. }
  9. if(!(fmtctx->oformat->flags& AVFMT_NOFILE))
  10. /* Close the output file. */
  11. avio_close(fmtctx->pb);
  12. /*free the stream */
  13. av_free(fmtctx);

复制代码

3、编译代码,记得添加库文件,运行一次代码,不用死循环,设置不用循环,因为是要让他打印出sdp文件的信息。得到sdp信息,比如我精简成如下:

  1. c=IN IP4 127.0.0.1
  2. m=video 56782 RTP/AVP 96
  3. a=rtpmap:96 H264/90000
  4. a=framerate:25
  5. a=fmtp:96 packetization-mode=1

复制代码

把这些信息保存到一个文本文件,并改名为sdp后缀,如mySDP.sdp。
4、从官网下载VLC播放器,重新运行上述的代码,这一次要循环,具体循环多久,你自己决定,这一次是正式测试了。代码跑起来后,把刚刚的sdp文件用VLC打开,直接把sdp文件拖到VLC播放器中就行了。等待缓冲,就可以看到效果了。
5、代码中剩掉了出错检查部分,请自行添加。
6、关于IP地址,这里是127.0.0.1,是供本机测试,可以改成制定的接受数据的电脑IP地址,或者广播地址IP地址。
7、经本人测试,局域网内不同电脑间测试,刚开始播放良好,进过一段时间后,开始出现吊针现象。经多次修改av_opt_set里面的参数(是修改x264的参数配置)也无法达到较理想的想过。

【FFMPEG】使用FFMPEG+H264实现RTP传输数据的更多相关文章

  1. ffmpeg摄像头采集h264编码RTP发送

    一. 相关API说明 1. av_register_all 2. avformat_network_init 不管是流媒体发送还是流媒体接收, 需要先执行该函数. 3. avformat_alloc_ ...

  2. Linux下源码安装ffmpeg及ffmpeg的简单使用说明

    一.编译安装 ffmpeg在安装时依赖的包和版本都很让人头疼,不同编译环境也各不相同.公司之前封装了一个又各种出错. 其实办法很简单,就是到官网一步一步按着做就行了:http://trac.ffmpe ...

  3. RTP/RTCP(一)-H264关于RTP协议的实现

    H264关于RTP协议的实现2010-07-22 13:35完整的C/S架构的基于RTP/RTCP的H.264视频传输方案.此方案中,在服务器端和客户端分别进行了功能模块设计.服务器端:RTP封装模块 ...

  4. (转载)[FFmpeg]使用ffmpeg从各种视频文件中直接截取视频图片

    你曾想过从一个视频文件中提取图片吗?在Linux下就可以,在这个教程中我将使用ffmpeg来从视频中获取图片. 什么是ffmpeg?What is ffmpeg? ffmpeg是一个非常有用的命令行程 ...

  5. H264的RTP负载打包的数据包格式,分组,分片

    H264的RTP负载打包的数据包格式,分组,分片 1.    RTP数据包格式 RTP报文头格式(见RFC3550 Page12): 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 ...

  6. ffmpeg yuv转h264

    ffmpeg -s 176x144 -i  container_qcif_176_144.yuv -b:v 7776k -r 25 -vcodec libx264 ds.h264

  7. 使用ffmpeg实现对h264视频解码 -- (实现了一个易于使用的c++封装库)

    H264是当今流行的视频压缩格式:ffmpeg是一个开源库,实现了对h264视频文件的解压缩. 为了降低使用ffmpeg的复杂性,尽量隐藏实现细节,我写了一个封装库.c#也可以很方便的使用此库.解压后 ...

  8. (转)MP4文件两种格式AVC1和H264的区别及利用FFMPEG demux为h264码流事项

    出自:http://www.mworkbox.com/wp/work/314.html 2013-05-04 MP4的视频H264封装有2种格式:h264和avc1,对于这个细节,很容易被忽略.笔者也 ...

  9. ffmpeg只编译h264

    ./configure --arch=arm --cross-prefix=arm-none-linux-gnueabi- --extra-ldflags=-static --target-os=li ...

随机推荐

  1. 2018多校第九场 HDU 6416 (DP+前缀和优化)

    转自:https://blog.csdn.net/CatDsy/article/details/81876341 #include <bits/stdc++.h> using namesp ...

  2. HDU 6059 - Kanade's trio | 2017 Multi-University Training Contest 3

    思路来自题解(看着题解和标程瞎吉尔比划了半天) /* HDU 6059 - Kanade's trio [ 字典树 ]  |  2017 Multi-University Training Conte ...

  3. Visual Studio 查看宏展开

    使用Visual Studio 开发c++项目,中遇到项目中宏定义套宏定义,难以阅读源代码的时候. 可在 项目-->右键-->配置属性-->c/c++ -->预处理器 --&g ...

  4. 外观模式(Facade)---结构型模式

    1 基础知识 定义:提供了一个统一的接口(外观类),用来访问子系统中的一群接口.特征:定义了一个高层接口让子系统更容易使用,减少了外部与子系统内多个模块的耦合. 本质:封装交互,简化调用. 优点:简化 ...

  5. printf:函数参数计算从右向左,从左向右?

    造冰箱的大熊猫@cnblogs 2019/8/3 1.问题 某天写了如下代码: unsigned char ReadByteFromFile ( FILE * fp ) { unsigned char ...

  6. 洛谷 P4933 大师

    题面 (实名推荐:本题的出题人小哥哥打球暴帅哦!(APIO/CTSC/WC的时候一起打过球w,而且大学在我隔壁喔) ) 没仔细看数据范围的时候真是摸不着头脑...还以为要 O(N^2) dp 爆锤.. ...

  7. WM_PAINT(父子窗口间)

    WM_PAINT(父子窗口间) 窗口句柄(HWND)都是由操作系统内核管理的,系统内部有一个z-order序列,记录着当前从屏幕底部(假象的从屏幕到眼睛的方向),到屏幕最高层的一个窗口句柄的排序,这个 ...

  8. 2017 ZSTU寒假排位赛 #3

    题目链接:https://vjudge.net/contest/147974#overview. A题,费用流,不会..跳过了. B题,给一个图,问至少添加几条边能成为强连通图.显然缩点,要使得成为一 ...

  9. Nginx访问非常慢

    由于域名绑定服务器IP,而服务器上部署了多个应用,想都通过域名访问,故弄了个Nginx转发. 加了Nginx以后,服务访问明显卡顿. 查看配置: location / { proxy_pass htt ...

  10. 使用 PM2 将 Node.js 的集群变得更加容易

    介绍 众所周知,Node.js运行在Chrome的JavaScript运行时平台上,我们把该平台优雅地称之为V8引擎.不论是V8引擎,还是之后的Node.js,都是以单线程的方式运行的,因此,在多核心 ...