private static void AssignStreamInfoFields(InputstreamInfo streamInfo, ref WaveFormatEx wf, ref AMMediaType amt)
 {
     wf.nChannels      = (ushort)streamInfo.Channels;
     wf.nSamplesPerSec = (int)streamInfo.SampleRate;
     if (wf.nSamplesPerSec == 0)
     {
         wf.nSamplesPerSec = 48000; // Fallback if missing, otherwise audio decoder filter will not connect
     }
     wf.nAvgBytesPerSec = streamInfo.Bandwidth / 8;
     amt.sampleSize     = streamInfo.Bandwidth;
 }
        private static uint CustomChannelCountSorting(InputstreamInfo i)
        {
            var channelCount = i.Channels;

            // Gives mono channels a higher number, so they are not preferred over stereo in ascending order.
            if (channelCount == 1)
            {
                channelCount *= 10;
            }
            return(channelCount);
        }
        /// <summary>
        /// Tries to create a matching <see cref="AMMediaType"/> for the given <paramref name="streamInfo"/>.
        /// </summary>
        /// <param name="streamInfo">stream</param>
        /// <param name="mediaType">media type</param>
        /// <returns><c>true</c> if successful</returns>
        public static bool TryGetType(InputstreamInfo streamInfo, out AMMediaType mediaType)
        {
            Func <InputstreamInfo, AMMediaType> mediaTypeFn;

            if (TYPE_MAPPINGS.TryGetValue(streamInfo.CodecInternalName, out mediaTypeFn) || TYPE_MAPPINGS.TryGetValue(streamInfo.CodecName, out mediaTypeFn))
            {
                mediaType = mediaTypeFn(streamInfo);
                return(true);
            }
            mediaType = null;
            return(false);
        }
        public static AMMediaType E_AC3(InputstreamInfo streamInfo)
        {
            WaveFormatEx wf = new WaveFormatEx();

            wf.wFormatTag     = 8192;
            wf.nBlockAlign    = 24;
            wf.wBitsPerSample = 32;
            wf.cbSize         = 0;

            AMMediaType amt = new AMMediaType();

            AssignStreamInfoFields(streamInfo, ref wf, ref amt);
            amt.majorType           = MediaType.Audio;
            amt.subType             = MEDIASUBTYPE_DOLBY_DDPLUS;
            amt.temporalCompression = false;
            amt.fixedSizeSamples    = true;
            amt.SetFormat(wf);
            return(amt);
        }
        public static AMMediaType AAC_LC(InputstreamInfo streamInfo)
        {
            WaveFormatEx wf = new WaveFormatEx();

            wf.wFormatTag     = 255;
            wf.nBlockAlign    = 1;
            wf.wBitsPerSample = 16;
            wf.cbSize         = 0;

            AMMediaType amt = new AMMediaType();

            AssignStreamInfoFields(streamInfo, ref wf, ref amt);
            amt.majorType           = MediaType.Audio;
            amt.subType             = MEDIASUBTYPE_ADTS; // Works better than RAW_AAC1 (tested with Amazon Prime and 7TV)
            amt.temporalCompression = false;
            amt.fixedSizeSamples    = true;
            amt.SetFormat(wf);
            return(amt);
        }
        /// <summary>
        /// AnnexB formatted h264 bitstream
        /// </summary>
        /// <param name="streamInfo"></param>
        /// <returns></returns>
        public static AMMediaType H264_AnnexB(InputstreamInfo streamInfo)
        {
            int width  = (int)streamInfo.Width;
            int height = (int)streamInfo.Height;

            if (streamInfo.ExtraData.Length > 0)
            {
                var codecData = new H264CodecData(streamInfo.ExtraData);

                SPSUnit spsUnit = new SPSUnit(codecData.SPS);
                width  = spsUnit.Width();
                height = spsUnit.Height();
            }

            VideoInfoHeader2 vi = new VideoInfoHeader2();

            vi.SrcRect.right     = width;
            vi.SrcRect.bottom    = height;
            vi.TargetRect.right  = width;
            vi.TargetRect.bottom = height;

            int hcf = HCF(width, height);

            vi.PictAspectRatioX = width / hcf;
            vi.PictAspectRatioY = height / hcf;

            vi.BmiHeader.Width       = width;
            vi.BmiHeader.Height      = height;
            vi.BmiHeader.Planes      = 1;
            vi.BmiHeader.Compression = FOURCC_H264;

            AMMediaType amt = new AMMediaType();

            amt.majorType           = MediaType.Video;
            amt.subType             = MediaSubType.H264;
            amt.temporalCompression = true;
            amt.fixedSizeSamples    = false;
            amt.sampleSize          = 1;
            amt.SetFormat(vi);
            return(amt);
        }
        /// <summary>
        /// AVC1 formatted H264 bitstream
        /// </summary>
        /// <param name="streamInfo"></param>
        /// <returns></returns>
        public static AMMediaType H264_AVC1(InputstreamInfo streamInfo)
        {
            H264CodecData  codecData = null;
            Mpeg2VideoInfo vi        = new Mpeg2VideoInfo();

            byte[] extraData = new byte[0];
            int    width     = (int)streamInfo.Width;
            int    height    = (int)streamInfo.Height;

            if (streamInfo.ExtraData.Length > 0)
            {
                codecData = new H264CodecData(streamInfo.ExtraData);

                SPSUnit spsUnit = new SPSUnit(codecData.SPS);
                width  = spsUnit.Width();
                height = spsUnit.Height();
            }

            vi.hdr.SrcRect.right     = width;
            vi.hdr.SrcRect.bottom    = height;
            vi.hdr.TargetRect.right  = width;
            vi.hdr.TargetRect.bottom = height;

            int hcf = HCF(width, height);

            vi.hdr.PictAspectRatioX = width / hcf;
            vi.hdr.PictAspectRatioY = height / hcf;

            vi.hdr.BmiHeader.Width  = width;
            vi.hdr.BmiHeader.Height = height;

            vi.hdr.BmiHeader.Planes      = 1;
            vi.hdr.BmiHeader.Compression = FOURCC_AVC1;
            vi.hdr.BmiHeader.BitCount    = 24;

            if (codecData != null)
            {
                vi.dwProfile = (uint)codecData.Profile;
                vi.dwLevel   = (uint)codecData.Level;
                vi.dwFlags   = (uint)codecData.NALSizeMinusOne + 1;

                extraData = NaluParser.CreateAVC1ParameterSet(codecData.SPS, codecData.PPS, 2);
            }
            else
            {
                // Example: avc1.4D401F -> Main Level 3.1
                // Profile     Value
                // Baseline    42E0
                // Main        4D40
                // High        6400
                // Extended    58A0

                // Level       Hex Value
                // 3.0         1E
                // 3.1         1F
                // 4.1         29
                // 5.1         33
                string codecInfo = streamInfo.CodecInternalName.Split('.').Last();
                if (codecInfo.Length == 6)
                {
                    int codecNum;
                    if (int.TryParse(codecInfo.Substring(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codecNum))
                    {
                        vi.dwProfile = (uint)codecNum;
                    }
                    if (int.TryParse(codecInfo.Substring(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codecNum))
                    {
                        vi.dwLevel = (uint)codecNum;
                    }
                }
            }

            vi.cbSequenceHeader = (uint)extraData.Length;

            AMMediaType amt = new AMMediaType();

            amt.majorType           = MediaType.Video;
            amt.subType             = MEDIASUBTYPE_AVC1;
            amt.temporalCompression = true;
            amt.fixedSizeSamples    = false;
            amt.sampleSize          = 1;
            SetFormat(vi, extraData, amt);
            return(amt);
        }