70#define BLUEFISH444_MAGIC 0x15b75db8
74#define MAX_BLUE_OUT_CHANNELS 4
79 ULONG UpdateFormat, ULONG MemoryFormat, ULONG VideoEngine);
80static void RouteChannel(BLUEVELVETC_HANDLE pSDK, ULONG Source, ULONG Destination,
88 for(
int i = 0; i < TilesCount; ++i) {
114#ifdef HAVE_BLUE_AUDIO
118 void put_audio_frame(
const struct audio_frame *)
noexcept;
149#ifdef HAVE_BLUE_AUDIO
151 hanc_stream_info_struct m_HancInfo;
152 pthread_spinlock_t m_AudioSpinLock;
159 int deviceId)
noexcept(
false) :
162 m_deviceId(deviceId),
163 m_AttachedDevicesCount(0),
166 m_pPlayingBuffer(NULL),
172 BLUE_S32 iDevices = 0;
176#ifdef HAVE_BLUE_AUDIO
179 throw runtime_error(
"Audio support missing in this build");
182 pthread_mutex_init(&m_lock, NULL);
183 pthread_cond_init(&m_WorkerCv, NULL);
184 pthread_cond_init(&m_BossCv, NULL);
186 BLUEVELVETC_HANDLE pSDK = bfcFactory();
187 bfcEnumerate(pSDK, &iDevices);
190 throw runtime_error(
"No Bluefish card detected");
193 bfcQueryCardType(pSDK, &m_CardType, m_deviceId);
194 bfcQueryCardProperty32(pSDK, INVALID_VIDEO_MODE_FLAG, &val32);
195 m_InvalidVideoModeFlag = val32;
197 if(BLUE_FAIL(bfcAttach(pSDK, m_deviceId))) {
199 throw runtime_error(
"Unable to attach card");
202 bfcQueryCardProperty32(pSDK, EPOCH_GET_PRODUCT_ID, &val32);
204 m_CardFirmware = val32;
205 m_deviceId = deviceId;
210#ifdef HAVE_BLUE_AUDIO
211 memset(&m_AudioDesc, 0,
sizeof(m_AudioDesc));
212 memset(&m_HancInfo, 0,
sizeof(m_HancInfo));
213 for(
int i = 0; i < 4; ++i) {
214 m_HancInfo.AudioDBNArray[i] = -1;
216 m_HancInfo.hanc_data_ptr = (
unsigned int *) bfAlloc(
MAX_HANC_SIZE);
217 pthread_spin_init(&m_AudioSpinLock, 0);
220 pthread_create(&m_thread, NULL, playback_thread,
this);
227 pthread_mutex_lock(&
m_lock);
230 pthread_mutex_unlock(&
m_lock);
231 unsigned long int FieldCount;
233 bfcWaitVideoOutputSync(
m_pSDK[0], UPD_FMT_FRAME, &FieldCount);
239 pthread_mutex_destroy(&
m_lock);
243#ifdef HAVE_BLUE_AUDIO
246 pthread_spin_destroy(&m_AudioSpinLock);
259 uint32_t FrameCount = 0;
261#ifdef HAVE_BLUE_AUDIO
262 uint32_t EmbAudioFlag = blue_enable_hanc_timestamp_pkt | blue_emb_audio_enable;
265 gettimeofday(&t0, NULL);
270 Overlapped[i].hEvent = CreateEvent(NULL,
TRUE,
FALSE, NULL);
276 pthread_mutex_lock(&
m_lock);
285 pthread_mutex_unlock(&
m_lock);
291 unsigned long int FieldCount = 0;
294 bfcWaitVideoOutputSync(
m_pSDK[0], UPD_FMT_FRAME, &FieldCount);
296 pthread_mutex_lock(&
m_lock);
299 pthread_mutex_unlock(&
m_lock);
302 bool WaitResult =
true;
305 unsigned char *videoBuffer;
307 OVERLAPPED *OverlapCh = &Overlapped[i];
310 videoBuffer = (
unsigned char *)
frame->pVideoBuffer[i];
312 videoBuffer = (
unsigned char *)
frame->pVideoBuffer[0];
315 int err = bfcSystemBufferWriteAsync(
317 int err = bfcSystemBufferWrite(
324 BlueImage_HANC_DMABuffer(
frame->BufferId, BLUE_DATA_IMAGE) :
325 BlueImage_DMABuffer(
frame->BufferId, BLUE_DATA_IMAGE)), 0
328 cerr <<
"Write failed (Channel " << (char) (
'A' + i) <<
")" << endl;
335 DWORD BytesReturned = 0;
336 GetOverlappedResult(bfcGetHandle(
m_pSDK[i]), &Overlapped[i], &BytesReturned,
TRUE);
337 ResetEvent(Overlapped[i].hEvent);
344#ifdef HAVE_BLUE_AUDIO
346 m_HancInfo.time_code = 0LL;
347 m_HancInfo.rp188_ltc_time_code = 0LL;
348 m_HancInfo.ltc_time_code = 0LL;
349 m_HancInfo.sd_vitc_time_code = 0LL;
352 uint32_t NrSamples = 0;
353 pthread_spin_lock(&m_AudioSpinLock);
354 uint32_t NumberAudioChannels = m_AudioDesc.ch_count;
355 char audio_data[2002*4*16];
356 unsigned int nSampleType;
357 ULONG EmbAudioProp = 0;
359 if(NumberAudioChannels > 0) {
362 switch(m_AudioDesc.bps) {
364 nSampleType = AUDIO_CHANNEL_16BIT;
367 nSampleType = AUDIO_CHANNEL_24BIT;
370 fprintf(stderr,
"[Blue] Unhandled audio sample type!\n");
374 if(NumberAudioChannels > 0)
375 EmbAudioProp |= (blue_emb_audio_group1_enable);
376 if(NumberAudioChannels > 4)
377 EmbAudioProp |= (blue_emb_audio_group2_enable);
378 if(NumberAudioChannels > 8)
379 EmbAudioProp |= (blue_emb_audio_group3_enable);
380 if(NumberAudioChannels > 12)
381 EmbAudioProp |= (blue_emb_audio_group4_enable);
384 m_AudioDesc.bps *m_AudioDesc.ch_count);
385 NrSamples = bytes / m_AudioDesc.bps / m_AudioDesc.ch_count;
387 pthread_spin_unlock(&m_AudioSpinLock);
391 m_AudioDesc.ch_count, NrSamples,
392 nSampleType, EmbAudioProp | EmbAudioFlag);
400 bfcSystemBufferWriteAsync(
m_pSDK[0], (
unsigned char *) m_HancInfo.hanc_data_ptr,
402 NULL, BlueImage_HANC_DMABuffer(
frame->BufferId, BLUE_DATA_HANC));
404 bfcSystemBufferWrite(
m_pSDK[0], (
unsigned char *) m_HancInfo.hanc_data_ptr,
406 BlueImage_HANC_DMABuffer(
frame->BufferId, BLUE_DATA_HANC), 0);
413 bfcRenderBufferUpdate(
m_pSDK[i],
415 BlueBuffer_Image_HANC(
frame->BufferId) :
416 BlueBuffer_Image(
frame->BufferId))
421 cerr <<
"[Blue444 disp] " <<
"Dropped " <<
431 gettimeofday(&t, NULL);
432 double seconds =
tv_diff(t, t0);
434 float fps = FrameCount / seconds;
436 FrameCount, seconds, fps);
446 CloseHandle(Overlapped[i].hEvent);
459 value = ENUM_BLACKGENERATOR_ON;
460 bfcSetCardProperty32(
m_pSDK[i], VIDEO_BLACKGENERATOR, value);
462 bfcVideoPlaybackStop(
m_pSDK[i], 1, 1);
494 int tile_width, tile_height;
496 pthread_mutex_lock(&m_lock);
497 while(!m_ReadyFrameQueue.empty() ||
499 pthread_cond_wait(&m_BossCv, &m_lock);
500 pthread_mutex_unlock(&m_lock);
528 if(m_CardType != CRD_BLUE_SUPER_NOVA) {
529 throw runtime_error(
"We need a SuperNova card for 4K mode! "
530 "Let us know if you need a different combination "
531 "(eg. 2x Bluefish card");
534 if(m_CardFirmware != ORAC_4SDIOUTPUT_FIRMWARE_PRODUCTID)
536 throw runtime_error(
"Wrong firmware; need 4 output channels (QuadOut)");
539 m_AttachedDevicesCount = 4;
541 m_AttachedDevicesCount = 1;
544 for(
int i = 0; i < m_AttachedDevicesCount; ++i) {
545 m_pSDK[i] = bfcFactory();
548 if(BLUE_FAIL(bfcAttach(m_pSDK[i], m_deviceId)))
550 throw runtime_error(
"Error on device attach");
554 VideoMode = m_InvalidVideoModeFlag;
567 if(VideoMode == m_InvalidVideoModeFlag) {
568 ostringstream msg_ss;
569 msg_ss <<
"Unable to find appropriate video format for " <<
570 tile_width <<
"x" << tile_height <<
572 " @" << fixed << setprecision(2) <<
desc.
fps;
573 throw runtime_error(msg_ss.str());
576 m_CurrentVideoMode = VideoMode;
578 ULONG UpdateFormat = UPD_FMT_FRAME;
582 MemoryFormat = MEM_FMT_2VUY;
585 MemoryFormat = MEM_FMT_V210;
588 MemoryFormat = MEM_FMT_RGBA;
594 throw logic_error(
"Unknown video format!!!");
597 ULONG VideoEngine = VIDEO_ENGINE_FRAMESTORE;
599 ULONG OutputChannels[4] = {
600 BLUE_VIDEO_OUTPUT_CHANNEL_A,
601 BLUE_VIDEO_OUTPUT_CHANNEL_B,
602 BLUE_VIDEO_OUTPUT_CHANNEL_C,
603 BLUE_VIDEO_OUTPUT_CHANNEL_D
605 ULONG Sources[4] = { EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA,
606 EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHB,
607 EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC,
608 EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHD
611 EPOCH_DEST_SDI_OUTPUT_B,
612 EPOCH_DEST_SDI_OUTPUT_C,
613 EPOCH_DEST_SDI_OUTPUT_D
616 for(
int i = 0; i < m_AttachedDevicesCount; ++i) {
618 UpdateFormat, MemoryFormat, VideoEngine);
621 BLUE_CONNECTOR_PROP_SINGLE_LINK);
626 val32 = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA,
627 EPOCH_DEST_AES_ANALOG_AUDIO_OUTPUT, BLUE_CONNECTOR_PROP_SINGLE_LINK);
628 bfcSetCardProperty32(m_pSDK[0], MR2_ROUTING, val32);
630 val32 = blue_emb_audio_group1_enable | blue_emb_audio_enable | blue_enable_hanc_timestamp_pkt;
631 bfcSetCardProperty32(m_pSDK[0], EMBEDDED_AUDIO_OUTPUT, val32);
635 for(
int i = 0; i < m_AttachedDevicesCount; ++i) {
637 bfcSetCardProperty32(m_pSDK[i], VIDEO_MODE, val32);
638 bfcQueryCardProperty32(m_pSDK[i], VIDEO_MODE, &val32);
639 if(val32 != VideoMode)
641 throw logic_error(
"Can't set video mode; FIFO running already?");
645 for(
int i = 0; i < m_AttachedDevicesCount; ++i) {
647 bfcSetCardProperty32(m_pSDK[i], VIDEO_IMAGE_WIDTH, val32);
649 bfcSetCardProperty32(m_pSDK[i], VIDEO_IMAGE_HEIGHT, val32);
651 bfcSetCardProperty32(m_pSDK[i], VIDEO_IMAGE_PITCH, val32);
654 BLUE_U32 Width, Height, BytesPerLine, BytesPerFrame, GoldenSize;
655 bfcGetVideoInfo(VideoMode, UpdateFormat, MemoryFormat, &Width, &Height, &BytesPerLine, &BytesPerFrame, &GoldenSize);
657 ULONG FrameSize = GoldenSize;
658 if(is4K && !isTiled4K) {
663 FrameSize = 5 * GoldenSize;
666 cout <<
"Video Golden: " << GoldenSize << endl;
667 cout <<
"Video Pixels per line: " << Width << endl;
668 cout <<
"Video lines: " << Height << endl;
669 cout <<
"Video Bytes per frame: " << BytesPerFrame << endl;
670 cout <<
"Video Bytes per line: " << BytesPerLine << endl;
674 m_FreeFrameQueue.push(new_buffer);
679 m_frame->tiles[i].data_len = BytesPerFrame;
682 if(!is4K || isTiled4K) {
683 m_GoldenSize = GoldenSize;
684 for(
int i = 0; i < m_AttachedDevicesCount; ++i) {
689 for(
int i = 0; i < m_AttachedDevicesCount; ++i) {
692 m_Offset[i] = y * m_GoldenSize + x *
697 for(
int i = 0; i < m_AttachedDevicesCount; ++i) {
698 bfcVideoPlaybackStart(m_pSDK[i], 0, 0);
704 pthread_mutex_lock(&
m_lock);
713 pthread_mutex_unlock(&
m_lock);
724 (
char *) m_pTmpFrame->pVideoBuffer[0]) {
725 throw invalid_argument(
"Invalid frame supplied!");
728 pthread_mutex_lock(&m_lock);
729 for(
int i = 0; i < m_TileCount; ++i) {
730 m_pTmpFrame->pVideoBuffer[i] = (
unsigned int *)(
void *) m_frame->tiles[i].data;
732 m_ReadyFrameQueue.push(m_pTmpFrame);
733 pthread_cond_signal(&m_WorkerCv);
734 pthread_mutex_unlock(&m_lock);
740static void InitOutputChannel(BLUEVELVETC_HANDLE pSDK, ULONG DefaultOutputChannel, ULONG UpdateFormat,
741 ULONG MemoryFormat, ULONG VideoEngine)
746 val32 = DefaultOutputChannel;
747 bfcSetCardProperty32(pSDK, DEFAULT_VIDEO_OUTPUT_CHANNEL, val32);
750 bfcVideoPlaybackStop(pSDK, 1, 1);
752 val32 = UpdateFormat;
753 bfcSetCardProperty32(pSDK, VIDEO_UPDATE_TYPE, val32);
755 val32 = MemoryFormat;
756 bfcSetCardProperty32(pSDK, VIDEO_MEMORY_FORMAT, val32);
760 bfcSetCardProperty32(pSDK, VIDEO_OUTPUT_ENGINE, val32);
762 val32 = ENUM_BLACKGENERATOR_OFF;
763 bfcSetCardProperty32(pSDK, VIDEO_BLACKGENERATOR, val32);
766static void RouteChannel(BLUEVELVETC_HANDLE pSDK, ULONG Source, ULONG Destination, ULONG LinkType)
770 val32 = EPOCH_SET_ROUTING(Source, Destination, LinkType);
771 bfcSetCardProperty32(pSDK, MR2_ROUTING, val32);
777#ifdef HAVE_BLUE_AUDIO
782 throw logic_error(
"Wrong audio attributes");
786 throw runtime_error(
"Audio: only 48 kHz audio supported");
789 throw runtime_error(
"Audio: more than 16 channels not supported");
793 throw runtime_error(
"Audio: more than 4 channels not supported");
796 throw runtime_error(
"Audio: only 16 or 24 bits per second supported");
799 pthread_spin_lock(&m_AudioSpinLock);
804 pthread_spin_unlock(&m_AudioSpinLock);
807void display_bluefish444_state::put_audio_frame(
const struct audio_frame *
frame)
noexcept
823 BLUEVELVETC_HANDLE pSDK = bfcFactory();
824 bfcEnumerate(pSDK, &iDevices);
827 cout <<
"bluefish444 (output) options:" << endl
828 <<
"\tbluefish444[:device=<device_id>]" << endl
829 <<
"\t\tID of the Bluefish device (if more present)" << endl
830 <<
"\t\t" << iDevices <<
" Bluefish devices found in this system" << endl;
832 cout <<
" (default)" << endl;
833 }
else if(iDevices > 1) {
834 cout <<
", valid indices [1," << iDevices <<
"]" << endl;
835 cout <<
"default is 1" << endl;
843 BLUEVELVETC_HANDLE pSDK = bfcFactory();
844 bfcEnumerate(pSDK, &iDevices);
849 for (
int i = 0; i < iDevices; i++) {
850 snprintf((*available_cards)[i].
dev,
sizeof (*available_cards)[i].
dev,
":device=%d", iDevices);
851 snprintf((*available_cards)[i].
name,
sizeof (*available_cards)[i].
name,
"Bluefish444 card #%d", iDevices);
860 if(strcmp(
fmt,
"help") == 0) {
863 }
else if(strncasecmp(
fmt,
"device=", strlen(
"device=")) == 0) {
864 deviceId = atoi(
fmt + strlen(
"device="));
866 cerr <<
"[Blue444 disp] Unknown parameter: " <<
fmt << endl;
875 }
catch(runtime_error &e) {
876 cerr <<
"[Blue444 disp] " << e.what() << endl;
890 }
catch(runtime_error &e) {
891 cerr <<
"[Blue444 disp] " << e.what() << endl;
905 }
catch(runtime_error &e) {
906 cerr <<
"[Blue444 disp] " << e.what() << endl;
919 }
catch(runtime_error &e) {
920 cerr <<
"[Blue444 disp] " << e.what() << endl;
940 int rgb_shift[] = {0, 8, 16};
953 if(
sizeof(rgb_shift) > *
len) {
956 memcpy(
val, rgb_shift,
sizeof(rgb_shift));
957 *
len =
sizeof(rgb_shift);
964 if(
sizeof(supported_il_modes) <= *
len) {
965 memcpy(
val, supported_il_modes,
sizeof(supported_il_modes));
969 *
len =
sizeof(supported_il_modes);
978 desc->sample_rate = 48000;
993#ifdef HAVE_BLUE_AUDIO
998 }
catch(runtime_error &e) {
999 cerr <<
"[Blue444 disp] " << e.what() << endl;
1011#ifdef HAVE_BLUE_AUDIO
1016 s->put_audio_frame(
frame);
1017 }
catch(runtime_error &e) {
1018 cerr <<
"[Blue444 disp] " << e.what() << endl;
struct video_frame long long nonblock
struct video_frame * frame
const char unsigned int flags
int void(** deleter)(void *))
void vf_free(struct video_frame *buf)
Frees video_frame structure.
int vc_get_linesize(unsigned int width, codec_t codec)
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 uint32_t GetNumberOfAudioSamplesPerFrame(uint32_t VideoMode, uint32_t FrameNumber) __attribute__((unused))
static const struct bluefish_frame_mode_t bluefish_frame_modes[]
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_INFO
normal reporting
#define PITCH_DEFAULT
default pitch, i. e. respective linesize
#define VIDEO_DISPLAY_ABI_VERSION
#define DISPLAY_NO_GENERIC_FPS_INDICATOR
@ DISPLAY_PROPERTY_BUF_PITCH
requested framebuffer pitch - int (bytes), may be PITCH_DEFAULT
@ DISPLAY_PROPERTY_RGB_SHIFT
red,green,blue shift - int[3] (bits)
@ DISPLAY_PROPERTY_SUPPORTED_IL_MODES
display supported interlacing modes - enum interlacing_t[]
@ DISPLAY_PROPERTY_VIDEO_MODE
requested video mode - int (one of display_prop_vid_mode)
@ DISPLAY_PROPERTY_CODECS
list of natively supported codecs - codec_t[]
@ DISPLAY_PROPERTY_AUDIO_FORMAT
@ DISPLAY_PROPERTY_VIDEO_SEPARATE_TILES
framebuffer consists of separate tiles
@ LIBRARY_CLASS_VIDEO_DISPLAY
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
void ring_buffer_destroy(struct ring_buffer *ring)
struct ring_buffer * ring_buffer_init(int size)
void ring_buffer_flush(struct ring_buffer *buf)
int ring_buffer_read(struct ring_buffer *ring, char *out, int max_len)
void ring_buffer_write(struct ring_buffer *ring, const char *in, int len)
struct used to comunicate with audio capture/playback device
av_buffer(int TilesCount, int GoldenSize)
vector< unsigned int * > pVideoBuffer
enum interlacing_t interlacing
queue< struct av_buffer * > m_FreeFrameQueue
struct video_frame * getf() noexcept
ULONG m_InvalidVideoModeFlag
unsigned long int m_LastFieldCount
display_bluefish444_state(unsigned int flags, int deviceId=1) noexcept(false)
queue< struct av_buffer * > m_ReadyFrameQueue
int m_AttachedDevicesCount
int m_Offset[MAX_BLUE_OUT_CHANNELS]
static void * playback_thread(void *arg) noexcept
struct video_frame * m_frame
BLUEVELVETC_HANDLE m_pSDK[MAX_BLUE_OUT_CHANNELS]
pthread_cond_t m_WorkerCv
void reconfigure(struct video_desc) noexcept(false)
void putf(struct video_frame *) noexcept(false)
struct av_buffer * m_pPlayingBuffer
virtual ~display_bluefish444_state() noexcept
void * playback_loop() noexcept
char * data
Raw tile data. Pointer must be at least 4B aligned.
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.
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
double tv_diff(struct timeval curr_time, struct timeval prev_time)
@ PROGRESSIVE
progressive frame
@ SEGMENTED_FRAME
Segmented frame. Contains the same data as progressive frame.
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
@ RGBA
RGBA 8-bit, big-endian.
@ v210
YCbCr 422 10-bit - xVY0U|xY2UY1|xUY3V|xY5VY4, little-endian (2 bit padding /'x'/),...
This is an umbrella header for video functions.
static bool display_bluefish444_reconfigure(void *state, struct video_desc desc)
static void display_bluefish444_done(void *state)
#define BLUEFISH444_MAGIC
static const struct video_display_info display_bluefish444_info
static bool display_bluefish444_reconfigure_audio(void *state, int quant_samples, int channels, int sample_rate)
static void RouteChannel(BLUEVELVETC_HANDLE pSDK, ULONG Source, ULONG Destination, ULONG LinkType)
static bool display_bluefish444_get_property(void *state, int property, void *val, size_t *len)
static void * display_bluefish444_init(struct module *parent, const char *fmt, unsigned int flags)
static void InitOutputChannel(BLUEVELVETC_HANDLE pSDK, ULONG DefaultOutputChannel, ULONG UpdateFormat, ULONG MemoryFormat, ULONG VideoEngine)
static struct video_frame * display_bluefish444_getf(void *state)
static bool display_bluefish444_putf(void *state, struct video_frame *frame, long long nonblock)
static void display_bluefish444_put_audio_frame(void *state, const struct audio_frame *frame)
static void display_bluefish444_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
#define MAX_BLUE_OUT_CHANNELS
static void show_help(void)
const char * get_interlacing_suffix(enum interlacing_t interlacing)
Returns suffix describing interlacing Eg. p, i or psf.