【FFMPEG】使用FFMPEG+H264实现RTP传输数据
开发环境:
WINDOWS7 32bit
MINGW
eclipse juno cdt
1、首先你要编译好FFMPEG,
a) 方法一:可以去官网下载源码,用MINGW编译(编译时记得支持H264,当然,事先得下载并编译好libx264,视频技术论坛里有很多介绍)
b) 方法二:更加省心省力的方法是,下载别人已经编译好的资源,如ZeranoeFFmpeg的,下载他的dev版本,包含了头文件,链接库等必须的东西,当然,这东西已经是支持H264的了。
2、以下的就是代码部分了:
a) 先声明必要的变量:
- AVFormatContext *fmtctx;
- AVStream *video_st;
- AVCodec *video_codec;
- const int FPS = 25; /* 25 images/s */
- const char *RDIP = “127.0.0.1”;
- unsigned int RDPORT = 5678;
- const unsigned int OUTWIDTH = 720;
- const unsigned int OUTHEIGHT = 480;
- av_register_all();
- avformat_network_init();
复制代码
b) 初始化AV容器
- fmtctx = avformat_alloc_context();
复制代码
c) 获得输出格式,这里是RTP网络流
- fmtctx->oformat = av_guess_format("rtp", NULL, NULL);
复制代码
d)打开网络流
- snprintf(fmtctx->filename, sizeof(fmtctx->filename),"rtp://%s:%d",RDIP,RDPORT);
- avio_open(&fmtctx->pb,fmtctx->filename, AVIO_FLAG_WRITE)
复制代码
e) 开始添加H264视频流
- video_st = NULL;video_st = add_video_stream(fmtctx, &video_codec, AV_CODEC_ID_H264);
复制代码
其中,add_video_stream函数为:
- add_video_stream(AVFormatContext *oc,AVCodec **codec, enum AVCodecID codec_id)
- {
- AVCodecContext *c;
- AVStream *st;
- /* find the video encoder */
- *codec = avcodec_find_encoder(codec_id);
- st = avformat_new_stream(oc, *codec);
- c = st->codec;
- avcodec_get_context_defaults3(c, *codec);
- c->codec_id = codec_id;
- c->width = OUTWIDTH;
- c->height = OUTHEIGHT;
- c->time_base.den = FPS;
- c->time_base.num = 1;
- c->pix_fmt = PIX_FMT_YUV420P;
- if(oc->oformat->flags & AVFMT_GLOBALHEADER)
- c->flags|= CODEC_FLAG_GLOBAL_HEADER;
- av_opt_set(c->priv_data, "preset", "ultrafast", 0);
- av_opt_set(c->priv_data, "tune","stillimage,fastdecode,zerolatency",0);
- av_opt_set(c->priv_data, "x264opts","crf=26:vbv-maxrate=728:vbv-bufsize=364:keyint=25",0);return st;}
- // OPEN THE CODE
- avcodec_open2(video_st->codec, video_codec, NULL);
- /* Write the stream header, if any. */
- avformat_write_header(fmtctx, NULL);
复制代码
f) 现在,就可以不断的编码数据,并发生数据了
- AVFrame* m_pYUVFrame = avcodec_alloc_frame();
- while(1) //这里设置成无限循环,你可以设置成250,或其他数进行测试,观看结果
- {
- fill_yuv_image(m_pYUVFrame, video_st->codec->frame_number,OUTWIDTH, OUTHEIGHT);
- /* encode the image */
- AVPacket pkt;
- int got_output = 0;
- av_init_packet(&pkt);
- pkt.data = NULL; // packet data will be allocated by the encoder
- pkt.size = 0;
- pkt.pts = AV_NOPTS_VALUE;
- pkt.dts =AV_NOPTS_VALUE;
- m_pYUVFrame->pts = video_st->codec->frame_number;
- ret = avcodec_encode_video2(c, &pkt,frame, &got_output);
- if (ret < 0) {fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
- exit(1);
- }
- /* If size is zero, it means the image was buffered. */
- if (got_output)
- {
- if (c->coded_frame->key_frame)pkt.flags |= AV_PKT_FLAG_KEY;
- pkt.stream_index = st->index;
- if (pkt.pts != AV_NOPTS_VALUE )
- {
- pkt.pts = av_rescale_q(pkt.pts,video_st->codec->time_base, video_st->time_base);
- }
- if(pkt.dts !=AV_NOPTS_VALUE )
- {
- pkt.dts = av_rescale_q(pkt.dts,video_st->codec->time_base, video_st->time_base);
- }
- /* Write the compressed frame to the media file. */
- ret = av_interleaved_write_frame(oc,&pkt);
- }
- else {
- ret = 0;
- }
- }
复制代码
g) Fill_yuv_image函数:
- /* Prepare a dummy image. */
- static void fill_yuv_image(AVPicture *pict,int frame_index,int width, int height)
- {
- int x, y, i;
- i = frame_index;
- /* Y */
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++)
- pict->data[0][y * pict->linesize[0] +x] = x + y + i * 3;
- /* Cb and Cr */
- for (y = 0; y < height / 2; y++)
- {
- for (x = 0; x < width / 2; x++)
- {
- pict->data[1][y * pict->linesize[1] +x] = 128 + y + i * 2;
- pict->data[2][y * pict->linesize[2] +x] = 64 + x + i * 5;
- }
- }
- }
复制代码
h) 打印sdp信息,仅需一次,打印的sdp信息,用在VLC播放器结束网络视频流时用到
- //打印sdp信息
- char sdp[2048];
- av_sdp_create(&fmtctx,1, sdp, sizeof(sdp));
- printf("%s\n",sdp);
- fflush(stdout);
复制代码
i)最后,做一些清理工作
- avcodec_free_frame(&m_pYUVFrame);
- av_write_trailer(fmtctx);
- /* Free the streams. */
- for (unsigned int i = 0; i< fmtctx->nb_streams;i++)
- {
- av_freep(&fmtctx->streams->codec);
- av_freep(&fmtctx->streams);
- }
- if(!(fmtctx->oformat->flags& AVFMT_NOFILE))
- /* Close the output file. */
- avio_close(fmtctx->pb);
- /*free the stream */
- av_free(fmtctx);
复制代码
3、编译代码,记得添加库文件,运行一次代码,不用死循环,设置不用循环,因为是要让他打印出sdp文件的信息。得到sdp信息,比如我精简成如下:
- c=IN IP4 127.0.0.1
- m=video 56782 RTP/AVP 96
- a=rtpmap:96 H264/90000
- a=framerate:25
- 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传输数据的更多相关文章
- ffmpeg摄像头采集h264编码RTP发送
一. 相关API说明 1. av_register_all 2. avformat_network_init 不管是流媒体发送还是流媒体接收, 需要先执行该函数. 3. avformat_alloc_ ...
- Linux下源码安装ffmpeg及ffmpeg的简单使用说明
一.编译安装 ffmpeg在安装时依赖的包和版本都很让人头疼,不同编译环境也各不相同.公司之前封装了一个又各种出错. 其实办法很简单,就是到官网一步一步按着做就行了:http://trac.ffmpe ...
- RTP/RTCP(一)-H264关于RTP协议的实现
H264关于RTP协议的实现2010-07-22 13:35完整的C/S架构的基于RTP/RTCP的H.264视频传输方案.此方案中,在服务器端和客户端分别进行了功能模块设计.服务器端:RTP封装模块 ...
- (转载)[FFmpeg]使用ffmpeg从各种视频文件中直接截取视频图片
你曾想过从一个视频文件中提取图片吗?在Linux下就可以,在这个教程中我将使用ffmpeg来从视频中获取图片. 什么是ffmpeg?What is ffmpeg? ffmpeg是一个非常有用的命令行程 ...
- 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 ...
- ffmpeg yuv转h264
ffmpeg -s 176x144 -i container_qcif_176_144.yuv -b:v 7776k -r 25 -vcodec libx264 ds.h264
- 使用ffmpeg实现对h264视频解码 -- (实现了一个易于使用的c++封装库)
H264是当今流行的视频压缩格式:ffmpeg是一个开源库,实现了对h264视频文件的解压缩. 为了降低使用ffmpeg的复杂性,尽量隐藏实现细节,我写了一个封装库.c#也可以很方便的使用此库.解压后 ...
- (转)MP4文件两种格式AVC1和H264的区别及利用FFMPEG demux为h264码流事项
出自:http://www.mworkbox.com/wp/work/314.html 2013-05-04 MP4的视频H264封装有2种格式:h264和avc1,对于这个细节,很容易被忽略.笔者也 ...
- ffmpeg只编译h264
./configure --arch=arm --cross-prefix=arm-none-linux-gnueabi- --extra-ldflags=-static --target-os=li ...
随机推荐
- kafka接口文档和kafka教程
http://kafka.apache.org/090/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html ...
- 【方法】如何实现图片压缩并使用FormData上传
在前端上传图片的操作过程中,当上传服务器时,如果图片过大,可能会影响页面响应速度,这个时候,我们便会对图片进行压缩处理,再上传服务器. 前端对图片进行压缩,一般使用canvas来实现.最后使用canv ...
- elastic search&logstash&kibana 学习历程(四)kibana安装部署和使用
kibana在linux上的部署安装 运行环境是centos7 基于jdk8 下载安装包:wget https://artifacts.elastic.co/downloads/kibana/kiba ...
- Docker容器常用命令汇总
Docker常用命令总结如下: # 查看docker详细信息 docker info # 获取当前节点所有容器 docker ps -a # 管理容器生命周期 docker [start|stop|r ...
- QTableWidget界面有数据之后鼠标点击无响应界面无响应
1.问题:QTableWidget上出现数据之后,界面无响应,鼠标点击没有响应,但是还是可以正常接收数据,连关闭按钮都无法关闭,必须通过杀死进程来关闭程序.有的电脑是无响应,有的电脑又可以. 2.分析 ...
- CSS3-弹性盒布局(Flex Box)
弹性盒布局(Flex Box) 一.概念 弹性盒子是 CSS3 的一种新的布局模式. CSS3 弹性盒( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型 ...
- 修改网卡缓存,解决Linux 网卡丢包严重问题
Linux 网卡丢包严重 生产中有一台linux设备并发比较大,droped包比较多,尤其是在跑游戏数据包的时候,存在严重的丢包现象,怀疑网卡性能不足,在更换设备前想能不有通过软件方法解决,通过网上一 ...
- arcgis python desc.dataType
desc = arcpy.Describe(r"C:\Users\dell\Documents\ArcGIS\ddd.shp") 是ShapeFile desc = arcpy.D ...
- ERROR 1292(22007)
ERROR 1292(22007) Table of Contents 1. 1292 1.1. 22007 1 1292 1.1 22007 错误信息 ERROR 1292 (22007): T ...
- 批量执行(Linux命令,上传/下载文件)
前言: 每个公司的网络环境大都划分 办公网络.线上网络,之所以划分的主要原因是为了保证线上操作安全: 对于外部用户而言也只能访问线上网络的特定开放端口,那么是什么控制了用户访问线上网络的呢? 防火墙过 ...