void ltc_time_to_frame(LTCFrame* frame, SMPTETimecode* stime, enum LTC_TV_STANDARD standard, int flags) { if (flags & LTC_USE_DATE) { smpte_set_timezone_code(stime, frame); frame->user6 = stime->years/10; frame->user5 = stime->years - frame->user6*10; frame->user4 = stime->months/10; frame->user3 = stime->months - frame->user4*10; frame->user2 = stime->days/10; frame->user1 = stime->days - frame->user2*10; } frame->hours_tens = stime->hours/10; frame->hours_units = stime->hours - frame->hours_tens*10; frame->mins_tens = stime->mins/10; frame->mins_units = stime->mins - frame->mins_tens*10; frame->secs_tens = stime->secs/10; frame->secs_units = stime->secs - frame->secs_tens*10; frame->frame_tens = stime->frame/10; frame->frame_units = stime->frame - frame->frame_tens*10; // Prevent illegal SMPTE frames if (frame->dfbit) { skip_drop_frames(frame); } if ((flags & LTC_NO_PARITY) == 0) { ltc_frame_set_parity(frame, standard); } }
int ltc_encoder_reinit(LTCEncoder *e, double sample_rate, double fps, enum LTC_TV_STANDARD standard, int flags) { if (sample_rate < 1) return -1; size_t bufsize = 1 + ceil(sample_rate / fps); if (bufsize > e->bufsize) { return -1; } e->state = 0; e->offset = 0; e->sample_rate = sample_rate; ltc_encoder_set_filter(e, 40.0); e->fps = fps; e->flags = flags; e->standard = standard; e->samples_per_clock = sample_rate / (fps * 80.0); e->samples_per_clock_2 = e->samples_per_clock / 2.0; e->sample_remainder = 0.5; if (flags & LTC_BGF_DONT_TOUCH) { e->f.col_frame = 0; if (flags<C_TC_CLOCK) { e->f.binary_group_flag_bit1 = 1; } else { e->f.binary_group_flag_bit1 = 0; } switch (standard) { case LTC_TV_625_50: /* 25 fps mode */ e->f.biphase_mark_phase_correction = 0; // BGF0 e->f.binary_group_flag_bit0 = (flags<C_USE_DATE)?1:0; // BGF2 break; default: e->f.binary_group_flag_bit0 = 0; e->f.binary_group_flag_bit2 = (flags<C_USE_DATE)?1:0; break; } } if ((flags<C_NO_PARITY) == 0) { ltc_frame_set_parity(&e->f, standard); } if ((int)rint(fps * 100.0) == 2997) e->f.dfbit = 1; else e->f.dfbit = 0; return 0; }
int ltc_frame_decrement(LTCFrame* frame, int fps, enum LTC_TV_STANDARD standard, int flags) { int rv = 0; int frames = frame->frame_units + frame->frame_tens * 10; if (frames > 0) { frames--; } else { frames = fps -1; } frame->frame_units = frames % 10; frame->frame_tens = frames / 10; if (frames == fps -1) { int secs = frame->secs_units + frame->secs_tens * 10; if (secs > 0) { secs--; } else { secs = 59; } frame->secs_units = secs % 10; frame->secs_tens = secs / 10; if (secs == 59) { int mins = frame->mins_units + frame->mins_tens * 10; if (mins > 0) { mins--; } else { mins = 59; } frame->mins_units = mins % 10; frame->mins_tens = mins / 10; if (mins == 59) { int hours = frame->hours_units + frame->hours_tens * 10; if (hours > 0) { hours--; } else { hours = 23; } frame->hours_units = hours % 10; frame->hours_tens = hours / 10; if (hours == 23) { /* 24h wrap around */ rv=1; if (flags<C_USE_DATE) { /* wrap date */ SMPTETimecode stime; stime.years = frame->user5 + frame->user6*10; stime.months = frame->user3 + frame->user4*10; stime.days = frame->user1 + frame->user2*10; if (stime.months > 0 && stime.months < 13) { unsigned char dpm[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; /* proper leap-year calc: * ((stime.years%4)==0 && ( (stime.years%100) != 0 || (stime.years%400) == 0) ) * simplified since year is 0..99 */ if ((stime.years%4)==0 /* && stime.years!=0 */ ) /* year 2000 was a leap-year */ dpm[1]=29; // if (stime.days > 1) { stime.days--; } else { stime.months = 1 + (stime.months + 10)%12; stime.days = dpm[stime.months-1]; if (stime.months == 12) { stime.years=(stime.years+99)%100; // XXX } } frame->user6 = stime.years/10; frame->user5 = stime.years%10; frame->user4 = stime.months/10; frame->user3 = stime.months%10; frame->user2 = stime.days/10; frame->user1 = stime.days%10; } else { rv=-1; } } } } } } if (frame->dfbit && /* prevent endless recursion */ fps > 2) { if ((frame->mins_units != 0) && (frame->secs_units == 0) && (frame->secs_tens == 0) && (frame->frame_units == 1) && (frame->frame_tens == 0) ) { ltc_frame_decrement(frame, fps, standard, flags<C_USE_DATE); ltc_frame_decrement(frame, fps, standard, flags<C_USE_DATE); } } if ((flags & LTC_NO_PARITY) == 0) { ltc_frame_set_parity(frame, standard); } return rv; }
int ltc_frame_increment(LTCFrame* frame, int fps, enum LTC_TV_STANDARD standard, int flags) { int rv = 0; frame->frame_units++; if (frame->frame_units == 10) { frame->frame_units = 0; frame->frame_tens++; } if (fps == frame->frame_units+frame->frame_tens*10) { frame->frame_units = 0; frame->frame_tens = 0; frame->secs_units++; if (frame->secs_units == 10) { frame->secs_units = 0; frame->secs_tens++; if (frame->secs_tens == 6) { frame->secs_tens = 0; frame->mins_units++; if (frame->mins_units == 10) { frame->mins_units = 0; frame->mins_tens++; if (frame->mins_tens == 6) { frame->mins_tens = 0; frame->hours_units++; if (frame->hours_units == 10) { frame->hours_units = 0; frame->hours_tens++; } if (frame->hours_units == 4 && frame->hours_tens==2) { /* 24h wrap around */ rv=1; frame->hours_tens=0; frame->hours_units = 0; if (flags&1) { /* wrap date */ SMPTETimecode stime; stime.years = frame->user5 + frame->user6*10; stime.months = frame->user3 + frame->user4*10; stime.days = frame->user1 + frame->user2*10; if (stime.months > 0 && stime.months < 13) { unsigned char dpm[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; /* proper leap-year calc: * ((stime.years%4)==0 && ( (stime.years%100) != 0 || (stime.years%400) == 0) ) * simplified since year is 0..99 */ if ((stime.years%4)==0 /* && stime.years!=0 */ ) /* year 2000 was a leap-year */ dpm[1]=29; stime.days++; if (stime.days > dpm[stime.months-1]) { stime.days=1; stime.months++; if (stime.months > 12) { stime.months=1; stime.years=(stime.years+1)%100; } } frame->user6 = stime.years/10; frame->user5 = stime.years%10; frame->user4 = stime.months/10; frame->user3 = stime.months%10; frame->user2 = stime.days/10; frame->user1 = stime.days%10; } else { rv=-1; } } } } } } } } if (frame->dfbit) { skip_drop_frames(frame); } if ((flags & LTC_NO_PARITY) == 0) { ltc_frame_set_parity(frame, standard); } return rv; }