关于直播技术的转载

以下内容全部转载自 https://home.cnblogs.com/u/lidabo/ 博客,如涉及侵权请告知,谢谢。

开源网络通信库参考

Sockets tcp/ip communication library

C++ Sockets Library

This is a GPL licensed C++ class library wrapping the berkeley sockets C API, and therefore works on most unixes and also win32. The library is in use in a number of real world applications, both commercial and open source.

Features include, but are not limited to, SSL support, IPv6 support, tcp and udp sockets, sctp sockets, http protocol, highly customizable error handling. Testing has been done on Linux and Windows 2000, and to some part on Solaris and Mac OS X.

References as follow:
《C++ Sockets Library: Class diagram》

《C++ Sockets库》

The Ultimate TCP-IP

(1)Easy To Use, Powerful Framework

Includes both high-level and low-level APIs.

No need to know Winsock programming. Work with the high level APIs to perform complex tasks with just a few lines of code.

Works with MFC, ATL and Windows SDK applications.

Fully object oriented, letting you create your own specialized Internet classes with ease.

The library is 100% royalty free.

Unlike other development components this framework is designed to work on all Win32 versions of Windows (i.e. not only NT).

Create highly scalable servers (hundreds of connections per CPU) using our multi-threaded server framework.

Create customized protocols for highly efficient data transfer.

(2)Includes Servers For The Most Popular Protocols

The Server edition of Ultimate TCP/IP includes the server-side implementations for the following protocols:

Web Server (HTTP protocol).

Finger server.

Fully functional Email and relay server (SMTP, POP3, DNS)

File transfer server (FTP)

Echo server.

*full source for each of the protocols is included

libcURL

libcurl - the multiprotocol file transfer library.

libcurl is a free and easy-to-use client-side URL transfer library, supporting FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, FILE, IMAP, SMTP, POP3, RTMP and RTSP. libcurl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, Kerberos4), file transfer resume, http proxy tunneling and more!

libcurl is highly portable, it builds and works identically on numerous platforms, including Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX, IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS and more…

libcurl is free, thread-safe, IPv6 compatible, feature rich, well supported, fast, thoroughly documented and is already used by many known, big and successful companies and numerous applications.

ACE

The ADAPTIVE Communication Environment (ACE) is a freely available, open-source object-oriented (OO) framework that implements many core patterns for concurrent communication software. ACE provides a rich set of reusable C++ wrapper facades and framework components that perform common communication software tasks across a range of OS platforms. The communication software tasks provided by ACE include event demultiplexing and event handler dispatching, signal handling, service initialization, interprocess communication, shared memory management, message routing, dynamic (re)configuration of distributed services, concurrent execution and synchronization.

ACE is targeted for developers of high-performance and real-time communication services and applications. It simplifies the development of OO network applications and services that utilize interprocess communication, event demultiplexing, explicit dynamic linking, and concurrency. In addition, ACE automates system configuration and reconfiguration by dynamically linking services into applications at run-time and executing these services in one or more processes or threads.

FTP Application

MiniFTP

MiniFTP is a Winsock API-based minimal FTP client to be used as a tutorial for using the Winsock API in an MFC environment.

gFTP

gFTP is a free multithreaded file transfer client for *NIX based machines.

KFTPgrabber

KFTPgrabber is a graphical FTP client for the K Desktop Environment. It implements many features required for usable FTP interaction.

Pure-FTPd

Pure-FTPd is a free (BSD), secure, production-quality and standard-conformant FTP server. It doesn’t provide useless bells and whistles, but focuses on efficiency and ease of use. It provides simple answers to common needs, plus unique useful features for personal users as well as hosting providers.

FileZilla

The free FTP solution. Both a client and a server are available. FileZilla is open source software distributed free.

Web Server Framework

(1)轻量级WebServer

lighttpd

Security, speed, compliance, and flexibility – all of these describe lighttpd (pron. lighty) which is rapidly redefining efficiency of a webserver; as it is designed and optimized for high performance environments. With a small memory footprint compared to other web-servers, effective management of the cpu-load, and advanced feature set (FastCGI, SCGI, Auth, Output-Compression, URL-Rewriting and many more) lighttpd is the perfect solution for every server that is suffering load problems.

