You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
Increasing max video cache frames, moving percentage-ahead caching to a setting, fixing a calculation error on bytes per frame
This commit is contained in:
@@ -78,6 +78,19 @@ namespace openshot
|
||||
Seek(new_position);
|
||||
}
|
||||
|
||||
// Get the size in bytes of a frame (rough estimate)
|
||||
int64_t VideoCacheThread::getBytes(int width, int height, int sample_rate, int channels, float fps)
|
||||
{
|
||||
int64_t total_bytes = 0;
|
||||
total_bytes += static_cast<int64_t>(width * height * sizeof(char) * 4);
|
||||
|
||||
// approximate audio size (sample rate / 24 fps)
|
||||
total_bytes += ((sample_rate * channels) / fps) * sizeof(float);
|
||||
|
||||
// return size of this frame
|
||||
return total_bytes;
|
||||
}
|
||||
|
||||
// Play the video
|
||||
void VideoCacheThread::Play() {
|
||||
// Start playing
|
||||
@@ -98,14 +111,14 @@ namespace openshot
|
||||
// Start the thread
|
||||
void VideoCacheThread::run()
|
||||
{
|
||||
// Get settings
|
||||
Settings *s = Settings::Instance();
|
||||
|
||||
// Types for storing time durations in whole and fractional microseconds
|
||||
using micro_sec = std::chrono::microseconds;
|
||||
using double_micro_sec = std::chrono::duration<double, micro_sec::period>;
|
||||
|
||||
while (!threadShouldExit() && is_playing) {
|
||||
// Get settings
|
||||
Settings *s = Settings::Instance();
|
||||
|
||||
// init local vars
|
||||
min_frames_ahead = s->VIDEO_CACHE_MIN_PREROLL_FRAMES;
|
||||
max_frames_ahead = s->VIDEO_CACHE_MAX_PREROLL_FRAMES;
|
||||
@@ -137,18 +150,24 @@ namespace openshot
|
||||
// To allow the cache to fill-up only on the initial pause.
|
||||
should_pause_cache = true;
|
||||
|
||||
// Calculate bytes per frame. If we have a reference openshot::Frame, use that instead (the preview
|
||||
// window can be smaller, can thus reduce the bytes per frame)
|
||||
int64_t bytes_per_frame = (reader->info.height * reader->info.width * 4) +
|
||||
(reader->info.sample_rate * reader->info.channels * 4);
|
||||
if (last_cached_frame && last_cached_frame->has_image_data && last_cached_frame->has_audio_data) {
|
||||
bytes_per_frame = last_cached_frame->GetBytes();
|
||||
// Calculate bytes per frame
|
||||
int64_t bytes_per_frame = getBytes(reader->info.width, reader->info.height,
|
||||
reader->info.sample_rate, reader->info.channels,
|
||||
reader->info.fps.ToFloat());
|
||||
Timeline *t = (Timeline *) reader;
|
||||
if (t->preview_width != reader->info.width || t->preview_height != reader->info.height) {
|
||||
// If we have a different timeline preview size, use that instead (the preview
|
||||
// window can be smaller, can thus reduce the bytes per frame)
|
||||
bytes_per_frame = getBytes(t->preview_width, t->preview_height,
|
||||
reader->info.sample_rate, reader->info.channels,
|
||||
reader->info.fps.ToFloat());
|
||||
}
|
||||
|
||||
// Calculate # of frames on Timeline cache (when paused)
|
||||
if (reader->GetCache() && reader->GetCache()->GetMaxBytes() > 0) {
|
||||
// When paused, use 1/2 the cache size (so our cache will be 50% before the play-head, and 50% after it)
|
||||
max_frames_ahead = (reader->GetCache()->GetMaxBytes() / bytes_per_frame) / 2;
|
||||
// When paused, limit the cached frames to the following % of total cache size.
|
||||
// This allows for us to leave some cache behind the plahead, and some in front of the playhead.
|
||||
max_frames_ahead = (reader->GetCache()->GetMaxBytes() / bytes_per_frame) * s->VIDEO_CACHE_PERCENT_AHEAD;
|
||||
if (max_frames_ahead > s->VIDEO_CACHE_MAX_FRAMES) {
|
||||
// Ignore values that are too large, and default to a safer value
|
||||
max_frames_ahead = s->VIDEO_CACHE_MAX_FRAMES;
|
||||
@@ -222,7 +241,7 @@ namespace openshot
|
||||
if (current_speed != speed) {
|
||||
break;
|
||||
}
|
||||
// Check if playback has stopped
|
||||
// Check if thread has stopped
|
||||
if (!is_playing) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ namespace openshot
|
||||
/// Destructor
|
||||
~VideoCacheThread();
|
||||
|
||||
/// Get the size in bytes of a frame (rough estimate)
|
||||
int64_t getBytes(int width, int height, int sample_rate, int channels, float fps);
|
||||
|
||||
/// Get Speed (The speed and direction to playback a reader (1=normal, 2=fast, 3=faster, -1=rewind, etc...)
|
||||
int getSpeed() const { return speed; }
|
||||
|
||||
|
||||
@@ -33,9 +33,10 @@ Settings *Settings::Instance()
|
||||
m_pInstance->DE_LIMIT_WIDTH_MAX = 1950;
|
||||
m_pInstance->HW_DE_DEVICE_SET = 0;
|
||||
m_pInstance->HW_EN_DEVICE_SET = 0;
|
||||
m_pInstance->VIDEO_CACHE_PERCENT_AHEAD = 0.75;
|
||||
m_pInstance->VIDEO_CACHE_MIN_PREROLL_FRAMES = 2;
|
||||
m_pInstance->VIDEO_CACHE_MAX_PREROLL_FRAMES = 8;
|
||||
m_pInstance->VIDEO_CACHE_MAX_FRAMES = 30 * 3;
|
||||
m_pInstance->VIDEO_CACHE_MAX_FRAMES = 30 * 20;
|
||||
m_pInstance->ENABLE_PLAYBACK_CACHING = true;
|
||||
m_pInstance->PLAYBACK_AUDIO_DEVICE_NAME = "";
|
||||
m_pInstance->PLAYBACK_AUDIO_DEVICE_TYPE = "";
|
||||
|
||||
@@ -82,6 +82,9 @@ namespace openshot {
|
||||
/// Which GPU to use to encode (0 is the first)
|
||||
int HW_EN_DEVICE_SET = 0;
|
||||
|
||||
/// Percentage of cache in front of the playhead (0.0 to 1.0)
|
||||
float VIDEO_CACHE_PERCENT_AHEAD = 0.75;
|
||||
|
||||
/// Minimum number of frames to cache before playback begins
|
||||
int VIDEO_CACHE_MIN_PREROLL_FRAMES = 2;
|
||||
|
||||
@@ -89,7 +92,7 @@ namespace openshot {
|
||||
int VIDEO_CACHE_MAX_PREROLL_FRAMES = 8;
|
||||
|
||||
/// Max number of frames (when paused) to cache for playback
|
||||
int VIDEO_CACHE_MAX_FRAMES = 30 * 3;
|
||||
int VIDEO_CACHE_MAX_FRAMES = 30 * 20;
|
||||
|
||||
/// Enable/Disable the cache thread to pre-fetch and cache video frames before we need them
|
||||
bool ENABLE_PLAYBACK_CACHING = true;
|
||||
|
||||
Reference in New Issue
Block a user