Skip to content

Commit

Permalink
Fixed high CPU on video playback and video freezing after resuming fr…
Browse files Browse the repository at this point in the history
…om sleep (#520)

Some snap videos ( ie. Proggetto Snaps ) consumed excessive amount of CPU. This was caused by  max_sleep being dependent on the time base instead of the frame rate.
Fixed video freezing after resuming from sleep, which was caused by only showing key frames.  Videos now restart when computer wakes up.
  • Loading branch information
oomek authored and mickelson committed Dec 22, 2018
1 parent f08fb01 commit 2ccc959
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions src/media.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class FeBaseStream
virtual ~FeBaseStream();

bool at_end; // set when at the end of our input
bool far_behind;
AVCodecContext *codec_ctx;
AVCodec *codec;
int stream_id;
Expand Down Expand Up @@ -199,6 +200,7 @@ class FeVideoImp : public FeBaseStream
public:
bool run_video_thread;
sf::Time time_base;
sf::Time max_sleep;
sf::Clock video_timer;
sf::Texture *display_texture;
SwsContext *sws_ctx;
Expand Down Expand Up @@ -259,6 +261,7 @@ void FeMediaImp::close()

FeBaseStream::FeBaseStream()
: at_end( false ),
far_behind( false ),
codec_ctx( NULL ),
codec( NULL ),
stream_id( -1 )
Expand All @@ -277,13 +280,15 @@ FeBaseStream::~FeBaseStream()

codec = NULL;
at_end = false;
far_behind = false;
stream_id = -1;
}

void FeBaseStream::stop()
{
clear_packet_queue();
at_end=false;
far_behind = false;
}

AVPacket *FeBaseStream::pop_packet()
Expand Down Expand Up @@ -588,8 +593,6 @@ void FeVideoImp::preload()

void FeVideoImp::video_thread()
{
sf::Time max_sleep = time_base / (sf::Int64)2;

const int QMAX = 16;
const int QMIN = 0;
int qscore( 10 ); // quality scoring
Expand All @@ -601,6 +604,8 @@ void FeVideoImp::video_thread()
int64_t prev_pts = 0;
int64_t prev_duration = 0;

sf::Time wait_time;

if ((!sws_ctx) || (!rgba_buffer[0]))
{
FeLog() << "Error initializing video thread" << std::endl;
Expand All @@ -610,12 +615,26 @@ void FeVideoImp::video_thread()
while ( run_video_thread )
{
bool do_process = true;

//
// If we are falling behind for more than 2 seconds
// it can only mean that we are in suspend/hibernation state,
// so we flag the video to be restarted on the next tick.
// This prevents displaying only keyframes for several seconds on wake.
//
if ( wait_time < sf::seconds( -2.0f ) )
{
wait_time = sf::seconds( 0 );
far_behind = true;
run_video_thread = false;
}

//
// First, display queued frame
//
if ( detached_frame )
{
sf::Time wait_time = (sf::Int64)detached_frame->pts * time_base
wait_time = (sf::Int64)detached_frame->pts * time_base
- m_parent->get_video_time();

if ( wait_time < max_sleep )
Expand Down Expand Up @@ -863,6 +882,9 @@ void FeMedia::close()

bool FeMedia::is_playing()
{
if ((m_video) && (m_video->far_behind))
return false;

if ((m_video) && (!m_video->at_end))
return (m_video->run_video_thread);

Expand Down Expand Up @@ -1066,6 +1088,8 @@ bool FeMedia::open( const std::string &archive,
m_video->time_base = sf::seconds(
av_q2d(m_imp->m_format_ctx->streams[stream_id]->time_base) );

m_video->max_sleep = sf::seconds( 0.5 / av_q2d(m_imp->m_format_ctx->streams[stream_id]->r_frame_rate));

float aspect_ratio = 1.0;
if ( codec_ctx->sample_aspect_ratio.num != 0 )
aspect_ratio = av_q2d( codec_ctx->sample_aspect_ratio );
Expand Down

0 comments on commit 2ccc959

Please sign in to comment.