27const uint64_t Player::kSleepIntervalMiliSec = 100;
30 const bool preload_fill_buffer_mode)
31 : is_initialized_(false),
35 task_buffer_(nullptr) {
36 task_buffer_ = std::make_shared<PlayTaskBuffer>();
39 preload_fill_buffer_mode));
45 if (is_initialized_.exchange(
true)) {
46 AERROR <<
"player has been initialized.";
50 if (producer_->Init()) {
54 is_initialized_.store(
false);
60 struct termios old = {0};
62 if (tcgetattr(0, &old) < 0) {
63 perror(
"tcsetattr()");
65 old.c_lflag &= ~ICANON;
69 if (tcsetattr(0, TCSANOW, &old) < 0) {
70 perror(
"tcsetattr ICANON");
72 if (read(0, &buf, 1) < 0) {
75 old.c_lflag |= ICANON;
77 if (tcsetattr(0, TCSADRAIN, &old) < 0) {
78 perror(
"tcsetattr ~ICANON");
83bool Player::ThreadFunc_Play_Nohup() {
84 if (!is_initialized_.load()) {
85 AERROR <<
"please call Init firstly.";
89 if (!is_stopped_.exchange(
false)) {
90 AERROR <<
"player has been stopped.";
93 auto& play_param = producer_->play_param();
95 consumer_->Start(play_param.begin_time_ns);
96 const double total_progress_time_s =
97 static_cast<double>(play_param.end_time_ns - play_param.begin_time_ns) /
99 static_cast<double>(play_param.start_time_s);
104 consumer_->Continue();
107 double progress_time_s =
108 static_cast<double>(producer_->play_param().start_time_s);
109 if (consumer_->last_played_msg_real_time_ns() > 0) {
111 static_cast<double>(consumer_->last_played_msg_real_time_ns() -
112 consumer_->base_msg_play_time_ns() +
113 consumer_->base_msg_real_time_ns() -
114 producer_->play_param().begin_time_ns) /
118 producer_->WriteRecordProgress(progress_time_s, total_progress_time_s);
120 if (producer_->is_stopped() && task_buffer_->Empty()) {
124 std::this_thread::sleep_for(
125 std::chrono::milliseconds(kSleepIntervalMiliSec));
132void Player::ThreadFunc_Term() {
133 while (!is_stopped_.load()) {
140 is_paused_ = !is_paused_;
149 nohup_play_th_.reset(
new std::thread(&Player::ThreadFunc_Play_Nohup,
this));
153 if (!producer_->is_initialized()) {
156 if (is_preloaded_.load()) {
157 producer_->Reset(progress_s);
158 is_preloaded_.store(
false);
160 if (progress_s == 0) {
166 is_paused_.exchange(
false);
168 is_paused_.exchange(paused_status);
170 producer_->FillPlayTaskBuffer();
171 is_preloaded_.store(
true);
176 if (!is_initialized_.load()) {
177 AERROR <<
"please call Init firstly.";
181 if (!is_stopped_.exchange(
false)) {
182 AERROR <<
"player has been stopped.";
186 auto& play_param = producer_->play_param();
187 std::cout <<
"\nPlease wait " << play_param.preload_time_s
188 <<
" second(s) for loading...\n"
189 <<
"Hit Ctrl+C to stop, Space to pause, or 's' to step.\n"
193 auto preload_sec = play_param.preload_time_s;
195 std::this_thread::sleep_for(std::chrono::seconds(1));
199 auto delay_sec = play_param.delay_time_s;
201 std::this_thread::sleep_for(std::chrono::seconds(1));
205 consumer_->Start(play_param.begin_time_ns);
207 std::ios::fmtflags before(std::cout.flags());
208 std::cout << std::fixed;
209 const double total_progress_time_s =
210 static_cast<double>(play_param.end_time_ns - play_param.begin_time_ns) /
212 static_cast<double>(play_param.start_time_s);
214 term_thread_.reset(
new std::thread(&Player::ThreadFunc_Term,
this));
217 consumer_->PlayOnce();
218 is_playonce_ =
false;
222 std::cout <<
"\r[PAUSED ] Record Time: ";
224 consumer_->Continue();
225 std::cout <<
"\r[RUNNING] Record Time: ";
228 double last_played_msg_real_time_s =
229 static_cast<double>(consumer_->last_played_msg_real_time_ns()) / 1e9;
231 double progress_time_s =
232 static_cast<double>(producer_->play_param().start_time_s);
233 if (consumer_->last_played_msg_real_time_ns() > 0) {
235 static_cast<double>(consumer_->last_played_msg_real_time_ns() -
236 consumer_->base_msg_play_time_ns() +
237 consumer_->base_msg_real_time_ns() -
238 producer_->play_param().begin_time_ns) /
242 std::cout << std::setprecision(3) << last_played_msg_real_time_s
243 <<
" Progress: " << progress_time_s <<
" / "
244 << total_progress_time_s;
247 if (producer_->is_stopped() && task_buffer_->Empty()) {
251 std::this_thread::sleep_for(
252 std::chrono::milliseconds(kSleepIntervalMiliSec));
255 std::cout <<
"\nplay finished." << std::endl;
256 std::cout.flags(before);
261 if (is_stopped_.exchange(
true)) {
266 if (term_thread_ !=
nullptr && term_thread_->joinable()) {
267 term_thread_->join();
268 term_thread_ =
nullptr;
274 if (is_stopped_.exchange(
true)) {
279 producer_->set_stopped();
283 task_buffer_->Clear();
284 if (nohup_play_th_ !=
nullptr && nohup_play_th_->joinable()) {
285 nohup_play_th_->join();
286 nohup_play_th_ =
nullptr;
Player(const PlayParam &play_param, const NodePtr &node=nullptr, const bool preload_fill_buffer_mode=false)
void HandleNohupThreadStatus()
Pause or continue to play record by change the nohup process status.
bool Reset()
Reset player for dv will repeatedly use
void NohupPlayRecord()
set nohup process to play record.
bool PreloadPlayRecord(const double &progress_s=0, bool paused_status=false)
Preload the player,fill play_task_buffer ahead ofr time to ensure fast playback and avoid consumer wa...
std::shared_ptr< apollo::cyber::Node > NodePtr