]> git.sesse.net Git - mlt/commitdiff
Add HD-SDI support to Linsys SDI module.
authorDan Dennedy <dan@dennedy.org>
Fri, 12 Feb 2010 04:28:30 +0000 (20:28 -0800)
committerDan Dennedy <dan@dennedy.org>
Fri, 12 Feb 2010 04:28:30 +0000 (20:28 -0800)
This has only been tested with the VidPort.
At this time, you must run the linsys sdiaudiocfg and sdivideocfg
utilities to configure your card. In time, we hope to remove this step.

src/modules/linsys/consumer_SDIstream.c
src/modules/linsys/sdi_generator.c
src/modules/linsys/sdi_generator.h [new file with mode: 0644]

index f391cb162c3b740706cb4f2631f2a8bec8ff2cdd..132446c1cde7baca6814bf6ebcccc91514a006a6 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)
+ **********************************************************************************
+ *  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)
  *
- * Tested with:
- *      SDI Master™ PCI
- *     SDI Master™ PCIe
- *      SDI Master™ FD PCIe LP
- *      SDI Master™ Quad/o PCIe LP
+ *  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
  *
- */
-
-/*
- * consumer_SDIstream.c
- * Consumer for MLT Framework > 0.2.4 (release 0.2.4 does NOT work, profiles where not implemented)
+ *     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
+ * and
+ * Dan Dennedy                        10.Feb.2010
+ * Ver. 2.0
+ * See also Git commit log.
+ *
+ **********************************************************************************
+ *
+ * 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:
  *
- * Example:
- *     inigo video.dv -consumer linsys_sdi:/dev/sditx0 buffer=0;
- *     melt video.dv -consumer linsys_sdi:/dev/sditx0 buffer=0;
+ * SDI boards with full frame stream (with blanking):
+ *     melt video.dv -consumer sdi:/dev/sditx0
+ *     melt video.dv -consumer sdi:/dev/sditx0 blanking=true
+ *     melt video.dv -consumer sdi dev_video=/dev/sditx0 blanking=true
+ *     melt video.dv audio_index=all -consumer sdi dev_video=/dev/sditx0 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_audio=/dev/sdiaudiotx0 blanking=false
+ *  melt -profile atsc_1080i_50 video.mpeg audio_index=all -consumer sdi dev_video=/dev/sdivideotx0 dev_audio=/dev/sdiaudiotx0 blanking=false
+ *  melt -profile atsc_1080i_50 video.mpeg audio_index=all -consumer sdi dev_video=/dev/sdivideotx0 dev_audio=/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 × 480/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 × 480/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    sdi_486i_5994   193
+ *
+ **/
 
-#include <framework/mlt_frame.h>
 #include <framework/mlt_consumer.h>
+#include <framework/mlt_frame.h>
+#include <framework/mlt_profile.h>
 #include <framework/mlt_log.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
 #include <stdint.h>
 #include <unistd.h>
 
+#ifdef WITH_JPEG
+// for JPEG output
+#include <jpeglib.h>
+#endif
+
 #include "sdi_generator.c"
 
+// alias for "struct consumer_SDIstream_s *" , now we can write "consumer_SDIstream". Makes it more readable...
 typedef struct consumer_SDIstream_s *consumer_SDIstream;
 
 struct consumer_SDIstream_s {
-
+       // Most of these values are set to their defaults by the parent consumer
        struct mlt_consumer_s parent; // This is the basic Consumer from which we fetch our data
-       char *path_destination_sdi; // Path for SDI output
+       mlt_image_format pix_fmt; // Must be mlt_image_yuv422 for SDI
+
+       int width;
+       int height;
+
+       struct audio_format audio_format;
+       /** device file:
+        *              /dev/sditx0
+        *              /dev/sdivideotx0
+        *              /dev/sdiaudiotx0
+        **/
+       char *device_file_video; // Path for SDI output
+       char *device_file_audio; // Path for exlusive SDI audio output
+
+       /* write own HANC (ancillary data) is available for:
+        * SDI board ASSY 193 HD        'blanking=false'
+        * SDI board ASSY 180 SD quad   'blanking=true'
+        * SDI board ASSY 145 SD single 'blanking=true'
+        *
+        * 0=false, 1=true
+        *
+        * */
+       uint8_t blanking;
+
+       // our audio channel pair for this frame
        int16_t audio_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES]; // The SDI audio channel pairs for this frame
-};
 
-/** Forward references to static functions.
- */
+       char *video_fmt_name; // 1080i25, 1080p25, 576i50, 480i2997, ...
+
+};
 
+/**
+ * Forward references to static functions.
+ **/
 static int consumer_start(mlt_consumer this);
 static int consumer_stop(mlt_consumer this);
 static int consumer_is_stopped(mlt_consumer this);
 static void consumer_close(mlt_consumer parent);
 static void *consumer_thread(void *);
 
-//*****************************************************************************************************
-//*****************************************************************************************************
-//*******************************************SDI Master Consumer***************************************
-//*****************************************************************************************************
-//*****************************************************************************************************
+static void consumer_write_JPEG(char * path, uint8_t **vBuffer, mlt_profile myProfile);
+int convertYCBCRtoRGB(int y1, int cb, int cr, int y2, int * target_rgb);
 
+/*****************************************************************************************************
+ ****************************************** SDI Master Consumer **************************************
+ *****************************************************************************************************/
 
