Skip to content

Commit

Permalink
add "decklink_ingest" program
Browse files Browse the repository at this point in the history
this captures directly from a DeckLink capture card into the MJPEG codec.
This eliminates some memory copying.
  • Loading branch information
asquared committed Feb 1, 2011
1 parent 63f8a0a commit c3459e1
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 2 deletions.
12 changes: 10 additions & 2 deletions core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ LDFLAGS += `pkg-config --libs cairo`
LDFLAGS += `pkg-config --libs pango`
LDFLAGS += `pkg-config --libs pangocairo`

all: sdl_gui mjpeg_ingest playoutd decklink_capture field_split ffoutput libjpeg_test time_libjpeg v4l2_ingest
all: sdl_gui mjpeg_ingest playoutd decklink_capture field_split ffoutput \
libjpeg_test time_libjpeg v4l2_ingest \
decklink_ingest

sdl_gui: sdl_gui.cpp mmap_buffer.cpp mjpeg_frame.cpp picture.cpp
$(CC) $(CFLAGS) `sdl-config --cflags` -o $@ $^ $(LDFLAGS) `sdl-config --libs` -lSDL_image -ljpeg
Expand All @@ -36,6 +38,11 @@ v4l2_ingest: v4l2_ingest.cpp mmap_buffer.cpp picture.cpp \
decklink_capture: decklink_capture.cpp $(SDK_PATH)/DeckLinkAPIDispatch.cpp
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)

decklink_ingest: decklink_ingest.cpp $(SDK_PATH)/DeckLinkAPIDispatch.cpp \
mmap_buffer.cpp picture.cpp mjpeg_frame.cpp \
stats.cpp mmap_state.cpp
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) -ljpeg

playoutd: playoutd.cpp mjpeg_frame.cpp picture.cpp mmap_buffer.cpp \
$(SDK_PATH)/DeckLinkAPIDispatch.cpp thread.cpp \
mutex.cpp condition.cpp event_handler.cpp
Expand All @@ -59,4 +66,5 @@ time_libjpeg: time_libjpeg.cpp mjpeg_frame.cpp picture.cpp

clean:
rm -f sdl_gui mjpeg_ingest playoutd decklink_capture \
field_split ffoutput libjpeg_test time_libjpeg v4l2_ingest
field_split ffoutput libjpeg_test time_libjpeg v4l2_ingest \
decklink_ingest
195 changes: 195 additions & 0 deletions core/decklink_ingest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#include "DeckLinkAPI.h"
#include "Capture.h"

#include "mmap_buffer.h"
#include "mmap_state.h"
#include "mjpeg_config.h"
#include "mjpeg_frame.h"
#include "stats.h"

MmapBuffer *buffer;
MmapState *clock_ipc;
MJPEGEncoder enc;
EncodeStats stats(29.97);

#define FRAMES_PER_SEC 30

HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame* videoFrame, IDeckLinkAudioInputPacket* audioFrame)
{
void *frameBytes;
void *audioFrameBytes;

BMDTimeValue time, duration;
int frameCount, frames, sec, min, hr;
int size;
void *data;
Picture *p;

// Handle Video Frame
if(videoFrame)
{
if (videoFrame->GetFlags() & bmdFrameHasNoInputSource)
{
fprintf(stderr, "!!! NO SIGNAL !!! \n");
}
else
{
size = videoFrame->GetRowBytes( ) * videoFrame->GetHeight( );
videoFrame->GetBytes(&data);

// make a 720x480 frame
p = Picture::alloc(720, 480, 1440, UYVY8);
memcpy(p->data, ((uint8_t *) data) + 6*1440, 480*1440);

// encode frame
mjpeg_frame *frm = enc.encode_full(p, true);
Picture::free(p);

clock_ipc->get(&frm->clock, sizeof(frm->clock));
frm->odd_dominant = true;
frm->interlaced = false;
buffer->put(frm, sizeof(struct mjpeg_frame) + frm->f1size);

stats.output_bytes(frm->f1size);
stats.finish_frames(1);
}

}

return S_OK;
}

HRESULT DeckLinkCaptureDelegate::VideoInputFormatChanged(BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode *mode, BMDDetectedVideoInputFormatFlags)
{
return S_OK;
}

int main(int argc, char *argv[])
{
IDeckLink *deckLink;
IDeckLinkInput *deckLinkInput;
IDeckLinkDisplayModeIterator *displayModeIterator;
IDeckLinkIterator *deckLinkIterator = CreateDeckLinkIteratorInstance();
DeckLinkCaptureDelegate *delegate = 0;
IDeckLinkDisplayMode *displayMode = 0;
IDeckLinkConfiguration *deckLinkConfig = 0;
BMDDisplayMode selectedDisplayMode = bmdModeNTSC;
BMDVideoConnection input_source;
int displayModeCount = 0;
int exitStatus = 1;
int ch;
int cardIndex = 2;
HRESULT result;
const char *string;

if (argc < 3) {
fprintf(stderr, "usage: %s card_index buffer\n", argv[0]);
return 1;
}

cardIndex = atoi(argv[1]);

buffer = new MmapBuffer(argv[2], MAX_FRAME_SIZE, true);
clock_ipc = new MmapState("clock_ipc");

if (!deckLinkIterator)
{
fprintf(stderr, "This application requires the DeckLink drivers installed.\n");
goto bail;
}

while (cardIndex >= 0) {
/* Connect to the first DeckLink instance */
result = deckLinkIterator->Next(&deckLink);
if (result != S_OK)
{
fprintf(stderr, "Invalid card index.\n");
goto bail;
}
cardIndex--;
}

deckLink->GetModelName(&string);
fprintf(stderr, "Found a card: %s\n", string);
free((void *)string);

if (deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkInput) != S_OK)
goto bail;

if (deckLink->QueryInterface(IID_IDeckLinkConfiguration, (void**)&deckLinkConfig) != S_OK)
goto bail;

/* set composite in */
if (deckLinkConfig->SetInt(bmdDeckLinkConfigVideoInputConnection,
bmdVideoConnectionComposite) != S_OK) {
fprintf(stderr, "failed to set composite input\n");
goto bail;
}

/* set 7.5 IRE setup level*/
if (deckLinkConfig->SetInt(bmdDeckLinkConfigAnalogVideoInputFlags,
bmdAnalogVideoFlagCompositeSetup75) != S_OK) {
fprintf(stderr, "failed to set analog input flags\n");
goto bail;
}

delegate = new DeckLinkCaptureDelegate();
deckLinkInput->SetCallback(delegate);
fprintf(stderr, "Callback set\n");


result = deckLinkInput->EnableVideoInput(selectedDisplayMode, bmdFormat8BitYUV, 0);
if(result != S_OK)
{
fprintf(stderr, "Failed to enable video input. Is another application using the card?\n");
goto bail;
}


result = deckLinkInput->StartStreams();
if(result != S_OK)
{
goto bail;
}


fprintf(stderr, "Attempting to start capture...\n");
// All Okay.
exitStatus = 0;

// Block main thread until signal occurs
while (1) { sleep(1); }
fprintf(stderr, "Stopping Capture\n");

bail:

if (deckLinkInput != NULL)
{
deckLinkInput->Release();
deckLinkInput = NULL;
}

if (deckLink != NULL)
{
deckLink->Release();
deckLink = NULL;
}


if (deckLinkConfig != NULL) {
deckLinkConfig->Release( );
deckLinkConfig = NULL;
}

if (deckLinkIterator != NULL)
deckLinkIterator->Release();

return exitStatus;
}

0 comments on commit c3459e1

Please sign in to comment.