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()
51 if (reader->info.has_audio)
52 audioPlayback->startThread(8);
53 if (reader->info.has_video) {
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) {
138 }
else if (video_position + speed > reader->info.video_length) {
140 video_position = reader->info.video_length;
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);
160 }
catch (
const ReaderClosed & e) {
162 }
catch (
const OutOfBoundsFrame & e) {
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);
Header file for all Exception classes.
Source file for PlayerPrivate class.
The audio playback thread.
This is the base class of all Renderers in libopenshot.
The video playback class.
This namespace is the default namespace for all code in the openshot library.