static void dvr_notify(dvr_entry_t *de, int now) { if (now || de->de_last_notify + 5 < dispatch_clock) { idnode_notify_simple(&de->de_id); de->de_last_notify = dispatch_clock; htsp_dvr_entry_update(de); } }
static void * dvr_thread(void *aux) { dvr_entry_t *de = aux; dvr_config_t *cfg = dvr_config_find_by_name_default(de->de_config_name); streaming_queue_t *sq = &de->de_sq; streaming_message_t *sm; th_pkt_t *pkt; int run = 1; int started = 0; int comm_skip = (cfg->dvr_flags & DVR_SKIP_COMMERCIALS); int commercial = COMMERCIAL_UNKNOWN; pthread_mutex_lock(&sq->sq_mutex); while(run) { sm = TAILQ_FIRST(&sq->sq_queue); if(sm == NULL) { pthread_cond_wait(&sq->sq_cond, &sq->sq_mutex); continue; } TAILQ_REMOVE(&sq->sq_queue, sm, sm_link); pthread_mutex_unlock(&sq->sq_mutex); switch(sm->sm_type) { case SMT_PACKET: pkt = sm->sm_data; if(pkt->pkt_commercial == COMMERCIAL_YES) dvr_rec_set_state(de, DVR_RS_COMMERCIAL, 0); else dvr_rec_set_state(de, DVR_RS_RUNNING, 0); if(pkt->pkt_commercial == COMMERCIAL_YES && comm_skip) break; if(commercial != pkt->pkt_commercial) muxer_add_marker(de->de_mux); commercial = pkt->pkt_commercial; if(started) { muxer_write_pkt(de->de_mux, sm->sm_type, sm->sm_data); sm->sm_data = NULL; } break; case SMT_MPEGTS: if(started) { dvr_rec_set_state(de, DVR_RS_RUNNING, 0); muxer_write_pkt(de->de_mux, sm->sm_type, sm->sm_data); sm->sm_data = NULL; } break; case SMT_START: if(started && muxer_reconfigure(de->de_mux, sm->sm_data) < 0) { tvhlog(LOG_WARNING, "dvr", "Unable to reconfigure \"%s\"", de->de_filename ?: lang_str_get(de->de_title, NULL)); // Try to restart the recording if the muxer doesn't // support reconfiguration of the streams. dvr_thread_epilog(de); started = 0; } if(!started) { pthread_mutex_lock(&global_lock); dvr_rec_set_state(de, DVR_RS_WAIT_PROGRAM_START, 0); if(dvr_rec_start(de, sm->sm_data) == 0) { started = 1; dvr_entry_notify(de); htsp_dvr_entry_update(de); dvr_entry_save(de); } pthread_mutex_unlock(&global_lock); } break; case SMT_STOP: if(sm->sm_code == SM_CODE_SOURCE_RECONFIGURED) { // Subscription is restarting, wait for SMT_START } else if(sm->sm_code == 0) { // Recording is completed de->de_last_error = 0; tvhlog(LOG_INFO, "dvr", "Recording completed: \"%s\"", de->de_filename ?: lang_str_get(de->de_title, NULL)); dvr_thread_epilog(de); started = 0; }else if(de->de_last_error != sm->sm_code) {
static void * dvr_thread(void *aux) { dvr_entry_t *de = aux; dvr_config_t *cfg = de->de_config; profile_chain_t *prch = de->de_chain; streaming_queue_t *sq = &prch->prch_sq; streaming_message_t *sm; th_subscription_t *ts; th_pkt_t *pkt; int run = 1; int started = 0; int comm_skip = cfg->dvr_skip_commercials; int commercial = COMMERCIAL_UNKNOWN; pthread_mutex_lock(&sq->sq_mutex); while(run) { sm = TAILQ_FIRST(&sq->sq_queue); if(sm == NULL) { pthread_cond_wait(&sq->sq_cond, &sq->sq_mutex); continue; } if ((ts = de->de_s) != NULL && started) { pktbuf_t *pb = NULL; if (sm->sm_type == SMT_PACKET) { pb = ((th_pkt_t*)sm->sm_data)->pkt_payload; if (((th_pkt_t*)sm->sm_data)->pkt_err) { de->de_data_errors += ((th_pkt_t*)sm->sm_data)->pkt_err; dvr_notify(de, 0); } } else if (sm->sm_type == SMT_MPEGTS) { pb = sm->sm_data; if (pb->pb_err) { de->de_data_errors += pb->pb_err; dvr_notify(de, 0); } } if (pb) atomic_add(&ts->ths_bytes_out, pktbuf_len(pb)); } TAILQ_REMOVE(&sq->sq_queue, sm, sm_link); pthread_mutex_unlock(&sq->sq_mutex); switch(sm->sm_type) { case SMT_PACKET: pkt = sm->sm_data; if(pkt->pkt_commercial == COMMERCIAL_YES) dvr_rec_set_state(de, DVR_RS_COMMERCIAL, 0); else dvr_rec_set_state(de, DVR_RS_RUNNING, 0); if(pkt->pkt_commercial == COMMERCIAL_YES && comm_skip) break; if(commercial != pkt->pkt_commercial) muxer_add_marker(prch->prch_muxer); commercial = pkt->pkt_commercial; if(started) { muxer_write_pkt(prch->prch_muxer, sm->sm_type, sm->sm_data); sm->sm_data = NULL; dvr_notify(de, 0); } break; case SMT_MPEGTS: if(started) { dvr_rec_set_state(de, DVR_RS_RUNNING, 0); muxer_write_pkt(prch->prch_muxer, sm->sm_type, sm->sm_data); sm->sm_data = NULL; dvr_notify(de, 0); } break; case SMT_START: if(started && muxer_reconfigure(prch->prch_muxer, sm->sm_data) < 0) { tvhlog(LOG_WARNING, "dvr", "Unable to reconfigure \"%s\"", de->de_filename ?: lang_str_get(de->de_title, NULL)); // Try to restart the recording if the muxer doesn't // support reconfiguration of the streams. dvr_thread_epilog(de); started = 0; } if(!started) { pthread_mutex_lock(&global_lock); dvr_rec_set_state(de, DVR_RS_WAIT_PROGRAM_START, 0); if(dvr_rec_start(de, sm->sm_data) == 0) { started = 1; idnode_changed(&de->de_id); htsp_dvr_entry_update(de); } pthread_mutex_unlock(&global_lock); } break; case SMT_STOP: if(sm->sm_code == SM_CODE_SOURCE_RECONFIGURED) { // Subscription is restarting, wait for SMT_START } else if(sm->sm_code == 0) { // Recording is completed de->de_last_error = 0; tvhlog(LOG_INFO, "dvr", "Recording completed: \"%s\"", de->de_filename ?: lang_str_get(de->de_title, NULL)); dvr_thread_epilog(de); started = 0; }else if(de->de_last_error != sm->sm_code) {