server icon indicating copy to clipboard operation
server copied to clipboard

Timecode support

Open jesperstarkar opened this issue 7 years ago • 23 comments

In an ongoing project we're working on adding timecode support. @Julusian is the lead programmer.

Proposed features

  • Three modes configurable or runtime configurable for each channel: Free running (default), Time of day (system time), and slaved (link to source).
  • SMPTE format
  • Marriage of frames and timecode pre. consumers
  • Compensation for internal latency, so that SDI output timecode will be in syn with SDI input timecode, even though the images are 6-8 frames old.

Open questions

  • Do we want different modes pr. consumer on a channel?
  • How do we handle compensation?
  • How do we handle daylight saving time switch, if we were to add logic to the time processing?
  • Sources other than Decklink to slave to? (@jamesdwise). A generic "Timecode producer" or multiple which can do LTC or other formats in the future?

Slaving to SDI input

  • Either config a given SDI input in the system and only use this for timecode reference, removing it as a possible input for CasparCG.
  • Or runtime slaving to an already engaged Decklink Producer. So basically referencing a layer which has Decklink input, slaving timecode from this.

In addition to the Decklink consumer throughput we want to use the -timecode flag for FFmpeg consumers to have timecode written to files.

jesperstarkar avatar Feb 22 '18 10:02 jesperstarkar

Realted to #821 and #772

jesperstarkar avatar Feb 22 '18 11:02 jesperstarkar

Timecode has to be bound to the channel frame output which must be in sync with a primary producer (e.g. decklink) providing the channel clock. This channel clock may or may not genlocked (external reference). And this reference signal may or may not be locked to UTC time. So the only thing you can do is to sync the timecode output once on server start to system time and continue with counting it up on each frame. Else you would run into problemes with skipped or duplicated timecode values. And keep in mind that each channel is not genlocked to each other. It may have an independant clock source so it needs its own timecode generator...

premultiply avatar Feb 22 '18 16:02 premultiply

Yeah timecode should be based off of output frame counting shouldn't it? It's my understanding that ffmpeg producer works via PTS and it's possible to drop or duplicate frames since it's just trying to air based on PTS and not tick successive frames to playout. @ronag can you shed some light on this?

TomKaltz avatar Feb 22 '18 17:02 TomKaltz

FFMPEG bases playback on time stamps.

ronag avatar Feb 22 '18 18:02 ronag

Yeah I guess it doesn't matter. There is a chance timecode could become discontinuous due to a performance-related skipped frame so worrying about a skipped or dupped frame due to channel PTS mismatch is acceptable.

TomKaltz avatar Feb 22 '18 19:02 TomKaltz

So the only thing you can do is to sync the timecode output once on server start to system time and continue with counting it up on each frame

I disagree with that. If the channel timecode doesn't update to input timecode at regular intervals, then you risk your clock drifting, especially if the server is dropping frames. Also what would happen if your timecode source wasnt running when you started up your caspar server? If the input timecode isnt monotonic then I would expect the output timecode to follow that as it is the reference timecode that we are following.

And keep in mind that each channel is not genlocked to each other.

Yes, the intention is that each channel will be able to have its own timecode source.

Julusian avatar Feb 25 '18 20:02 Julusian

Worse case: Input and output may not be in sync and channels may not be in sync and timecode may jump forward and backwards, freezes or is missing at all. Happy timing! Good luck and have fun with it. ;-)

You need a reliable, synced and monothonic time source if you start implementing anything like this. At least outputs and channels need to be genlocked and locked to a single timecode source. Else it would be not frame accurate but that could be done anytime with any simple client without all these timecode implementations.

premultiply avatar Feb 25 '18 21:02 premultiply

Can i ask, Are you planning on VITC support to the Decklink/Bluefish Producers, This would be really helpful in installations running SCTE 104/35 for Ad Insertion for those using it as a main channel playout.

Andy

maceyldn avatar Feb 28 '18 10:02 maceyldn

TC will be read from VITC.

jesperstarkar avatar Feb 28 '18 10:02 jesperstarkar

@maceyldn img_0312

Output only for now, free running and pr. channel. @Julusian will be focusing on slaving to an input soon.

jesperstarkar avatar Apr 04 '18 12:04 jesperstarkar

Timecode can now be passed through caspar. It is paired with frames through the mixer, so is kept in sync with the video. This is easily tested by feeding a decklink a source with both vitc and bitc, and viewing the decklink consumer on a monitor with vitc viewing (or use another decklink with the CapturePreview sdk sample project)

I have added some AMCP commands to set a timecode source. The names are not final are are likely to change.

>>TIME [channel] 
<<201 TIME OK
<<[00:00:00:00] //some timecode
returns current timecode of the channel
>>TIME [channel] [timecode]
<<4xx TIME FAILED // if is locked to source or
<<4xx TIME FAILED // if timecode is invalid or
<<201 TIME OK
<<[00:00:00:00] //some timecode
sets the current timecode of the channel
>>TIMECODE [channel] SOURCE CLOCK
<<202 TIMECODE SOURCE OK
sets the timecode to follow system clock (currently always UTC)
>>TIMECODE [channel] SOURCE CLEAR
<<202 TIMECODE SOURCE OK
clears the timecode source, and leaves it to freerun
>>TIMECODE [channel] SOURCE LAYER [num]
<<4xx TIMECODE SOURCE FAILED // if not enough parameters
<<202 TIMECODE SOURCE OK
attempts to set the timecode source as the producer currently in the specified layer.
doesnt currently report failure or check producer type (will be changed)

The only producer that can currently provide timecode is decklink, and it must be active as a source on the channel. It is all done via 2/3 methods on the frame_producer interface, so any producer can easily be extended to be a source in future. Once the producer is unloaded, a warning is printed to the console, and the channel is left freerunning from the last timecode. The current timecode and source will be exposed over osc, so they can be monitored

