TimecodeValueImpl (Media Authoring with Java API)
Date: 2016-02-05

tv.amwa.maj.record.impl

## Class TimecodeValueImpl

- java.lang.Object
- - tv.amwa.maj.record.impl.TimecodeValueImpl

- All Implemented Interfaces:
    Serializable, Cloneable, Comparable<TimecodeValue>, CommonConstants, XMLSerializable, TimecodeValue

      public final class TimecodeValueImpl
      extends Object
      implements TimecodeValue, Serializable, XMLSerializable, Comparable<TimecodeValue>, Cloneable, CommonConstants

  Implementation of a value that represents video tape or audio tape timecode information. The timecode interface is capable of representing timecode values specified by SMPTE 12M.

  Representation of timecode values based on a frame offset from the start of an item of content. This class also models the number of frames per second associated with a timecode value and whether the timecode requires the calculation of drop frames.

  All methods that operate on the timecode value, such as `compareTo(tv.amwa.maj.record.TimecodeValue)`, `toString()` and `convertToRealTime()` respect the number of frames-per-second and drop frame values. See the method descriptions for more details.

  This implementation can support high frame rate television. In this case, timecode values will format in a way that is not compatible with SMPTE 12M. For example, a timecode value of `00:00:21:135` represents the 135th frame of the frame 21 seconds into a 300 fps item, frame 6435.

  See Also:
    `TimecodeSegment.getTimecode()`, `TimecodeSegment`, Serialized Form

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class and Description
    --- | ---
    `class` | `TimecodeValueImpl.TimeComponents` Component parts of a timecode value, represented as hours, minutes, seconds and frames in a second.

  - ### Field Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static String` | `DROPFRAME_TAG`
    `static String` | `FRAMESPERSECOND_TAG`
    `static String` | `STARTTIMECODE_TAG`
    `static String` | `TIMECODEVALUE_TAG`

    - ### Fields inherited from interface tv.amwa.maj.constant.CommonConstants

      `AAF_METADICT_NAMESPACE, AAF_METADICT_PREFIX, AAF_XML_NAMESPACE, AAF_XML_PREFIX, ApplicationPluginObjectID, ApplicationPluginsID, MAX_NUM_RGBA_COMPS, MemberOfID, ObjectClassID, ParentClassID, PropertiesID, XMLClassIDAsAttributeName`

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `TimecodeValueImpl()` Create a default timecode value.
    `TimecodeValueImpl(boolean drop, long startFrame, short fps)` Create a timecode value.
    `TimecodeValueImpl(short fps, short hours, short minutes, short seconds, short frames, boolean drop)` Create a new timecode value from the given hours, minutes, seconds and frames according to the given number of frames per second and whether the timecode value requires drop frame calculations.
    `TimecodeValueImpl(short fps, short hours, short minutes, short seconds, short frames, short framePair, boolean drop)` Create a new timecode value from the given hours, minutes, seconds, frames and frame pair according to the given number of frames per second and whether the timecode value requires drop frame calculations.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `void` | `appendXMLChildren(Node parent)` Append extra child elements to the given parent node to serialize the value of an object to an XML fragment.
    `void` | `appendXMLGrandchildren(Node timecodeElement)` Append just the child elements specifying the value of this timecode to the given node.
    `static TimecodeValueImpl` | `calculateDuration(TimecodeValue startValue, TimecodeValue endValue)` Calculate the duration of a piece of media from its start timecode and end timecode.
    `static TimecodeValueImpl` | `calculateEndTimecode(TimecodeValue startValue, TimecodeValue duration)` Calculate the end timecode for a segment of media from its start timecode and a timecode value representing its duration.
    `TimecodeValue` | `clone()` Create a cloned copy of this timecode value.
    `int` | `compareTo(TimecodeValue o)` Chronologically compare this timecode value to another one based on real time, which is calculated to take account of frames per second and drop frame values.
    `TimecodeValueImpl.TimeComponents` | `convertToActualTimeValues()` Converts this timecode into a `TimecodeValueImpl.TimeComponents` value.
    `TimeStruct` | `convertToRealTime()` Converts the timecode value to a real time, taking account of the frames per second and drop frame values.
    `boolean` | `equals(Object o)` Check to see if another timecode value is equal to this one.
    `String` | `getComment()` Include a comment when serializing a value to XML.
    `boolean` | `getDropFrame()` Determines whether the timecode is drop (`true` value) or nondrop (`false` value).
    `short` | `getFramesPerSecond()` Returns the frames per second of the videotape or audio tape of the timecode.
    `long` | `getStartTimecode()` Returns the timecode value by the number of frames offset from the start of the video or audio.
    `int` | `hashCode()`
    `static TimecodeValue` | `parseTimecode(String timecodeText)` Parses a SMPTE-style string representation of a timecode and creates a MAJ API timecode value, implying default values for the frames per second and drop frame parameters from the timecode text.
    `static TimecodeValue` | `parseTimecode(String timecodeText, short fps)` Parses a SMPTE-style string representation of a timecode and creates a MAJ API timecode value, working out the drop frame value from the given timcode text.
    `static TimecodeValue` | `parseTimecode(String timecodeText, short fps, boolean drop)` Parses a SMPTE-style string representation of a timecode and creates a MAJ API timecode value, with all parameters specified.
    `void` | `setDropFrame(boolean drop)` Sets whether the timecode is drop (`true` value) or nondrop (`false` value).
    `void` | `setFramesPerSecond(short framesPerSecond)` Sets the frames per second of the videotape or audio tape of the timecode.
    `void` | `setStartTimecode(long startFrame)` Sets the timecode value by the number of frames offset from the start of the video or audio.
    `String` | `toString()` Formats a timecode value representation in accordance with the SMPTE and EBU specifications.

    - ### Methods inherited from class java.lang.Object

      `getClass, notify, notifyAll, wait, wait, wait`

