/// <summary>
        /// The SlideImageGenerator can be shared by a set of modules.
        /// This allows us to avoid duplicating work of building slide images.
        /// Use this static method to get the instance, then run Process if
        /// the job has changed.
        /// </summary>
        /// <param name="job"></param>
        /// <param name="progressTracker"></param>
        /// <param name="log"></param>
        /// <returns></returns>
        public static SlideImageGenerator GetInstance(ArchiveTranscoderJob job,
                                                      ProgressTracker progressTracker,
                                                      LogMgr log)
        {
            if (instance == null)
            {
                instance = new SlideImageGenerator(job, progressTracker, log);
            }
            else
            {
                //Reset all properties
                instance.Job = job;
                instance.TheProgressTracker = progressTracker;
                instance.TheLogMgr          = log;
                instance.TheRtDocuments     = null;
                instance.TheSlideMessages   = null;
            }

            return(instance);
        }
        /// <summary>
        /// Do all the initial time consuming preparation including building temp directories from
        /// any decks specified with the job, and scanning data prior to start time to attempt to determine
        /// the presentation state.
        /// We require that Init complete before GetNextSample.
        /// </summary>
        public bool Init(ProgressTracker progressTracker)
        {
            if ((streamPlayers == null) || (streamPlayers.Length == 0))
            {
                // No data is not considered an error.
                return(true);
            }

            //preserve the end value to be restored when we're done.
            int oldEnd = progressTracker.EndValue;

            //build directories from any decks specified in the job
            imageGenerator = SlideImageGenerator.GetInstance(this.job, progressTracker, logMgr);

            //Refresh image export size and job in case they have changed.
            imageGenerator.SetImageExportSize(false, this.outputWidth, this.outputHeight);
            imageGenerator.Job = this.job;

            //Run process to build or refresh deck images.
            imageGenerator.Process();

            //Tell SlideImageMgr about the decks.
            slideImageMgr.SetSlideDirs(imageGenerator.OutputDirs);

            //scan data preceeding start time to establish all initial state
            progressTracker.CurrentValue  = 0;
            progressTracker.EndValue      = (int)lookBehindDuration;
            progressTracker.CustomMessage = "Initializing Presentation Data";
            BufferChunk bc;
            long        timestamp;

            while (!cancel)
            {
                long t; int index;
                if (getNextStreamPlayerFrameTime(out t, out index))
                {
                    if (t < start.Ticks)
                    {
                        if (streamPlayers[index].GetNextFrame(out bc, out timestamp))
                        {
                            slideImageMgr.ProcessFrame(bc);
                            progressTracker.CurrentValue = (int)(((TimeSpan)(new DateTime(timestamp) - streamPlayers[0].Start)).TotalSeconds);
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    break;
                }
            }

            if (!cancel)
            {
                initialized = true;
            }

            progressTracker.CustomMessage = "";
            progressTracker.EndValue      = oldEnd;
            return(true);
        }