clean-up: relocate NTSC drop-frame conversion functions
...extract these functions and the associated test
from the low-level C time handling library and
document them with a dedicated C++ header and test.
''This is unfinished work'' —
the extracted functions provide only the low level computations;
actually, a specialised time quantisation or time code would be required.
------------
Note though,
after extracting these functions, the rest of the plain-C test
can be removed, since equivalent functionality is covered in
much more detail by the tests of the C++ time handling framework.
Notably this allows to get rid of the direct component accessor functions.
------------
__Remark__: the base implementation of many time conversion functions
and especially NTSC drop-frame was provided by Stefan Kangas
See:
6a44134833
This commit is contained in:
parent
55b39ae592
commit
255fc82a1b
8 changed files with 305 additions and 661 deletions
|
|
@ -140,85 +140,6 @@ lumiera_time_of_gridpoint (int64_t nr, raw_time_64 origin, raw_time_64 grid);
|
||||||
raw_time_64
|
raw_time_64
|
||||||
lumiera_build_time (long millis, uint secs, uint mins, uint hours);
|
lumiera_build_time (long millis, uint secs, uint mins, uint hours);
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a time value by summing up the given components.
|
|
||||||
* @param fps framerate (frames per second)
|
|
||||||
* @param frames number of additional frames
|
|
||||||
* @param secs number of seconds
|
|
||||||
* @param mins number of minutes
|
|
||||||
* @param hours number of hours
|
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a time value by summing up the given components.
|
|
||||||
* The components are interpreted as a NTSC drop-frame timecode.
|
|
||||||
* @warning take care not to specify time codes that are illegal NTSC drop-frame times.
|
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours);
|
|
||||||
|
|
||||||
|
|
||||||
/** Extract the hour part of given time. */
|
|
||||||
int
|
|
||||||
lumiera_time_hours (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
/** Extract the minute part of given time. */
|
|
||||||
int
|
|
||||||
lumiera_time_minutes (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
/** Extract the seconds part of given time. */
|
|
||||||
int
|
|
||||||
lumiera_time_seconds (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
/** Extract the milliseconds part of given time. */
|
|
||||||
int
|
|
||||||
lumiera_time_millis (raw_time_64 time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the remaining frame part of given time.
|
|
||||||
* @param fps frame rate (frames per second)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_frames (raw_time_64 time, uint fps);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the frame part of given time, using NTSC drop-frame timecode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_frames (raw_time_64 time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the second part of given time, using NTSC drop-frame timecode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_seconds (raw_time_64 time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the minute part of given time, using NTSC drop-frame timecode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_minutes (raw_time_64 time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the hour part of given time, using NTSC drop-frame timecode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_hours (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal Diagnostics helper: render time value in H:MM:SS.mmm format.
|
|
||||||
* @return `safeclib` temporary buffer containing formatted time string
|
|
||||||
* @note any time output for real should go through quantisation followed
|
|
||||||
* by rendering into a suitable timecode format.
|
|
||||||
*/
|
|
||||||
char*
|
|
||||||
lumiera_tmpbuf_print_time (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
DROPFRAME.hpp - Utilities for handling time
|
DROPFRAME.hpp - drop-frame timecode conversions
|
||||||
|
|
||||||
Copyright (C)
|
Copyright (C)
|
||||||
2010, Stefan Kangas <skangas@skangas.se>
|
2010, Stefan Kangas <skangas@skangas.se>
|
||||||
|
|
@ -11,35 +11,39 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file dropframe.hpp
|
/** @file dropframe.hpp
|
||||||
** Common functions for handling of time values.
|
** Calculations to support mapping into NTSC drop frame timecode.
|
||||||
** Working with time values in sexagesimal format, quantising time and converting
|
** This is a scheme for mapping frame numbers to a time display in SMPTE format,
|
||||||
** to/from common timecode formats can be tricky to get right. Thus the goal is
|
** i.e. with hours, minutes, seconds and a frame count. It was introduced in USA
|
||||||
** to concentrate the actual bits of math for these operations into a small number
|
** at the time when colour television with the NTSC standard was introduced.
|
||||||
** of library functions, which are easy to test thoroughly in isolation.
|
** Since the existing black and white television broadcast system based on analogue
|
||||||
|
** signal processing had initially be fixed to the same frequency as the power grid,
|
||||||
|
** which runs with 60 Hz in USA, the addition of the additional carriers for the
|
||||||
|
** colour information was confronted with problems of signal cross-talk, due to
|
||||||
|
** some overtones of the used carriers falling into the same frequency band.
|
||||||
|
** As a pragmatic workaround, the frame rate was reduced to 29.97 fps.
|
||||||
**
|
**
|
||||||
** Built on top of that, the actual time handling in the GUI and within the Lumiera
|
** This fix of one problem however caused secondary problems for the production
|
||||||
** session is mostly confined to use the opaque lib::time::Time wrapper objects.
|
** of content for television broadcast, since at this frame rate, one hour of
|
||||||
** When time values actually need to be _quantised_ (aligned to a frame grid),
|
** content would not sum up cleanly to a simple number of frames. Since the
|
||||||
** this is expressed at the API through using the lib::time::QuTime type, which
|
** purpose of time code is to label each frame with a time stamp, as a solution,
|
||||||
** then in turn can be materialised into a number of _timecode formats_.
|
** the mapping of time stamps to frame numbers is manipulated:
|
||||||
** These definitions ensure that whenever an actual quantisation (rounding)
|
** - every minute, there is one second which is mapped to 28 frames only
|
||||||
** operation is performed, the link to the appropriate time grid is available,
|
** - with the exception of every 10 minutes, where no such gap is applied
|
||||||
** so that multiple output or rendering operations can use differing time origins
|
** This scheme adds up to allocating 108 frames less per hour, as would be used
|
||||||
** and frame rates simultaneously on the same model.
|
** with a full frame rate of 30 fps. It should be noted though that applying such
|
||||||
|
** a »drop event« every minute does not mean to _omit actual content frames_ —
|
||||||
|
** rather it is the dime display in the time stamp which suddenly skips ahead by
|
||||||
|
** +2 frames every minute (but not every 10th minute).
|
||||||
**
|
**
|
||||||
** The Lumiera Vault Layer functions mostly operate on raw frame counts, which in
|
** @todo 2025 this header provides some calculation functions to implement such
|
||||||
** this model are defined to be a special kind of timecode, and thus dependent on
|
** a mapping scheme (thereby documenting the know-how). But the project
|
||||||
** a preceding time quantisation.
|
** never got to the point of integrating this functionality into an
|
||||||
|
** actual timecode implementation. Doing so will be future work.
|
||||||
|
** ///////////////////////////////////////////////////TICKET #751
|
||||||
**
|
**
|
||||||
** @deprecated 2025 this should not be a "simple" C library set aside from the Lumiera
|
** @see time-dropframe-test.cpp
|
||||||
** time handling framework, rather it should be clarified that these are
|
|
||||||
** implementation helpers and must not be used by any application code.
|
|
||||||
** It should be checked which of these functions actually need to be
|
|
||||||
** exposed through an interface header, since these are typically
|
|
||||||
** used to implement parts of the time handling framework.
|
|
||||||
**
|
|
||||||
** @see lib::time::Time
|
|
||||||
** @see timequant.hpp
|
** @see timequant.hpp
|
||||||
|
** @see lib::time::Time
|
||||||
** @see TimeValue_test
|
** @see TimeValue_test
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
@ -48,180 +52,28 @@
|
||||||
#ifndef LUMIERA_TIME_DROPFRAME_H
|
#ifndef LUMIERA_TIME_DROPFRAME_H
|
||||||
#define LUMIERA_TIME_DROPFRAME_H
|
#define LUMIERA_TIME_DROPFRAME_H
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus /*=================== C++ facilities ===================== */
|
|
||||||
#include "lib/time/timevalue.hpp"
|
#include "lib/time/timevalue.hpp"
|
||||||
|
|
||||||
using lib::time::raw_time_64;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
namespace lib {
|
||||||
* Converts a fraction of seconds to Lumiera's internal opaque time scale.
|
namespace time {
|
||||||
* @param fractionalSeconds given as rational number
|
|
||||||
* @note inconsistent with Lumiera's general quantisation behaviour,
|
|
||||||
* here negative fractional micro-ticks are truncated towards zero.
|
/**
|
||||||
* This was deemed irrelevant in practice.
|
* Compute the consecutive frame number from a given time,
|
||||||
*/
|
* which is interpreted at the NTSC drop frame timecode grid.
|
||||||
raw_time_64
|
*/
|
||||||
lumiera_rational_to_time (lib::time::FSecs const& fractionalSeconds);
|
int64_t calculate_ntsc_drop_frame_number (raw_time_64 time);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a frame count into Lumiera's internal time scale.
|
* Build effective time from a NTSC drop frame timecode.
|
||||||
* based on a framerate given as rational number (e.g. NTSC)
|
* @warning take care not to specify time codes that are illegal NTSC drop-frame times.
|
||||||
* @note handles only positive frame counts and assumes the
|
*/
|
||||||
* origin to be at zero.
|
raw_time_64 build_time_from_ntsc_drop_frame (uint frames, uint secs, uint mins, uint hours);
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_framecount_to_time (uint64_t frameCount, lib::time::FrameRate const& fps);
|
|
||||||
|
}} // lib::time
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the duration of one frame in Lumiera time units.
|
|
||||||
* @param framerate underlying framerate as rational number
|
|
||||||
* @throw error::Logic on zero framerate
|
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_frame_duration (lib::time::FrameRate const& fps);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" { /* ===================== C interface ======================== */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Quantise the given time into a fixed grid, relative to the origin.
|
|
||||||
* The time grid used for quantisation is comprised of equally spaced intervals,
|
|
||||||
* rooted at the given origin. The interval starting with the origin is numbered
|
|
||||||
* as zero. Each interval includes its lower bound, but excludes its upper bound.
|
|
||||||
* @param grid spacing of the grid intervals, measured in TimeValue::Scale (µ-ticks)
|
|
||||||
* @return number of the grid interval containing the given time.
|
|
||||||
* @warning the resulting value is limited to (Time::Min, Time::MAX)
|
|
||||||
*/
|
|
||||||
int64_t
|
|
||||||
lumiera_quantise_frames (raw_time_64 time, raw_time_64 origin, raw_time_64 grid);
|
|
||||||
|
|
||||||
int64_t
|
|
||||||
lumiera_quantise_frames_fps (raw_time_64 time, raw_time_64 origin, uint framerate);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Similar to #lumiera_quantise_frames, but returns a grid aligned _relative time_.
|
|
||||||
* @return time of start of the grid interval containing the given time,
|
|
||||||
* but measured relative to the origin
|
|
||||||
* @warning because the resulting value needs to be limited to fit into a 64bit long,
|
|
||||||
* the addressable time range can be considerably reduced. For example, if
|
|
||||||
* origin = Time::MIN, then all original time values above zero will be
|
|
||||||
* clipped, because the result, relative to origin, needs to be <= Time::MAX
|
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_quantise_time (raw_time_64 time, raw_time_64 origin, raw_time_64 grid);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate time of a grid point (frame start)
|
|
||||||
* @param nr index number of the grid point (0 is at origin)
|
|
||||||
* @param grid spacing of the grid intervals, measured in TimeValue::Scale (µ-ticks)
|
|
||||||
* @return time point (frame start) on the Lumiera internal time scale
|
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_time_of_gridpoint (int64_t nr, raw_time_64 origin, raw_time_64 grid);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a time value by summing up the given components.
|
|
||||||
* @param millis number of milliseconds
|
|
||||||
* @param secs number of seconds
|
|
||||||
* @param mins number of minutes
|
|
||||||
* @param hours number of hours
|
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_build_time (long millis, uint secs, uint mins, uint hours);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a time value by summing up the given components.
|
|
||||||
* @param fps framerate (frames per second)
|
|
||||||
* @param frames number of additional frames
|
|
||||||
* @param secs number of seconds
|
|
||||||
* @param mins number of minutes
|
|
||||||
* @param hours number of hours
|
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a time value by summing up the given components.
|
|
||||||
* The components are interpreted as a NTSC drop-frame timecode.
|
|
||||||
* @warning take care not to specify time codes that are illegal NTSC drop-frame times.
|
|
||||||
*/
|
|
||||||
raw_time_64
|
|
||||||
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours);
|
|
||||||
|
|
||||||
|
|
||||||
/** Extract the hour part of given time. */
|
|
||||||
int
|
|
||||||
lumiera_time_hours (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
/** Extract the minute part of given time. */
|
|
||||||
int
|
|
||||||
lumiera_time_minutes (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
/** Extract the seconds part of given time. */
|
|
||||||
int
|
|
||||||
lumiera_time_seconds (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
/** Extract the milliseconds part of given time. */
|
|
||||||
int
|
|
||||||
lumiera_time_millis (raw_time_64 time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the remaining frame part of given time.
|
|
||||||
* @param fps frame rate (frames per second)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_frames (raw_time_64 time, uint fps);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the frame part of given time, using NTSC drop-frame timecode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_frames (raw_time_64 time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the second part of given time, using NTSC drop-frame timecode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_seconds (raw_time_64 time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the minute part of given time, using NTSC drop-frame timecode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_minutes (raw_time_64 time);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extract the hour part of given time, using NTSC drop-frame timecode.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_hours (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal Diagnostics helper: render time value in H:MM:SS.mmm format.
|
|
||||||
* @return `safeclib` temporary buffer containing formatted time string
|
|
||||||
* @note any time output for real should go through quantisation followed
|
|
||||||
* by rendering into a suitable timecode format.
|
|
||||||
*/
|
|
||||||
char*
|
|
||||||
lumiera_tmpbuf_print_time (raw_time_64 time);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}//extern "C"
|
|
||||||
#endif
|
|
||||||
#endif /*LUMIERA_TIME_DROPFRAME_H*/
|
#endif /*LUMIERA_TIME_DROPFRAME_H*/
|
||||||
|
|
|
||||||
|
|
@ -42,10 +42,6 @@
|
||||||
#include "lib/format-string.hpp"
|
#include "lib/format-string.hpp"
|
||||||
#include "lib/util.hpp"
|
#include "lib/util.hpp"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "lib/tmpbuf.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
@ -382,32 +378,6 @@ namespace util {
|
||||||
/* ===== implementation of the C API functions ===== */
|
/* ===== implementation of the C API functions ===== */
|
||||||
|
|
||||||
|
|
||||||
char*
|
|
||||||
lumiera_tmpbuf_print_time (raw_time_64 time)
|
|
||||||
{
|
|
||||||
int milliseconds, seconds, minutes, hours;
|
|
||||||
bool negative = (time < 0);
|
|
||||||
|
|
||||||
if (negative)
|
|
||||||
time = -time;
|
|
||||||
|
|
||||||
time /= TIME_SCALE_MS;
|
|
||||||
milliseconds = time % 1000;
|
|
||||||
time /= 1000;
|
|
||||||
seconds = time % 60;
|
|
||||||
time /= 60;
|
|
||||||
minutes = time % 60;
|
|
||||||
time /= 60;
|
|
||||||
hours = time;
|
|
||||||
|
|
||||||
char *buffer = lumiera_tmpbuf_snprintf(64, lib::time::DIAGNOSTIC_FORMAT,
|
|
||||||
negative ? "-" : "", hours, minutes, seconds, milliseconds);
|
|
||||||
|
|
||||||
ENSURE(buffer != NULL);
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @todo this utility function could be factored out into a `FSecs` or `RSec` class ///////////////////////TICKET #1262
|
/// @todo this utility function could be factored out into a `FSecs` or `RSec` class ///////////////////////TICKET #1262
|
||||||
raw_time_64
|
raw_time_64
|
||||||
lumiera_rational_to_time (FSecs const& fractionalSeconds)
|
lumiera_rational_to_time (FSecs const& fractionalSeconds)
|
||||||
|
|
@ -564,24 +534,30 @@ lumiera_time_frames (raw_time_64 time, uint fps)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace lib {
|
||||||
/* ===== NTSC drop-frame conversions ===== */
|
namespace time { ////////////////////////////////////////////////////////////////////////////////////////////TICKET #1259 : move all calculation functions into a C++ namespace
|
||||||
|
|
||||||
|
|
||||||
namespace { // implementation helper
|
/* ===== NTSC drop-frame conversions ===== */
|
||||||
|
|
||||||
|
namespace { // conversion parameters
|
||||||
|
|
||||||
const uint FRAMES_PER_10min = 10*60 * 30000/1001;
|
const uint FRAMES_PER_10min = 10*60 * 30000/1001;
|
||||||
const uint FRAMES_PER_1min = 1*60 * 30000/1001;
|
const uint FRAMES_PER_1min = 1*60 * 30000/1001;
|
||||||
const uint DISCREPANCY = (1*60 * 30) - FRAMES_PER_1min;
|
const uint DISCREPANCY = (1*60 * 30) - FRAMES_PER_1min;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** reverse the drop-frame calculation
|
/**
|
||||||
* @param time absolute time value in micro ticks
|
* @remark This function reverses building the drop-frame timecode,
|
||||||
* @return the absolute frame number using NTSC drop-frame encoding
|
* and thus maps a time into consecutive frame numbers
|
||||||
* @todo I doubt this works correct for negative times!!
|
* at NTSC framerate (i.e. without gaps)
|
||||||
|
* @param timecode represented as time value in µ-ticks
|
||||||
|
* @return the absolute frame number as addressed by NTSC drop-frame
|
||||||
|
* @todo 2011 I doubt this works correct for negative times!!
|
||||||
*/
|
*/
|
||||||
inline int64_t
|
int64_t
|
||||||
calculate_drop_frame_number (raw_time_64 time)
|
calculate_ntsc_drop_frame_number (raw_time_64 time)
|
||||||
{
|
{
|
||||||
int64_t frameNr = calculate_quantisation (time, 0, 30000, 1001);
|
int64_t frameNr = calculate_quantisation (time, 0, 30000, 1001);
|
||||||
|
|
||||||
|
|
@ -596,44 +572,30 @@ namespace { // implementation helper
|
||||||
int64_t dropIncidents = (10-1) * tenMinFrames.quot + remainingMinutes;
|
int64_t dropIncidents = (10-1) * tenMinFrames.quot + remainingMinutes;
|
||||||
return frameNr + 2*dropIncidents;
|
return frameNr + 2*dropIncidents;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_frames (raw_time_64 time)
|
|
||||||
{
|
|
||||||
return calculate_drop_frame_number(time) % 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_seconds (raw_time_64 time)
|
|
||||||
{
|
|
||||||
return calculate_drop_frame_number(time) / 30 % 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_minutes (raw_time_64 time)
|
|
||||||
{
|
|
||||||
return calculate_drop_frame_number(time) / 30 / 60 % 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
lumiera_time_ntsc_drop_hours (raw_time_64 time)
|
|
||||||
{
|
|
||||||
return calculate_drop_frame_number(time) / 30 / 60 / 60 % 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_time_64
|
|
||||||
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours)
|
|
||||||
{
|
|
||||||
uint64_t total_mins = 60 * hours + mins;
|
|
||||||
uint64_t total_frames = 30*60*60 * hours
|
|
||||||
+ 30*60 * mins
|
|
||||||
+ 30 * secs
|
|
||||||
+ frames
|
|
||||||
- 2 * (total_mins - total_mins / 10);
|
|
||||||
raw_time_64 result = lumiera_framecount_to_time (total_frames, FrameRate::NTSC);
|
|
||||||
|
|
||||||
if (0 != result) // compensate for truncating down on conversion
|
|
||||||
result += 1; // without this adjustment the frame number
|
/**
|
||||||
return result; // would turn out off by -1 on back conversion
|
* @remark This is the mapping function to translate NTSC drop frame
|
||||||
}
|
* timecode specification into an actual time, with the necessary
|
||||||
|
* skip events every 1.-9. minute, thereby allocating 108 frames
|
||||||
|
* less per hour, than would be required for full 30 fps.
|
||||||
|
* @return raw time value on a µ-tick scale
|
||||||
|
*/
|
||||||
|
raw_time_64
|
||||||
|
build_time_from_ntsc_drop_frame (uint frames, uint secs, uint mins, uint hours)
|
||||||
|
{
|
||||||
|
uint64_t total_mins = 60 * hours + mins;
|
||||||
|
uint64_t total_frames = 30*60*60 * hours
|
||||||
|
+ 30*60 * mins
|
||||||
|
+ 30 * secs
|
||||||
|
+ frames
|
||||||
|
- 2 * (total_mins - total_mins / 10);
|
||||||
|
raw_time_64 result = lumiera_framecount_to_time (total_frames, FrameRate::NTSC);
|
||||||
|
|
||||||
|
if (0 != result) // compensate for truncating down on conversion
|
||||||
|
result += 1; // without this adjustment the frame number
|
||||||
|
return result; // would turn out off by -1 on back conversion
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}} // lib::time
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
TESTING "Time conversion" ./test-time
|
|
||||||
|
|
||||||
TEST "ntsc drop-frame calculations" ntsc_drop_frame << END
|
|
||||||
return: 0
|
|
||||||
END
|
|
||||||
|
|
@ -130,7 +130,7 @@ return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
||||||
PLANNED "Drop-Frame calculation" TimeDropframe_test <<END
|
TEST "NTSC drop-frame calculation" TimeDropframe_test <<END
|
||||||
return: 0
|
return: 0
|
||||||
END
|
END
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,166 +20,177 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "lib/test/test.h"
|
#include "lib/test/run.hpp"
|
||||||
|
#include "lib/test/test-helper.hpp"
|
||||||
#include <inttypes.h>
|
#include "lib/time/dropframe.hpp"
|
||||||
#include <ctype.h>
|
#include "lib/time/timevalue.hpp"
|
||||||
#include <nobug.h>
|
|
||||||
|
|
||||||
typedef int64_t raw_time_64; //////////////////////////////////////////////////////////////////////////////TICKET #1259 turn time.h in to a C++ implementation header
|
|
||||||
|
|
||||||
#include "lib/time.h" /////////////////////////////////////////////////////////////////////////////////////TICKET #1259 this should not be a general purpose library, but rather an implementation base
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
namespace lib {
|
||||||
calculate_framecount (raw_time_64 t, uint fps)
|
namespace time{
|
||||||
{
|
namespace test{
|
||||||
return lumiera_quantise_frames_fps (t,0,fps);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TESTS_BEGIN
|
|
||||||
|
|
||||||
const int FRAMES = 15;
|
|
||||||
const int MILLIS = 700;
|
|
||||||
const int SECONDS = 20;
|
|
||||||
const int MINUTES = 55;
|
|
||||||
const int HOURS = 3;
|
|
||||||
const int FPS = 24;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 1. Basic functionality
|
|
||||||
*/
|
|
||||||
|
|
||||||
TEST (basic)
|
|
||||||
{
|
|
||||||
// Zero
|
|
||||||
raw_time_64 t = lumiera_build_time (0,0,0,0);
|
|
||||||
|
|
||||||
CHECK ((raw_time_64) t == 0);
|
|
||||||
CHECK (lumiera_time_millis (t) == 0);
|
|
||||||
CHECK (lumiera_time_seconds (t) == 0);
|
|
||||||
CHECK (lumiera_time_minutes (t) == 0);
|
|
||||||
CHECK (lumiera_time_hours (t) == 0);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS) == 0);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS+5) == 0);
|
|
||||||
CHECK (calculate_framecount (t,FPS) == 0);
|
|
||||||
CHECK (calculate_framecount (t, FPS+5) == 0);
|
|
||||||
|
|
||||||
ECHO ("%s", lumiera_tmpbuf_print_time (t));
|
|
||||||
|
|
||||||
// Non-zero
|
|
||||||
t = lumiera_build_time (MILLIS, SECONDS, MINUTES, HOURS);
|
|
||||||
|
|
||||||
CHECK (lumiera_time_millis (t) == MILLIS);
|
|
||||||
CHECK (lumiera_time_seconds (t) == SECONDS);
|
|
||||||
CHECK (lumiera_time_minutes (t) == MINUTES);
|
|
||||||
CHECK (lumiera_time_hours (t) == HOURS);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS) == FPS * MILLIS / 1000);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS+5) == (FPS+5) * MILLIS / 1000);
|
|
||||||
CHECK (calculate_framecount (t, FPS) == 338896);
|
|
||||||
CHECK (calculate_framecount (t, FPS+5) == 409500);
|
|
||||||
|
|
||||||
ECHO ("%s", lumiera_tmpbuf_print_time (t));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 2. Frame rate dependent calculations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
TEST (fps)
|
|
||||||
{
|
|
||||||
raw_time_64 t = lumiera_build_time_fps (FPS, FRAMES, SECONDS, MINUTES, HOURS);
|
|
||||||
|
|
||||||
CHECK (lumiera_time_millis (t) == FRAMES * 1000 / FPS);
|
|
||||||
CHECK (lumiera_time_seconds (t) == SECONDS);
|
|
||||||
CHECK (lumiera_time_minutes (t) == MINUTES);
|
|
||||||
CHECK (lumiera_time_hours (t) == HOURS);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS) == FRAMES);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS+5) == FRAMES * (FPS+5)/FPS);
|
|
||||||
CHECK (calculate_framecount (t, FPS) == 338895);
|
|
||||||
CHECK (calculate_framecount (t, FPS+5) == 409498);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3. NTSC drop-frame calculations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
TEST (ntsc_drop_frame)
|
|
||||||
{
|
|
||||||
// Make sure frame 0 begins at 0
|
|
||||||
raw_time_64 t = lumiera_build_time_ntsc_drop (0, 0, 0, 0);
|
|
||||||
|
|
||||||
CHECK ((raw_time_64) t == 0);
|
|
||||||
CHECK (lumiera_time_millis (t) == 0);
|
|
||||||
CHECK (lumiera_time_seconds (t) == 0);
|
|
||||||
CHECK (lumiera_time_minutes (t) == 0);
|
|
||||||
CHECK (lumiera_time_hours (t) == 0);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS) == 0);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS+5) == 0);
|
|
||||||
CHECK (calculate_framecount (t, FPS) == 0);
|
|
||||||
CHECK (calculate_framecount (t, FPS+5) == 0);
|
|
||||||
|
|
||||||
|
using time::Time;
|
||||||
|
using time::TimeVar;
|
||||||
|
using time::FSecs;
|
||||||
|
using time::raw_time_64;
|
||||||
|
|
||||||
|
namespace {// Test setup
|
||||||
t = lumiera_build_time_ntsc_drop (FRAMES, SECONDS, MINUTES, HOURS);
|
const int FRAMES = 15;
|
||||||
|
const int MILLIS = 700;
|
||||||
// Calculate manually what result to expect....
|
const int SECONDS = 20;
|
||||||
int frames = FRAMES + 30*SECONDS + 30*60*MINUTES + 30*60*60*HOURS; // sum up using nominal 30fps
|
const int MINUTES = 55;
|
||||||
int minutes_to_drop_frames = (MINUTES - MINUTES/10) + (HOURS * 54); // but every minute, with the exception of every 10 minutes...
|
const int HOURS = 3;
|
||||||
frames -= 2*minutes_to_drop_frames; // ...drop 2 frames
|
|
||||||
int64_t expectedMillis = 1000LL * frames * 1001/30000; // now convert frames to time, using the real framerate
|
|
||||||
|
/* ====== conversion helpers to verify results ====== */
|
||||||
expectedMillis %= 1000; // look at the remainder..
|
|
||||||
CHECK (lumiera_time_millis (t) == expectedMillis);
|
const auto TIME_SCALE_sec{lib::time::TimeValue::SCALE };
|
||||||
|
const auto TIME_SCALE_ms {lib::time::TimeValue::SCALE / 1'000};
|
||||||
CHECK (lumiera_time_seconds (t) == SECONDS); // while all other components should come out equal as set
|
|
||||||
CHECK (lumiera_time_minutes (t) == MINUTES);
|
int
|
||||||
CHECK (lumiera_time_hours (t) == HOURS);
|
dropframe_frames (raw_time_64 timecode)
|
||||||
|
|
||||||
// Reverse calculate frames for NTSC drop
|
|
||||||
//CHECK (lumiera_quantise_frames (t, 0, dropFrameDuration) == frames); // the total nominal frames
|
|
||||||
CHECK (lumiera_time_ntsc_drop_frames (t) == FRAMES); // maximum one frame off due to rounding
|
|
||||||
|
|
||||||
// Cover the whole value range;
|
|
||||||
// Manually construct a drop-frame timecode
|
|
||||||
// Make sure our library function returns the same times.
|
|
||||||
int min;
|
|
||||||
int sec;
|
|
||||||
int frame;
|
|
||||||
int hrs;
|
|
||||||
for (hrs = 0; hrs <= 24; hrs += 6)
|
|
||||||
for (min = 0; min <= 59; min += 1)
|
|
||||||
for (sec = 0; sec <= 59; sec += 10)
|
|
||||||
for (frame = 0; frame <= 29; frame++)
|
|
||||||
{
|
|
||||||
// Skip dropped frames
|
|
||||||
if (min % 10 && sec == 0 && frame < 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
t = lumiera_build_time_ntsc_drop(frame, sec, min, hrs);
|
|
||||||
/*
|
|
||||||
ECHO ("%02d:%02d:%02d;%02d"
|
|
||||||
, lumiera_time_ntsc_drop_hours (t)
|
|
||||||
, lumiera_time_ntsc_drop_minutes (t)
|
|
||||||
, lumiera_time_ntsc_drop_seconds (t)
|
|
||||||
, lumiera_time_ntsc_drop_frames (t)
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
CHECK (lumiera_time_ntsc_drop_frames (t) == frame);
|
|
||||||
CHECK (lumiera_time_ntsc_drop_seconds (t) == sec);
|
|
||||||
CHECK (lumiera_time_ntsc_drop_minutes (t) == min);
|
|
||||||
CHECK (lumiera_time_ntsc_drop_hours (t) == hrs % 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we do not get non-existent frames
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 59; i++)
|
|
||||||
{
|
{
|
||||||
int frame = (i % 10 == 0) ? 0 : 2;
|
return calculate_ntsc_drop_frame_number(timecode) % 30;
|
||||||
t = lumiera_build_time_ntsc_drop (frame, 0, i, 0);
|
|
||||||
CHECK (lumiera_time_ntsc_drop_frames (t) == frame);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
int
|
||||||
|
dropframe_seconds (raw_time_64 timecode)
|
||||||
|
{
|
||||||
|
return calculate_ntsc_drop_frame_number(timecode) / 30 % 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dropframe_minutes (raw_time_64 timecode)
|
||||||
|
{
|
||||||
|
return calculate_ntsc_drop_frame_number(timecode) / 30 / 60 % 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dropframe_hours (raw_time_64 timecode)
|
||||||
|
{
|
||||||
|
return calculate_ntsc_drop_frame_number(timecode) / 30 / 60 / 60 % 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
time_hours (raw_time_64 time)
|
||||||
|
{
|
||||||
|
return time / TIME_SCALE_sec / 60 / 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
time_minutes (raw_time_64 time)
|
||||||
|
{
|
||||||
|
return (time / TIME_SCALE_sec / 60) % 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
time_seconds (raw_time_64 time)
|
||||||
|
{
|
||||||
|
return (time / TIME_SCALE_sec) % 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
time_millis (raw_time_64 time)
|
||||||
|
{
|
||||||
|
return (time / TIME_SCALE_ms) % 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************//**
|
||||||
|
* @test document the computation of NTSC drop frame timecode mapping.
|
||||||
|
*/
|
||||||
|
class TimeDropframe_test : public Test
|
||||||
|
{
|
||||||
|
virtual void
|
||||||
|
run (Arg)
|
||||||
|
{
|
||||||
|
verify_DropFrame_conv();
|
||||||
|
verify_completeMapping();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @test perform a drop-frame timecode conversion
|
||||||
|
* and verify the complete round-trip is correct.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
verify_DropFrame_conv()
|
||||||
|
{
|
||||||
|
// Make sure frame 0 begins at 0
|
||||||
|
raw_time_64 t = build_time_from_ntsc_drop_frame (0, 0, 0, 0);
|
||||||
|
CHECK (t == 0);
|
||||||
|
|
||||||
|
t = build_time_from_ntsc_drop_frame (FRAMES, SECONDS, MINUTES, HOURS);
|
||||||
|
|
||||||
|
// Calculate manually what result to expect....
|
||||||
|
int frames = FRAMES + 30*SECONDS + 30*60*MINUTES + 30*60*60*HOURS; // sum up using nominal 30fps
|
||||||
|
int minutes_to_drop_frames = (MINUTES - MINUTES/10) + (HOURS * 54); // but every minute, with the exception of every 10 minutes...
|
||||||
|
frames -= 2*minutes_to_drop_frames; // ...drop 2 frames
|
||||||
|
int64_t expectedMillis = 1000LL * frames * 1001/30000; // now convert frames to time, using the real framerate
|
||||||
|
|
||||||
|
expectedMillis %= 1000; // look at the remainder..
|
||||||
|
CHECK (time_millis (t) == expectedMillis);
|
||||||
|
|
||||||
|
CHECK (time_seconds (t) == SECONDS); // while all other components should come out equal as set
|
||||||
|
CHECK (time_minutes (t) == MINUTES);
|
||||||
|
CHECK (time_hours (t) == HOURS);
|
||||||
|
|
||||||
|
// Reverse calculate frames for NTSC drop
|
||||||
|
//CHECK (lumiera_quantise_frames (t, 0, dropFrameDuration) == frames); // the total nominal frames
|
||||||
|
CHECK (dropframe_frames (t) == FRAMES); // maximum one frame off due to rounding
|
||||||
|
|
||||||
TESTS_END
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** @test Cover the whole value range of a day in drop-frame:
|
||||||
|
* - manually construct a drop-frame timecode
|
||||||
|
* - make sure our library function returns the same times.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
verify_completeMapping()
|
||||||
|
{
|
||||||
|
for (int hrs = 0; hrs <= 24; hrs += 6)
|
||||||
|
for (int min = 0; min <= 59; min += 1)
|
||||||
|
for (int sec = 0; sec <= 59; sec += 10)
|
||||||
|
for (int frame = 0; frame <= 29; frame++)
|
||||||
|
{
|
||||||
|
// Skip dropped frames
|
||||||
|
if (min % 10 && sec == 0 && frame < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
raw_time_64 t = build_time_from_ntsc_drop_frame(frame, sec, min, hrs);
|
||||||
|
/*
|
||||||
|
ECHO ("%02d:%02d:%02d;%02d"
|
||||||
|
, lumiera_time_ntsc_drop_hours (t)
|
||||||
|
, lumiera_time_ntsc_drop_minutes (t)
|
||||||
|
, lumiera_time_ntsc_drop_seconds (t)
|
||||||
|
, lumiera_time_ntsc_drop_frames (t)
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
CHECK (dropframe_frames (t) == frame);
|
||||||
|
CHECK (dropframe_seconds (t) == sec);
|
||||||
|
CHECK (dropframe_minutes (t) == min);
|
||||||
|
CHECK (dropframe_hours (t) == hrs % 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we do not get non-existent frames
|
||||||
|
for (int i = 0; i < 59; i++)
|
||||||
|
{
|
||||||
|
int frame = (i % 10 == 0) ? 0 : 2;
|
||||||
|
raw_time_64 t = build_time_from_ntsc_drop_frame (frame, 0, i, 0);
|
||||||
|
CHECK (dropframe_frames (t) == frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Register this test class... */
|
||||||
|
LAUNCHER (TimeDropframe_test, "unit common");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}}} // namespace lib::time::test
|
||||||
|
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
/*
|
|
||||||
TEST-TIME - test the time conversion lib
|
|
||||||
|
|
||||||
Copyright (C)
|
|
||||||
2010, Stefan Kangas <skangas@skangas.se>
|
|
||||||
|
|
||||||
**Lumiera** is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by the
|
|
||||||
Free Software Foundation; either version 2 of the License, or (at your
|
|
||||||
option) any later version. See the file COPYING for further details.
|
|
||||||
|
|
||||||
* *****************************************************************/
|
|
||||||
|
|
||||||
/** @file test-time.c
|
|
||||||
** C unit test to cover the basic low-level time handling operations
|
|
||||||
** @see time.h
|
|
||||||
** @see timevalue.hpp
|
|
||||||
** @see TimeValue_test high-level time entities
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "lib/test/test.h"
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <nobug.h>
|
|
||||||
|
|
||||||
typedef int64_t raw_time_64; //////////////////////////////////////////////////////////////////////////////TICKET #1259 turn time.h in to a C++ implementation header
|
|
||||||
|
|
||||||
#include "lib/time.h" /////////////////////////////////////////////////////////////////////////////////////TICKET #1259 this should not be a general purpose library, but rather an implementation base
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
calculate_framecount (raw_time_64 t, uint fps)
|
|
||||||
{
|
|
||||||
return lumiera_quantise_frames_fps (t,0,fps);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TESTS_BEGIN
|
|
||||||
|
|
||||||
const int FRAMES = 15;
|
|
||||||
const int SECONDS = 20;
|
|
||||||
const int MINUTES = 55;
|
|
||||||
const int HOURS = 3;
|
|
||||||
const int FPS = 24;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 3. NTSC drop-frame calculations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
TEST (ntsc_drop_frame)
|
|
||||||
{
|
|
||||||
// Make sure frame 0 begins at 0
|
|
||||||
raw_time_64 t = lumiera_build_time_ntsc_drop (0, 0, 0, 0);
|
|
||||||
|
|
||||||
CHECK ((raw_time_64) t == 0);
|
|
||||||
CHECK (lumiera_time_millis (t) == 0);
|
|
||||||
CHECK (lumiera_time_seconds (t) == 0);
|
|
||||||
CHECK (lumiera_time_minutes (t) == 0);
|
|
||||||
CHECK (lumiera_time_hours (t) == 0);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS) == 0);
|
|
||||||
CHECK (lumiera_time_frames (t, FPS+5) == 0);
|
|
||||||
CHECK (calculate_framecount (t, FPS) == 0);
|
|
||||||
CHECK (calculate_framecount (t, FPS+5) == 0);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
t = lumiera_build_time_ntsc_drop (FRAMES, SECONDS, MINUTES, HOURS);
|
|
||||||
|
|
||||||
// Calculate manually what result to expect....
|
|
||||||
int frames = FRAMES + 30*SECONDS + 30*60*MINUTES + 30*60*60*HOURS; // sum up using nominal 30fps
|
|
||||||
int minutes_to_drop_frames = (MINUTES - MINUTES/10) + (HOURS * 54); // but every minute, with the exception of every 10 minutes...
|
|
||||||
frames -= 2*minutes_to_drop_frames; // ...drop 2 frames
|
|
||||||
int64_t expectedMillis = 1000LL * frames * 1001/30000; // now convert frames to time, using the real framerate
|
|
||||||
|
|
||||||
expectedMillis %= 1000; // look at the remainder..
|
|
||||||
CHECK (lumiera_time_millis (t) == expectedMillis);
|
|
||||||
|
|
||||||
CHECK (lumiera_time_seconds (t) == SECONDS); // while all other components should come out equal as set
|
|
||||||
CHECK (lumiera_time_minutes (t) == MINUTES);
|
|
||||||
CHECK (lumiera_time_hours (t) == HOURS);
|
|
||||||
|
|
||||||
// Reverse calculate frames for NTSC drop
|
|
||||||
//CHECK (lumiera_quantise_frames (t, 0, dropFrameDuration) == frames); // the total nominal frames
|
|
||||||
CHECK (lumiera_time_ntsc_drop_frames (t) == FRAMES); // maximum one frame off due to rounding
|
|
||||||
|
|
||||||
// Cover the whole value range;
|
|
||||||
// Manually construct a drop-frame timecode
|
|
||||||
// Make sure our library function returns the same times.
|
|
||||||
int min;
|
|
||||||
int sec;
|
|
||||||
int frame;
|
|
||||||
int hrs;
|
|
||||||
for (hrs = 0; hrs <= 24; hrs += 6)
|
|
||||||
for (min = 0; min <= 59; min += 1)
|
|
||||||
for (sec = 0; sec <= 59; sec += 10)
|
|
||||||
for (frame = 0; frame <= 29; frame++)
|
|
||||||
{
|
|
||||||
// Skip dropped frames
|
|
||||||
if (min % 10 && sec == 0 && frame < 2)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
t = lumiera_build_time_ntsc_drop(frame, sec, min, hrs);
|
|
||||||
/*
|
|
||||||
ECHO ("%02d:%02d:%02d;%02d"
|
|
||||||
, lumiera_time_ntsc_drop_hours (t)
|
|
||||||
, lumiera_time_ntsc_drop_minutes (t)
|
|
||||||
, lumiera_time_ntsc_drop_seconds (t)
|
|
||||||
, lumiera_time_ntsc_drop_frames (t)
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
CHECK (lumiera_time_ntsc_drop_frames (t) == frame);
|
|
||||||
CHECK (lumiera_time_ntsc_drop_seconds (t) == sec);
|
|
||||||
CHECK (lumiera_time_ntsc_drop_minutes (t) == min);
|
|
||||||
CHECK (lumiera_time_ntsc_drop_hours (t) == hrs % 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we do not get non-existent frames
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 59; i++)
|
|
||||||
{
|
|
||||||
int frame = (i % 10 == 0) ? 0 : 2;
|
|
||||||
t = lumiera_build_time_ntsc_drop (frame, 0, i, 0);
|
|
||||||
CHECK (lumiera_time_ntsc_drop_frames (t) == frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TESTS_END
|
|
||||||
|
|
@ -162886,8 +162886,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
...nachdem gavl_time_t durch einen Typedef ersetzt ist, und ich das Thema durch #1261 bereits abgesteckt habe, könnte der Bestand einer eigenständigen Basis-Library durch wenige Umordnungen aufgehoben werden. Denn darum geht es mir: ich will in Lumiera eine Ordnung schaffen, in der gedankenloses einfach-mal-Machen keinen Raum findet.
|
...nachdem gavl_time_t durch einen Typedef ersetzt ist, und ich das Thema durch #1261 bereits abgesteckt habe, könnte der Bestand einer eigenständigen Basis-Library durch wenige Umordnungen aufgehoben werden. Denn darum geht es mir: ich will in Lumiera eine Ordnung schaffen, in der gedankenloses einfach-mal-Machen keinen Raum findet.
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html></richcontent>
|
||||||
</richcontent>
|
|
||||||
<node CREATED="1747520507617" ID="ID_391130031" MODIFIED="1748350248986" TEXT="sollte die konkreten Verwendungen durchsehen">
|
<node CREATED="1747520507617" ID="ID_391130031" MODIFIED="1748350248986" TEXT="sollte die konkreten Verwendungen durchsehen">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head/>
|
||||||
|
|
@ -162896,8 +162895,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
...möglicherweise lassen sich diese Funktionen nämlich in Gruppen einteilen und dann direkt in einen anonymen namespace in die jeweilige Translation-Unit schieben....
|
...möglicherweise lassen sich diese Funktionen nämlich in Gruppen einteilen und dann direkt in einen anonymen namespace in die jeweilige Translation-Unit schieben....
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html></richcontent>
|
||||||
</richcontent>
|
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1747520518579" ID="ID_1232667630" MODIFIED="1747520531129" TEXT="müßte dann auch den C-Test (test-time) auflösen">
|
<node CREATED="1747520518579" ID="ID_1232667630" MODIFIED="1747520531129" TEXT="müßte dann auch den C-Test (test-time) auflösen">
|
||||||
<node CREATED="1747520690709" ID="ID_920147641" MODIFIED="1747520695437" TEXT="der ist eigentlich nicht lang"/>
|
<node CREATED="1747520690709" ID="ID_920147641" MODIFIED="1747520695437" TEXT="der ist eigentlich nicht lang"/>
|
||||||
|
|
@ -163166,7 +163164,8 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
<font ITALIC="true" NAME="SansSerif" SIZE="12"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node CREATED="1748363166124" ID="ID_20271646" MODIFIED="1748363183352" TEXT="also: stattdessen rigoros mit Stubs arbeiten">
|
<node CREATED="1748363166124" ID="ID_20271646" MODIFIED="1748388589043" TEXT="also: stattdessen rigoros mit Stubs arbeiten">
|
||||||
|
<icon BUILTIN="yes"/>
|
||||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1748363186304" ID="ID_1752179075" MODIFIED="1748363276225" TEXT="d.h. das Timecode-Widget ganz ersichtlich brechen">
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1748363186304" ID="ID_1752179075" MODIFIED="1748363276225" TEXT="d.h. das Timecode-Widget ganz ersichtlich brechen">
|
||||||
<richcontent TYPE="NOTE"><html>
|
<richcontent TYPE="NOTE"><html>
|
||||||
<head/>
|
<head/>
|
||||||
|
|
@ -163175,8 +163174,7 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
gebrochen ist es ja ohnehin und sowiso, und weiter damit arbeiten möchte ich nicht — ganz ehrlich, das war ein »Griff ins Klo«, das ist kein Code, den man erhalten sollte.
|
gebrochen ist es ja ohnehin und sowiso, und weiter damit arbeiten möchte ich nicht — ganz ehrlich, das war ein »Griff ins Klo«, das ist kein Code, den man erhalten sollte.
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html></richcontent>
|
||||||
</richcontent>
|
|
||||||
<icon BUILTIN="yes"/>
|
<icon BUILTIN="yes"/>
|
||||||
</node>
|
</node>
|
||||||
<node COLOR="#435e98" CREATED="1748370343922" ID="ID_767625066" MODIFIED="1748370424799" TEXT="weitere Verwendungen der Dezimator-Funktionen direkt inlinen">
|
<node COLOR="#435e98" CREATED="1748370343922" ID="ID_767625066" MODIFIED="1748370424799" TEXT="weitere Verwendungen der Dezimator-Funktionen direkt inlinen">
|
||||||
|
|
@ -163192,11 +163190,46 @@ Since then others have made contributions, see the log for the history.</font></
|
||||||
<icon BUILTIN="button_ok"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1748370446771" ID="ID_514685019" MODIFIED="1748370458042" TEXT="Drop-Frame-Berechnung dokumentieren">
|
<node COLOR="#338800" CREATED="1748370446771" ID="ID_514685019" MODIFIED="1748388515380" TEXT="Drop-Frame-Berechnung dokumentieren">
|
||||||
<icon BUILTIN="pencil"/>
|
<icon BUILTIN="button_ok"/>
|
||||||
<node COLOR="#435e98" CREATED="1748370471401" ID="ID_241597558" MODIFIED="1748370583898" TEXT="teset-time.c ⟼ time/time-dropframe-test.cpp">
|
<node COLOR="#435e98" CREATED="1748370471401" ID="ID_241597558" MODIFIED="1748383700953" TEXT="test-time.c ⟼ time/time-dropframe-test.cpp">
|
||||||
<icon BUILTIN="list"/>
|
<icon BUILTIN="list"/>
|
||||||
</node>
|
</node>
|
||||||
|
<node COLOR="#338800" CREATED="1748383707870" ID="ID_1871702886" MODIFIED="1748388462890" TEXT="Funktionen umordnen">
|
||||||
|
<icon BUILTIN="button_ok"/>
|
||||||
|
<node CREATED="1748383746542" ID="ID_1117132995" MODIFIED="1748383761481" TEXT="umziehen in Namespace lib::time"/>
|
||||||
|
<node CREATED="1748383717910" ID="ID_6099644" MODIFIED="1748383730804" TEXT="umziehen in Header lib/time/dropframe.hpp"/>
|
||||||
|
<node CREATED="1748383731428" ID="ID_1472070007" MODIFIED="1748383743307" TEXT="Implementierung verbleibt in lib/time/time.cpp"/>
|
||||||
|
<node CREATED="1748383780122" ID="ID_170667006" MODIFIED="1748383790175" TEXT="nur die eigentliche Berechnungslogik erhalten">
|
||||||
|
<node CREATED="1748383816257" ID="ID_1470396784" MODIFIED="1748384512960" TEXT="int64_t calculate_ntsc_drop_frame_number (raw_time_64 timecode)"/>
|
||||||
|
<node CREATED="1748383835599" ID="ID_328152526" MODIFIED="1748385988435" TEXT="raw_time_64 build_time_from_ntsc_drop_frame (frames, secs, mins, hours)"/>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388465815" ID="ID_1825328642" MODIFIED="1748388490811" STYLE="fork" TEXT="all die Konverter / Deizimator-Funktionen direkt lokal im Test definieren">
|
||||||
|
<icon BUILTIN="idea"/>
|
||||||
|
</node>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#174956" COLOR="#8dfd49" CREATED="1748388518698" ID="ID_1682762507" MODIFIED="1748388574315" STYLE="bubble" TEXT="umgezogener Test läuft GRÜN">
|
||||||
|
<edge COLOR="#61fe5b" STYLE="bezier" WIDTH="thin"/>
|
||||||
|
<font NAME="SansSerif" SIZE="15"/>
|
||||||
|
</node>
|
||||||
|
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#8b2f98" CREATED="1748388204363" ID="ID_926423450" MODIFIED="1748388454445" TEXT=" �� totmachen ��">
|
||||||
|
<node COLOR="#435e98" CREATED="1748388215333" ID="ID_1531959638" MODIFIED="1748388508038" TEXT="test-time.c">
|
||||||
|
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||||
|
<icon BUILTIN="back"/>
|
||||||
|
</node>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388277997" ID="ID_1633487385" MODIFIED="1748388508037" TEXT="lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388277999" ID="ID_260910175" MODIFIED="1748388508037" TEXT="lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278001" ID="ID_1058883405" MODIFIED="1748388508037" TEXT="lumiera_time_hours (raw_time_64 time)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278002" ID="ID_235432384" MODIFIED="1748388508037" TEXT="lumiera_time_minutes (raw_time_64 time)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278003" ID="ID_493874247" MODIFIED="1748388508036" TEXT="lumiera_time_seconds (raw_time_64 time)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278005" ID="ID_1348006733" MODIFIED="1748388508036" TEXT="lumiera_time_millis (raw_time_64 time)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278006" ID="ID_1001439160" MODIFIED="1748388508036" TEXT="lumiera_time_frames (raw_time_64 time, uint fps)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278008" ID="ID_18545784" MODIFIED="1748388508036" TEXT="lumiera_time_ntsc_drop_frames (raw_time_64 time)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278010" ID="ID_1558655339" MODIFIED="1748388508035" TEXT="lumiera_time_ntsc_drop_seconds (raw_time_64 time)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278011" ID="ID_1940069424" MODIFIED="1748388508035" TEXT="lumiera_time_ntsc_drop_minutes (raw_time_64 time)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278013" ID="ID_1868369312" MODIFIED="1748388508035" TEXT="lumiera_time_ntsc_drop_hours (raw_time_64 time)"/>
|
||||||
|
<node COLOR="#435e98" CREATED="1748388278014" ID="ID_275417741" MODIFIED="1748388508019" TEXT="lumiera_tmpbuf_print_time (raw_time_64 time)"/>
|
||||||
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
</node>
|
</node>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue