コード例 #1
0
        private bool _OpenVideoStream()
        {
            int        videoStreamIndex;
            SACDecoder decoder;

            try
            {
                _Videodecoder    = CAcinerella.AcCreateVideoDecoder(_Instance);
                decoder          = (SACDecoder)Marshal.PtrToStructure(_Videodecoder, typeof(SACDecoder));
                videoStreamIndex = decoder.StreamIndex;
            }
            catch (Exception)
            {
                CLog.LogError("Error opening video file (can't find decoder): " + _FileName);
                return(false);
            }

            if (videoStreamIndex < 0)
            {
                return(false);
            }

            _Width  = decoder.StreamInfo.VideoInfo.FrameWidth;
            _Height = decoder.StreamInfo.VideoInfo.FrameHeight;

            if (decoder.StreamInfo.VideoInfo.FramesPerSecond > 0)
            {
                _FrameDuration = 1f / (float)decoder.StreamInfo.VideoInfo.FramesPerSecond;
            }

            _Framebuffer.Init(_Width * _Height * 4);
            _FrameAvailable = false;
            return(true);
        }
コード例 #2
0
        private void _Decode()
        {
            const int minFrameDropCount = 4;
            // With => seekThreshold frames to drop use seek instead of skip
            const int seekThreshold = 25; // 25 frames = 0.5 second with _FrameDuration = 0.02f

            if (_NoMoreFrames)
            {
                return;
            }

            float videoTime      = RequestTime;
            float timeDifference = videoTime - _LastDecodedTime;

            bool dropFrame = timeDifference >= (minFrameDropCount - 1) * _FrameDuration;

            bool hasFrameDecoded = false;

            if (dropFrame)
            {
                var frameDropCount = (int)Math.Ceiling(timeDifference / _FrameDuration);
                if (!_DropSeekEnabled || frameDropCount < seekThreshold)
                {
                    hasFrameDecoded = _DropWithSkip(frameDropCount);
                }
                else
                {
                    hasFrameDecoded = _DropWithSeek(videoTime, frameDropCount);
                }
            }

            if (!hasFrameDecoded)
            {
                try
                {
                    hasFrameDecoded = CAcinerella.AcGetFrame(_Instance, _Videodecoder);
                }
                catch (Exception)
                {
                    CLog.LogError("Error AcGetFrame " + _FileName);
                }
            }
            if (hasFrameDecoded)
            {
                _FrameAvailable = true;
            }
            else
            {
                if (Loop)
                {
                    RequestTime = _LoopedRequestTime;
                    _Skip();
                }
                else
                {
                    _NoMoreFrames = true;
                }
            }
        }
コード例 #3
0
        //Just call this if thread is not alive
        private void _Free()
        {
            if (_Videodecoder != IntPtr.Zero)
            {
                CAcinerella.AcFreeDecoder(_Videodecoder);
            }

            if (_Instance != IntPtr.Zero)
            {
                CAcinerella.AcClose(_Instance);
                CAcinerella.AcFree(_Instance);
            }
        }
コード例 #4
0
        private bool _DropWithSkip(int frameDropCount)
        {
            bool hasFrameDecoded = false;

            // Add 1 dropped frame per 16 frames (Power of 2 -> Div is fast) as skipping takes time too and we don't want to skip again
            frameDropCount += frameDropCount / 16;
            try
            {
                hasFrameDecoded = CAcinerella.AcSkipFrames(_Instance, _Videodecoder, frameDropCount);
            }
            catch (Exception)
            {
                CLog.LogError("Error AcSkipFrame " + _FileName);
            }
            return(hasFrameDecoded);
        }
コード例 #5
0
        // Skip to a given time (in s)
        private void _Skip()
        {
            float skipTime = RequestTime; //Copy to variable to have consistent checks

            if (skipTime < 0 || skipTime >= Length)
            {
                skipTime = 0;
            }

            try
            {
                CAcinerella.AcSeek(_Videodecoder, -1, (Int64)(skipTime * 1000f));
            }
            catch (Exception e)
            {
                CLog.LogError("Error seeking video file \"" + _FileName + "\": " + e.Message);
            }
            _LastDecodedTime = skipTime;

            _FrameAvailable = false;
        }
コード例 #6
0
        private bool _DropWithSeek(float videoTime, int frameDropCount)
        {
            bool hasFrameDecoded = false;

            try
            {
                hasFrameDecoded = CAcinerella.AcSeek(_Videodecoder, 0, (long)videoTime * 1000L);
            }
            catch (Exception)
            {
                CLog.LogError("Error AcSeek " + _FileName);
            }

            if (!hasFrameDecoded)
            {
                // Fallback to frame skipping
                _DropSeekEnabled = false;
                hasFrameDecoded  = _DropWithSkip(frameDropCount);
            }

            return(hasFrameDecoded);
        }
コード例 #7
0
        //Open the file and get the length.
        public bool LoadFile(String fileName)
        {
            _FileName = fileName;
            try
            {
                _Instance = CAcinerella.AcInit();
                CAcinerella.AcOpen2(_Instance, fileName);

                var instance = (SACInstance)Marshal.PtrToStructure(_Instance, typeof(SACInstance));
                Length = instance.Info.Duration / 1000f;
                bool ok = instance.Opened && Length > 0.001f;
                _DropSeekEnabled = true;
                if (ok)
                {
                    return(true);
                }
                _Free();
            }
            catch (Exception) {}
            CLog.LogError("Error opening video file: " + _FileName);
            _Instance = IntPtr.Zero;
            return(false);
        }