QuickTime流媒体.docx

上传人:b****4 文档编号:27486511 上传时间:2023-07-02 格式:DOCX 页数:8 大小:23.54KB
下载 相关 举报
QuickTime流媒体.docx_第1页
第1页 / 共8页
QuickTime流媒体.docx_第2页
第2页 / 共8页
QuickTime流媒体.docx_第3页
第3页 / 共8页
QuickTime流媒体.docx_第4页
第4页 / 共8页
QuickTime流媒体.docx_第5页
第5页 / 共8页
点击查看更多>>
下载资源
资源描述

QuickTime流媒体.docx

《QuickTime流媒体.docx》由会员分享,可在线阅读,更多相关《QuickTime流媒体.docx(8页珍藏版)》请在冰豆网上搜索。

QuickTime流媒体.docx

QuickTime流媒体

QuickTime流媒体

  你看,问题是,在QTJ世界中大多数的我们都一直假定QTJ中的流媒体API已经损坏,我并不是想为此事而掩盖什么。

好的,我继续来通过各种各样的人通过不同的技术进行工作的掩盖获取去这样做,但是我不想再来一次。

此外,流媒体冲突的情况似乎特别的糟糕。

没有人能得到它的演示代码工作方式――thisposttothequicktime-javalist是令许多用户对获取苹果公司的AudioBroadcaster和DrawableBroadcaster演示工作方式绝望的典型。

让事情更糟糕,演示之一依靠一个在QTJ6.1版本中作为退回到原始的GUI提供的已经被取消的GUI预览组件类,提供组件只对Movies,MovieControllers和GraphicsImporters,而不是流式的Presentations,视频捕捉,或者某些图形美好得像来自多种资源“合成”制作。

所以,官方给出的演示它首先看起来是不会工作,和现在的关键类有冲突(如果在Java1.4中运行会抛出RuntimeExceptions异常)。

预测实际的流式内容和QTJ6.1看上去会非常糟糕。

    令我欣喜,甚至是有点吃惊的是,有报道称流媒体能够在QTJ6.1中工作。

在本文章中,我将介绍通过QTJ实现简单的网络广播的基础    需求    QuickTime的流媒体API,在Java中由只可在MacOS(Classic和OSX)中运行的包quicktime.streaming声明。

在QTJ中存在Windows版本的类,但是它们却不能工作。

但是,你可以使用Windows版本的QuickTime作为流媒体的客户端,如果在Java中运行并不是关键的,你可获取DarwinStreamingServer,一个开源项目可在Windows2000Server和2003Server上运行如同在Solaris9和RedHatLinux9上一样。

    使用QuickTime流媒体最简单的事情就是我在此说明的生动内容。

你需要至少一个音频输入设备,如一个内置的麦克风或者一个耳机。

当然,拥有一个QuickTime支持的摄像机,如一个iSight,将会更让人印象深刻。

    Streaming是什么,不是什么    给出了术语“流”的含义并不容易明确术语“Streaming”的正确含义。

例如,QuickTime长期支持一种“快速启动”的特征――如果QuickTime明确拥有足够的开始播放的资源并且不会用完目前下载速率下的资源一段录像能开始播放――那是一些用户将Streaming的一种形式弄错了。

自然的,这有它自己的优势:

容易创建并且确保了所有的包都到达了客户端。

但是真正的Streaming,换句话说,Streaming符合Internet工程工作小组(IETF)的标准,这是一个完全不同的问题,直到QuickTime5才被支持,并且直到QTJ6才支持Java。

    Streaming的形式允许服务器控制传输,但很难在实时中保证最优化运行。

客户端未下载潜在的大文件,这样的方法是独特的便利的直接广播。

事实上,QuickTime的流媒体使用两种“实时”的流媒体传输协议:

实时传输协议(RTP)来传输媒体数据包,实时流协议(RTSP)用于控制信息。

RTP使用潜在的有损UDP连接,所以所有的人都有意的忍耐再传输期间的包的丢失。

这就意味着客户端需要友好的操作未获取所有数据的视频帧或者音频例子。

更好的方法是通过基于TCP/IP的连接,它可以使用不确定的重试(也会因此需要一个不确定的时间)来获取丢失的包。

    Presentation和SDP文件    在QuickTime中,流媒体传输等同一个电影――一个电影可以有音轨和视轨,一个元数据的聚集将它们全都联系在一起,此表示会将一些多种的音频和视频流的元数据联系起来。

