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(Priority::high);
53 if (reader->info.has_video) {
54 videoCache->startThread(Priority::high);
55 videoPlayback->startThread(Priority::high);
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;
182 startThread(Priority::high);
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);