internal VideoDetails(int[] supportedAudioBitRates, 
     int frameRate, 
     Size frameSize,
     int bitRate, 
     int audioSamplesPerSecond,
     int audioAverageBytesPerSecond,
     string videoEncoding, 
     string audioEncoding,
     Transcoder transcoder,
     string errorMessage)
 {
     this.SupportedAudioBitRates = supportedAudioBitRates;
     this.FrameRate = frameRate;
     this.FrameSize = frameSize;
     this.BitRate = bitRate;
     this.AudioAverageBytesPerSecond = audioAverageBytesPerSecond;
     this.AudioSamplesPerSecond = audioSamplesPerSecond;
     this.AudioEncoding = audioEncoding;
     this.VideoEncoding = videoEncoding;
     this.Transcoder = transcoder;
     this.ErrorMessage = errorMessage;
 }
        void TranscodeVideoTest(string filename)
        {
            using (MFSystem.Start())
            {
                var transcoder = new Transcoder
                {
                    VideoFiles = new[] { new SourceReaderExtra(filename, null) },
                    DestinationFile = Path.ChangeExtension(filename, "wmv"),
                    VideoBitRate = 5000000,
                    AudioBitRate = 48000/8
                };

                TraceInfo.WriteLine("Begining video re-encoding.");

                transcoder.ProcessVideo((readers, saveToSink) =>
                {
                    int lastSecond = 0;
                    var fn = AVOperations.FadeIn(saveToSink);

                    readers.First().SourceReader.Samples(sample => {
                        if (sample.Stream.CurrentMediaType.IsVideo && sample.Sample != null)
                        {
                            var s = (int)sample.Sample.SampleTime.FromNanoToSeconds();
                            if (s != lastSecond)
                                TraceInfo.WriteLine("Converted: {0} seconds", s);
                            lastSecond = s;
                        }

                        return fn(sample);

                    });
                });

                TraceInfo.WriteLine("Video converted.  Review the video file {0} to confirm it looks OK.", transcoder.DestinationFile);
                TraceInfo.WriteLine("Success!");
            }
        }
        void Process(Transcoder transcoder, bool highlights, Action<long, long> monitorProgress, Func<bool> isAborted)
        {
            try
            {
                TraceInfo.WriteLineIf(highlights, "Transcoding highlights to {0}", transcoder.DestinationFile);
                TraceInfo.WriteLineIf(!highlights, "Transcoding full replay to {0}", transcoder.DestinationFile);

                transcoder.ProcessVideo((readers, saveToSink) =>
                {
                    var writeToSink = monitorProgress == null ? saveToSink : MonitorProgress(saveToSink);

                    var fadeSegments = AVOperations.FadeIn(AVOperations.FadeOut(writeToSink));
                    var edits = highlights ? ApplyEdits(writeToSink) : writeToSink;
                    var mainBodyOverlays = AVOperations.Overlay(applyRaceDataOverlay, edits);
                    var introOverlay = AVOperations.Overlay(applyIntroOverlay, fadeSegments);

                    var sourceReaderExtra = readers.FirstOrDefault(r => ((CapturedVideoFile)r.State).isIntroVideo);
                    if (sourceReaderExtra != null)
                    {
                        var introSourceReader = sourceReaderExtra.SourceReader;
                        var mainReaders = AVOperations.Combine(readers.Skip(1).Select(r => r.SourceReader).ToArray(), Settings.Default.VideoSplitGap);

                        totalDuration += introSourceReader.Duration + mainReaders.Duration;
                        
                        AVOperations.StartConcat(introSourceReader, introOverlay,
                            AVOperations.Concat(mainReaders, mainBodyOverlays, isAborted), isAborted);
                    }
                    else
                    {
                        var mainReaders = AVOperations.Combine(readers.Select(r => r.SourceReader).ToArray(), Settings.Default.VideoSplitGap);

                        totalDuration += mainReaders.Duration;

                        AVOperations.Concat(mainReaders, mainBodyOverlays, isAborted)(0, 0);
                    }
                });
                
                TraceInfo.WriteLineIf(highlights, "Done Transcoding highlights to {0}", transcoder.DestinationFile);
                TraceInfo.WriteLineIf(!highlights, "Done Transcoding full replay to {0}", transcoder.DestinationFile);
            }
            catch (Exception e)
            {
                TraceError.WriteLine(e.Message);
                TraceError.WriteLine(e.StackTrace);
                throw e;
            }
        }
        public static void Apply(string gameDataFile, int videoBitRate, string destFile, bool highlights, Action<long, long> progressReporter, Func<bool> isAborted, string pluginName)
        {
            try
            {
                var leaderBoard = new LeaderBoard { OverlayData = OverlayData.FromFile(gameDataFile), PluginName = pluginName };

                var transcoder = new Transcoder
                {
                    VideoFiles = leaderBoard.OverlayData.VideoFiles.ToSourceReaderExtra(),
                    DestinationFile = destFile,
                    VideoBitRate = videoBitRate
                };

                new TranscodeAndOverlay(leaderBoard, progressReporter).Process(transcoder, highlights, progressReporter, isAborted);
            }
            catch (Exception e)
            {
                TraceError.WriteLine(e.Message);
                TraceError.WriteLine(e.StackTrace);
                throw e;
            }
        }
        void TranscodeVideoTest(string filename)
        {
            using (MFSystem.Start())
            {
                var transcoder = new Transcoder
                {
                    VideoFiles = new [] { new SourceReaderExtra(filename, null)},
                    DestinationFile = Path.ChangeExtension(filename, "wmv"),
                    VideoBitRate = 5000000,
                    AudioBitRate = 48000/8
                };

                TraceInfo.WriteLine("Begining video re-encoding.");

                transcoder.ProcessVideo((readers, saveToSink) =>
                {
                    readers.First().SourceReader.Samples(AVOperations.FadeIn(saveToSink));
                });

                TraceInfo.WriteLine("Video converted.  Review the video file {0} to confirm it looks OK.", transcoder.DestinationFile);
                TraceInfo.WriteLine("Success!");
            }
        }
        public static void Apply(string gameDataFile, int videoBitRate, int audioBitRate, string destFile, bool highlights, Action<long, long> progressReporter)
        {
            var leaderBoard = new LeaderBoard { OverlayData = OverlayData.FromFile(gameDataFile) };

            var transcoder = new Transcoder
            {
                VideoFiles = leaderBoard.OverlayData.VideoFiles.ToSourceReaderExtra(),
                DestinationFile = destFile,
                VideoBitRate = videoBitRate,
                AudioBitRate = audioBitRate
            };

            new TranscodeAndOverlay(leaderBoard, progressReporter)._Apply(transcoder, highlights, progressReporter);
        }
        public static VideoDetails TestFor(string videoFileName)
        {
            List<int> supportedAudioBitRates = new List<int>();

            using (MFSystem.Start())
            {
                var readWriteFactory = new ReadWriteClassFactory();

                var sourceReader = readWriteFactory.CreateSourceReaderFromURL(videoFileName, null);

                var videoStream = sourceReader.Streams.FirstOrDefault(s => s.IsSelected && s.NativeMediaType.IsVideo);
                if (videoStream.IsNull)
                    throw new Exception("Unable to find video track within file.");

                var audioStream = sourceReader.Streams.FirstOrDefault(s => s.IsSelected && s.NativeMediaType.IsAudio);
                if (audioStream.IsNull)
                    throw new Exception("Unable to find audio track within file.");

                var channels = audioStream.NativeMediaType.AudioNumberOfChannels;
                var sampleRate = audioStream.NativeMediaType.AudioSamplesPerSecond;

                var types = MFSystem.TranscodeGetAudioOutputAvailableTypes(MediaFoundation.MFMediaType.WMAudioV9, MediaFoundation.Transform.MFT_EnumFlag.All);

                foreach (var bitRate in types
                    .Where(t => t.AudioSamplesPerSecond == sampleRate)
                    .Select(t => t.AudioAverageBytesPerSecond)
                    .Distinct()
                    .OrderBy(t => t))
                {
                    supportedAudioBitRates.Add(bitRate);
                }

                int videoBitRate = 0;
                videoStream.NativeMediaType.TryGetBitRate(out videoBitRate);

                var audioSamplesPerSecond = audioStream.NativeMediaType.AudioSamplesPerSecond;
                var audioAverageBytesPerSecond = audioStream.NativeMediaType.AudioAverageBytesPerSecond;

                var audioSubTypeName = audioStream.CurrentMediaType.SubTypeName;
                var videoSubTypeName = videoStream.CurrentMediaType.SubTypeName;

                var transcoder = new Transcoder
                {
                    VideoFiles = new[] { new SourceReaderExtra(videoFileName, null) },
                    DestinationFile = Path.ChangeExtension(videoFileName, "wmv"),
                    VideoBitRate = 5000000
                };

                var errorMessage = transcoder.TestVideoConversion();

                return new VideoDetails(
                    supportedAudioBitRates.ToArray(),
                    videoStream.NativeMediaType.FrameRate.ToInt(),
                    videoStream.NativeMediaType.FrameSize,
                    videoBitRate / 1000000,
                    audioSamplesPerSecond,
                    audioAverageBytesPerSecond,
                    videoSubTypeName,
                    audioSubTypeName,
                    transcoder,
                    errorMessage);
            }
        }