/// <summary> /// This function is used to intialize a heuristics module. It must be implemented by all derived classes. /// </summary> /// <param name="manifestInfo">The manifest for the stream we are reading</param> /// <param name="playbackInfo">The playback info for the media element</param> /// <param name="adInsertPoints">Optional expected points for advertising. Can be null</param> public abstract void Initialize(ManifestInfo manifestInfo, PlaybackInfo playbackInfo, AdInsertionPoint[] adInsertPoints);
/// <summary> /// Initializes a new instance of the AdaptiveStreamingSource class /// </summary> /// <param name="mediaElement">The media element that we are sending samples to. We use it internally to keep track of playback statistics</param> /// <param name="url">The url of the manifest for the stream we are serving</param> public AdaptiveStreamingSource(MediaElement mediaElement, Uri url) { // Make sure our Url is not null if (null == url) { throw new ArgumentNullException("url", Errors.NullUrlOnMSSError); } // Also check the mediaElement parameter if (null == mediaElement) { throw new ArgumentNullException("mediaElement", Errors.NullMediaElementOnMSSError); } // Remember the Url to the manifest we are streaming m_manifestSourceUrl = url; // Create our default manifest parser ManifestParser = new ManifestParserImpl(); // Create our default chunk parser factory ChunkParserFactory = new ChunkParserFactoryImpl(); // Create our default url generator UrlGenerator = new UrlGeneratorImpl(); // Create a new queue for processing commands. All work is done on a background thread, // which will shuttle events back to the UI thread in case something needs to be displayed. m_workQueue = new WorkQueue(); // Create the thread that we are going to run background commands on m_workQueueThread = new Thread(WorkerThread); // Make sure we remember the Dispatcher class for the UI thread UIDispatcher.Load(); // Playback info is a wrapper on around media element m_playbackInfo = new PlaybackInfo(mediaElement); // Hook our heuristics events m_heuristics.ChunkReplacementSuggested += HeuristicsChunkReplacementSuggested; }
/// <summary> /// Handle a close command /// </summary> private void DoClose() { Tracer.Trace(TraceChannel.MSS, "Media closed"); if (m_heuristics != null) { m_heuristics.Shutdown(); } if (m_manifestInfo != null) { m_manifestInfo.Shutdown(); } m_workQueueThread = null; m_isWorkQueueThreadStarted = false; m_workQueue = null; m_playbackInfo = null; }
/// <summary> /// Implements Heuristics.Initialize(). Called to initialize this heuristics module with /// the given manifest file and optional adverting insertion points /// </summary> /// <param name="manifestInfo">The manifest of the stream we are using</param> /// <param name="playbackInfo">The playback info for the media element</param> /// <param name="adInsertPoints">Optional ad insertion points. Can be null</param> public override void Initialize(ManifestInfo manifestInfo, PlaybackInfo playbackInfo, AdInsertionPoint[] adInsertPoints) { Tracer.Trace(TraceChannel.MSS, "MediaSource instance {0}, sessionID: {1}", InstanceId.ToString("B"), sm_sessionId.ToString("B")); // Store our manifest info m_manifestInfo = manifestInfo; m_playbackInfo = playbackInfo; // We only support 1 audio and 1 video stream right now, so let's throw an exception // if someone tries to create us with more than that int numStreams = m_manifestInfo.NumberOfStreams; if (numStreams > 2) { throw new AdaptiveStreamingException("We only support 1 audio and 1 video stream at this time"); } // Copy the add insertion points over m_adInsertPoints = new AdInsertionPoints(); foreach (AdInsertionPoint ad in adInsertPoints) { m_adInsertPoints.Add(ad); } // Allocate some internal variables m_heuristicsMode = new HeuristicsMode[numStreams]; m_fixedBitrateIndex = new int[numStreams]; m_mediaStreamTypes = new MediaStreamType[numStreams]; m_maxDownloadsPerStream = new int[numStreams]; m_numDownloadsInProgress = new int[numStreams]; m_nextChunkId = new int[numStreams]; // Go through each stream in our manifest and do per-stream configuration int numVideoStreams = 0, numAudioStreams = 0; for (int i = 0; i < numStreams; i++) { StreamInfo streamInfo = m_manifestInfo.GetStreamInfoForStream(i); // Initialize some of the arrays we just created m_mediaStreamTypes[i] = streamInfo.MediaType; m_fixedBitrateIndex[i] = 0; m_maxDownloadsPerStream[i] = GlobalMaxDownloadsPerStream; m_numDownloadsInProgress[i] = 0; m_nextChunkId[i] = 0; // If we are a video stream, then we need to set our heuristics mode // to Full switch (streamInfo.MediaType) { case MediaStreamType.Audio: m_heuristicsMode[i] = HeuristicsMode.FixedRate; ++numAudioStreams; break; case MediaStreamType.Video: m_heuristicsMode[i] = HeuristicsMode.Full; ++numVideoStreams; break; default: throw new AdaptiveStreamingException(Errors.NonVideoOrAudioStreamsNotSupportedError); } // Configure this stream InitializeHeuristicsForStream( streamInfo.StreamId, (double)m_maxBufferSizeInMs / 1000, m_manifestInfo.GetStreamInfoForStream(i).Bitrates.Count, m_manifestInfo.GetStreamInfoForStream(i).GetBitrateArray()); } // Make sure we found only 1 video and 1 audio stream if (numVideoStreams != 1) { throw new AdaptiveStreamingException(Errors.IncorrectNumberOfVideoStreamsError); } // Start scheduling our downloads ScheduleDownloads(); }