问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何使用FFMPEG+H264实现RTP传输数据

发布网友 发布时间:2022-04-22 08:12

我来回答

1个回答

热心网友 时间:2022-06-18 10:19

开发环境:
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 mmy 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地址。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
小白开始做牛腩烧番茄前,应该做哪些准备? 普洱茶不管是纯料还是拼配它本身就很有意思 普洱茶的纯料VS拼配,谁更值得珍藏? 为什么我们听到熟悉的歌曲的音乐会感觉在唱歌词呢? abs制动防抱死系统什么时候用到 请问有谁知道离朝阳北路的煊特嘉园(炫特区)最近的浩沙健身俱乐部在哪 ... 朝阳北苑郊野公园有哪些 北苑哪些公园 北京北苑健身有哪些 王者荣耀黄忠开大怎么转圈 成语大什么大什么 求一篇营销员的工作心得和体会 用ARM开发板制作视频监控器,摄像头采集到的数据经... 大()大() 销售心得体会200字范文 Android摄像头获得YUV格式的视频,网上很多都把它... 大【 】大【 】 销售心得体会 linux下有没有比较方便的对yuv文件或者H264文件进... 如何将yuv编码为h264,自己编码或者ffmpeg都可以。 关于销售的工作总结怎么写 为什么jpege支持yuv422,h264不支持 立秋分为三候,一候凉风至;二候白露生;三候寒蝉鸣... yuv420视频输入用h264编码以后保存成文件,可以用... 销售每日感悟 立秋第二天下雨 如何把摄像头采集的rgb图像转成yuv格式,并进行H26... 立秋第二天弟弟送给我的奶茶怎么发朋友圈 为什么H264编码要先把数据转换成YUV图像格式的 立秋的第二天 销售工作是怎样的体验 大( )大( ) ffmpeg解码.h264文件为yuv420。求解答 销售心得怎么写? 用什么成语表示超市里商品很多 大什么大什么 谈谈对销售的理解与体会 怎么使用ffmpeg命令将422sp的yuv数据转成h264文件 大()大()怎么填空 学习营销管理心得有哪些? 销售培训心得怎么写? 1080p数据流 25帧每秒 在一分钟内会生成多少G数据 ... 大行大市能拿来描写城市吗? 做销售是一种怎样的体验 大( ) 大( ) 词语有哪些 如何使用ffmpeg命令将422sp的yuv数据转成h264文件 如大什么大什么成语 上飞机能带什么,不能带什么?? 大x大x的成语大全 上飞机能带什么不能带什么