The next step is to be able to configure channel timecode from the config file. This is what I propose unless anyone has any suggestions:

<channel>
  <timecode>free [free|clock|layer]</timecode>
  <timecode_offset>???</timecode_offset>            // clock only, not yet sure on how to format. may be timezone
  <timecode_source>DECKLINK 5 FORMAT 1080i5000</timecode_device> // AMCP command to load into layer specified above
  <timecode_source_layer>10</timecode_device_layer> // layer to load producer into
</channel>

I was previously thinking to have a timecode_device tag instead of timecode_source, but that would be rather inflexible for parameters or get overly complex. This should be much simpler to handle and maintain.

Perhaps this should be made more generic to allow for loading multiple layers at startup, one of which can then be chosen as the timecode source. eg:

<channel>
  <timecode>free [free|clock|layer]</timecode>
  <timecode_offset>???</timecode_offset> 
  <timecode_layer>10</timecode_layer>
  <predefined_layers>
    <layer id="0">BG_LIGHT LOOP</layer> // video file
    <layer id="10">DECKLINK 5 FORMAT 1080i5000</layer>
    <layer id="20">[HTML] http://localhost:3000/overlay.html</layer>
  </predefined_layers>
</channel>

Does anyone have any thoughts on what I have done so far or my proposal for the config file?

Julusian avatar Apr 18 '18 21:04 Julusian

NICE any test done yet with interupted / reversed or cue'ed back/forward TC ?

MauriceVeraart avatar Apr 18 '18 21:04 MauriceVeraart

@MauriceVeraart Not yet, but I shall do once I have a test program to generate such timecodes

Julusian avatar Apr 18 '18 23:04 Julusian

ok thanks julusian can I help by making a file with jumpy timecode ?

other question by VITC you mean RP188 right ? found this in BM's sdk doc

2.4.9 Timecode/Timecode user bits The capture and output of VITC and RP188 timecodes are supported on certain DeckLink models. VITC timecodes are only supported with SD video modes. RP188 timecodes are only supported with HD video modes. To use this feature please refer to the following points:

MauriceVeraart avatar Apr 20 '18 08:04 MauriceVeraart

There is not such thing as „jumpy“ timecode on files as it was possibly on VTRs. Files like MXF have a „StartTC“ metadata entry in header and its the decoder job to advance it frame by frame.

There may be other custom legacy and incompatible „timecode“ tracks in some wrappers but this is only possible to use by special software/hardware and may be inconsistent to other timecodes in same file etc.

premultiply avatar Apr 20 '18 09:04 premultiply

other question by VITC you mean RP188 right ?

Yes, I am using RP188. I intend to make it auto select RP188 or VITC based on the video format being used.

can I help by making a file with jumpy timecode ?

I don't think that is necessary, and I'm not sure how I could even play such a file. The Blackmagic SDK includes a simple sample to generate an output with timecode, so my plan is to modify that.

Julusian avatar Apr 20 '18 09:04 Julusian

Sorry for not being complete ;) I ment a audiofile with LTC recorded on it to put into a generator / inserter I have old deck's and stuff laying around where I could make weird timecode stuff with like slow running, or reversed and such

nevermind

MauriceVeraart avatar Apr 20 '18 09:04 MauriceVeraart

Ah ok. Thanks for the offer, but I have what I need for now :)

Julusian avatar Apr 20 '18 09:04 Julusian

This is now complete and just needs further testing and porting to 2.2 I have a document describing the final functionality including new commands and config as well as known limitations, which will eventually make its way to the wiki Doc: https://docs.google.com/document/d/1xkksxIdNHMO95RFF8wJ3vYRbXCHwKnjkMwVqwAyjv3A/edit?usp=sharing Build: https://drive.google.com/open?id=1krPtXGHIxes2MRqzxuagtw7AzZYrIgj7

Julusian avatar May 08 '18 16:05 Julusian

Cool definatly gona check it out some were this week.

Just a question (if it's a stupid question don't shoot me I am a C++ novice ;) ) where do you handover the timecode from the sources (free/clock/layer) to the part that processes it.

or in other words if I make a TCsource myself what should I call (just want to test myseIf to see if I could make a artnet timecode interface)

ls Maurice

MauriceVeraart avatar May 08 '18 16:05 MauriceVeraart

@MauriceVeraart

If its a producer, then there are a couple of methods to override from frame_producer as defined by https://github.com/nrkno/tv-automation-casparcg-server/blob/2.1.x/core/producer/timecode_source.h Then the producer can be loaded onto the channel and used as a source the same as the decklink can currently.

The selection between the various types of source gets handled by this class https://github.com/nrkno/tv-automation-casparcg-server/blob/2.1.x/core/channel_timecode.cpp It has a reference to the layer producer (if any) and produces the clock and free times. The channel then calls the tick method on this during its loop to determine the time to use.

So for an artnet source, unless you want it loaded as a layer in the channel, feed it into channel_timecode::set_source() and it should start providing your timecode

Julusian avatar May 08 '18 16:05 Julusian

Hi Julusian

If you still remember, could you let me know which build you have implemented this in? It is a part of the master branch now or where do I find your work?

simonsundgaard avatar Mar 28 '22 08:03 simonsundgaard

There is a rebased (onto 2.4 beta 1) prototype implementation at https://github.com/CasparCG/server/commit/056c9469da08b5c958ccf5fc12713e62a94490fa. This has not been tested at all, and needs some further work before it can be considered ready for merging. Primarily it is probably needed to support more producer types as timecode sources.

If anyone wants to pick this up and finish it off feel free to do so. I do not expect to continue development of this myself

Julusian avatar Dec 24 '23 00:12 Julusian