mongoose(shttpd)

Mongoose is an easy to use web server. It can be embedded into existing application to provide a web interface to it.

Features:

l Crossplatform - works on Windows, MacOS and most flavors of UNIX

l CGI, SSL, SSI, Digest (MD5) authorization, resumed download, aliases

l IP-based ACL, Windows service, GET, POST, HEAD, PUT, DELETE methods

l Small footprint: executable size is 40 kB on Linux 2.6 i386 system, 60 kB on Windows system

l Embeddable with simple and clean API. Source is in single .c file to make things easy

thttpd

thttpd is a simple, small, portable, fast, and secure HTTP server.

Simple:

It handles only the minimum necessary to implement HTTP/1.1. Well, maybe a little more than the minimum.

Small:

See the comparison chart. It also has a very small run-time size, since it does not fork and is very careful about memory allocation.

Portable:

It compiles cleanly on most any Unix-like OS, specifically including FreeBSD, SunOS 4, Solaris 2, BSD/OS, Linux, OSF.

Fast:

In typical use it’s about as fast as the best full-featured servers (Apache, NCSA, Netscape). Under extreme load it’s much faster.

Secure:

It goes to great lengths to protect the web server machine against attacks and breakins from other sites.

It also has one extremely useful feature (URL-traffic-based throttling) that no other server currently has. Plus, it supports IPv6 out of the box, no patching required.

References as follow:

《移植thttpd》

《深入研究嵌入式web服务器的视频监控应用》

(2)IM WebServer

Jabber

Jabber is InstantMessaging(IM) server written in pure C language,which is the origin of XMPP. It is based on XMPP(Extensible Messaging and Presence Protocol) expressed in XML.With Jabber/XMPP, differences between the IM are overcomed. It allows you to communicate between MSN,Yahoo, and etc.

Instant messaging between the Google Talk servers and its clients uses an open protocol, XMPP, allowing users of other XMPP/Jabber clients to communicate with Google Talk users. That is any client that supports Jabber/XMPP can connect to the Google Talk service.Refer to Google Talk and MSN via Jabber together in iChat.

References as follow:

A web based Jabber/XMPP client

Psi - The Cross-Platform Jabber/XMPP Client For Power Users

《开源Jabber(XMPP) IM服务器介绍》

《安装Jabberd服务器》

(3)重量级WebServer

Apache HTTP SERVER PROJECT

The Number One HTTP Server On The Internet!

The Apache HTTP Server Project is a collaborative software development effort aimed at creating a robust, commercial-grade, featureful, and freely-available source code implementation of an HTTP (Web) server.

References as follow:

Apache HTTP Server Version 2.2 Documentation

《Windows 下Apache httpd-2.2.11编译手记》

Nginx

nginx [engine x] is a HTTP and reverse proxy server, as well as a mail proxy server written by Igor Sysoev. It has been running for more than five years on many heavily loaded Russian sites including Rambler (RamblerMedia.com). According to Netcraft nginx served or proxied 4.70% busiest sites in April 2010. Here are some of success stories: FastMail.FM, Wordpress.com.

The sources are licensed under 2-clause BSD-like license.

Basic HTTP features:
l Serving static and index files, and autoindexing; open file descriptor cache;

l Accelerated reverse proxying with caching; simple load balancing and fault tolerance;

l Accelerated support with caching of remote FastCGI servers; simple load balancing and fault tolerance;

l Modular architecture. Filters include gzipping, byte ranges, chunked responses, XSLT, SSI, and image resizing filter. Multiple SSI inclusions within a single page can be processed in parallel if they are handled by FastCGI or proxied servers.

l SSL and TLS SNI support.

References as follow:
《Nginx负载均衡搭建胜过Apache十倍?》

《牛X的NGINX,牛X的Igor Sysoev》

《nginx源码分析》

《nginx 0.8.47版发布》

《Nginx+Php搭建Web服务器》

《实战Nginx:取代Apache的高性能Web服务器》

Memcache

《网站Cache全分析》

《Cache性能分析》

《同时多线程处理器上的Cache性能分析与优化》
Memcached

Free & open source, high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.

Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.

