]> git.sesse.net Git - mlt/blobdiff - src/modules/linsys/sdi_generator.c
Add qglsl multi consumer (opengl branch).
[mlt] / src / modules / linsys / sdi_generator.c
index 72e757d121f2b3b90ff0c00a89c731c050cf7b2c..928be548719e6f192124dd01aebbd6c30c082c23 100644 (file)
@@ -1,7 +1,14 @@
-/*
+/**
+ *
+ * MLT SDI Consumer:
+ * request video and audio data from MLT and generate an SDI stream
+ *
+ * Copyright (C) Broadcasting Center Europe S.A. http://www.bce.lu
+ * an RTL Group Company  http://www.rtlgroup.com
+ * All rights reserved.
+ *
+ * E-mail: support_plasec@bce.lu
  *
- * MLT SDI Consumer: request video and audio data from MLT and generate an SDI stream
- * Copyright (C) 2008 Broadcasting Center Europe S.A. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  *
  *
- *
  * DESCRIPTION:
  * This software act as interface between the MLT Frameworkas as
- * MLT Consumer and the Linear Systems Ltd. SMPTE 259M-C boards.
+ * MLT Consumer and the Linear Systems Ltd. SMPTE 292M and SMPTE 259M-C boards.
  *
  * Linear Systems can be contacted at http://www.linsys.ca
  *
- * ---------------------------------------------------------------
+ **********************************************************************************
  *      System : INTeL I686 64Bit
- *          OS : Linux SuSE Kernel 2.6.27.23-0.1-default
- *     Compiler: gcc  (c++)
- * ---------------------------------------------------------------
- *     Project : MLT SDI Consumer for SD
+ *          OS : Linux SuSE Kernel 2.6.27.39-0.2-default
+ *     Compiler: gcc 4.3.2 (c++)
+ **********************************************************************************
+ *     Project : MLT SDI Consumer for SD and HD
  *  Started by : Thomas Kurpick, Dipl.Inf. (FH)
- * ---------------------------------------------------------------
- * This program writes an SDI stream to the SDI driver provided
- * device files. E.g. SDI device file:
- *   /dev/sditx0         (SD)
- *   /dev/sditx1         (SD)
- *   /dev/sditx2         (SD)
- *   /dev/sditx4         (SD)
- *
- * Tested with:
- *      SDI Master™ PCI
- *     SDI Master™ PCIe
- *      SDI Master™ FD PCIe LP
- *      SDI Master™ Quad/o PCIe LP
+ **********************************************************************************
+ *  Supported and tested boards for SD-SDI or HD-SDI Output:
+ *      PCI SDI Master™              (model 107)
+ *     PCIe SDI Master™             (model 159)
+ *      PCIe LP SDI Master™ FD       (model 145)
+ *      PCIe LP SDI Master™ Quad/o   (model 180)
+ *      PCIe LP HD-SDI Master™ O     (model 193)
  *
- */
+ *  Note: PCIe LP HD-SDI Master™ O (model 193) is an VidPort model and supports an
+ *  seperate video and audio interface. Device file:
+ *             /dev/sdivideotx[]       for active video data
+ *     /dev/sdiaudiotx[]       for pcm audio data
+ *
+ *     This mlt consumer use the following device files:
+ *   /dev/sditx[]         (SD-PAL)     up to 8 x AES (8 x stereo / 16 audio channels)
+ *   /dev/sdivideotx[]    (HD)
+ *   /dev/sdiaudiotx[]    (HD)         up to 4 x AES (4 x stereo / 8 audio channels)
+ *
+ *
+ **********************************************************************************
+ * Last modified by:
+ * Thomas Kurpick                     08.Jan.2010
+ * Ver. 2.0
+ *
+ **********************************************************************************
+ *
+ * Consumer properties:
+ *     'dev_video'
+ *     'dev_audio'
+ *     'blanking'
+ * Only to monitor the SDI output a beta version of jpeg-writer is implemented.
+ *     'jpeg_files' a number for output interval
+ *     'save_jpegs' path for image
+ *
+ * EXAMPLE:
+ *
+ * SDI boards with full frame stream (with blanking):
+ *     melt video.dv -consumer sdi:/dev/sditx0 buffer=0;
+ *     melt video.dv -consumer sdi:/dev/sditx0 buffer=0 blanking=true;
+ *     melt video.dv -consumer sdi dev_video=/dev/sditx0 buffer=0 blanking=true;
+ *     melt video.dv audio_index=all -consumer sdi dev_video=/dev/sditx0 buffer=0 blanking=true;
+ *
+ * SDI boards without full frame stream (without blanking):
+ *  melt -profile atsc_1080i_50 video.mpeg audio_index=1   -consumer sdi dev_video=/dev/sdivideotx0 dev_sdiaudio=/dev/sdiaudiotx0 blanking=false
+ *  melt -profile atsc_1080i_50 video.mpeg audio_index=all -consumer sdi dev_video=/dev/sdivideotx0 dev_sdiaudio=/dev/sdiaudiotx0 blanking=false
+ *  melt -profile atsc_1080i_50 video.mpeg audio_index=all -consumer sdi dev_video=/dev/sdivideotx0 dev_sdiaudio=/dev/sdiaudiotx0 blanking=false jpeg_files=25 save_jpegs=channel_04.jpg
+ *
+ *
+ * SDI output formats and MLT profiles:
+ * #####################################################################################################################################################
+ * ########## SMPTE 274M 1920 x 1080 Image Sample Structure ############################################################################################
+ * #####################################################################################################################################################
+ * System No.  System nomenclature             Form of scanning        Frame rate                              Embedded Audio                  MLT profile             Linsys board support (model)
+ *     4                       1920 x 1080/60/I                interlaced                      30 HZ                                   4 x AES (8 channels)    atsc_1080i_60   193
+ *     5                       1920 x 1080/59.94/I             interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    atsc_1080i_5994 193
+ *     6                       1920 x 1080/50/I                interlaced                      25 HZ                                   4 x AES (8 channels)    atsc_1080i_50   193
+ *     7                       1920 x 1080/30/P                progressive                     30 HZ                                   4 x AES (8 channels)    atsc_1080p_30   193
+ *     8                       1920 x 1080/29.97/P             progressive                     30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    atsc_1080p_2997 193
+ *     9                       1920 x 1080/25/P                progressive                     25 HZ                                   4 x AES (8 channels)    atsc_1080p_25   193
+ *     10                      1920 x 1080/24/P                progressive                     24 HZ                                   4 x AES (8 channels)    atsc_1080p_24   193
+ *     11                      1920 x 1080/23.98/P             progressive                     24000/1001 ~ 23.98 HZ   4 x AES (8 channels)    atsc_1080p_2398 193
+ *
+ * #####################################################################################################################################################
+ * ########## SMPTE 296M 1280 × 720 Progressive Image Sample Structure #################################################################################
+ * #####################################################################################################################################################
+ * System No.  System nomenclature             Form of scanning        Frame rate                              Embedded Audio                  MLT profile             Linsys board support (model)
+ * 1                           1280 × 720/60          progressive                     60 HZ                                   4 x AES (8 channels)    atsc_720p_60    193
+ * 2                           1280 × 720/59.94       progressive                     60000/1001 ~ 59.97 HZ   4 x AES (8 channels)    atsc_720p_5994  193
+ * 3                           1280 × 720/50          progressive                     50 HZ                                   4 x AES (8 channels)    atsc_720p_50    193
+ * 4                           1280 × 720/30          progressive                     30 HZ                                   4 x AES (8 channels)    atsc_720p_30    193
+ * 5                           1280 × 720/29.97       progressive                     30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    atsc_720p_2997  193
+ * 6                           1280 × 720/25          progressive                     25 HZ                                   4 x AES (8 channels)    atsc_720p_25    193
+ * 7                           1280 × 720/24          progressive                     24 HZ                                   4 x AES (8 channels)    atsc_720p_24    193
+ * 8                           1280 × 720/23.98       progressive                     24000/1001 ~ 23.98 HZ   4 x AES (8 channels)    atsc_720p_2398  193
+ *
+ * #####################################################################################################################################################
+ * ########## SMPTE 125M 486i 29.97Hz & BT.656 576i 25Hz ###############################################################################################
+ * #####################################################################################################################################################
+ * System No.  System nomenclature             Form of scanning        Frame rate                              Embedded Audio                  MLT profile             Linsys board support (model)
+ * SD PAL              720 × 576/50/I                 interlaced                      25 HZ                                   8 x AES (16 channels)   dv_pal                  180,145,159,107
+ * SD PAL              720 × 576/50/I                 interlaced                      25 HZ                                   4 x AES (8 channels)    dv_pal                  193
+ * SD NTSC             720 × 486/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   8 x AES (16 channels)   sdi_486i_5994   TODO:180,145,159,107
+ * SD NTSC             720 × 486/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    sdi_486i_5994   193
+ *
+ **/
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include <pthread.h>
-
-// defines
-#define TOTAL_SAMPLES 1728
-#define ANCILLARY_DATA_SAMPLES 280
-#define TOTAL_LINES 625
-#define FIELD_1 1
-#define FIELD_2 2
-#define VERT_BLANKING 0
-#define ACTIVE_VIDEO 1
-
-// Master SDI device
-#define SDI_IOC_MAGIC '='
-#define SDI_IOC_TXGETEVENTS    _IOR(SDI_IOC_MAGIC, 2, unsigned int)
-
-// Transmitter event flag bit locations
-#define SDI_EVENT_TX_BUFFER_ORDER      0
-#define SDI_EVENT_TX_BUFFER            (1 << SDI_EVENT_TX_BUFFER_ORDER)
-#define SDI_EVENT_TX_FIFO_ORDER                1
-#define SDI_EVENT_TX_FIFO              (1 << SDI_EVENT_TX_FIFO_ORDER)
-#define SDI_EVENT_TX_DATA_ORDER                2
-#define SDI_EVENT_TX_DATA              (1 << SDI_EVENT_TX_DATA_ORDER)
-
-// function prototypes
-static int sdimaster_init(char *outputpath, int format);
-static int sdimaster_close();
-static int sdimaster_playout(uint8_t **vBuffer, int16_t **aBuffer0, int16_t **aBuffer1, int16_t **aBuffer2, int16_t **aBuffer3, int16_t **aBuffer4,
-               int16_t **aBuffer5, int16_t **aBuffer6, int16_t **aBuffer7, int sizeofVideo, int sizeofAudio, int audio_streams, int my_DBN);
-static int sdimaster_playout_raw(uint8_t *vBuffer, int16_t *aBuffer0, int16_t *aBuffer1, int16_t *aBuffer2, int16_t *aBuffer3, int16_t *aBuffer4,
-               int16_t *aBuffer5, int16_t *aBuffer6, int16_t *aBuffer7, int sizeofVideo, int sizeofAudio, int audio_streams, int my_DBN);
-
-static int create_SDI_line(uint16_t *buf, int field, int active, uint8_t *video_buffer, int16_t *audio_buffer0, int16_t *audio_buffer1, int16_t *aBuffer2,
-               int16_t *aBuffer3, int16_t *aBuffer4, int16_t *aBuffer5, int16_t *aBuffer6, int16_t *aBuffer7, int linenumber_sdiframe, int linenumber_video,
-               int my_DBN, int16_t AudioGroupCounter, int16_t AudioGroups2Write, int audio_streams);
-static int writeANC(uint16_t *p, int linenumber_sdiframe, uint16_t DID, int my_DBN, int16_t *audio_buffer_A, int16_t *audio_buffer_B,
-               int16_t AudioDataPacketCounter, int16_t AudioGroups2Write, int audio_streams);
-static uint16_t checker(uint16_t *DID_pointer);
-
-static uint8_t getZBit(int sample_number);
-static uint8_t getChannelStatusBit(uint16_t sample_number, uint8_t ch);
-static int16_t getNumberOfAudioGroups2Write(int linenuber);
-
-static uint8_t getDBN(int my_DBN);
-
-static uint8_t *pack10(uint8_t *outbuf, uint16_t *inbuf, size_t count);
-
-static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int16_t *audio_sample);
-
-// Filehandler for sdi output
-static int fh_sdi_dest;
-
-struct SDI_atr {
-       int status;
-       int *fh;
-       uint8_t *data;
-       size_t framesize;
-} SDI_atr;
-
-// 192bit for AESChannelStatusBits
-uint8_t AESChannelStatusBitArray[192]; // beta array
-//uint8_t AESChannelStatusBitArray[24]; // TODO better way for 24x8bit !!!
-
-
-/*!/brief Initialization of the file handlers for the Playout
- * @param *outputpath: file or SDITX device
- * @param format:  0:PAL, 1:NTSC (unused, PAL is always used)
+#include "sdi_generator.h"
+
+/*!/brief initialization of the file handlers for the playout
+ * @param *device_video: file or SDITX device or SDIVIDEOTX device
+ * @param *device_audio: file or SDIAUDIOTX device
+ * @param blanking: true or false (if false the consumer write only active video data without any VANH or HANC)
  */
