Windows Phone播放視頻流

  • 前言

     MediaElement是Windows Phone中播放本地或者網絡視頻文件和音樂文件的經常使用控件,支持的格式能夠從這裏看。經過Play,Pause,Stop,Position方法或屬性能夠方便的控制文件的播放暫停或快進。MediaElement包含6種狀態,分別是buffering、opening、playing、closed、stopped、pause。能夠經過註冊MediaElement的CurrentStateChanged事件來獲取CurrentState來對UI作出不一樣的響應。須要注意的是,MediaElement在某些特定狀態下對於API的調用不會當即反應。好比,當MediaElement的狀態在buffering的時候,若是調用Play事件,MediaElement要等到緩衝結束後才能執行Play操做。在這種場景下就須要咱們針對特定的CurrentState作出UI上的交互來填補緩衝時間帶來的程序無響應問題。下面就來給出一個XAML的例子。網絡

<MediaElement 
    x:Name="media" 
    Source="xbox.wmv" 
    CurrentStateChanged="media_state_changed" 
    Width="300" Height="300"/>

      Source是控制播放文件路徑的屬性,上面給出一個播放本地文件的例子,也能夠指定網絡上的文件路徑。當更改或設置Source的值後,MediaElement的狀態會進入opening,若是設置Source爲null,則會進入closed狀態。今天咱們重點要說的是,如何使用MediaElement播放網絡的視頻流,即直播的場景。ide

  • MediaStreamSource

    MediaStreamSource是用於將視頻流直接送入MediaElement的媒體管道中的類,也能夠做爲用於MediaElement不支持的視頻格式的中轉站。經過MediaElement的SetSource方法指定,SetSource方法也能夠用來播放本地的視頻流。爲了完成網絡視頻流的轉換等處理,一般咱們自定義一個繼承MediaStreamSoure的類,再實現一些必要的方法。好比,OpenMediaAsyncGetSampleAsyncSeekAsync等。下面咱們就來看看一個簡單的自定義類實現的步驟。spa

protected override void OpenMediaAsync()
{
//描述媒體示例
_mediaSampleAttributes[MediaSampleAttributeKeys.FrameHeight] = _height.ToString();
_mediaSampleAttributes[MediaSampleAttributeKeys.FrameWidth] = _width.ToString();
//描述媒體流
_mediaStreamAttributes[MediaStreamAttributeKeys.Height] = _height.ToString();
_mediaStreamAttributes[MediaStreamAttributeKeys.Width] = _width.ToString();
_mediaStreamAttributes[MediaStreamAttributeKeys.CodecPrivateData] ="";
_mediaStreamAttributes[MediaStreamAttributeKeys.VideoFourCC] ="H264";
//詳盡描述媒體流
_mediaStreamDescriptions.Add(new MediaStreamDescription(MediaStreamType.Video, _mediaStreamAttributes));
//描述媒體源
Dictionary<MediaSourceAttributesKeys, string> mediaSourceAttributes =new Dictionary<MediaSourceAttributesKeys, string>();
mediaSourceAttributes[MediaSourceAttributesKeys.CanSeek] ="false";
mediaSourceAttributes[MediaSourceAttributesKeys.Duration] = _duration.ToString(CultureInfo.InvariantCulture);
ReportOpenMediaCompleted(mediaSourceAttributes, _mediaStreamDescriptions);
}

     當MediaElement的Source被指定後將進入opening狀體,這時將調用OpenMediaAsync方法。這個方法用來描述將要播放的視頻流的流體,高寬,格式,長短等信息。VideoFourCC屬性表明要播放的流的視頻格式,它是由一個四個字符的字符串指定,好比:"H264","MP43","YV12"等。經過調用ReportOpenMediaCompleted方法告知MediaElement視頻流已經打開能夠繼續進行下面的操做。code

protected override void GetSampleAsync(MediaStreamType mediaStreamType)
{
var msd =new MediaStreamDescription(MediaStreamType.Video, _mediaStreamAttributes);
//詳盡描述媒體示例
var mediaSample =new MediaStreamSample(
msd,
_mediaStream,
_offect,
_count,
_timeStamp,
_mediaSampleAttributes);
ReportGetSampleCompleted(mediaSample);
}

      在MediaStreamSource打開以後,將調用GetSampleAsync方法。上面的代碼經過ReportGetSampleCompleted方法將組織好的視頻流裝入到媒體管道中。若是這個時候視頻流因爲網絡緣由或者須要轉碼等操做尚未準備好,那麼咱們能夠調用ReportGetSampleProgress方法來通知MediaElement緩衝的進度,這時MediaElement將進入到buffering狀態,若是當前的CurrrentState是Playing,那麼視頻播放將暫停播放進入到buffering狀態。GetSampleAsync方法會被調用屢次,直到再次受到來自ReportGetSampleCompleted的視頻流才繼續播放。視頻

protected override void SeekAsync(long seekToTime)
{
    ReportSeekCompleted(seekToTime);
}

      在播放網絡媒體視頻流的過程當中經常須要進度條的功能。若是將MediaSourceAttributesKeys.CanSeek的屬性值設成false,那麼SeekAsync的參數seekToTime將是0。若是你要實現進度條的功能,那麼必需要確保seekToTime的值在視頻的duration以內。若是改觸發了進度,那麼咱們就須要從新組織視頻流,直到從新調用ReportGetSampleCompleted方法,MediaElement纔會繼續播放。blog

      當視頻播放接受後咱們須要插入一個空的MediaStreamSample來告知MediaElement視頻播放結束,這時CurrentState將進入到closed狀態。繼承

  • 總結

    以上咱們簡單的介紹了在Windows Phone中播放視頻流的方法,播放音頻流的方法也是如此,須要修改MediaStreamType屬性的值。流的來源能夠經過Socket或者Http。格式轉換是一個在視頻播放中很複雜的問題,這裏就不進行介紹了,有須要的同窗能夠留言討論或者自行研究。事件

相關文章
相關標籤/搜索