Exemplo n.º 1
0
        /// <summary>
        /// validates a source against a given AVC level taking into account the source properties and the x264 settings
        /// <param name="bytesPerFrame">bytesize of a single frame</param>
        /// <param name="FS">frame area in pixels</param>
        /// <param name="MBPS">macroblocks per second</param>
        /// <param name="settings">the codec config to test</param>
        /// <param name="compliantLevel">the first avc level that can be used to encode this source</param>
        /// <returns>whether or not the current level is okay, if false and compliantLevel is -1,
        /// the source could not be read</returns>
        public bool validateAVCLevel(int hRes, int vRes, double framerate, x264Settings settings, out int compliantLevel)
        {
            settings = (x264Settings)settings.clone(); //Otherwise this sets it to the lowest compliant level anyway.
            const int unrestricted = 15;               // maybe this should be set as a global constant

            compliantLevel = unrestricted;
            if (settings.Level == unrestricted) // 15 = unrestricted
            {
                return(true);
            }

            int    FrameSize            = (int)maxFS(hRes, vRes);
            int    MBPS                 = maxBPS(hRes, vRes, framerate);
            int    hBlocks              = macroblocks(hRes);
            int    vBlocks              = macroblocks(vRes);
            double bufferSize           = pictureBufferSize(settings, bytesPerFrame(hRes, vRes));
            int    allowableBPS         = this.getMaxMBPS(settings.Level);
            int    allowableFS          = this.getMaxFS(settings.Level);
            double dimensionRestriction = Math.Ceiling(Math.Sqrt((double)(allowableFS) * 8));
            double allowableDPB         = this.getMaxDPB(settings.Level);

            if (allowableBPS >= MBPS && allowableFS >= FrameSize && allowableDPB >= bufferSize &&
                dimensionRestriction >= hBlocks && dimensionRestriction >= vBlocks)
            {
                return(true);
            }
            else
            {
                while (settings.Level < unrestricted && (allowableBPS < MBPS || allowableFS < FrameSize ||
                                                         allowableDPB < bufferSize || dimensionRestriction < hBlocks || dimensionRestriction < vBlocks))
                {
                    settings.Level       = settings.Level + 1;
                    allowableBPS         = this.getMaxMBPS(settings.Level);
                    allowableFS          = this.getMaxFS(settings.Level);
                    dimensionRestriction = Math.Ceiling(Math.Sqrt((double)(allowableFS) * 8));
                    allowableDPB         = this.getMaxDPB(settings.Level);
                }
                compliantLevel = settings.Level;
                return(false);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Checks a collection of x264Settings and modifies them if needed to fit within the level constraints.
        /// </summary>
        /// <param name="level">the level to enforce</param>
        /// <param name="inputSettings">the collection of x264Settings to check</param>
        /// <param name="frameSize">the size of the decoded video frame in bytes</param>
        /// <returns>A compliant set of x264Settings</returns>
        public x264Settings EnforceSettings(int level, x264Settings inputSettings, double frameSize, out AVCLevelEnforcementReturn enforcement)
        {
            x264Settings enforcedSettings = (x264Settings)inputSettings.clone();

            enforcement                     = new AVCLevelEnforcementReturn();
            enforcement.Altered             = false;
            enforcement.EnableP4x4mv        = true;
            enforcement.EnableVBVBufferSize = true;
            enforcement.EnableVBVMaxRate    = true;
            enforcement.Panic               = false;
            enforcement.PanicString         = "";

            if (!checkP4x4(level, inputSettings))
            {
                enforcement.Altered     = true;
                enforcedSettings.P4x4mv = false;
            }
            if (checkP4x4Enabled(level, inputSettings))
            {
                enforcement.EnableP4x4mv = true;
            }
            else
            {
                enforcement.EnableP4x4mv = false;
            }

            // step through various options to enforce the max decoded picture buffer size
            while (!this.checkMaxDPB(level, enforcedSettings, frameSize))
            {
                if (enforcedSettings.BFramePyramid)
                {
                    enforcement.Altered            = true;
                    enforcedSettings.BFramePyramid = false; // try turning off pyramid first
                }
                else
                if (enforcedSettings.NbRefFrames > 1)
                {
                    enforcement.Altered           = true;
                    enforcedSettings.NbRefFrames -= 1;     // try reducing the number of reference frames
                }
                else
                if (enforcedSettings.NbBframes > 0)
                {
                    enforcement.Altered        = true;
                    enforcedSettings.NbBframes = 0;         // try turning off B frames
                }
                else
                {
                    enforcement.Panic       = true;
                    enforcement.PanicString = "Can't force settings to conform to level (the frame size is too large)";
                    // reset output settings to original and set level to unrestrained
                    enforcedSettings       = (x264Settings)inputSettings.clone();
                    enforcedSettings.Level = 15;
                    return(enforcedSettings);
                }
            }

            // Disallow independent specification of MaxBitrate and MaxBufferSize unless Unrestrained
            if (level < 15)
            {
                enforcement.EnableVBVMaxRate    = false;
                enforcedSettings.VBVMaxBitrate  = -1;
                enforcement.EnableVBVBufferSize = false;
                enforcedSettings.VBVBufferSize  = -1;
            }
            else
            {
                enforcement.EnableVBVMaxRate    = true;
                enforcement.EnableVBVBufferSize = true;
            }

            return(enforcedSettings);
        }