65#define MAX_BLUE_IN_CHANNELS 4
72static void *
worker(
void *arg);
77static int CompleteBlueAsyncReq(HANDLE hDevice, LPOVERLAPPED pOverlap);
84 BLUEVELVETC_HANDLE
pSDK = bfcFactory();
85 bfcEnumerate(
pSDK, &iDevices);
88 printf(
"Bluefish444 capture\n");
90 printf(
"\t-t bluefish444[:framestore|:duplex][:depth={10|8}]"
91 "[:subfield][:4K][:device=<device_id>]\n");
93 printf(
"\t\t4K - use 4 inputs of a SuperNova card\n");
95 printf(
"\t\t<device_id> - ID of the Bluefish device (if more present)\n");
96 cout <<
"\t\t" << iDevices <<
" Bluefish devices found in this system" << endl;
98 cout <<
" (default)" << endl;
99 }
else if(iDevices > 1) {
100 cout <<
", valid indices [1," << iDevices <<
"]" << endl;
101 cout <<
"default is 1" << endl;
166 blue_video_sync_struct *pIrqInfo;
169#ifdef HAVE_BLUE_AUDIO
177 OVERLAPPED OverlapChA;
195static void BailOut(BLUEVELVETC_HANDLE pSDK);
196static void InitInputChannel(BLUEVELVETC_HANDLE pSDK, uint32_t DefaultInputChannel,
197 uint32_t UpdateFormat, uint32_t MemoryFormat, uint32_t VideoEngine);
198void RouteChannel(BLUEVELVETC_HANDLE pSDK, uint32_t Source, uint32_t Destination,
201#ifdef HAVE_BLUE_AUDIO
211void InitInputChannel(BLUEVELVETC_HANDLE pSDK, uint32_t DefaultInputChannel, uint32_t UpdateFormat, uint32_t MemoryFormat, uint32_t VideoEngine)
214 bfcSetCardProperty32(pSDK, DEFAULT_VIDEO_INPUT_CHANNEL, DefaultInputChannel);
217 bfcVideoCaptureStop(pSDK);
219 bfcSetCardProperty32(pSDK, VIDEO_INPUT_UPDATE_TYPE, UpdateFormat);
221 bfcSetCardProperty32(pSDK, VIDEO_INPUT_MEMORY_FORMAT, MemoryFormat);
224 bfcSetCardProperty32(pSDK, VIDEO_INPUT_ENGINE, VideoEngine);
227void RouteChannel(BLUEVELVETC_HANDLE pSDK, uint32_t Source, uint32_t Destination, uint32_t LinkType)
229 uint32_t
val = EPOCH_SET_ROUTING(Source, Destination, LinkType);
230 bfcSetCardProperty32(pSDK, MR2_ROUTING,
val);
252 streamsize ss = cout.precision();
253 cout <<
"[Blue cap] Format changed " <<
257 " @" << setprecision(2) <<
266static int CompleteBlueAsyncReq(HANDLE hDevice, LPOVERLAPPED pOverlap)
269 ResetEvent(pOverlap->hEvent);
270 GetOverlappedResult(hDevice, pOverlap, &bytesReturned,
TRUE);
272 return bytesReturned;
281 BOOL bWaitForField =
TRUE;
284 UINT SubFieldIrqs = 0;
289 bfcVideoSyncStructSet(s->
pSDK[0], s->pIrqInfo, BLUE_VIDEO_INPUT_CHANNEL_A,
291 IGNORE_SYNC_WAIT_TIMEOUT_VALUE);
292 bfcWaitVideoSyncAsync(s->
pSDK[0], &s->OverlapChA, s->pIrqInfo);
293 IrqReturn = WaitForSingleObject(s->OverlapChA.hEvent, 1000);
294 CompleteBlueAsyncReq(bfcGetHandle(s->
pSDK[0]), &s->OverlapChA);
296 bfcVideoSyncStructGet(s->
pSDK[0], s->pIrqInfo, VideoMsc, SubFieldIrqs);
298 bWaitForField =
FALSE;
300 }
while(!((SubFieldIrqs == 0) && !bWaitForField));
308 unsigned long int FieldCount = 0;
321 bfcRenderBufferCapture(s->
pSDK[i], BlueBuffer_Image_HANC(s->
ScheduleID));
333 bfcRenderBufferCapture(s->
pSDK[i], BlueBuffer_Image_HANC(s->
ScheduleID));
352 BLUEVELVETC_HANDLE pSDK = bfcFactory();
353 bfcEnumerate(pSDK, &iDevices);
358 for (
int i = 0; i < iDevices; ++i) {
359 auto& card = (*available_cards)[i];
360 snprintf(card.dev,
sizeof(card.dev),
":device=%d", i + 1);
361 snprintf(card.name,
sizeof(card.name),
"Bluefish444 card #%d", i);
365#ifdef HAVE_BLUE_AUDIO
423 cerr <<
"Too many output channels requested." << endl;
426 s->
objHancDecode.type_of_sample_required = (AUDIO_CHANNEL_16BIT|AUDIO_CHANNEL_LITTLEENDIAN);
429 s->
objHancDecode.audio_input_source = AUDIO_INPUT_SOURCE_EMB;
431 s->
objHancDecode.audio_input_source = AUDIO_INPUT_SOURCE_AES;
433 cerr <<
"[Blue cap] Analog audio not supported." << endl;
450 pthread_mutex_lock(&s->
lock);
455 pthread_mutex_unlock(&s->
lock);
462 uint32_t GoldenSize = 0;
463 uint32_t ChunkSize = 0;
464 uint32_t nChunks = 1;
465 unsigned long int FieldCount = 0;
469 UINT SubFieldIrqs = 0;
470 uint32_t VideoMode = VID_FMT_INVALID;
472 int hanc_buffer_id=-1;
474 blue_videoframe_info_ex FrameInfo;
476 unsigned long int CurrentFieldCount = FieldCount;
477 struct av_frame *current_frame = NULL;
486 bfcQueryCardProperty32(s->
pSDK[i], VIDEO_INPUT_SIGNAL_VIDEO_MODE, &val32);
487 if(val32 >= VID_FMT_INVALID)
489 cerr <<
"No valid input signal on channel " <<
490 (char)(
'A' + i) << endl;
497 if(val32 != VideoMode) {
498 cerr <<
"Different signal detected on channel " <<
499 (char)(
'A' + i) <<
" than on " <<
514 bfcVideoSyncStructSet(s->
pSDK[0], s->pIrqInfo, BLUE_VIDEO_INPUT_CHANNEL_A,
516 IGNORE_SYNC_WAIT_TIMEOUT_VALUE);
517 bfcWaitVideoSyncAsync(s->
pSDK[0], &s->OverlapChA, s->pIrqInfo);
518 IrqReturn = WaitForSingleObject(s->OverlapChA.hEvent, 1000);
519 CompleteBlueAsyncReq(bfcGetHandle(s->
pSDK[0]), &s->OverlapChA);
521 bfcVideoSyncStructGet(s->
pSDK[0], s->pIrqInfo, VideoMsc, SubFieldIrqs);
523 if(SubFieldIrqs == 0) {
524 FieldCount = VideoMsc;
531 cout <<
"Error: dropped " << ((FieldCount - s->
LastFieldCount + 2)/2) <<
" frames" << endl;
538 pthread_mutex_lock(&s->
lock);
567 BLUE_U32 Width, Height, BytesPerLine, BytesPerFrame;
568 bfcGetVideoInfo(VideoMode, s->
UpdateFormat, s->
MemoryFormat, &Width, &Height, &BytesPerLine, &BytesPerFrame, &GoldenSize);
569 ChunkSize = BytesPerFrame;
572 for(
int i = 0; i < 2; ++i) {
576 pthread_mutex_unlock(&s->
lock);
579 bfcSetCardProperty32(s->
pSDK[i], VIDEO_INPUT_UPDATE_TYPE,
581 bfcSetCardProperty32(s->
pSDK[i], EPOCH_SUBFIELD_INPUT_INTERRUPTS,
588 ChunkSize = GoldenSize;
590 cout <<
"Golden : " << GoldenSize << endl <<
591 "BytesPerFrame: " << BytesPerFrame << endl <<
592 "ChunkSize : " << ChunkSize << endl;
595 cerr <<
"[Blue422 cap] Fatal: unknown video mode: " << VideoMode << endl;
602 pthread_mutex_lock(&s->
lock);
608 pthread_mutex_unlock(&s->
lock);
612 unsigned int FifoSize = 0;
613 if(BLUE_FAIL(bfcGetCaptureVideoFrameInfoEx(s->
pSDK[0], &s->OverlapChA, FrameInfo,
615 cerr <<
"Capture frame failed!" << endl;
620 if(BLUE_FAIL(bfcGetCaptureVideoFrameInfoEx(s->
pSDK[0], &FrameInfo))) {
621 cerr <<
"Capture frame failed!" << endl;
628 cerr <<
"Invalid video mode!" << endl;
633 if(FrameInfo.BufferId == -1) {
634 cerr <<
"No buffer!" << endl;
638 BufferId = FrameInfo.BufferId;
644 if(SubFieldIrqs == 0) {
645 nOffset = (nChunks - 1) * ChunkSize;
648 nOffset = (SubFieldIrqs - 1) * ChunkSize;
660 bfcSystemBufferReadAsync(s->
pSDK[i], (
unsigned char *)
663 BlueImage_HANC_DMABuffer(BufferId, BLUE_DATA_IMAGE), nOffset);
665 bfcSystemBufferRead(s->
pSDK[i], (
unsigned char *)
668 BlueImage_HANC_DMABuffer(BufferId, BLUE_DATA_IMAGE), nOffset);
672#ifdef HAVE_BLUE_AUDIO
674 hanc_buffer_id = BufferId;
679 bfcSystemBufferReadAsync(s->
pSDK[0], (
unsigned char *) s->
hanc_buffer,
MAX_HANC_SIZE, NULL, BlueImage_HANC_DMABuffer(BufferId, BLUE_DATA_HANC));
681 bfcSystemBufferRead(s->
pSDK[0], (
unsigned char *) s->
hanc_buffer,
MAX_HANC_SIZE, BlueImage_HANC_DMABuffer(BufferId, BLUE_DATA_HANC), 0);
684 int iCardType = CRD_INVALID;
686 bfcDecodeHancFrameEx(s->
pSDK[0], iCardType, (
unsigned int *) s->
hanc_buffer,
695 if(!s->
SubField || SubFieldIrqs == 0) {
698 bfcRenderBufferCapture(s->
pSDK[i],
709 if(!s->
SubField || SubFieldIrqs == 0) {
713 gettimeofday(&t, NULL);
716 float fps = s->
frames / seconds;
723 pthread_mutex_lock(&s->
lock);
729 pthread_mutex_unlock(&s->
lock);
744 while((
item = strtok_r(
fmt,
":", &save_ptr))) {
745 if(strcasecmp(
item,
"framestore") == 0) {
747 }
else if(strcasecmp(
item,
"duplex") == 0) {
749 }
else if(strncasecmp(
item,
"depth=", strlen(
"depth=")) == 0) {
750 int depth = atoi(
item + strlen(
"depth="));
753 }
else if (
depth == 10) {
756 cerr <<
"[Blue cap] Unsupported bit depth: " <<
depth << endl;
758 }
else if(strcasecmp(
item,
"subfield") == 0) {
760 }
else if(strncasecmp(
item,
"device=", strlen(
"device=")) == 0) {
762 }
else if(strcasecmp(
item,
"4K") == 0) {
765 cerr <<
"[Blue cap] Unrecognized option: " <<
item << endl;
776 ULONG InputChannels[4] = {
777 BLUE_VIDEO_INPUT_CHANNEL_A,
778 BLUE_VIDEO_INPUT_CHANNEL_B,
779 BLUE_VIDEO_INPUT_CHANNEL_C,
780 BLUE_VIDEO_INPUT_CHANNEL_D
782 ULONG Sources[4] = { EPOCH_SRC_SDI_INPUT_A,
783 EPOCH_SRC_SDI_INPUT_B,
784 EPOCH_SRC_SDI_INPUT_C,
785 EPOCH_SRC_SDI_INPUT_D
787 ULONG
Destinations[4] = { EPOCH_DEST_INPUT_MEM_INTERFACE_CHA,
788 EPOCH_DEST_INPUT_MEM_INTERFACE_CHB,
789 EPOCH_DEST_INPUT_MEM_INTERFACE_CHC,
790 EPOCH_DEST_INPUT_MEM_INTERFACE_CHD
798 printf(
"vidcap_bluefish444_init\n");
803 printf(
"Unable to allocate bluefish444 capture state\n");
819 memset(&s->OverlapChA, 0,
sizeof(s->OverlapChA));
820 s->OverlapChA.hEvent = CreateEvent(NULL,
TRUE,
FALSE, NULL);
829 s->pIrqInfo = bfcNewVideoSyncStruct(s->
pSDK);
831 cerr <<
"Subfields not supported under Linux." << endl;
841 cerr <<
"4K mode is not supported in duplex mode." << endl;
845 cerr <<
"Subfields are not supported in 4K mode." << endl;
853 s->
pSDK[i] = bfcFactory();
856 bfcEnumerate(s->
pSDK[0], &iDevices);
858 cout <<
"No Bluefish device detected." << endl;
864 cerr <<
"Error on device attach (channel " <<
865 (char)(
'A' + i) <<
")" << endl;
872 int iCardType = CRD_INVALID;
874 bfcQueryCardProperty32(s->
pSDK[0], EPOCH_GET_PRODUCT_ID, &firmware);
876 if (iCardType != CRD_BLUE_SUPER_NOVA) {
877 cerr <<
"4K supported only for a SuperNova card!" << endl;
880 if(firmware != ORAC_4SDIINPUT_FIRMWARE_PRODUCTID) {
881 cerr <<
"Wrong firmware; need 4 input channels (QuadIn)";
893 bfcQueryCardProperty32(s->
pSDK[0], INVALID_VIDEO_MODE_FLAG, &val32);
899 gettimeofday(&s->
t0, NULL);
910 bfcVideoCaptureStop(s->
pSDK[i]);
911 if(BLUE_FAIL(bfcVideoCaptureStart(s->
pSDK[i]))) {
919 gettimeofday(&s->
t0, NULL);
925#ifdef HAVE_BLUE_AUDIO
928 cerr <<
"[Blue cap] Unable to grab audio in sub-field mode." << endl;
933 cerr <<
"[Blue cap] Unable to setup audio." << endl;
941 cerr <<
"[Blue cap] Unable to capture audio. Support isn't compiled in." << endl;
946 pthread_mutex_init(&s->
lock, NULL);
954 cerr <<
"[Blue cap] Error initializing thread." << endl;
975 pthread_mutex_lock(&s->
lock);
991 pthread_mutex_unlock(&s->
lock);
995 CloseHandle(s->OverlapChA.hEvent);
1008 bfcVideoCaptureStop(s->
pSDK[i]);
1029 pthread_mutex_lock(&s->
lock);
1048 pthread_mutex_unlock(&s->
lock);
1054 if(
frame->audio_len) {
1081 pthread_mutex_unlock(&s->
lock);
struct video_frame * frame
const char unsigned int flags
struct audio_frame ** audio
int void(** deleter)(void *))
void vf_free(struct video_frame *buf)
Frees video_frame structure.
struct video_frame * vf_alloc_desc(struct video_desc desc)
Allocates video frame accordig given desc.
This file contains definition of some common audio types.
static const int bluefish_frame_modes_count
static const struct bluefish_frame_mode_t bluefish_frame_modes[]
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_NOTICE
information that may be interesting
#define LOG_LEVEL_INFO
normal reporting
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDCAP_INIT_OK
initialization successful
#define VIDCAP_NO_GENERIC_FPS_INDICATOR
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_FAIL
error ocured
unsigned int audio_capture_channels
#define DEFAULT_AUDIO_CAPTURE_CHANNELS
@ LIBRARY_CLASS_VIDEO_CAPTURE
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
struct used to comunicate with audio capture/playback device
struct video_frame * video
av_frame(struct video_desc desc, int GoldenSize, int BytesPerFrame, int AudioLen)
enum interlacing_t interlacing
char * data
Raw tile data. Pointer must be at least 4B aligned.
unsigned int data_len
length of the data
unsigned int offset
Fragment offset from tile beginning (in bytes). Used only if frame is fragmented.
pthread_cond_t CapturedFrameReadyCV
pthread_cond_t CapturedFrameDoneCV
uint32_t InvalidVideoModeFlag
BLUEVELVETC_HANDLE pSDK[MAX_BLUE_IN_CHANNELS]
struct av_frame_base * CapturedFrame
pthread_cond_t FreeFrameQueueNotEmptyCV
struct av_frame * NetworkFrame
struct video_desc video_desc
queue< struct av_frame * > FreeFrameQueue
unsigned int * hanc_buffer
unsigned long int LastFieldCount
struct hanc_decode_struct objHancDecode
enum interlacing_t interlacing
unsigned int width
width of every tile (!)
unsigned int height
height of every tile (!)
Struct video_frame represents a video frame and contains video description.
enum interlacing_t interlacing
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
unsigned int frame_fragment_id
Used only if (fragment == 1). ID of the frame. Fragments of same frame must have the same ID.
unsigned int fragment
Indicates that the tile is fragmented. Normally not used (only for Bluefish444).
unsigned int last_fragment
Used only if (fragment == 1). Indicates this is the last fragment.
double tv_diff(struct timeval curr_time, struct timeval prev_time)
@ UPPER_FIELD_FIRST
First stored field is top, followed by bottom.
@ PROGRESSIVE
progressive frame
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
@ v210
YCbCr 422 10-bit - xVY0U|xY2UY1|xUY3V|xY5VY4, little-endian (2 bit padding /'x'/),...
struct audio_desc audio_desc_from_frame(const struct audio_frame *frame)
This is an umbrella header for video functions.
static void WaitForMajorInterrupt(struct vidcap_bluefish444_state *s)
static void SyncForSignal(struct vidcap_bluefish444_state *s)
static void vidcap_bluefish444_probe(device_info **available_cards, int *count, void(**deleter)(void *))
static void * worker(void *arg)
static void BailOut(BLUEVELVETC_HANDLE pSDK)
static void InitInputChannel(BLUEVELVETC_HANDLE pSDK, uint32_t DefaultInputChannel, uint32_t UpdateFormat, uint32_t MemoryFormat, uint32_t VideoEngine)
static int vidcap_bluefish444_init(struct vidcap_params *params, void **state)
static const struct video_capture_info vidcap_bluefish444_info
static void signal_error(struct vidcap_bluefish444_state *s)
#define MAX_BLUE_IN_CHANNELS
static bool should_exit_worker
bool UpdateVideoMode(struct vidcap_bluefish444_state *s, uint32_t VideoMode)
void RouteChannel(BLUEVELVETC_HANDLE pSDK, uint32_t Source, uint32_t Destination, uint32_t LinkType)
static bool setup_audio(struct vidcap_bluefish444_state *s, unsigned int flags)
static struct video_frame * vidcap_bluefish444_grab(void *state, struct audio_frame **audio)
static void vidcap_bluefish444_done(void *state)
static void parse_fmt(struct vidcap_bluefish444_state *s, char *fmt)
static void show_help(void)
const char * vidcap_params_get_fmt(const struct vidcap_params *params)
unsigned int vidcap_params_get_flags(const struct vidcap_params *params)
#define VIDCAP_FLAG_AUDIO_AESEBU
AES/EBU audio.
#define VIDCAP_FLAG_AUDIO_EMBEDDED
HD-SDI embedded audio.
const char * get_interlacing_suffix(enum interlacing_t interlacing)
Returns suffix describing interlacing Eg. p, i or psf.