上一篇文章我们介绍了如何用一个简单的UDP socket搭建一个RTP服务器。我把这份80行的代码呈现到客户面前的时候,就有人不满意了。
还有人在参考的时候会问:“楼主你的TS格式的文件是哪里来的?应该去哪里下载?”
“这也太简单了吧,不就是用UDP把TS文件发过去么?就这么几十行代码也算个大作业?”
“平时看的视频格式哪有TS的呀,不是avi就是mp4、rmvb什么的,根本不实用啊!”
 
首先回答问题1:
如果你用过强大的ffmpeg,就可以用一行简单的命令
  1. ffmpeg -i INPUTFILE.XXX OUTPUTFILE.ts
把几乎任何格式的文件转换成TS文件。
 
再回答问题2:
如果能实现同样的功能,我确实更倾向使用简单的方法。说我偷懒也好,没有技术含量也好。我觉得,很多时候最简单直接的方法最有效。
 
这篇帖子主要的内容就是来回答问题3:如何用RTP协议传输各种格式的视频。

预备知识

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

不要告诉我不可以。如果真的不可以,那么我们岂不是要把各种格式的视频解码器实现一遍?也就是说我们要自己重新写一个ffmpeg工程!
当然是可以的,关键是看如何使用。有几种选择:借用别人的源码然后集成到我们的工程;或是调用别人的接口来使用已经编译好的库;还是直接使用别人的程序?这就是复用粒度大小的选择。很少有人会用第一种方法,因为别人的源码不见得拿来就能编译通过并且成功使用。多数人会选择第二种方法,看起来顺理成章,也是可以适应一定需求变化的。(这是做软件最需要考虑的地方)
不过鉴于这个项目是一个课堂的作业,加上我比较喜欢偷懒,就选择了最简单的第三种方法。

参考代码

第一步

首先需要对上一篇中的代码做一些简单的修改:
把原先的
  1. int main(){

改为

  1. int main(int argc, char **argv){
再把原先的
  1. FILE *ts_file = fopen("/home/baby/Videos/480p.ts", "r+");

改为

  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。
  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之类的非实时流文件格式。
 
大功告成!并且远远超过了当初的需求,但是客户的需求善变如人心,下一步又是什么呢?

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

  1. 自己动手写RTP服务器——用RTP协议传输TS流

    上一篇文章我们介绍了关于RTP协议的知识,那么我们现在就自己写一个简单的传输TS流媒体的RTP服务器吧. 预备知识 关于TS流的格式:TS流封装的具体格式请参考文档ISO/IEC 13818-1.这里 ...

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

    转自:http://blog.csdn.net/baby313/article/details/7353605 本文会带领着你一步步动手实现一个简单的RTP传输服务器,旨在了解RTP流媒体传输协议以及 ...

  3. 自己动手写http服务器——处理http连接(二)

    关于http报文格式请看这篇文章 //http_conn.h #ifndef HTTPCONNECTION_H #define HTTPCONNECTION_H #include <unistd ...

  4. 自己动手写http服务器——主程序(三)

    功能:目前只支持对资源的访问. 使用的模型:多线程加epoll,与传统的一个连接请求一个线程处理不同的是,这个模型只为那些需要服务的连接请求调用线程进行处理, 整个模型的大致流程 创建一个线程持对象, ...

  5. 自己动手写http服务器——线程池(一)

    创建一个线程池,每有一个连接对象就将它添加到工作队列中,线程池中的线程通过竞争来取得任务并执行它(它是通过信号量实现的). //filename threadpool.h #ifndef THREAD ...

  6. 利用html 5 websocket做个山寨版web聊天室(手写C#服务器)

    在之前的博客中提到过看到html5 的websocket后很感兴趣,终于可以摆脱长轮询(websocket之前的实现方式可以看看Developer Works上的一篇文章,有简单提到,同时也说了web ...

  7. 自己动手写处理器之第二阶段(1)——可编程逻辑器件与PLD电路设计流程

    将陆续上传本人写的新书<自己动手写处理器>(尚未出版),今天是第五篇,我尽量每周四篇         通过上一章的介绍,读者应该知道CPU内部有一些主要的电路,比方:译码电路.运算电路.控 ...

  8. 自己动手写处理器之第二阶段(2)——Verilog HDL简单介绍

    将陆续上传本人写的新书<自己动手写处理器>(尚未出版),今天是第六篇.我尽量每周四篇 2.3 Verilog HDL简单介绍 本书实现的OpenMIPS处理器是使用Verilog HDL编 ...

  9. RTSP/RTP 媒体传输和控制协议

    1 前言 本文档主要描述了 NewStream Vision 系统中前端视频服务器(DVR, 网络摄像机), 中心转发服务器以及客户端之间的多媒体通信以及控制协议. 本协议主要基于标准的 IETE 的 ...

随机推荐

  1. 1、 Linux中的root用户切换(转载)

    su和su - 的区别 大部分Linux发行版的默认账户是普通用户,而更改系统文件或者执行某些命令,需要root身份才能进行,这就需要从当前用户切换到root用户,Linux中切换用户的命令是su或s ...

  2. leetcode Swap Nodes in Pairs python

    # Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = ...

  3. linux chmod使用说明

    chmod是用来改变一个目录的访问权限的,一般的方式是:chmod a+rwx 其中a代表全部,还有u[目录拥有者] ,g[目录拥有组],o[其他用户] r代表读,w代表写,x代表可以执行,对应数字权 ...

  4. shell基础认识

    Shell 我们在终端下写命令Linux内核是看不懂的必须通过shell解释成内核可执行的代码 这就是shell(其实解释命令这只是它的一个功能模块,shell还可以用来进行程序设计) 有点类似win ...

  5. llinuxs介绍与常用命令

    一.Linux系统概述1.计算机资源软件资源硬件资源操作系统2.操作系统WindowsMacOSLinuxUnix3.Linux含义狭义Linux:由Linus一段内核代码广义Linux:Linux厂 ...

  6. 使用verilog实现4选1数据选择器的几种方法

    第一种方法module mux( d1, d2, d3, d4, se1, se2, dout ); input d1; input d2; input d3; input d4; input se1 ...

  7. 获取EIP(汇编语言直接给Delphi变量赋值)

    var EIP: Cardinal; procedure GetEIP(); stdcall; asm pop eax; mov EIP,eax; push eax; end; procedure T ...

  8. 关于java同步包中ConcurrentLinkedQueue类的深入分析与理解

    一,官方描写叙述 一个基于连接节点的无界线程安全队列.这个队列的顺序是先进先出.队列头部的元素是留在队列中时间最长的,队列尾部的元素是留在队列中时间最短的.新元素被插入到元素的尾部,队列从队列的头部检 ...

  9. 为什么没有好用的Android游戏引擎?

    随着Android平台的不断发展,最近Android开发人员数量呈现出上升势头,就连以往较为冷门的游戏开发领域也涌现出不少生力军.然而,全新的问题正摆在了刚開始学习的人面前,非常多他们从未遇过的问题開 ...

  10. 假设写一个android桌面滑动切换屏幕的控件(一)

    首先这个控件应该是继承ViewGroup: 初始化: public class MyGroup extends ViewGroup{ private Scroller mScroller; priva ...