Skip to content

Commit 4c09985

Browse files
committed
10x less CPU overload! :D
1 parent 51f367d commit 4c09985

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

SeeShark/FFmpeg/VideoStreamDecoder.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public unsafe class VideoStreamDecoder : Disposable
2121
protected readonly AVFormatContext* FormatContext;
2222
protected readonly Frame Frame;
2323
protected readonly AVPacket* Packet;
24+
protected readonly AVStream* Stream;
2425
protected readonly int StreamIndex;
2526

2627
public readonly string CodecName;
@@ -43,9 +44,10 @@ public VideoStreamDecoder(string url, AVInputFormat* inputFormat = null)
4344
StreamIndex = ffmpeg
4445
.av_find_best_stream(formatContext, AVMediaType.AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0)
4546
.ThrowExceptionIfError();
47+
Stream = formatContext->streams[StreamIndex];
4648
CodecContext = ffmpeg.avcodec_alloc_context3(codec);
4749

48-
ffmpeg.avcodec_parameters_to_context(CodecContext, formatContext->streams[StreamIndex]->codecpar)
50+
ffmpeg.avcodec_parameters_to_context(CodecContext, Stream->codecpar)
4951
.ThrowExceptionIfError();
5052
ffmpeg.avcodec_open2(CodecContext, codec, null).ThrowExceptionIfError();
5153

@@ -58,6 +60,13 @@ public VideoStreamDecoder(string url, AVInputFormat* inputFormat = null)
5860
Frame = new Frame();
5961
}
6062

63+
/// <summary>
64+
/// Trigger field, used to decide whether we wait longer during a Thread.Sleep()
65+
/// when there are no frames available.
66+
/// </summary>
67+
/// <remarks>
68+
/// Waiting longer would mean a full frame interval (for example ~16ms when 60 fps), 1ms otherwise.
69+
private bool waitLonger = false;
6170
public DecodeStatus TryDecodeNextFrame(out Frame nextFrame)
6271
{
6372
int eagain = ffmpeg.AVERROR(ffmpeg.EAGAIN);
@@ -74,8 +83,13 @@ public DecodeStatus TryDecodeNextFrame(out Frame nextFrame)
7483
{
7584
nextFrame = Frame;
7685
GC.Collect();
77-
Thread.Sleep(1);
7886

87+
// Big brain move to avoid overloading the CPU \o/
88+
AVRational fps = Stream->r_frame_rate;
89+
Thread.Sleep(waitLonger ? 1000 * fps.den / (fps.num + 5) : 1);
90+
91+
// We only wait longer once to make sure we catch the frame on time.
92+
waitLonger = false;
7993
return error == eagain
8094
? DecodeStatus.NoFrameAvailable
8195
: DecodeStatus.EndOfStream;
@@ -98,6 +112,8 @@ public DecodeStatus TryDecodeNextFrame(out Frame nextFrame)
98112
error.ThrowExceptionIfError();
99113

100114
nextFrame = Frame;
115+
// Always wait longer just after receiving a new frame.
116+
waitLonger = true;
101117
GC.Collect();
102118
return DecodeStatus.NewFrame;
103119
}

0 commit comments

Comments
 (0)