Windows Phone 实时播放H264裸码流

      因为项目的需要,近日调研了一下在 Windows Phone 手机上播放H264裸码流的方法,期间参考了大量的网络资源,最终得以解决这个问题,对如此具有钻研和奉献精神的他们表示诚挚的感谢!

       在查阅资料的过程中,首先遇到的比较头疼的问题就是太多的资料都是讲述如何在SilverLight页面上解码HVU或H264数据呈现音视频,虽然将这些代码移植到 WP7 上很简单,但是要呈现出视频就不是那么简单了,偶再一次的在这个问题上磨练了心智。书归正传,在移植过程中,总共遇到两个大的问题,第一个是在模拟器上怎么也呈现不出视频,第二个是在模拟器上呈现出视频后,在真机上怎么也显不出视频。我擦,真的很凄惨啊,搞的偶吃不香睡不香,期间备受折磨啊,呜呜!

       首先说第一个问题,在模拟器上显示视频。根据前辈们的指点,两个条件是必须的:MediaElement控件和用来设置MediaElement数据源的继承自MediaStreamSource的类(暂时命名为H264MediaStreamSource吧)。在调研这个问题时,我仔细阅读了“在 Silverlight 应用程序中实现对 FLV 视频格式的支持”这片文章,其中“如何解码 FLV 文件中的 H.264 视频流”这段研读的很仔细,不过之后移植到Windows Phone 手机程序上,模拟器不显视频的原因也出自这里,因为作者的程序是Silverlight 应用程序,正如文中所言,一些属性是不需要设置的,但是在Windows Phone程序中,这些属性就必须设置了,譬如MediaSampleAttributeKeys和MediaStreamAttributeKeys枚举中的宽高值。经过验证,即便是在XAML里面设置了MediaElement的宽高值,如果在H264MediaStreamSource里面不设置MediaSampleAttributeKeys和MediaStreamAttributeKeys枚举中的宽高值,再怎么样在模拟器中也是显示不了视频图像的。重载方法OpenMediaAsync的代码如下:

protected override void OpenMediaAsync()        

{            

    emptyDict[MediaSampleAttributeKeys.FrameWidth] = width.ToString();   

    emptyDict[MediaSampleAttributeKeys.FrameHeight] = height.ToString();

    Dictionary<MediaStreamAttributeKeys, string> videoStreamAttributes = new Dictionary<MediaStreamAttributeKeys, string>();

    videoStreamAttributes[MediaStreamAttributeKeys.CodecPrivateData] = "";        

    videoStreamAttributes[MediaStreamAttributeKeys.VideoFourCC] = "H264";        

    videoStreamAttributes[MediaStreamAttributeKeys.Width] = width.ToString();         

    videoStreamAttributes[MediaStreamAttributeKeys.Height] = height.ToString();         

    this.videoStreamDescription = new MediaStreamDescription(MediaStreamType.Video, videoStreamAttributes);

          

    Dictionary<MediaSourceAttributesKeys, string> mediaSourceAttributes = new Dictionary<MediaSourceAttributesKeys, string>();

    mediaSourceAttributes[MediaSourceAttributesKeys.Duration] = "0";          

   if (stream.CanSeek)          

   {              

        mediaSourceAttributes[MediaSourceAttributesKeys.CanSeek] = "1";        

    }         

    else        

   {        

         mediaSourceAttributes[MediaSourceAttributesKeys.CanSeek] = "0";        

   }        

    List<MediaStreamDescription> mediaStreamDescriptions = new List<MediaStreamDescription>();        

    mediaStreamDescriptions.Add(this.videoStreamDescription);

    this.ReportOpenMediaCompleted(mediaSourceAttributes, mediaStreamDescriptions);   

   }

 

       第二个问题是在关于在模拟器上能显示视频图像,但是真机中不能显示的问题,直接的现象就是怎么也不进GetSampleAsync这个接口!网上查了很久,好多老外也为这个问题纠结额,解决方法也是无意尝试中得知:就是OpenMediaAsync这个方法中的一句话需要改变下而已,呜呜,天杀的!将videoStreamAttributes[MediaStreamAttributeKeys.CodecPrivateData] = ""的值改成你H264裸码流第一帧中的SPS+PPS,类似于videoStreamAttributes[MediaStreamAttributeKeys.CodecPrivateData] = "000001674D4015965301004A2000000168E9238800",具体根据你的实际数值而定。

        无论如何,解码H264裸数据的问题总算解决了,接下来的必定还有好多未知的难题待解,戒骄戒躁,继续加油咯!

posted @ 2012-05-07 18:00  Lirica  阅读(1523)  评论(10编辑  收藏  举报