void gtimer_arm_abs(gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when) { lock_assert(&global_lock); if(gti->gti_callback != NULL) LIST_REMOVE(gti, gti_link); gti->gti_callback = callback; gti->gti_opaque = opaque; gti->gti_expire = when; LIST_INSERT_SORTED(>imers, gti, gti_link, gtimercmp); }
static void vda_callback(void *aux, CFDictionaryRef frame_info, OSStatus status, uint32_t infoFlags, CVImageBufferRef buf) { vda_decoder_t *vdad = aux; CFNumberRef ref; vda_frame_t *vf; uint8_t skip; if(buf == NULL) return; ref = CFDictionaryGetValue(frame_info, CFSTR("skip")); CFNumberGetValue(ref, kCFNumberSInt8Type, &skip); if(skip) return; vf = malloc(sizeof(vda_frame_t)); ref = CFDictionaryGetValue(frame_info, CFSTR("pts")); CFNumberGetValue(ref, kCFNumberSInt64Type, &vf->vf_pts); ref = CFDictionaryGetValue(frame_info, CFSTR("duration")); CFNumberGetValue(ref, kCFNumberSInt32Type, &vf->vf_duration); ref = CFDictionaryGetValue(frame_info, CFSTR("epoch")); CFNumberGetValue(ref, kCFNumberSInt8Type, &vf->vf_epoch); ref = CFDictionaryGetValue(frame_info, CFSTR("drive_clock")); CFNumberGetValue(ref, kCFNumberSInt8Type, &vf->vf_drive_clock); vf->vf_buf = buf; CFRetain(buf); hts_mutex_lock(&vdad->vdad_mutex); LIST_INSERT_SORTED(&vdad->vdad_frames, vf, vf_link, vf_cmp, vda_frame_t); if(vdad->vdad_max_ts != PTS_UNSET) { if(vf->vf_pts > vdad->vdad_max_ts) { vdad->vdad_flush_to = vdad->vdad_max_ts; vdad->vdad_max_ts = vf->vf_pts; } } else { vdad->vdad_max_ts = vf->vf_pts; } hts_mutex_unlock(&vdad->vdad_mutex); }
void gtimer_arm_abs2 (gtimer_t *gti, gti_callback_t *callback, void *opaque, struct timespec *when) { lock_assert(&global_lock); if (gti->gti_callback != NULL) LIST_REMOVE(gti, gti_link); gti->gti_callback = callback; gti->gti_opaque = opaque; gti->gti_expire = *when; LIST_INSERT_SORTED(>imers, gti, gti_link, gtimercmp); //tvhdebug("gtimer", "%p @ %ld.%09ld", gti, when->tv_sec, when->tv_nsec); if (LIST_FIRST(>imers) == gti) pthread_cond_signal(>imer_cond); // force timer re-check }
void GTIMER_FCN(gtimer_arm_absn) (GTIMER_TRACEID_ gtimer_t *gti, gti_callback_t *callback, void *opaque, time_t when) { lock_assert(&global_lock); if (gti->gti_callback != NULL) LIST_REMOVE(gti, gti_link); gti->gti_callback = callback; gti->gti_opaque = opaque; gti->gti_expire = when; #if ENABLE_GTIMER_CHECK gti->gti_id = id; #endif LIST_INSERT_SORTED(>imers, gti, gti_link, gtimercmp); if (LIST_FIRST(>imers) == gti) pthread_cond_signal(>imer_cond); // force timer re-check }
void GTIMER_FCN(mtimer_arm_abs) (GTIMER_TRACEID_ mtimer_t *mti, mti_callback_t *callback, void *opaque, int64_t when) { lock_assert(&global_lock); if (mti->mti_callback != NULL) LIST_REMOVE(mti, mti_link); mti->mti_callback = callback; mti->mti_opaque = opaque; mti->mti_expire = when; #if ENABLE_GTIMER_CHECK mti->mti_id = id; #endif LIST_INSERT_SORTED(&mtimers, mti, mti_link, mtimercmp); if (LIST_FIRST(&mtimers) == mti) tvh_cond_signal(&mtimer_cond, 0); // force timer re-check }
static void htsp_tagAddUpdate(htsp_connection_t *hc, htsmsg_t *m, int create) { const char *id; htsmsg_t *members; htsmsg_field_t *f; prop_t *metadata, *before, *nodes; char txt[200]; int num = 0, i; htsp_tag_t *ht, *n; const char *title; if((id = htsmsg_get_str(m, "tagId")) == NULL) return; title = htsmsg_get_str(m, "tagName"); hts_mutex_lock(&hc->hc_meta_mutex); if(create) { ht = calloc(1, sizeof(htsp_tag_t)); ht->ht_id = strdup(id); ht->ht_title = strdup(title ?: ""); LIST_INSERT_SORTED(&hc->hc_tags, ht, ht_link, tag_compar); n = LIST_NEXT(ht, ht_link); ht->ht_root = prop_create_root(id); snprintf(txt, sizeof(txt), "htsp://%s:%d/tag/%s", hc->hc_hostname, hc->hc_port, id); prop_set_string(prop_create(ht->ht_root, "url"), txt); prop_set_string(prop_create(ht->ht_root, "type"), "directory"); if(prop_set_parent_ex(ht->ht_root, hc->hc_tags_nodes, n ? n->ht_root : NULL, NULL)) abort(); } else {
/* * Create/Find region entry */ static region_t *_muxes_region_create ( const char *type, const char *id, const char *desc ) { region_t *reg; region_list_t *list = NULL; if (!strcmp(type, "dvb-s")) list = ®ions_DVBS; else if (!strcmp(type, "dvb-t")) list = ®ions_DVBT; else if (!strcmp(type, "dvb-c")) list = ®ions_DVBC; else if (!strcmp(type, "atsc")) list = ®ions_ATSC; if (!list) return NULL; LIST_FOREACH(reg, list, link) { if (!strcmp(reg->id, id)) break; } if (!reg) { reg = calloc(1, sizeof(region_t)); reg->id = strdup(id); reg->name = strdup(desc); LIST_INSERT_SORTED(list, reg, link, _reg_cmp); } return reg; }
static void picture_out(vdec_decoder_t *vdd) { int r, lumasize; uint32_t addr; vdec_picture_format picfmt; vdec_pic_t *vp; char metainfo[64]; pktmeta_t *pm; picfmt.alpha = 0; picfmt.format_type = VDEC_PICFMT_YUV420P; picfmt.color_matrix = VDEC_COLOR_MATRIX_BT709; r = vdec_get_pic_item(vdd->handle, &addr); if(r != 0) return; vdec_picture *pi = (void *)(intptr_t)addr; pm = &vdd->pktmeta[pi->userdata[0]]; vdd->pending_flush |= pm->flush; if(/* pi->status != 0 ||*/ pi->attr != 0 || pm->skip) { vdec_get_picture(vdd->handle, &picfmt, NULL); reset_active_pictures(vdd, "pic err", 0); return; } if(vdd->pending_flush) { reset_active_pictures(vdd, "stream flush", 0); vdd->pending_flush = 0; vdd->max_order = -1; } int64_t pts = pm->nopts ? AV_NOPTS_VALUE : pi->pts[0].low + ((uint64_t)pi->pts[0].hi << 32); int64_t dts = pm->nodts ? AV_NOPTS_VALUE : pi->dts[0].low + ((uint64_t)pi->dts[0].hi << 32); int64_t order; if(pi->codec_type == VDEC_CODEC_TYPE_MPEG2) { vdec_mpeg2_info *mpeg2 = (void *)(intptr_t)pi->codec_specific_addr; lumasize = mpeg2->width * mpeg2->height; vp = alloc_picture(vdd, lumasize); vp->fi.fi_width = mpeg2->width; vp->fi.fi_height = mpeg2->height; vp->fi.fi_duration = mpeg2->frame_rate <= 8 ? mpeg_durations[mpeg2->frame_rate] : 40000; if(pm->disable_deinterlacer) { vp->fi.fi_interlaced = 0; } else { vp->fi.fi_interlaced = !mpeg2->progressive_frame; vp->fi.fi_tff = mpeg2->top_field_first; } if(mpeg2->color_description) vp->fi.fi_color_space = mpeg2->matrix_coefficients; switch(pm->aspect_override) { default: switch(mpeg2->aspect_ratio) { case VDEC_MPEG2_ARI_SAR_1_1: vp->fi.fi_dar_num = mpeg2->width; vp->fi.fi_dar_den = mpeg2->height; break; case VDEC_MPEG2_ARI_DAR_4_3: vp->fi.fi_dar_num = 4; vp->fi.fi_dar_den = 3; break; case VDEC_MPEG2_ARI_DAR_16_9: vp->fi.fi_dar_num = 16; vp->fi.fi_dar_den = 9; break; case VDEC_MPEG2_ARI_DAR_2P21_1: vp->fi.fi_dar_num = 221; vp->fi.fi_dar_den = 100; break; } break; case 1: vp->fi.fi_dar_num = 4; vp->fi.fi_dar_den = 3; break; case 2: vp->fi.fi_dar_num = 16; vp->fi.fi_dar_den = 9; break; } snprintf(metainfo, sizeof(metainfo), "MPEG2 %dx%d%c (Cell)", mpeg2->width, mpeg2->height, vp->fi.fi_interlaced ? 'i' : 'p'); if(pts == AV_NOPTS_VALUE && dts != AV_NOPTS_VALUE && mpeg2->picture_coding_type[0] == 3) pts = dts; #if VDEC_DETAILED_DEBUG TRACE(TRACE_DEBUG, "VDEC DEC", "%ld %d", pts, mpeg2->picture_coding_type[0]); #endif order = vdd->order_base; vdd->order_base++; } else { vdec_h264_info *h264 = (void *)(intptr_t)pi->codec_specific_addr; lumasize = h264->width * h264->height; vp = alloc_picture(vdd, lumasize); vp->fi.fi_width = h264->width; vp->fi.fi_height = h264->height; vp->fi.fi_duration = h264->frame_rate <= 7 ? mpeg_durations[h264->frame_rate + 1] : 40000; vp->fi.fi_interlaced = 0; vp->fi.fi_tff = 0; if(h264->color_description_present_flag) vp->fi.fi_color_space = h264->matrix_coefficients; vp->fi.fi_dar_num = h264->width; vp->fi.fi_dar_den = h264->height; if(h264->aspect_ratio_idc == 0xff) { vp->fi.fi_dar_num *= h264->sar_width; vp->fi.fi_dar_den *= h264->sar_height; } else { const uint8_t *p; p = h264_sar[h264->aspect_ratio_idc <= 16 ? h264->aspect_ratio_idc : 0]; vp->fi.fi_dar_num *= p[0]; vp->fi.fi_dar_den *= p[1]; } if(h264->idr_picture_flag) { vdd->order_base += 0x100000000LL; vdd->poc_ext = 0; } uint32_t om = h264->pic_order_count[0] & 0x7fff; int p = om >> 13; if(p == ((vdd->poc_ext + 1) & 3)) { vdd->poc_ext = p; if(p == 0) vdd->order_base += 0x100000000LL; } if(p == 3 && vdd->poc_ext == 0) { order = vdd->order_base + om - 0x100000000LL; } else { order = vdd->order_base + om; } if(pts == AV_NOPTS_VALUE && dts != AV_NOPTS_VALUE) { if(h264->picture_type[0] == 2) { vdd->seen_b_frames = 100; pts = dts; } if(vdd->seen_b_frames) vdd->seen_b_frames--; if(!vdd->seen_b_frames) pts = dts; } #if VDEC_DETAILED_DEBUG TRACE(TRACE_DEBUG, "VDEC DEC", "POC=%3d:%-3d IDR=%d PS=%d LD=%d %x 0x%llx %ld %d", (uint16_t)h264->pic_order_count[0], (uint16_t)h264->pic_order_count[1], h264->idr_picture_flag, h264->pic_struct, h264->low_delay_hrd_flag, h264->nalUnitPresentFlags, order, pts, h264->picture_type[0]); #endif if(vdd->level_major) snprintf(metainfo, sizeof(metainfo), "h264 (Level %d.%d) %dx%d%c (Cell)", vdd->level_major, vdd->level_minor, h264->width, h264->height, vp->fi.fi_interlaced ? 'i' : 'p'); else snprintf(metainfo, sizeof(metainfo), "h264 %dx%d%c (Cell)", h264->width, h264->height, vp->fi.fi_interlaced ? 'i' : 'p'); } prop_set_string(vdd->metainfo, metainfo); vp->fi.fi_pix_fmt = PIX_FMT_YUV420P; vp->fi.fi_pts = pts; vp->fi.fi_epoch = pm->epoch; vp->fi.fi_prescaled = 0; vp->fi.fi_color_space = COLOR_SPACE_UNSET; vp->fi.fi_delta = pm->delta; vp->fi.fi_drive_clock = pm->drive_clock; vdec_get_picture(vdd->handle, &picfmt, rsx_to_ppu(vp->vp_offset)); vp->order = order; hts_mutex_lock(&vdd->mtx); LIST_INSERT_SORTED(&vdd->pictures, vp, link, vp_cmp); if(vdd->max_order != -1) { if(vp->order > vdd->max_order) { vdd->flush_to = vdd->max_order; vdd->max_order = vp->order; } } else { vdd->max_order = vp->order; } hts_mutex_unlock(&vdd->mtx); }
/* * Process a file */ static void scanfile_load_file ( const char *type, fb_dir *dir, const char *name ) { int i, opos; fb_file *fp; scanfile_region_t *reg = NULL; scanfile_network_t *net; char *str; char buf[256], buf2[256], buf3[256]; tvhtrace("scanfile", "load file %s", name); fp = fb_open2(dir, name, 1, 0); if (!fp) return; /* Region */ strncpy(buf, name, sizeof(buf)); if (!strcmp(type, "dvb-s")) { reg = scanfile_region_create(type, "geo", "Geo-synchronous Orbit"); } else { str = buf; while (*str) { if (*str == '-') { *str = '\0'; reg = scanfile_region_create(type, buf, tldcode2longname(buf)); *str = '-'; break; } str++; } } if (!reg) { fb_close(fp); return; } /* Network */ str = buf; while (*str) { if (!isprint(*str)) *str = '_'; str++; } *str = '\0'; if (!strcmp(type, "dvb-s") && scanfile_network_dvbs_pos(buf, &opos)) { snprintf(buf3, sizeof(buf3), "%c%3i.%i%c:%s", opos < 0 ? '<' : '>', abs(opos) / 10, abs(opos) % 10, opos < 0 ? 'W' :'E', buf); strcpy(buf, buf3); } snprintf(buf2, sizeof(buf2), "%s_%s", type, buf); net = calloc(1, sizeof(scanfile_network_t)); net->sfn_id = strdup(buf2); net->sfn_name = strdup(buf); LIST_INSERT_SORTED(®->sfr_networks, net, sfn_link, scanfile_network_cmp); /* Process file */ while (!fb_eof(fp)) { /* Get line */ memset(buf, 0, sizeof(buf)); if (!fb_gets(fp, buf, sizeof(buf) - 1)) break; i = 0; while (buf[i]) { if (buf[i] == '#') buf[i] = '\0'; else i++; } while (i > 0 && buf[i-1] < 32) buf[--i] = 0; /* Process mux */ switch (*buf) { case 'A': case 'C': case 'T': case 'S': scanfile_load_one(net, buf); default: break; } } fb_close(fp); }
/* * Process a file */ static void _muxes_load_file ( const char *type, fb_dir *dir, const char *name ) { int i; fb_file *fp; region_t *reg = NULL; network_t *net; char *str; char buf[256], buf2[256]; fp = fb_open2(dir, name, 1, 0); if (!fp) return; /* Region */ strncpy(buf, name, sizeof(buf)); if (!strcmp(type, "dvb-s")) { reg = _muxes_region_create(type, "geo", "Geo-synchronous Orbit"); } else { str = buf; while (*str) { if (*str == '-') { *str = '\0'; reg = _muxes_region_create(type, buf, tldcode2longname(buf)); *str = '-'; break; } str++; } } if (!reg) { fb_close(fp); return; } /* Network */ str = buf; while (*str) { if (!isalnum(*str)) *str = '_'; str++; } *str = '\0'; snprintf(buf2, sizeof(buf2), "%s_%s", type, buf); net = calloc(1, sizeof(network_t)); net->id = strdup(buf2); net->name = strdup(buf); LIST_INSERT_SORTED(®->networks, net, link, _net_cmp); /* Process file */ while (!fb_eof(fp)) { /* Get line */ memset(buf, 0, sizeof(buf)); if (!fb_gets(fp, buf, sizeof(buf) - 1)) break; i = 0; while (buf[i]) { if (buf[i] == '#') buf[i] = '\0'; else i++; } while (i > 0 && buf[i-1] < 32) buf[--i] = 0; /* Process mux */ switch (*buf) { case 'A': case 'C': case 'T': case 'S': _muxes_load_one(net, buf); default: break; } } fb_close(fp); }