private void NegotiateStream(uint streamIndex, Guid majorType, Guid[] possibleSubtypes)
        {
            IMFMediaType outputMediaType = null;
            Exception    lastException   = null;
            bool         foundValidType  = false;

            foreach (Guid subType in possibleSubtypes)
            {
                try
                {
                    // Create a partial media type
                    MFHelper.MFCreateMediaType(out outputMediaType);
                    outputMediaType.SetGUID(new Guid(Consts.MF_MT_MAJOR_TYPE), majorType);
                    outputMediaType.SetGUID(new Guid(Consts.MF_MT_SUBTYPE), subType);

                    // Set it as the current media type in source reader
                    this.sourceReader.SetCurrentMediaType(streamIndex, IntPtr.Zero, outputMediaType);

                    // Get the full media type from Source Reader
                    this.sourceReader.GetCurrentMediaType(streamIndex, out outputMediaType);

                    // Set it as the input media type in Sink Writer
                    this.sinkWriter.SetInputMediaType(this.streamsInfo[streamIndex].OutputStreamIndex, outputMediaType, null);

                    // If no exceptions were thrown a suitable media type was found
                    foundValidType = true;

                    // Break from the loop so no more media types are tried
                    break;
                }
                catch (Exception ex)
                {
                    // Something went wrong, the loop will continue and the next type will be tried
                    lastException = ex;
                }
            }

            // If FormatFound is false no suitable type was found and the operation can't continue
            if (foundValidType == false)
            {
                if (lastException != null)
                {
                    throw new Exception(lastException.Message, lastException);
                }
                else
                {
                    throw new Exception("Unknown error occurred");
                }
            }
        }
        private IMFMediaType CreateTargetVideoMediaType()
        {
            IMFMediaType mediaType = null;

            MFHelper.MFCreateMediaType(out mediaType);

            mediaType.SetGUID(new Guid(Consts.MF_MT_MAJOR_TYPE), new Guid(Consts.MFMediaType_Video));

            mediaType.SetGUID(new Guid(Consts.MF_MT_SUBTYPE), this.videoOutput.Subtype);
            mediaType.SetUINT64(new Guid(Consts.MF_MT_FRAME_SIZE), this.videoOutput.FrameSize.Packed);
            mediaType.SetUINT64(new Guid(Consts.MF_MT_FRAME_RATE), this.videoOutput.FrameRate.Packed);
            mediaType.SetUINT64(new Guid(Consts.MF_MT_PIXEL_ASPECT_RATIO), this.videoOutput.PixelAspectRatio.Packed);
            mediaType.SetUINT32(new Guid(Consts.MF_MT_AVG_BITRATE), this.videoOutput.AvgBitRate);
            mediaType.SetUINT32(new Guid(Consts.MF_MT_INTERLACE_MODE), this.videoOutput.InterlaceMode);

            return(mediaType);
        }
        private IMFMediaType CreateTargetAudioMediaType()
        {
            IMFMediaType mediaType = null;

            if (audioOutput.Subtype.Equals(new Guid(Consts.MFAudioFormat_AAC)))
            {
                // Create the AAC media type
                MFHelper.MFCreateMediaType(out mediaType);

                mediaType.SetGUID(new Guid(Consts.MF_MT_MAJOR_TYPE), new Guid(Consts.MFMediaType_Audio));

                mediaType.SetGUID(new Guid(Consts.MF_MT_SUBTYPE), this.audioOutput.Subtype);
                mediaType.SetUINT32(new Guid(Consts.MF_MT_AUDIO_AVG_BYTES_PER_SECOND), this.audioOutput.AvgBytePerSecond);
                mediaType.SetUINT32(new Guid(Consts.MF_MT_AUDIO_NUM_CHANNELS), this.audioOutput.NumOfChannels);
                mediaType.SetUINT32(new Guid(Consts.MF_MT_AUDIO_SAMPLES_PER_SECOND), this.audioOutput.SamplesPerSecond);
                mediaType.SetUINT32(new Guid(Consts.MF_MT_AUDIO_BLOCK_ALIGNMENT), this.audioOutput.BlockAlignment);
                mediaType.SetUINT32(new Guid(Consts.MF_MT_AUDIO_BITS_PER_SAMPLE), this.audioOutput.BitsPerSample);
            }
            else
            {
                // Create the WMA media type
                uint   codecConfig         = 0;
                uint   elementsNumber      = 0;
                uint   selectedType        = 0;
                int    avgBitrateDiff      = int.MaxValue;
                uint   avgBytePerSecond    = uint.MaxValue;
                object supportedAttributes = null;

                // Get the available audio ouput types for the required sub type
                IMFCollection availableTypes = null;
                MFHelper.MFTranscodeGetAudioOutputAvailableTypes(audioOutput.Subtype, (uint)Enums.MFT_ENUM_FLAG.MFT_ENUM_FLAG_ALL, codecConfig, out availableTypes);

                // Get the number of types
                availableTypes.GetElementCount(out elementsNumber);

                for (uint elementIndex = 0; elementIndex < elementsNumber; elementIndex++)
                {
                    // Get the next element
                    availableTypes.GetElement(elementIndex, out supportedAttributes);
                    mediaType = (IMFMediaType)supportedAttributes;

                    // Get the byte per second
                    mediaType.GetUINT32(new Guid(Consts.MF_MT_AUDIO_AVG_BYTES_PER_SECOND), out avgBytePerSecond);

                    // If this is better than the last one found remember the index
                    if (Math.Abs((int)avgBytePerSecond - (int)audioOutput.AvgBytePerSecond) < avgBitrateDiff)
                    {
                        selectedType   = elementIndex;
                        avgBitrateDiff = Math.Abs((int)avgBytePerSecond - (int)audioOutput.AvgBytePerSecond);
                    }

                    mediaType = null;
                }

                // Get the best audio type found
                availableTypes.GetElement(selectedType, out supportedAttributes);
                mediaType = (IMFMediaType)supportedAttributes;
            }

            return(mediaType);
        }