-/**
- * This is what will be called by the factory
+/** This is what will be called by the factory
  * @param profile: profile name for consumer
  * @param type: unused
  * @param *id: unused
@@ -109,6 +210,7 @@ mlt_consumer consumer_SDIstream_init(mlt_profile profile, mlt_service_type type,
 
        // If malloc and consumer init ok
        if (this != NULL && mlt_consumer_init(&this->parent, this, profile) == 0) {
+
                // Get the parent consumer object
                mlt_consumer parent = &this->parent;
 
@@ -117,9 +219,9 @@ mlt_consumer consumer_SDIstream_init(mlt_profile profile, mlt_service_type type,
 
                // Set output path for SDI, default is "/dev/sditx0"
                if (arg == NULL) {
-                       this->path_destination_sdi = strdup("/dev/sditx0");
+                       this->device_file_video = strdup("/dev/sditx0");
                } else {
-                       this->path_destination_sdi = strdup(arg);
+                       this->device_file_video = strdup(arg);
                }
 
                // Set up start/stop/terminated callbacks
@@ -127,8 +229,13 @@ mlt_consumer consumer_SDIstream_init(mlt_profile profile, mlt_service_type type,
                parent->stop = consumer_stop;
                parent->is_stopped = consumer_is_stopped;
 
-               // Hardcode the audio sample rate to 48KHz for SDI
-               mlt_properties_set_int(MLT_CONSUMER_PROPERTIES(parent), "frequency", 48000);
+               // Set explizit to zero or other value
+               int i, j;
+               for (i = 0; i < MAX_AUDIO_STREAMS; i++) {
+                       for (j = 0; j < MAX_AUDIO_SAMPLES; j++) {
+                               this->audio_buffer[i][j] = j;
+                       }
+               }
 
                // Return the consumer produced
                return parent;
@@ -145,6 +252,7 @@ mlt_consumer consumer_SDIstream_init(mlt_profile profile, mlt_service_type type,
  * Start the consumer.
  **/
 static int consumer_start(mlt_consumer parent) {
+
        // Get the properties
        mlt_properties properties = mlt_consumer_properties(parent);
 
@@ -169,7 +277,7 @@ static int consumer_start(mlt_consumer parent) {
 }
 
 /**
- * Stop the consumer.
+ * Stop the consumer
  **/
 static int consumer_stop(mlt_consumer parent) {
 
@@ -178,6 +286,7 @@ static int consumer_stop(mlt_consumer parent) {
 
        // Check that we're running
        if (mlt_properties_get_int(properties, "running")) {
+
                // Get the threads
                pthread_t *consumer_pthread = mlt_properties_get_data(properties, "consumer_pthread", NULL);
 
@@ -186,12 +295,13 @@ static int consumer_stop(mlt_consumer parent) {
 
                // Wait for termination
                pthread_join(*consumer_pthread, NULL);
+
        }
        return 0;
 }
 
 /**
- * Determine if the consumer is stopped.
+ * Determine if the consumer is stopped
  **/
 static int consumer_is_stopped(mlt_consumer this) {
        // Get the properties
@@ -203,6 +313,7 @@ static int consumer_is_stopped(mlt_consumer this) {
  * Threaded wrapper for pipe.
  **/
 static void *consumer_thread(void *arg) {
+
        // Identify the arg
        consumer_SDIstream this = arg;
 
@@ -210,13 +321,54 @@ static void *consumer_thread(void *arg) {
        mlt_consumer consumer = &this->parent;
 
        // Convenience functionality (this is to stop melt/inigo after the end of a playout)
-       int terminate_on_pause = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES(consumer), "terminate_on_pause");
-       int terminated = 0;
+       int terminate_on_pause = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES( consumer ), "terminate_on_pause");
+       int terminated = 0; // save ony status
+
+       int save_jpegs = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES( consumer ), "save_jpegs");
+       char * jpeg_folder = mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "jpeg_file");
+
+       // If no folder is specified, skip jpeg export
+       if (jpeg_folder == NULL) {
+               save_jpegs = 0;
+       }
+
+       if (save_jpegs > 0)
+               mlt_log_info(MLT_CONSUMER_SERVICE(consumer), "Saving a JPEG every %i frame.\n", save_jpegs);
+
+       int counter = 0; // each second we save a Jpeg
+
+       // set blanking flag; is not nessary we write no own blanking(HANC) for HD board ASSY 193
+       if (mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking") != NULL) {
+               // set value
+               if (strcmp(strdup(mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking")), "false")) {
+                       this->blanking = 1;
+               } else if (strcmp(strdup(mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking")), "true")) {
+                       this->blanking = 0;
+               } else {
+                       this->blanking = 1;
+               }
+       } else {
+               // set default value without HD board, also with blanking
+               this->blanking = 1;
+       }
+
+       // set properties (path) for device files
+       if (mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "dev_video") != NULL) {
+               this->device_file_video = strdup(mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "dev_video"));
+       }
+       if (mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "dev_audio") != NULL) {
+               if (this->blanking == 0) {
+                       this->device_file_audio = strdup(mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "dev_audio"));
+               } else {
+                       // if we write HANC we do not write further audio data
+                       mlt_log_info(MLT_CONSUMER_SERVICE(consumer), "Audio device file is set but will not be used.\n");
+               }
+       }
 
        // Define a frame pointer
        mlt_frame frame;
 
-       if (!sdimaster_init(this->path_destination_sdi, 0)) {
+       if (!sdi_init(this->device_file_video, this->device_file_audio, this->blanking, mlt_service_profile((mlt_service) consumer))) {
                exit(0);
        }
 
@@ -226,6 +378,18 @@ static void *consumer_thread(void *arg) {
        double fps = mlt_properties_get_double(MLT_CONSUMER_PROPERTIES(consumer), "fps");
        unsigned int count = 0;
 
+       // Tell the framework how we want our audio and video
+       int frequency = 48000;
+       int channels = 0;
+       int samples = mlt_sample_calculator(fps, frequency, count++);
+
+       this->audio_format.aformat = mlt_audio_s16;
+       this->audio_format.channels = 0;
+       this->pix_fmt = mlt_image_yuv422;
+
+       uint8_t *video_buffer;
+       int16_t *audio_buffer_tmp; // the upstream audio buffer
+
        // Loop until told not to
        while (!consumer_is_stopped(consumer) && terminated == 0) { //
 
@@ -234,47 +398,41 @@ static void *consumer_thread(void *arg) {
 
                        // Check for termination
                        if (terminate_on_pause && frame != NULL) {
-                               terminated = mlt_properties_get_double(MLT_FRAME_PROPERTIES(frame), "_speed") == 0.0;
+                               terminated = mlt_properties_get_double(MLT_FRAME_PROPERTIES( frame ), "_speed") == 0.0;
                                if (terminated == 1) {
-                                       mlt_log_info(MLT_CONSUMER_SERVICE(consumer), "End of playout reached, terminating\n");
-                                       fflush(stdout);
+                                       mlt_log_verbose(MLT_CONSUMER_SERVICE(consumer), "\nEnd of playout reached, terminating\n");
                                        consumer_stop(consumer);
                                }
                        }
 
                        // True if mlt_consumer_rt_frame(...) successful
                        if (mlt_properties_get_int(mlt_frame_properties(frame), "rendered") == 1) {
-                               mlt_properties properties = MLT_CONSUMER_PROPERTIES(consumer);
-
-                               // Tell the framework how we want our audio and video
-                               int width = mlt_properties_get_int(properties, "width");
-                               int height = mlt_properties_get_int(properties, "height");
-                               int frequency = 48000;
-                               int channels = 0;
-                               int samples = mlt_sample_calculator(fps, frequency, count++);
-                               mlt_image_format pix_fmt = mlt_image_yuv422;
-                               mlt_audio_format aformat = mlt_audio_s16;
-                               uint8_t *video_buffer;
-                               int16_t *audio_buffer_tmp; // the upstream audio buffer
 
                                // Get the video from this frame and save it to our video_buffer
-                               mlt_frame_get_image(frame, &video_buffer, &pix_fmt, &width, &height, 0);
+                               mlt_frame_get_image(frame, &video_buffer, &this->pix_fmt, &this->width, &this->height, 1);
 
                                // Get the audio from this frame and save it to our audio_buffer
-                               mlt_frame_get_audio(frame, (void**) &audio_buffer_tmp, &aformat, &frequency, &channels, &samples);
-                               mlt_log_debug(MLT_CONSUMER_SERVICE(consumer), "channels: %i samples: %i\n", channels, samples);
-                               
-                               int out_channels = channels;
-                               if ( mlt_properties_get( properties, "force_channels" ) )
-                                       out_channels = mlt_properties_get_int( properties, "force_channels" );
-
-                               // Tell the sdi_generator.c to playout our frame
-                               // 8 audio streams with 2 stereo channels are possible
+                               mlt_frame_get_audio(frame, (void**) &audio_buffer_tmp, &this->audio_format.aformat, &frequency, &channels, &samples);
+
+                               this->audio_format.sample_rate = frequency;
+                               this->audio_format.samples = samples;
+
+                               // TODO, current hard coded to all 8 channels, also we write 8 channels to the sdi board
+                               // the Linys SDI board must be right configured with the same number of channels!!!
+                               this->audio_format.channels = 8;
+                               // this->audio_format.channels = channels; // take given number of channels
+
+                               /* Tell the sdi_generator.c to playout our frame
+                                * 8 AES (8 x stereo channels are possible, max. 16 channels) Linsys SD board model:    107, 159, 145, 180
+                                * 4 AES (4 x stereo channels are possible, max. 8 channels) Linsys HD board model:             193
+                                */
                                if (video_buffer) {
+
+                                       // provide mapping of audio channels
                                        int i, j = 0;
                                        int map_channels, map_start;
 
-                                       for (i = 0; i < MAX_AUDIO_STREAMS && j < out_channels; i++) {
+                                       for (i = 0; i < MAX_AUDIO_STREAMS && j < channels; i++) {
                                                char key[27];
                                                int c;
 
@@ -282,6 +440,7 @@ static void *consumer_thread(void *arg) {
                                                map_channels = mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame), key);
                                                sprintf(key, "meta.map.audio.%d.start", i);
                                                map_start = mlt_properties_get_int(MLT_FRAME_PROPERTIES(frame), key);
+
                                                if (!map_channels)
                                                        map_channels = channels - j;
                                                for (c = 0; c < map_channels && j < channels; c++, j++) {
@@ -296,17 +455,34 @@ static void *consumer_thread(void *arg) {
                                                        }
                                                }
                                        }
-                                       my_dbn = sdimaster_playout(video_buffer, this->audio_buffer, (out_channels + 1) / 2, my_dbn);
-                               } else
-                                       mlt_log_warning(MLT_CONSUMER_SERVICE(consumer), "video_buffer was NULL, skipping playout\n");
 
+                                       // generate SDI frame and playout
+                                       my_dbn = sdi_playout(video_buffer, this->audio_buffer, &this->audio_format, (channels + 1) / 2, my_dbn);
+
+                                       // write a JPEG of every X-th frame
+                                       if (save_jpegs > 0 && counter >= save_jpegs) {
+                                               consumer_write_JPEG(jpeg_folder, &video_buffer, mlt_service_profile((mlt_service) consumer));
+                                               counter = 0;
+                                       } else if (save_jpegs > 0) {
+                                               counter++;
+                                       }
+                               } else {
+                                       mlt_log_warning(MLT_CONSUMER_SERVICE(consumer), "Videobuffer was NULL, skipping playout!\n");
+                               }
                        } else {
                                mlt_log_warning(MLT_CONSUMER_SERVICE(consumer), "WARNING the requested frame is not yet rendered! This will cause image disturbance!\n");
+
+                               if (video_buffer) {
+                                       my_dbn = sdi_playout(video_buffer, this->audio_buffer, &this->audio_format, (channels + 1) / 2, my_dbn);
+                               } else {
+                                       mlt_log_warning(MLT_CONSUMER_SERVICE(consumer), "Videobuffer was NULL, skipping playout!\n");
+                               }
                        }
 
                        if (frame != NULL)
                                mlt_frame_close(frame);
                }
+
        }
        return NULL;
 }
@@ -319,7 +495,8 @@ static void consumer_close(mlt_consumer parent) {
        // Get the actual object
        consumer_SDIstream this = parent->child;
 
-       free(this->path_destination_sdi);
+       free(this->device_file_video);
+       free(this->device_file_audio);
 
        // Now clean up the rest (the close = NULL is a bit nasty but needed for now)
        parent->close = NULL;
@@ -331,3 +508,150 @@ static void consumer_close(mlt_consumer parent) {
        // Finally clean up this
        free(this);
 }
+
+/**
+ * Write videobuffer as JPEG to path
+ * @param path
+ **/
+static void consumer_write_JPEG(char * filename, uint8_t **vBuffer, mlt_profile myProfile) {
+
+#ifdef WITH_JPEG
+
+       int bytes_per_pixel = 3; // or 1 for GRACYSCALE images
+       int color_space = JCS_RGB; // or JCS_GRAYSCALE for grayscale images
+
+       uint8_t * buffer_position = *vBuffer;
+       uint8_t image_rgb[myProfile->width * myProfile->height * bytes_per_pixel];
+
+       //convert vBuffer to RGB
+       int i;
+       for (i = 0; i < sizeof(image_rgb) / 6; i++) {
+               int y1 = *(buffer_position++);
+               int cb = *(buffer_position++);
+               int y2 = *(buffer_position++);
+               int cr = *(buffer_position++);
+               convertYCBCRtoRGB(y1, cb, cr, y2, &image_rgb[i * 6]);
+       }
+
+       struct jpeg_compress_struct cinfo;
+       struct jpeg_error_mgr jerr;
+
+       // this is a pointer to one row of image data
+       JSAMPROW row_pointer[1];
+
+       FILE *outfile = fopen(filename, "wb");
+
+       if (!outfile) {
+               mlt_log_error(NULL, "%s: Error opening output jpeg file %s\n!", __FILE__, filename);
+               return;
+       }
+       cinfo.err = jpeg_std_error(&jerr);
+       jpeg_create_compress(&cinfo);
+       jpeg_stdio_dest(&cinfo, outfile);
+
+       // Setting the parameters of the output file here
+       cinfo.image_width = myProfile->width;
+       cinfo.image_height = myProfile->height;
+       cinfo.input_components = bytes_per_pixel;
+       cinfo.in_color_space = (J_COLOR_SPACE) color_space;
+
+       // default compression parameters, we shouldn't be worried about these
+       jpeg_set_defaults(&cinfo);
+
+       // Now do the compression
+       jpeg_start_compress(&cinfo, TRUE);
+
+       // like reading a file, this time write one row at a time
+       while (cinfo.next_scanline < cinfo.image_height) {
+               row_pointer[0] = &image_rgb[cinfo.next_scanline * cinfo.image_width * cinfo.input_components];
+               jpeg_write_scanlines(&cinfo, row_pointer, 1);
+       }
+       // similar to read file, clean up after we're done compressing
+       jpeg_finish_compress(&cinfo);
+       jpeg_destroy_compress(&cinfo);
+       fclose(outfile);
+#endif
+}
+
+/**
+ * converts  YCbCr samples to two 32-bit RGB values
+ * @param y1 cb cr and y2 values
+ * @param target pointer
+ * @return 0 upon success
+ **/
+int convertYCBCRtoRGB(int y1, int cb, int cr, int y2, int * target_rgb) {
+
+#ifdef WITH_JPEG
+
+       uint32_t tmp = 0;
+       uint8_t r1, g1, b1, r2, g2, b2;
+
+       //pointer to current output buffer position
+       uint8_t * target_pointer = target_rgb;
+
+       // colorconversion for first pixel and output to rgb buffer
+       /* B1 */
+       tmp = 1.164 * (y1 - 16) + 2.017 * (cb - 128);
+       if (tmp > 255)
+               tmp = 255;
+       if (tmp < 0)
+               tmp = 0;
+       b1 = tmp;
+
+       /* G1 */
+       tmp = 1.164 * (y1 - 16) - 0.813 * (cr - 128) - 0.392 * (cb - 128);
+       if (tmp > 255)
+               tmp = 255;
+       if (tmp < 0)
+               tmp = 0;
+       g1 = tmp;
+
+       /* R1 */
+       tmp = 1.164 * (y1 - 16) + 1.596 * (cr - 128);
+       if (tmp > 255)
+               tmp = 255;
+       if (tmp < 0)
+               tmp = 0;
+       r1 = tmp;
+
+       // colorconversion for second pixel and output to rgb buffer
+       /* B2 */
+       tmp = 1.164 * (y2 - 16) + 2.017 * (cb - 128);
+       if (tmp > 255)
+               tmp = 255;
+       if (tmp < 0)
+               tmp = 0;
+       b2 = tmp;
+
+       /* G2 */
+       tmp = 1.164 * (y2 - 16) - 0.813 * (cr - 128) - 0.392 * (cb - 128);
+       if (tmp > 255)
+               tmp = 255;
+       if (tmp < 0)
+               tmp = 0;
+       g2 = tmp;
+
+       /* R2 */
+       tmp = 1.164 * (y2 - 16) + 1.596 * (cr - 128);
+       if (tmp > 255)
+               tmp = 255;
+       if (tmp < 0)
+               tmp = 0;
+       r2 = tmp;
+
+       //      r=y+1.5958*v;
+       //  g=y-0.39173*u-0.81290*v;
+       //  b=y+2.017*u;
+
+       *target_pointer++ = r1;
+       *target_pointer++ = g1;
+       *target_pointer++ = b1;
+
+       *target_pointer++ = r2;
+       *target_pointer++ = g2;
+       *target_pointer++ = b2;
+
+       return 0;
+#endif
+       return 1;
+}
index f4af2a2e63f7a53ddba93654c016a98c9890ed39..0004f741e6c0e59583425cfe48ab988a8b25d3f8 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)
  *
- */
-
-#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 MAX_AUDIO_SAMPLES (1920*2)    // 1920 Samples per Channel and we have stereo (48000 Hz /25 fps = 1920 Samples per frame)
-#define MAX_AUDIO_STREAMS (8)
-#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 aBuffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], 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_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES],
-               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[MAX_AUDIO_SAMPLES], int16_t audio_buffer_B[MAX_AUDIO_SAMPLES],
-               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, int32_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 !!!
+ *  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 × 480/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 × 480/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    sdi_486i_5994   193
+ *
+ **/
 
+#include "sdi_generator.h"
 
 /*!/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)
+ * @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) {
+
+       // set device file
+       device_file_video = device_video;
+       device_file_audio = device_audio;
+
+       // set flag for using of blanking with anilary data
+       info.blanking = blanking;
+
+       // set pack methode 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } 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;
+       } else {
+               printf("Consumer gets unknown format: %s", myProfile->description);
+               info.fmt = &FMT_576i50;
+       }
+
+       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 video format (currently only PAL is available)
-       if (format != 0) {
-               printf("sdimaster_init get format '%i' ", format);
+       // Check if the format support own blanking (note: model 193 support 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 this configurred SD board and SDI format. Try arguemnt: 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 (device_file_video != NULL) {
+               // open file handler 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);
+               }
+               printf("SDI consumer use video device file: %s\n", device_file_video);
        }
 
-       // small description
-       // http://www.sencore.com/newsletter/Nov05/DigAudioChannelStatusBits.htm
-       // or
-       // http://www.sencore.com/uploads/files/DigAudioChannelStatusBits.pdf
+       // Check if seperat device file for audio must use
+       if (device_file_audio != NULL) {
+               // open file handler for audio output
+               if ((fh_sdi_audio = open(device_file_audio, O_WRONLY | O_CREAT, 0777)) == -1) {
+                       perror(NULL);
+                       printf("\ncould not open audio output destination: %s\n", device_file_audio);
+                       return EXIT_FAILURE;
+               }
+               printf("SDI consumer use audio device file: %s\n", device_file_audio);
+       }
 
-       // create empty AESChannelStatusBitArray
-       int i = 0;
-       for (i = 0; i < sizeof(AESChannelStatusBitArray) / sizeof(AESChannelStatusBitArray[0]); i++)
-               AESChannelStatusBitArray[i] = 0;
+       // 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;
+
+               /**
+                * Professionel 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 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; // ^
+       }
 
-       /**
-        * Professionel 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 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; // ^
+       // 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_480i5994) {
+               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;
+                       }
+               }
+       }
+
+       // hack/overwrite because we use default the pack_v210() not as befor the pack10()
+       //(*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;
+       }
+
+       printf("SDI frame size:%li\n", sdi_frame_size);
+
+       // 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
+/**
+ * Writes video and audio to specified files in SDI format
  * @param *vBuffer: Pointer to a video Buffer
- * @param aBuffer: An array of 8 audio channel pairs (2 mono channels)
+ * @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 aBuffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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, aBuffer, 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
+                                **/
+                               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;
+                               // 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);
+                               }
+                               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;
+                               }
+                               if (info.blanking) {
+                                       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);
+                                       }
+                                       info.xyz = &FIELD_2_VERT_BLANKING;
+                                       // 7 lines vertical data
+                                       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 opt. video data ?? // TODO have look to SMPTE
+                                       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;
+                               // 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);
+                               }
+                               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;
+                               }
+                               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
@@ -348,123 +771,204 @@ static int sdimaster_playout(uint8_t *vBuffer, int16_t aBuffer[MAX_AUDIO_STREAMS
        // 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;
-               // printf ("Getting the transmitter event flags.\n");
-               if (ioctl(fh_sdi_dest, SDI_IOC_TXGETEVENTS, &val) < 0) {
+               if (ioctl(fh_sdi_video, SDI_IOC_TXGETEVENTS, &val) < 0) {
                        // Maybe this is not an SDI device...
-
-                       // fprintf (stderr, "SDI output:");
-                       // perror ("unable to get the transmitter event flags");
+                       fprintf(stderr, "SDI VIDEO 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 "
+                               printf("SDI VIDEO driver transmit buffer queue underrun "
                                        "detected.\n");
-                               sleep(5);
                        }
                        if (val & SDI_EVENT_TX_FIFO) {
-                               printf("SDI onboard transmit FIFO underrun detected.\n");
-
+                               printf("SDI VIDEO onboard transmit FIFO underrun detected.\n");
                                // TODO react
                        }
                        if (val & SDI_EVENT_TX_DATA) {
-                               // printf("SDI transmit data change detected.\n");
+                               printf("SDI VIDEO transmit data change detected.\n");
                        }
                }
+               fflush(stdout);
+       }
+
+       // 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 == 1601 || audio_format->samples == 1602 ? 1600 : audio_format->samples; // TODO buffer underrun by NTSC frequencs because of 3/2 pull down
+               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; // TODO sdi board must be pre-configured for 32bit samples!!!!
+
+               // 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++;
+                       }
+
+                       // write pseudo tracks
+                       // now fill rest of audio tracks with NULL or copy of first track
+                       while (stream_number < 4) { // TODO linsys board model 193 have a limit to 4 AES groups (=4streams,8channels)
+
+                               // 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++;
+                       }
+
+                       sample_number++;
+
+//                     // Check for events of the SDI board (only firmware 0.9)
+//                     unsigned int val;
+//                     if (ioctl(fh_sdi_audio, SDI_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 & SDI_EVENT_TX_BUFFER) {
+//                                     printf("SDI AUDIO driver transmit buffer queue underrun "
+//                                             "detected.\n");
+//                             }
+//                             if (val & SDI_EVENT_TX_FIFO) {
+//                                     printf("SDI AUDIO onboard transmit FIFO underrun detected.\n");
+//                                     //TODO react
+//                             }
+//                             if (val & SDI_EVENT_TX_DATA) {
+//                                     printf("SDI AUDIO transmit data change detected.\n");
+//                             }
+//                     }
+               }
        }
 
        return getDBN(my_DBN);
 } // end sdimaster_playout()
 