Memcached is simple yet powerful. Its simple design promotes quick deployment, ease of development, and solves many problems facing large data caches. Its API is available for most popular languages.

References as follow:
《Memcached完全剖析》

Squid cache

Squid is a caching proxy for the Web supporting HTTP, HTTPS, FTP, and more. It reduces bandwidth and improves response times by caching and reusing frequently-requested web pages. Squid has extensive access controls and makes a great server accelerator. It runs on most available operating systems, including Windows and is licensed under the GNU GPL.

Features:

Making the most of your Internet Connection

Website Content Acceleration and Distribution

Varnish

Varnish is a state-of-the-art, high-performance HTTP accelerator. It uses the advanced features in Linux 2.6, FreeBSD 6/7 and Solaris 10 to achieve its high performance.

References as follow:
《使用Varnish代替Squid做网站缓存加速器的详细解决方案》

Multimedia Streaming and P2P

An RTSP Toolkit

oRTP

oRTP - a Real-time Transport Protocol (RFC3550) stack under LGPL

References as follow:

oRTP Document

《oRTP Introduction》

《从RTP到oRTP》

《oRTP协议栈浅析》

JRTPLIB

JRTPLIB is an object-oriented RTP library written in C++. The library offers support for the Real-time Transport Protocol (RTP), defined in RFC 3550. It makes it very easy to send and receive RTP packets and the RTCP (RTP Control Protocol) functions are handled entirely internally.

References as follow:

Document Reference

《流媒体相关知识介绍及其RTP应用》

MPEG4IP

MPEG4IP provides an end-to-end system to explore streaming multimedia. The package includes many existing open source packages and the “glue” to integrate them together. This is a tool for streaming video and audio that is standards-oriented and free from proprietary protocols and extensions.

spook

Spook is a Linux server application to capture live video and audio and stream it over an IP network. Currently, Spook supports capturing from a Firewire IIDC camera or Video4Linux(2) source and streaming MPEG4 with RTSP or JPEG stills with HTTP.

Spook for arm

LScube

The LScube - Libre Streaming, Libre Software, Libre Standards (formerly known as OMSP - Open Media Streaming Project) is a free/libre software project, supported by the Internet Media Group, that develops and maintains a suite of programs focused on multimedia streaming. We strive to fully support the IETF’s standards for the real-time data transport over IP. The aim of the project is to provide open, free and interoperable solutions on a par with other proprietary streaming applications. All LScube software is released under Free Software licenses.

Fenice - legacy streaming server

Feng - the RTSP/RTP streaming server

The new streaming server sports various usability and architectural improvement over Fenice, our previous design.

Libnemesi - the RTSP/RTP client library

References as follow:

《Fenice vm流程研究》

live555(VC6版本,VC2005版本)
This code forms a set of C++ libraries for multimedia streaming, using open standard protocols (RTP/RTCP, RTSP, SIP). These libraries - which can be compiled for Unix (including Linux and Mac OS X), Windows, and QNX (and other POSIX-compliant systems) - can be used to build streaming applications.

References as follow:

live Documentation

《用VC2005编译多媒体串流程序库》

VLC

Free streaming and multimedia solutions for all OS!

VLC is a free and open source cross-platform multimedia player and framework, that plays most multimedias files as well as DVD, Audio CD, VCD, and various streaming protocols.

References as follow:

Doc/Support

《VLC RTSP implementation with live555》

《Windows平台下vlc的编译》

《VC6编译VLC-0.9.9a步骤说明》

《VLC产生rtsp测试源》

Helix

The Helix DNA™ Server

The Helix DNA Server is a universal delivery engine supporting the real time packetization and network transmission of any media type to any device.

Helix DNA Client

The Helix DNA Client is the universal digital media playback engine, supporting playback of any format and codec on any device. It provides the underlying multimedia functionality to a whole host of applications that require local and streaming playback of multiple formats in disparate environements.

Helix Player

The Helix Player is an open source media player for Linux, Solaris, and Symbian based on the Helix DNA Client media engine.

《RealPlayer 10.0.8 For Wince 源码》

IP Messenger

This is a pop up style LAN Messenger for multi platforms.

