GetFFmpegErrorMessage() public static method

Gets the FFmpeg error mesage based on the error code
public static GetFFmpegErrorMessage ( int code ) : string
code int The code.
return string
        private bool FillDecodedPictureHolderFrame(AVPacket *readingPacket, bool emptyPacket)
        {
            var receivedFrame = 0;

            // Empty packet explanation: http://stackoverflow.com/questions/25526075/multiple-frames-lost-if-i-use-av-read-frame-in-ffmpeg
            if (emptyPacket)
            {
                ffmpeg.av_init_packet(readingPacket);
                readingPacket->stream_index = InputVideoStream->index;
            }

            try
            {
                var decodingPacket = (AVPacket)System.Runtime.InteropServices.Marshal.PtrToStructure(new IntPtr(readingPacket), typeof(AVPacket)); // by-value copy
                while (decodingPacket.size > 0 || emptyPacket)
                {
                    var decodeResult = ffmpeg.avcodec_decode_video2(VideoCodecContext, DecodedPictureHolder, &receivedFrame, readingPacket);
                    if (decodeResult < Constants.SuccessCode)
                    {
                        var errorMessage = Helper.GetFFmpegErrorMessage(decodeResult);
                        break;
                    }
                    else
                    {
                        decodingPacket.size -= decodeResult;

                        if (emptyPacket && decodingPacket.size == 0)
                        {
                            break;
                        }
                    }
                }
            }
            finally
            {
                ffmpeg.av_free_packet(readingPacket);
            }

            return(receivedFrame != 0);
        }
        private bool FillDecodedWaveHolderFrame(AVPacket *readingPacket, bool emptyPacket)
        {
            var receivedFrame = 0;

            if (emptyPacket)
            {
                ffmpeg.av_init_packet(readingPacket);
                readingPacket->stream_index = InputAudioStream->index;
            }

            try
            {
                var decodingPacket = (AVPacket)System.Runtime.InteropServices.Marshal.PtrToStructure(new IntPtr(readingPacket), typeof(AVPacket)); // by-value copy
                while (decodingPacket.size > 0 || emptyPacket)
                {
                    var decodeResult = ffmpeg.avcodec_decode_audio4(AudioCodecContext, DecodedWaveHolder, &receivedFrame, &decodingPacket);
                    if (decodeResult < Constants.SuccessCode)
                    {
                        var errorMessage = Helper.GetFFmpegErrorMessage(decodeResult);
                        break;
                        throw new Exception(string.Format("Error decoding audio packet. Code {0} - {1}", decodeResult, errorMessage));
                    }
                    else
                    {
                        decodingPacket.size -= decodeResult;

                        if (emptyPacket && decodingPacket.size == 0)
                        {
                            break;
                        }
                    }
                }
            }
            finally
            {
                ffmpeg.av_free_packet(readingPacket);
            }

            return(receivedFrame != 0);
        }