音频和视频你非常喜欢的流媒体种类也是值得关注的,自从某些其他的媒体类型(sprites,Flash内容)被QuickTime支持后并没有操作好失去的包,并不适合作为流媒体传播。

    你可能被建议去建立一个流媒体,你会需要创建一个Presentation并开始它。

但是现在呢?

最普遍的这样做的方法是创建一个会话描述协议(SDP)文件,将其放入静态工厂方法Presentation.fromFile()。

SDP文件以一种适当的简单的文本格式,由RFC2327和severalupdates所定义。

我发现这些都是早期的理论而不是实际操作,但是稍后让我们担心的是执行详细信息。

这是一个被一些Apple的流媒体使用的例子,在TimMonroe的QuickTimeToolkitVolumeTwo中:

    v=0  c=INIP4224.2.1.2/20/1  m=audio1000RTP/AVP12  m=video2000RTP/AVP101  a=rtpmap:

101H263-1998    以下是每一行的解释:

    ·v=0:

这是SDP的版本号。

在这里版本号是0表示在SDP中没有次要的号码。

  ·c=INIP4224.2.1.2/20/1:

这是提供在描述中使用的连接的信息。

INIP4表示是一个IPv4的网络地址。

224.2.1.2是地址(注意这是一个多点传输地址,所有许多的客户端能连接到广播),20是存在时间,1是临近使用的多点传输地址的数量。

  ·m=audio1000RTP/AVP12:

m=这一行定义了用于广播的流媒体。

在这里明显的是audio,发送经由到RTP到端口1000。

12在简单的QCELP音频中定义了有效负载类型。

这些在RFC3551中定义了。

  ·m=video2000RTP/AVP101:

这一媒体行定义了一个video媒体流,由RTP传输到端口2000。

有效负载类型为95,所以使用101表示在原始的RFC中视频格式没有给出负载类型,在SDP中替换它会被映射到一个众所周知的常量中。

  ·a=rtpmap:

101H263-1998:

这个完成键入在前一行指出的动态负载。

使用此类型,你会使用一个在96和127之间的值(本例中是101),然后用一个字符串命名此负载类型(H263-1998)。

    这当然好,但是当在我的例程序中使用它的时候,我只获得了一个视频流却没有声音。

所以,我使用了一个很不同的SDP,最初在QTJ的DrawableBroadcaster演示中出现。

是的,他们不赞同这么做:

    m=audio2656RTP/AVP96  c=INIP4239.60.60.60  a=rtpmap:

96x-qt  m=video2700RTP/AVP96  a=rtpmap:

96x-qt    这里最大的不同就是音频和视频都使用了相同的动态负载映射,这并不是针对一个真正的编码器,而是一般的x-qt。

在这里胜利的是你能在运行时间上挑选任一QuickTime的音频和视频编码器,而不是在SDP文件中强迫导致。

底侧是这些可以不是由非QuickTime客户端可分析的,反之使用十分标准的和/或者旧的编码器并且在SDP中指定他们使它更像其他的客户端(Real,JMF等)能够操作你的系统。

    这就是你的SDP文件。

现在不要加入一个Presentation。

    创建Presentation    我们的流媒体服务器程序调用LittleBroadcast,这并没有多少代码,只有不过140行。

在本文中,我将一步一步的进行,解释一般的部分,但提供其全部的清单。

