精华内容
下载资源
问答
  • 行业分类-设备装置-组成用于排列多媒体元素的标记的方法和装置
  • 多媒体

    千次阅读 2016-07-12 23:56:22
    本章将结合Web前端的发展历程和未来的发展前景详解现在HTML5中引入的多媒体技术HTML5的多媒体支持在HTML5规范出来之前,网页对视频和音频播放的支持基本上是靠Flash插件来实现,在HTML5之后,同文字和图片一样,音频...
    本章将结合Web前端的发展历程和未来的发展前景详解现在HTML5中引入的多媒体技术

    HTML5的多媒体支持

    在HTML5规范出来之前,网页对视频和音频播放的支持基本上是靠Flash插件来实现,在HTML5之后,同文字和图片一样,音频和视频直接变成HTML一系列规范中第一等公民,首先是JavaScript接口的支持,开发者可以使用JavaScript接口来方便的控制音视频的播放,实现例如播放、停止和记录等功能,其次HTML5中多媒体与图片一样可以用其他技术来进行操作,例如使用CSS技术来修改它的样式,例如3D变形,Web开发者可以将视频同Canvas2D或者WebGL结合在一起,而Flash插件中的视频是不能做到的。在HTML5中,对于多媒体的支持大致可以包括一下几个部分:第一是HTML的元素“video”,他用于音视频的播放;第二是“audio”,它用于单纯的音频播放;第三是可以将多个声音合成处理的WebAudio技术;第四是将照相机、麦克分与视频、音频和通信结合起来使用的最新技术WebRTC(网络实时通信),这使得Web领域使用视频对话和视频网络会议成为了现实。

    视频

    HTML5视频

    在HTML5规范定义中,Web开发者可以使用“video”元素来播放视频资源,其中视频涉及到视频编码格式,目前标准中包含了三种编码格式:Ogg、MPEG4和WebM,其中Ogg使用Theora作为视频编码格式和Vorbis作为音频编码格式,MPEG4使用H.264作为视频编码格式和AAC作为音频编码格式,WebM是有Google研发的标准,使用VP8作为视频编码格式和Vorbis作为音频编码格式。HTML提供了一些属性让开发者来使用JavaScript代码检查和操作视频,HTML5在“video”和“audio”元素之间抽象了一个基类元素“media”,结合它提供的能力,大致有一下几个方面的JavaScript编程接口,首先是资源加载和信息方面的接口,开发者可以通过特定接口检查游览器支持什么格式,如Metadata和海报(Poster)等,其次是缓冲(Buffering)处理,包括缓冲区域、进度等信息,然后是播放方面的状态,包括播放、暂停、终止等。再次是搜寻(Seeking)方面的信息,包括设置当前时间、“Timeupdate”事件,以及两个状态“Seeking”和“seeked”,最后是音量方面的设置,包括获取和设置音量、静音和音量变换等事件。

    WebKit基础设施

    WebKit提供了支持多媒体规范的基础框架,如音视频元素、JavaScript接口和视频播放等,根据WebKit的一般设计思想,它主要是提供标准的实现框架,而具体的实现有各个移植类来完成,因为音视频需要平台的支持,下图显示了各个类和它们之间的关系,也包括了Chromium移动的几个基础类:
    这里写图片描述
    首先WebKit是支持规范定义的编程接口,图中左侧的HTMLMediaElement和HTMLVideoElement类是DOM树中的节点类,包括众多的DOM接口,这些接口可以被JavaScript代码访问;其次是MediaPlayer和MediaPlayerClient两个类,MediaPlayer类是一个公共标准累,被HTMLMediaElement类使用来播放音频和视频,它本身支持提供抽象接口,具体实现依赖于不同的WebKit移植,同时一些播放器中的状态信息需要通知到HTMLMediaElement类,这里使用MediaPlayerClient类来定义这些有关状态信息的接口,HTMLMediaElement类需要继承MediaPlayerClient类并接收这些状态信息,根据前面的描述,规范要求将事件派发到JavaScript代码中,而这个实现在HTMLMediaElement类完成,然后是不同移植对MediaPlayer类的实现,其中包括MediaPlayerPrivateInterface类和WebMediaPlayerClientImpl类,前者是除了Chromium移植之外使用的标准接口也是一个抽象接口,由不同移植来实现,后者是Chromium移植的实现类,因为Chromium将WebKit复制出Blink之后就将MediaPlayerPrivateInterface类直接移除了,而在MediaPlayer类中直接调用它,WebMediaPlayerClientImpl类会使用Chromium移植自己定义的WebMediaPlayer接口类来作为实际的播放器,而真正的播放器则是在Chromium项目的代码中来实现,最后同渲染有关,这里就是之前介绍的RenderObject树和RenderLayer树,图中的RenderMedia类和RenderVideo类是RenderObject的子类,用于表示Media节点和Video节点。

    Chromium视频机制
    资源获取

    由于视频资源相对其他资源而言比较大,当用户播放视频的时候需要连续性播放以获得较好的体验,但是网络可能并不是移植都稳定和告诉,所以资源的获取对用户体验很重要,需要使用缓存机制或者其他机制来预先获取视频资源。下图是Chromium中的缓存资源类,BufferedDataSource类表示资源数据,它是一个简单的数据表示类,内存包含一个较小的内存空间(32K),实际的缓冲机制由BufferedResourceLoader类完成,在Chromium的设置中,最小的缓存空间是2M内存,最大的缓存空间是20M,并没有使用磁盘来缓存视频资源:
    这里写图片描述

    基础设施

    下图是chromium中支持硬件加速机制的视频播放所需基础设施的总体架构图,基于Chromium的多进程结构:
    这里写图片描述
    根据多进程架构的设计原则,Chromium的媒体播放器的实现应该在Renderer进程,而对于资源的获取则是在Browser进程,其中WebKit基础设施需要每个移植的具体实现,因此WebKit的Chromium移植部分提供了桥接接口,并且实现则是在Chromium代码中来完成,Chromium支持媒体播放器的具体实现涉及到不同的操作系统,目前Chromium在不同操作系统上实现的媒体播放器也不一样,下图显示了Chromium的基础类:
    这里写图片描述
    上半部分是WebKit和WebKit的Chromium移植中的相关类,下半部分是Chromium中使用硬件加速机制来实现视频播放的基础设施类,从做到分开来看,左边部分是播放器的具体实现类,右边部分是支持视频在合成器中工作的相关类。
    首先看下这些类和对象的创建过程,WebMediaPlayerClientImpl类是WebKit在创建HTMLMediaElement对象之后创建MediaPlayer对象的时候有MediaPlayer对象来创建的,当视频资源开始加载时,WebKit创建一个WebMediaPlayer对象,当然就是Chromium中的具体实现类WebMediaPlayerImpl对象,同时WebMediaPlayerClientImpl类也实现了WebMediaPlayerClient类,所以WebMediaPlayerImpl在播放视频的过程中需要向该WebMediaPlayerClient类更新各种状态,这些状态信息最终会传递到HTMLMediaElement类中,最终可能成为JavaScript事件,之后WebMediaPlayerImpl对象会创建一个WebLayerImpl对象,海湖同时创建VideoLayer对象,根据合成器的设计,Chromium还有一个LayerImpl树,在同步的时候,VideoLayer对象对应的VideoLayerImpl对象会被创建,之后Chromium需要创建VideoFrameProviderClientImpl对象,该对象将合成器的Video层同视频播放器联系起来并将合成器绘制一帧的请求转给提供视频内容的VideoFrameProvider类,这实际上是调用Chromium的媒体播放器WebMediaPlayerImpl,因为它是一个VideoFrameProvider类的实现子类,然后是Chromium如何使用这些类来生成和显示每一帧,当合成器调用每一层来绘制下一帧的时候,VideoFrameProviderClientImpl::AcquireLockAndCurrentFrame()函数会被调用,然后该函数调用WebMediaPlayerImpl类的GetCurrentFrame函数返回当前一帧的数据,VideoLayerImpl类根据需要会将这一帧数据上传到GPU的纹理对象中,当绘制完这一帧之后,VideoLayerImpl调用VidelFrameProviderClientImpl::PutCurrentFrame来通知播放器这一帧已绘制完成,并释放掉相应的资源,同时,媒体播放器也可以通知合成器有一些新帧生成,需要绘制出来,它会首先调用播放器的VideoFrameProvider::DidReceiveFrame()函数,该函数用来检查当前有没有一个VideoLayerImpl对象,如果有对象存在,需要设置它的SetNeedsRedraw标记位,这样合成器就知道需要重新生成新的一帧,最后是有关视频播放对象的销毁过程,有多种情况使Chromium需要销毁媒体播放器和相关的资源,如“video”元素被移除或者设置为隐藏等,这样视频元素对应的各种层对象以及WebKit和Chromium中的这些设施都会被销毁,WebMediaPalyerImpl类是多媒体播放器的具体实现类,在Chromium项目中,随着对Android系统的支持,Chromium既能支持左面系统也能支持移动系统,而这两者对视频和音频的支持很不一样,所以在不同系统上WebMediaPlayerImpl是如何实现和工作的也很不一样。

    桌面系统

    在桌面系统中,Chroimum使用了一套多媒体播放框架,而不是直接使用系统或者第三方库的完整解决方案,下图是Chromium在桌面系统上采用的多媒体播放引擎的工作模块和过程,这一框架称为多媒体管线化引擎,图中主要的模块四号多路分配器、音视频解码器、音视频渲染器,这些部分主要被WebMediaPlayerImpl类调用:
    这里写图片描述
    在处理音视频的管线化过程中,需要解码器和渲染其来分别处理视频和音频数据,它们均采用一种叫做“拉”而不是“推”的方式进行,也就是说有视频或者音频渲染器根据声卡或者时钟控制器,按需求来请求解码器解码数据,然后解码器和渲染器又向前请求“拉”数据,直到请求从视频资源文件读入数据,根据之前的多进程架构和Chromium的安全机制,整个管线化引擎虽然在Render进程中,但是由于Render进程不能访问声卡,所以渲染器需要通过IPC将数据或者消息同Browser进程通信,由Browser进程来访问声卡。虽然FFmpeg多媒体库拥有上述管线化的能力,但Chromium并不是将其作为一个黑盒来使用,而是分别使用FFmpeg的不同模块来实现自己的管线化引擎,目的是由自身来控制这一整个过程。Chromum使用并行FFmpeg解码技术,也就是说FFmpeg能够在帧这个层面上并行解码,当然不是针对所有格式的视频文件,目前主要针对H.264这个格式的视频。

    Android系统

    Chromium使用的是Android系统所提供的android.media.MediaPlayer类,也就是使用系统提供的音视频的渲染框架,在减少了管线化引擎带来复杂性的同时,也引入了一些额外的复杂问题。Android中的Chromium彻底抛弃了FFmpeg,直接使用系统自带的多媒体功能,因而,Android系统支持什么样的音视频格式,Chromium就只能支持什么样的相应格式,同时由于Android多媒体框架的优点使得视频元素仍然能够同HTML5中的其他技术一起工作。
    Ⅰ Android媒体播放框架
    Android中使用一个名为“MediaService”的服务进程来为应用程序提供音频和视频的播放功能,对于每一个使用多媒体播发功能的应用程序来说,“MediaService”服务是透明的,因为Android系统提供了“MediaService”的封装接口,这些接口隐藏了“MediaService”服务内部的细节,应用程序只是使用了简单的播放接口。MediaService能够为多个播放器提供服务,对于播放器来说,它的主要设置为两个参数,其一是输入的URL,第二是输出结果的绘制目标,下图描述了Android的播放器类和相关类:
    这里写图片描述
    当应用程序使用播放器的时候,Chromium可以创建MediaPlayer类的对象,调用setDataSource函数来设置待播放视频文件,并调用setSurface来设置视频结果绘制的目标-SurfaceTexture对象,这是一个GL的纹理对象,实际的解码和绘制是在MediaService进程中完成,这需要该纹理对象能够被多个不同的GL上下文对象所访问,支持多个GL上下文对象访问的GL纹理对象的类型GL_TEXTURE_EXTERNAL_OES,由此可以看到Chromium使用Android系统提供的音视频播放功能,表示Chromium使用Android系统的音视频解码器,所以Chromium是依赖与Android系统支持的音视频编码格式,而不像Chromium桌面版独立与操作系统的音视频编码格式。
    Ⅱ Chromium的视频解决方案
    在Android系统上,因为Chromium使用系统的多媒体框架,所以没有自己的管线化引擎,主要的工作是将Chromium的架构同Android多媒体框架结合起来以完成对网页中视频和音频的播放。下图是Chromium的Android系统上支持音频和视频播放的播放器主要类,因为Chromium的多进程架构,所以这里面包括两大部分,首先是右侧的Render进程的相关类,根据前面Chromium的桌面版上支持多媒体的相关类,可以看到WebKit::WebMediaPlayer类和WebMediaPlayerClient类来自于WebKit的Chromium移植,这两个类在所有平台上的定义都是一样的:
    这里写图片描述
    上图中右侧的Render进程,从上向下首先是WebMediaPlayerAndroid类,它同之前的WebMediaPlayerImpl类相似,表示的是Android系统上网页中的播放器,同video元素是一一对应的,与桌面系统不一样的是,Android系统使用RendeerMediaPlayerManager类来管理所有的WebMediaPlayerAndroid对象,因为一个网页中可能包含多个播放器实例,而WebMediaPlayerProxyAndroid则是同Browser进程来通信的,因为真正的Android播放器是在Browser进程中,主要请求Browser进程创建实际的Android的MediaPlayer类并设置播放文件的信息,左侧则是实际的播放器,在JNI(Java Native Interface)之上的是Java类,该播放器就是使用Android系统的android.media.MediaPlayer及其相关类来工作的,从下向上看首先是BrowserMediaPlayerManager类,该类不仅负责同Render进程的播放器类进行通信,而且自身又是一个播放器的管理类,它包含当前全部网页中的所有播放器对象,因为可能会有多个Render进程,所以只能通过播放器的唯一标记来区分这些播放器,BrowserMediaPlayerManager类管理称为MediaPlayerAndroid类的多个对象,而MediaPlayerAndroid的子类MediaPlayerBridge则是具体实现类,该子类能够与Java层中相同名字类通过JNI调用来控制Android系统的播放器类,以上的基本过程就是如何在网页中创建一个播放器,从右向左直到android.media.MediaPlayer对象被创建,同时Chromium获取网页中设置的视频文件的URL字符串然后传递并设置该URL字符串到Android的媒体播放器作为输入,对于输出Chrome使用SurfaceTexture对象作为输出目标,当Chromium调用WebMediaPlayerAndroid类的play函数时,该函数发起请求从Render进程到Browser进程来创建输出目标,也就是SurfeceTexture对象,下图描述了这个过程中使用到的主要类和之间的关系:
    这里写图片描述
    右侧的Render进程,最上面的StreamTexureFactoryImpl是创建目标结果存储空间的类,它被WebMediaPlayerAndroid类使用来创建所需要的结果存储对象StreamTexture,由于实际的对象是在Browser进程中创建的,所以Render进程中的StreamTextureProxy类就是一个代理类,最后的请求是通过GPUChannelHost类传递给Browser进程。在Browser进程中,负责处理上述请求的是GPU线程,该线程有StreamTextureManagerAndroid类处理所有创建StreamTexture对象的请求,StreamTexture对象的直接使用者是GPU线程,Render进程需要区分和标识这些StreamTexture对象,具体的方法是使用整形标记符来表示Browser进程中的各个StreamTexture对象,StreamTexture和StreamTextureManager是基础抽象类,在Android系统上,StreamTextureAndroid和StreamTextureManagerAndroid是实际的实现类,StreamTextureAndroid表示的是C++端的桥接类,它包含一个SurfaceTexture对象,该对象会在Java端创建一个android.graphics.SurfaceTexture对象,Chromium设置该对象到MediaPlayer对象作为播放器的输出目标,当视频播放器将解码后的结果写入到SurfaceTexture中后,播放器需要告诉Chromium游览器这一信息,Chroimum游览器需要执行合成操作而合成器在Render进程中,同之前创建SurfaceTexture对象的调用过程正好相反,这里需要使用回调机制,这就是Java层SurfaceTextureListener类的作用,该回调类注册Java层的回调对象到创建好的SurfaceTexture对象,当该对象被写入新的帧的时候,Chromium首先从Browse进程中的Java层将这一回调动作通过JNI到C++层的SurfaceTextureListener类的FrameAvailable函数,该函数经过StreamTextureAndroid和StreamTextureManagerAndroid类最后发送到Render进程,Render进程的调用过程如下:
    这里写图片描述
    网页中的视频播放有两种模式,其一是嵌入式模式,其二是全屏模式,这两种模式在解码后结果的处理上是不一样的,下图描述了全屏模式创建视频结果的绘制目标的相关类和过程:
    这里写图片描述
    当播放器进入全屏模式的时候,Chromium使用ContentVideoView类来管理,该类会创建一个SurfaceView对象并将对象传递给C++端的ContentVideoView类,因为统一时刻只有一个播放器是全屏模式,而且BrowserMediaPlayerManager管理所有的MediaPlayer对象,该管理类能够知道哪个对象是全屏模式,并将该SurfaceView对象设置到相应的MediaPlayer对象中去。

    字幕

    视频需要字母的支持,W3C组织已经开始定义支持字幕的“trace”元素,而字幕文件采用的格式是WebVTT格式,该格式看起来比较直观,简单的例子就是时间戳区间加上相应的字母文字,一下是使用字母的视频元素,因为语言的问题,每个“video”元素可以有多个“trace”元素,每个“trace”元素可以用来表示一个语言:

    <video controls="controls">
      <source src="video.mp4" type="video/mp4">
      <trace src="trace.vtt" kind="subtitles" srclang="en" label="English"></trace>
    </video>

    字幕文件的解释工作不依赖与各个WebKit移植,WebCore模块支持“track”元素解析、字幕文件解析等功能,下图是WebKit支持字幕功能的主要类:
    这里写图片描述
    “track”本身是一个HTML元素,因此它在DOM中有相应的节点元素,这就是HTMLTrackElement类,根据规范,“track“元素有一个重要的属性”src“,该属性指定了字幕文件的URL,WebKit使用LoadableTextTrack类来负责解析字幕文件并使用TextTrack类来存储解析后的结果,目前WebKit只支持WebVTT格式的字幕,使用WebVTTParser解析器来解释它们。
    下面一部分是提供接口,这里的接口是WebKit的Chromium移植所定义的接口不同额移植所定义的接口可能不一样,接口有两个类,WebInbandTextTrack和WebInbandTextTrackClient类,且是公开接口,WebInbandTextTrack类是有Chromium实现由WebKit调用,而WebInbandTextTrackClient则是有WebKit实现,实现类就是InbandTextTrackPrivateImpl,它实现WebInbandTextTrackClient的接口,然后后调用解析后的字幕并返回给Chromium。上述需要将一些消息传递给JavaScript代码,因为规范提供了JavaScript接口,开发者可以让JavaScript代码控制或者获取字幕信息,下面是Chromium中支持框架,下图描述了Chromium是如何将WebKit中的字幕信息桥接到多媒体管线化引擎中的:
    这里写图片描述
    在Chromium中,WebMediaPlayerImpl类创建继承类的对象,并设置WebInbandTextTrackClient对戏那个到该对象,该对象实际上是InTextTrack,它包含解析后的字幕内容,这样TextTrackImpl就可以获取字幕的内容,而TextTrack对象会被多媒体的管线化引擎多调用并渲染在视频的结果中。

    音频

    音频元素

    音频支持不仅指对声音的播放,还包括对音频的编辑和合成以及对乐器数字接口等的支持。

    HTML5 Audio元素

    在HTML5中使用”audio“元素来表示,同视频类似,HTML5标准中定义了三种格式:Ogg、MP3和Wav,因为视频内容通常包含音频数据,所以不仅仅是”audio“元素才会使用音频播放,同时,音频的字幕同视频一样,”track“元素也可以用在”audio“元素的字母中,用来显示字幕。

    基础设施

    音频的支持方面还是从输入和输出两个方面着手,对于输入,同视频类似,WebKit使用资源加载器先加载音频文件,之后建立音频元素、管线话引擎相关类,如MediaPlayer类,HTMLAudioElement和WebMediaPlayer类等,同视频不一样的是,视频的输出是GPU中的纹理对象,而音频需要输出到声卡,因此需要打开声卡设备,由于Chromium的沙箱模型机制,所以只能靠Browser进程来打开和关闭声卡设备,下图描述了多进程中如何将音频从Render进程传输到Browser进程,以及WebKit和Chromium中相应的基础设施:
    这里写图片描述
    首先看Render进程,从上玩下介绍如下:

    • WebKit::WebAudioSourceProvider和WebKit::WebAudioSourceProviderClient:最上面两个类是WebKit的Chromium移植接口类,前者提供音频原数据,也就是音频文件中的数据,这里采用“拉”的方式,也就是在ResourceLoader加载数据之后,当且仅当渲染引擎需要新的数据的时候,主动从加载后的数据中拉出数据来进行解码,“provideInput”函数由Chromium实现,由WebKit引擎调用,WebKit::WebAudioSourceProviderClient提供“setFormat”函数,用于让Chromium的媒体播放器设置频道数量、采样率等信息,WebAudioSourceProviderImpl是WebKit::WebAudioSourceProvider的实现类
    • AudioRendererImpl:该类是音频渲染器的实现,并使用AudioRenderSink将音频解码的结果输出到音频设备
    • AudioRendererSink:一个抽象类,用于表示一个音频终端店,能够接收解码后的音频信息,典型的例子就是音频设备
    • AudioRendererMixer:渲染器中的调用类
    • AudioOutputDevice:音频的输出设备,当然只是一个桥接层,因为实际的调用请求是通过下面两个类传送给Browser进程的
    • AudioOutputIPCImpl和AudioMessageFilter:前者将数据和指令通过IPC发送给Browser进程,后者就是执行消息发送机制的类

    下面是Browser进程,从下向上一次介绍:

    • AudioRendererHost:Browser进程端同Renderer进程通信并调度管理输出视频流的功能,对于每个输出流,有相应的AudioOutputStream对象对应,并且通过AudioOutputController类处理和优化输出
    • AudioOutputController:该类控制一个AudioOutputStream对象并提供数据给该对象,提供play、pause、stop等功能,因为它控制这音频的输出结果
    • AudiOutputStream和AudioOutputProxy:音频的输出流类和其子类,AudioOutputProxy是一个使用优化算法的类,它仅在Start()和Stop()函数之间打开音频设备,其他情况下音频设备都是关闭的,AudioOutputProxy使用AudioOutputDispatcher打开和关闭实际的物理音频设备
    • AudioOutputDispatcher和AudioOutputDispatcherImpl:控制音频设备的接口类和实际实现类

    由此可以得出当WebKit和Chromium需要输出解码后的音频数据是,通过从侧自上向下、左侧自下向上的过程,然后使用共享内存的方式将解码后的数据输出到实际的物理设备中。

    Web Audio

    Audio元素能够用来播放各种格式的音频,但是HTML5还拥有更强大的能力来处理声音,这就是Web Audio,该规范提供了搞层次的JavaScript接口,用来处理和合成声音,整个思路就是提供一张图,giant图中的每个节点称为AudioNode,这些节点构成处理的整个过程,虽然实际的处理是使用C/C++来完成,但是Web Audio也提供了一些接口来让Web前端开发者使用JavaScript代码来调用C/C++的实现,WebAudio对于很多Web应用很有帮助,例如它呢能够帮助开发者设计和实时合成出各种音效,根据W3C的Web Audio规范的定义,整个处理过程可以看成一个拓扑图,该图有一个或多个输入源,称为Source节点,中间的所有点都可以看成各种处理过程,它们组成复杂的网,图中有一个最终节点称为“Destination”,它可以表示实际的音频设备,每个图只能有一个该类型的节点,上述图中的所有节点都是工作在一个上下文中,称为AudioContext:
    这里写图片描述
    对于Source1节点,它没有输入节点,hi有输出节点,对于中间的这些节点,它们既包含输入节点也包含输出节点,而对应Destination节点,它只有输入节点,没有输出节点,图中的其他节点都是可以任意定义的,这些即诶但每一个都可以代表一种处理算法,开发者可以根据需要设置不同的节点以处理出不同效果的音频输出,中间这些节点有很多类型,它们的作用也不一样,这些节点的实现通常由C或者C++代码来完成以达到高性能,当然这里提供的接口都是JavaScript接口。Web Audio的绝大多数处理都是在WebKi中完成的,而不需要Chromium过多的参与,除了输入源和输出结果到实际设备,其他同前面的多媒体数据源是一致的。下图的上半部分主要是支持规范中的标准接口,例如AudioBufferSourceNode、AudioContext、DestinationNode和OscillatorNode等类,它们对应上图中规范定义的接口,还有众多类没有绘出,以下重点关注OsicllatorNode类,它需要对音频数据进行大量计算,包括向量的加法、乘法等,同时该节点类需要使用PeriodicWave来计算周期性波形,这里面需要使用到FFT(快速傅立叶变换)算法,因为音频的及时性,网页对性能有非常高的要求,对于Chromium移植,不同平台采用不同的加速算法,在Windows和Linux中使用FFMpeg中的高性能算法,在Android上使用OpenMax DL提供的接口来加速,而在Mac上又是不同的算法:
    这里写图片描述

    MIDI和Web MIDI

    MIDI是一个通信标准,它是电子乐器之间,以及电子乐器与电脑之间的统一交流协议,用以确定电脑音乐程序、合成器和其他电子音响设备互相交换信息与控制信息的方法,同其他的声音格式不同,MIDI不是记录采样信息,而是记录乐器的演奏指令。音频也可以以MIDI格式来存储,但是该格式不是HTML5的标准,所以游览器并没有内置支持它们,为了让MIDI格式的音乐播放出来,可以使用JavaScript代码,这就是MIDI.js,它使用上面提到的WebAudio技术和Audio元素来实现音乐的播放。Web MIDI规范中定义了输入和输出的MIDI设备,如MIDIInput和MIDIOutput,通过MIDIAccess接口分那会到所有枚举的输入和输出设备,MIDIInput主要包含一个接收指令的函数“onMessage”,而MIDIOutput包含一个发送指令的函数“send”,而发送的数据指令就是MIDIEvent,该指令包含一个时间戳和数据,WebKIt和Chromium对于Web MIDI的支持主要包括三个部分,第一是加入JavaScript的绑定,第二是将对MIDI接口的支持从Redner进程桥接到Browser进程,第三是Chromium的具体实现。

    WebRTC

    WebRTC(Web Real Time Communication)技术,中文全称为Web实时通信技术,是一种提供实时视频通信的规范,目前是W3C推荐的规范。

    原理和规范

    构建网络视频通信需要三种类型的技术,其一是视频,其二是音频,其三是网络传输

    • 音视频输入和输出设备:同音视频播放不同,因为它们只是需要输出设备,这里需要输入和输出设备,同时输入使用getUserMedia技术,而输出基本上可以采用音视频播放的基本框架
    • 网络连接的建立:因为视频通信需要不停的传送大量数据,所以需要建立一种可靠的网络连接来让各个参与方传输数据
    • 数据捕获、比那吗和发送:当用户打开设备之后,需要捕获这些数据并对它们进行编码,因为原始数据的数据量太大,然后需要将编码后的数据通过连接传输出去
    • 数据接收、解码和显示:接收来自其他方的数据流并进行解码,然后显示出来,这个跟播放媒体文件的需求比较类似

    下图结合主要组成部分构建一个比较完整的音视频通信过程:
    这里写图片描述
    下面了解一下规范中如何针对上面的描述来定义相应的JavaScript接口,根据W3C推荐的规范草案,主要包括一下几个部分:

    • Media Capture and Streams 规范和WebRTC对它的扩展,这个主要是依赖摄像头和麦克风来捕获多媒体流,WebRTC对它进行扩展,使得多媒体流可以满足网络传输用途,也就是“video”元素可以来源与多媒体流而不仅仅是资源文件
    • 点到点的连接,也就是规范中的RTCPeerConnection接口,它能够建立端到端的连接,两者直接通过某种方式传输控制信息,至于方式并没有进行规定
    • RTCDataChannel接口,通过该接口,通信双方可以发哦是那个任何类型的信息,例如文本或者二进制数据,这个不是必须的,不过这个功能极大的方便了开发者,其主要思想来源与WebSocket
    WebKit和Chromium的实现

    首先了解下WebRTC技术的内部框架和功能模块,下图主要包括三大方面,即语言、视频和传输,它们三个构成WebRTC的主要组成部分,其中iSAC(internet Speech Audio Codec)和iLBC(internet Low Bitrate Codec)是两种不同的音频编码格式,是为了适应互联网的语言传输要求而存在的,前者是针对带宽比较大的情况,后者是针对带宽较小的情况,其中VP8同样是Google提供免费视频格式,传输部分主要是加入了对前面协议的支持模块,在会话管理中,主要使用一个开源项目libjingle来管理,下面部分主要是WebRTC工作时依赖的下层功能的接口,在Chromium游览器中,它会提供相应接口和功能给WebRTC使用:
    这里写图片描述
    上图是WebRTC开源项目的架构图,在Chromium中,通常使用WebRTC项目来完成WebRTC规范的功能,并使用libjingle项目来建立点到点的连接,所有Chromium主要的目的是将WebRTC和libjingle的能力桥接到游览器中来,先看WebRTC规范中建立连接所需要的相关的技术设备,下图是WebKit、Chromium及Chromium中使用libjingle的类的层次图:
    这里写图片描述
    基础设备分成三个层次,首先是WebKit,该部分最上面的类是RTCPeerConnection,该类是对WebRTC连接的接口类,实际上它是从规范中定义的RTCPeerConnection接口文件生成的基本框架,实际真正和JavaScript引擎打交道还需要一个桥接类,该桥接类包含一个实际实现的连接类句柄m_peerHandler,它是这个连接所包含的本地多媒体流和远端对方的多媒体流,场景大致是首先WebKit需要将本地的多媒体流收集起来,通过连接传输给对方,本地可以选择是否通过“video”播放,同时需要接收从对方传输过来的多媒体流,接下来是WebKit的实现类,该类能够满足RTCPeerConnection的功能要求,但是它需要通过不同移植的实现才能完成,因为本身WebKit的WebCore并没有这样的能力,在WebKit的Chromium中同样定义了两个类WebRTCPeerConnectionHandler和WebRTCPeerCOnnectionHandlerClient,根据WebKit的类名定义方式,前者是需要Chroimum来实现,后者则由Chromium调用,并由WebKit来实现,这里主要是应用连接事件的监听函数,所以WebKit能够将它们传递给JavaScript引擎,之后是Chromium的实现类,RTCPeerCOnnectionHandler类继承自WebKit的Chromium移植的接口类,并做了具体的实现,也就是content::RTCPeerConnectionHandler,它同时集成自PeerConnectionHandleBase类,而该类拥有了支持建立连接所需的能力,当然它是依赖于libjingle项目提供的连接能力,libjingle提供了建立和管理连接的能力,支持透过NAT和防火墙设备、代理等建立连接,libjingle不仅支持点到点的连接,也支持多用户连接,同时还包含了连接所使用的MediaStream接口,这是因为Chromium本身不直接使用WebRTC项目提供的接口,而是调用libjingle来建立连接,并使用libjingle提供的MediaStream接口,而libjingle本身则会使用WebRTC项目的音视频处理引擎。
    下面总结下多媒体流,先看下WebKit是怎样支持getUserMedia这个接口的,下图描述了WebKit,以及WebKit的Chroimum移植中所定义的接口:
    这里写图片描述
    最上层的是WebKit支持多媒体流编程接口提供的具体实现类,如NavigatorMediaStream类,而直接同V8JavaScript引擎桥接的类是V8NavigatorUserMediaSuccessCallback,它是一个绑定类,因为getUserMedia接口主要是返回一个MediaStream对象,而MediaStream类可以提供众多访问数据流的接口,而连接的目的就是需要将MediaStream对应的多媒体流传输出去,UserMediaRequest类负责请求创建一个MediaStream对象,在WebKit的Chromium移植中,定义WebUserMediaClient为一个接口类,Chromium需要新建子类来实现这一功能,这就是Chromium中的MediaStreamImpl类。WebKit使用MediaStreamRegistry类来注册和管理对应的类,管理类根据ID信息来识别各个多媒体数据流,在接口层中,Chromium移植使用WebMediaStream类来表示多媒体流,使用WebMediaStreamRegistry类来表示注册管理类,下面的问题是MediaStream接口需要提供各种事件给网页,因为很多实际的工作是在Chromium中来完成的,所以MediaStreamImpl会将这些事件从Chromium传递给WebKit,同时因为Chromium的多进程和沙箱模型,一些工作需要在Browser进程中完成,下图是所描述的跨进程的基础设施:
    这里写图片描述
    IPC左侧部分是Browser进程中的两个主要类,分别是消息处理类和MediaSrteam的管理类,该管理类知道MediaStream对应的网页是什么,并将事件(如创建和销毁等)传回Render进程,右侧是消息派发类,主要帮助MediaStreamImpl类来完成与Browser进程相关的MediaStream消息的传递,MediaStream可以表示本地的多媒体流也可以表示远端的多媒体流,对于本地的多媒体流,需要音频和视频的捕获机制,同时使用上面建立的连接传输给远端,对于远端的多媒体流,需要使用连接来接收数据,并使用到音频和视频的解码能力,下面分成四个部分来分别介绍,首先是音频的捕获机制,下图描述了该机制使用的主要类,当我那工业需要创建多媒体流的时候,MediaStreamImpl会创建音频捕获类WebRtcAudioCapturer类,因为捕获音频需要音频输入设备,所以使用AudioDeviceFactory工厂类创建一个逻辑上的AudioInputDevice对象,另外一个重要的类是WebRtcAudioDeviceImpl,用来表示音频的设备,该类继承自WebRtcAudioDeviceNotImpl类,这其实是继承自libjingle和WebRTC项目中的抽象接口的一个桥接类,用来表示它们需要的音频设备,包括输入鼠辈,同样因为Render进程不能访问音频输入设备,所以需要IPC来完成一个功能,Browser进程的AudioInputController会控制和访问设备,而AudioInputDeviceManager可以管理和控制所有输入设备:
    这里写图片描述
    其次是处理远程多媒体流中的音频解码和播放功能,下图是Chromium处理远端音频流所需要的一些主要类及关系图,这里不涉及连接如何接收传输的数据,因为Chromium是使用libjingle和WebRTC项目来完成连接的功能,Chromium使用WebRtcAudioRender类来完成音频渲染,该桥接类会被WebMediaPlayer作为渲染音频的实现类,其作用主要是将MediaStream的数据同实际的音频渲染类结合起来:
    这里写图片描述
    再次是从视频输入设备请求捕获本地视频流,下图是该功能依赖的一些主要类:
    这里写图片描述
    实线右侧Render进程中的设施,同样是MediaStreamImpl类发起,有辅助工厂类MediaStreamDependencyFactory帮助创建一个RtcVideoCapaturer,用来获取视频,该类有两个作用,其一是是吸纳linjingle和WebRTC项目中的接口类,因为需要薯片输入的实现,这个同音频部分类似,另外就是将调用请求交割一个代理类来完成(RtcVideoCaptureDelegate类),分别是管理类VideoCaptureImplManager和视频捕获类VideoCaptureImpl,并包括一个发送消息到Browser进程的辅助类,在Browser进程使用控制类VideoCaptureController来获取VideoCaptureDevice,该类会使用摄像头等视频输入设备。最后是处理远端多媒体流中的视频解码和播放功能,当MediaStreamImpl对象接收到远端的多媒体流之后,它会使用WebRTC来会视频数据进行解码,因为可以使用硬件来解码,提供了处理的性能:
    这里写图片描述
    把WebRTC整个过程综合起来分析如下图,可以有一种更为整体和直观的感受:
    这里写图片描述

    展开全文
  • Android多媒体开发

    万次阅读 2016-10-02 12:38:29
    多媒体(duō méi tǐ) 的英文单词是Multimedia,它media和multi两部分组成。一般理解为多种媒体的综合 多媒体是计算机和视频技术的结合,实际上它是两个媒体;声音和图像,或者用现在的术语:音响和电视。 ...

    Android多媒体开发系列文章

    1. Android多媒体开发:录音机
    2. Android多媒体开发:照相机
    3. TextureView+MediaPlayer实现在线短视频播放
    4. Android多媒体开发:第三方框架

    一、什么是多媒体

    • 多媒体(duō méi tǐ) 的英文单词是Multimedia,它由media和multi两部分组成。一般理解为多种媒体的综合

    • 多媒体是计算机和视频技术的结合,实际上它是两个媒体;声音和图像,或者用现在的术语:音响和电视。

    • 多媒体(Multimedia),在计算机系统中,组合两种或两种以上媒体的一种人机交互式信息交流和传播媒体

    • 使用的媒体包括文字、图片、照片、声音 (包含音乐、语音旁白、特殊音效)、动画和影片,以及程式所提供的互动功能

    • 多媒体是超媒体(Hypermedia)系统中的一个子集,而超媒体系统是使用超链接 (Hyperlink)构成的全球信息系统

    • 全球信息系统是因特网上使用 TCP/IP 协议和 UDP/IP 协议

    二、音乐播放器

    Android 官方提供了MediaPlayer 核心类,用于播放音乐,其状态流程如下图所示。MediaPlayer 必须严格按照状态图操作,否则就会出现错误,这些错误都是底层抛出,严格按照状态图操作的话一般就不会出问题。

    MediaPlayer,原生的API,可以播放音视频,但是支持的格式比较少,实际开发中用的比较少,但是还是很有必要学习,熟悉API,因为Vitamio框架的API大部分跟原生的API是一样的

    1、MediaPlayer使用流程图

    这里写图片描述

    2、MediaPlayer核心方法

    方法说明
    create()播放本地res/raw/目录下的资源
    reset()重置为初始状态
    setAudioStreamType()设置音乐格式,例如:AudioManager.STREAM_MUSIC
    setDataSource()设置音频源,本地网络资源均可
    prepare()播放前的准备工作
    prepareAsync()异步进行准备工作,播放网络音频的时候使用
    start()开始或恢复播放
    pause()暂停播放
    stop()停止播放
    release()释放资源
    getDuration()获取音乐最大长度(毫秒单位)
    getCurrentPosition()获取当前的播放进度
    seekTo()拖拽进度
    setDisplay()设置输出画面
    setOnPreparedListener()设置准备监听

     
    为了演示MediaPlayer 的使用,我们需要提前准备一个mp3 文件放到sdcard 中

    需求:制作一个播放器,能够播放/暂停/停止音乐文件,并且添加一个SeekBar(可以拖拽的ProgressBar),当音乐播放时SeekBar 也会不断的跟新当前的进度,当用户拖动SeekBar 时可以更改播放的进度

    这里写图片描述

    布局文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="play"
                android:text="播放"/>
    
            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="pause"
                android:text="暂停"/>
    
            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:onClick="stop"
                android:text="停止"/>
    
        </LinearLayout>
    
        <SeekBar
            android:id="@+id/sb"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    

    代码实现

    public class MainActivity extends Activity implements OnSeekBarChangeListener {
    
            private SeekBar     sb;
            private MediaPlayer player;
            private int         duration;
            // 播放器的几个状态
            private static final int PLAYING  = 1;// 播放状态
            private static final int PAUSING  = 2;// 暂停状态
            private static final int STOPPING = 3;// 停止状态
            private volatile     int CURRENT  = 0;// 当前状态
            private Timer timer;
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                sb = (SeekBar) findViewById(R.id.sb);
                //设置拖动监听
                sb.setOnSeekBarChangeListener(this);
            }
    
            //播放
            public void play(View view) {
                if (player != null) {
                    if (CURRENT == PLAYING) {
                        Toast.makeText(this, "音乐已经在播放了", Toast.LENGTH_SHORT).show();
                        return;
                    } else if (CURRENT == PAUSING) {
                        player.start();
                        CURRENT = PLAYING;
                        return;
                    }
                }
                try {
                    //创建一个播放器对象
                    player = new MediaPlayer();
                    //给播放器设置音乐路径
                    player.setDataSource("/mnt/sdcard/test.mp3");
                    //设置音乐格式
                    player.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    //准备
                    player.prepare();
                    //获取音乐最大长度(毫秒单位)
                    duration = player.getDuration();
                    //给SeekBar 设置最大值
                    sb.setMax(duration);
                    //音乐开始播放
                    player.start();
                    //设置当前的状态为播放
                    CURRENT = PLAYING;
                    if (timer == null) {
                        //创建定时器
                        timer = new Timer();
                    }
                    /**
                     * 参数1:匿名内部类,相当于Runnable 类
                     * 参数2:第一次延时多长时间(毫秒)后执行,0 则代表立即执行
                     * 参数3:每隔多长时间(毫秒)执行一次
                     */
                    timer.schedule(new TimerTask() {
    
                        @Override
                        public void run() {//该方法每1 秒被调用一次
                            if (CURRENT == PLAYING) {
                                runOnUiThread(new Runnable() {
    
                                    @Override
                                    public void run() {
                                        //双重判断,尽可能避免线程问题,因为该段代码时在主线程中的,
                                        //第一次判断是在子线程中进行的
                                        if (player != null && CURRENT == PLAYING) {
                                            //获取当前的播放进度
                                            int currentPosition = player.getCurrentPosition();
                                            //设置给SeekBar
                                            sb.setProgress(currentPosition);
                                        }
                                    }
                                });
                            }
    
                        }
                    }, 0, 1000);
    
                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(this, "音乐播放失败" + e, 0).show();
                }
            }
    
            /**
             * 暂停
             */
            public void pause(View view) {
                if (player != null && CURRENT == PLAYING) {
                    player.pause();
                    CURRENT = PAUSING;
                }
            }
    
            /**
             * 停止
             */
            public void stop(View view) {
                if (player != null) {
                    if (CURRENT == PLAYING || CURRENT == PAUSING) {
                        CURRENT = STOPPING;
                        //取消定时器
                        timer.cancel();
                        timer = null;
                        player.stop();
                        player.reset();
                        player.release();
                        player = null;
                        sb.setProgress(0);
                    }
                }
            }
    
            /*
            * 拖动过程中回调多次
            */
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (player == null) {
                    sb.setProgress(0);
                } else {
                    player.seekTo(progress);
                }
            }
    
            /*
            * 开始拖动前回调一次
            */
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                if (player == null) {
                    Toast.makeText(this, "音乐播放器还未开始", Toast.LENGTH_SHORT).show();
                }
            }
    
            /*
            * 结束拖动后回调一次
            */
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
    
            @Override
            protected void onDestroy() {
                super.onDestroy();
                stop(null);
            }
    
        }

    3、播放本地res/raw/目录下的资源

    MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
    mediaPlayer.start(); // no need to call prepare(); create() does that for you

    4、播放本地URI资源

    Uri myUri = ....; // initialize Uri here
    MediaPlayer mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    mediaPlayer.setDataSource(getApplicationContext(), myUri);
    mediaPlayer.prepare();
    mediaPlayer.start();

    5、播放网络资源

    String url = "http://........"; // your URL here
    MediaPlayer mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    mediaPlayer.setDataSource(url);
    mediaPlayer.prepare(); // might take long! (for buffering, etc)
    mediaPlayer.start();

    6、异步准备

    String url = "http://........"; // your URL here
            MediaPlayer mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setDataSource(url);
            mediaPlayer.prepareAsync();
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mp.start();
                }
            });

    7、在后台Service异步执行播放任务

    public class MyService extends Service implements MediaPlayer.OnPreparedListener {
        MediaPlayer mMediaPlayer;
        private static final String ACTION_PLAY = "com.example.action.PLAY";
        MediaPlayer mMediaPlayer = null;
    
        public int onStartCommand(Intent intent, int flags, int startId) {
            ...
            if (intent.getAction().equals(ACTION_PLAY)) {
                mMediaPlayer = ... // initialize it here
                mMediaPlayer.setOnPreparedListener(this);
                mMediaPlayer.prepareAsync(); // prepare async to not block main thread
            }
        }
    
        /** Called when MediaPlayer is ready */
        public void onPrepared(MediaPlayer player) {
            player.start();
        }
    }
    
     public void initMediaPlayer() {
            // ...initialize the MediaPlayer here...
    
            mMediaPlayer.setOnErrorListener(this);
        }
    
        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            // ... react appropriately ...
            // The MediaPlayer has moved to the Error state, must be reset!
        }
    

    8、在手机睡眠时使用唤醒锁

    mMediaPlayer = new MediaPlayer();
    // ... other initialization here ...
    mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
    
    //wifi锁
    WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
        .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");
    
    wifiLock.acquire();
    
    //当暂停,不再需要网络时释放锁
    wifiLock.release();

    9、在前台服务运行播放任务

    这里写图片描述 这里写图片描述

    String songName;
    // assign the song name to songName
    PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
                    new Intent(getApplicationContext(), MainActivity.class),
                    PendingIntent.FLAG_UPDATE_CURRENT);
    Notification notification = new Notification();
    notification.tickerText = text;
    notification.icon = R.drawable.play0;
    notification.flags |= Notification.FLAG_ONGOING_EVENT;
    notification.setLatestEventInfo(getApplicationContext(), "MusicPlayerSample",
                    "Playing: " + songName, pi);
    startForeground(NOTIFICATION_ID, notification);

    10、处理音频焦点

    AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
        AudioManager.AUDIOFOCUS_GAIN);
    
    if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        // could not get audio focus.
    }

    requestAudioFocus() 方法的第一个参数是一个 AudioManager.OnAudioFocusChangeListener,当任何时候音频焦点发生变化的时候,会回调 OnAudioFocusChangeListener的onAudioFocusChange()方法

    class MyService extends Service
                    implements AudioManager.OnAudioFocusChangeListener {
        // ....
        public void onAudioFocusChange(int focusChange) {
            // Do something based on focus change...
        }
    }

    11、播放完毕时手动释放资源

    public class MyService extends Service {
       MediaPlayer mMediaPlayer;
       // ...
    
       @Override
       public void onDestroy() {
           if (mMediaPlayer != null) mMediaPlayer.release();
       }
    }

    三、Mp3文件简介

    ID3

    一般是位于一个mp3文件的开头或末尾的若干字节内,附加了关于该mp3的歌手,标题,专辑名称,年代,风格等信息,该信息就被称为ID3信息,ID3信息分为两个版本,v1和v2版。 其中:v1版的ID3在mp3文件的末尾128字节,以TAG三个字符开头,后面跟上歌曲信息。 v2版一般位于mp3的开头,可以存储歌词,该专辑的图片等大容量的信息。

    V1与V2

    • ID3V1记录在MP3文件的末尾,长度固定
    • ID3V2就记录在MP3文件的首部。 ID3V2一共有4个版本,但流行的播放软件一般只支持第3版,既ID3v2.3。
    • 对ID3V2的操作比ID3V1要慢。而且ID3V2结构比ID3V1的结构要复杂得多,但比ID3V1全面且可以伸缩和扩展。

    四、视频播放器

    1、SurfaceView

    SurfaceView提供了一个绘画的界面,你可以控制该界面的格式和大小,SurfaceView 负责在屏幕正确位置安置一个界面。SurfaceView的其中一个目的,是为了在子线程渲染屏幕,但需要注意几点

    • 所有SurfaceView 和SurfaceHolder.Callback 的方法,都必须在主线程调用
    • 必须保证绘制线程,必须在SurfaceView 有效的情况下才能使用,也就是在SurfaceHolder.Callback.surfaceCreated() 和SurfaceHolder.Callback.surfaceDestroyed()之间调用

    SurfaceView是View的子类,等同于TextView、ImageView等一系列控件。核心功能可以通过子线程进行界面的绘制,绘制需要注意的内容:

    所有SurfaceView和SurfaceHolder.Callback的方法都应该在UI线程里调用,一般来说就是应用程序主线程。渲染线程所要访问的各种变量应该作同步处理。

    由于surface可能被销毁,它只在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的surface

    • 双缓冲技术:内存中有两个画布,A画布显示至屏幕,B画布在内存中绘制下一帧画面,绘制完毕后B显示至屏幕,A在内存中继续绘制下一帧画面
    • SurfaceView 是双缓冲机制,一个用来缓冲数据,另一个用来展现数据,可以提高数据展示的速度,单缓冲需要先加载数据再去展示数据,但是双缓冲在展示第一个页面数据的时候已经把第二个页面的数据加载好了
    • 对画面的实时更新要求较高,重量级组件,可见时才创建
    • SurfaceView一旦不可见,就会被销毁,一旦可见,就会被创建,销毁时停止播放,再次创建时再开始播放
    • 播放视频也是用MediaPlayer,不过跟音频不同,要设置显示在哪个SurfaceView

    2、使用MediaPlayer+SurfaceView 播放视频

    在该节中,视频播放依然使用MediaPlayer 类,为了方便演示,我们直接使用本文中创建的工程,只需在布局文件添加SurfaceView 控件即可

    布局文件

    <RelativeLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin"
            tools:context=".MainActivity">
    
            <SurfaceView
                android:id="@+id/sv"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
    
        </RelativeLayout>

    实现代码

    public class MainActivity extends Activity {
            private MediaPlayer player;
            static int currentPosition;
            private SurfaceView sv;
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
    
                sv = (SurfaceView) findViewById(R.id.sv);
                //拿到surfaceview的控制器
                final SurfaceHolder sh = sv.getHolder();
    
                //      Thread t = new Thread(){
                //          @Override
                //          public void run() {
                //              try {
                //                  sleep(200);
                //              } catch (InterruptedException e) {
                //                  e.printStackTrace();
                //              }
                //              runOnUiThread(new Runnable() {
                //                  @Override
                //                  public void run() {
                //                      MediaPlayer player = new MediaPlayer();
                //                      player.reset();
                //                      try {
                //                          player.setDataSource("sdcard/2.3gp");
                //                          player.setDisplay(sh);
                //                          player.prepare();
                //                          player.start();
                //                      } catch (Exception e) {
                //                          e.printStackTrace();
                //                      } 
                //                      
                //                  }
                //              });
                //              
                //          }
                //      };
                //      t.start();
                //SurfaceView是重量级组件,可见时才会创建
                //给SurfaceHolder设置CallBack,类似于侦听,可以知道SurfaceView的状态
                sh.addCallback(new Callback() {
    
                    //surfaceView销毁时调用
                    @Override
                    public void surfaceDestroyed(SurfaceHolder holder) {
                        //每次surfaceview销毁时,同时停止播放视频
                        if(player != null){
                            currentPosition = player.getCurrentPosition();
                            player.stop();
                            player.release();
                            player = null;
                        }
                    }
                    //surfaceView创建时调用
                    @Override
                    public void surfaceCreated(SurfaceHolder holder) {
                        //每次surfaceView创建时才去播放视频
                        if(player == null){
                            player = new MediaPlayer();
                            player.reset();
                            try {
                                player.setDataSource("sdcard/2.3gp");
                                player.setDisplay(sh);
                                player.prepare();
                                player.start();
                                player.seekTo(currentPosition);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    //surfaceView结构改变时调用
                    @Override
                    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    
                    }
                });
            }
        }

    使用VideoView 播放视频

    VideoView 跟MediaPlayer 相比播放视频步骤要简单的多,因为VideoView 原生提供了播放,暂停、快进、快退、进度条等方法。使用起来要方便的很多

    1、设置布局文件,布局文件比较简单,因此这里只给你VideoView 标签

     <VideoView
     android:id="@+id/vv"
     android:layout_width="match_parent"
     android:layout_height="match_parent" />

    2、设置VideoView 的播放文件路径和媒体控制器,调用start 方法即可播放媒体文件

    //实例化VideoView 对象
    vv = (VideoView) findViewById(R.id.vv);
    //从界面获取播放路径
    et_path = (EditText) findViewById(R.id.et_path);
    
    //给VideoView 设置视频路径
    vv.setVideoPath(et_path.getText().toString());
    //设置VideoView 控制器,我们当前类实现了MediaPlayerControl 接口
    vv.setMediaController(new MediaController(this));
    //开始播放
     vv.start();
     //设置当前播放器窗口设置为焦点
     vv.requestFocus();

    3、覆写MediaPlayerControl 接口中的抽象方法

     @Override
        public void start() {
        }
    
        @Override
        public void pause() {
    
        }
    
        @Override
        public int getDuration() {
            return 0;
        }
    
        @Override
    
        public int getCurrentPosition() {
            return 0;
        }
    
        @Override
        public void seekTo(int pos) {
        }
    
        @Override
        public boolean isPlaying() {
            return false;
        }
    
        @Override
        public int getBufferPercentage() {
            return 0;
        }
    
        @Override
        public boolean canPause() {
            return false;
        }
    
        @Override
        public boolean canSeekBackward() {
            return false;
        }
    
        @Override
        public boolean canSeekForward() {
            return false;
        }
    
        @Override
        public int getAudioSessionId() {
            return 0;
        }
    
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            return super.onKeyDown(keyCode, event);
        }
    
        @Override
        public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
            return super.onKeyMultiple(keyCode, repeatCount, event);
        }

    注意:上面的方法都是回调方法,我们可以在这些方法里面实现我们的业务逻辑。只有当我们给VideoView设置setMediaController 后控制器才会出现

    这里写图片描述

    收音机

    • 播放协议: MMS
    • MMS(Microsoft Media Server protocol)是一种串流媒体传送协议 ,android并不支持这种流媒体协议

    引入Vitamo框架进行播放

    • 核心类:io.vov.vitamio.MediaPlayer
    • 操作:同系统的MediaPlayer,代码编写与播放网络音乐相近

    视频处理

    电影文件有很多基本的组成部分。首先,文件本身被称为容器Container,容器的类型决定了信息被存放在文件中的位置。AVI和Quicktime就是容器的例子。接着,你有一组流,例如,你经常有的是一个音频流和一个视频流。(一个流只是一种想像出来的词语,用来表示一连串的通过时间来串连的数据元素)。在流中的数据元素被称为帧Frame。每个流是由不同的编码器来编码生成的。编解码器描述了实际的数据是如何被编码Coded和解码DECoded的,因此它的名字叫做CODEC。接着从流中被读出来的叫做包Packets。包是一段数据,它包含了一段可以被解码成方便我们最后在应用程序中操作的原始帧的数据。

    七个模块分别为:读文件模块,解复用模块 ,视频解码模块,音频解码音频,颜色空间转换模块,视频显示模块,音频播放模块

    粗略的分为五类,分别是 Source filer, Demux flter, Decoder filter, Color Space converter filter,Render filter,各类 filter的功能与作用简述如下

    Source filter

    Source filter 源过滤器的作用是为下级 demux filter 以包的形式源源不断的提供数据流。在通常情况下,我们有多种方式可以获得数据流,一种是从本地文件中读取,一种是从网上获取,Sourcefilter 另外一个作用就是屏蔽读本地文件和获取网络数据的差别,在下一级的 demux filter 看来,本地文件和网络数据是一样的。

    Demux filter

    解复用过滤器的作用是识别文件类型,媒体类型,分离出各媒体原始数据流,打上时钟信息后送给下级 decoder filter。为识别出不同的文件类型和媒体类型,常规的做法是读取一部分数据,然后遍历解复用过滤器支持的文件格式和媒体数据格式,做匹配来确定是哪种文件类型,哪种媒体类型;有些媒体类型的原始数据外面还有其他的信息,比如时间,包大小,是否完整包等等。demux filter 解析数据包后取出原始数据,有些类型的媒体不管是否是完整包都立即送往下级 decoder filter,有些类型的媒体要送完整数据包,此时可能有一些数据包拼接的动作;当然时钟信息的计算也是 demux filter 的工作内容,这个时钟用于各媒体之间的同步。在本例中,AVI Splitter 是 Demux filter。

    Decoder filter

    解码过滤器的作用就是解码数据包,并且把同步时钟信息传递下去。对视频媒体而言,通常是解码成 YUV 数据,然后利用显卡硬件直接支持 YUV 格式数据 Overlay 快速显示的特性让显卡极速显示。YUV格式是一个统称,常见的有 YV12,YUY2,UYVY 等等。有些非常古老的显卡和嵌入式系统不支持 YUV 数据显示,那就要转换成 RGB 格式的数据,每一帧的每一个像素点都要转换,分别计算 RGB 分量,并且因为转换是浮点运算,虽然有定点算法,还是要耗掉相当一部分 CPU,总体上效率底下;对音频媒体而言,通常是解码成 PCM 数据,然后送给声卡直接输出。在本例中,AVI Decompress 和 ACM Warper 是 decoder filter。

    Color space converter filter

    颜色空间转换过滤器的作用是把视频解码器解码出来的数据转换成当前显示系统支持的颜色格式。通常视频解码器解码出来的是 YUV 数据,PC 系统是直接支持 YUV 格式的,也支持 RGB 格式,有些嵌入式系统只支持 RGB 格式的。在本例中,视频解码器解码出来的是 RGB8 格式的数据,Color space converter filter 把 RGB8 转换成 RGB32 显示。

    Render filter

    渲染过滤器的作用就是在适当的时间渲染相应的媒体,对视频媒体就是直接显示图像,对音频就是播放声音。视音频同步的策略方法有好几种,其中最简单的一种就是默认视频和音频基准时间相同,这时音频可以不打时钟信息,通过计算音频的采样频率,量化 bit 数,声道数等基本参数就知道音频 PCM 的数据速率,按照这个速率往前播放即可;视频必须要使用同步时钟信息来决定什么时候显示。DirectShow 采用一个有序链表 ,把接收到的数据包放进有序链表中,启动一个定时器,每次定时器时间到就扫描链表,比较时钟信息,或者显示相应的帧,或者什么也不做,每次接收到新的数据帧,首先判断时钟信息,如果是历史数据帧就丢弃,如果是将来显示数据帧就进有序链表,如果当前时间帧就直接显示。如此这样,保持视频和音频在人体感觉误差范围内相对的动态同步。在本例中 VideoRender 和 Default DirectSound Device 是 Render filter,同时也是 Sink filter

    JetPlayer

    JetPlayer jetPlayer = JetPlayer.getJetPlayer();
    jetPlayer.loadJetFile("/sdcard/level1.jet");
    byte segmentId = 0;
    
    // queue segment 5, repeat once, use General MIDI, transpose by -1 octave
    jetPlayer.queueJetSegment(5, -1, 1, -1, 0, segmentId++);
    // queue segment 2
    jetPlayer.queueJetSegment(2, -1, 0, 0, 0, segmentId++);
    
    jetPlayer.play();

    TextureView

    TextureView、Surfaceview、SurfaceTexture、GLSurfaceView

    画中画

    https://github.com/googlesamples/android-PictureInPicture

    https://developer.android.google.cn/training/tv/playback/picture-in-picture.html?hl=zh-cn#handling_ui

    展开全文
  • 第一章 多媒体

    2016-12-24 14:15:46
    第一章 概论——多媒体技术的特征 1、 什么多媒体?  多媒体(multimedia):融合两种或两种以上媒体的人-机... 超媒体(hypermedia):文字、声音、图形、图像或电视等媒体元素组成相互关联的超文本系统,用户

    第一章   概论——多媒体技术的特征

    1、 什么是多媒体?

       多媒体(multimedia):融合两种或两种以上媒体的人-机互动的信息交流和传播媒体

       超文本(hypertext):包含指向其他文档或文档元素的指针的电子文档。传统文本以线性方式组织,超文本以非线性方式组织

       超媒体(hypermedia):由文字、声音、图形、图像或电视等媒体元素组成相互关联的超文本系统,用户可方便地浏览与主题相关的内容;提供一种符合人类思维习惯的工作和学习环境。

    *是不是简单的集合在一起就是多媒体?

    2、 多媒体的三大特征?    P3

       集成性;交互性;同步性

       集成性包括多种媒体的集成和多种业务的集成;交互性包括人与人的交互和人-机交互。同步性:多媒体通信终端上显现的图象、声音和文字等信息是以同步方式工作。

    3、 多媒体产生的技术背景? P3

       压缩编码;集成电路;数字存储技术

    4、 多媒体系统的分类?P5

       独立商亭式(单一多媒体):凡是一台多媒体计算机为核心的应用系统,例如商场的导购系统,博物馆导游系统;它的人性化的设计界面以及实时性是关键。

         通过网络提供业务的:

           多媒体会议与协同 多媒体即时通信(人-人)

          多媒体信息检索与查询、点播电视等(人-机):P6

      涉及到两个重要的技术问题:如何存?如何合理、有效地组织多媒体数据的存储和检索;如何取?如何向用户提供丰富的信息和如何让用户快速、有效地查询和阅览这些信息。

       *问的是基本多媒体分类还是通过网络提供业务分类?

      当前多媒体数据库采用存储方式?扩展的关系数据库或者采用面向对象的数据库,数据量很大的视频则是以文件形式存储。

    5、 点播电视(VOD)的概念? 模型? +第八章终端的框架标准   P10

        非对称性的交互控制

        基于客户机和服务器的模型:客户机去选播产品,服务器从它提供的服务中选择客户想要的服务。

    6、 三网融合?P11     电信网、计算机网、有线电视网

    展开全文
  • html多媒体

    2014-04-25 18:38:55
    HTML 多媒体

    转载于http://www.w3school.com.cn/html/html_video.asp

    HTML 多媒体

    现代网络浏览器已支持很多多媒体格式。

    什么是多媒体?

    多媒体来自多种不同的格式。它可以是您听到或看到的任何内容,文字、图片、音乐、音效、录音、电影、动画等等。

    在因特网上,您会经常发现嵌入网页中的多媒体元素,现代浏览器已支持多种多媒体格式。

    浏览器支持

    第一款因特网浏览器只支持文本,而且即使是对文本的支持也仅限于单一字体和单一颜色。随后诞生了支持颜色、字体和文本样式的浏览器,图片支持也被加入。

    不同的浏览器以不同的方式处理对音效、动画和视频的支持。某些元素能够以内联的方式处理,而某些则需要额外的插件。

    多媒体格式


    多媒体元素(比如视频和音频)存储于媒体文件中。

    确定媒体类型的最常用的方法是查看文件扩展名。当浏览器得到文件扩展名 .htm 或 .html 时,它会假定该文件是 HTML 页面。.xml 扩展名指示 XML 文件,而 .css 扩展名指示样式表。图片格式则通过 .gif 或 .jpg 来识别。

    多媒体元素元素也拥有带有不同扩展名的文件格式,比如 .swf、.wmv、.mp3 以及 .mp4。

    视频格式

    MP4 格式是一种新的即将普及的因特网视频格式。HTML5 、Flash 播放器以及优酷等视频网站均支持它。
    格式 文件 描述
    AVI .avi AVI (Audio Video Interleave) 格式是由微软开发的。所有运行 Windows 的计算机都支持 AVI 格式。它是因特网上很常见的格式,但非 Windows 计算机并不总是能够播放。
    WMV .wmv Windows Media 格式是由微软开发的。Windows Media 在因特网上很常见,但是如果未安装额外的(免费)组件,就无法播放 Windows Media 电影。一些后期的 Windows Media 电影在所有非 Windows 计算机上都无法播放,因为没有合适的播放器。
    MPEG
    • .mpg
    • .mpeg
    MPEG (Moving Pictures Expert Group) 格式是因特网上最流行的格式。它是跨平台的,得到了所有最流行的浏览器的支持。
    QuickTime .mov QuickTime 格式是由苹果公司开发的。QuickTime 是因特网上常见的格式,但是 QuickTime 电影不能在没有安装额外的(免费)组件的 Windows 计算机上播放。
    RealVideo
    • .rm
    • .ram
    RealVideo 格式是由 Real Media 针对因特网开发的。该格式允许低带宽条件下(在线视频、网络电视)的视频流。由于是低带宽优先的,质量常会降低。
    Flash
    • .swf
    • .flv
    Flash (Shockwave) 格式是由 Macromedia 开发的。Shockwave 格式需要额外的组件来播放。但是该组件会预装到 Firefox 或 IE 之类的浏览器上。
    Mpeg-4 .mp4 Mpeg-4 (with H.264 video compression) 是一种针对因特网的新格式。事实上,YouTube 推荐使用 MP4。YouTube 接收多种格式,然后全部转换为 .flv 或 .mp4 以供分发。越来越多的视频发布者转到 MP4,将其作为 Flash 播放器和 HTML5 的因特网共享格式。

    声音格式

    格式 文件 描述
    MIDI
    • .mid
    • .midi

    MIDI (Musical Instrument Digital Interface) 是一种针对电子音乐设备(比如合成器和声卡)的格式。MIDI 文件不含有声音,但包含可被电子产品(比如声卡)播放的数字音乐指令。

    点击这里播放 The Beatles

    因为 MIDI 格式仅包含指令,所以 MIDI 文件极其小巧。上面的例子只有 23k 的大小,但却能播放将近 5 分钟。MIDI 得到了广泛的平台上的大量软件的支持。大多数流行的网络浏览器都支持 MIDI。

    RealAudio
    • .rm
    • .ram
    RealAudio 格式是由 Real Media 针对因特网开发的。该格式也支持视频。该格式允许低带宽条件下的音频流(在线音乐、网络音乐)。由于是低带宽优先的,质量常会降低。
    Wave .wav Wave (waveform) 格式是由 IBM 和微软开发的。所有运行 Windows 的计算机和所有网络浏览器(除了 Google Chrome)都支持它。
    WMA .wma WMA 格式 (Windows Media Audio),质量优于 MP3,兼容大多数播放器,除了 iPod。WMA 文件可作为连续的数据流来传输,这使它对于网络电台或在线音乐很实用。
    MP3
    • .mp3
    • .mpga
    MP3 文件实际上是 MPEG 文件的声音部分。MPEG 格式最初是由运动图像专家组开发的。MP3 是其中最受欢迎的针对音乐的声音格式。期待未来的软件系统都支持它。

    使用哪种格式?

    WAVE 是因特网上最受欢迎的无压缩声音格式,所有流行的浏览器都支持它。如果您需要未经压缩的声音(音乐或演讲),那么您应该使用 WAVE 格式。

    MP3 是最新的压缩录制音乐格式。MP3 这个术语已经成为数字音乐的代名词。如果您的网址从事录制音乐,那么 MP3 是一个选项。

    HTML Object 元素


    <object> 的作用是支持 HTML 助手(插件)。

    HTML 助手(插件)

    辅助应用程序(helper application)是可由浏览器启动的程序。辅助应用程序也称为插件。

    辅助程序可用于播放音频和视频(以及其他)。辅助程序是使用 <object> 标签来加载的。

    使用辅助程序播放视频和音频的一个优势是,您能够允许用户来控制部分或全部播放设置。

    大多数辅助应用程序允许对音量设置和播放功能(比如后退、暂停、停止和播放)的手工(或程序的)控制。

    使用 QuickTime 来播放 Wave 音频


    实例

    <object width="420" height="360"
    classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
    codebase="http://www.apple.com/qtactivex/qtplugin.cab">
    <param name="src" value="bird.wav" />
    <param name="controller" value="true" />
    </object>

    使用 QuickTime 来播放 MP4 视频

    实例

    <object width="420" height="360"
    classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B"
    codebase="http://www.apple.com/qtactivex/qtplugin.cab">
    <param name="src" value="movie.mp4" />
    <param name="controller" value="true" />
    </object>

    使用 Flash 来播放 SWF 视频

    实例

    <object width="400" height="40"
    classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
    codebase="http://fpdownload.macromedia.com/
    pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0">
    <param name="SRC" value="bookmark.swf">
    <embed src="bookmark.swf" width="400" height="40"></embed>
    </object>

    使用 Windows Media Player 来播放 WMV 影片

    实例

    <object width="100%" height="100%"
    type="video/x-ms-asf" url="3d.wmv" data="3d.wmv"
    classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6">
    <param name="url" value="3d.wmv">
    <param name="filename" value="3d.wmv">
    <param name="autostart" value="1">
    <param name="uiMode" value="full" />
    <param name="autosize" value="1">
    <param name="playcount" value="1">
    <embed type="application/x-mplayer2" src="3d.wmv" width="100%"
     height="100%" autostart="true" showcontrols="true" 
    pluginspage="http://www.microsoft.com/Windows/MediaPlayer/"></embed>
    </object>

    HTML 音频

    雅虎媒体播放器

    实例

    <a href="song.mp3">Play Sound</a>
    
    <script type="text/javascript" src="http://mediaplayer.yahoo.com/js">
    </script>
    

    亲自试一试

    使用雅虎播放器是免费的。如需使用它,您需要把这段 JavaScript 插入网页底部:

    <script type="text/javascript" src="http://mediaplayer.yahoo.com/js"></script>

    然后只需简单地把 MP3 文件链接到您的 HTML 中,JavaScript 会自动地为每首歌创建播放按钮:

    <a href="song1.mp3">Play Song 1</a>
    <a href="song2.mp3">Play Song 2</a>
    ...
    ...
    ...
    

    雅虎媒体播放器为您的用户提供的是一个小型的播放按钮,而不是完整的播放器。不过,当您点击该按钮,会弹出完整的播放器。

    请注意,这个播放器始终停靠在窗框底部。只需点击它,就可将其滑出。

    使用超链接

    如果网页包含指向媒体文件的超链接,大多数浏览器会使用“辅助应用程序”来播放文件。

    以下代码片段显示指向 mp3 文件的链接。如果用户点击该链接,浏览器会启动“辅助应用程序”来播放该文件:

    实例

    <a href="song.mp3">Play the sound</a>

    亲自试一试

    内联的声音

    当您在网页中包含声音,或者作为网页的组成部分时,它被称为内联声音。

    如果您打算在 web 应用程序中使用内联声音,您需要意识到很多人都觉得内联声音令人恼火。同时请注意,用户可能已经关闭了浏览器中的内联声音选项。

    我们最好的建议是只在用户希望听到内联声音的地方包含它们。一个正面的例子是,在用户需要听到录音并点击某个链接时,会打开页面然后播放录音。

    HTML 4.01 多媒体标签

    标签 描述
    <applet> 不赞成。定义内嵌 applet。
    <embed> HTML4 中不赞成,HTML5 中允许。定义内嵌对象。
    <object> 定义内嵌对象。
    <param> 定义对象的参数。

    HTML 5 多媒体标签

    标签 描述
    <audio> 标签定义声音,比如音乐或其他音频流。
    <embed> 标签定义嵌入的内容,比如插件。

    HTML 视频

    在 HTML 中播放视频的方法有很多种。

    实例

    <video width="320" height="240" controls="controls">
      <source src="movie.mp4" type="video/mp4" />
      <source src="movie.ogg" type="video/ogg" />
      <source src="movie.webm" type="video/webm" />
      <object data="movie.mp4" width="320" height="240">
        <embed src="movie.swf" width="320" height="240" />
      </object>
    </video>
    

    亲自试一试

    问题,问题,以及解决方法

    在 HTML 中播放视频并不容易!

    您需要谙熟大量技巧,以确保您的视频文件在所有浏览器中(Internet Explorer, Chrome, Firefox, Safari, Opera)和所有硬件上(PC, Mac , iPad, iPhone)都能够播放。

    在本章,W3School 为您总结了问题和解决方法。

    使用 <embed> 标签

    <embed> 标签的作用是在 HTML 页面中嵌入多媒体元素。

    下面的 HTML 代码显示嵌入网页的 Flash 视频:

    实例

    <embed src="movie.swf" height="200" width="200"/>

    亲自试一试

    问题

    • HTML4 无法识别 <embed> 标签。您的页面无法通过验证。
    • 如果浏览器不支持 Flash,那么视频将无法播放
    • iPad 和 iPhone 不能显示 Flash 视频。
    • 如果您将视频转换为其他格式,那么它仍然不能在所有浏览器中播放。

    使用 <object> 标签

    <object> 标签的作用是在 HTML 页面中嵌入多媒体元素。

    下面的 HTML 片段显示嵌入网页的一段 Flash 视频:

    实例

    <object data="movie.swf" height="200" width="200"/>

    亲自试一试

    问题

    • 如果浏览器不支持 Flash,将无法播放视频。
    • iPad 和 iPhone 不能显示 Flash 视频。
    • 如果您将视频转换为其他格式,那么它仍然不能在所有浏览器中播放。

    使用 <video> 标签

    <video> 是 HTML 5 中的新标签。

    <video> 标签的作用是在 HTML 页面中嵌入视频元素。

    以下 HTML 片段会显示一段嵌入网页的 ogg、mp4 或 webm 格式的视频:

    实例

    <video width="320" height="240" controls="controls">
      <source src="movie.mp4" type="video/mp4" />
      <source src="movie.ogg" type="video/ogg" />
      <source src="movie.webm" type="video/webm" />
    Your browser does not support the video tag.
    </video>
    

    亲自试一试

    问题

    • 您必须把视频转换为很多不同的格式。
    • <video> 元素在老式浏览器中无效。
    • <video> 元素无法通过 HTML 4 和 XHTML 验证。

    最好的 HTML 解决方法

    HTML 5 + <object> + <embed>

    <video width="320" height="240" controls="controls">
      <source src="movie.mp4" type="video/mp4" />
      <source src="movie.ogg" type="video/ogg" />
      <source src="movie.webm" type="video/webm" />
      <object data="movie.mp4" width="320" height="240">
        <embed src="movie.swf" width="320" height="240" />
      </object>
    </video>
    

    亲自试一试

    上例中使用了 4 中不同的视频格式。HTML 5 <video> 元素会尝试播放以 mp4、ogg 或 webm 格式中的一种来播放视频。如果均失败,则回退到 <embed> 元素。

    问题

    • 您必须把视频转换为很多不同的格式
    • <video> 元素无法通过 HTML 4 和 XHTML 验证。
    • <embed> 元素无法通过 HTML 4 和 XHTML 验证。

    注释:使用 <!DOCTYPE html> (HTML5) 解决验证问题。

    优酷解决方案

    在 HTML 中显示视频的最简单的方法是使用优酷等视频网站。

    如果您希望在网页中播放视频,那么您可以把视频上传到优酷等视频网站,然后在您的网页中插入 HTML 代码即可播放视频:

    <embed src="http://player.youku.com/player.php/sid/XMzI2NTc4NTMy/v.swf" 
    width="480" height="400" 
    type="application/x-shockwave-flash">
    </embed>
    

    亲自试一试

    使用超链接

    如果网页包含指向媒体文件的超链接,大多数浏览器会使用“辅助应用程序”来播放文件。

    以下代码片段显示指向 AVI 文件的链接。如果用户点击该链接,浏览器会启动“辅助应用程序”,比如 Windows Media Player 来播放这个 AVI 文件:

    实例

    <a href="movie.swf">Play a video file</a>

    亲自试一试

    关于内联视频的一段注释

    当视频被包含在网页中时,它被称为内联视频。

    如果您打算在 web 应用程序中使用内联视频,您需要意识到很多人都觉得内联视频令人恼火。

    同时请注意,用户可能已经关闭了浏览器中的内联视频选项。

    我们最好的建议是只在用户希望看到内联视频的地方包含它们。一个正面的例子是,在用户需要看到视频并点击某个链接时,会打开页面然后播放视频。

    HTML 4.01 多媒体标签

    标签 描述
    <applet> 不赞成。定义内嵌 applet。
    <embed> 不赞成。定义内嵌对象。(HTML5 中允许)
    <object> 定义内嵌对象。
    <param> 定义对象的参数。

    HTML 5 多媒体标签

    标签 描述
    <video> 标签定义声音,比如音乐或其他音频流。
    <embed> 标签定义嵌入的内容,比如插件。

    展开全文
  • 多媒体信息技术》复习思考题

    万次阅读 2017-07-06 09:17:48
    多媒体是融合两种或者两种以上媒体的一种人-机交互式的信息交流和传播媒体。 对信息技术而言,多媒体是用多种媒体综合表达信息内容。对计算机而言,多媒体是将图、文、声、像等内容混成在一起的一门计算机技术。...
  • 多媒体技术及应用课后习题

    千次阅读 2019-10-01 23:36:40
    1.什么多媒体? 答:使用计算机交互式综合技术和数字通信网络技术处理多种表示媒体——文本、图形、图像和声音,使多种信息建立逻辑连接,集成为一个交互式系统。多媒体不仅指多种媒体,而且包含处理和应用它们,...
  • android多媒体框架学习

    千次阅读 2014-02-07 14:50:25
    Multimedia Framework overview(多媒体框架概述)--base on jellybean(一) jellybean 的多媒体跟以前的版本,通过对比没啥变化,最大的变化是google终于舍得给multimedia建个独立的git了(framework/av),等...
  • 20972多媒体操作系统

    千次阅读 2019-06-18 21:14:00
    多媒体操作系统   11.1 多媒体系统简介  随着多媒体技术的发展,在传统OS中也相应增加了许多能处理音频和视频信息的多媒体功能。现在流行的操作系统,如Linux、 Windows 系列等,就已具有多媒体功能。本章...
  • 基础知识点 多媒体技术的特征集成性交互性实时性 多媒体作品中交互方式按钮菜单对话 图形与图像的区别图形指的是用计算机绘制出来的画面 点直线圆等为主要组成元素图像通常是指图像输入设备 捕捉的实际场景画面...
  • 多媒体基础知识点.pdf

    2020-08-17 10:33:12
    图形与图像的区别图形指的是用计算机绘制出来的画面 点直线圆等为主要组成元素图像通常是指图像输入设备 捕捉的实际场景画面如扫描仪数码相机屏幕抓屏等获取 的画面都属于图像 4. 常见的图片处理软件 photoshop...
  • 多媒体基础知识点.doc

    2020-04-14 12:03:34
    多媒体作品中交互方式: 按钮菜单对话 图形与图像的区别图形指的是用计算机绘制出来的画面点直线圆等为主要组成元素图像通常是指图像输入设备捕捉的实际场景画面如扫描仪数码相机屏幕抓屏等获取的画面都属于图像...
  • 多媒体技术复习汇总

    千次阅读 2007-02-15 10:18:00
    1. 什么媒体媒体是信息表示和传输的载体。2. 媒体分类:感觉媒体,表示媒体,表现媒体,存储媒体,传输媒体3. 多媒体技术的定义和特点:多媒体技术就是计算机交互式综合处理声、文、图信息的技术,具有集成性...
  • 它是多媒体重要的组成部分,也称为多媒体系统开发工具软件。  用户应用软件 1.2图形和图像  基本原理 ◆亮度、色调和饱和度 亮度:表示光的明亮程度,它与被观察物体的发光强度和人类视觉系统的视敏功能有关。 ...
  • 多媒体技术复习汇总 收藏

    千次阅读 2010-10-12 18:56:00
     什么媒体媒体是信息表示和传输的载体。 2. 媒体分类:感觉媒体,表示媒体,表现媒体,存储媒体,传输媒体 3. 多媒体技术的定义和特点:多媒体技术就是计算机交互式综合处理声、文、图信息的技术,...
  • 多媒体开发指南

    千次阅读 2005-12-07 20:40:00
    流信息设置中的流信息包含流的比特率(bit rate),缓冲窗口和媒体属性的设置。视频和音频的流信息准确描述了文件中的媒体配置,包括压缩数据使用的编码和解码器(如果有的话)。一个设置也包含很多创建ASF文件时使用...
  • 1、多媒体元素是指多媒体应用中可以显示给用户的媒体组成,主要包含文本、图形、图像、声音、视频、动画等元素。 2、人们经常谈论的声音质量通常用声音信号的范围确定,现在通常把声音的质量分成5个等级,低到高...
  • 多媒体技术复习汇总

    2013-01-10 15:28:13
    什么媒体媒体是信息表示和传输的载体。 2.  媒体分类:感觉媒体,表示媒体,表现媒体,存储媒体,传输媒体 3.  多媒体技术的定义和特点:多媒体技术就是计算机交互式综合处理声、文、图信息的技术,具有...
  • 《实用多媒体技术》课程习题解答第一章 多媒体计算机概述单项选择题1-6:1、请根据多媒体的特性判断以下哪些属于多媒体的范畴?(1)交互式视频游戏 (2)有声图书 (3)彩色画报 (4)彩色电视(A)仅(1) ...
  •  jellybean 的多媒体跟以前的版本,通过对比没啥变化,最大的变化是google终于舍得给multimedia建个独立的git了(framework/av),等你好久了!也体现了media 在整个android系统中的重要性!fra
  • 电子商务多媒体制作技术与应用教学大纲 课程信息 课程名称电子商务多媒体制作技术与应用 课程类别素质选修课/专业基础课 课程性质选修/...课程负责人 二课程简介 图像声音视频是组成多媒体的3个重要元素它们也是电子
  • VC多媒体编程

    千次阅读 2012-04-12 00:09:53
    -- VC多媒体编程 -- Visual C++中基于多文档视窗模型的重叠图象拼接技术 摘要   图象拼接是在全景视频系统、地理信息系统等应用中经常遇到的一个问题,本文基于网格匹配的方法对边界部分有重叠的...
  • 多媒体技术复习题

    千次阅读 2017-05-23 20:29:49
    多媒体技术复习题 一. 选择题 1. 所谓媒体是指:( b ) A. 二进制代码 B. 表示和传播信息的载体 C. 计算机输入与输出的信息 D. 计算机屏幕显示的信息   2. 帧频率为25帧/秒的电视制式有( b )。 A. ...
  • 多媒体信息数字化

    千次阅读 2017-10-16 15:31:00
    计算机多媒体信息包括哪些?  图片、音频、视频 声音的数字化 波形文件,模拟信号,就是时间和幅度都是连续变化的信号 数字化: 将连续的模拟声音信号转换成时间和幅度都离散的数字信号 采样 每隔一个时间...
  • 数字多媒体技术解密

    千次阅读 2014-03-03 16:30:56
    如果算上模拟时代的话,多媒体传输并非多么新鲜的事情。...从某种意义上讲,数字技术的突飞猛进对多媒体通信的推动并非它能够在多大程度上提高媒体内容的质量——这方面某些斯基们所起的所用可能会更大——而是它可以令
  • Android多媒体架构分析

    千次阅读 2011-04-26 19:51:00
    Android多媒体架构分析 Revision History Date Issue Description Author wylhistory 目录 1. Abstract 2. Introduction 3. Android 多媒体架构 3.1 代码位置 3.2 MediaPlayer 3.3 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,385
精华内容 6,554
关键字:

多媒体由什么媒体元素组成