自己动手写RTP服务器——传输所有格式的视频

上一篇文章我们介绍了如何用一个简单的UDP socket搭建一个RTP服务器。我把这份80行的代码呈现到客户面前的时候,就有人不满意了。

还有人在参考的时候会问:“楼主你的TS格式的文件是哪里来的?应该去哪里下载?”
“这也太简单了吧,不就是用UDP把TS文件发过去么?就这么几十行代码也算个大作业?”
“平时看的视频格式哪有TS的呀,不是avi就是mp4、rmvb什么的,根本不实用啊!”

 

首先回答问题1:

如果你用过强大的ffmpeg,就可以用一行简单的命令

[plain] view plaincopy

 

 

  1. ffmpeg -i INPUTFILE.XXX OUTPUTFILE.ts  

把几乎任何格式的文件转换成TS文件。

 

再回答问题2:

如果能实现同样的功能,我确实更倾向使用简单的方法。说我偷懒也好,没有技术含量也好。我觉得,很多时候最简单直接的方法最有效。

 

这篇帖子主要的内容就是来回答问题3:如何用RTP协议传输各种格式的视频。

预备知识

我们是否可以调用别人的分流器或者解码器?

不要告诉我不可以。如果真的不可以,那么我们岂不是要把各种格式的视频解码器实现一遍?也就是说我们要自己重新写一个ffmpeg工程!

当然是可以的,关键是看如何使用。有几种选择:借用别人的源码然后集成到我们的工程;或是调用别人的接口来使用已经编译好的库;还是直接使用别人的程序?这就是复用粒度大小的选择。很少有人会用第一种方法,因为别人的源码不见得拿来就能编译通过并且成功使用。多数人会选择第二种方法,看起来顺理成章,也是可以适应一定需求变化的。(这是做软件最需要考虑的地方)

不过鉴于这个项目是一个课堂的作业,加上我比较喜欢偷懒,就选择了最简单的第三种方法。

参考代码

第一步

首先需要对上一篇中的代码做一些简单的修改:

把原先的