在后面的Resources章节中有可用到一个.tar.gz文件,连同SDP文件和一个Ant构建文件。

    packagecom.mac.invalidname.qtjstreaming;importquicktime.*;  importquicktime.std.*;  importquicktime.util.*;  importquicktime.qd.*;  importquicktime.io.*;  importquicktime.streaming.*;  importquicktime.app.time.*;  importjava.io.*;importjava.awt.*;  importjava.awt.event.*;  publicclassLittleBroadcastextendsTaskingimplementsActionListener{    这是一长串典型的引入QuickTime,包括了使用其QDGraphics来提供一个摄像机画面以外的图形界面的qd,读取SDP文件的io,用于流媒体API的streaming,以及获得给予Presentation运行时间的有效任务的time。

最后一点,注意该类扩展直Tasking――提供周期性调用的task()。

本应用程序中,它用于不断的调用Presentation的idle()方法,并使其循环工作。

你在本书中学习到也就是Movies所需要的,但是此任务几乎一直都自动的为你所操作。

使用Presentation并不好运。

(或者为此事而捕获,但有些离开本主题了。

)    booleanbroadcasting=false;  publicstaticfinalintBROADCAST_WIDTH=176;  publicstaticfinalintBROADCAST_HEIGHT=144;  ButtonstartStopButton;  ButtonconfigButton;  Presentationpres;  intpresenterTimeScale=600;    这些是服务器的实例变量。

是一个用于指定当开始/停止按钮按下的时候做什么的标记。

下面是一对广播视频大小的常量,紧跟着是服务器GUI的按钮。

最后是一个Presentation对象,以及它的时间尺度。

(媒体的保持时间系统,一个600的时间尺度表示一秒种里有600个单位;600也是QuickTime中默认的。

)    publicstaticvoidmain(String[]args){  System.out.println("main");  try{  QTSession.open();  newLittleBroadcast();  }catch(QTExceptionqte){  qte.printStackTrace();  }  }    在这个main中并没有什么独特的地方。

我投入了所有的精力在构造函数上以防止为那些我需要的实例创建一个内部类。

如果你扩展本代码,你可能会发现这很有用。

    publicLittleBroadcast()throwsQTException{  System.out.println("LittleBroadcastconstructor");  QTFilefile=newQTFile(newFile("little.sdp"));  try{  MediaParamsmediaParams=newMediaParams();  mediaParams.setWidth(BROADCAST_WIDTH);  mediaParams.setHeight(BROADCAST_HEIGHT);  QDGraphicsmyGWorld=  newQDGraphics(newQDRect(  BROADCAST_WIDTH,BROADCAST_HEIGHT));  mediaParams.setGWorld(myGWorld);  PresParamspresParams=  newPresParams(presenterTimeScale,  QTSConstants.kQTSSendMediaFlag|  QTSConstants.kQTSAutoModeFlag|  QTSConstants.kQTSDontShowStatusFlag,  mediaParams);  pres=Presentation.fromFile(file,presParams);    构造函数的第一事是装载名为little.sdp的SDP文件。

但这并不是所有的都需要创建Presentation――在调用Presentation.fromFile()的时候需要服务器应用程序设置一些必要的参数。

首先,你要创建一个MediaParams对象,这样你能设置视频的高度和宽度。

您必须做的其它重要事是提供照相机一个图形界面,由QDGraphics创建MediaParams设置。

是的,名字是古怪的,因为QTJ设计员想注重与AWTGraphics对象的相似性,但得到或设置这样的对象的用途的所有方法是使用其本地API名字,GWorld。

最后,你为所有的Presentation创建一个PresParams来设置参数。

这采取一个有些任意的时标,一些算术上的行为标记彼此OR'ed,以及MediaParams。

可能的行为标记,都被定义在QTSConstants,包括:

    ·KQTSAutoModeFlag:

都使用默认值。

最重要地,这些使用默认值Sourcer,Presentation的来源,是从各种各样的输入装置执行获取的SequenceGrabber。

它还可能播放一个在磁盘上或是任意目录下的的QuickTime文件;稍后我将探讨这些问题。

    ·KQTDontShowStatusFlag:

不要创建一个会导致连接数和状态信息总被显示在客户端的流媒体状态处理程序。

    ·KQTSSendMediaFlag:

发送,不接收数据。

    ·KQTSReceiveMediaFlag:

接收,不发送数据。

    在SDP文件说明,参数,以及GWorld设置下,创建Presentation和Presentation.fromFile()。

    //findaudiostream      StreamaudioStream=null;  for(inti=1;i<=pres.getNumStreams();i++){  System.out.println("stream:

"+i+":

"+  pres.getIndStream(i));  StreamaStream=pres.getIndStream(i);  if(pres.hasCharacteristic(aStream,  StdQTConstants.audioMediaCharacteristic)){  audioStream=aStream;  break;  }  }  System.out.println("audioStream="+audioStream);  pres.setVolumes(audioStream,100,100);  System.out.println("createdpresentation,gworld=="+  pres.getGWorld()+",size=="+  mediaParams.getWidth()+"x"+  mediaParams.getHeight()+",streams=="+  pres.getNumStreams());    //*******这不是真正地必要的,但它将告诉你怎么通过Presentation游览来挑选各自的流媒体。

Presentation.getIndStream会由索引返回一个Stream(附注QuickTime索引都是基于1)。

它重复这些audioMediaCharacteristic请求查找音频流(对于录影,您就要请求visualMediaCharacteristic)。

这个实例在audioStream上为左右声道设置音量最大值为100。

    最后,println从Presentation和MediaParams转存一些有意义的元数据。

    配置Presentation    SettingsDialogsd=newSettingsDialog(pres);  System.out.println("Didsettings");  pres.preroll();  broadcasting=false;    这是设置presentation最后的步骤。

SettingsDialog存在用户以输入装置选择的音频和视频(二个流媒体SDP文件被指定在Presentation中)。

每个流媒体都可由一个压缩格式来定制(MPEG-4,SorensonVideo3,H.263,等)以及一个分包器(有时由压缩格式定义;可观察它是否随着压缩格式的改变而自动改变)。

这个GUI实例显示在图1。

     图像1.为一个PresentationSettingsDialog    在此图中,音频默认为计算机连线输入。

更改它为iSight,您需要点击Source按钮,提出的可选设备列表显示在图2上。

     图2.来源选择对话框    最后就是调用Presentation.preroll(),如同Movie.preroll(),提供Presentation一个机会预先分配资源以及准备好开始流媒体Presentation。

    提供一个控制GUI    //Makemonitorwindow  startStopButton=newButton("Start");  configButton=newButton("Configure");  startStopButton.addActionListener(this);  configButton.addActionListener(this);  FramemonitorFrame=newFrame("QTJStreaming");  monitorFrame.setLayout(newBorderLayout());  PanelbuttonPanel=newPanel();  buttonPanel.add(startStopButton);  buttonPanel.add(configButton);  monitorFrame.add(buttonPanel,BorderLayout.SOUTH);  monitorFrame.pack();  monitorFrame.setVisible(true);    这个为控制和配置Presentation设置了很小的GUI,提供基本的一个起始/停止键和一个配置按钮。

按钮作为一个ActionListener提交给this,意味着这个类将需要提供一个actionPerformed方法来处理按钮点击。

控制GUI的屏幕截图显示在图3。

     图3.监控/控制窗体    在这点上你也许会问一个有趣的问题:

"从什么时候我们开始关心使用GUI提供server?

"据推测,这是从ClassicMacOS开始的一个传统,它没有一个用命令行启动和传递参数的程序。

但此外,你通常会希望提供一个流媒体数据的预览,并且如果您有一个预览视窗,为什么会也没有一个配置的GUI?

    无论如何,这是大概的讨论,因为QTJ6.1不提供您能使用来预览的一个AWTComponent。

在有些方面有希望的是,QTFactory将得到一个新的超负荷为采用一个Presentation并且返回一个显示流媒体视频的Component的makeQTComponent。

它大概可能使用一些QuickDrawvoodoo而完全放弃Java的东西。

如果,在各task()中回调(参见下面)您采取GWorld被及早创建,转换它成Pict,并且作为一份唯一命名的文件,您会看见每一个都是不同的,意味GWorld每次都得到新数据。

所以如果您替换掉GWorld,改为能给AWTComponent在各通道上定义象素,您会有银幕上的预览。

何人有胆量如此做?

在quicktime-javalist上查看。

    详细资料    //addshutdownhandlertomakesurepresentation  //getsstopped  ThreadpresentationStopper=newThread(){  publicvoidrun(){  try{  pres.stop();  }catch(QTExceptionqte){}  }  };  Runtime.getRuntime().addShutdownHook(presentationStopper);    这个关闭异常分支确定Presentation在程序退出之前被终止。

这是重要的原因,象SequenceGrabber,Presentation愉快继续运行在您的应用程序退出之后,绑定一个端口,严重的循环,使用您的获取设备保留其它应用程序,等。

  }catch(QTExceptione){  e.printStackTrace();  System.exit(-1);  }  }    最后,构造函数捕捉并抛出所有的QTExceptions。

  publicvoidactionPerformed(ActionEventae){  System.out.println("actionPerformed");  try{  if(ae.getSource()==startStopButton){  if(broadcasting){  pres.stop();  stopTasking();  broadcasting=false;  startStopButton.setLabel("Start");  System.out.println("Stopped");  }else{  pres.start();  startTasking();  broadcasting=true;  startStopButton.setLabel("Stop");  System.out.println("Started");  }  }elseif(ae.getSource()==configButton){  newSettingsDialog(pres);  }  }catch(QTExceptionqte){  qte.printStackTrace();  }  }    这是非常直接的处理起始/终止和设置按钮。

如果点击的按钮是起始/终止,设置GUI就会调用在Presentation上的start()或stop(),开始或停止正在执行的任务(定期回调这个类的task()方法),为下按钮点击目的设置broadcasting标志,并且更改按钮标签。

如果用户点击了配置,它生成为Presentation新的SettingsDialog。

    publicsynchronizedfinalvoidtask()throwsQTException{  pres.idle(null);  }}    最后的这个方法实现了继承自Tasking的task()方法并且被在操作开始按钮调用s

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1