文章目录
  1. 1. 如何使用
  2. 2. 实现细节

事实上早在2013年的时候博主就实现了不依赖任何第三方库在WP8上播放FLV格式的视频文件(见这篇文章),只不过当时没有将源代码开放出来。时间过去了将近两年,但是似乎在GitHub上依然没有开源的方便易用的这方面的库,所以博主决定将这个库重写一遍开源出来。代码托管在GitHub

这个库支持Windows Phone Silverlight应用和Windows Runtime Universal应用,前者面向Windows Phone 8+,后者面向Windows Phone 8.1+和Windows 8.1+。

如何使用

这个库以简单易用为设计目标,在你的项目中使用这个库只需要写数行代码。

假设我们有一个MediaElement控件,将其命名为mediaElement,并且在应用的安装目录下Assets文件夹中存在test.flv。

在Windows Phone Silverlight应用中需使用DawnPlayer.FlvMediaStreamSource

1
2
3
4
5
var applicationFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
var storageFile = await applicationFolder.GetFileAsync("Assets\\test.flv");
var randomAccessStream = await storageFile.OpenReadAsync();
mediaElement.SetSource(FlvMediaStreamSource.Wrap(randomAccessStream));
mediaElement.Play();

在Windows Runtime Universal应用中需使用dawn_player.flv_media_stream_source

1
2
3
4
5
6
var applicationFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
var storageFile = await applicationFolder.GetFileAsync("Assets\\test.flv");
var randomAccessStream = await storageFile.OpenReadAsync();
fmss = await flv_media_stream_source.create_async(randomAccessStream);
mediaElement.SetMediaStreamSource(fmss.unwrap());
mediaElement.Play();

实现细节

目前互联网上绝大多数的FLV格式的视频文件都是使用H.264(AVC)作为视频编码,使用AAC作为音频编码。对于同样使用这两种编码的MP4文件可以直接使用MediaElement进行播放,而FLV文件则不行。从MSDN上的文档可以知道H.264和AAC都在Windows Phone支持的编码之列。MediaElement之所以能够直接播放MP4文件是因为Windows Phone知道如何从MP4文件中分离出音、视频数据并对其各自进行解码和播放,但是Windows Phone并不知道如何从FLV文件中分离出音、视频数据。在这里MP4和FLV就好比是容器,将相同编码的音、视频数据以不同的格式封装成一个视频文件。

幸运的是,Windows Phone Silverlight(下文简称WPSL)和Windows Runtime(下文简称WinRT)都提供了一种叫MediaStreamSource的机制,允许由应用程序来做音、视频的分离工作,然后将分离出来的音、视频Sample发送到媒体管道由系统来负责解码和播放,以此来移除容器相关,播放原本所不支持的容器格式。

这个库由以下这些部分组成:

  • 一个AMF(Action Message Format)的解码器amf_decode.hpp
    FLV的file body是由一个个的tag组成的,tag分为audio tag、video tag和script tag三种。script tag中有一个叫onMetaData的tag,当中包含了视频文件的时长、宽、高等元信息(meta data),这些信息使用AMF进行编码。这个AMF的解码器就是用来解析这些元信息的。此外对于一个用于在线播放的FLV文件,这个元信息通常还包含了一个名为keyframes的民间标准对象,这个对象存储着关键帧到关键帧所在tag文件偏移的映射表。

  • 一个FLV文件的解析器flv_parser.hpp
    这是一个完全依照 _FLV Video File Format Specification Version 10_,使用纯C++实现,兼具性能和可移植性的FLV文件格式解析器,内部使用前面所说的AMF解码器来解码元信息。使用这个解析器解析前需要先注册感兴趣的解析事件,当解析器解析到特定的数据时会调用对应的回调函数。支持的解析事件包括

  • on_script_tag
    当解析成功一个script tag时会触发,注册这个事件以获取FLV视频的元信息。

  • on_audio_specific_config
    当解析成功一个AAC sequence header时会触发,注册这个事件以获得AudioSpecificConfig(ISO/IEC 14496-3)。这个AudioSpecicifConfig含有声道数(channel count)、采样率(sample rate)、比特率(bit rate)等信息。这些信息用于在Windows Phone Silverlight中构造AudioCodecPrivateData,在Windows Runtime中构造AudioEncodingProperties。

  • on_avc_decoder_configuration_record
    当解析成功一个AVC sequence header时触发,注册这个事件以获得SPS(sequence parameter set)和PPS(picture parameter set)。SPS和PPS可以用于构造VideoCodecPrivateData。

  • on_audio_sample
    当解析成功一个audio tag且获取到audio sample时触发,注册这个事件以接收audio sample。

  • on_video_sample
    当解析成功一个video tag且获取到video sample时触发,注册这个事件以接收video sample。

  • 一个分离控制器flv_player.hpp
    这个分离器控制器负责调用分离器分离从文件中读取到的数据,以及处理打开、缓冲、seek等操作。在内部维护一个常驻线程和多个池化线程,绝大多数对外接口都是异步的。

  • 一个MediaStreamSource
    虽然WPSL和WinRT都支持MediaStreamSource,但是这种机制的实现方式却大不相同(尽管如此DawnPlayer还是在WPSL和WinRT上共用了前面的解码器、分离器和控制器的全部代码)。

    在WPSL中是将分离控制器flv_player封装成FlvMediaStreamSource,这个类继承自抽象类MediaStreamSource,并实现了OpenMediaAsync、GetSampleAsync、SeekAsync和CloseMedia等方法。

    而在WinRT中MediaStreamSource既不是抽象类也无法继承它(声明为sealed)。取而代之的是事件订阅机制。所以在WinRT中博主的做法是将分离器控制器封装成flv_media_stream_source,由这个类来处理订阅的Starting和SampleRequested等事件。

文章目录
  1. 1. 如何使用
  2. 2. 实现细节