getting into the code a little bit -- two buffers?

28 views
Skip to first unread message

Alex Newman

unread,
Dec 3, 2012, 5:24:34 PM12/3/12
to openr...@googlegroups.com
(I'm not a professional coder, most of my experience is in scripting and the like.)

I think my best play here is to boil down the current code to its basics.  I don't need DSK capability, input selectors nor the video output to be on the GUI.  Cue/playback on the BlackMagic output, if no clip is loaded, mirror the input.

So, getting to the code... I'm a little confused on how the buffers work. 

in decklink_ingest.cpp:

16    MmapBuffer *buffer;
...
57    buffer->put(frm, sizeof(struct mjpeg_frame) + frm->flsize);

I believe this is what declares the record buffer and writes the individual frame to it.

and then in playoutd.cpp, line 29:

MmapBuffer *buffers[MAX_CHANNELS];


So, as far as I can tell, these are separate buffers.  playoutd.cpp never invokes the buffer->get method.

My basic idea is this, basing it off the code found in the event listener of playoutd.cpp line 461...

case EVT_OUTPUT_NEED_FRAME:
   (get the current frame being sent to the input...
    until an event comes through to pause, rewind, load clip)

So I think this could be the key here.  Getting the record buffer to be accessed by playout.d.  would it be OK to combine the mainloops of decklink_ingest.cpp and playoutd.cpp into one master record/playback daemon?  then I could access the record buffer directly, correct?

The idea with my GUI spin is to use XML to create "shows," which will track different clips.  when an in-out-clip sequence is done, it'll access the main record buffer for playback.  after the show's over, it can melt all the clips into separate movie files and dispose of the record buffer, making the clips available for the next show.  Once it's stable it'll get its own runlevel and the entire Fedora desktop will be invisible.

Andrew Armenia

unread,
Dec 3, 2012, 6:58:18 PM12/3/12
to openr...@googlegroups.com
The buffers are a memory mapped file. So it is a region of memory shared between decklink_ingest and playoutd when these two programs are run with the same buffer file. The ingest process only calls the put method, and the playout process only calls the get method. It could be a bit confusing, especially if you don't have a lot of programming experience.

As far as getting the input to loop through to the output, you may need a second DeckLink to accomplish that. The cards I've used cannot capture and output simultaneously, despite having both input and output connectors. When capturing, the output always mirrors the input. If you're OK with not recording while you're playing back, you could shut down the capture before you start the playout. For instant replay purposes here at RPI TV, I found this to be not completely acceptable, because you never know when something might happen. That is why the system was designed to play out on a different card than it records from.

You'd mentioned 720p before. There is another code base that I developed over at https://github.com/exavideo/exacore that we are currently using for 1080i replay. It should be able to work at 720p with some tweaks, however there are at least a few places in the code that assume 1920x1080 frame sizes. Also, the newer code is multithreaded (not multiprocess) and so might be a bit easier to follow.

Hope this helps,


-Andrew

Alex Newman

unread,
Dec 4, 2012, 5:19:23 PM12/4/12
to openr...@googlegroups.com
I definitely think I'll be switching over to exacore.  I'm going to take a closer look this afternoon but it seems like what I'm looking for is in /replay/replay_buffer.cpp and replay_ingest.cpp, /drivers/decklink.cpp.  I've never used ruby but I was able to pick up lua in no time this summer on another project, so hopefully it's a short learning curve.

the hardware arrives Friday so this weekend I'll try to get exacore working and hopefully be able to run the same test record that's in OR's documentation.  Thanks for the pointer.
Reply all
Reply to author
Forward
0 new messages