It is based on TCP/IP(UDP).

It does not require server machine-most primitive P2P infrastructure.

Simple, lightweight, and compact size.

References as follow:

《IPMSG分析》

《IPMSG(飞鸽传书)协议翻译》

《IPMSG协议》

《IPMSG飞鸽传书网络协议解析手记》

《IPMsg中最核心的数据结构》

《IPMSG(飞鸽传书)文件发送源码分析》

Icecast

icecast is free server software for streaming audio(Mpeg III) over Internet with P2P technology.

peercast

PeerCast is a simple, free way to listen to radio and watch video on the Internet. It uses P2P technology to let anyone become a broadcaster without the costs of traditional streaming.

References as follow:

《peercast王浩聪注释版》

《Peercast over IPv6》

myseelite

MyseeLite is a P2P Media Streaming System including servers on Linux and client on Windows 98/NT/2000/XP/2003. It was commercial once, but now goes opensource. It was developed from 2003.8 by a company in China.

References as follow:

《P2P网络技术原理与C++开发案例》

《myseelite源代码和开发分析》


P2P直播、点播技术学习经验

  自8月份以来一直埋头学习P2P在音/视频直播、点播上的学习,受到不少网友的帮助,在此也留下自己学到的一点点的经验。

  第一个接触的开源项目是peercast,应该说上手非常快,这必须感谢王浩聪的注释版,稍做调整后便架起了自己的广播平台,运行起来效果也很理想。于是尝试发布视频流,在局域网内测试未发现问题,但是拿到广域网上问题马上出来了,播放要么中断、要么缓冲。

  于是,仔细学习代码的相关流程,网上也查了一些资料,发现peercast的网络模型为树形,而视频所需要的上传流量一般都在30K以上,这样客户机很难满足下线所需的资源。所以才会出现问题。为了更深入的学习

  为了更深入的学习P2P应用,第二个编译的是mysee公司开源的myseelite,这个项目共开放了三个版本:myseelite1、myseelite2.0、myseelite2.1,下面我将粗略的介绍下这三个版本:

  myseelite1 这个版本的服务端必须运行在linux系统上,为了编译这个版本,我特地弄了一台linux机器,TP、CP、SP三个服务全部编译成功,运行MMSServer.exe连接成功,但服务端去没有看到生成的相关频道信息,在调试中找到了几位网友也在看这个项目,知道还有myseelite2。

  myseelite2.1 先介绍2.1是因为我是先从2.1开始编译的,环境搭好以后,顺利编译出各个程序并配置、运行,Capture.exe点上传后崩溃。经网友指点得知2.1问题比较多,放弃~

  myseelite2.0 既然2.1有问题那我们就用2.0学习也一样,环境之前搭好,编译也顺利,运行。。。playerd.exe崩溃。。。(我特想找个人抽两下),后经指点2.0播放器有问题要用2.1的来播放,好吧!换了播放器之后果然可以播放。然而经过更深入的测试发现,问题依然很多。。。比如播放一段时间后莫名中断,有时无法P2P。。。。

  至此,mysee三个版本全部接触过,果真是个令真震撼的开源项目,八卦的话咱就不多说了,既然是来学习的,代码还得深入的看,经过两周的编译、调试,才发现自己是多么的才疏学浅,居然没能把这套东西稳定运行。。。。

  第三个是P2PCenter,有人说这个项目是个团队开发,不如mysee有公司背景,我不知道这位兄台是否亲自编译过这些项目,就我学习的经验来看,P2PCenter采用UDP协议,比mysee的tcp更适合做P2P,P2PCenter编译可直接部署运行,至于稳定性我无法评论,因为我主要学习直播,而P2PCenter是无法实现直播的,虽然网上都在转载它可以直播,但我没有看出来它如何直播。

  如果让我推荐,那么我首推P2PCenter,无论你做直播还是点播,这个应该都是最佳选择,点播可以直接部署,直播需要自己写个采集MMS流的模块。

  纯学习推荐peercast,虽然太老,但是个非常成熟的项目,值的学习。至于mysee,如果你的空余时间多,有充分的时间DEBUG,那么可以去看看。至少我个人认识这个项目没啥可学习的地方,首先他是TCP的协议,本身就不适合做P2P,再着问题不是一般的多。


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

  本文会带领着你一步步动手实现一个简单的RTP传输服务器,旨在了解RTP流媒体传输协议以及一些关于多媒体编解码的知识。