-// ****************************************************************************************
-// ***************************  Create Line  **********************************************
-// ****************************************************************************************
+
+//****************************************************************************************
+//***************************  Create Line  **********************************************
+//****************************************************************************************
 
 /** generate one SDI line
  * @param *buf: buffer to hold the line
  * @param field: size of the video Buffer
  * @param active: v-blank or active-video
  * @param *video_buffer: video buffer
- * @param audio_buffer: array of 8 channel pairs
+ * @param *audio_buffer2: 1.audio buffer ch1-ch2
+ * @param *audio_buffer1: 2.audio buffer ch2-ch3
  * @param line: linenumber
  * @param AudioGroupCounter: count written AudioGroup
  * @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_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES],
-               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
         *
@@ -474,23 +978,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_buffer[0], audio_buffer[1], 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_buffer[2], audio_buffer[3], 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_buffer[4], audio_buffer[5], 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_buffer[6], audio_buffer[7], AudioGroupCounter, AudioGroups2Write, audio_streams);
 
        // Fill ANC data in until the end (position(p) to `ANCILLARY_DATA_SAMPLES`)
        while (p < (buf + ANCILLARY_DATA_SAMPLES + 4)) {
@@ -498,51 +1031,54 @@ 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;
+       //#########################################################################################
 
-       // 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
+
+                       // shift "<< 2" because 8 bit data in 10 bit word
 
                        // 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;
+                       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
+                       }
 
-                       *p = video_buffer[(linenumber_video * 1440) + ((p - 288) - buf) + 1] << 2; // Cb
+                       *p = video_buffer[(active_video_line * 1440) + ((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[(active_video_line * 1440) + ((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[(active_video_line * 1440) + ((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[(active_video_line * 1440) + ((p - 288) - buf) - 1] << 2; // Y2
                        p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040;
@@ -555,14 +1091,170 @@ 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[MAX_AUDIO_SAMPLES], int16_t audio_buffer_B[MAX_AUDIO_SAMPLES], 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 (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;
 
-       /* ANC Ancillary
-        *
-        *      [ADF][ADF][ADF][DID][DBN][DC][UDW]...[UDW][CS]
+               }
+
+               /* 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)) {
+
+                       if (active_video_line >= info->fmt->active_lines_per_frame) {
+                               active_video_line = info->fmt->active_lines_per_frame - 1;
+                       }
+
+                       //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1;
+                       //                      *p++ = sample > 1440 ? 735 : (video_buffer[sample] << 2);
+                       //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1;
+                       //                      *p++ = sample > 1440 ? 335 : (video_buffer[sample] << 2);
+                       //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1;
+                       //                      *p++ = sample > 1440 ? 793 : (video_buffer[sample] << 2);
+                       //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1;
+                       //                      *p++ = sample > 1440 ? 335 : (video_buffer[sample] << 2);
+
+                       *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1] << 2; // Cb
+                       p++;
+                       // check values, but need manny resources
+                       //                      if (*(p - 1) < 0x040)
+                       //                              *(p - 1) = 0x040;
+                       //                      if (*(p - 1) > 0x3c0)
+                       //                              *(p - 1) = 0x3c0;
+                       //
+                       *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1] << 2; // Y1
+                       p++;
+                       //                      if (*(p - 1) < 0x040)
+                       //                              *(p - 1) = 0x040;
+                       //                      if (*(p - 1) > 0x3ac)
+                       //                              *(p - 1) = 0x3ac;
+                       //
+                       *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1] << 2; // Cr
+                       p++;
+                       //                      if (*(p - 1) < 0x040)
+                       //                              *(p - 1) = 0x040;
+                       //                      if (*(p - 1) > 0x3c0)
+                       //                              *(p - 1) = 0x3c0;
+                       //
+                       *p = video_buffer[(active_video_line * info->fmt->active_samples_per_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;
@@ -570,13 +1262,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;
@@ -587,41 +1274,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
@@ -636,7 +1323,7 @@ static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DB
                        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
@@ -646,10 +1333,10 @@ static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DB
                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 */
 