- - ### Field Detail

    - #### TIMECODEVALUE_TAG

          public static final String TIMECODEVALUE_TAG

      See Also:
        Constant Field Values

    - #### STARTTIMECODE_TAG

          public static final String STARTTIMECODE_TAG

      See Also:
        Constant Field Values

    - #### FRAMESPERSECOND_TAG

          public static final String FRAMESPERSECOND_TAG

      See Also:
        Constant Field Values

    - #### DROPFRAME_TAG

          public static final String DROPFRAME_TAG

      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### TimecodeValueImpl

          public TimecodeValueImpl(boolean drop,
                                   @FrameOffset
                                   long startFrame,
                                   @UInt16
                                   short fps)
                            throws IllegalArgumentException

      Create a timecode value.

      Parameters:
        `drop` - Indicates whether the timecode is drop (`true` value) or nondrop (`false` value).
        `startFrame` - Specifies the timecode as the number of frames offset from the start of the video or audio.
        `fps` - Frames per second of the videotape or audio tape.
      Throws:
        `IllegalArgumentException` - The frames per second value is not a positive value.

    - #### TimecodeValueImpl

          public TimecodeValueImpl()

      Create a default timecode value. Default values are non-drop, start frame set to 0 and frame rate of 1 frames per second.

    - #### TimecodeValueImpl

          public TimecodeValueImpl(@UInt16
                                   short fps,
                                   short hours,
                                   short minutes,
                                   short seconds,
                                   short frames,
                                   boolean drop)
                            throws IllegalArgumentException

      Create a new timecode value from the given hours, minutes, seconds and frames according to the given number of frames per second and whether the timecode value requires drop frame calculations. Internally, these values are converted to an offset value.

      For frames per second values above 30, the value of the frame pair part of the timecode will be set to zero. To set the frame pair value (VITC Field Flag Bit), use `TimecodeValueImpl(short, short, short, short, short, short, boolean)`.

      This method does not apply strict boundaries. Negative values and values greater than the acceptable bounds when displaying a timecode will be accepted and mapped to an appropriate offset. For example, the following three calls to this method create equivalent timecode values:

           time1 = new TimecodeValueImpl(25, 0, 0, 63,   0, false);
           time2 = new TimecodeValueImpl(25, 0, 1, 03,   0, false);
           time3 = new TimecodeValueImpl(25, 0, 1, 04, -25, false);

      Parameters:
        `fps` - Number of frames per second for this timecode value.
        `hours` - Number of hours since the start of an item represented by this timecode.
        `minutes` - Number of minutes in the hour of an item represented by this timecode.
        `seconds` - Number of seconds in the minute of an item represented by this timecode.
        `frames` - Number of frames through the second of an item represented by this timecode.
        `drop` - Does this timecode require drop frame calculation?
      Throws:
        `IllegalArgumentException` - The number of frames per second is not a positive (greater than zero) number.

    - #### TimecodeValueImpl

          public TimecodeValueImpl(@UInt16
                                   short fps,
                                   short hours,
                                   short minutes,
                                   short seconds,
                                   short frames,
                                   short framePair,
                                   boolean drop)

      Create a new timecode value from the given hours, minutes, seconds, frames and frame pair according to the given number of frames per second and whether the timecode value requires drop frame calculations. Internally, these values are converted to an offset value.

      This method does not apply strict boundaries. Negative values and values greater than the acceptable bounds when displaying a timecode will be accepted and mapped to an appropriate offset. For example, the following three calls to this method create equivalent timecode values:

           time1 = new TimecodeValueImpl(25, 0, 0, 63,   0, 0, false);
           time2 = new TimecodeValueImpl(25, 0, 1, 03,   0, 1, false);
           time3 = new TimecodeValueImpl(25, 0, 1, 04, -25, 1, false);

      Parameters:
        `fps` - Number of frames per second for this timecode value.
        `hours` - Number of hours since the start of an item represented by this timecode.
        `minutes` - Number of minutes in the hour of an item represented by this timecode.
        `seconds` - Number of seconds in the minute of an item represented by this timecode.
        `frames` - Number of frames through the second of an item represented by this timecode.
        `framePair` - For frames per second greater than 30, is this the first (.0) or second (.1) in a pair?
        `drop` - Does this timecode require drop frame calculation?
      Throws:
        `IllegalArgumentException` - The number of frames per second is not a positive (greater than zero) number.

  - ### Method Detail

    - #### getDropFrame

          public boolean getDropFrame()

      Description copied from interface: `TimecodeValue`

      Determines whether the timecode is drop (`true` value) or nondrop (`false` value).

      If drop is set to `true`, the real frames-per-second rate represented by the timecode is 29.97. Calculations of the real time represented by a timecode or to create a textual representation of the time code drop 108 selected frames per hour.

      Specified by:
        `getDropFrame` in interface `TimecodeValue`
      Returns:
        Is the timecode a drop value?

    - #### setDropFrame

          public void setDropFrame(boolean drop)

      Description copied from interface: `TimecodeValue`

      Sets whether the timecode is drop (`true` value) or nondrop (`false` value).

      Specified by:
        `setDropFrame` in interface `TimecodeValue`
      Parameters:
        `drop` - Is the timecode a drop value?

    - #### getFramesPerSecond

          public short getFramesPerSecond()

      Description copied from interface: `TimecodeValue`

      Returns the frames per second of the videotape or audio tape of the timecode.

      Specified by:
        `getFramesPerSecond` in interface `TimecodeValue`
      Returns:
        Frames per second of the videotape or audiotape of the timecode.

    - #### setFramesPerSecond

          public void setFramesPerSecond(short framesPerSecond)

      Description copied from interface: `TimecodeValue`

      Sets the frames per second of the videotape or audio tape of the timecode.

      Specified by:
        `setFramesPerSecond` in interface `TimecodeValue`
      Parameters:
        `framesPerSecond` - Frames per second of the videotape or audiotape of the timecode.

    - #### getStartTimecode

          public long getStartTimecode()

      Description copied from interface: `TimecodeValue`

      Returns the timecode value by the number of frames offset from the start of the video or audio.

      Specified by:
        `getStartTimecode` in interface `TimecodeValue`
      Returns:
        Timecode offset value.

    - #### setStartTimecode

          public void setStartTimecode(long startFrame)

      Description copied from interface: `TimecodeValue`

      Sets the timecode value by the number of frames offset from the start of the video or audio.

      Specified by:
        `setStartTimecode` in interface `TimecodeValue`
      Parameters:
        `startFrame` - Frame offset value to use to set the timecode.

    - #### hashCode

          public int hashCode()

      Overrides:
        `hashCode` in class `Object`

    - #### equals

          public final boolean equals(Object o)

      Check to see if another timecode value is equal to this one. Two timecode values are equal if they have the same start frame, number of frames per second and consistent drop frame or non-drop frame values.

      To check to see if two timecode values are equal in time, use `compareTo(tv.amwa.maj.record.TimecodeValue)`.

      Overrides:
        `equals` in class `Object`
      Parameters:
        `o` - Object to test for equality with this one.
      See Also:
        `Object.equals(Object)`

    - #### compareTo

          public final int compareTo(TimecodeValue o)
                              throws NullPointerException

      Chronologically compare this timecode value to another one based on real time, which is calculated to take account of frames per second and drop frame values.

      Specified by:
        `compareTo` in interface `Comparable<TimecodeValue>`
      Specified by:
        `compareTo` in interface `TimecodeValue`
      Parameters:
        `o` - Timecode value to compare this value to.
      Returns:
        A value of -1 if this timecode value is less than the given value, 0 if they are equal and 1 if this one is greater than the one given.
      Throws:
        `NullPointerException` - The given timecode value to compare to this one is `null`.

    - #### toString

          public String toString()

      Formats a timecode value representation in accordance with the SMPTE and EBU specifications. Specifically:

      - EBU TS N12-1999: "Time-and-control codes for television recording". 1999.
      - SMPTE 0012-2008: "SMPTE standard for television, audio and film - time and control code". February 2008. (Character format from SMPTE 0258-2004).

      The format of the returned value is "`hh:mm:ss;ff(.p)?`" for timecodes with drop frames and "`hh:mm:ss:ff(.p)?`" for timecodes with no drop frame. The components of the value of the timecode are:

      - `hh` is the number of hours
      - `mm` is the number of minutes;
      - `ss` is the number of seconds;
      - `ff` is the number of frames through this second;
      .
      - `(.p)?` for frame rates over 30, whether the frame is the first (`.0`) or second (`.1`) of the pair.
      Specified by:
        `toString` in interface `TimecodeValue`
      Overrides:
        `toString` in class `Object`
      Returns:
        String representation of this timecode value.
      See Also:
        `Forge.parseTimecode(String)`

    - #### convertToRealTime

          public TimeStruct convertToRealTime()
                                       throws NumberFormatException

      Converts the timecode value to a real time, taking account of the frames per second and drop frame values. The value returned is a `TimeStructImpl` value, containing the hours, minutes, seconds and fractions of a second represented by the frame offset value returned by `getStartTimecode()`.

      Specified by:
        `convertToRealTime` in interface `TimecodeValue`
      Returns:
        A time value representing the real time offset of the timecode value.
      Throws:
        `NumberFormatException` - The timecode value is larger than the range it is possible to represent with a time structure value.

    - #### parseTimecode

          public static final TimecodeValue parseTimecode(String timecodeText,
                                                          @UInt16
                                                          short fps,
                                                          boolean drop)
                                                   throws NullPointerException,
                                                          ParseException,
                                                          IllegalArgumentException

      Parses a SMPTE-style string representation of a timecode and creates a MAJ API timecode value, with all parameters specified. The method will try and parse both drop and non-drop values, working with both SMPTE-12M values and the additional frame pair value for higher frame rate television.

      The format of a timecode parsed by this method is:

      <hour>`:`<minute>`:`<second>`:`<frame>(`.`<framePair>)?

      The hour, minute, second and frame values should all be Java short values. The framePair value should be either 0 or 1. The number of digits is not significant, although values are limited to being `Int16`. For example, the values `"01:02:03:04"` is parsed the same as `"1:2:003:4".`

      Parameters:
        `timecodeText` - String representation of a timecode value.
        `fps` - Number of frames per second this timecode is measured against.
        `drop` - Whether this timecode has drop values or not?
      Returns:
        A timecode value created by parsing the given textual representation.
      Throws:
        `NullPointerException` - The given timecode string is `null`.
        `ParseException` - It is not possible to parse the given value to a MAJ API timecode value.
        `IllegalArgumentException` - The given frames per second value is a negative value.

    - #### parseTimecode

          public static final TimecodeValue parseTimecode(String timecodeText,
                                                          @UInt16
                                                          short fps)
                                                   throws NullPointerException,
                                                          ParseException

      Parses a SMPTE-style string representation of a timecode and creates a MAJ API timecode value, working out the drop frame value from the given timcode text. The method will try and parse both drop and non-drop values, working with both SMPTE-12M values and a broader definition of timecodes as required for high frame rate television. This method assumes any value with a "`;`" in it is a drop-frame value; otherwise the value is assumed to be a non-drop timecode.

      String timecode representations are parsed as follows:

      - The format of a non-drop timecode specified by frame is:
        <hour>`:`<minute>`:`<second>`:`<frame>(`.`<framePair>)?
      - The format of a drop timecode specified by frame is:
        <hour>`:`<minute>`:`<second>`;`<frame>(`.`<framePair>)?

      The hour, minute, second and frame values should all be Java short values. The framePair value should be either 0 or 1. The number of digits is not significant, although values are limited to being `Int16`. For example, the values `"01:02:03:04"` is parsed the same as `"1:2:003:4".`

      Parameters:
        `timecodeText` - String representation of a timecode value.
        `fps` - Number of frames per second this timecode is measured against.
      Returns:
        A timecode value created by parsing the given textual representation.
      Throws:
        `NullPointerException` - The given timecode string is `null`.
        `ParseException` - It is not possible to parse the given value to a MAJ API timecode value or the given frames per second value is a negative value.

    - #### parseTimecode

          public static final TimecodeValue parseTimecode(String timecodeText)
                                                   throws NullPointerException,
                                                          ParseException

      Parses a SMPTE-style string representation of a timecode and creates a MAJ API timecode value, implying default values for the frames per second and drop frame parameters from the timecode text. The method will try and parse both drop and non-drop values, working with both SMPTE-12M values and a broader definition of timecodes as required for high frame rate television. This method assumes any value with a "`;`" in it is a drop-frame value at 30 fps or 60 fps, otherwise the value is assumed to be a non-drop timecode at 25 fps or 50 fps. The higher frame rates of 60 fps; and 50 fps if the value ends with a frame pair value of `.0` or `.1`.

      String timecode representations are parsed as follows:

      - The format of a non-drop timecode specified by frame is:
        <hour>`:`<minute>`:`<second>`:`<frame>(`.`<framePair>)?
      - The format of a drop timecode specified by frame is:
        <hour>`:`<minute>`:`<second>`;`<frame>(`.`<framePair>)?

      The hour, minute, second and frame values should all be Java short values. The framePair value should be either 0 or 1. The number of digits is not significant, although values are limited to being `Int16`. For example, the values `"01:02:03:04"` is parsed the same as `"1:2:003:4".`

      Parameters:
        `timecodeText` - String representation of a timecode value.
      Returns:
        A timecode value created by parsing the given textual representation.
      Throws:
        `NullPointerException` - The given timecode string is `null`.
        `ParseException` - It is not possible to parse the given value to a MAJ API timecode value.

    - #### convertToActualTimeValues

          public TimecodeValueImpl.TimeComponents convertToActualTimeValues()

      Converts this timecode into a `TimecodeValueImpl.TimeComponents` value. This method will carry out drop frame calculations if required.

      Returns:
        Componentized representation of this timecode value.

    - #### clone

          public final TimecodeValue clone()

      Description copied from interface: `TimecodeValue`

      Create a cloned copy of this timecode value.

      Specified by:
        `clone` in interface `TimecodeValue`
      Overrides:
        `clone` in class `Object`
      Returns:
        Cloned copy of this timecode value.

    - #### appendXMLChildren

          public void appendXMLChildren(Node parent)

      Description copied from interface: `XMLSerializable`

      Append extra child elements to the given parent node to serialize the value of an object to an XML fragment. Methods of the `XMLBuilder` class are provided to help with this process.

      Specified by:
        `appendXMLChildren` in interface `XMLSerializable`
      Parameters:
        `parent` - XML parent element to append child nodes to.

    - #### appendXMLGrandchildren

          public void appendXMLGrandchildren(Node timecodeElement)

      Append just the child elements specifying the value of this timecode to the given node.

      Parameters:
        `timecodeElement` - Element to append timecode specifiers to.

    - #### calculateDuration

          public static final TimecodeValueImpl calculateDuration(TimecodeValue startValue,
                                                                  TimecodeValue endValue)
                                                           throws NullPointerException,
                                                                  IllegalArgumentException

      Calculate the duration of a piece of media from its start timecode and end timecode. The value returned is a timecode representing the duration. Both values must be specified with the same number of frames per second and matching drop timecode specifications. The end value must be the same or greater than the start value.

      To calculate the number of frames of an item of media, call `getStartTimecode()` on the value returned by this method.

      Parameters:
        `startValue` - Start timecode at the beginning of the segment of media, sometimes known as SOM (Start Of Message).
        `endValue` - End timecode at the end of the segment of media, sometimes known as EOM (End Of Message).
      Returns:
        Duration timecode value calculated as the difference between the end value and the start value.
      Throws:
        `NullPointerException` - One or both of the start and/or end timecodes is/are `null`.
        `IllegalArgumentException` - It was not possible to calculate the duration as the timecode values are incompatible or the start value is after the end value.
      See Also:
        `LengthType`, `calculateEndTimecode(tv.amwa.maj.record.TimecodeValue, tv.amwa.maj.record.TimecodeValue)`

    - #### calculateEndTimecode

          public static final TimecodeValueImpl calculateEndTimecode(TimecodeValue startValue,
                                                                     TimecodeValue duration)
                                                              throws NullPointerException,
                                                                     IllegalArgumentException

      Calculate the end timecode for a segment of media from its start timecode and a timecode value representing its duration. Both values must be specified with the same number of frames per second and matching drop timecode specifications.

      Parameters:
        `startValue` - Start timecode at the beginning of a segment of media.
        `duration` - Duration of the media specified as a timecode value.
      Returns:
        End timecode value calculated by adding the duration timecode's length to the start timecode.
      Throws:
        `NullPointerException` - One or both of the start and/or duration values is/are `null`.
        `IllegalArgumentException` - It was not possible to calculate the end timecode as the timecode values are incompatible.
      See Also:
        `calculateDuration(tv.amwa.maj.record.TimecodeValue, tv.amwa.maj.record.TimecodeValue)`

    - #### getComment

          public String getComment()

      Description copied from interface: `XMLSerializable`

      Include a comment when serializing a value to XML. The comment will be inserted as the first child node of the element representing the class.

      Specified by:
        `getComment` in interface `XMLSerializable`
      Returns:
        Comment to add as the first child node of the element representing this class.

(c)2007-2016 Richard Cartwright, all rights reserved. Licensed under Apache 2 license and subject to the AMWA IPR policy.