- 浏览: 103417 次
- 性别:
- 来自: 南京
文章分类
最新评论
Recall that RTSP is the actual protocol over which streaming commands are initiated, through which the RTP packets are received. The RTSP protocol is like a command initiator, a bit like HTTP. For a really good explanation of a typical RTSP session, please see these specifications for a simple RTSP client. For the purposes of this article, I am going to oversimplify the protocol implementation. Figure 1 shows the typical RTSP session between a client and a streaming server.
Figure 1. A typical RTSP session between a RTSP client and a streaming server (click for full-size image).
In a nutshell, an RTSP client initiates a session by sending a DESCRIBE
request to the streaming server which means that the client wants more information about a media file. An example DESCRIBE
request may look like this:
DESCRIBE rtsp://localhost:554/media.3gp rtsp/1.0
CSeq: 1
The URL for the media file is followed by the RTSP version that the client is following, and a carriage return/line feed (CRLF). The next line contains the sequence number of this request and increments for each subsequent request sent to the server. The command is terminated by a single line on its own (as are all RTSP commands).
All client commands that are successful receive a response that starts with RTSP/1.0 200 OK
. For the DESCRIBE
request, the server responds with several parameters, and if the file is present and streamable, this response contains any information for any tracks in special control strings that start with a a=control:trackID=
String. The trackID
is important and is used to create the next requests to the server.
Once described, the media file's separate tracks are set up for streaming using the SETUP
command, and these commands should indicate the transport properties for the subsequent RTP packets. This is shown here:
SETUP rtsp://localhost:554/media.3gp/trackID=3 rtsp/1.0
CSeq: 2
TRANSPORT: UDP;unicast;client_port=8080-8081
The previous command indicates to the server to set up to stream trackID
3 of the media.3gp file, to send the packets via UDP, and to send them to port 8080 on the client (8081 is for RTCP commands). The response to the first SETUP
command (if it is okay) will contain the session information for subsequent commands and must be included as shown here:
SETUP rtsp://localhost:554/media.3gp/trackID=3 rtsp/1.0
CSeq: 3
Session: 556372992204
TRANSPORT: UDP;unicast;client_port=8080-8081
An OK response from the server indicates that you can send the PLAY command, which will make the server start sending the RTP packets:
PLAY rtsp://localhost:554/media.3gp rtsp/1.0
CSeq: 3
Session: 556372992204
Notice that the PLAY
command is issued only on the main media file, and not on any individual tracks. The same is true for the PAUSE
and TEARDOWN
commands, which are identical to the PLAY
command, except for the command itself.
The following listing contains the RTSPProtocolHandler
class. The comments in the code and the brief information so far should help with understanding how this protocol handler works:
importjava.util.Vector; importjava.io.InputStream; importjava.io.IOException; importjava.io.OutputStream; publicclassRTSPProtocolHandler{ //theaddressofthemediafileasanrtsp://...String privateStringaddress; //theinputstreamtoreceiveresponsefromtheserver privateInputStreamis; //theoutputstreamtowritetotheserver privateOutputStreamos; //theincrementingsequencenumberforeachrequest //sentbytheclient privatestaticintCSeq=1; //thesessionidsentbytheserverafteraninitialsetup privateStringsessionId; //thenumberoftracksinamediafile privateVectortracks=newVector(2); //flagstoindicatethestatusofasession privatebooleandescribed,setup,playing; privateBooleanstopped=true; //constants privatestaticfinalStringCRLF=" "; privatestaticfinalStringVERSION="rtsp/1.0"; privatestaticfinalStringTRACK_LINE="a=control:trackID="; privatestaticfinalStringTRANSPORT_DATA= "TRANSPORT:UDP;unicast;client_port=8080-8081"; privatestaticfinalStringRTSP_OK="RTSP/1.0200OK"; //baseconstructor,takesthemediaaddress,inputandoutputstreams publicRTSPProtocolHandler( Stringaddress,InputStreamis,OutputStreamOs){ this.address=address; this.is=is; this.os=Os; } //creates,sendsandparsesaDESCRIBEclientrequest publicvoiddoDescribe()throwsIOException{ //ifalreadydescribed,return if(described)return; //createthebasecommand StringbaseCommand=getBaseCommand("DESCRIBE"+address); //executeitandreadtheresponse Stringresponse=doCommand(baseCommand); //theresponsewillcontaintrackinformation,amongstotherthings parseTrackInformation(response); //setflag described=true; } //creates,sendsandparsesaSETUPclientrequest publicvoiddoSetup()throwsIOException{ //ifnotdescribed if(!described)thrownewIOException("NotDescribed!"); //createthebasecommandforthefirstSETUPtrack StringbaseCommand= getBaseCommand( "SETUP"+address+"/trackID="+tracks.elementAt(0)); //addthestatictransportdata baseCommand+=CRLF+TRANSPORT_DATA; //readresponse Stringresponse=doCommand(baseCommand); //parseitforsessioninformation parseSessionInfo(response); //ifsessioninformationcannotbeparsed,itisanerror if(sessionId==null) thrownewIOException("Couldnotfindsessioninfo"); //now,sendSETUPcommandsforeachofthetracks intcntOfTracks=tracks.size(); for(inti=1;i<cntOfTracks;i++){ baseCommand= getBaseCommand( "SETUP"+address+"/trackID="+tracks.elementAt(i)); baseCommand+=CRLF+"Session:"+sessionId+CRLF+TRANSPORT_DATA; doCommand(baseCommand); } //thisisnowsetup setup=true; } //issuesaPLAYcommand publicvoiddoPlay()throwsIOException{ //mustbefirstsetup if(!setup)thrownewIOException("NotSetup!"); //createbasecommand StringbaseCommand=getBaseCommand("PLAY"+address); //addsessioninformation baseCommand+=CRLF+"Session:"+sessionId; //executeit doCommand(baseCommand); //setflags playing=true; stopped=false; } //issuesaPAUSEcommand publicvoiddoPause()throwsIOException{ //ifitisnotplaying,donothing if(!playing)return; //createbasecommand StringbaseCommand=getBaseCommand("PAUSE"+address); //addsessioninformation baseCommand+=CRLF+"Session:"+sessionId; //executeit doCommand(baseCommand); //setflags stopped=true; playing=false; } //issuesaTEARDOWNcommand publicvoiddoTeardown()throwsIOException{ //ifnotsetup,nothingtoteardown if(!setup)return; //createbasecommand StringbaseCommand=getBaseCommand("TEARDOWN"+address); //addsessioninformation baseCommand+=CRLF+"Session:"+sessionId; //executeit doCommand(baseCommand); //setflags described=setup=playing=false; stopped=true; } //thismethodisaconveniencemethodtoputaRTSPcommandtogether privateStringgetBaseCommand(Stringcommand){ return( command+ ""+ VERSION+//version CRLF+ "CSeq:"+(CSeq++)//incrementingsequence ); } //executesacommandandreceivesresponsefromserver privateStringdoCommand(StringfullCommand)throwsIOException{ //toreadtheresponsefromtheserver byte[]buffer=newbyte[2048]; //debug System.err.println("======CLIENTREQUEST======"); System.err.println(fullCommand+CRLF+CRLF); System.err.println("============================"); //sendacommand os.write((fullCommand+CRLF+CRLF).getBytes()); //readresponse intlength=is.read(buffer); Stringresponse=newString(buffer,0,length); //emptythebuffer buffer=null; //iftheresponsedoesn'tstartwithanallclear if(!response.startsWith(RTSP_OK)) thrownewIOException("Serverreturnedinvalidcode:"+response); //debug System.err.println("======SERVERRESPONSE======"); System.err.println(response.trim()); System.err.println("============================="); returnresponse; } //conveniencemethodtoparseaserverresponsetoDESCRIBEcommand //fortrackinformation privatevoidparseTrackInformation(Stringresponse){ StringlocalRef=response; StringtrackId=""; intindex=localRef.indexOf(TRACK_LINE); //iteratethroughtheresponsetofindallinstancesofthe //TRACK_LINE,whichindicatesallthetracks.Addallthe //trackid'stothetracksvector while(index!=-1){ intbaseIdx=index+TRACK_LINE.length(); trackId=localRef.substring(baseIdx,baseIdx+1); localRef=localRef.substring(baseIdx+1,localRef.length()); index=localRef.indexOf(TRACK_LINE); tracks.addElement(trackId); } } //findoutthesessioninformationfromthefirstSETUPcommand privatevoidparseSessionInfo(Stringresponse){ sessionId= response.substring( response.indexOf("Session:")+"Session:".length(), response.indexOf("Date:")).trim(); } }
发表评论
-
规范的模板化项目架构管理
2012-05-03 23:31 845总在寻找项目开发简单化、标准化、统一化的开发管理方法,在项目 ... -
Java的ftp上传下载工具
2012-04-05 22:17 1718自己写的利用apache的net包写的ftp的上传、下 ... -
SmartGWT学习注意事项(一)
2012-03-31 20:42 1533首先表明,我 ... -
J2ME程序开发全方位基础讲解汇总
2007-08-03 14:19 619一、J2ME中需要的Java基础知识现在有大部分人,都是从零开 ... -
使用J2ME技术开发RPG游戏
2007-08-03 14:24 550RPG(角色扮演游戏)是手机游戏中的一类主要类型,也是相对来说 ... -
移动视频: QuickTime for Java API 入门
2007-08-05 12:45 619在 Java 平台上创建 iPod 视频内容 ... -
技术交流:QuickTime流媒体和Java(图)
2007-08-05 12:46 629这并不是即将问世的Quic ... -
JMF下载安装与支持格式
2007-08-05 12:47 853JMF开发进度不是很快,所以目前还是比较薄弱。 JMF,全名 ... -
搭建J2ME开发环境
2007-08-05 12:48 566由于WTK并没有提供代码编辑的功能,因此本文讲述如何使用Ecl ... -
JMF系统介绍
2007-08-09 15:18 697一.简介 1.1JMF 体系结构 ... -
Experiments in Streaming Content in Java ME(一)
2007-08-13 13:43 578Since my book on Mobile Media A ... -
Experiments in Streaming Content in Java ME(三)-----Back to RTPSourceStream and StreamingDataSource
2007-08-13 13:46 1029With the protocol handler in pl ... -
java中文件操作大全
2007-08-22 15:40 554一.获得控制台用户输入的信息 /***//**获得控 ... -
Pocket PC、Pocket PC Phone、Smartphone的区别
2007-08-23 16:59 653首先说明几个概念: 1、什么是Pocket PC?Pocket ... -
Windows mobile Install the Tools
2007-08-23 17:39 577Install Visual Studio 2005 ... -
windows mobile 5.0 模拟器上网的设置
2007-08-28 14:31 642在确保主机已连上互联网的情况下,按以下步骤设置: 1、打 ... -
使用 Windows Mobile 5.0 中的图片、视频和照相机
2007-08-29 15:47 814使用 Windows Mobile 5.0 中的图片、视频和照 ... -
Windows Mobile的安装与流媒体的安装设置
2007-09-05 17:29 851本文重点描述了在Windows Mobile下使用流媒体服务 ... -
Windows Mobile中的WebService应用
2007-09-07 15:03 634Web Service对于开发者来说已经不再是一个陌生概念了。 ... -
Struts配置文件详解(来自csdn)
2007-11-30 08:35 497Struts应用采用两个基于X ...
相关推荐
标题“Experiments in Streaming Content in Java ME(源码下载)”涉及的是在Java ME环境中实现流媒体内容的实验。Java ME(Micro Edition)是Java平台的一个版本,主要用于移动设备和嵌入式系统。这个项目可能专注于...
java8流源码java-flow-experiments 在这个存储库中,我正在试验 ,它将成为 Java 8 应用程序java.util.concurrent包中的 Java 9 的一部分。 这个存储库是为我的主题为 java.util.concurrent.Flow 做好准备的演讲准备...
这本书对反应式机器人和行为式机器人有各种介绍,对智能机器人的爱好者是一个很不错的启发学习。
Java 第二次试验报告 本资源摘要信息是基于 Java 第二次试验报告,涵盖了 Java 基础知识点,包括注释、数据类型、变量、赋值、运算符等。 标题解释 Java 第二次试验报告的标题 clearly indicates that this is a ...
In related work, an exhaustivesearchfromallone-hoprelations,two-hop relations,andsoontothemax-hoprelationsin the knowledge graph is necessary but expensive. Therefore, the number of hops is generally...
高斯投影java源码Quick-Data-Science-Experiments-2017 在制品: 判别与生成分类器 () 通过迭代重新加权最小二乘法解决逻辑回归 () WIP课程: UCL RL 大卫银 () 丹尼布里茨 () 贝叶斯 ML 麦吉尔 () cs224 斯坦福 NLP...
Design of Experiments for Engineers and Scientists Second Edition Design of Experiments (DOE) is a powerful technique used for both exploring new processes and gaining increased knowledge of existing ...
If you know Java, Mastering Machine Learning with Java is your next step on the path to becoming an advanced practitioner in Data Science. This book aims to introduce you to an array of advanced ...
java俄罗斯框源码关于 GECCO 2015 发表的论文“N-Tuple Network for Knowledge-Free Reinforcement Learning in High Dimensions: A Case Study in SZ-Tetris”中描述的运行实验的源代码。 作者 Wojciech Jaśkowski...
1 the fruit-fly experiments described in Carl Zimmer’s piece in the Science Times on Tuesday. Fruit flies who were taught to be smarter than the average fruit fly 2 to live shorter lives. This ...
java8 看不到源码使用自 Gradle 6.4 起可用的 JPMS 支持的示例(示例的当前版本需要Gradle 6.7+ ): 以及依赖于纯库的自动模块 带有 JUnit 4 单元(白盒)测试的模块 - 使用模块补丁 - 和集成(黑盒)测试 带有 ...
most recent meeting was in the last week of March in Utah. Also present was Bill Duvall of SRI who has recently started working with Jeff Rulifson. Somewhat independently, Gerard DeLoche of UCLA ...
graphql-me-experiments Graphql-ExpressJs-MongoDB *猫鼬-实验本地跑步(通天塔) 克隆后,转到根文件夹并运行: npm install npm start编译文件(Babel)并运行它们(节点)。 npm install npm run build npm run ...
根据给定文件的信息,我们可以深入探讨Java编程语言的关键知识点,这些知识点主要集中在“SUN - SL-275 Java Programming Language.pdf”这一资料中,它被认为是SCJP(Sun Certified Java Programmer)不可或缺的...
We show that an end-to-end deep learning approach can be used to recognize either English or Mandarin Chinese speech—two vastly different languages. Because it replaces entire pipelines of hand-...
《车辆:合成心理学的实验》是由Valentino Braitenberg所著的一本经典著作,它深入探讨了人工生命和智能机器人的概念,特别是在心理学视角下的机器行为。这本书的核心是Braitenberg小车,这是一种简单的机器人设计,...
The release of Java 9 has brought many subtle and not-so-subtle changes to the way in which Java programmers approach their code. The most important ones are definitely the availability of a REPL, ...
In the research of social networks, the structure holes usually refers to the vertices in the network at the key positions of information diffusion. The detection of such vertices is of great ...
"fxa-content-experiments-restored:fxa-content-server的实验"这个标题暗示了一个关于Firefox Accounts(fxa)内容服务器的恢复实验。这个项目可能涉及到对原有功能的改进、新功能的测试或者性能优化。 Firefox ...