/** * Transforms a timecode string (hh:mm:ss:ff) to milliseconds according to the given edit rate (frame rate). * <p> * Currently works with non-drop timecodes only. * </p> * * @param tc an SMPTE timecode (hh:mm:ss:ff) * @param unitsInSecStr edit unit rate in a form "25 1" * @return a number of milliseconds */ public static long smpteTimecodeToMilliSeconds(String tc, String unitsInSecStr) { BigFraction unitsInSec = parseEditRate(unitsInSecStr); return smpteTimecodeToMilliSeconds(tc, unitsInSec); }
private Stream<Slice<PEltype>> split(Stream<PEltype> pStream) { SliceBuilder<PEltype> builder = new SliceBuilder<PEltype>() .setBeginGetter(p -> ConversionHelper.smpteTimecodeToMilliSeconds(p.getBegin(), frameRate)) .setEndGetter(p -> ConversionHelper.smpteTimecodeToMilliSeconds(p.getEnd(), frameRate)); return SplitUtils.split(pStream .map(builder::build) .collect(Collectors.toList())).stream(); }
@Test public void smpteTimecodeToMilliseconds() { assertEquals(4000L, ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04:00", "25")); assertEquals(4000L, ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04:00", "25 1")); assertEquals(0L, ConversionHelper.smpteTimecodeToMilliSeconds("00:00:00:00", "25")); assertEquals(4000L, ConversionHelper.smpteTimecodeToMilliSeconds("00;00;04;00", "25")); assertEquals(4000L, ConversionHelper.smpteTimecodeToMilliSeconds("00.00.04.00", "25")); assertEquals(4000L, ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04;00", "25")); assertEquals(4000L, ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04.00", "25")); assertEquals(4000L, ConversionHelper.smpteTimecodeToMilliSeconds("0:0:4.0", "25")); assertEquals(4000L, ConversionHelper.smpteTimecodeToMilliSeconds("0:0:4:00", "25")); assertEquals(960L, ConversionHelper.smpteTimecodeToMilliSeconds("00:00:00:24", "25")); assertEquals(500L, ConversionHelper.smpteTimecodeToMilliSeconds("00:00:00:25", "50")); assertEquals(200L, ConversionHelper.smpteTimecodeToMilliSeconds("00:00:00:10", "50")); assertEquals(18243000L, ConversionHelper.smpteTimecodeToMilliSeconds("05:04:03:00", "25")); assertEquals(18243960L, ConversionHelper.smpteTimecodeToMilliSeconds("05:04:03:24", "25")); assertEquals(18243500L, ConversionHelper.smpteTimecodeToMilliSeconds("05:04:03:25", "50")); assertEquals(18243200L, ConversionHelper.smpteTimecodeToMilliSeconds("05:04:03:10", "50")); assertEquals(243200L, ConversionHelper.smpteTimecodeToMilliSeconds("00:4:3:10", "50")); }
@Test(expected = ConversionHelperException.class) public void incorrectSmpteTimecodeToMillisecondsIncorrectEditRateEmpty() { ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04:00", ""); }
@Test(expected = ConversionHelperException.class) public void incorrectSmpteTimecodeToMillisecondsEmptyFrames() { ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04:", "25"); }
@Test(expected = ConversionHelperException.class) public void incorrectSmpteTimecodeToMillisecondsNotNumbers() { ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04:nn", "25"); }
@Test(expected = ConversionHelperException.class) public void incorrectSmpteTimecodeToMillisecondsIncorrectEditRateNonNumber() { ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04:00", "aaa"); }
@Test(expected = ConversionHelperException.class) public void incorrectSmpteTimecodeToMillisecondsIncorrectEditRateMoreArguments() { ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04:00", "30000 1001 1"); }
@Test(expected = ConversionHelperException.class) public void incorrectSmpteTimecodeToMillisecondsNoFrame() { ConversionHelper.smpteTimecodeToMilliSeconds("00:00:04", "25"); }
private long getDestStartTime() { // composition timecode as specified in CPL String cplStartTime = getCompositionTimecodeStart(); BigFraction cplRate = getCompositionTimecodeRate(); // start time as specified in conversion.xml (destination parameter). DestTemplateParameterContext destContext = contextProvider.getDestContext(); String destStartTime = destContext.getParameterValue(DestContextParameters.START_TIME); String destRateStr = destContext.getParameterValue(DestContextParameters.FRAME_RATE); BigFraction destRate = StringUtils.isEmpty(destRateStr) ? null : ConversionHelper.parseEditRate(destRateStr); // values from conversion.xml has higher priority String startTime = StringUtils.isEmpty(destStartTime) ? cplStartTime : destStartTime; BigFraction rate = destRate == null ? cplRate : destRate; // convert to milliseconds if (!StringUtils.isEmpty(startTime) && (rate != null)) { return ConversionHelper.smpteTimecodeToMilliSeconds(startTime, rate); } // default fallback 00:00:00:00 return 0L; }
/** * Check that total duration specified in Metadata.xml is less than total duration of the output file. * Otherwise conversion will abort at the very last step (BMX). It may make the user unhappy after a long conversion. */ private void checkTotalDuration() { String metadataTotalDurationTc = metadataXmlProvider.getDpp().getTechnical().getTimecodes().getTotalProgrammeDuration().getValue(); if (StringUtils.isEmpty(metadataTotalDurationTc)) { return; } String destFps = contextProvider.getDestContext().getParameterValue(DestContextParameters.FRAME_RATE); if (destFps == null) { destFps = MetadataXmlProvider.DEST_FRAME_RATE; } BigFraction fps = ConversionHelper.parseEditRate(destFps); long metadataTotalDurationMs = ConversionHelper.smpteTimecodeToMilliSeconds( metadataTotalDurationTc, fps); long cplTotalDurationMs = getCplTotalDurationMs(); // BMX accepts any total duration if zero timecode is specified in metadata.xml if (metadataTotalDurationMs == 0) { return; } if (metadataTotalDurationMs > cplTotalDurationMs) { throw new ConversionException( String.format("A total programme duration as specified in metadata.xml (%s, %s ms) exceeds a " + "total duration of the output as defined by the CPL (%s, %s ms) ", metadataTotalDurationTc, String.valueOf(metadataTotalDurationMs), ConversionHelper.msToSmpteTimecode(cplTotalDurationMs, fps), String.valueOf(cplTotalDurationMs))); } }