@@ -660,22 +1347,22 @@ static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DB
 
                        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
+                                       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
+                                       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
+                                       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
+                                       getZBit(sample_number/2), 3, &audio_buffer_B[sample_number]); // right
                        p+=3;
                        counter+=2;
                }
@@ -705,37 +1392,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
@@ -749,11 +1435,16 @@ 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, int32_t audio_sample) {
+ **/
+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)
-       audio_sample <<= 4; // Shift by 4 (louder)
+       int32_t audio_sample = *audio_samplex;
+       audio_sample = audio_sample << 4; // Shift by 4 (louder)
 
        // parity_counter
        int8_t parity_counter = 0;
@@ -761,9 +1452,9 @@ static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int32_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
@@ -774,16 +1465,16 @@ static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int32_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;
@@ -800,30 +1491,30 @@ static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int32_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
@@ -839,13 +1530,13 @@ static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int32_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;
        }
 }
@@ -856,7 +1547,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;
 
@@ -918,43 +1609,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) {
@@ -962,6 +1653,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
@@ -971,7 +1680,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;
 
@@ -988,11 +1698,276 @@ 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:
+               while (p < (buf + samples)) {
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+                       *p++ = 0x200;
+                       *p++ = 0x040;
+               }
+               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;
+}
diff --git a/src/modules/linsys/sdi_generator.h b/src/modules/linsys/sdi_generator.h
new file mode 100644 (file)
index 0000000..0c5ec59
--- /dev/null
@@ -0,0 +1,226 @@
+/**
+ * sdi_generator.h
+ **/
+
+#include <framework/mlt_frame.h>
+#include <framework/mlt_profile.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <pthread.h>
+
+#include <signal.h>
+#include <math.h>
+
+#ifndef SDI_GENERATOR_H_
+#define SDI_GENERATOR_H_
+
+// defines only for SD NTSC (mkline funktion for test pattern)
+#define VERT_BLANKING 0
+#define MAIN_SET 1
+#define CHROMA_SET 2
+#define BLACK_SET 3
+#define BLACK 4
+
+// defines for SD SDI with blanking
+#define ANCILLARY_DATA_SAMPLES 280
+#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)
+
+// Filehandler for sdi output
+static int fh_sdi_video;
+static int fh_sdi_audio;
+
+#define MAX_SAMPLES_PER_LINE (2*2750)
+#define MAX_LINES_PER_FRAME 1125
+#define MAX_AUDIO_STREAMS (8)
+// max. audio samples per frame
+#define MAX_AUDIO_SAMPLES (2002*2)
+/**
+ * 23.98Hz = fix:{2002}
+ * 24Hz = fix:{2000}
+ * 25Hz = fix:{1920}
+ * 29.97Hz = vari:{1601,1602,1602}
+ * 30Hz = fix:{1600}
+ **/
+
+#define MAX_SDI_HEIGHT 1125                    // HD-SDI
+#define MAX_SDI_WIDTH 2750                     // HD-SDI (FMT_1080p24 has up to 2750)
+#define MAX_SDI_FRAMESIZE (MAX_SDI_HEIGHT*MAX_SDI_WIDTH*2) // SDI frame size, (2 Pixels are represented by 4 bytes, yuyv422)
+struct source_format {
+       unsigned int lines_per_frame;
+       unsigned int active_lines_per_frame;
+       unsigned int samples_per_line;
+       unsigned int active_samples_per_line;
+       unsigned int interlaced;
+};
+
+struct audio_format {
+
+       mlt_audio_format aformat; // default: mlt_audio_pcm
+       uint16_t samples; // default 2*1920
+       uint16_t sample_rate; // default 48000
+       int channels; // default 2 (stereo)
+/**
+ * 0 channels = audio disabled, transmit only
+ * 2 channels (stereo)
+ * 4 channels
+ * 6 channels
+ * 8 channels
+ **/
+};
+
+// HD
+static const struct source_format FMT_1080i60 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2200,
+               .active_samples_per_line = 2*1920, .interlaced = 1 };
+
+static const struct source_format FMT_1080i5994 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2200,
+               .active_samples_per_line = 2*1920, .interlaced = 1 };
+
+static const struct source_format FMT_1080i50 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2640,
+               .active_samples_per_line = 2*1920, .interlaced = 1 };
+
+static const struct source_format FMT_1080p30 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2200,
+               .active_samples_per_line = 2*1920, .interlaced = 0 };
+
+static const struct source_format FMT_1080p2997 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2200,
+               .active_samples_per_line = 2*1920, .interlaced = 0 };
+
+static const struct source_format FMT_1080p25 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2640,
+               .active_samples_per_line = 2*1920, .interlaced = 0 };
+
+static const struct source_format FMT_1080p24 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2750,
+               .active_samples_per_line = 2*1920, .interlaced = 0 };
+
+static const struct source_format FMT_1080p2398 = { .lines_per_frame = 1125, .active_lines_per_frame = 1080, .samples_per_line = 2*2750,
+               .active_samples_per_line = 2*1920, .interlaced = 0 };
+
+static const struct source_format FMT_720p60 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*1650,
+               .active_samples_per_line = 2*1280, .interlaced = 0 };
+
+static const struct source_format FMT_720p5994 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*1650,
+               .active_samples_per_line = 2*1280, .interlaced = 0 };
+
+static const struct source_format FMT_720p50 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*1980,
+               .active_samples_per_line = 2*1280, .interlaced = 0 };
+
+static const struct source_format FMT_720p30 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*3300,
+               .active_samples_per_line = 2*1280, .interlaced = 0 };
+
+static const struct source_format FMT_720p2997 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*3300,
+               .active_samples_per_line = 2*1280, .interlaced = 0 };
+
+static const struct source_format FMT_720p25 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*3960,
+               .active_samples_per_line = 2*1280, .interlaced = 0 };
+
+static const struct source_format FMT_720p24 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*4125,
+               .active_samples_per_line = 2*1280, .interlaced = 0 };
+
+static const struct source_format FMT_720p2398 = { .lines_per_frame = 750, .active_lines_per_frame = 720, .samples_per_line = 2*4125,
+               .active_samples_per_line = 2*1280, .interlaced = 0 };
+
+// SD PAL
+static const struct source_format FMT_576i50 = { .lines_per_frame = 625, .active_lines_per_frame = 576, .samples_per_line = 2*864 /*1728*/,
+               .active_samples_per_line = 2*720 /* 720xY, 360xCb, 360xCr */, .interlaced = 1 };
+
+// SD NTSC
+static const struct source_format FMT_480i5994 = { .lines_per_frame = 525, .active_lines_per_frame = 486, .samples_per_line = 2*858 /*1716*/,
+               .active_samples_per_line = 2*720 /* 720xY, 360xCb, 360xCr */, .interlaced = 1 };
+
+struct trs {
+       unsigned short int sav;
+       unsigned short int eav;
+};
+
+static const struct trs FIELD_1_ACTIVE = { .sav = 0x200, .eav = 0x274 };
+static const struct trs FIELD_1_VERT_BLANKING = { .sav = 0x2ac, .eav = 0x2d8 };
+static const struct trs FIELD_2_ACTIVE = { .sav = 0x31c, .eav = 0x368 };
+static const struct trs FIELD_2_VERT_BLANKING = { .sav = 0x3b0, .eav = 0x3c4 };
+
+struct line_info {
+       const struct source_format *fmt;
+       unsigned int ln;
+       const struct trs *xyz;
+       uint8_t blanking;
+};
+
+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 !!!
+
+// buffer for one sdi line
+uint16_t * line_buffer;
+// counter for active line number
+uint16_t active_video_line;
+// buffer for sdi frame size
+uint64_t sdi_frame_size;
+// buffer for the complete SDI frame
+uint8_t * data;
+
+static char * device_file_video;
+static char * device_file_audio;
+static struct line_info info;
+static uint8_t *(*pack)(uint8_t *outbuf, unsigned short int *inbuf, size_t count);
+static size_t elements;
+static unsigned int samples;
+
+// functions
+static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, mlt_profile myProfile);
+
+static int sdimaster_close();
+
+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);
+
+static int mkline(unsigned short int *buf, const struct line_info *info, unsigned int pattern);
+
+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);
+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);
+
+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);
+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 inline uint8_t *pack8(uint8_t *outbuf, uint16_t *inbuf, size_t count); // alias 'pack_uyvy()'
+static inline uint8_t *pack10(uint8_t *outbuf, uint16_t *inbuf, size_t count);
+static inline uint8_t *pack_v210(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);
+
+#endif /* SDI_GENERATOR_H_ */