[cpp] view plaincopy

 

 

  1. int main(){  

改为

[cpp] view plaincopy

 

 

  1. int main(int argc, char **argv){  

再把原先的

[cpp] view plaincopy

 

 

  1. FILE *ts_file = fopen("/home/baby/Videos/480p.ts", "r+");  

改为

[cpp] view plaincopy

 

 

  1. if (argc != 2){  
  2.     puts("Usage: ./rtp_server INPUTFILE");  
  3.     return 0;  
  4. }  
  5. FILE *ts_file = fopen(argv[1], "r+");  

可以看出我们这次不读取固定文件,而是根据用户自己的输入读取文件,这样就灵活了许多。

第二步

源代码编译通过后,只需写一个简单的shell脚本mk_rtp_server.sh。

[plain] view plaincopy

 

 

  1. #!/bin/sh  
  2. mkfifo fifo.ts  
  3. ffmpeg -i $1 -y fifo.ts &  
  4. ./rtp_server fifo.ts  

只有四行有木有,很简单有木有!

其实就是利用了ffmpeg的分流与解码,然后利用命名管道把ffmpeg的输出到处到一个管道中,然后再用我们前面写好的rtp_server去读这个文件。

(切记ffmpeg参数里面的-y是必不可少的)

OK,大功告成。chmod之后执行这个脚本文件./mk_rtp_server.sh INPUTFILE.XXX,拿个播放器测试一下。”嗯~果然不错~“

只要你的ffmpeg装的够完整,那么几乎所有的格式都可以变成rtp流。包括avi之类的非实时流文件格式。

 

大功告成!并且远远超过了当初的需求,但是客户的需求善变如人心,下一步又是什么呢?

时间: 2024-11-01 21:20:28

自己动手写RTP服务器——传输所有格式的视频的相关文章

自己动手写RTP服务器——关于RTP协议

本文会带领着你一步步动手实现一个简单的RTP传输服务器,旨在了解RTP流媒体传输协议以及一些关于多媒体编解码的知识.   关于RTP协议的必备知识 要动手实现一个协议,当然首先需要阅读该协议的文档.RTP协议的文档,有rfc1889.rfc1890.rfc3550,其中rfc3550是现在的版本,另外两个是过期版.这个协议可以在ietf的官网找到:http://tools.ietf.org/html/rfc3550 RTP packet RTP是基于UDP协议的,RTP服务器会通过UDP协议,通

自己动手写一个java版简单云相册_java

动手写一个java版简单云相册,实现的功能是: 用户可以一次上传一个至多个文件. 用户可以下载其他人上传的图片. 用户可以查看其他所有人的图片. 用户只能删除通过自己IP上传的图片. 用到的技术: 文件上传下载.设计模式.Dom4j.xPath等. 先看下2个页面: 源代码: web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns=

动手写个小组件(组件入门)(1)

动手写个小组件(组件入门) 这篇文章主要是为想将自己的ASP水平提高的人写的! 把ASP代码变成组件,开发者不仅是加快了ASP的速度,而且也能保护自己的代码.这篇文章写出来,也是为了给想开发组件网友上一堂入门课! 下面,我们会来编写一个非常简单的组件,重点是知道怎样开发DLL组件,而不是其复杂的代码!这些都要靠你们自己以后的努力了. 服务器端组件 首先,服务器端的组件要有别于客户端的组件.客户端的组件是通过网络传输,依靠HTML来起作用.而且只能在IE上有用.但是服务器端的组件是运行在服务器端,

VC 6 RTP流媒体传输协议编程实例(

资源下载:http://download.111cn.net/source/444512 实时流协议RTSP(RealTimeStreamingProtocol)是由RealNetworks和 Netscape共同提出的,该协议定义了一对多应用程序如何有效地通过IP网络传送多媒体数据.RTSP在体系结构上位于RTP(实时传输)和RTCP(实时控制)之上,它使用 TCP或RTP完成数据传输.HTTP与RTSP相比,HTTP传送HTML,而RTP传送的是多媒体数据.HTTP请求由客户机发出,服务器作

编码-FFMPEG实时解码RTP传输的H264流视频花屏

问题描述 FFMPEG实时解码RTP传输的H264流视频花屏 自己用QT写的程序,在PC上采集视频编码RTP打包发送.如果发送给自己,然后用VLC播放的话是可以正常显示的(尽管延迟会不断增大,这个问题再待解决),但是用自己编的软件确无法正常显示,能看到一瞬间有部分画面正常,然后一会画面就糊掉了. 同样的代码, 我在树莓派上,用OPENMAX硬件加速编码,然后同样的打包方式发送,发送给树莓派自己或者给PC,都能正常地显示. 不知道这个是哪部分出了原因?到底是FFMPEG编码部分出问题,还是接收的代

《自己动手写Docker》书摘之一: Linux Namespace

Linux Namespace 介绍 我们经常听到说Docker 是一个使用了Linux Namespace 和 Cgroups 的虚拟化工具,但是什么是Linux Namespace 它在Docker内是怎么被使用的,说到这里很多人就会迷茫,下面我们就先介绍一下Linux Namespace 以及它们是如何在容器里面使用的. 概念 Linux Namespace 是kernel 的一个功能,它可以隔离一系列系统的资源,比如PID(Process ID),User ID, Network等等.一

动手写个数字输入框2:起手式——拦截非法字符

前言  最近在用Polymer封装纯数字的输入框,开发过程中发现不是坑,也有不少值得研究的地方.本系列打算分4篇来叙述这段可歌可泣的踩坑经历: 1. <动手写个数字输入框1:input[type=number]的遗憾> 2. <动手写个数字输入框2:起手式--拦截非法字符> 3. <动手写个数字输入框3:痛点--输入法是个魔鬼> 4. <动手写个数字输入框4:魔鬼在细节--打磨光标位置> 从源头抓起--拦截非法字符  从<动手写个数字输入框1:inpu

错误 1 服务器标记的格式不正确。

问题描述 <asp:TextBoxrunat="server"Text="HelloWorld"BackColor="#FFE0C0"BorderColor="#FFC080"Font-Size="12pt"ForeColor="#C04000"Width="224px"/><asp:TextBoxSkinId="textboxSkin&q

自己动手写ASP.NET ORM框架(二):AdoHelper支持多数据库操作的封装(2)

在上一篇文章中已经分析了AdoHelper的部分代码,接下来将继续分析剩余的部分代码,这里分析ExecuteNonQuery方法的实现,代码块1-1: // <summary>//通过提供的参数,执行无结果集的数据库操作命令// 并返回执行数据库操作所影响的行数.// </summary>// <param name="connectionString">数据库连接字符串</param>// <param name="co