// Video thread void Scheduler::video_thread_fn() { auto vid = GL::shared(file->video().width, file->video().height, file->video().aspect_ratio, file->video().ctx->pix_fmt); video = vid; auto event = GLEvent::shared(); if (file->sub().active) sub_renderer = ASSRenderer::shared(file->sub().fonts, file->sub().ass_data, file->video().width, file->video().height); AVFrame *frame = avcodec_alloc_frame(); // Add event handler for GL. add_event_handler(event); while (video_thread_active && vid_pkt_queue.alive()) { event->poll(); avlock.lock(); if (vid_pkt_queue.size() > 0 && !is_paused) { auto pkt = vid_pkt_queue.pull(); avlock.unlock(); process_video(pkt.get(), vid, frame); if (file->sub().active) process_subtitle(vid); // We have to calculate how long we should wait before swapping frame to screen. // We sync everything to audio clock. double delta = get_time(); avlock.lock(); delta -= audio_pts_ts; double sleep_time = video_pts - (audio_pts + delta); avlock.unlock(); // Yes, it can happen! :( if (delta < 0.0) delta = 0.0; //std::cout << "Delta: " << delta << std::endl; if (video_pts > (audio_pts + delta) && audio_thread_active) { double last_frame_delta = get_time(); last_frame_delta -= video_pts_ts; // :( if (last_frame_delta < 0.0) last_frame_delta = 0.0; // We try to keep the sleep time to a somewhat small value to avoid choppy video in some cases. // Max sleep time should be a bit over 1 frame time to allow audio to catch up. double max_sleep = 1.2 * frame_time() - last_frame_delta; if (max_sleep < 0.0) max_sleep = 0.0; if (sleep_time > max_sleep) { sleep_time = max_sleep; } //std::cout << "Sleep for " << sleep_time << std::endl; sync_sleep(sleep_time); } video_pts_ts = get_time(); vid->flip(); } else { avlock.unlock(); if (is_paused) sync_sleep(0.01); else { // Having some race conditions... quickfix it for now. vid_pkt_queue.wait(); //sync_sleep(0.01); //vid_pkt_queue.signal(); } } } video_thread_active = false; av_free(frame); }
//------------------------------------------------------------------- // PURPOSE: Parse script (conf.script_file) for parameters and title //------------------------------------------------------------------- static void script_scan() { // Reset everything sc_param *p = script_params; while (p) { if (p->name) free(p->name); if (p->desc) free(p->desc); if (p->options) free(p->options); if (p->option_buf) free(p->option_buf); sc_param *l = p; p = p->next; free(l); } script_params = tail = 0; script_param_count = 0; parse_version(&script_version, "1.3.0.0", 0); script_has_version = 0; is_script_loaded = 0; // Load script file const char *buf=0; if (conf.script_file[0] != 0) buf = load_file_to_length(conf.script_file, 0, 1, 4096); // Assumes parameters are in first 4K of script file // Check file loaded if (buf == 0) { strcpy(script_title, "NO SCRIPT"); return; } // Build title from name (in case no title in script) const char *c = get_script_filename(); strncpy(script_title, c, sizeof(script_title)-1); script_title[sizeof(script_title)-1]=0; // Fillup order, defaults const char *ptr = buf; while (ptr[0]) { ptr = skip_whitespace(ptr); if (ptr[0] == '@') { if (strncmp("@title", ptr, 6)==0) { process_title(ptr+6); } else if (strncmp("@subtitle", ptr, 9)==0) { process_subtitle(ptr+9); } else if (strncmp("@param", ptr, 6)==0) { process_param(ptr+6); } else if (strncmp("@default", ptr, 8)==0) { process_default(ptr+8, 1); } else if (strncmp("@range", ptr, 6)==0) { process_range(ptr+6); } else if (strncmp("@values", ptr, 7)==0) { process_values(ptr+7); } else if (strncmp("@chdk_version", ptr, 13)==0) { ptr = skip_whitespace(ptr+13); parse_version(&script_version, ptr, 0); script_has_version = 1; } } else if (ptr[0] == '#') { process_single(ptr+1); } ptr = skip_eol(ptr); } free((void*)buf); is_script_loaded = 1; }