Precision time stamps are absolute time stamps associated with each compressed frame, indicating the date and time when a frame was compressed. These time stamps are 64-bit numbers representing the number of microseconds that have elapsed since midnight (12:00:00 AM) on Jan 1, 1970. Note that these time stamps CANNOT store dates from before Jan 1, 1970. In other words, you cannot represent Dec 31, 1969 6:00 PM.
Precision time stamps can be inserted in MPEG2 or H.264 video streams. The time stamps are stored in the compressed stream, thus they can be present in any container that supports these video compressions (MPEG2 Program, MPEG2 Transport, ISO/MP4, AVI, Ogg, etc).
Precision time stamps are described in MISB ST 0604.3 "Time Stamping Compressed Motion Imagery" and MISB ST 0603.2 "Common Time Reference for Digital Motion Imagery using Coordinated Universal Time (UTC)".
Since precision time stamps are stored in the compressed stream and are stored in each frame, they will survive if you take a portion of the video and copy it to another file without recompressing it. The time stamps will be lost if the video is recompressed.
Each frame has its own time stamp and the overhead is about 32-35 bytes per frame. These time stamps might have been present from the beginning or can be added by the following filters:
LEAD MPEG2 Encoder (3.0)
LEAD H264 Encoder (4.0)
LEAD MPEG2 Transport Multiplexer
Each of the above filters will have the following:
A property that enables/disables the insertion of precision time stamps: ILMMPEG2Encoder::EnablePrecisionTimeStamp, ILMH264Encoder::EnablePrecisionTimeStamp, ILMMpg2MxT::PrecisionTimeStampAction
A property containing the start value (in microseconds since Jan 1, 1970): ILMMPEG2Encoder::PrecisionTimeStampStartValue, ILMH264Encoder::PrecisionTimeStampStartValue, ILMMpg2MxT::PrecisionTimeStampStartValue
A method for converting a string containing the date and time to a number containing the microseconds since Jan 1, 1970: ILMMPEG2Encoder::ConvertDateToPrecisionTimeStamp, ILMH264Encoder::ConvertDateToPrecisionTimeStamp, ILMMpg2MxT::ConvertDateToPrecisionTimeStamp
Precision time stamps are in Coordinated Universal Time (UTC, also known as GMT). So they should be converted from local time to UTC. There are system functions for converting from local time to UTC time and vice versa.
The start value set in the filter is used to calculate the precision time stamp for the frame at relative time 0.000s. The timestamp for every other frame in the stream is calculated from the start value by adding the relative time offset of each frame compared to the beginning of the stream.
All filters expect the time stamp to be passed as a number (floating point value) representing the number of microseconds since Jan 1, 1970. Calculating this number is not trivial, so helper functions are provided for converting a string containing the date and time to this number. The filters can automatically convert a few standard formats and multiple custom formats.
The strings can be converted if they are in one of the standard formats or in a custom format.
The built-in date string formats are converted by passing NULL or empty ("") strings as the pszFormatString parameter to the ConvertDateToPrecisionTimeStamp methods. The are of the following:
hh:mm:ss AM format. The date is assumed to be the current date. The hour is in 1-12 format and needs an AM/PM indicator. Valid examples:
12:31:15 AM
12:31:15 PM
WWW MTH DD hh:mm:ss YYYY format. MTH is the month using 3-letter name in English, YYYY is the year using 4 digits (so 2014, not 14). The hour is in 24-hour format, not using AM/PM. Valid examples:
Fri Oct 03 15:16:26 2014
MM/DD/YYYY hh:mm:ss AM format. The order of the numbers in the date is: month/date/year. The numbers for month and days can be with 1 or 2 digits. Valid examples:
1/1/2014 9:09:04 AM
10/1/2014 9:09:04 AM
10/20/2014 9:09:04 AM
10/20/2014 10:09:04 AM
/* This example uses the ILMMpg2MxT interface, but the code for using the ILMMPEG2Encoder and ILMH264Encoder interfaces is very similar so it will not be shown here. Notice that the second parameter passed to the ConvertDateToPrecisionTimeStamp method is NULL since this is a standard date format */
private void EnablePrecisionTimeStampMux()
{
LMMpg2MxTLib.ILMMpg2MxT pMux;
try
{
pMux = (LMMpg2MxTLib.ILMMpg2MxT)ConvertCtrl1.GetSubObject(ConvertObject.TargetFilter);
}
catch (System.Exception except)
{
pMux = null;
}
if (pMux != null)
{
pMux.PrecisionTimeStampAction = LMMpg2MxTLib.Mpg2MxT_PrecisionTimeStampAction.Mpg2MxT_PrecisionTimeStampAction_AddAlways;
double PrecisionTimeStampValue;
pMux.ConvertDateToPrecisionTimeStamp("10/2/2014 9:08:04 AM", null, out PrecisionTimeStampValue);
pMux.PrecisionTimeStampStartValue = PrecisionTimeStampValue;
}
}
European-style dates use the format "day/month/year" and Japanese-style date formats use the format "year/month/date". These cannot be converted using the standard conversion, but they can be converted using a custom string format. This is done by passing a format string describing the date and time components to the ConvertDateToPrecisionTimeStamp methods. Also, the standard separator for the date is slash ('/'), but some dates strings might use dashes ('-') or periods ('.') for the date. All of these can be specified in the format string.
Note that the case of the characters in the format string is important. For example, lower case 'y' represents year in two-digit format, while upper case 'Y' represents year in 4-digit format. Also, 'm' is for minutes, whereas 'M' is the month.
The following characters can be passed in the format string (no other characters are allowed in the format string and will generate an error if present):
Character |
Meaning |
Y |
(Upper case Y) The year in 4-digit format (1970..3000) |
y |
(Lower case Y) The year in 2-digit format. Numbers less than 70 are considered to be above 2000. Numbers higher than or equal to 70 are considered to be in 1900. So the valid date range is that can be represented in this format is 1970..2069 |
M |
Month in 1-2 digits (1..12). 1 is January and 12 is December |
d |
Day in 1-2 digits (1..31) |
h |
Hour in 12-hour format (1-12). Note that this will usually require the AM/PM indicator. 12 AM is morning (00 in 24-hour format) |
H |
Hour in 24-hour format (0-23). Note that '0' is 12 AM and '12' is 12 PM. This does not require AM/PM indicator |
m |
Minute (0..59) |
s |
Second (0..59) |
AM/PM indicator |
|
u | Fractions of a second (tenths of a second, hundredths of a second, milliseconds). If the number has one digit, the value is a tenth of a second. If two digits, hundredths of a second. If three digits, milliseconds. |
' ', '.', '-', ':', '/' |
Space (" "), period ("."), dash ("-"), colon (":") and slash ("/") are treated as separators |
Examples of non-standard date strings with the corresponding custom format string
Non-standard Date string | Format string |
22/12/89 12:08:04 AM | d/M/y h:m:s t |
22/12/1989 12:08:04 AM | d/M/Y h:m:s t |
2014-10-27 14:10:53.421 | Y-M-d H:m:s.u |
/* This examples uses the ILMMpg2MxT interface, but the code for using the ILMMPEG2Encoder and ILMH264Encoder interfaces is very similar so it will not be shown here.
Note that the separator for the date is dash ('-') not slash ('/') and it is indicated in the format string. */
{
LMMpg2MxTLib.ILMMpg2MxT pMux;
try
{
pMux = (LMMpg2MxTLib.ILMMpg2MxT)ConvertCtrl1.GetSubObject(ConvertObject.TargetFilter);
}
catch (System.Exception except)
{
pMux = null;
}
if (pMux != null)
{
pMux.PrecisionTimeStampAction = LMMpg2MxTLib.Mpg2MxT_PrecisionTimeStampAction.Mpg2MxT_PrecisionTimeStampAction_AddAlways;
double PrecisionTimeStampValue;
pMux.ConvertDateToPrecisionTimeStamp("2014-10-27 14:10:53.4212", "Y-M-d H:m:s.u", out PrecisionTimeStampValue);
pMux.PrecisionTimeStampStartValue = PrecisionTimeStampValue;
}
}