Esempio n. 3
0
        /// <summary>
        /// Internals the seek input.
        /// </summary>
        /// <param name="renderTime">The render time.</param>
        private void InternalSeekInput(decimal renderTime)
        {
            if (IsLiveStream)
            {
                if (LeadingFramesCache.IsEmpty == false)
                {
                    RealtimeClock.Seek(LeadingFramesCache.FirstFrameTime);
                }

                return;
            }

#if DEBUG
            var seekStopwatch = new System.Diagnostics.Stopwatch();
            seekStopwatch.Start();
#endif

            if (renderTime < StartTime)
            {
                renderTime = StartTime;
            }

            RealtimeClock.Seek(renderTime);

            var allowedThreshold = Constants.SeekThresholdSeconds;
            var seekOffsetLength = Constants.SeekOffsetSeconds;

            var seekTime         = renderTime - seekOffsetLength;
            var maxSeekStartTime = seekTime - allowedThreshold;

            var bufferedLeadingFrames = new FFmpegMediaFrameCache(LeadingFramesCache);
            var bufferedLaggingFrames = new FFmpegMediaFrameCache(LaggingFramesCache);

            var outerLoopCount        = 0;
            var innerLoopCount        = 0;
            var frameReleaseCount     = 0;
            var doSeekInStream        = true;
            var doSeekByPullingFrames = true;
            var seekFlag            = 0;
            var seekFrameResult     = 0;
            var startTime           = DateTime.UtcNow;
            var lastFailedTimestamp = long.MinValue;
            var seekToLastFrame     = false;

            var seekTimeBase      = LeadingFramesCache.Type == MediaFrameType.Video ? InputVideoStream->time_base : InputAudioStream->time_base;
            var seekStreamIndex   = LeadingFramesCache.Type == MediaFrameType.Video ? InputVideoStream->index : InputAudioStream->index;
            var leadingFrameIndex = -1;

            try
            {
                while (doSeekInStream)
                {
                    outerLoopCount++;

                    if (seekTime < StartTime)
                    {
                        seekTime = StartTime;
                    }

                    if (lastFailedTimestamp == StartDts)
                    {
                        if (LeadingFramesCache.IsEmpty == false)
                        {
                            RealtimeClock.Seek(LeadingFramesCache.FirstFrameTime);
                        }

                        ErrorOccurredCallback(this, new MediaPlaybackException(MediaPlaybackErrorSources.InternalSeekInput, MediaPlaybackErrorCode.SeekFailedCritical,
                                                                               string.Format("Target Postion @ {0:0.000}s has already failed to seek. First DTS {1} also failed and will not retry.", seekTime, StartDts)));

                        return;
                    }

                    var targetTimestamp = Helper.SecondsToTimestamp(seekTime, seekTimeBase);
                    if (lastFailedTimestamp == targetTimestamp)
                    {
                        ErrorOccurredCallback(this, new MediaPlaybackException(MediaPlaybackErrorSources.InternalSeekInput, MediaPlaybackErrorCode.SeekFailedWillRetry,
                                                                               string.Format("Target Postion @ {0:0.000}s has already failed to seek. Target timestamp will now be First DTS {1}.", seekTime, StartDts)));

                        targetTimestamp = StartDts;
                    }

                    seekFlag = (seekTime < renderTime || seekTime <= StartTime ? (int)ffmpeg.AVSEEK_FLAG_BACKWARD : 0) | 0; // FFmpegInvoke.AVSEEK_FLAG_ANY;
                    //seekFlag = FFmpegInvoke.AVSEEK_FLAG_BACKWARD; // | FFmpegInvoke.AVSEEK_FLAG_ANY;

                    seekFrameResult = ffmpeg.av_seek_frame(InputFormatContext, seekStreamIndex, targetTimestamp, seekFlag); // significantly faster than seek_file
                    //seekFrameResult = FFmpegInvoke.avformat_seek_file(InputFormatContext, streamIndex, long.MinValue, targetTimestamp, long.MaxValue, seekFlag);
                    if (seekFrameResult < Constants.SuccessCode)
                    {
                        if (LeadingFramesCache.IsEmpty == false)
                        {
                            RealtimeClock.Seek(LeadingFramesCache.FirstFrameTime);
                        }

                        var errorMessage = Helper.GetFFmpegErrorMessage(seekFrameResult);
                        ErrorOccurredCallback(this, new MediaPlaybackException(MediaPlaybackErrorSources.InternalSeekInput, MediaPlaybackErrorCode.SeekFailedFFmpeg,
                                                                               string.Format("FFmpeg av_seek_frame @ {1:0.000}: Failed with error code {0}. {2}", seekFrameResult, seekTime, errorMessage)));

                        return;
                    }
                    else
                    {
                        if (VideoCodecContext != null)
                        {
                            ffmpeg.avcodec_flush_buffers(VideoCodecContext);
                        }

                        if (AudioCodecContext != null)
                        {
                            ffmpeg.avcodec_flush_buffers(AudioCodecContext);
                        }
                    }

                    leadingFrameIndex = -1;
                    bufferedLeadingFrames.Clear();
                    bufferedLaggingFrames.Clear();

                    doSeekInStream        = false;
                    doSeekByPullingFrames = true;

                    while (doSeekByPullingFrames)
                    {
                        innerLoopCount++;

                        var frame = this.PullMediaFrame();
                        if (frame != null)
                        {
                            if (frame.StartTime < maxSeekStartTime)
                            {
                                frame.EnqueueRelease();
                                frameReleaseCount++;
                                continue;
                            }

                            if (frame.Type == bufferedLeadingFrames.Type)
                            {
                                leadingFrameIndex++;
                                if (leadingFrameIndex == 0 && frame.Type == bufferedLeadingFrames.Type && frame.StartTime - frame.Duration > maxSeekStartTime && maxSeekStartTime > 0M)
                                {
                                    seekTime -= seekOffsetLength;
                                    frame.EnqueueRelease();
                                    doSeekInStream      = true;
                                    lastFailedTimestamp = targetTimestamp;
                                    break;
                                }

                                // We are Full minus 1 at this point. We'll stop buffering
                                if (bufferedLeadingFrames.Count >= bufferedLeadingFrames.Capacity - 1)
                                {
                                    doSeekByPullingFrames = false;
                                }

                                bufferedLeadingFrames.Add(frame);
                            }
                            else if (frame.Type == bufferedLaggingFrames.Type)
                            {
                                // add the lagging frame no matter what
                                if (bufferedLaggingFrames.IsFull)
                                {
                                    bufferedLaggingFrames.RemoveFirst();
                                }

                                bufferedLaggingFrames.Add(frame);
                            }

                            // Find out if we have the frame
                            var seekFrameIndex    = bufferedLeadingFrames.IndexOf(renderTime, true);
                            var minimumFrameCount = (seekFrameIndex - 1) * 2;

                            // if we have more than enough frames in the buffer or we have reached a full or end condition, stop buffering frames
                            if (seekFrameIndex > 0)
                            {
                                if (bufferedLeadingFrames.Count >= minimumFrameCount || bufferedLeadingFrames.IsFull || IsAtEndOfStream)
                                {
                                    doSeekByPullingFrames = false;
                                }
                            }
                        }

                        // We're already padt the end of the stream. Natural duration was wron for the leading frames cache.
                        if (IsAtEndOfStream && bufferedLeadingFrames.Count <= 0)
                        {
                            doSeekInStream   = true;
                            seekTime        -= seekOffsetLength;
                            maxSeekStartTime = seekTime - allowedThreshold;
                            seekToLastFrame  = true;
                        }

                        if (doSeekInStream)
                        {
                            break;
                        }

                        if (doSeekByPullingFrames == false || IsAtEndOfStream)
                        {
                            LeadingFramesCache.Replace(bufferedLeadingFrames);
                            LaggingFramesCache.Replace(bufferedLaggingFrames);

                            if (seekToLastFrame && LeadingFramesCache.Count > 0)
                            {
                                RealtimeClock.Seek(LeadingFramesCache.LastFrameTime);
                            }

                            return;
                        }
                    }
                }
            }
            finally
            {
#if DEBUG
                seekStopwatch.Stop();
                SeekTimes.Add(seekStopwatch.ElapsedMilliseconds);
                InnerLoopCounts.Add(innerLoopCount);
                System.Diagnostics.Debug.WriteLine("Seek @ {6:0.000} = Long: {0:00}\t Short: {1:000}\t Short (AVG): {2:0.000}\t Waste Count: {3:000}\t Elapsed: {4}\tElapsed (AVG): {5:0.000}",
                                                   outerLoopCount, innerLoopCount, InnerLoopCounts.Average(), frameReleaseCount, seekStopwatch.ElapsedMilliseconds, SeekTimes.Average(), renderTime);
#endif
            }
        }