#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "include/decklink_c.h"
bool abort_loop = false;
uint8_t next_blue = 0;
long width = 1920;
long height = 1080;
DecklinkTimeValue scheduled = 0;
cdecklink_video_frame_t *generate_next_frame(cdecklink_output_t *output) {
cdecklink_mutable_video_frame_t *mutable_frame;
if (cdecklink_output_create_video_frame(output, width, height, width * 4, decklinkFormat8BitBGRA,
decklinkFrameFlagDefault, &mutable_frame) != S_OK) {
printf("Failed to create output frame\n");
return NULL;
}
cdecklink_video_frame_t *frame = cdecklink_mutable_video_frame_to_video_frame(mutable_frame);
uint8_t *bytes;
if (cdecklink_video_frame_get_bytes(frame, (void **) (&bytes)) != S_OK) {
printf("Failed to get frame bytes\n");
cdecklink_mutable_video_frame_release(mutable_frame);
return NULL;
}
for (int o = 0; o < width * height * 4; o += 4) {
bytes[o] = 255;
bytes[o + 1] = next_blue;
bytes[o + 2] = 0;
bytes[o + 3] = 255;
}
next_blue += 10;
return frame;
}
HRESULT frame_completed(void *context, cdecklink_video_frame_t *frame,
DecklinkOutputFrameCompletionResult result) {
if (frame != NULL) {
cdecklink_video_frame_release(frame); }
if (context == NULL) {
printf("No output in callback\n");
return S_FALSE;
}
cdecklink_output_t *output = context;
cdecklink_video_frame_t *next_frame = generate_next_frame(output);
if (next_frame == NULL) {
printf("Failed to generate next frame\n");
return S_FALSE;
}
if (cdecklink_output_schedule_video_frame(output, next_frame, scheduled, 1000, 25000) != S_OK) {
printf("Failed to schedule next frame\n");
return S_FALSE;
}
scheduled += 1000;
return S_OK;
}
HRESULT playback_stopped(void *context) {
printf("Playback stopped\n");
return S_OK;
}
int main() {
cdecklink_iterator_t *iterator = cdecklink_create_decklink_iterator_instance();
if (!iterator)
goto CLEANUP;
int index = 3;
printf("Choose decklink device to output to: ");
printf("\n");
scanf("%d", &index);
cdecklink_device_t *device = NULL;
int i = -1;
while (cdecklink_iterator_next(iterator, &device) == S_OK) {
if (++i == index) {
break;
}
cdecklink_device_release(device);
device = NULL;
}
if (i != index || device == NULL) {
printf("Invalid device index\n");
goto CLEANUP;
}
const char *display_name;
if (FAILED(cdecklink_device_get_display_name(device, &display_name))) {
printf("Failed to get device name\n");
goto CLEANUP;
}
printf("Selected device: %s\n", display_name);
cdecklink_free_string(display_name);
cdecklink_output_t *output;
if (FAILED(cdecklink_device_query_output(device, &output))) {
printf("Device does not support output\n");
goto CLEANUP;
}
cdecklink_display_mode_iterator_t *mode_iterator;
if (cdecklink_output_get_display_mode_iterator(output, &mode_iterator) != S_OK) {
printf("Failed to create output mode iterator\n");
goto CLEANUP;
}
printf("Select videomode:\n");
cdecklink_display_mode_t *mode;
int mode_i = 0;
while (cdecklink_display_mode_iterator_next(mode_iterator, &mode) == S_OK) {
const char *name;
if (FAILED(cdecklink_display_mode_get_name(mode, &name))) {
} else {
printf("%d: %s\n", mode_i++, name);
cdecklink_free_string(name);
cdecklink_display_mode_release(mode);
mode = NULL;
}
}
cdecklink_display_mode_iterator_release(mode_iterator);
mode_iterator = NULL;
index = 7;
printf("\n");
scanf("%d", &index);
if (cdecklink_output_get_display_mode_iterator(output, &mode_iterator) != S_OK) {
printf("Failed to create output mode iterator\n");
goto CLEANUP;
}
mode_i = -1;
while (cdecklink_display_mode_iterator_next(mode_iterator, &mode) == S_OK) {
if (++mode_i == index) {
break;
}
cdecklink_display_mode_release(mode);
mode = NULL;
}
width = cdecklink_display_mode_get_width(mode);
height = cdecklink_display_mode_get_height(mode);
DecklinkDisplayMode mode2 = cdecklink_display_mode_get_display_mode(mode);
if (cdecklink_output_enable_video_output(output, mode2, decklinkVideoOutputFlagDefault) != S_OK) {
printf("Failed to enable video output\n");
goto CLEANUP;
}
if (cdecklink_output_set_scheduled_frame_completion_callback(output, output, &frame_completed,
&playback_stopped) !=
S_OK) {
printf("Failed to set callback\n");
goto CLEANUP;
}
for (int j = 0; j < 3; ++j) {
cdecklink_video_frame_t *frame = generate_next_frame(
output); if (cdecklink_output_schedule_video_frame(output, frame, scheduled, 1000, 25000) != S_OK) {
printf("Failed to schedule frame\n");
goto CLEANUP;
}
scheduled += 1000;
}
if (cdecklink_output_start_scheduled_playback(output, 0, 1000, 1.0) != S_OK) {
printf("Failed to start playback\n");
goto CLEANUP;
}
sleep(1);
printf("Press Any Key to Continue\n");
scanf("%d", &index);
abort_loop = true;
DecklinkTimeValue stopped;
if (cdecklink_output_stop_scheduled_playback(output, 0, &stopped, 1000) != S_OK) {
printf("Failed to start playback\n");
goto CLEANUP;
}
sleep(1);
CLEANUP:
if (mode_iterator)
cdecklink_display_mode_iterator_release(mode_iterator);
if (output)
cdecklink_output_release(output);
if (device)
cdecklink_device_release(device);
if (iterator)
cdecklink_iterator_release(iterator);
return 0;
}