关于RTP协议的必备知识

  要动手实现一个协议,当然首先需要阅读该协议的文档。RTP协议的文档,有rfc1889、rfc1890、rfc3550,其中rfc3550是现在的版本,另外两个是过期版。这个协议可以在ietf的官网找到:http://tools.ietf.org/html/rfc3550

RTP packet

  RTP是基于UDP协议的,RTP服务器会通过UDP协议,通常每次会发送一个RTP packet。客户端通过解析RTP packet,读取其中的数据然后进行播放了。

RTP packet的结构如下:
|
|– RTP Header:RTP 包的头部
|– contributing sources:个数为0-n个,所以可以为空。具体定义参考rfc3550
|– RTP payload:即RTP要传输的数据

RTP Header

  这是RTP流的头部,在网上搜索RTP格式,就会搜到很多文章介绍这个头部的定义。我们这里参考rfc3550的定义,在5.1节(http://tools.ietf.org/html/rfc3550#section-5.1)。

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |V=2|P|X|  CC   |M|     PT      |       sequence number         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           timestamp                           |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           synchronization source (SSRC) identifier            |
   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
   |            contributing source (CSRC) identifiers             |
   |                             ....                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

每行是32 bits,由此可以直观看到每个表示部分所占的位数。简单介绍一下:

V(version):2 bits,RTP的版本,这里统一为2
P(padding):1 bit,如果置1,在packet的末尾被填充,填充有时是方便一些针对固定长度的算法的封装
X(extension):1 bit,如果置1,在RTP Header会跟着一个header extension
CC(CSRC count): 4 bits,表示头部后contributing sources的个数
M(marker): 1 bit,具体这位的定义会在一个profile里
PT(playload type): 7 bits,表示所传输的多媒体的类型,对应的编号在另一份文档rfc3551中有列出(http://tools.ietf.org/html/rfc3551)
sequence number: 16 bits,每个RTP packet的sequence number会自动加一,以便接收端检测丢包情况
timestamp: 32 bits,时间戳
SSRC: 32 bits,同步源的id,没两个同步源的id不能相同
CSRC: 上文说到,个数由CC指定,范围是0-15

  以上的一些概念是一些要实现RTP服务器所必备的知识。介绍的非常简略,详细的定义还是要参考rfc3550原文。

动手实践

  我们既然已经知道了RTP packet的结构,那么我们以前用到的RTP流是否也是这样的结构呢?如何验证呢?接下来,我们就一步步验证RTP流的结构。

  我们知道RTP是基于UDP协议的,那么我们就先做一个简单的UDP接受端,看看我们可以从RTP服务器接受到什么信息。要实现这个接受端,你需要有一定的网络编程经验,至于具体到操作系统、编程环境、开发语言等都不限制。为了简单,我这里用python给出一个小小的例子程序。

import socket  

# Build a socket to receive data from RTP server.  
# Here we use SOCK_DGRAM, because RTP is on UDP.  
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  
sock.bind(("localhost", 6666))  

for i in range(5):  
        # We just get 16 bytes to analyze the RTP Header.  
        buf = sock.recv(16)  

        # Output the result in octal.  
        for c in buf:  
                print "%x" % ord(c),  
        print  

sock.close()  

  这就是接受程序啦,非常短小,而且有简单注释,这里就不解释了。

  接受端已经做好了,那么去哪里找RTP服务器作发送端呢?你可以用一些搭建流媒体服务器的工具,我这里选用的是强大的VLC。关于VLC搭建流媒体服务器的方法,请参考我前面的文章基于移动平台的多媒体框架——用VLC搭建简单的流媒体服务器。这里需要注意几个配置的地方,一是选择Destination的时候要选择RTP而不要选择RTSP,然后地址可以填写本机ip地址或直接写localhost,端口号填写的要和接受端一致,这里是6666。配置好之后的string应该类似于:

:sout=#rtp{dst=localhost,port=6666,mux=ts} :no-sout-rtp-sap :no-sout-standard-sap :ttl=1

  服务端配置完成之后,开始Stream。这时打开接受端,就会接受到一些数据,我接收到的数据开头是:

80 a1 20 43 8c cf 76 3c 93 59 d 74 47 0 44 10 80 a1 20 44 8c cf 79 4b
93 59 d 74 47 40 42 36 80 a1 20 45 8c cf 7d 36 93 59 d 74 47 0 44 1a
80 a1 20 46 8c cf 81 21 93 59 d 74 47 40 45 1a 80 a1 20 47 8c cf 85 c
93 59 d 74 47 0 45 1b

  这是十六进制的表示。我们依照上面的Header的格式对其进行解读:
第一个byte 80 表示:

V(version)=2
P(padding)=0
X(extension)=0
CC(CSRC count)=0

第二个byte a1 表示:

M(marker)=1
PT(playload type)=33(对照rfc3551可以发现,33表示MP2T AV,正是我们用VLC Stream的格式类型)

  后面的2bytes的sequence number我们可以直观的看出是在加一,4bytes的timestamp也是在不断递增的。再之后的93 59 d 74就是SSRC id了,由于CC为0,所以没有CCRC。再之后的几位都是RTP所要传输的数据了。

总结

  对RTP协议的熟悉是实现它的基础。这里我只是做一个简单的介绍,需要详细了解,读官方的文档是必不可少的步骤。

  通过写一个小程序打印出RTP流中具体的数据,并没有对实现RTP服务器有直接帮助。但是可以让你对协议本身以及编程环境更加熟悉,也方便了以后实现过程中进行调试。不论你在什么环境用什么语言实现,都强烈建议写一个这样的小程序。


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

  上一篇文章我们介绍了关于RTP协议的知识,那么我们现在就自己写一个简单的传输TS流媒体的RTP服务器吧。

预备知识

  关于TS流的格式:TS流封装的具体格式请参考文档ISO/IEC 13818-1。这里我们只需要了解一些简单的信息就好。首先TS流是有许多的TS Packet组成的,每个TS Packet的长度固定为188 bytes,每个packet都是以sync_byte:0x47开头。

  MTU(Maximum Transmission Unit): 最大传输单元。是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位)。最大传输单元这个参数通常与通信接口有关(网络接口卡、串口等)。例如:以太网无法接收大于1500 字节的数据包。

参考代码
  下面我会把自己写的简单的代码贴出来,并且一步步地说明。

新建main.c文件,内容如下:

#include   
#include   
#include   
#include   
#include   

#define TS_PACKET_SIZE 188  
#define MTU 1500  

  说明:包含一些必要的头文件,并且定义了TS Packet的长度(188 bytes),MTU的限制(1500 bytes)。

struct rtp_header{  
    unsigned char cc:4;  
    unsigned char x:1;  
    unsigned char p:1;  
    unsigned char v:2;  

    unsigned char pt:7;  
    unsigned char m:1;  

    unsigned short sequence_number;  
    unsigned int timestamp;  
    unsigned int ssrc;  
};  

void init_rtp_header(struct rtp_header *h){  
    h->v = 2;  
    h->p = 0;  
    h->x = 0;  
    h->cc = 0;  
    h->m = 0;  
    h->pt = 33;  
    h->sequence_number = 123;  
    h->timestamp = 123;  
    h->ssrc = 123;  
}  

  说明:这里定义了RTP Header的结构体,以及初始化的方法。这里用到了位域,这是实现协议的时候常常会用到的方法。

需要注意的是:

  你会发现这里定义RTP Header的时候,上一篇讲到的具体顺序不同。原因是本机和网络字节流的顺序相反,如果按照v p x cc的顺序来定义一个byte,在这个byte内部v p x cc就会按照从低位到高位的顺序放置;而在RTP流中,应该是顺序从高位到低位放置的。所以每个byte我都把顺序做了倒置。

  初始化RTP Header的函数的初始化值的意义请参考rfc3550。为了实现简单,其中的sequence_number、timestamp、ssrc,都是随意填写的。在发送包的时候需要将sequence_number递增。

void sequence_number_increase(struct rtp_header *header){  
    unsigned short sequence = ntohs(header->sequence_number);  
    sequence++;  
    header->sequence_number = htons(sequence);  
}  

  说明:这个函数的目的就是让sequence_number加一,还是由于本机与网络字节序不同的原因,所以显得略微复杂些。

int main(){  
    // RTP Packet we will send  
    char buf[MTU];  
    unsigned int count = 0;  

    // Init RTP Header  
    init_rtp_header((struct rtp_header*)buf);  
    count = sizeof(struct rtp_header);  

    // Init socket  
    int sock = socket(AF_INET, SOCK_DGRAM, 0);  
    struct sockaddr_in dest_addr;  

    dest_addr.sin_family=AF_INET;  
    dest_addr.sin_port = htons(6666);  
    dest_addr.sin_addr.s_addr = INADDR_ANY;  
    bzero(&(dest_addr.sin_zero),8);  

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

  说明:终于到了main函数了,main函数的开始很简单,四个部分的初始化:代表RTP Packet的buffer,RTP Header,Socket,TS流媒体文件。如果你手头没有现成的TS文件,可以用ffmpeg转码得到一个ts文件:“ffmpeg -i video.xxx video.ts”, 其中 video.xxx 表示输入的视频文件,video.ts 为输出的TS文件。

while(!feof(ts_file)){  
    int read_len = fread(buf+count, 1, TS_PACKET_SIZE, ts_file);  
    if(*(buf+count) != 0x47){  
        fprintf(stderr, "Bad sync header!\n");  
        continue;  
    }  
    count += read_len;  

    if (count + TS_PACKET_SIZE > MTU){// We should send  
        sequence_number_increase((struct rtp_header*)buf);  
        sendto(sock, buf, count, 0, (const struct sockaddr*)&dest_addr, sizeof(dest_addr));  
        count = sizeof(struct rtp_header);  
        usleep(10000);  
    }  
}  

fclose(ts_file);  

  说明:一切就绪后就可以不断的用UDP发送RTP Packet了。每次从ts_file中读取188 bytes,附加到buf之后,如果buf的长度还没用到达MTU的限制,那么就继续添加,否则就将buf发送出去。每次发送会将sequence_number加一,并且间隔10000微秒。当然这只是个简单的例子,实际发送视频是要根据时间戳的。

测试

  短短几十行代码是否就能完成一个RTP服务器?我们需要用实验来验证。

  我的测试环境是Linux,用gcc编译通过,使用VLC(MPlayer 测试也可以通过了)作为接收端。

  首先启动我们的发送端程序,然后再执行“vlc rtp://127.0.0.1:6666”,等待几秒后,发现真的可以进行播放啦!


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

  上一篇文章我们介绍了如何用一个简单的UDP socket搭建一个RTP服务器。我把这份80行的代码呈现到客户面前的时候,就有人不满意了。
  还有人在参考的时候会问:“楼主你的TS格式的文件是哪里来的?应该去哪里下载?”
  “这也太简单了吧,不就是用UDP把TS文件发过去么?就这么几十行代码也算个大作业?”
  “平时看的视频格式哪有TS的呀,不是avi就是mp4、rmvb什么的,根本不实用啊!”

首先回答问题1:
  如果你用过强大的ffmpeg,就可以用一行简单的命令

ffmpeg -i INPUTFILE.XXX OUTPUTFILE.ts  

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

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

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

预备知识

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

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

int main(){  

改为

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

再把原先的

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

改为

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

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

第二步

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

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

  只有四行有木有,很简单有木有!
  其实就是利用了ffmpeg的分流与解码,然后利用命名管道把ffmpeg的输出到处到一个管道中,然后再用我们前面写好的rtp_server去读这个文件。
  (切记ffmpeg参数里面的-y是必不可少的)
  OK,大功告成。chmod之后执行这个脚本文件./mk_rtp_server.sh INPUTFILE.XXX,拿个播放器测试一下。”嗯~果然不错~“
  只要你的ffmpeg装的够完整,那么几乎所有的格式都可以变成rtp流。包括avi之类的非实时流文件格式。

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

你可能感兴趣的:(多媒体编解码)