26 : renderer(rb), Thread(
"player"), video_position(1), audio_position(0),
27 speed(1), reader(NULL), last_video_position(1), max_sleep_ms(125000), playback_frames(0), is_dirty(true)
35 PlayerPrivate::~PlayerPrivate()
44 void PlayerPrivate::run()
52 audioPlayback->startThread(8);
54 videoCache->startThread(2);
55 videoPlayback->startThread(4);
58 using std::chrono::duration_cast;
61 using micro_sec = std::chrono::microseconds;
62 using double_micro_sec = std::chrono::duration<double, micro_sec::period>;
65 std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds> start_time;
66 start_time = std::chrono::time_point_cast<micro_sec>(std::chrono::system_clock::now());
68 while (!threadShouldExit()) {
70 int frame_speed = std::max(abs(speed), 1);
71 const auto frame_duration = double_micro_sec(1000000.0 / (reader->
info.
fps.
ToDouble() * frame_speed));
72 const auto max_sleep = frame_duration * 4;
77 if ((speed == 0 && video_position == last_video_position) ||
78 (speed != 0 && last_speed != speed) ||
79 (speed != 0 && !is_dirty && !videoCache->
isReady()))
82 std::this_thread::sleep_for(frame_duration / 4);
85 start_time = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
90 audioPlayback->Seek(video_position);
99 videoPlayback->frame = frame;
100 videoPlayback->render.signal();
103 last_video_position = video_position;
107 const auto current_time = std::chrono::system_clock::now();
108 const auto remaining_time = double_micro_sec(start_time +
109 (frame_duration * playback_frames) - current_time);
112 if (remaining_time > remaining_time.zero() ) {
113 if (remaining_time < max_sleep) {
114 std::this_thread::sleep_for(remaining_time);
117 std::this_thread::sleep_for(max_sleep);
124 std::shared_ptr<openshot::Frame> PlayerPrivate::getFrame()
131 if (video_position + speed >= 1 && video_position + speed <= reader->info.video_length) {
132 video_position = video_position + speed;
134 }
else if (video_position + speed < 1) {
144 if (frame && frame->number == video_position && video_position == last_video_position) {
151 playback_frames += std::abs(speed);
154 videoCache->
Seek(video_position);
157 return reader->
GetFrame(video_position);
165 return std::shared_ptr<openshot::Frame>();
169 void PlayerPrivate::Seek(int64_t new_position)
171 video_position = new_position;
172 last_video_position = 0;
177 bool PlayerPrivate::startPlayback()
179 if (video_position < 0)
return false;
187 void PlayerPrivate::stopPlayback()
189 if (videoCache->isThreadRunning() && reader->
info.
has_video) videoCache->stopThread(max_sleep_ms);
190 if (audioPlayback->isThreadRunning() && reader->
info.
has_audio) audioPlayback->stopThread(max_sleep_ms);
191 if (videoPlayback->isThreadRunning() && reader->
info.
has_video) videoPlayback->stopThread(max_sleep_ms);
192 if (isThreadRunning()) stopThread(max_sleep_ms);
double ToDouble() const
Return this fraction as a double (i.e. 1/2 = 0.5)
The audio playback thread.
Exception when a reader is closed, and a frame is requested.
bool has_video
Determines if this file has a video stream.
virtual std::shared_ptr< openshot::Frame > GetFrame(int64_t number)=0
Header file for all Exception classes.
bool has_audio
Determines if this file has an audio stream.
bool isReady()
Is cache ready for video/audio playback.
int64_t video_length
The number of frames in the video stream.
The video playback class.
Source file for PlayerPrivate class.
openshot::ReaderInfo info
Information about the current media file.
Exception for frames that are out of bounds.
This namespace is the default namespace for all code in the openshot library.
void Seek(int64_t new_position)
Seek the reader to a particular frame number.
This is the base class of all Renderers in libopenshot.
openshot::Fraction fps
Frames per second, as a fraction (i.e. 24/1 = 24 fps)