-static int sdimaster_init(char *outputpath, int format) {
+static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, mlt_profile myProfile,
+               const struct audio_format * audio_format) {
+
+       // set device file
+       device_file_video = device_video;
+       device_file_audio = device_audio;
+
+       // set flag for using of blanking with ancillary data
+       info.blanking = blanking;
+
+       // set pack method for SDI word conversion
+       pack = pack8;
+       //pack = pack10;
+       //pack = pack_v210;
+
+       // check format
+       if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 0) {
+               info.fmt = &FMT_1080i60;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_60HZ;
+       } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+                       == 1001 && myProfile->progressive == 0) {
+               info.fmt = &FMT_1080i5994;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_59_94HZ;
+       } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 0) {
+               info.fmt = &FMT_1080i50;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_50HZ;
+       } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 1) {
+               info.fmt = &FMT_1080p30;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_30HZ;
+       } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+                       == 1001 && myProfile->progressive == 1) {
+               info.fmt = &FMT_1080p2997;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_29_97HZ;
+       } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 1) {
+               info.fmt = &FMT_1080p25;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_25HZ;
+       } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 1) {
+               info.fmt = &FMT_1080p24;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_24HZ;
+       } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den
+                       == 1001 && myProfile->progressive == 1) {
+               info.fmt = &FMT_1080p2398;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_23_98HZ;
+       } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 1) {
+               info.fmt = &FMT_720p60;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_60HZ;
+       } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60000 && myProfile->frame_rate_den
+                       == 1001 && myProfile->progressive == 1) {
+               info.fmt = &FMT_720p5994;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_59_94HZ;
+       } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 50 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 1) {
+               info.fmt = &FMT_720p50;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_50HZ;
+       } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 1) {
+               info.fmt = &FMT_720p30;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_30HZ;
+       } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+                       == 1001 && myProfile->progressive == 1) {
+               info.fmt = &FMT_720p2997;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_29_97HZ;
+       } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 1) {
+               info.fmt = &FMT_720p25;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_25HZ;
+       } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 1) {
+               info.fmt = &FMT_720p24;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_24HZ;
+       } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den
+                       == 1001 && myProfile->progressive == 1) {
+               info.fmt = &FMT_720p2398;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_23_98HZ;
+       } else if (myProfile->width == 720 && myProfile->height == 576 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
+                       && myProfile->progressive == 0) {
+               info.fmt = &FMT_576i50;
+               sdi_frame_mode = SDIVIDEO_CTL_BT_601_576I_50HZ;
+       } else if (myProfile->width == 720 && myProfile->height == 486 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+                       == 1001 && myProfile->progressive == 0) {
+               info.fmt = &FMT_486i5994;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_125M_486I_59_94HZ;
+       } else if (myProfile->width == 720 && myProfile->height == 480 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+                       == 1001 && myProfile->progressive == 0) {
+               info.fmt = &FMT_480i5994;
+               sdi_frame_mode = SDIVIDEO_CTL_SMPTE_125M_486I_59_94HZ;
+       } else {
+               printf("Consumer got unknown format: %s", myProfile->description);
+               info.fmt = &FMT_576i50;
+               sdi_frame_mode = SDIVIDEO_CTL_BT_601_576I_50HZ;
+       }
 
-       // check video format (currently only PAL is available)
-       if (format != 0) {
-               printf("sdimaster_init get format '%i' ", format);
+       printf("Consumer use format: %s\nProfile: %i %i %i %i %i\n", myProfile->description, myProfile->width, myProfile->height,
+                       myProfile->frame_rate_num, myProfile->frame_rate_den, myProfile->progressive);
+
+       // Check if the format supports own blanking (note: model 193 supports currently only active video at the video device file)
+       if (info.blanking && info.fmt != &FMT_576i50) {
+               printf("SDI consumer doesn't support blanking(HANC) for the configured SD board and SDI format. Try argument: blanking=false\n");
                return EXIT_FAILURE;
        }
 
-       // open destination for SDI output
-       if ((fh_sdi_dest = open(outputpath, O_WRONLY | O_CREAT, 0777)) == -1) {
-               perror(NULL);
-               printf("\ncould not open video output destination!\n");
-               return EXIT_FAILURE;
+       // if we write our own HANC we need an AES channel status bit array
+       if (info.blanking) {
+
+               // small description
+               // http://www.sencore.com/newsletter/Nov05/DigAudioChannelStatusBits.htm
+               // or
+               // http://www.sencore.com/uploads/files/DigAudioChannelStatusBits.pdf
+
+               // create empty AESChannelStatusBitArray
+               int i = 0;
+               for (i = 0; i < sizeof(AESChannelStatusBitArray) / sizeof(AESChannelStatusBitArray[0]); i++)
+                       AESChannelStatusBitArray[i] = 0;
+
+               /**
+                * Professional Format - Channel Status Bits
+                **/
+               ////// Byte 0 //////
+               AESChannelStatusBitArray[0] = 1; // professional format
+
+               AESChannelStatusBitArray[1] = 0; // PCM Format
+
+               AESChannelStatusBitArray[2] = 1; // Emphasis: [100] No Emphasis
+               AESChannelStatusBitArray[3] = 0; // ^
+               AESChannelStatusBitArray[4] = 0; // ^
+
+               AESChannelStatusBitArray[5] = 0; // locked
+
+               AESChannelStatusBitArray[6] = 0; // sample frequency Fs: [01]48kHz, [10]44kHz, [11]32kHz
+               AESChannelStatusBitArray[7] = 1; // ^
+               ////// Byte 1 //////
+               AESChannelStatusBitArray[8] = 0; // channel mode: [0000] not indicated, [0001]2channels, [0010]1channel mono, ...
+               AESChannelStatusBitArray[9] = 0; // ^
+               AESChannelStatusBitArray[10] = 0; // ^
+               AESChannelStatusBitArray[11] = 1; // ^
+               ////// Byte 2 //////
+               AESChannelStatusBitArray[19] = 0; // Encoded sample word length [100]20bits,
+               AESChannelStatusBitArray[20] = 0; //
+               AESChannelStatusBitArray[21] = 0; //
+               ////// Byte 3 //////
+               AESChannelStatusBitArray[24] = 0; //
+               AESChannelStatusBitArray[25] = 0; //
+               AESChannelStatusBitArray[26] = 0; //
+               AESChannelStatusBitArray[27] = 0; //
+               AESChannelStatusBitArray[28] = 0; //
+               AESChannelStatusBitArray[29] = 0; //
+               AESChannelStatusBitArray[30] = 0; //
+               AESChannelStatusBitArray[31] = 0; // Multi Channel Mode
+               ////// Byte 4-21 //////
+               //AESChannelStatusBitArray[32-179]= 0;
+               ////// Byte 22 //////
+               AESChannelStatusBitArray[180] = 0; // Reliability Flags
+               AESChannelStatusBitArray[181] = 1; // ^
+               AESChannelStatusBitArray[182] = 1; // ^
+               AESChannelStatusBitArray[183] = 1; // ^
+               ////// Byte 23 //////
+               AESChannelStatusBitArray[184] = 0; // Cyclic Redundancy Check
+               AESChannelStatusBitArray[185] = 1; // ^
+               AESChannelStatusBitArray[186] = 0; // ^
+               AESChannelStatusBitArray[187] = 0; // ^
+               AESChannelStatusBitArray[188] = 1; // ^
+               AESChannelStatusBitArray[189] = 0; // ^
+               AESChannelStatusBitArray[190] = 1; // ^
+               AESChannelStatusBitArray[191] = 1; // ^
+       }
+
+       // set buffer for one line of active video samples
+       line_buffer = (uint16_t*) calloc(info.fmt->samples_per_line, sizeof(uint16_t));
+
+       // calculate and set buffer for the complete SDI frame
+       if (info.fmt != &FMT_576i50 && info.fmt != &FMT_486i5994) {
+               if (info.blanking) {
+                       if (pack == pack_v210) {
+                               samples = (info.fmt->samples_per_line / 96 * 48) + ((info.fmt->samples_per_line % 96) ? 48 : 0);
+                               sdi_frame_size = samples * info.fmt->lines_per_frame * 8 / 3;
+                       } else {
+                               sdi_frame_size = info.fmt->samples_per_line * info.fmt->lines_per_frame;
+                       }
+               } else {
+                       if (pack == pack_v210) {
+                               samples = (info.fmt->active_samples_per_line / 96 * 48) + ((info.fmt->active_samples_per_line % 96) ? 48 : 0);
+                               sdi_frame_size = samples * info.fmt->active_lines_per_frame * 8 / 3;
+                       } else {
+                               sdi_frame_size = info.fmt->active_samples_per_line * info.fmt->active_lines_per_frame;
+                       }
+               }
+       } else {
+               if (info.blanking) {
+                       if (pack == pack_v210) {
+                               sdi_frame_size = info.fmt->samples_per_line * 4 / 3 * info.fmt->lines_per_frame;
+                       } else if (pack == pack8) {
+                               sdi_frame_size = info.fmt->samples_per_line * info.fmt->lines_per_frame;
+                       } else {
+                               sdi_frame_size = info.fmt->samples_per_line * 10 / 8 * info.fmt->lines_per_frame;
+                       }
+               } else {
+                       if (pack == pack_v210) {
+                               sdi_frame_size = info.fmt->active_samples_per_line * 4 / 3 * info.fmt->active_lines_per_frame;
+                       } else if (pack == pack8) {
+                               sdi_frame_size = info.fmt->active_samples_per_line * info.fmt->active_lines_per_frame;
+                       } else {
+                               sdi_frame_size = info.fmt->active_samples_per_line * 10 / 8 * info.fmt->active_lines_per_frame;
+                       }
+               }
        }
 
-       // small description
-       // http://www.sencore.com/newsletter/Nov05/DigAudioChannelStatusBits.htm
-       // or
-       // http://www.sencore.com/uploads/files/DigAudioChannelStatusBits.pdf
+       // (*10/8 because we store (TOTAL_SAMPLES*TOTAL_LINES) words with 10 bit in this 8 bit array) )
+       if (info.fmt == &FMT_576i50 && info.blanking) {
+               sdi_frame_size = info.fmt->samples_per_line * 10 / 8 * info.fmt->lines_per_frame;
+       }
 
-       // create empty AESChannelStatusBitArray
-       int i = 0;
-       for (i = 0; i < sizeof(AESChannelStatusBitArray) / sizeof(AESChannelStatusBitArray[0]); i++)
-               AESChannelStatusBitArray[i] = 0;
+       if (info.blanking) {
+               printf("SDI frame size: %"PRIu64"\n", sdi_frame_size);
+       } else {
+               printf("Frame size for active video: %"PRIu64"\n", sdi_frame_size);
+       }
 
        /**
-        * Professionel Format - Channel Status Bits
+        * Setup HD-SDI Master device (vidport):
+        *
+        * if device_file_video available then
+        *      if vidport available
+        *              1. setup
+        *      end
+        *      1. open device file handler
+        *
+        *      if device_file_audio available then
+        *              1. setup
+        *              2. open device file handler
+        *      end
+        * end
         **/
-       ////// Byte 0 //////
-       AESChannelStatusBitArray[0] = 1; // professional format
-
-       AESChannelStatusBitArray[1] = 0; // PCM Format
-
-       AESChannelStatusBitArray[2] = 1; // Emphasis: [100] No Emphasis
-       AESChannelStatusBitArray[3] = 0; // ^
-       AESChannelStatusBitArray[4] = 0; // ^
-
-       AESChannelStatusBitArray[5] = 0; // locked
-
-       AESChannelStatusBitArray[6] = 0; // sample frequncy Fs: [01]48kHz, [10]44kHz, [11]32kHz
-       AESChannelStatusBitArray[7] = 1; // ^
-       ////// Byte 1 //////
-       AESChannelStatusBitArray[8] = 0; // channel mode: [0000] not indicated, [0001]2channels, [0010]1channel mono, ...
-       AESChannelStatusBitArray[9] = 0; // ^
-       AESChannelStatusBitArray[10] = 0; // ^
-       AESChannelStatusBitArray[11] = 1; // ^
-       ////// Byte 2 //////
-       AESChannelStatusBitArray[19] = 0; // Encoded sample word length [100]20bits,
-       AESChannelStatusBitArray[20] = 0; //
-       AESChannelStatusBitArray[21] = 0; //
-       ////// Byte 3 //////
-       AESChannelStatusBitArray[24] = 0; //
-       AESChannelStatusBitArray[25] = 0; //
-       AESChannelStatusBitArray[26] = 0; //
-       AESChannelStatusBitArray[27] = 0; //
-       AESChannelStatusBitArray[28] = 0; //
-       AESChannelStatusBitArray[29] = 0; //
-       AESChannelStatusBitArray[30] = 0; //
-       AESChannelStatusBitArray[31] = 0; // Multi Channel Mode
-       ////// Byte 4-21 //////
-       //AESChannelStatusBitArray[32-179]= 0;
-       ////// Byte 22 //////
-       AESChannelStatusBitArray[180] = 0; // Reliability Flags
-       AESChannelStatusBitArray[181] = 1; // ^
-       AESChannelStatusBitArray[182] = 1; // ^
-       AESChannelStatusBitArray[183] = 1; // ^
-       ////// Byte 23 //////
-       AESChannelStatusBitArray[184] = 0; // Cyclic Redundancy Check
-       AESChannelStatusBitArray[185] = 1; // ^
-       AESChannelStatusBitArray[186] = 0; // ^
-       AESChannelStatusBitArray[187] = 0; // ^
-       AESChannelStatusBitArray[188] = 1; // ^
-       AESChannelStatusBitArray[189] = 0; // ^
-       AESChannelStatusBitArray[190] = 1; // ^
-       AESChannelStatusBitArray[191] = 1; // ^
+       if (device_file_video != NULL) {
+
+               // If we use a Linsys HD board with active video (without blanking) setup the board for the used mode
+               if (strstr(device_file_video, "sdivideotx") != NULL && !info.blanking) {
+
+                       char * value;
+
+                       // Buffer size
+                       value = itoa(sdi_frame_size);
+                       setSDIVideoProperties(SETTING_BUFFER_SIZE_VIDEO, value, device_video);
+                       free(value);
+
+                       // Frame Mode
+                       value = itoa(sdi_frame_mode);
+                       setSDIVideoProperties(SETTING_FRAME_MODE, value, device_video);
+                       free(value);
+
+                       // Data Mode
+                       if (pack == pack8)
+                               setSDIVideoProperties(SETTING_DATA_MODE, "0", device_video);
+                       else if (pack == pack_v210)
+                               setSDIVideoProperties(SETTING_DATA_MODE, "1", device_video);
+               }
+
+               // open file handle for SDI(video) output
+               if ((fh_sdi_video = open(device_file_video, O_WRONLY)) == -1) {
+                       perror(NULL);
+                       printf("\ncould not open video output destination: %s\n", device_file_video);
+                       return EXIT_FAILURE;
+               }
+               printf("SDI consumer uses video device file: %s\n", device_file_video);
+
+               // Check if we have to use a separate device file for audio
+               if (device_file_audio != NULL) {
+
+                       // set settings for audio device file
+                       if (strstr(device_file_audio, "sdiaudiotx") != NULL && !info.blanking) {
+
+                               char * value;
+
+                               /**
+                                * prepare sample size
+                                * MLT suports: 16bit, 32bit
+                                * LINSYS SDI boards supports: 16bit, 24bit, 32bit
+                                * we set 16bit as default
+                                **/
+                               uint8_t sample_size = audio_format->aformat == mlt_audio_s32 ? 32 : 16;
+
+                               // Buffer size
+                               // audio buffer per frame (Bytes) = sample rate / frame rate * ( sample size / 1Byte ) x channels
+                               value = itoa(
+                                               (uint64_t) audio_format->sample_rate / ( (uint64_t) myProfile->frame_rate_num / (uint64_t) myProfile->frame_rate_den) * (uint64_t) sample_size / 8
+                                                               * (uint64_t) audio_format->channels);
+                               setSDIAudioProperties(SETTING_BUFFER_SIZE_AUDIO, value, device_audio);
+                               free(value);
+
+                               // channels
+                               value = itoa(audio_format->channels);
+                               setSDIAudioProperties(SETTING_CHANNELS, value, device_audio);
+                               free(value);
+
+                               // sample rate
+                               value = itoa(audio_format->sample_rate);
+                               setSDIAudioProperties(SETTING_SAMPEL_RATE, value, device_audio);
+                               free(value);
+
+                               // sample size
+                               value = itoa(sample_size);
+                               setSDIAudioProperties(SETTING_SAMPLE_SIZE, value, device_audio);
+                               free(value);
+                       }
+
+                       // open file handle for audio output
+                       if ((fh_sdi_audio = open(device_file_audio, O_WRONLY)) == -1) {
+                               perror(NULL);
+                               printf("\nCould not open audio output destination: %s\n", device_file_audio);
+                               return EXIT_FAILURE;
+                       }
+                       printf("SDI consumer uses audio device file: %s\n", device_file_audio);
+               }
+
+       }
+
+       // set buffer for the complete SDI frame
+       data = (uint8_t*) calloc(sdi_frame_size, sizeof(uint8_t));
 
        return 1;
 }
 
-//****************************************************************************************
-//*****************************  PLAYOUT  ************************************************
-//****************************************************************************************
-
-/** Writes video and audio to specified files in SDI format
- * @param **vBuffer: Pointer to a video Buffer
- * @param **aBuffer0: Pointer to an audio Buffer (2 mono channels)
- * @param **aBuffer1: Pointer to an audio Buffer (2 mono channels)
- * @param **aBuffer2: Pointer to an audio Buffer (2 mono channels)
- * @param **aBuffer3: Pointer to an audio Buffer (2 mono channels)
- * @param **aBuffer4: Pointer to an audio Buffer (2 mono channels)
- * @param **aBuffer5: Pointer to an audio Buffer (2 mono channels)
- * @param **aBuffer6: Pointer to an audio Buffer (2 mono channels)
- * @param **aBuffer7: Pointer to an audio Buffer (2 mono channels)
- * @param sizeofVideo: size of the video Buffer
- * @param sizeofAudio: size of every audio Buffer
+/**
+ * Writes video and audio to specified files in SDI format
+ * @param *vBuffer: Pointer to a video Buffer
+ * @param aBuffer[][]
+ * @param *audio_format: mlt audio_format
  * @param audio_streams: number of audio streams which have content in aBuffer (available 0-8)
- *
  * @return current DBN (data block number of SDI frame)
- *
- */
-static int sdimaster_playout(uint8_t **vBuffer, int16_t **aBuffer0, int16_t **aBuffer1, int16_t **aBuffer2, int16_t **aBuffer3, int16_t **aBuffer4,
-               int16_t **aBuffer5, int16_t **aBuffer6, int16_t **aBuffer7, int sizeofVideo, int sizeofAudio, int audio_streams, int my_DBN) {
-
-       // Buffer for one line of SDI
-       uint16_t buf[TOTAL_SAMPLES];
-
-       // Buffer for the complete SDI frame
-       //(*10/8 because we store (TOTAL_SAMPLES*TOTAL_LINES) words with 10 bit in this 8 bit array) )
-       uint8_t data[TOTAL_SAMPLES * 10 / 8 * TOTAL_LINES];
+ **/
+static int sdi_playout(uint8_t *vBuffer, int16_t aBuffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], const struct audio_format * audio_format,
+               int audio_streams, int my_DBN) {
 
        // Pointer to the start of data. This is used to fill data line by line
        uint8_t *p = data;
 
-       // Size of the SDI frame (also size of data)
-       size_t framesize = TOTAL_SAMPLES * 10 / 8 * TOTAL_LINES;
-
        //*******************************************************************************************
        //****************      Build the SDI frame line by line ****************************************
        //*******************************************************************************************
-       //counter for the lines
-       int i = 0;
-       int16_t AudioGroupCounter = 0;
-
-       /*#####################################################*/
-       /*########      FIELD 1                         #######################*/
-       /*#####################################################*/
-
-       // line 1-22    VERTICAL_BLANKING:23 lines                              SAV 0x2ac               EAV 0x2d8
-       for (i = 1; i <= 5; i++) {
-               create_SDI_line(buf, FIELD_1, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                               getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-               AudioGroupCounter += getNumberOfAudioGroups2Write(i);
-               p = pack10(p, buf, TOTAL_SAMPLES);
-       }
-       for (i = 6; i <= 8; i++) {
-               create_SDI_line(buf, FIELD_1, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                               getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-               AudioGroupCounter += getNumberOfAudioGroups2Write(i);
-               p = pack10(p, buf, TOTAL_SAMPLES);
-       }
-       for (i = 9; i <= 22; i++) {
-               create_SDI_line(buf, FIELD_1, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                               getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-               AudioGroupCounter += getNumberOfAudioGroups2Write(i);
-               p = pack10(p, buf, TOTAL_SAMPLES);
-       }
-       // line 23-310  ACTIVE: 287 lines                                               SAV 0x200               EAV 0x274
-       int f1counter = 1; // only odd lines
-       for (i = 23; i <= 310; i++) {
-               create_SDI_line(buf, FIELD_1, ACTIVE_VIDEO, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i,
-                               f1counter, getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-               AudioGroupCounter += getNumberOfAudioGroups2Write(i);
-               p = pack10(p, buf, TOTAL_SAMPLES);
-               f1counter += 2;
-       }
-       i = 311;
-       // line 311-312 VERTICAL_BLANKING: 2 lines                              SAV 0x2ac               EAV 0x2d8
-       create_SDI_line(buf, FIELD_1, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                       getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-       AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
-       p = pack10(p, buf, TOTAL_SAMPLES);
-       create_SDI_line(buf, FIELD_1, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                       getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-       AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
-       p = pack10(p, buf, TOTAL_SAMPLES);
-
-       /*#####################################################*/
-       /*########      FIELD 2        ########################*/
-       /*#####################################################*/
-
-       // line 313-336 VERTICAL_BLANKING: 23 lines                             SAV 0x3b0               EAV 0x3c4
-       create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                       getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-       AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
-       p = pack10(p, buf, TOTAL_SAMPLES);
-
-       create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                       getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-       AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
-       p = pack10(p, buf, TOTAL_SAMPLES);
-
-       create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                       getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-       AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
-       p = pack10(p, buf, TOTAL_SAMPLES);
-
-       create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                       getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-       AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
-       p = pack10(p, buf, TOTAL_SAMPLES);
-
-       create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                       getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-       AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
-       p = pack10(p, buf, TOTAL_SAMPLES);
-
-       create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                       getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-       AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
-       p = pack10(p, buf, TOTAL_SAMPLES);
-
-       // `getAudioGroups2Write()`=0
-       for (i = 319; i <= 321; i++) {
-               create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                               getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-               AudioGroupCounter += getNumberOfAudioGroups2Write(i);
-               p = pack10(p, buf, TOTAL_SAMPLES);
-       }
-       for (i = 322; i <= 335; i++) {
-               create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                               getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-               AudioGroupCounter += getNumberOfAudioGroups2Write(i);
-               p = pack10(p, buf, TOTAL_SAMPLES);
-       }
-       // line 336-623 ACTIVE: 288 lines                                               SAV 0x31c               EAV 0x368
-       int f2counter = 2; // only even Lines
-       for (i = 336; i <= 623; i++) {
-
-               create_SDI_line(buf, FIELD_2, ACTIVE_VIDEO, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i,
-                               f2counter, getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-               AudioGroupCounter += getNumberOfAudioGroups2Write(i);
-               p = pack10(p, buf, TOTAL_SAMPLES);
-               f2counter += 2;
-       }
-       // line 624-625 VERTICAL_BLANKING: 2 lines                              SAV 0x3b0               EAV 0x3c4
-       for (i = 624; i <= 625; i++) {
-               create_SDI_line(buf, FIELD_2, VERT_BLANKING, *vBuffer, *aBuffer0, *aBuffer1, *aBuffer2, *aBuffer3, *aBuffer4, *aBuffer5, *aBuffer6, *aBuffer7, i, 0,
-                               getDBN(my_DBN++), AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
-               AudioGroupCounter += getNumberOfAudioGroups2Write(i);
-               p = pack10(p, buf, TOTAL_SAMPLES);
+
+       /*
+        * if SDI FMT_576i50 for card ASSY 145 or ASSY 159, with access to whole SDI frame buffer
+        *   and device_file_audio must be NULL
+        *      than we write own audio data,
+        * else
+        *      than HD for card ASSY 193
+        */
+       //if (info.fmt == &FMT_576i50 && device_file_audio == NULL && !strcmp(device_file_video, "/dev/sdivideotx0")) {
+       if (info.fmt == &FMT_576i50 && info.blanking) {
+
+               //counter for the lines
+               int i = 0;
+               int16_t AudioGroupCounter = 0;
+
+               /*#####################################################*/
+               /*########      FIELD 1                         #######################*/
+               /*#####################################################*/
+
+               info.xyz = &FIELD_1_VERT_BLANKING;
+
+               // line 1-22    VERTICAL_BLANKING:23 lines                              SAV 0x2ac               EAV 0x2d8
+               for (i = 1; i <= 5; i++) {
+                       create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                                       getNumberOfAudioGroups2Write(i), audio_streams);
+                       AudioGroupCounter += getNumberOfAudioGroups2Write(i);
+                       p = pack10(p, line_buffer, info.fmt->samples_per_line);
+               }
+               for (i = 6; i <= 8; i++) {
+                       create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                                       getNumberOfAudioGroups2Write(i), audio_streams);
+                       AudioGroupCounter += getNumberOfAudioGroups2Write(i);
+                       p = pack10(p, line_buffer, info.fmt->samples_per_line);
+               }
+               for (i = 9; i <= 22; i++) {
+                       create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                                       getNumberOfAudioGroups2Write(i), audio_streams);
+                       AudioGroupCounter += getNumberOfAudioGroups2Write(i);
+                       p = pack10(p, line_buffer, info.fmt->samples_per_line);
+               }
+               // line 23-310  ACTIVE: 287 lines                                               SAV 0x200               EAV 0x274
+               info.xyz = &FIELD_1_ACTIVE;
+               int f1counter = 1; // only odd lines
+               for (i = 23; i <= 310; i++) {
+                       create_SD_SDI_Line(line_buffer, &info, FIELD_1, ACTIVE_VIDEO, vBuffer, aBuffer, i, f1counter, getDBN(my_DBN++),
+                                       AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
+                       AudioGroupCounter += getNumberOfAudioGroups2Write(i);
+                       p = pack10(p, line_buffer, info.fmt->samples_per_line);
+                       f1counter += 2;
+               }
+               i = 311;
+               // line 311-312 VERTICAL_BLANKING: 2 lines                              SAV 0x2ac               EAV 0x2d8
+               info.xyz = &FIELD_1_VERT_BLANKING;
+               create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                               getNumberOfAudioGroups2Write(i), audio_streams);
+               AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
+               p = pack10(p, line_buffer, info.fmt->samples_per_line);
+               create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                               getNumberOfAudioGroups2Write(i), audio_streams);
+               AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
+               p = pack10(p, line_buffer, info.fmt->samples_per_line);
+
+               /*#####################################################*/
+               /*########      FIELD 2        ########################*/
+               /*#####################################################*/
+
+               info.xyz = &FIELD_2_VERT_BLANKING;
+
+               // line 313-336 VERTICAL_BLANKING: 23 lines                             SAV 0x3b0               EAV 0x3c4
+               create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                               getNumberOfAudioGroups2Write(i), audio_streams);
+               AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
+               p = pack10(p, line_buffer, info.fmt->samples_per_line);
+
+               create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                               getNumberOfAudioGroups2Write(i), audio_streams);
+               AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
+               p = pack10(p, line_buffer, info.fmt->samples_per_line);
+
+               create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                               getNumberOfAudioGroups2Write(i), audio_streams);
+               AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
+               p = pack10(p, line_buffer, info.fmt->samples_per_line);
+
+               create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                               getNumberOfAudioGroups2Write(i), audio_streams);
+               AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
+               p = pack10(p, line_buffer, info.fmt->samples_per_line);
+
+               create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                               getNumberOfAudioGroups2Write(i), audio_streams);
+               AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
+               p = pack10(p, line_buffer, info.fmt->samples_per_line);
+
+               create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                               getNumberOfAudioGroups2Write(i), audio_streams);
+               AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
+               p = pack10(p, line_buffer, info.fmt->samples_per_line);
+
+               // `getAudioGroups2Write()`=0
+               for (i = 319; i <= 321; i++) {
+                       create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                                       getNumberOfAudioGroups2Write(i), audio_streams);
+                       AudioGroupCounter += getNumberOfAudioGroups2Write(i);
+                       p = pack10(p, line_buffer, info.fmt->samples_per_line);
+               }
+               for (i = 322; i <= 335; i++) {
+                       create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                                       getNumberOfAudioGroups2Write(i), audio_streams);
+                       AudioGroupCounter += getNumberOfAudioGroups2Write(i);
+                       p = pack10(p, line_buffer, info.fmt->samples_per_line);
+               }
+               // line 336-623 ACTIVE: 288 lines                                               SAV 0x31c               EAV 0x368
+               info.xyz = &FIELD_2_ACTIVE;
+               int f2counter = 2; // only even Lines
+               for (i = 336; i <= 623; i++) {
+
+                       create_SD_SDI_Line(line_buffer, &info, FIELD_2, ACTIVE_VIDEO, vBuffer, aBuffer, i, f2counter, getDBN(my_DBN++),
+                                       AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
+                       AudioGroupCounter += getNumberOfAudioGroups2Write(i);
+                       p = pack10(p, line_buffer, info.fmt->samples_per_line);
+                       f2counter += 2;
+               }
+               // line 624-625 VERTICAL_BLANKING: 2 lines                              SAV 0x3b0               EAV 0x3c4
+               info.xyz = &FIELD_2_VERT_BLANKING;
+               for (i = 624; i <= 625; i++) {
+                       create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
+                                       getNumberOfAudioGroups2Write(i), audio_streams);
+                       AudioGroupCounter += getNumberOfAudioGroups2Write(i);
+                       p = pack10(p, line_buffer, info.fmt->samples_per_line);
+               }
+
+       } else { // use HD board without blanking
+
+               // start with first even line
+               active_video_line = 1;
+
+               /* *****************************************
+                * *********** LINE DISTRIBUTION ***********
+                * *****************************************
+                *
+                * << decide form of scanning (interlaced || progressive) >>
+                * if (interlaced)
+                *              << decide lines per frame (1125 || 625 || 525) >>
+                *              if(1125)                                        1080x1920 HD
+                *                      than create lines
+                *              else if(625)                              576x720 PAL
+                *                      than create lines
+                *              else (525)                                        486x720 NTSC
+                *                      than create lines
+                * else (progressive)
+                *              << decide resolution (1125 || 750) >>
+                *              if(1125)                                        1080x1920 HD
+                *                      than create lines
+                *              else(750)                                        720x1280 HD
+                *                      than create lines
+                *
+                **/
+
+               // Generate a frame
+               if (info.fmt->interlaced) {
+
+                       /****************************************
+                        * INTERLACED
+                        ****************************************/
+
+                       if (info.fmt->lines_per_frame == 1125) {
+
+                               if (info.blanking) {
+                                       elements = info.fmt->samples_per_line;
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 1; info.ln <= 20; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               } else {
+                                       elements = info.fmt->active_samples_per_line;
+                               }
+                               info.xyz = &FIELD_1_ACTIVE;
+                               for (info.ln = 21; info.ln <= 560; info.ln++) {
+                                       create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+                                       p = pack(p, line_buffer, elements);
+                                       active_video_line += 2;
+                               }
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 561; info.ln <= 563; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                                       info.xyz = &FIELD_2_VERT_BLANKING;
+                                       for (info.ln = 564; info.ln <= 583; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+                               // start with first odd line
+                               active_video_line = 2;
+
+                               info.xyz = &FIELD_2_ACTIVE;
+                               for (info.ln = 584; info.ln <= 1123; info.ln++) {
+                                       create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+                                       p = pack(p, line_buffer, elements);
+                                       active_video_line += 2;
+                               }
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_2_VERT_BLANKING;
+                                       for (info.ln = 1124; info.ln <= 1125; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+                       } else if (info.fmt->lines_per_frame == 625) {
+
+                               elements = info.fmt->active_samples_per_line;
+
+                               // start with first even line
+                               active_video_line = 1;
+
+                               /**
+                                *  Generate an SDI PAL frame
+                                **/
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 1; info.ln <= 22; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+                               info.xyz = &FIELD_1_ACTIVE;
+                               for (info.ln = 23; info.ln <= 310; info.ln++) {
+                                       create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+                                       p = pack(p, line_buffer, elements);
+                                       active_video_line += 2;
+                               }
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 311; info.ln <= 312; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                                       info.xyz = &FIELD_2_VERT_BLANKING;
+                                       for (info.ln = 313; info.ln <= 335; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+
+                               // start with first odd line
+                               active_video_line = 2;
+
+                               info.xyz = &FIELD_2_ACTIVE;
+                               for (info.ln = 336; info.ln <= 623; info.ln++) {
+                                       create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+                                       p = pack(p, line_buffer, elements);
+                                       active_video_line += 2;
+                               }
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_2_VERT_BLANKING;
+                                       for (info.ln = 624; info.ln <= 625; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+                       } else if (info.fmt->lines_per_frame == 525) {
+
+                               /**
+                                *  Generate an SDI NTSC frame
+                                *
+                                *
+                                *   16 lines   VERT_BLANKING   FIELD_1_VERT_BLANKING
+                                *    1 lines   VERT_BLANKING   FIELD_1_ACTIVE
+                                *    3 lines   ACTIVE_VIDEO    FIELD_1_ACTIVE                  (opt. video data)
+                                *  240 lines   ACTIVE_VIDEO    FIELD_1_ACTIVE
+                                *    2 lines   VERT_BLANKING   FIELD_1_VERT_BLANKING
+                                *
+                                *    8 lines   VERT_BLANKING   FIELD_2_VERT_BLANKING
+                                *    9 lines   VERT_BLANKING   FIELD_2_VERT_BLANKING
+                                *    3 lines   ACTIVE_VIDEO    FIELD_2_ACTIVE                  (opt. video data)
+                                *  240 lines   ACTIVE_VIDEO    FIELD_2_ACTIVE
+                                *    4 lines   VERT_BLANKING   FIELD_2_VERT_BLANKING
+                                *
+                                **/
+
+                               elements = info.fmt->active_samples_per_line;
+
+                               active_video_line = 1;
+
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 1; info.ln <= 15; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                                       for (info.ln = 16; info.ln <= 16; info.ln++) {
+                                               info.xyz = &FIELD_1_ACTIVE;
+                                               mkline(line_buffer, &info, VERT_BLANKING);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+
+                               info.xyz = &FIELD_1_ACTIVE;
+
+                               // 480 or 486 lines
+                               if (info.fmt == &FMT_480i5994) {
+                                       // 3 lines opt. video data
+                                       for (info.ln = 17; info.ln <= 19; info.ln++) {
+                                               mkline(line_buffer, &info, BLACK);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                                       // 240 lines
+                                       for (info.ln = 20; info.ln <= 259; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                               active_video_line += 2;
+                                       }
+                               } else {
+                                       // 243 lines
+                                       for (info.ln = 17; info.ln <= 259; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                               active_video_line += 2;
+                                       }
+                               }
+                               if (info.blanking) {
+                                       // 2 lines vertical data
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 260; info.ln <= 261; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                                       // 8 lines vertical data
+                                       info.xyz = &FIELD_2_VERT_BLANKING;
+                                       for (info.ln = 262; info.ln <= 269; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                                       // 9 lines
+                                       for (info.ln = 270; info.ln <= 278; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+
+                               }
+
+                               active_video_line = 0;
+
+                               // 480 or 486 lines
+                               if (info.fmt == &FMT_480i5994) {
+                                       // 3 lines opt. video data
+                                       info.xyz = &FIELD_2_ACTIVE;
+                                       for (info.ln = 279; info.ln <= 281; info.ln++) {
+                                               mkline(line_buffer, &info, BLACK);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                                       // 240 lines
+                                       for (info.ln = 282; info.ln <= 521; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                               active_video_line += 2;
+                                       }
+                               } else {
+                                       // 243 lines
+                                       for (info.ln = 279; info.ln <= 521; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                               active_video_line += 2;
+                                       }
+                               }
+                               // 4 lines vertical data
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_2_VERT_BLANKING;
+                                       for (info.ln = 522; info.ln <= 525; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+                       }
+               } else {
+
+                       /****************************************
+                        * PROGRESSIVE
+                        ****************************************/
+
+                       // start with first line numerber
+                       active_video_line = 0;
+
+                       if (info.fmt->lines_per_frame == 1125) {
+                               if (info.blanking) {
+                                       elements = info.fmt->samples_per_line;
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 1; info.ln <= 41; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               } else {
+                                       elements = info.fmt->active_samples_per_line;
+                               }
+                               info.xyz = &FIELD_1_ACTIVE;
+                               for (info.ln = 42; info.ln <= 1121; info.ln++) {
+                                       create_HD_SDI_Line(line_buffer, &info, active_video_line++, ACTIVE_VIDEO, vBuffer);
+                                       p = pack(p, line_buffer, elements);
+                               }
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 1122; info.ln <= 1125; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+                       } else {
+                               if (info.blanking) {
+                                       elements = info.fmt->samples_per_line;
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 1; info.ln <= 25; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               } else {
+                                       elements = info.fmt->active_samples_per_line;
+                               }
+                               info.xyz = &FIELD_1_ACTIVE;
+                               for (info.ln = 26; info.ln <= 745; info.ln++) {
+                                       create_HD_SDI_Line(line_buffer, &info, active_video_line++, ACTIVE_VIDEO, vBuffer);
+                                       p = pack(p, line_buffer, elements);
+                               }
+                               if (info.blanking) {
+                                       info.xyz = &FIELD_1_VERT_BLANKING;
+                                       for (info.ln = 746; info.ln <= 750; info.ln++) {
+                                               create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
+                                               p = pack(p, line_buffer, elements);
+                                       }
+                               }
+                       }
+               }
        }
 
        // sum of bytes that have already been written to file
@@ -360,40 +917,153 @@ static int sdimaster_playout(uint8_t **vBuffer, int16_t **aBuffer0, int16_t **aB
        // store actual written bytes per 'write()
        int written_bytes = 0;
 
-       /*****************************************/
-       /**** WRITE BUFFER TO FILEHANDLE *********/
-       /*****************************************/
-
+       /**
+        * WRITE BUFFER TO FILEHANDLE
+        **/
        // Write the complete frame to output
        // The "while" is necessary because the sdi device file does not take the complete frame at once
-       while (bytes < framesize) {
-               if ((written_bytes = write(fh_sdi_dest, data + bytes, framesize - bytes)) < 0) {
-                       fprintf(stderr, "\nunable to write SDI.\n");
+       written_bytes = 0;
+       while (bytes < sdi_frame_size) {
+
+               if ((written_bytes = write(fh_sdi_video, data + bytes, sdi_frame_size - bytes)) < 0) {
+                       fprintf(stderr, "\nunable to write SDI video.\n");
                        return -1;
                }
                bytes += written_bytes;
+       }
+
+       // Check for events of the SDI board
+       unsigned int val;
+       if (ioctl(fh_sdi_video, SDI_IOC_TXGETEVENTS, &val) < 0) {
+               // Maybe this is not an SDI device...
+               //fprintf(stderr, "SDI VIDEO output:");
+               //perror("unable to get the transmitter event flags");
+       } else if (val) {
+               if (val & SDI_EVENT_TX_BUFFER) {
+                       printf("SDI VIDEO driver transmit buffer queue underrun "
+                               "detected.\n");
+                       fflush(stdout);
+               }
+               if (val & SDI_EVENT_TX_FIFO) {
+                       printf("SDI VIDEO onboard transmit FIFO underrun detected.\n");
+                       fflush(stdout);
+               }
+               if (val & SDI_EVENT_TX_DATA) {
+                       printf("SDI VIDEO transmit data change detected.\n");
+                       fflush(stdout);
+               }
+       }
 
-               // Check for events of the SDI board
-               unsigned int val;
-               // printf ("Getting the transmitter event flags.\n");
-               if (ioctl(fh_sdi_dest, SDI_IOC_TXGETEVENTS, &val) < 0) {
-                       // Maybe this is not an SDI device...
-
-                       // fprintf (stderr, "SDI output:");
-                       // perror ("unable to get the transmitter event flags");
-               } else if (val) {
-                       if (val & SDI_EVENT_TX_BUFFER) {
-                               printf("SDI driver transmit buffer queue underrun "
-                                       "detected.\n");
-                               sleep(5);
+       // if available write audio data
+       if (fh_sdi_audio) {
+
+               // count writen bytes
+               written_bytes = 0;
+
+               // set number of samples and cut by 1600 if NTSC (handle problem of real time encoding of NTSC frequencies)
+               size_t samples_total_per_track = audio_format->samples;
+               uint16_t sample_number = 0;
+               size_t channels_per_track_total = 2;
+               uint8_t stream_number = 0;
+
+               //printf("samples_total_per_track:%li\n", samples_total_per_track);
+
+               // to write blockwise 2 samples of one track we must claculate the number of bytes we want to write per write-session
+               // 2samples = 2x16Bit = 32Bit = 4Byte
+               // 2samples = 2x32Bit = 64Bit = 8Byte
+               // set total bytes per session
+               size_t bytes_total = 0;
+               bytes_total = audio_format->aformat == mlt_audio_s16 ? channels_per_track_total * sizeof(int16_t) : bytes_total;
+               bytes_total = audio_format->aformat == mlt_audio_s32 ? channels_per_track_total * sizeof(int32_t) : bytes_total;
+
+               // write all samples of all streams interleaved
+               /**
+                * aBuffer[track0]+sample1
+                * aBuffer[track0]+sample2
+                * aBuffer[track1]+sample1
+                * aBuffer[track1]+sample2
+                * aBuffer[track.]+sample1
+                * aBuffer[track.]+sample2
+                *
+                * aBuffer[track0]+sample3
+                * aBuffer[track0]+sample4
+                * aBuffer[track1]+sample3
+                * aBuffer[track1]+sample4
+                * aBuffer[track.]+sample3
+                * aBuffer[track.]+sample4
+                *
+                * aBuffer[track0]+sample5
+                * aBuffer[track0]+sample6
+                * aBuffer[track1]+sample5
+                * aBuffer[track1]+sample6
+                * aBuffer[track.]+sample5
+                * aBuffer[track.]+sample6
+                **/
+               int sum_written_bytes = 0;
+               int sum_written_bytes_a = 0;
+               int sum_written_bytes_b = 0;
+
+               // write all samples per track
+               while (sample_number < samples_total_per_track) {
+
+                       stream_number = 0;
+
+                       /**
+                        * Because we have and write a fix number of audio streams to SDI board:
+                        * we have a actual number of real audio tracks and a rest number of pseudo tracks
+                        **/
+                       // write all streams
+                       while (stream_number < audio_streams) {
+
+                               // write for every stream n samples
+                               // n = number of channels per stream
+                               written_bytes = 0;
+                               while (written_bytes < bytes_total) {
+                                       written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[stream_number] + sample_number * bytes_total + written_bytes,
+                                                       bytes_total - written_bytes);
+                               }
+                               sum_written_bytes += written_bytes;
+                               sum_written_bytes_a += written_bytes;
+
+                               stream_number++;
                        }
-                       if (val & SDI_EVENT_TX_FIFO) {
-                               printf("SDI onboard transmit FIFO underrun detected.\n");
 
-                               // TODO react
+                       // write pseudo tracks
+                       // now fill rest of audio tracks(AES frames) with NULL or copy of first track
+                       while (stream_number < audio_format->channels / 2) {
+
+                               // write for every stream n samples
+                               // n = number of channels per stream
+                               written_bytes = 0;
+                               while (written_bytes < bytes_total) {
+                                       written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[0] + sample_number * bytes_total + written_bytes,
+                                                       bytes_total - written_bytes);
+                               }
+                               sum_written_bytes += written_bytes;
+                               sum_written_bytes_b += written_bytes;
+
+                               stream_number++;
                        }
-                       if (val & SDI_EVENT_TX_DATA) {
-                               printf("SDI transmit data change detected.\n");
+
+                       sample_number++;
+
+                       // Check for events of the SDI audio device
+                       unsigned int val;
+                       if (ioctl(fh_sdi_audio, SDIAUDIO_IOC_TXGETEVENTS, &val) < 0) {
+                               //Maybe this is not an SDI device...
+                               //                              fprintf(stderr, "SDI AUDIO output:");
+                               //                              perror("unable to get the transmitter event flags");
+                       } else if (val) {
+                               if (val & SDIAUDIO_EVENT_TX_BUFFER) {
+                                       printf("SDI AUDIO driver transmit buffer queue underrun "
+                                               "detected.\n");
+                               }
+                               if (val & SDIAUDIO_EVENT_TX_FIFO) {
+                                       printf("SDI AUDIO onboard transmit FIFO underrun detected.\n");
+                               }
+                               if (val & SDIAUDIO_EVENT_TX_DATA) {
+                                       printf("SDI AUDIO transmit data change detected.\n");
+                               }
                        }
                }
        }
@@ -401,18 +1071,10 @@ static int sdimaster_playout(uint8_t **vBuffer, int16_t **aBuffer0, int16_t **aB
        return getDBN(my_DBN);
 } // end sdimaster_playout()
 
-// used by raw2sdi.c
-// interface to this sdimaster_playout()
-static int sdimaster_playout_raw(uint8_t *vBuffer, int16_t *aBuffer0, int16_t *aBuffer1, int16_t *aBuffer2, int16_t *aBuffer3, int16_t *aBuffer4,
-               int16_t *aBuffer5, int16_t *aBuffer6, int16_t *aBuffer7, int sizeofVideo, int sizeofAudio, int audio_streams, int my_DBN) {
 
-       return sdimaster_playout(&vBuffer, &aBuffer0, &aBuffer1, &aBuffer2, &aBuffer3, &aBuffer4, &aBuffer5, &aBuffer6, &aBuffer7, sizeofVideo, sizeofAudio,
-                       audio_streams, my_DBN);
-}
-
-// ****************************************************************************************
-// ***************************  Create Line  **********************************************
-// ****************************************************************************************
+//****************************************************************************************
+//***************************  Create Line  **********************************************
+//****************************************************************************************
 
 /** generate one SDI line
  * @param *buf: buffer to hold the line
@@ -426,68 +1088,33 @@ static int sdimaster_playout_raw(uint8_t *vBuffer, int16_t *aBuffer0, int16_t *a
  * @param AudioGroups2Write: number of samples to write
  * @param audio_streams: number of audio streams to integrate
  */
-static int create_SDI_line(uint16_t *buf, int field, int active, uint8_t *video_buffer, int16_t *audio_buffer0, int16_t *audio_buffer1, int16_t *audio_buffer2,
-               int16_t *audio_buffer3, int16_t *audio_buffer4, int16_t *audio_buffer5, int16_t *audio_buffer6, int16_t *audio_buffer7, int linenumber_sdiframe,
-               int linenumber_video, int my_DBN, int16_t AudioGroupCounter, int16_t AudioGroups2Write, int audio_streams) {
+static inline int create_SD_SDI_Line(uint16_t *buf, const struct line_info *info, int field, int active, uint8_t *video_buffer,
+               int16_t audio_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], int linenumber_sdiframe, int active_video_line, int my_DBN,
+               int16_t AudioGroupCounter, int16_t AudioGroups2Write, int audio_streams) {
 
        // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
-       //                                      *************************************************************************
+       //                                      *************************************************************************
        // 625 lines:           | EAV |     ANC      | SAV |            [CbY1CrY2]                                                      |
-       //                                      *************************************************************************
+       //                                      *************************************************************************
        // 1728 SDI-words:      | 4   |         280              | 4   |                720+360+360=1440                                        |
-       //                                      *************************************************************************
+       //                                      *************************************************************************
 
        // points to current position in line
        uint16_t *p = buf;
-       // XYZ word
-       uint16_t sav, eav;
-
-       // Set XYZ-word for each case
-       switch (field) {
-       case FIELD_1:
-               switch (active) {
-               case VERT_BLANKING:
-                       eav = 0x2d8; // 0xb6 << 2; // set bits for XYZ-word : [MSB:1][F][V][H][P3][P2][P1][P0][0][LSB:0]
-                       sav = 0x2ac; // 0xab << 2;
-                       break;
-               case ACTIVE_VIDEO:
-                       eav = 0x274; // 0x9d << 2;
-                       sav = 0x200; // 0x80 << 2;
-                       break;
-               default:
-                       return -1;
-               }
-               break;
-       case FIELD_2:
-               switch (active) {
-               case VERT_BLANKING:
-                       eav = 0x3c4; // 0xf1 << 2;
-                       sav = 0x3b0; // 0xec << 2;
-                       break;
-               case ACTIVE_VIDEO:
-                       eav = 0x368; // 0xda << 2;
-                       sav = 0x31c; // 0xc7 << 2;
-                       break;
-               default:
-                       return -1;
-               }
-               break;
-       default:
-               return -1;
-       }
 
-       // #########################################################################################
+       //#########################################################################################
        /* TRS Timing Reference Signal for EAV
         *              [3ff]
         *              [000]
         *              [000]
         *              [XYZ-Wort]
         * */
+
        *p++ = 0x3ff;
        *p++ = 0x000;
        *p++ = 0x000;
-       *p++ = eav;
-       // #########################################################################################
+       *p++ = info->xyz->eav;
+       //#########################################################################################
 
        /* ANC Ancillary Data with AES
         *
@@ -497,23 +1124,52 @@ static int create_SDI_line(uint16_t *buf, int field, int active, uint8_t *video_
        // write ANC Data and get number of samples are written
        // step with `p` += to the number of written samples
 
-       // Audio Group 1 with AES Frame 1 - 2
-       if (audio_streams > 0 && audio_streams <= 2) {
-               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer0, audio_buffer1, AudioGroupCounter, AudioGroups2Write, audio_streams);
-       }
+       //printf("audio_streams:%i\n",audio_streams);
 
-       // Audio Group 2 with AES Frame 3 - 4
-       if (audio_streams > 2 && audio_streams <= 4) {
-               p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer2, audio_buffer3, AudioGroupCounter, AudioGroups2Write, audio_streams);
+       // 1 stream, Audio Group 1 with AES Frame 1 - 2
+       if (audio_streams == 1) {
+               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[0], AudioGroupCounter, AudioGroups2Write);
+       }
+       // 2 streams, Audio Group 1 with AES Frame 1 - 2
+       if (audio_streams == 2) {
+               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
+       }
+       // 3 streams, Audio Group 2 with AES Frame 1 - 4
+       if (audio_streams == 3) {
+               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[2], AudioGroupCounter, AudioGroups2Write);
+       }
+       // 4 streams, Audio Group 2 with AES Frame 1 - 4
+       if (audio_streams == 4) {
+               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
+       }
+       // 5 streams, Audio Group 3 with AES Frame 1 - 6
+       if (audio_streams == 5) {
+               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[4], AudioGroupCounter, AudioGroups2Write);
+       }
+       // 6 streams, Audio Group 3 with AES Frame 1 - 6
+       if (audio_streams == 6) {
+               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
+       }
+       // 7 streams, Audio Group 4 with AES Frame 1 - 7
+       if (audio_streams == 7) {
+               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x2F9, my_DBN, audio_buffer[6], audio_buffer[6], AudioGroupCounter, AudioGroups2Write);
+       }
+       // 8 streams, Audio Group 4 with AES Frame 1 - 7
+       if (audio_streams == 8) {
+               p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
+               p += writeANC(p, linenumber_sdiframe, 0x2F9, my_DBN, audio_buffer[6], audio_buffer[7], AudioGroupCounter, AudioGroups2Write);
        }
-
-       // Audio Group 3 with AES Frame 5 - 6
-       if (audio_streams > 4 && audio_streams <= 6)
-               p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer4, audio_buffer5, AudioGroupCounter, AudioGroups2Write, audio_streams);
-
-       if (audio_streams > 6 && audio_streams <= 8)
-               // Audio Group 4 with AES Frame 6 - 7
-               p += writeANC(p, linenumber_sdiframe, 0x2F9, my_DBN, audio_buffer6, audio_buffer7, AudioGroupCounter, AudioGroups2Write, audio_streams);
 
        // Fill ANC data in until the end (position(p) to `ANCILLARY_DATA_SAMPLES`)
        while (p < (buf + ANCILLARY_DATA_SAMPLES + 4)) {
@@ -521,48 +1177,58 @@ static int create_SDI_line(uint16_t *buf, int field, int active, uint8_t *video_
                *p++ = 0x200;
                *p++ = 0x040;
        }
-       // #########################################################################################
+       //#########################################################################################
        // TRS Timing Reference Signal for SAV
        *p++ = 0x3ff;
        *p++ = 0x000;
        *p++ = 0x000;
-       *p++ = sav;
-       // #########################################################################################
+       *p++ = info->xyz->sav;
+       //#########################################################################################
+
+
+       // Because we skip the first line of video, it can happen that we read too far in the buffer
+       if (active_video_line >= info->fmt->active_lines_per_frame) {
+               active_video_line = info->fmt->active_lines_per_frame - 1; // in SD PAL was set 575
+       }
+       //Index of the start of the current line in the video_buffer
+       int start_of_current_line = active_video_line * info->fmt->active_samples_per_line;
 
-       // If VBlank then fill the line with 0x200 and 0x040
+       // If VBlank then fill the line with 0x200 and 0x040 (total black)
        switch (active) {
        default:
        case VERT_BLANKING:
-               while (p < (buf + TOTAL_SAMPLES)) {
+               while (p < (buf + info->fmt->samples_per_line)) {
                        *p++ = 0x200;
                        *p++ = 0x040;
                }
                break;
        case ACTIVE_VIDEO:
 
-               // Insert the Video into the Line
-               while (p < (buf + TOTAL_SAMPLES)) { // fill the rest of the line with active video
+               // Insert the video into the line
+               while (p < (buf + info->fmt->samples_per_line)) { // fill the rest of the line with active video
 
-                       // Because we skip the first line of video, it can happen that we read too far in the buffer
-                       if (linenumber_video >= 576)
-                               linenumber_video = 575;
+                       // shift "<< 2" because 8 bit data in 10 bit word
 
-                       *p++ = video_buffer[(linenumber_video * 1440) + ((p - 288) - buf) + 1] << 2; // Cb
+                       *p = video_buffer[start_of_current_line + ((p - 288) - buf) + 1] << 2; // Cb
+                       p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040; // check values
                        if (*(p - 1) > 0x3c0)
                                *(p - 1) = 0x3c0;
-                       *p++ = video_buffer[(linenumber_video * 1440) + ((p - 288) - buf) - 1] << 2; // Y1
+                       *p = video_buffer[start_of_current_line + ((p - 288) - buf) - 1] << 2; // Y1
+                       p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040;
                        if (*(p - 1) > 0x3ac)
                                *(p - 1) = 0x3ac;
-                       *p++ = video_buffer[(linenumber_video * 1440) + ((p - 288) - buf) + 1] << 2; // Cr
+                       *p = video_buffer[start_of_current_line + ((p - 288) - buf) + 1] << 2; // Cr
+                       p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040;
                        if (*(p - 1) > 0x3c0)
                                *(p - 1) = 0x3c0;
-                       *p++ = video_buffer[(linenumber_video * 1440) + ((p - 288) - buf) - 1] << 2; // Y2
+                       *p = video_buffer[start_of_current_line + ((p - 288) - buf) - 1] << 2; // Y2
+                       p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040;
                        if (*(p - 1) > 0x3ac)
@@ -574,14 +1240,164 @@ static int create_SDI_line(uint16_t *buf, int field, int active, uint8_t *video_
        return 0;
 }
 
-static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DBN, int16_t *audio_buffer_A, int16_t *audio_buffer_B, int16_t AudioGroupCounter,
-               int16_t AudioGroups2Write, int audio_streams) {
+/**
+ * create_HD_SDI_Line - generate one line
+ * @buf: pointer to a buffer
+ * @info: pointer to a line information structure
+ * @active_video_line
+ * @active:
+ * @video_buffer: pattern
+ *
+ * Returns a negative error code on failure and zero on success.
+ **/
+static inline int create_HD_SDI_Line(uint16_t *buf, const struct line_info *info, uint16_t active_video_line, unsigned int active,
+               uint8_t *video_buffer) {
+       uint16_t *p = buf, *endp, ln;
+       uint16_t samples = info->blanking ? info->fmt->samples_per_line : info->fmt->active_samples_per_line;
+
+       if (active_video_line >= info->fmt->active_lines_per_frame) {
+               active_video_line = info->fmt->active_lines_per_frame - 1;
+       }
 
-       /* ANC Ancillary
-        *
-        *      [ADF][ADF][ADF][DID][DBN][DC][UDW]...[UDW][CS]
+       int start_of_current_line = active_video_line * info->fmt->active_samples_per_line;
+
+       if (info->blanking) {
+
+               // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
+               // Example SD PAL:
+               //                  *************************************************************************
+               // 625 lines:       | EAV |     ANC      | SAV |        [CbY1CrY2]                          |
+               //                  *************************************************************************
+               // 1728 SDI-words:  | 4   |     280          | 4   |        720+360+360=1440                    |
+               //                                      *************************************************************************
+
+               // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
+               // Example HD 1080i:
+               //                  *************************************************************************
+               // 1125 lines:      | EAV | LN  | CRC | ANC | SAV | [CbY1CrY2]                              |
+               //                  *************************************************************************
+               // 5280 SDI-words:  | 6   | 4   | 4   | 280     | 6   | 1920+720+720=3840                       |
+               //                  *************************************************************************
+
+               if (info->fmt == &FMT_576i50) {
+                       /* EAV */
+                       *p++ = 0x3ff;
+                       *p++ = 0x000;
+                       *p++ = 0x000;
+                       *p++ = info->xyz->eav;
+               } else {
+                       /* EAV */
+                       *p++ = 1023;
+                       *p++ = 1023;
+                       *p++ = 0;
+                       *p++ = 0;
+                       *p++ = 0;
+                       *p++ = 0;
+                       *p++ = info->xyz->eav;
+                       *p++ = info->xyz->eav;
+                       /* LN */
+                       ln = ((info->ln & 0x07f) << 2) | (~info->ln & 0x040) << 3;
+                       *p++ = ln;
+                       *p++ = ln;
+                       ln = ((info->ln & 0x780) >> 5) | 0x200;
+                       *p++ = ln;
+                       *p++ = ln;
+                       /* CRC, added by serializer */
+                       *p++ = 512;
+                       *p++ = 64;
+                       *p++ = 512;
+                       *p++ = 64;
+
+               }
+
+               /* Horizontal blanking */
+               while (p < (buf + info->fmt->samples_per_line - info->fmt->active_samples_per_line - 4)) {
+                       *p++ = 512;
+                       *p++ = 64;
+                       *p++ = 512;
+                       *p++ = 64;
+               }
+
+               if (info->fmt == &FMT_576i50) {
+                       /* SAV */
+                       *p++ = 0x3ff;
+                       *p++ = 0x000;
+                       *p++ = 0x000;
+                       *p++ = info->xyz->sav;
+               } else {
+                       /* SAV */
+                       *p++ = 1023;
+                       *p++ = 1023;
+                       *p++ = 0;
+                       *p++ = 0;
+                       *p++ = 0;
+                       *p++ = 0;
+                       *p++ = info->xyz->sav;
+                       *p++ = info->xyz->sav;
+               }
+       }
+       /* Active region */
+       endp = p;
+
+       switch (active) {
+       default:
+       case VERT_BLANKING:
+               while (p < (buf + samples)) {
+                       *p++ = 512;
+                       *p++ = 64;
+                       *p++ = 512;
+                       *p++ = 64;
+               }
+               break;
+       case ACTIVE_VIDEO:
+
+       {
+
+               while (p < (buf + samples)) {
+
+                       *p = video_buffer[start_of_current_line + (p - buf) + 1] << 2; // Cb
+                       p++;
+                       //check values, this needs a lot of resources
+                       //                      if (*(p - 1) < 0x040)
+                       //                              *(p - 1) = 0x040;
+                       //                      if (*(p - 1) > 0x3c0)
+                       //                              *(p - 1) = 0x3c0;
+                       //
+                       *p = video_buffer[start_of_current_line + (p - buf) - 1] << 2; // Y1
+                       p++;
+                       //                      if (*(p - 1) < 0x040)
+                       //                              *(p - 1) = 0x040;
+                       //                      if (*(p - 1) > 0x3ac)
+                       //                              *(p - 1) = 0x3ac;
+                       //
+                       *p = video_buffer[start_of_current_line + (p - buf) + 1] << 2; // Cr
+                       p++;
+                       //                      if (*(p - 1) < 0x040)
+                       //                              *(p - 1) = 0x040;
+                       //                      if (*(p - 1) > 0x3c0)
+                       //                              *(p - 1) = 0x3c0;
+                       //
+                       *p = video_buffer[start_of_current_line + (p - buf) - 1] << 2; // Y2
+                       p++;
+                       //                      if (*(p - 1) < 0x040)
+                       //                              *(p - 1) = 0x040;
+                       //                      if (*(p - 1) > 0x3ac)
+                       //                              *(p - 1) = 0x3ac;
+               }
+       }
+               break;
+       }
+       return 0;
+}
+
+static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DBN, int16_t *audio_buffer_A, int16_t *audio_buffer_B,
+               int16_t AudioGroupCounter, int16_t AudioGroups2Write) {
+
+       /**
+        * ANC Ancillary Data (vgl. SMPTE 291-M page 6 )
+        * [ADF][ADF][ADF][DID][DBN][DC][UDW]...[UDW][CS]
         *
-        * */
+        **/
 
        // save only current position for return value
        uint16_t *pp = p;
@@ -589,13 +1405,8 @@ static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DB
        uint16_t buffer = 0; // set all explicit to zero, special the bit9 for parity
        // parity_counter
        int8_t parity_counter = 0;
-       // var `i` for forloops
-       int i = 0;
 
        if (AudioGroups2Write > 0) {
-               // printf("\n %i\n", (audiobuffer_line/8));
-
-               // Ancillary Data (vgl. SMPTE 291-M page 6 )
 
                // 3 ADF        (Ancillary Data Flag)
                *p++ = 0x000;
@@ -606,41 +1417,41 @@ static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DB
                // save DID for checker()
                uint16_t *DID_pointer = p;
                *p++ = DID;// (AES Audio Data, Group
-
-               // *p++ = 0x2FF; // (AES Audio Data, Group1=0x2FF)
-               // *p++ = 0x1FD;        // (AES Audio Data, Group2=0x1FD)
-               // *p++ = 0x1FB;        // (AES Audio Data, Group3=0x1FB)
-               // *p++ = 0x2F9;        // (AES Audio Data, Group4=0x2F9)
+               //              *p++ = 0x2FF; // (AES Audio Data, Group1=0x2FF)
+               //              *p++ = 0x1FD;   // (AES Audio Data, Group2=0x1FD)
+               //              *p++ = 0x1FB;   // (AES Audio Data, Group3=0x1FB)
+               //              *p++ = 0x2F9;   // (AES Audio Data, Group4=0x2F9)
 
                // 1 DBN        (Data Block Number) inactiv: 1000000000 b9,b8,b7-b0     ; SMPTE 272-M chapter15.1
-               // *p++ = 0x200;
-
-               // 1 DBN should start with previus DBN of SDI-Frame
-               //      -need "previus DBN" or "current framenumber"
-               //              SDI-LINE        DBN
-               //              [1]                     [1]             << start sdi frame >>
-               //              [2]                     [2]
-               //              [.]                     [.]
-               //              [255]           [255]
-               //              [256]           [1]
-               //              [257]           [2]
-               //              [.]                     [.]
-               //              [510]           [255]
-               //              [511]           [1]
-               //              [512]           [2]
-               //              [.]                     [.]
-               //              [625]           [115]   << end sdi frame >>
-               //              [1]                     [116]   << start sdi frame >>
+               //              *p++ = 0x200;
+
+               // 1 DBN (dynamic version0.1-beta ), should start with previus DBN of SDI-Frame
+               //      -need "previus DBN" or "current framenumber"
+               //              SDI-LINE:       DBN:
+               //              [1]                     [1]             << start sdi frame
+               //              [2]                     [2]
+               //              [.]                     [.]
+               //              [255]           [255]
+               //              [256]           [1]
+               //              [257]           [2]
+               //              [.]                     [.]
+               //              [510]           [255]
+               //              [511]           [1]
+               //              [512]           [2]
+               //              [.]                     [.]
+               //              [625]           [115]   << end sdi frame
+               //              [1]                     [116]   << start sdi frame
                // Accuracy of videoline_sdiframe(1 up to 625) to 8bit (1-255)
-               // buffer = ((videoline_sdiframe-1) % 255)+1;
+               //buffer = ((videoline_sdiframe-1) % 255)+1;
                buffer = my_DBN;
                parity_counter = 0;
                // count binary ones for parity
+               int i = 0;
                for (i = 0; i < 8; i++) {
                        if (buffer & (1 << i))
                                parity_counter++;
                }
-               if ((parity_counter % 2) == 0) { // else leave the 0
+               if ((parity_counter % 2) == 0) { //else leave the 0
                        buffer += 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
                } else {
                        buffer += 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
@@ -649,57 +1460,51 @@ static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DB
 
                // 1 DC         (Data Counter)
                // number of UDW = AudioGroups2Write x 2AESFrames x 2channesl x 3words(X,X+1,X+2)
-               buffer = AudioGroups2Write * 2* 2* 3 ; parity_counter= 0;
+               buffer = AudioGroups2Write * 2 * 2 * 3;
+               parity_counter = 0;
                // count binary ones for parity
-               for (i=0; i<8; i++) {
+               for (i = 0; i < 8; i++) {
                        if (buffer & (1 << i))
-                       parity_counter++;
+                               parity_counter++;
                }
-               if ((parity_counter%2)==0) { // else leave the 0
-                       buffer+= 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
+               if ((parity_counter % 2) == 0) { //else leave the 0
+                       buffer += 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
                } else {
-                       buffer+= 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
+                       buffer += 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
                }
                *p++ = buffer;
 
-               // z-bit for beginning of a new AES channel status block
-               int8_t z = 0;
-
-               int16_t sample_number=0;
+               int16_t sample_number = 0;
                int16_t counter = 0;
                // write subframes:
-               // = n x 1AudioGroup
+               // = n x 1 AudioGroup
                // = n x 2 x 1AESFrame
                // = n x 2 x 2samples
-               // = 4samples
+               // = 4 samples
                // = 4 x 3words
-               while (counter < AudioGroups2Write*2) { /* 4:3 */
+               while (counter < AudioGroups2Write * 2) { /* 4:3 */
 
                        // write one Audio Group with 4 x AES subframes
                        // ( samples for ch01,ch02,ch03,ch04 or ch05,ch06,ch07,ch08 or ch09,ch10,ch11,ch12 or ch13,ch14,ch15,ch16)
                        // and use audio_buffer_A(stereo) and audio_buffer_B(stereo)
                        // `pack_AES_subframe()` write 3 ANC words (3*10bit), also 1 sample
 
-                       sample_number=(AudioGroupCounter*2)+ counter;
-                       pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 1),
-                                       getZBit(sample_number/2), 0, &audio_buffer_A[sample_number]); // left
-                       p+=3; // step 3 words
+                       sample_number = (AudioGroupCounter * 2) + counter;
+                       pack_AES_subframe(p, getChannelStatusBit(sample_number / 2, 1), getZBit(sample_number / 2), 0, &audio_buffer_A[sample_number]); // left
+                       p += 3; // step 3 words
 
-                       sample_number=(AudioGroupCounter*2)+ counter+1;
-                       pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 2),
-                                       getZBit(sample_number/2), 1, &audio_buffer_A[sample_number]); // right
-                       p+=3;
+                       sample_number = (AudioGroupCounter * 2) + counter + 1;
+                       pack_AES_subframe(p, getChannelStatusBit(sample_number / 2, 2), getZBit(sample_number / 2), 1, &audio_buffer_A[sample_number]); // right
+                       p += 3;
 
-                       sample_number=(AudioGroupCounter*2)+ counter;
-                       pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 3),
-                                       getZBit(sample_number/2), 2, &audio_buffer_B[sample_number]); // left
-                       p+=3;
+                       sample_number = (AudioGroupCounter * 2) + counter;
+                       pack_AES_subframe(p, getChannelStatusBit(sample_number / 2, 3), getZBit(sample_number / 2), 2, &audio_buffer_B[sample_number]); // left
+                       p += 3;
 
-                       sample_number=(AudioGroupCounter*2)+ counter+1;
-                       pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 4),
-                                       getZBit(sample_number/2), 3, &audio_buffer_B[sample_number]); // right
-                       p+=3;
-                       counter+=2;
+                       sample_number = (AudioGroupCounter * 2) + counter + 1;
+                       pack_AES_subframe(p, getChannelStatusBit(sample_number / 2, 4), getZBit(sample_number / 2), 3, &audio_buffer_B[sample_number]); // right
+                       p += 3;
+                       counter += 2;
                }
 
                // 1 CS         (Checksum from DID - UDW)
@@ -709,7 +1514,7 @@ static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DB
                // rest until end of `ANCILLARY_DATA_SAMPLES` will be fill in a loop after call this function
                *p++ = 0x040;
        }
-       return p-pp;
+       return p - pp;
 }
 
 // calculate checksumm of ANC (SMPTE 272-M 15.3 Checksum (CS))
@@ -727,37 +1532,36 @@ static uint16_t checker(uint16_t *DID_pointer) {
        // DC - DataCounter
        cs += (*DID_pointer) & 0x1FF; // 9 x LSB
 
-       // Wir merken uns die Adresse an der DC im Feld steht und addieren auf diese den tatsächlichen Wert von DC.
-       // jetzt zeigt der merker auf das letzte Datenfeld...
-
+       // store address of DC an ad to the real value of DC
        // DataCounter store
-       // ´ende´ steht auf DataCounter
+       // ´ende´ point to DataCounter
        uint16_t *ende = DID_pointer;
-       // ´ende´ zeigt auf letztes feld
-       ende += (*DID_pointer) & 0xFF; // ohne parity-Bit und ¬9-Bit
+       // ´ende´ point to last field
+       ende += (*DID_pointer) & 0xFF; // without parity-Bit and ¬9-Bit
 
        DID_pointer++;
 
-       // DID_pointer auf Adressen kleiner 'ende' zeigt
+       // while DID_pointer point to smaller addres like 'ende'
        while (DID_pointer <= ende) {
                cs += (*DID_pointer++) & 0x1FF; // 9 x LSB
        }
 
-       // limit to 9Bi
+       // limit to 9Bit, because of overflow of sum
        cs = cs & 0x1FF;
 
-       // bit10 NOT bit9
-       // - cs invertieren (mit ~)
-       // - & mit bitmaske '01 0000 0000'
-       // - das übrig gebliebene Bit um eins nach links shiften
-       // - auf cs addieren
+       // set bit10 NOT bit9:
+       // - cs invert
+       // - & with bitmask '01 0000 0000'
+       // - shift rest (1xbit)to left
+       // - add to cs
        cs += ((~cs) & 0x100) << 1;
 
        return cs;
 } // end checker
 
 
-/** pack 16bit in AES subframe with 3words (30bit) and write in ´*p´
+/**
+ * pack 16bit in AES subframe with 3 words (30 bit) and write in ´*p´
  * 10bit-words --> [X],[X+1], [X+2] implements 20bit for audio
  *
  *                     BIT       9,     8,   7,   6,   5,   4,   3,   2,   1,   0
@@ -771,9 +1575,13 @@ static uint16_t checker(uint16_t *DID_pointer) {
  * @param z: value of AES subframe
  * @param ch: channel od AES subframe (value:0,1,2,3)
  * @param *audio_samplex: pointer to the audio buffer
- * */
+ **/
 static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int16_t *audio_samplex) {
 
+       /**
+        *  NOTE: WE JUST SUPPORT ONLY 16BIT SAMPLE SIZE
+        **/
+
        // push 16bit up to 20bit(32bit)
        int32_t audio_sample = *audio_samplex;
        audio_sample = audio_sample << 4; // Shift by 4 (louder)
@@ -784,9 +1592,9 @@ static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int16_t
        // 16bit buffer to write 10bit of [X]word,[X+1]word,[X+2]word,
        uint16_t buffer = 0;
 
-       // #########################################################
-       // ### WORD X  ############################################
-       // #########################################################
+       //#########################################################
+       //### WORD X  ############################################
+       //#########################################################
        // word X: !bit8, a5, a4, a3, a2, a1, a0, ch1, ch0, z
        // SMPTE 272M s.7
        buffer = z; // z bit every 192bit = 1
@@ -797,16 +1605,16 @@ static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int16_t
        // write word ´X´
        *p++ = buffer;
 
-       // count ones (zähle Einsen)
+       // count ones
        int i = 0;
        for (i = 0; i < 9; i++) {
                if (buffer & 1 << i)
                        parity_counter++;
        }
 
-       // #########################################################
-       // ### WORD X+1 ############################################
-       // #########################################################
+       //#########################################################
+       //### WORD X+1 ############################################
+       //#########################################################
        // word X+1: !bit8, a14, a13, a12, a11, a10, a9, a8, a7, a6
        // SMPTE 272M s.7
        buffer = 0;
@@ -823,30 +1631,30 @@ static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int16_t
                        parity_counter++;
        }
 
-       // #########################################################
-       // ### WORD X+2 ############################################
-       // #########################################################
+       //#########################################################
+       //### WORD X+2 ############################################
+       //#########################################################
        // word X+2: !bit8, P, C, U, V, a19, a18, a17, a16, a15
        // SMPTE 272M s.7
        buffer = 0;
        buffer += (audio_sample >> 15) & 0x01F; // a15 - a19
        // default of [V][U][C] bits = `0`
-       // buffer += 1<<5;      // V (AES sample validity bit)
-       // buffer += 1<<6;      // U (AES user bit)
-       // buffer += 1<<7;      // C (AES audio channel status bit)
-       buffer += c << 7;       // C (AES audio channel status bit)
+       //buffer += 1<<5;       // V (AES sample validity bit)
+       //buffer += 1<<6;       // U (AES user bit)
+       //buffer += 1<<7;       // C (AES audio channel status bit)
+       buffer += c << 7; // C (AES audio channel status bit)
 
-       // count ones
+       // count ones (zähle Einsen)
        for (i = 0; i < 8; i++) {
                if (buffer & 1 << i)
                        parity_counter++;
        }
 
-       //      if (!parity_counter%2) // else leave the 0
-       //              buffer+= 1 << 8; // P (AES even parity bit)
+       //      if (!parity_counter%2) //else leave the 0
+       //              buffer+= 1 << 8; // P (AES even parity bit)
        //
-       //      buffer += ((~buffer) & 0x100 )<<1; // !bit8
-       if ((parity_counter % 2) == 0) { // else leave the 0
+       //      buffer += ((~buffer) & 0x100 )<<1; // !bit8
+       if ((parity_counter % 2) == 0) { //else leave the 0
                buffer += 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
        } else {
                buffer += 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
@@ -862,13 +1670,13 @@ static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int16_t
 static uint8_t getZBit(int sample_number) {
 
        // start in SDI line 6 also 18samples later
-       // sample_number+=192-18;
+       //sample_number+=192-18;
 
        if (sample_number % 192 == 0) {
-               // printf("1 %i\n", sample_number);
+               //printf("1 %i\n", sample_number);
                return 1;
        } else {
-               // printf("0");
+               //printf("0");
                return 0;
        }
 }
@@ -879,7 +1687,7 @@ static uint8_t getChannelStatusBit(uint16_t sample_number, uint8_t ch) {
        uint8_t AESChannelStatusBit = 0;
 
        // start in SDI line 6 also 18samples later
-       // AESChannelStatusBit=((sample_number+192-18)%192);
+       //AESChannelStatusBit=((sample_number+192-18)%192);
        // interval in 192bit
        AESChannelStatusBit = sample_number % 192;
 
@@ -941,43 +1749,43 @@ static int16_t getNumberOfAudioGroups2Write(int linenumber) {
                return 3;
        }
 
-       //      // `4:3`-distribution
-       //      if(linenumber<=315){
-       //              if(linenumber>=6 && linenumber<=8){
-       //                      return 0;
-       //              }
-       //              if((linenumber+5)%10==0){
-       //                      return 4;
-       //              }else{
-       //                      return 3;
-       //              }
-       //      }else{
-       //              if(linenumber>=319 && linenumber<=321){
-       //                      return 0;
-       //              }
-       //              if((linenumber-8)%10==0){
-       //                      return 4;
-       //              }else{
-       //                      return 3;
-       //              }
-       //      }
-
-       //      // full-distribution
-       //      if(linenumber<=45){
-       //              return 4;
-       //      }else{
-       //              return 3;
-       //      }
-
-       //      // fullhalf-distribution
-       //      if (linenumber==625)
-       //              return 4;
+       //      // `4:3`-distribution
+       //      if(linenumber<=315){
+       //              if(linenumber>=6 && linenumber<=8){
+       //                      return 0;
+       //              }
+       //              if((linenumber+5)%10==0){
+       //                      return 4;
+       //              }else{
+       //                      return 3;
+       //              }
+       //      }else{
+       //              if(linenumber>=319 && linenumber<=321){
+       //                      return 0;
+       //              }
+       //              if((linenumber-8)%10==0){
+       //                      return 4;
+       //              }else{
+       //                      return 3;
+       //              }
+       //      }
+
+       //      // full-distribution
+       //      if(linenumber<=45){
+       //              return 4;
+       //      }else{
+       //              return 3;
+       //      }
+
+       //      // fullhalf-distribution
+       //      if (linenumber==625)
+       //              return 4;
        //
-       //      if (linenumber%14==0) {
-       //              return 4;
-       //      } else {
-       //              return 3;
-       //      }
+       //      if (linenumber%14==0) {
+       //              return 4;
+       //      } else {
+       //              return 3;
+       //      }
 
 }
 static uint8_t getDBN(int my_DBN) {
@@ -985,6 +1793,24 @@ static uint8_t getDBN(int my_DBN) {
        return ((my_DBN - 1) % 255) + 1;
 }
 
+/**
+ * pack8 - pack a line of 8-bit data
+ * @outbuf: pointer to the output buffer
+ * @inbuf: pointer to the input buffer
+ * @count: number of elements in the buffer
+ *
+ * Returns a pointer to the next output location.
+ **/
+static inline uint8_t *
+pack8(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
+       uint16_t *inp = inbuf;
+       uint8_t *outp = outbuf;
+
+       while (inp < (inbuf + count)) {
+               *outp++ = *inp++ >> 2;
+       }
+       return outp;
+}
 
 /**
  * pack10 - pack a line of 10-bit data
@@ -994,7 +1820,8 @@ static uint8_t getDBN(int my_DBN) {
  *
  * Returns a pointer to the next output location.
  **/
-static uint8_t * pack10(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
+static inline uint8_t * pack10(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
+
        uint16_t *inp = inbuf;
        uint8_t *outp = outbuf;
 
@@ -1011,11 +1838,576 @@ static uint8_t * pack10(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
 
        return outp;
 }
+/**
+ * pack_v210 - pack a line of v210 data
+ * @outbuf: pointer to the output buffer
+ * @inbuf: pointer to the input buffer
+ * @count: number of elements in the buffer
+ *
+ * Returns a pointer to the next output location.
+ **/
+static inline uint8_t * pack_v210(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
+
+       uint16_t *inp = inbuf;
+       uint8_t *outp = outbuf;
+
+       count = (count / 96) * 96 + ((count % 96) ? 96 : 0);
+       while (inp < (inbuf + count)) {
+               *outp++ = *inp & 0xff;
+               *outp = *inp++ >> 8;
+               *outp++ += (*inp << 2) & 0xfc;
+               *outp = *inp++ >> 6;
+               *outp++ += (*inp << 4) & 0xf0;
+               *outp++ = *inp++ >> 4;
+       }
+       return outp;
+}
 
 // Clean up
 static int sdimaster_close() {
 
-       close(fh_sdi_dest);
+       free(line_buffer);
+       free(data);
+
+       if (fh_sdi_audio)
+               close(fh_sdi_audio);
+       if (fh_sdi_video)
+               close(fh_sdi_video);
 
        return 1;
 }
+
+/**
+ * mkline - generate one line
+ * @buf: pointer to a buffer
+ * @info: pointer to a line information structure
+ * @pattern: pattern
+ *
+ * Returns a negative error code on failure and zero on success.
+ **/
+static int mkline(unsigned short int *buf, const struct line_info *info, unsigned int pattern) {
+       const unsigned int b = 205;
+       unsigned short int *p = buf, *endp;
+       unsigned int samples = info->blanking ? info->fmt->samples_per_line : info->fmt->active_samples_per_line;
+
+       if (info->blanking) {
+               /* EAV */
+               *p++ = 0x3ff;
+               *p++ = 0x000;
+               *p++ = 0x000;
+               *p++ = info->xyz->eav;
+               /* Horizontal blanking */
+               while (p < (buf + 272)) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               /* SAV */
+               *p++ = 0x3ff;
+               *p++ = 0x000;
+               *p++ = 0x000;
+               *p++ = info->xyz->sav;
+       }
+       /* Active region */
+       endp = p;
+       switch (pattern) {
+       default:
+       case VERT_BLANKING:
+               while (p < (buf + samples)) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               break;
+       case BLACK: /* black line (filler for FMT_480i5994 ) */
+               while (p < (buf + samples)) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               break;
+       case GREEN: /* green line for test purpose */
+               while (p < (buf + samples)) {
+                       *p++ = 289;
+                       *p++ = 450;
+                       *p++ = 231;
+                       *p++ = 450;
+               }
+               break;
+       case MAIN_SET:
+               /* 75% gray */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 512;
+                       *p++ = 721;
+                       *p++ = 512;
+                       *p++ = 721;
+               }
+               /* 75% yellow */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 176;
+                       *p++ = 646;
+                       *p++ = 567;
+                       *p++ = 646;
+               }
+               /* 75% cyan */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 625;
+                       *p++ = 525;
+                       *p++ = 176;
+                       *p++ = 525;
+               }
+               /* 75% green */
+               endp += b - 1;
+               while (p < endp) {
+                       *p++ = 289;
+                       *p++ = 450;
+                       *p++ = 231;
+                       *p++ = 450;
+               }
+               /* 75% magenta */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 735;
+                       *p++ = 335;
+                       *p++ = 793;
+                       *p++ = 335;
+               }
+               /* 75% red */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 399;
+                       *p++ = 260;
+                       *p++ = 848;
+                       *p++ = 260;
+               }
+               /* 75% blue */
+               while (p < (buf + samples)) {
+                       *p++ = 848;
+                       *p++ = 139;
+                       *p++ = 457;
+                       *p++ = 139;
+               }
+               break;
+       case CHROMA_SET:
+               /* 75% blue */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 848;
+                       *p++ = 139;
+                       *p++ = 457;
+                       *p++ = 139;
+               }
+               /* black */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               /* 75% magenta */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 735;
+                       *p++ = 335;
+                       *p++ = 793;
+                       *p++ = 335;
+               }
+               /* black */
+               endp += b - 1;
+               while (p < endp) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               /* 75% cyan */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 625;
+                       *p++ = 525;
+                       *p++ = 176;
+                       *p++ = 525;
+               }
+               /* black */
+               endp += b + 1;
+               while (p < endp) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               /* 75% gray */
+               while (p < (buf + samples)) {
+                       *p++ = 512;
+                       *p++ = 721;
+                       *p++ = 512;
+                       *p++ = 721;
+               }
+               break;
+       case BLACK_SET:
+               /* -I */
+               endp += 257;
+               while (p < endp) {
+                       *p++ = 624;
+                       *p++ = 231;
+                       *p++ = 390;
+                       *p++ = 231;
+               }
+               /* white */
+               endp += 257;
+               while (p < endp) {
+                       *p++ = 0x200;
+                       *p++ = 940;
+                       *p++ = 0x200;
+                       *p++ = 940;
+               }
+               /* +Q */
+               endp += 257;
+               while (p < endp) {
+                       *p++ = 684;
+                       *p++ = 177;
+                       *p++ = 591;
+                       *p++ = 177;
+               }
+               /* black */
+               endp += 257;
+               while (p < endp) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               /* blacker than black */
+               endp += 68;
+               while (p < endp) {
+                       *p++ = 0x200;
+                       *p++ = 29;
+                       *p++ = 0x200;
+                       *p++ = 29;
+               }
+               /* black */
+               endp += 68 + 2;
+               while (p < endp) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               /* whiter than black */
+               endp += 68;
+               while (p < endp) {
+                       *p++ = 0x200;
+                       *p++ = 99;
+                       *p++ = 0x200;
+                       *p++ = 99;
+               }
+               /* black */
+               while (p < (buf + samples)) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               break;
+       }
+       return 0;
+}
+
+static int setSDIVideoProperties(enum sdi_setting_video_e setting, char * value, char * device) {
+
+       const char fmt[] = "/sys/class/sdivideo/sdivideo%cx%i/%s";
+       struct stat buf;
+       int num;
+       char type, name[256], data[256];
+       char *endptr;
+
+       /* Get the sysfs info */
+       memset(&buf, 0, sizeof(buf));
+
+       /**
+        * Stat the file, fills the structure with info about the file
+        * Get the major number from device node
+        **/
+       if (stat(device, &buf) < 0) {
+               fprintf(stderr, "%s: ", device);
+               perror("unable to get the file status");
+               return -1;
+       }
+
+       /* Check if it is a character device or not */
+       if (!S_ISCHR (buf.st_mode)) {
+               fprintf(stderr, "%s: not a character device\n", device);
+               return -1;
+       }
+
+       /* Check the minor number to determine if it is a receive or transmit device */
+       type = (buf.st_rdev & 0x0080) ? 'r' : 't';
+
+       /* Get the receiver or transmitter number */
+       num = buf.st_rdev & 0x007f;
+
+       /* Build the path to sysfs file */
+       snprintf(name, sizeof(name), fmt, type, num, "dev");
+       memset(data, 0, sizeof(data));
+
+       /* Read sysfs file (dev) */
+       if (util_read(name, data, sizeof(data)) < 0) {
+               fprintf(stderr, "%s: ", device);
+               perror("unable to get the device number");
+               return -1;
+       }
+       /* Compare the major number taken from sysfs file to the one taken from device node */
+       if (strtoul(data, &endptr, 0) != (buf.st_rdev >> 8)) {
+               fprintf(stderr, "%s: not a SMPTE 292M/SMPTE 259M-C device\n", device);
+               return -1;
+       }
+       if (*endptr != ':') {
+               fprintf(stderr, "%s: error reading %s\n", device, name);
+               return -1;
+       }
+
+       // Which setting do we write
+       if (setting == SETTING_BUFFER_NUMBER_VIDEO) {
+               snprintf(name, sizeof(name), fmt, type, num, "buffers");
+               snprintf(data, sizeof(data), "%s\n", value);
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the number of buffers");
+                       return -1;
+               }
+               printf("\tSet number of buffers = %s\n", value);
+       } else if (setting == SETTING_BUFFER_SIZE_VIDEO) {
+               snprintf(name, sizeof(name), fmt, type, num, "bufsize");
+               snprintf(data, sizeof(data), "%s\n", value);
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the buffer size");
+                       return -1;
+               }
+               printf("\tSet buffer size = %s Bytes\n", value);
+       } else if (setting == SETTING_CLOCK_SOURCE) {
+               snprintf(name, sizeof(name), fmt, type, num, "clock_source");
+               snprintf(data, sizeof(data), "%s\n", value);
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the clock source");
+                       return -1;
+               }
+               printf("\tSet clock source = %s\n", value);
+       } else if (setting == SETTING_DATA_MODE) {
+               snprintf(name, sizeof(name), fmt, type, num, "mode");
+               snprintf(data, sizeof(data), "%s\n", value);
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the interface operating mode");
+                       return -1;
+               }
+               printf("\tSet data mode = %s\n", value);
+       } else if (setting == SETTING_FRAME_MODE) {
+               snprintf(name, sizeof(name), fmt, type, num, "frame_mode");
+               snprintf(data, sizeof(data), "%s\n", value);
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the interface frame mode");
+                       return -1;
+               }
+               printf("\tSet frame mode = %s\n", value);
+       }
+
+       return 0;
+
+}
+
+static int setSDIAudioProperties(enum sdi_setting_audio_e setting, char * value, char * device) {
+       const char fmt[] = "/sys/class/sdiaudio/sdiaudio%cx%i/%s";
+       struct stat buf;
+       int num;
+       char type, name[256], data[256];
+       char *endptr;
+
+       /* Get the sysfs info */
+       memset(&buf, 0, sizeof(buf));
+       if (stat(device, &buf) < 0) {
+               fprintf(stderr, "%s: ", device);
+               perror("unable to get the file status");
+               return -1;
+       }
+       if (!S_ISCHR (buf.st_mode)) {
+               fprintf(stderr, "%s: not a character device\n", device);
+               return -1;
+       }
+       type = (buf.st_rdev & 0x0080) ? 'r' : 't';
+       num = buf.st_rdev & 0x007f;
+       snprintf(name, sizeof(name), fmt, type, num, "dev");
+       memset(data, 0, sizeof(data));
+       if (util_read(name, data, sizeof(data)) < 0) {
+               fprintf(stderr, "%s: ", device);
+               perror("unable to get the device number");
+               return -1;
+       }
+
+       if (strtoul(data, &endptr, 0) != (buf.st_rdev >> 8)) {
+               fprintf(stderr, "%s: not an audio device\n", device);
+               return -1;
+       }
+       if (*endptr != ':') {
+               fprintf(stderr, "%s: error reading %s\n", device, name);
+               return -1;
+       }
+
+       if (setting == SETTING_BUFFER_NUMBER_AUDIO) {
+               snprintf(name, sizeof(name), fmt, type, num, "buffers");
+               snprintf(data, sizeof(data), "%s\n", value);
+
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the number of buffers");
+                       return -1;
+               }
+               printf("\tSet number of buffers = %s\n", value);
+       } else if (setting == SETTING_BUFFER_SIZE_AUDIO) {
+               snprintf(name, sizeof(name), fmt, type, num, "bufsize");
+               snprintf(data, sizeof(data), "%s\n", value);
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the buffer size");
+                       return -1;
+               }
+               printf("\tSet buffer size = %s Bytes\n", value);
+       } else if (setting == SETTING_SAMPLE_SIZE) {
+               snprintf(name, sizeof(name), fmt, type, num, "sample_size");
+               snprintf(data, sizeof(data), "%s\n", value);
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the interface audio sample size");
+                       return -1;
+               }
+               switch (atol(value)) {
+               case SDIAUDIO_CTL_AUDSAMP_SZ_16:
+                       printf("\tAssuming 16-bit audio.\n");
+                       break;
+               case SDIAUDIO_CTL_AUDSAMP_SZ_24:
+                       printf("\tAssuming 24-bit audio.\n");
+                       break;
+               case SDIAUDIO_CTL_AUDSAMP_SZ_32:
+                       printf("\tAssuming 32-bit audio.\n");
+                       break;
+               default:
+                       printf("\tSet audio sample size = %lu.\n", atol(value));
+                       break;
+               }
+       } else if (setting == SETTING_SAMPEL_RATE) {
+               snprintf(name, sizeof(name), fmt, type, num, "sample_rate");
+               snprintf(data, sizeof(data), "%lu\n", atol(value));
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set the interface audio sample rate");
+                       return -1;
+               }
+               switch (atoi(value)) {
+               case 32000:
+                       printf("\tAssuming 32 kHz audio.\n");
+                       break;
+               case 44100:
+                       printf("\tAssuming 44.1 kHz audio.\n");
+                       break;
+               case 48000:
+                       printf("\tAssuming 48 kHz audio.\n");
+                       break;
+               default:
+                       printf("\tSet audio sample rate = %lu.\n", atol(value));
+                       break;
+               }
+       } else if (setting == SETTING_CHANNELS) {
+               snprintf(name, sizeof(name), fmt, type, num, "channels");
+               snprintf(data, sizeof(data), "%lu\n", atol(value));
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set "
+                               "the interface audio channel enable");
+                       return -1;
+               }
+               switch (atol(value)) {
+               case SDIAUDIO_CTL_AUDCH_EN_0:
+                       printf("\tDisabling audio.\n");
+                       break;
+               case SDIAUDIO_CTL_AUDCH_EN_2:
+                       printf("\tAssuming 2 channels of audio.\n");
+                       break;
+               case SDIAUDIO_CTL_AUDCH_EN_4:
+                       printf("\tAssuming 4 channels of audio.\n");
+                       break;
+               case SDIAUDIO_CTL_AUDCH_EN_6:
+                       printf("\tAssuming 6 channels of audio.\n");
+                       break;
+               case SDIAUDIO_CTL_AUDCH_EN_8:
+                       printf("\tAssuming 8 channels of audio.\n");
+                       break;
+               default:
+                       printf("\tSet audio channel enable = %lu.\n", atol(value));
+                       break;
+               }
+       } else if (setting == SETTING_NON_AUDIO) {
+               snprintf(name, sizeof(name), fmt, type, num, "non_audio");
+               snprintf(data, sizeof(data), "0x%04lX\n", atol(value));
+               if (util_write(name, data, sizeof(data)) < 0) {
+                       fprintf(stderr, "%s: ", device);
+                       perror("unable to set "
+                               "the interface non-audio");
+                       return -1;
+               }
+               switch (atol(value)) {
+               case 0x0000:
+                       printf("\tPassing PCM audio.\n");
+                       break;
+               case 0x00ff:
+                       printf("\tPassing non-audio.\n");
+                       break;
+               default:
+                       printf("\tSet non-audio = 0x%04lX.\n", atol(value));
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static ssize_t util_read(const char *name, char *buf, size_t count) {
+       ssize_t fd, ret;
+
+       if ((fd = open(name, O_RDONLY)) < 0) {
+               return fd;
+       }
+       ret = read(fd, buf, count);
+       close(fd);
+       return ret;
+}
+
+static ssize_t util_write(const char *name, const char *buf, size_t count) {
+       ssize_t fd, ret;
+
+       if ((fd = open(name, O_WRONLY)) < 0) {
+               return fd;
+       }
+       ret = write(fd, buf, count);
+       close(fd);
+       return ret;
+}
+
+static char * itoa(uint64_t i) {
+
+       if (i == 0)
+               return strdup("0");
+
+       char * mystring = (char *) malloc(50);
+       sprintf(mystring, "%"PRIu64, i);
+
+       return mystring;
+}