]> git.sesse.net Git - mlt/blob - src/modules/linsys/sdi_generator.c
f05460054e8a683141f1164db11a62f95b587600
[mlt] / src / modules / linsys / sdi_generator.c
1 /**
2  *
3  * MLT SDI Consumer:
4  * request video and audio data from MLT and generate an SDI stream
5  *
6  * Copyright (C) Broadcasting Center Europe S.A. http://www.bce.lu
7  * an RTL Group Company  http://www.rtlgroup.com
8  * All rights reserved.
9  *
10  * E-mail: support_plasec@bce.lu
11  *
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26  *
27  *
28  * DESCRIPTION:
29  * This software act as interface between the MLT Frameworkas as
30  * MLT Consumer and the Linear Systems Ltd. SMPTE 292M and SMPTE 259M-C boards.
31  *
32  * Linear Systems can be contacted at http://www.linsys.ca
33  *
34  **********************************************************************************
35  *      System : INTeL I686 64Bit
36  *          OS : Linux SuSE Kernel 2.6.27.39-0.2-default
37  *     Compiler: gcc 4.3.2 (c++)
38  **********************************************************************************
39  *     Project : MLT SDI Consumer for SD and HD
40  *  Started by : Thomas Kurpick, Dipl.Inf. (FH)
41  **********************************************************************************
42  *  Supported and tested boards for SD-SDI or HD-SDI Output:
43  *      PCI SDI Master™              (model 107)
44  *      PCIe SDI Master™             (model 159)
45  *      PCIe LP SDI Master™ FD       (model 145)
46  *      PCIe LP SDI Master™ Quad/o   (model 180)
47  *      PCIe LP HD-SDI Master™ O     (model 193)
48  *
49  *  Note: PCIe LP HD-SDI Master™ O (model 193) is an VidPort model and supports an
50  *  seperate video and audio interface. Device file:
51  *              /dev/sdivideotx[]       for active video data
52  *      /dev/sdiaudiotx[]       for pcm audio data
53  *
54  *      This mlt consumer use the following device files:
55  *   /dev/sditx[]         (SD-PAL)      up to 8 x AES (8 x stereo / 16 audio channels)
56  *   /dev/sdivideotx[]    (HD)
57  *   /dev/sdiaudiotx[]    (HD)          up to 4 x AES (4 x stereo / 8 audio channels)
58  *
59  *
60  **********************************************************************************
61  * Last modified by:
62  * Thomas Kurpick                     08.Jan.2010
63  * Ver. 2.0
64  *
65  **********************************************************************************
66  *
67  * Consumer properties:
68  *      'dev_video'
69  *      'dev_audio'
70  *      'blanking'
71  * Only to monitor the SDI output a beta version of jpeg-writer is implemented.
72  *      'jpeg_files' a number for output interval
73  *      'save_jpegs' path for image
74  *
75  * EXAMPLE:
76  *
77  * SDI boards with full frame stream (with blanking):
78  *      melt video.dv -consumer sdi:/dev/sditx0 buffer=0;
79  *      melt video.dv -consumer sdi:/dev/sditx0 buffer=0 blanking=true;
80  *      melt video.dv -consumer sdi dev_video=/dev/sditx0 buffer=0 blanking=true;
81  *      melt video.dv audio_index=all -consumer sdi dev_video=/dev/sditx0 buffer=0 blanking=true;
82  *
83  * SDI boards without full frame stream (without blanking):
84  *  melt -profile atsc_1080i_50 video.mpeg audio_index=1   -consumer sdi dev_video=/dev/sdivideotx0 dev_sdiaudio=/dev/sdiaudiotx0 blanking=false
85  *  melt -profile atsc_1080i_50 video.mpeg audio_index=all -consumer sdi dev_video=/dev/sdivideotx0 dev_sdiaudio=/dev/sdiaudiotx0 blanking=false
86  *  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
87  *
88  *
89  * SDI output formats and MLT profiles:
90  * #####################################################################################################################################################
91  * ########## SMPTE 274M 1920 x 1080 Image Sample Structure ############################################################################################
92  * #####################################################################################################################################################
93  * System No.   System nomenclature             Form of scanning        Frame rate                              Embedded Audio                  MLT profile             Linsys board support (model)
94  *      4                       1920 x 1080/60/I                interlaced                      30 HZ                                   4 x AES (8 channels)    atsc_1080i_60   193
95  *      5                       1920 x 1080/59.94/I             interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    atsc_1080i_5994 193
96  *      6                       1920 x 1080/50/I                interlaced                      25 HZ                                   4 x AES (8 channels)    atsc_1080i_50   193
97  *      7                       1920 x 1080/30/P                progressive                     30 HZ                                   4 x AES (8 channels)    atsc_1080p_30   193
98  *      8                       1920 x 1080/29.97/P             progressive                     30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    atsc_1080p_2997 193
99  *      9                       1920 x 1080/25/P                progressive                     25 HZ                                   4 x AES (8 channels)    atsc_1080p_25   193
100  *      10                      1920 x 1080/24/P                progressive                     24 HZ                                   4 x AES (8 channels)    atsc_1080p_24   193
101  *      11                      1920 x 1080/23.98/P             progressive                     24000/1001 ~ 23.98 HZ   4 x AES (8 channels)    atsc_1080p_2398 193
102  *
103  * #####################################################################################################################################################
104  * ########## SMPTE 296M 1280 × 720 Progressive Image Sample Structure #################################################################################
105  * #####################################################################################################################################################
106  * System No.   System nomenclature             Form of scanning        Frame rate                              Embedded Audio                  MLT profile             Linsys board support (model)
107  * 1                            1280 × 720/60          progressive                     60 HZ                                   4 x AES (8 channels)    atsc_720p_60    193
108  * 2                            1280 × 720/59.94       progressive                     60000/1001 ~ 59.97 HZ   4 x AES (8 channels)    atsc_720p_5994  193
109  * 3                            1280 × 720/50          progressive                     50 HZ                                   4 x AES (8 channels)    atsc_720p_50    193
110  * 4                            1280 × 720/30          progressive                     30 HZ                                   4 x AES (8 channels)    atsc_720p_30    193
111  * 5                            1280 × 720/29.97       progressive                     30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    atsc_720p_2997  193
112  * 6                            1280 × 720/25          progressive                     25 HZ                                   4 x AES (8 channels)    atsc_720p_25    193
113  * 7                            1280 × 720/24          progressive                     24 HZ                                   4 x AES (8 channels)    atsc_720p_24    193
114  * 8                            1280 × 720/23.98       progressive                     24000/1001 ~ 23.98 HZ   4 x AES (8 channels)    atsc_720p_2398  193
115  *
116  * #####################################################################################################################################################
117  * ########## SMPTE 125M 486i 29.97Hz & BT.656 576i 25Hz ###############################################################################################
118  * #####################################################################################################################################################
119  * System No.   System nomenclature             Form of scanning        Frame rate                              Embedded Audio                  MLT profile             Linsys board support (model)
120  * SD PAL               720 × 576/50/I                 interlaced                      25 HZ                                   8 x AES (16 channels)   dv_pal                  180,145,159,107
121  * SD PAL               720 × 576/50/I                 interlaced                      25 HZ                                   4 x AES (8 channels)    dv_pal                  193
122  * 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
123  * SD NTSC              720 × 480/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    sdi_486i_5994   193
124  *
125  **/
126
127 #include "sdi_generator.h"
128
129 /*!/brief initialization of the file handlers for the playout
130  * @param *device_video: file or SDITX device or SDIVIDEOTX device
131  * @param *device_audio: file or SDIAUDIOTX device
132  * @param blanking: true or false (if false the consumer write only active video data without any VANH or HANC)
133  */
134 static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, mlt_profile myProfile, const struct audio_format * audio_format) {
135
136         // set device file
137         device_file_video = device_video;
138         device_file_audio = device_audio;
139
140         // set flag for using of blanking with ancillary data
141         info.blanking = blanking;
142
143         // set pack method for SDI word conversion
144         pack = pack8;
145         //pack = pack10;
146         //pack = pack_v210;
147
148         // check format
149         if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1 && myProfile->progressive
150                         == 0) {
151                 info.fmt = &FMT_1080i60;
152                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_60HZ;
153         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
154                         && myProfile->progressive == 0) {
155                 info.fmt = &FMT_1080i5994;
156                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_59_94HZ;
157         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
158                         && myProfile->progressive == 0) {
159                 info.fmt = &FMT_1080i50;
160                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_50HZ;
161         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
162                         && myProfile->progressive == 1) {
163                 info.fmt = &FMT_1080p30;
164                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_30HZ;
165         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
166                         && myProfile->progressive == 1) {
167                 info.fmt = &FMT_1080p2997;
168                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_29_97HZ;
169         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
170                         && myProfile->progressive == 1) {
171                 info.fmt = &FMT_1080p25;
172                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_25HZ;
173         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24 && myProfile->frame_rate_den == 1
174                         && myProfile->progressive == 1) {
175                 info.fmt = &FMT_1080p24;
176                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_24HZ;
177         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den == 1001
178                         && myProfile->progressive == 1) {
179                 info.fmt = &FMT_1080p2398;
180                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_23_98HZ;
181         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60 && myProfile->frame_rate_den == 1
182                         && myProfile->progressive == 1) {
183                 info.fmt = &FMT_720p60;
184                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_60HZ;
185         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60000 && myProfile->frame_rate_den == 1001
186                         && myProfile->progressive == 1) {
187                 info.fmt = &FMT_720p5994;
188                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_59_94HZ;
189         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 50 && myProfile->frame_rate_den == 1
190                         && myProfile->progressive == 1) {
191                 info.fmt = &FMT_720p50;
192                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_50HZ;
193         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
194                         && myProfile->progressive == 1) {
195                 info.fmt = &FMT_720p30;
196                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_30HZ;
197         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
198                         && myProfile->progressive == 1) {
199                 info.fmt = &FMT_720p2997;
200                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_29_97HZ;
201         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
202                         && myProfile->progressive == 1) {
203                 info.fmt = &FMT_720p25;
204                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_25HZ;
205         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24 && myProfile->frame_rate_den == 1
206                         && myProfile->progressive == 1) {
207                 info.fmt = &FMT_720p24;
208                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_24HZ;
209         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den == 1001
210                         && myProfile->progressive == 1) {
211                 info.fmt = &FMT_720p2398;
212                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_23_98HZ;
213         } else if (myProfile->width == 720 && myProfile->height == 576 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
214                         && myProfile->progressive == 0) {
215                 info.fmt = &FMT_576i50;
216                 sdi_frame_mode = SDIVIDEO_CTL_BT_601_576I_50HZ;
217         } else if (myProfile->width == 720 && myProfile->height == 480 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
218                         && myProfile->progressive == 0) {
219                 info.fmt = &FMT_480i5994;
220                 sdi_frame_mode = SDIVIDEO_CTL_SMPTE_125M_486I_59_94HZ;
221         } else {
222                 printf("Consumer got unknown format: %s", myProfile->description);
223                 info.fmt = &FMT_576i50;
224                 sdi_frame_mode = SDIVIDEO_CTL_BT_601_576I_50HZ;
225         }
226
227         printf("Consumer use format: %s\nProfile: %i %i %i %i %i\n", myProfile->description, myProfile->width, myProfile->height, myProfile->frame_rate_num,
228                         myProfile->frame_rate_den, myProfile->progressive);
229
230         // Check if the format supports own blanking (note: model 193 supports currently only active video at the video device file)
231         if (info.blanking && info.fmt != &FMT_576i50) {
232                 printf("SDI consumer doesn't support blanking(HANC) for the configured SD board and SDI format. Try argument: blanking=false\n");
233                 return EXIT_FAILURE;
234         }
235
236         // if we write our own HANC we need an AES channel status bit array
237         if (info.blanking) {
238
239                 // small description
240                 // http://www.sencore.com/newsletter/Nov05/DigAudioChannelStatusBits.htm
241                 // or
242                 // http://www.sencore.com/uploads/files/DigAudioChannelStatusBits.pdf
243
244                 // create empty AESChannelStatusBitArray
245                 int i = 0;
246                 for (i = 0; i < sizeof(AESChannelStatusBitArray) / sizeof(AESChannelStatusBitArray[0]); i++)
247                         AESChannelStatusBitArray[i] = 0;
248
249                 /**
250                  * Professional Format - Channel Status Bits
251                  **/
252                 ////// Byte 0 //////
253                 AESChannelStatusBitArray[0] = 1; // professional format
254
255                 AESChannelStatusBitArray[1] = 0; // PCM Format
256
257                 AESChannelStatusBitArray[2] = 1; // Emphasis: [100] No Emphasis
258                 AESChannelStatusBitArray[3] = 0; // ^
259                 AESChannelStatusBitArray[4] = 0; // ^
260
261                 AESChannelStatusBitArray[5] = 0; // locked
262
263                 AESChannelStatusBitArray[6] = 0; // sample frequency Fs: [01]48kHz, [10]44kHz, [11]32kHz
264                 AESChannelStatusBitArray[7] = 1; // ^
265                 ////// Byte 1 //////
266                 AESChannelStatusBitArray[8] = 0; // channel mode: [0000] not indicated, [0001]2channels, [0010]1channel mono, ...
267                 AESChannelStatusBitArray[9] = 0; // ^
268                 AESChannelStatusBitArray[10] = 0; // ^
269                 AESChannelStatusBitArray[11] = 1; // ^
270                 ////// Byte 2 //////
271                 AESChannelStatusBitArray[19] = 0; // Encoded sample word length [100]20bits,
272                 AESChannelStatusBitArray[20] = 0; //
273                 AESChannelStatusBitArray[21] = 0; //
274                 ////// Byte 3 //////
275                 AESChannelStatusBitArray[24] = 0; //
276                 AESChannelStatusBitArray[25] = 0; //
277                 AESChannelStatusBitArray[26] = 0; //
278                 AESChannelStatusBitArray[27] = 0; //
279                 AESChannelStatusBitArray[28] = 0; //
280                 AESChannelStatusBitArray[29] = 0; //
281                 AESChannelStatusBitArray[30] = 0; //
282                 AESChannelStatusBitArray[31] = 0; // Multi Channel Mode
283                 ////// Byte 4-21 //////
284                 //AESChannelStatusBitArray[32-179]= 0;
285                 ////// Byte 22 //////
286                 AESChannelStatusBitArray[180] = 0; // Reliability Flags
287                 AESChannelStatusBitArray[181] = 1; // ^
288                 AESChannelStatusBitArray[182] = 1; // ^
289                 AESChannelStatusBitArray[183] = 1; // ^
290                 ////// Byte 23 //////
291                 AESChannelStatusBitArray[184] = 0; // Cyclic Redundancy Check
292                 AESChannelStatusBitArray[185] = 1; // ^
293                 AESChannelStatusBitArray[186] = 0; // ^
294                 AESChannelStatusBitArray[187] = 0; // ^
295                 AESChannelStatusBitArray[188] = 1; // ^
296                 AESChannelStatusBitArray[189] = 0; // ^
297                 AESChannelStatusBitArray[190] = 1; // ^
298                 AESChannelStatusBitArray[191] = 1; // ^
299         }
300
301         // set buffer for one line of active video samples
302         line_buffer = (uint16_t*) calloc(info.fmt->samples_per_line, sizeof(uint16_t));
303
304         // calculate and set buffer for the complete SDI frame
305         if (info.fmt != &FMT_576i50 && info.fmt != &FMT_480i5994) {
306                 if (info.blanking) {
307                         if (pack == pack_v210) {
308                                 samples = (info.fmt->samples_per_line / 96 * 48) + ((info.fmt->samples_per_line % 96) ? 48 : 0);
309                                 sdi_frame_size = samples * info.fmt->lines_per_frame * 8 / 3;
310                         } else {
311                                 sdi_frame_size = info.fmt->samples_per_line * info.fmt->lines_per_frame;
312                         }
313                 } else {
314                         if (pack == pack_v210) {
315                                 samples = (info.fmt->active_samples_per_line / 96 * 48) + ((info.fmt->active_samples_per_line % 96) ? 48 : 0);
316                                 sdi_frame_size = samples * info.fmt->active_lines_per_frame * 8 / 3;
317                         } else {
318                                 sdi_frame_size = info.fmt->active_samples_per_line * info.fmt->active_lines_per_frame;
319                         }
320                 }
321         } else {
322                 if (info.blanking) {
323                         if (pack == pack_v210) {
324                                 sdi_frame_size = info.fmt->samples_per_line * 4 / 3 * info.fmt->lines_per_frame;
325                         } else if (pack == pack8) {
326                                 sdi_frame_size = info.fmt->samples_per_line * info.fmt->lines_per_frame;
327                         } else {
328                                 sdi_frame_size = info.fmt->samples_per_line * 10 / 8 * info.fmt->lines_per_frame;
329                         }
330                 } else {
331                         if (pack == pack_v210) {
332                                 sdi_frame_size = info.fmt->active_samples_per_line * 4 / 3 * info.fmt->active_lines_per_frame;
333                         } else if (pack == pack8) {
334                                 sdi_frame_size = info.fmt->active_samples_per_line * info.fmt->active_lines_per_frame;
335                         } else {
336                                 sdi_frame_size = info.fmt->active_samples_per_line * 10 / 8 * info.fmt->active_lines_per_frame;
337                         }
338                 }
339         }
340
341         // (*10/8 because we store (TOTAL_SAMPLES*TOTAL_LINES) words with 10 bit in this 8 bit array) )
342         if (info.fmt == &FMT_576i50 && info.blanking) {
343                 sdi_frame_size = info.fmt->samples_per_line * 10 / 8 * info.fmt->lines_per_frame;
344         }
345
346         if (info.blanking) {
347                 printf("SDI frame size: %li\n", sdi_frame_size);
348         } else {
349                 printf("Frame size for active video: %li\n", sdi_frame_size);
350         }
351
352         /**
353          * Setup HD-SDI Master device (vidport):
354          *
355          * if device_file_video available then
356          *      if vidport available
357          *              1. setup
358          *      end
359          *      1. open device file handler
360          *
361          *      if device_file_audio available then
362          *              1. setup
363          *              2. open device file handler
364          *      end
365          * end
366          **/
367         if (device_file_video != NULL) {
368
369                 // If we use a Linsys HD board with active video (without blanking) setup the board for the used mode
370                 if (strstr(device_file_video, "sdivideotx") != NULL && !info.blanking) {
371
372                         char * value;
373
374                         // Buffer size
375                         value = itoa(sdi_frame_size);
376                         setSDIVideoProperties(SETTING_BUFFER_SIZE_VIDEO, value, device_video);
377                         free(value);
378
379                         // Frame Mode
380                         value = itoa(sdi_frame_mode);
381                         setSDIVideoProperties(SETTING_FRAME_MODE, value, device_video);
382                         free(value);
383
384                         // Data Mode
385                         if (pack == pack8)
386                                 setSDIVideoProperties(SETTING_DATA_MODE, "0", device_video);
387                         else if (pack == pack_v210)
388                                 setSDIVideoProperties(SETTING_DATA_MODE, "1", device_video);
389                 }
390
391                 // open file handle for SDI(video) output
392                 if ((fh_sdi_video = open(device_file_video, O_WRONLY)) == -1) {
393                         perror(NULL);
394                         printf("\ncould not open video output destination: %s\n", device_file_video);
395                         return EXIT_FAILURE;
396                 }
397                 printf("SDI consumer uses video device file: %s\n", device_file_video);
398
399                 // Check if we have to use a separate device file for audio
400                 if (device_file_audio != NULL) {
401
402                         // set settings for audio device file
403                         if (strstr(device_file_audio, "sdiaudiotx") != NULL && !info.blanking) {
404
405                                 char * value;
406
407                                 /**
408                                  * prepare sample size
409                                  * MLT suports: 16bit, 32bit
410                                  * LINSYS SDI boards supports: 16bit, 24bit, 32bit
411                                  * we set 16bit as default
412                                  **/
413                                 uint8_t sample_size = audio_format->aformat == mlt_audio_s32 ? 32 : 16;
414
415                                 // Buffer size
416                                 // audio buffer per frame (Bytes) = sample rate / frame rate * ( sample size / 1Byte ) x channels
417                                 value = itoa(audio_format->sample_rate / (myProfile->frame_rate_num / myProfile->frame_rate_den) * sample_size / 8 * audio_format->channels );
418                                 setSDIAudioProperties(SETTING_BUFFER_SIZE_AUDIO, value, device_audio);
419                                 free(value);
420
421                                 // channels
422                                 value = itoa(audio_format->channels);
423                                 setSDIAudioProperties(SETTING_CHANNELS, value, device_audio);
424                                 free(value);
425
426                                 // sample rate
427                                 value = itoa(audio_format->sample_rate);
428                                 setSDIAudioProperties(SETTING_SAMPEL_RATE, value, device_audio);
429                                 free(value);
430
431                                 // sample size
432                                 value = itoa(sample_size);
433                                 setSDIAudioProperties(SETTING_SAMPLE_SIZE, value, device_audio);
434                                 free(value);
435                         }
436
437                         // open file handle for audio output
438                         if ((fh_sdi_audio = open(device_file_audio, O_WRONLY)) == -1) {
439                                 perror(NULL);
440                                 printf("\nCould not open audio output destination: %s\n", device_file_audio);
441                                 return EXIT_FAILURE;
442                         }
443                         printf("SDI consumer uses audio device file: %s\n", device_file_audio);
444                 }
445
446         }
447
448         // set buffer for the complete SDI frame
449         data = (uint8_t*) calloc(sdi_frame_size, sizeof(uint8_t));
450
451         return 1;
452 }
453
454 /**
455  * Writes video and audio to specified files in SDI format
456  * @param *vBuffer: Pointer to a video Buffer
457  * @param aBuffer[][]
458  * @param *audio_format: mlt audio_format
459  * @param audio_streams: number of audio streams which have content in aBuffer (available 0-8)
460  * @return current DBN (data block number of SDI frame)
461  **/
462 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,
463                 int my_DBN) {
464
465         // Pointer to the start of data. This is used to fill data line by line
466         uint8_t *p = data;
467
468         //*******************************************************************************************
469         //****************      Build the SDI frame line by line ****************************************
470         //*******************************************************************************************
471
472         /*
473          * if SDI FMT_576i50 for card ASSY 145 or ASSY 159, with access to whole SDI frame buffer
474          *   and device_file_audio must be NULL
475          *      than we write own audio data,
476          * else
477          *      than HD for card ASSY 193
478          */
479         //if (info.fmt == &FMT_576i50 && device_file_audio == NULL && !strcmp(device_file_video, "/dev/sdivideotx0")) {
480         if (info.fmt == &FMT_576i50 && info.blanking) {
481
482                 //counter for the lines
483                 int i = 0;
484                 int16_t AudioGroupCounter = 0;
485
486                 /*#####################################################*/
487                 /*########      FIELD 1                         #######################*/
488                 /*#####################################################*/
489
490                 info.xyz = &FIELD_1_VERT_BLANKING;
491
492                 // line 1-22    VERTICAL_BLANKING:23 lines                              SAV 0x2ac               EAV 0x2d8
493                 for (i = 1; i <= 5; i++) {
494                         create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
495                                         getNumberOfAudioGroups2Write(i), audio_streams);
496                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
497                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
498                 }
499                 for (i = 6; i <= 8; i++) {
500                         create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
501                                         getNumberOfAudioGroups2Write(i), audio_streams);
502                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
503                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
504                 }
505                 for (i = 9; i <= 22; i++) {
506                         create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
507                                         getNumberOfAudioGroups2Write(i), audio_streams);
508                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
509                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
510                 }
511                 // line 23-310  ACTIVE: 287 lines                                               SAV 0x200               EAV 0x274
512                 info.xyz = &FIELD_1_ACTIVE;
513                 int f1counter = 1; // only odd lines
514                 for (i = 23; i <= 310; i++) {
515                         create_SD_SDI_Line(line_buffer, &info, FIELD_1, ACTIVE_VIDEO, vBuffer, aBuffer, i, f1counter, getDBN(my_DBN++), AudioGroupCounter,
516                                         getNumberOfAudioGroups2Write(i), audio_streams);
517                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
518                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
519                         f1counter += 2;
520                 }
521                 i = 311;
522                 // line 311-312 VERTICAL_BLANKING: 2 lines                              SAV 0x2ac               EAV 0x2d8
523                 info.xyz = &FIELD_1_VERT_BLANKING;
524                 create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
525                                 getNumberOfAudioGroups2Write(i), audio_streams);
526                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
527                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
528                 create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
529                                 getNumberOfAudioGroups2Write(i), audio_streams);
530                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
531                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
532
533                 /*#####################################################*/
534                 /*########      FIELD 2        ########################*/
535                 /*#####################################################*/
536
537                 info.xyz = &FIELD_2_VERT_BLANKING;
538
539                 // line 313-336 VERTICAL_BLANKING: 23 lines                             SAV 0x3b0               EAV 0x3c4
540                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
541                                 getNumberOfAudioGroups2Write(i), audio_streams);
542                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
543                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
544
545                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
546                                 getNumberOfAudioGroups2Write(i), audio_streams);
547                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
548                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
549
550                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
551                                 getNumberOfAudioGroups2Write(i), audio_streams);
552                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
553                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
554
555                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
556                                 getNumberOfAudioGroups2Write(i), audio_streams);
557                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
558                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
559
560                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
561                                 getNumberOfAudioGroups2Write(i), audio_streams);
562                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
563                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
564
565                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
566                                 getNumberOfAudioGroups2Write(i), audio_streams);
567                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
568                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
569
570                 // `getAudioGroups2Write()`=0
571                 for (i = 319; i <= 321; i++) {
572                         create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
573                                         getNumberOfAudioGroups2Write(i), audio_streams);
574                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
575                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
576                 }
577                 for (i = 322; i <= 335; i++) {
578                         create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
579                                         getNumberOfAudioGroups2Write(i), audio_streams);
580                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
581                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
582                 }
583                 // line 336-623 ACTIVE: 288 lines                                               SAV 0x31c               EAV 0x368
584                 info.xyz = &FIELD_2_ACTIVE;
585                 int f2counter = 2; // only even Lines
586                 for (i = 336; i <= 623; i++) {
587
588                         create_SD_SDI_Line(line_buffer, &info, FIELD_2, ACTIVE_VIDEO, vBuffer, aBuffer, i, f2counter, getDBN(my_DBN++), AudioGroupCounter,
589                                         getNumberOfAudioGroups2Write(i), audio_streams);
590                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
591                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
592                         f2counter += 2;
593                 }
594                 // line 624-625 VERTICAL_BLANKING: 2 lines                              SAV 0x3b0               EAV 0x3c4
595                 info.xyz = &FIELD_2_VERT_BLANKING;
596                 for (i = 624; i <= 625; i++) {
597                         create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
598                                         getNumberOfAudioGroups2Write(i), audio_streams);
599                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
600                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
601                 }
602
603         } else { // use HD board without blanking
604
605                 // start with first even line
606                 active_video_line = 1;
607
608                 /* *****************************************
609                  * *********** LINE DISTRIBUTION ***********
610                  * *****************************************
611                  *
612                  * << decide form of scanning (interlaced || progressive) >>
613                  * if (interlaced)
614                  *              << decide lines per frame (1125 || 625 || 525) >>
615                  *              if(1125)                                        1080x1920 HD
616                  *                      than create lines
617                  *              else if(625)                              576x720 PAL
618                  *                      than create lines
619                  *              else (525)                                        486x720 NTSC
620                  *                      than create lines
621                  * else (progressive)
622                  *              << decide resolution (1125 || 750) >>
623                  *              if(1125)                                        1080x1920 HD
624                  *                      than create lines
625                  *              else(750)                                        720x1280 HD
626                  *                      than create lines
627                  *
628                  **/
629
630                 // Generate a frame
631                 if (info.fmt->interlaced) {
632
633                         /****************************************
634                          * INTERLACED
635                          ****************************************/
636
637                         if (info.fmt->lines_per_frame == 1125) {
638
639                                 if (info.blanking) {
640                                         elements = info.fmt->samples_per_line;
641                                         info.xyz = &FIELD_1_VERT_BLANKING;
642                                         for (info.ln = 1; info.ln <= 20; info.ln++) {
643                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
644                                                 p = pack(p, line_buffer, elements);
645                                         }
646                                 } else {
647                                         elements = info.fmt->active_samples_per_line;
648                                 }
649                                 info.xyz = &FIELD_1_ACTIVE;
650                                 for (info.ln = 21; info.ln <= 560; info.ln++) {
651                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
652                                         p = pack(p, line_buffer, elements);
653                                         active_video_line += 2;
654                                 }
655                                 if (info.blanking) {
656                                         info.xyz = &FIELD_1_VERT_BLANKING;
657                                         for (info.ln = 561; info.ln <= 563; info.ln++) {
658                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
659                                                 p = pack(p, line_buffer, elements);
660                                         }
661                                         info.xyz = &FIELD_2_VERT_BLANKING;
662                                         for (info.ln = 564; info.ln <= 583; info.ln++) {
663                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
664                                                 p = pack(p, line_buffer, elements);
665                                         }
666                                 }
667                                 // start with first odd line
668                                 active_video_line = 2;
669
670                                 info.xyz = &FIELD_2_ACTIVE;
671                                 for (info.ln = 584; info.ln <= 1123; info.ln++) {
672                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
673                                         p = pack(p, line_buffer, elements);
674                                         active_video_line += 2;
675                                 }
676                                 if (info.blanking) {
677                                         info.xyz = &FIELD_2_VERT_BLANKING;
678                                         for (info.ln = 1124; info.ln <= 1125; info.ln++) {
679                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
680                                                 p = pack(p, line_buffer, elements);
681                                         }
682                                 }
683                         } else if (info.fmt->lines_per_frame == 625) {
684
685                                 elements = info.fmt->active_samples_per_line;
686
687                                 // start with first even line
688                                 active_video_line = 1;
689
690                                 /**
691                                  *  Generate an SDI PAL frame
692                                  **/
693                                 if (info.blanking) {
694                                         info.xyz = &FIELD_1_VERT_BLANKING;
695                                         for (info.ln = 1; info.ln <= 22; info.ln++) {
696                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
697                                                 p = pack(p, line_buffer, elements);
698                                         }
699                                 }
700                                 info.xyz = &FIELD_1_ACTIVE;
701                                 for (info.ln = 23; info.ln <= 310; info.ln++) {
702                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
703                                         p = pack(p, line_buffer, elements);
704                                         active_video_line += 2;
705                                 }
706                                 if (info.blanking) {
707                                         info.xyz = &FIELD_1_VERT_BLANKING;
708                                         for (info.ln = 311; info.ln <= 312; info.ln++) {
709                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
710                                                 p = pack(p, line_buffer, elements);
711                                         }
712                                         info.xyz = &FIELD_2_VERT_BLANKING;
713                                         for (info.ln = 313; info.ln <= 335; info.ln++) {
714                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
715                                                 p = pack(p, line_buffer, elements);
716                                         }
717                                 }
718
719                                 // start with first odd line
720                                 active_video_line = 2;
721
722                                 info.xyz = &FIELD_2_ACTIVE;
723                                 for (info.ln = 336; info.ln <= 623; info.ln++) {
724                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
725                                         p = pack(p, line_buffer, elements);
726                                         active_video_line += 2;
727                                 }
728                                 if (info.blanking) {
729                                         info.xyz = &FIELD_2_VERT_BLANKING;
730                                         for (info.ln = 624; info.ln <= 625; info.ln++) {
731                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
732                                                 p = pack(p, line_buffer, elements);
733                                         }
734                                 }
735                         } else if (info.fmt->lines_per_frame == 525) {
736
737                                 /**
738                                  *  Generate an SDI NTSC frame
739                                  **/
740                                 elements = info.fmt->active_samples_per_line;
741
742                                 active_video_line = 1;
743
744                                 if (info.blanking) {
745                                         info.xyz = &FIELD_1_VERT_BLANKING;
746                                         for (info.ln = 1; info.ln <= 15; info.ln++) {
747                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
748                                                 p = pack(p, line_buffer, elements);
749                                         }
750                                         for (info.ln = 16; info.ln <= 16; info.ln++) {
751                                                 info.xyz = &FIELD_1_ACTIVE;
752                                                 mkline(line_buffer, &info, VERT_BLANKING);
753                                                 p = pack(p, line_buffer, elements);
754                                         }
755                                 }
756
757                                 info.xyz = &FIELD_1_ACTIVE;
758                                 // 3 lines opt. video data
759                                 for (info.ln = 17; info.ln <= 19; info.ln++) {
760                                         mkline(line_buffer, &info, BLACK);
761                                         p = pack(p, line_buffer, elements);
762                                 }
763                                 for (info.ln = 20; info.ln <= 259; info.ln++) {
764                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
765                                         p = pack(p, line_buffer, elements);
766                                         active_video_line += 2;
767                                 }
768                                 if (info.blanking) {
769                                         info.xyz = &FIELD_1_VERT_BLANKING;
770                                         for (info.ln = 260; info.ln <= 261; info.ln++) {
771                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
772                                                 p = pack(p, line_buffer, elements);
773                                         }
774                                         info.xyz = &FIELD_2_VERT_BLANKING;
775                                         // 7 lines vertical data
776                                         for (info.ln = 262; info.ln <= 269; info.ln++) {
777                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
778                                                 p = pack(p, line_buffer, elements);
779                                         }
780                                         // 9 lines opt. video data ?? // TODO have a look to SMPTE
781                                         for (info.ln = 270; info.ln <= 278; info.ln++) {
782                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
783                                                 p = pack(p, line_buffer, elements);
784                                         }
785
786                                 }
787
788                                 active_video_line = 0;
789                                 // 3 lines opt. video data
790                                 info.xyz = &FIELD_2_ACTIVE;
791                                 for (info.ln = 279; info.ln <= 281; info.ln++) {
792                                         mkline(line_buffer, &info, BLACK);
793                                         p = pack(p, line_buffer, elements);
794                                 }
795                                 for (info.ln = 282; info.ln <= 521; info.ln++) {
796                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
797                                         p = pack(p, line_buffer, elements);
798                                         active_video_line += 2;
799                                 }
800                                 if (info.blanking) {
801                                         info.xyz = &FIELD_2_VERT_BLANKING;
802                                         for (info.ln = 522; info.ln <= 525; info.ln++) {
803                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
804                                                 p = pack(p, line_buffer, elements);
805                                         }
806                                 }
807                         }
808                 } else {
809
810                         /****************************************
811                          * PROGRESSIVE
812                          ****************************************/
813
814                         // start with first line numerber
815                         active_video_line = 0;
816
817                         if (info.fmt->lines_per_frame == 1125) {
818                                 if (info.blanking) {
819                                         elements = info.fmt->samples_per_line;
820                                         info.xyz = &FIELD_1_VERT_BLANKING;
821                                         for (info.ln = 1; info.ln <= 41; info.ln++) {
822                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
823                                                 p = pack(p, line_buffer, elements);
824                                         }
825                                 } else {
826                                         elements = info.fmt->active_samples_per_line;
827                                 }
828                                 info.xyz = &FIELD_1_ACTIVE;
829                                 for (info.ln = 42; info.ln <= 1121; info.ln++) {
830                                         create_HD_SDI_Line(line_buffer, &info, active_video_line++, ACTIVE_VIDEO, vBuffer);
831                                         p = pack(p, line_buffer, elements);
832                                 }
833                                 if (info.blanking) {
834                                         info.xyz = &FIELD_1_VERT_BLANKING;
835                                         for (info.ln = 1122; info.ln <= 1125; info.ln++) {
836                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
837                                                 p = pack(p, line_buffer, elements);
838                                         }
839                                 }
840                         } else {
841                                 if (info.blanking) {
842                                         elements = info.fmt->samples_per_line;
843                                         info.xyz = &FIELD_1_VERT_BLANKING;
844                                         for (info.ln = 1; info.ln <= 25; info.ln++) {
845                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
846                                                 p = pack(p, line_buffer, elements);
847                                         }
848                                 } else {
849                                         elements = info.fmt->active_samples_per_line;
850                                 }
851                                 info.xyz = &FIELD_1_ACTIVE;
852                                 for (info.ln = 26; info.ln <= 745; info.ln++) {
853                                         create_HD_SDI_Line(line_buffer, &info, active_video_line++, ACTIVE_VIDEO, vBuffer);
854                                         p = pack(p, line_buffer, elements);
855                                 }
856                                 if (info.blanking) {
857                                         info.xyz = &FIELD_1_VERT_BLANKING;
858                                         for (info.ln = 746; info.ln <= 750; info.ln++) {
859                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
860                                                 p = pack(p, line_buffer, elements);
861                                         }
862                                 }
863                         }
864                 }
865         }
866
867         // sum of bytes that have already been written to file
868         int bytes = 0;
869         // store actual written bytes per 'write()
870         int written_bytes = 0;
871
872         /**
873          * WRITE BUFFER TO FILEHANDLE
874          **/
875         // Write the complete frame to output
876         // The "while" is necessary because the sdi device file does not take the complete frame at once
877         written_bytes = 0;
878         while (bytes < sdi_frame_size) {
879
880                 if ((written_bytes = write(fh_sdi_video, data + bytes, sdi_frame_size - bytes)) < 0) {
881                         fprintf(stderr, "\nunable to write SDI video.\n");
882                         return -1;
883                 }
884                 bytes += written_bytes;
885         }
886
887         // Check for events of the SDI board
888         unsigned int val;
889         if (ioctl(fh_sdi_video, SDI_IOC_TXGETEVENTS, &val) < 0) {
890                 // Maybe this is not an SDI device...
891                 //fprintf(stderr, "SDI VIDEO output:");
892                 //perror("unable to get the transmitter event flags");
893         } else if (val) {
894                 if (val & SDI_EVENT_TX_BUFFER) {
895                         printf("SDI VIDEO driver transmit buffer queue underrun "
896                                 "detected.\n");
897                         fflush(stdout);
898                 }
899                 if (val & SDI_EVENT_TX_FIFO) {
900                         printf("SDI VIDEO onboard transmit FIFO underrun detected.\n");
901                         fflush(stdout);
902                 }
903                 if (val & SDI_EVENT_TX_DATA) {
904                         printf("SDI VIDEO transmit data change detected.\n");
905                         fflush(stdout);
906                 }
907         }
908
909         // if available write audio data
910         if (fh_sdi_audio) {
911
912                 // count writen bytes
913                 written_bytes = 0;
914
915                 // set number of samples and cut by 1600 if NTSC (handle problem of real time encoding of NTSC frequencies)
916                 size_t samples_total_per_track = audio_format->samples;
917                 uint16_t sample_number = 0;
918                 size_t channels_per_track_total = 2;
919                 uint8_t stream_number = 0;
920
921                 //printf("samples_total_per_track:%li\n", samples_total_per_track);
922
923                 // to write blockwise 2 samples of one track we must claculate the number of bytes we want to write per write-session
924                 // 2samples = 2x16Bit = 32Bit = 4Byte
925                 // 2samples = 2x32Bit = 64Bit = 8Byte
926                 // set total bytes per session
927                 size_t bytes_total = 0;
928                 bytes_total = audio_format->aformat == mlt_audio_s16 ? channels_per_track_total * sizeof(int16_t) : bytes_total;
929                 bytes_total = audio_format->aformat == mlt_audio_s32 ? channels_per_track_total * sizeof(int32_t) : bytes_total;
930
931                 // write all samples of all streams interleaved
932                 /**
933                  * aBuffer[track0]+sample1
934                  * aBuffer[track0]+sample2
935                  * aBuffer[track1]+sample1
936                  * aBuffer[track1]+sample2
937                  * aBuffer[track.]+sample1
938                  * aBuffer[track.]+sample2
939                  *
940                  * aBuffer[track0]+sample3
941                  * aBuffer[track0]+sample4
942                  * aBuffer[track1]+sample3
943                  * aBuffer[track1]+sample4
944                  * aBuffer[track.]+sample3
945                  * aBuffer[track.]+sample4
946                  *
947                  * aBuffer[track0]+sample5
948                  * aBuffer[track0]+sample6
949                  * aBuffer[track1]+sample5
950                  * aBuffer[track1]+sample6
951                  * aBuffer[track.]+sample5
952                  * aBuffer[track.]+sample6
953                  **/
954                 int sum_written_bytes = 0;
955                 int sum_written_bytes_a = 0;
956                 int sum_written_bytes_b = 0;
957
958                 // write all samples per track
959                 while (sample_number < samples_total_per_track) {
960
961                         stream_number = 0;
962
963                         /**
964                          * Because we have and write a fix number of audio streams to SDI board:
965                          * we have a actual number of real audio tracks and a rest number of pseudo tracks
966                          **/
967                         // write all streams
968                         while (stream_number < audio_streams) {
969
970                                 // write for every stream n samples
971                                 // n = number of channels per stream
972                                 written_bytes = 0;
973                                 while (written_bytes < bytes_total) {
974                                         written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[stream_number] + sample_number * bytes_total + written_bytes, bytes_total
975                                                         - written_bytes);
976                                 }
977                                 sum_written_bytes += written_bytes;
978                                 sum_written_bytes_a += written_bytes;
979
980                                 stream_number++;
981                         }
982
983                         // write pseudo tracks
984                         // now fill rest of audio tracks(AES frames) with NULL or copy of first track
985                         while (stream_number < audio_format->channels/2) {
986
987                                 // write for every stream n samples
988                                 // n = number of channels per stream
989                                 written_bytes = 0;
990                                 while (written_bytes < bytes_total) {
991                                         written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[0] + sample_number * bytes_total + written_bytes, bytes_total - written_bytes);
992                                 }
993                                 sum_written_bytes += written_bytes;
994                                 sum_written_bytes_b += written_bytes;
995
996                                 stream_number++;
997                         }
998
999                         sample_number++;
1000
1001                         // Check for events of the SDI audio device
1002                         unsigned int val;
1003                         if (ioctl(fh_sdi_audio, SDIAUDIO_IOC_TXGETEVENTS, &val) < 0) {
1004                                 //Maybe this is not an SDI device...
1005                                 //                              fprintf(stderr, "SDI AUDIO output:");
1006                                 //                              perror("unable to get the transmitter event flags");
1007                         } else if (val) {
1008                                 if (val & SDIAUDIO_EVENT_TX_BUFFER) {
1009                                         printf("SDI AUDIO driver transmit buffer queue underrun "
1010                                                 "detected.\n");
1011                                 }
1012                                 if (val & SDIAUDIO_EVENT_TX_FIFO) {
1013                                         printf("SDI AUDIO onboard transmit FIFO underrun detected.\n");
1014                                 }
1015                                 if (val & SDIAUDIO_EVENT_TX_DATA) {
1016                                         printf("SDI AUDIO transmit data change detected.\n");
1017                                 }
1018                         }
1019                 }
1020         }
1021
1022         return getDBN(my_DBN);
1023 } // end sdimaster_playout()
1024
1025
1026 //****************************************************************************************
1027 //***************************  Create Line  **********************************************
1028 //****************************************************************************************
1029
1030 /** generate one SDI line
1031  * @param *buf: buffer to hold the line
1032  * @param field: size of the video Buffer
1033  * @param active: v-blank or active-video
1034  * @param *video_buffer: video buffer
1035  * @param *audio_buffer2: 1.audio buffer ch1-ch2
1036  * @param *audio_buffer1: 2.audio buffer ch2-ch3
1037  * @param line: linenumber
1038  * @param AudioGroupCounter: count written AudioGroup
1039  * @param AudioGroups2Write: number of samples to write
1040  * @param audio_streams: number of audio streams to integrate
1041  */
1042 static inline int create_SD_SDI_Line(uint16_t *buf, const struct line_info *info, int field, int active, uint8_t *video_buffer,
1043                 int16_t audio_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], int linenumber_sdiframe, int active_video_line, int my_DBN, int16_t AudioGroupCounter,
1044                 int16_t AudioGroups2Write, int audio_streams) {
1045
1046         // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
1047         //                                      *************************************************************************
1048         // 625 lines:           | EAV |     ANC      | SAV |            [CbY1CrY2]                                                      |
1049         //                                      *************************************************************************
1050         // 1728 SDI-words:      | 4   |         280              | 4   |                720+360+360=1440                                        |
1051         //                                      *************************************************************************
1052
1053         // points to current position in line
1054         uint16_t *p = buf;
1055
1056         //#########################################################################################
1057         /* TRS Timing Reference Signal for EAV
1058          *              [3ff]
1059          *              [000]
1060          *              [000]
1061          *              [XYZ-Wort]
1062          * */
1063
1064         *p++ = 0x3ff;
1065         *p++ = 0x000;
1066         *p++ = 0x000;
1067         *p++ = info->xyz->eav;
1068         //#########################################################################################
1069
1070         /* ANC Ancillary Data with AES
1071          *
1072          *      [ADF][ADF][ADF][DID][DBN][DC][UDW]...[UDW][CS]
1073          *
1074          * */
1075         // write ANC Data and get number of samples are written
1076         // step with `p` += to the number of written samples
1077
1078         //printf("audio_streams:%i\n",audio_streams);
1079
1080         // 1 stream, Audio Group 1 with AES Frame 1 - 2
1081         if (audio_streams == 1) {
1082                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[0], AudioGroupCounter, AudioGroups2Write);
1083         }
1084         // 2 streams, Audio Group 1 with AES Frame 1 - 2
1085         if (audio_streams == 2) {
1086                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1087         }
1088         // 3 streams, Audio Group 2 with AES Frame 1 - 4
1089         if (audio_streams == 3) {
1090                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1091                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[2], AudioGroupCounter, AudioGroups2Write);
1092         }
1093         // 4 streams, Audio Group 2 with AES Frame 1 - 4
1094         if (audio_streams == 4) {
1095                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1096                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1097         }
1098         // 5 streams, Audio Group 3 with AES Frame 1 - 6
1099         if (audio_streams == 5) {
1100                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1101                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1102                 p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[4], AudioGroupCounter, AudioGroups2Write);
1103         }
1104         // 6 streams, Audio Group 3 with AES Frame 1 - 6
1105         if (audio_streams == 6) {
1106                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1107                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1108                 p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
1109         }
1110         // 7 streams, Audio Group 4 with AES Frame 1 - 7
1111         if (audio_streams == 7) {
1112                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1113                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1114                 p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
1115                 p += writeANC(p, linenumber_sdiframe, 0x2F9, my_DBN, audio_buffer[6], audio_buffer[6], AudioGroupCounter, AudioGroups2Write);
1116         }
1117         // 8 streams, Audio Group 4 with AES Frame 1 - 7
1118         if (audio_streams == 8) {
1119                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1120                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1121                 p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
1122                 p += writeANC(p, linenumber_sdiframe, 0x2F9, my_DBN, audio_buffer[6], audio_buffer[7], AudioGroupCounter, AudioGroups2Write);
1123         }
1124
1125         // Fill ANC data in until the end (position(p) to `ANCILLARY_DATA_SAMPLES`)
1126         while (p < (buf + ANCILLARY_DATA_SAMPLES + 4)) {
1127                 // video color: black
1128                 *p++ = 0x200;
1129                 *p++ = 0x040;
1130         }
1131         //#########################################################################################
1132         // TRS Timing Reference Signal for SAV
1133         *p++ = 0x3ff;
1134         *p++ = 0x000;
1135         *p++ = 0x000;
1136         *p++ = info->xyz->sav;
1137         //#########################################################################################
1138
1139
1140         // Because we skip the first line of video, it can happen that we read too far in the buffer
1141         if (active_video_line >= info->fmt->active_lines_per_frame) {
1142                 active_video_line = info->fmt->active_lines_per_frame - 1; // in SD PAL was set 575
1143         }
1144         //Index of the start of the current line in the video_buffer
1145         int start_of_current_line = active_video_line * info->fmt->active_samples_per_line;
1146
1147         // If VBlank then fill the line with 0x200 and 0x040 (total black)
1148         switch (active) {
1149         default:
1150         case VERT_BLANKING:
1151                 while (p < (buf + info->fmt->samples_per_line)) {
1152                         *p++ = 0x200;
1153                         *p++ = 0x040;
1154                 }
1155                 break;
1156         case ACTIVE_VIDEO:
1157
1158                 // Insert the video into the line
1159                 while (p < (buf + info->fmt->samples_per_line)) { // fill the rest of the line with active video
1160
1161                         // shift "<< 2" because 8 bit data in 10 bit word
1162
1163                         *p = video_buffer[start_of_current_line + ((p - 288) - buf) + 1] << 2; // Cb
1164                         p++;
1165                         if (*(p - 1) < 0x040)
1166                                 *(p - 1) = 0x040; // check values
1167                         if (*(p - 1) > 0x3c0)
1168                                 *(p - 1) = 0x3c0;
1169                         *p = video_buffer[start_of_current_line + ((p - 288) - buf) - 1] << 2; // Y1
1170                         p++;
1171                         if (*(p - 1) < 0x040)
1172                                 *(p - 1) = 0x040;
1173                         if (*(p - 1) > 0x3ac)
1174                                 *(p - 1) = 0x3ac;
1175                         *p = video_buffer[start_of_current_line + ((p - 288) - buf) + 1] << 2; // Cr
1176                         p++;
1177                         if (*(p - 1) < 0x040)
1178                                 *(p - 1) = 0x040;
1179                         if (*(p - 1) > 0x3c0)
1180                                 *(p - 1) = 0x3c0;
1181                         *p = video_buffer[start_of_current_line + ((p - 288) - buf) - 1] << 2; // Y2
1182                         p++;
1183                         if (*(p - 1) < 0x040)
1184                                 *(p - 1) = 0x040;
1185                         if (*(p - 1) > 0x3ac)
1186                                 *(p - 1) = 0x3ac;
1187
1188                 }
1189                 break;
1190         }
1191         return 0;
1192 }
1193
1194 /**
1195  * create_HD_SDI_Line - generate one line
1196  * @buf: pointer to a buffer
1197  * @info: pointer to a line information structure
1198  * @active_video_line
1199  * @active:
1200  * @video_buffer: pattern
1201  *
1202  * Returns a negative error code on failure and zero on success.
1203  **/
1204 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) {
1205         uint16_t *p = buf, *endp, ln;
1206         uint16_t samples = info->blanking ? info->fmt->samples_per_line : info->fmt->active_samples_per_line;
1207
1208         if (active_video_line >= info->fmt->active_lines_per_frame) {
1209                 active_video_line = info->fmt->active_lines_per_frame - 1;
1210         }
1211
1212         int start_of_current_line = active_video_line * info->fmt->active_samples_per_line;
1213
1214         if (info->blanking) {
1215
1216                 // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
1217                 // Example SD PAL:
1218                 //                  *************************************************************************
1219                 // 625 lines:       | EAV |     ANC      | SAV |        [CbY1CrY2]                          |
1220                 //                  *************************************************************************
1221                 // 1728 SDI-words:  | 4   |     280          | 4   |        720+360+360=1440                    |
1222                 //                                      *************************************************************************
1223
1224                 // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
1225                 // Example HD 1080i:
1226                 //                  *************************************************************************
1227                 // 1125 lines:      | EAV | LN  | CRC | ANC | SAV | [CbY1CrY2]                              |
1228                 //                  *************************************************************************
1229                 // 5280 SDI-words:  | 6   | 4   | 4   | 280     | 6   | 1920+720+720=3840                       |
1230                 //                  *************************************************************************
1231
1232                 if (info->fmt == &FMT_576i50) {
1233                         /* EAV */
1234                         *p++ = 0x3ff;
1235                         *p++ = 0x000;
1236                         *p++ = 0x000;
1237                         *p++ = info->xyz->eav;
1238                 } else {
1239                         /* EAV */
1240                         *p++ = 1023;
1241                         *p++ = 1023;
1242                         *p++ = 0;
1243                         *p++ = 0;
1244                         *p++ = 0;
1245                         *p++ = 0;
1246                         *p++ = info->xyz->eav;
1247                         *p++ = info->xyz->eav;
1248                         /* LN */
1249                         ln = ((info->ln & 0x07f) << 2) | (~info->ln & 0x040) << 3;
1250                         *p++ = ln;
1251                         *p++ = ln;
1252                         ln = ((info->ln & 0x780) >> 5) | 0x200;
1253                         *p++ = ln;
1254                         *p++ = ln;
1255                         /* CRC, added by serializer */
1256                         *p++ = 512;
1257                         *p++ = 64;
1258                         *p++ = 512;
1259                         *p++ = 64;
1260
1261                 }
1262
1263                 /* Horizontal blanking */
1264                 while (p < (buf + info->fmt->samples_per_line - info->fmt->active_samples_per_line - 4)) {
1265                         *p++ = 512;
1266                         *p++ = 64;
1267                         *p++ = 512;
1268                         *p++ = 64;
1269                 }
1270
1271                 if (info->fmt == &FMT_576i50) {
1272                         /* SAV */
1273                         *p++ = 0x3ff;
1274                         *p++ = 0x000;
1275                         *p++ = 0x000;
1276                         *p++ = info->xyz->sav;
1277                 } else {
1278                         /* SAV */
1279                         *p++ = 1023;
1280                         *p++ = 1023;
1281                         *p++ = 0;
1282                         *p++ = 0;
1283                         *p++ = 0;
1284                         *p++ = 0;
1285                         *p++ = info->xyz->sav;
1286                         *p++ = info->xyz->sav;
1287                 }
1288         }
1289         /* Active region */
1290         endp = p;
1291
1292         switch (active) {
1293         default:
1294         case VERT_BLANKING:
1295                 while (p < (buf + samples)) {
1296                         *p++ = 512;
1297                         *p++ = 64;
1298                         *p++ = 512;
1299                         *p++ = 64;
1300                 }
1301                 break;
1302         case ACTIVE_VIDEO:
1303
1304         {
1305
1306                 while (p < (buf + samples)) {
1307
1308                         *p = video_buffer[start_of_current_line + (p - buf) + 1] << 2; // Cb
1309                         p++;
1310                         //check values, this needs a lot of resources
1311                         //                      if (*(p - 1) < 0x040)
1312                         //                              *(p - 1) = 0x040;
1313                         //                      if (*(p - 1) > 0x3c0)
1314                         //                              *(p - 1) = 0x3c0;
1315                         //
1316                         *p = video_buffer[start_of_current_line + (p - buf) - 1] << 2; // Y1
1317                         p++;
1318                         //                      if (*(p - 1) < 0x040)
1319                         //                              *(p - 1) = 0x040;
1320                         //                      if (*(p - 1) > 0x3ac)
1321                         //                              *(p - 1) = 0x3ac;
1322                         //
1323                         *p = video_buffer[start_of_current_line + (p - buf) + 1] << 2; // Cr
1324                         p++;
1325                         //                      if (*(p - 1) < 0x040)
1326                         //                              *(p - 1) = 0x040;
1327                         //                      if (*(p - 1) > 0x3c0)
1328                         //                              *(p - 1) = 0x3c0;
1329                         //
1330                         *p = video_buffer[start_of_current_line + (p - buf) - 1] << 2; // Y2
1331                         p++;
1332                         //                      if (*(p - 1) < 0x040)
1333                         //                              *(p - 1) = 0x040;
1334                         //                      if (*(p - 1) > 0x3ac)
1335                         //                              *(p - 1) = 0x3ac;
1336                 }
1337         }
1338                 break;
1339         }
1340         return 0;
1341 }
1342
1343 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,
1344                 int16_t AudioGroups2Write) {
1345
1346         /**
1347          * ANC Ancillary Data (vgl. SMPTE 291-M page 6 )
1348          * [ADF][ADF][ADF][DID][DBN][DC][UDW]...[UDW][CS]
1349          *
1350          **/
1351
1352         // save only current position for return value
1353         uint16_t *pp = p;
1354         // 16bit buffer to write temporarily 10bit word
1355         uint16_t buffer = 0; // set all explicit to zero, special the bit9 for parity
1356         // parity_counter
1357         int8_t parity_counter = 0;
1358
1359         if (AudioGroups2Write > 0) {
1360
1361                 // 3 ADF        (Ancillary Data Flag)
1362                 *p++ = 0x000;
1363                 *p++ = 0x3FF;
1364                 *p++ = 0x3FF;
1365
1366                 // 1 DID        (Data Identification)
1367                 // save DID for checker()
1368                 uint16_t *DID_pointer = p;
1369                 *p++ = DID;// (AES Audio Data, Group
1370                 //              *p++ = 0x2FF; // (AES Audio Data, Group1=0x2FF)
1371                 //              *p++ = 0x1FD;   // (AES Audio Data, Group2=0x1FD)
1372                 //              *p++ = 0x1FB;   // (AES Audio Data, Group3=0x1FB)
1373                 //              *p++ = 0x2F9;   // (AES Audio Data, Group4=0x2F9)
1374
1375                 // 1 DBN        (Data Block Number) inactiv: 1000000000 b9,b8,b7-b0     ; SMPTE 272-M chapter15.1
1376                 //              *p++ = 0x200;
1377
1378                 // 1 DBN (dynamic version0.1-beta ), should start with previus DBN of SDI-Frame
1379                 //      -need "previus DBN" or "current framenumber"
1380                 //              SDI-LINE:       DBN:
1381                 //              [1]                     [1]             << start sdi frame
1382                 //              [2]                     [2]
1383                 //              [.]                     [.]
1384                 //              [255]           [255]
1385                 //              [256]           [1]
1386                 //              [257]           [2]
1387                 //              [.]                     [.]
1388                 //              [510]           [255]
1389                 //              [511]           [1]
1390                 //              [512]           [2]
1391                 //              [.]                     [.]
1392                 //              [625]           [115]   << end sdi frame
1393                 //              [1]                     [116]   << start sdi frame
1394                 // Accuracy of videoline_sdiframe(1 up to 625) to 8bit (1-255)
1395                 //buffer = ((videoline_sdiframe-1) % 255)+1;
1396                 buffer = my_DBN;
1397                 parity_counter = 0;
1398                 // count binary ones for parity
1399                 int i = 0;
1400                 for (i = 0; i < 8; i++) {
1401                         if (buffer & (1 << i))
1402                                 parity_counter++;
1403                 }
1404                 if ((parity_counter % 2) == 0) { //else leave the 0
1405                         buffer += 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1406                 } else {
1407                         buffer += 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1408                 }
1409                 *p++ = buffer;
1410
1411                 // 1 DC         (Data Counter)
1412                 // number of UDW = AudioGroups2Write x 2AESFrames x 2channesl x 3words(X,X+1,X+2)
1413                 buffer = AudioGroups2Write * 2* 2* 3 ; parity_counter= 0;
1414                 // count binary ones for parity
1415                 for (i=0; i<8; i++) {
1416                         if (buffer & (1 << i))
1417                         parity_counter++;
1418                 }
1419                 if ((parity_counter%2)==0) { //else leave the 0
1420                         buffer+= 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1421                 } else {
1422                         buffer+= 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1423                 }
1424                 *p++ = buffer;
1425
1426                 int16_t sample_number=0;
1427                 int16_t counter = 0;
1428                 // write subframes:
1429                 // = n x 1 AudioGroup
1430                 // = n x 2 x 1AESFrame
1431                 // = n x 2 x 2samples
1432                 // = 4 samples
1433                 // = 4 x 3words
1434                 while (counter < AudioGroups2Write*2) { /* 4:3 */
1435
1436                         // write one Audio Group with 4 x AES subframes
1437                         // ( samples for ch01,ch02,ch03,ch04 or ch05,ch06,ch07,ch08 or ch09,ch10,ch11,ch12 or ch13,ch14,ch15,ch16)
1438                         // and use audio_buffer_A(stereo) and audio_buffer_B(stereo)
1439                         // `pack_AES_subframe()` write 3 ANC words (3*10bit), also 1 sample
1440
1441                         sample_number=(AudioGroupCounter*2)+ counter;
1442                         pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 1),
1443                                         getZBit(sample_number/2), 0, &audio_buffer_A[sample_number]); // left
1444                         p+=3; // step 3 words
1445
1446                         sample_number=(AudioGroupCounter*2)+ counter+1;
1447                         pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 2),
1448                                         getZBit(sample_number/2), 1, &audio_buffer_A[sample_number]); // right
1449                         p+=3;
1450
1451                         sample_number=(AudioGroupCounter*2)+ counter;
1452                         pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 3),
1453                                         getZBit(sample_number/2), 2, &audio_buffer_B[sample_number]); // left
1454                         p+=3;
1455
1456                         sample_number=(AudioGroupCounter*2)+ counter+1;
1457                         pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 4),
1458                                         getZBit(sample_number/2), 3, &audio_buffer_B[sample_number]); // right
1459                         p+=3;
1460                         counter+=2;
1461                 }
1462
1463                 // 1 CS         (Checksum from DID - UDW)
1464                 *p++ = checker(DID_pointer);
1465
1466                 // fill ANC with one dummy for videocolor black
1467                 // rest until end of `ANCILLARY_DATA_SAMPLES` will be fill in a loop after call this function
1468                 *p++ = 0x040;
1469         }
1470         return p-pp;
1471 }
1472
1473 // calculate checksumm of ANC (SMPTE 272-M 15.3 Checksum (CS))
1474 static uint16_t checker(uint16_t *DID_pointer) {
1475
1476         // Checksumm
1477         uint16_t cs = 0x00;
1478
1479         // DID - Datablock Identification
1480         cs += (*DID_pointer++) & 0x1FF; // 9 x LSB
1481
1482         // DBN - Datablock Number
1483         cs += (*DID_pointer++) & 0x1FF; // 9 x LSB
1484
1485         // DC - DataCounter
1486         cs += (*DID_pointer) & 0x1FF; // 9 x LSB
1487
1488         // store address of DC an ad to the real value of DC
1489         // DataCounter store
1490         // ´ende´ point to DataCounter
1491         uint16_t *ende = DID_pointer;
1492         // ´ende´ point to last field
1493         ende += (*DID_pointer) & 0xFF; // without parity-Bit and ¬9-Bit
1494
1495         DID_pointer++;
1496
1497         // while DID_pointer point to smaller addres like 'ende'
1498         while (DID_pointer <= ende) {
1499                 cs += (*DID_pointer++) & 0x1FF; // 9 x LSB
1500         }
1501
1502         // limit to 9Bit, because of overflow of sum
1503         cs = cs & 0x1FF;
1504
1505         // set bit10 NOT bit9:
1506         // - cs invert
1507         // - & with bitmask '01 0000 0000'
1508         // - shift rest (1xbit)to left
1509         // - add to cs
1510         cs += ((~cs) & 0x100) << 1;
1511
1512         return cs;
1513 } // end checker
1514
1515
1516 /**
1517  * pack 16bit in AES subframe with 3 words (30 bit) and write in ´*p´
1518  * 10bit-words --> [X],[X+1], [X+2] implements 20bit for audio
1519  *
1520  *                      BIT       9,     8,   7,   6,   5,   4,   3,   2,   1,   0
1521  *                                #####  ###  ###  ###  ###  ###  ###  ###  ###  ###
1522  *      [X]             :       [ !bit8, a5,  a4,  a3,  a2,  a1,  a0,  ch0, ch1, z   ],
1523  *      [X+1]   :       [ !bit8, a14, a13, a12, a11, a10, a9,  a8,  a7 , a6  ],
1524  *      [X+2]   :       [ !bit8, P,   C,   U,   V,   a19, a18, a17, a16, a15 ]
1525  *
1526  * @param *p: Pointer to SDI frame buffer
1527  * @param c: value of AES subframe Channel Status Bit
1528  * @param z: value of AES subframe
1529  * @param ch: channel od AES subframe (value:0,1,2,3)
1530  * @param *audio_samplex: pointer to the audio buffer
1531  **/
1532 static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int16_t *audio_samplex) {
1533
1534         /**
1535          *  NOTE: WE JUST SUPPORT ONLY 16BIT SAMPLE SIZE
1536          **/
1537
1538         // push 16bit up to 20bit(32bit)
1539         int32_t audio_sample = *audio_samplex;
1540         audio_sample = audio_sample << 4; // Shift by 4 (louder)
1541
1542         // parity_counter
1543         int8_t parity_counter = 0;
1544
1545         // 16bit buffer to write 10bit of [X]word,[X+1]word,[X+2]word,
1546         uint16_t buffer = 0;
1547
1548         //#########################################################
1549         //### WORD X  ############################################
1550         //#########################################################
1551         // word X: !bit8, a5, a4, a3, a2, a1, a0, ch1, ch0, z
1552         // SMPTE 272M s.7
1553         buffer = z; // z bit every 192bit = 1
1554         buffer += ch << 1; // ch1 - ch0
1555         buffer += (audio_sample & 0x3f) << 3; // a5 - a0
1556         buffer += ((~buffer) & 0x100) << 1; // !bit8
1557
1558         // write word ´X´
1559         *p++ = buffer;
1560
1561         // count ones
1562         int i = 0;
1563         for (i = 0; i < 9; i++) {
1564                 if (buffer & 1 << i)
1565                         parity_counter++;
1566         }
1567
1568         //#########################################################
1569         //### WORD X+1 ############################################
1570         //#########################################################
1571         // word X+1: !bit8, a14, a13, a12, a11, a10, a9, a8, a7, a6
1572         // SMPTE 272M s.7
1573         buffer = 0;
1574         buffer += (audio_sample >> 6) & 0x1ff; // a14 - a6
1575         buffer += ((~buffer) & 0x100) << 1; // !bit8
1576
1577         // write word ´X+1´
1578         *p++ = buffer;
1579
1580         // count ones (zähle Einsen)
1581         i = 0;
1582         for (i = 0; i < 9; i++) {
1583                 if (buffer & 1 << i)
1584                         parity_counter++;
1585         }
1586
1587         //#########################################################
1588         //### WORD X+2 ############################################
1589         //#########################################################
1590         // word X+2: !bit8, P, C, U, V, a19, a18, a17, a16, a15
1591         // SMPTE 272M s.7
1592         buffer = 0;
1593         buffer += (audio_sample >> 15) & 0x01F; // a15 - a19
1594         // default of [V][U][C] bits = `0`
1595         //buffer += 1<<5;       // V (AES sample validity bit)
1596         //buffer += 1<<6;       // U (AES user bit)
1597         //buffer += 1<<7;       // C (AES audio channel status bit)
1598         buffer += c << 7; // C (AES audio channel status bit)
1599
1600         // count ones (zähle Einsen)
1601         for (i = 0; i < 8; i++) {
1602                 if (buffer & 1 << i)
1603                         parity_counter++;
1604         }
1605
1606         //      if (!parity_counter%2) //else leave the 0
1607         //              buffer+= 1 << 8; // P (AES even parity bit)
1608         //
1609         //      buffer += ((~buffer) & 0x100 )<<1; // !bit8
1610         if ((parity_counter % 2) == 0) { //else leave the 0
1611                 buffer += 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1612         } else {
1613                 buffer += 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1614         }
1615         *p++ = buffer;
1616
1617         // write word ´X+2´
1618         *p++ = buffer;
1619
1620         return 1;
1621 }
1622
1623 static uint8_t getZBit(int sample_number) {
1624
1625         // start in SDI line 6 also 18samples later
1626         //sample_number+=192-18;
1627
1628         if (sample_number % 192 == 0) {
1629                 //printf("1 %i\n", sample_number);
1630                 return 1;
1631         } else {
1632                 //printf("0");
1633                 return 0;
1634         }
1635 }
1636
1637 static uint8_t getChannelStatusBit(uint16_t sample_number, uint8_t ch) {
1638
1639         // return value
1640         uint8_t AESChannelStatusBit = 0;
1641
1642         // start in SDI line 6 also 18samples later
1643         //AESChannelStatusBit=((sample_number+192-18)%192);
1644         // interval in 192bit
1645         AESChannelStatusBit = sample_number % 192;
1646
1647         // when mulichannelmode is true
1648         if (AESChannelStatusBitArray[31] == 1) {
1649                 // set bits for channel
1650                 if (AESChannelStatusBit == 30 && ch == 2)
1651                         return 1;
1652                 if (AESChannelStatusBit == 30 && ch == 4)
1653                         return 1;
1654                 if (AESChannelStatusBit == 29 && (ch == 4))
1655                         return 1;
1656                 if (AESChannelStatusBit == 29 && (ch == 3))
1657                         return 1;
1658         }
1659         return AESChannelStatusBitArray[AESChannelStatusBit];
1660 }
1661
1662 static int16_t getNumberOfAudioGroups2Write(int linenumber) {
1663
1664         // `4:3_VTR`-distribution
1665         if (linenumber >= 11 && linenumber <= 95) {
1666                 if ((linenumber - 11) % 14 == 0) {
1667                         return 4;
1668                 } else {
1669                         return 3;
1670                 }
1671         } else if (linenumber >= 108 && linenumber <= 220) {
1672                 if ((linenumber - 10) % 14 == 0) {
1673                         return 4;
1674                 } else {
1675                         return 3;
1676                 }
1677         } else if (linenumber >= 233 && linenumber <= 345) {
1678                 if ((linenumber - 9) % 14 == 0) {
1679                         return 4;
1680                 } else {
1681                         return 3;
1682                 }
1683         } else if (linenumber >= 358 && linenumber <= 470) {
1684                 if ((linenumber - 8) % 14 == 0) {
1685                         return 4;
1686                 } else {
1687                         return 3;
1688                 }
1689         } else if (linenumber >= 483 && linenumber <= 595) {
1690                 if ((linenumber - 7) % 14 == 0) {
1691                         return 4;
1692                 } else {
1693                         return 3;
1694                 }
1695         } else if (linenumber >= 608 && linenumber <= 622) {
1696                 if ((linenumber - 6) % 14 == 0) {
1697                         return 4;
1698                 } else {
1699                         return 3;
1700                 }
1701         } else {
1702                 return 3;
1703         }
1704
1705         //      // `4:3`-distribution
1706         //      if(linenumber<=315){
1707         //              if(linenumber>=6 && linenumber<=8){
1708         //                      return 0;
1709         //              }
1710         //              if((linenumber+5)%10==0){
1711         //                      return 4;
1712         //              }else{
1713         //                      return 3;
1714         //              }
1715         //      }else{
1716         //              if(linenumber>=319 && linenumber<=321){
1717         //                      return 0;
1718         //              }
1719         //              if((linenumber-8)%10==0){
1720         //                      return 4;
1721         //              }else{
1722         //                      return 3;
1723         //              }
1724         //      }
1725
1726         //      // full-distribution
1727         //      if(linenumber<=45){
1728         //              return 4;
1729         //      }else{
1730         //              return 3;
1731         //      }
1732
1733         //      // fullhalf-distribution
1734         //      if (linenumber==625)
1735         //              return 4;
1736         //
1737         //      if (linenumber%14==0) {
1738         //              return 4;
1739         //      } else {
1740         //              return 3;
1741         //      }
1742
1743 }
1744 static uint8_t getDBN(int my_DBN) {
1745
1746         return ((my_DBN - 1) % 255) + 1;
1747 }
1748
1749 /**
1750  * pack8 - pack a line of 8-bit data
1751  * @outbuf: pointer to the output buffer
1752  * @inbuf: pointer to the input buffer
1753  * @count: number of elements in the buffer
1754  *
1755  * Returns a pointer to the next output location.
1756  **/
1757 static inline uint8_t *
1758 pack8(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
1759         uint16_t *inp = inbuf;
1760         uint8_t *outp = outbuf;
1761
1762         while (inp < (inbuf + count)) {
1763                 *outp++ = *inp++ >> 2;
1764         }
1765         return outp;
1766 }
1767
1768 /**
1769  * pack10 - pack a line of 10-bit data
1770  * @outbuf: pointer to the output buffer
1771  * @inbuf: pointer to the input buffer
1772  * @count: number of elements in the buffer
1773  *
1774  * Returns a pointer to the next output location.
1775  **/
1776 static inline uint8_t * pack10(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
1777
1778         uint16_t *inp = inbuf;
1779         uint8_t *outp = outbuf;
1780
1781         while (inp < (inbuf + count)) {
1782                 *outp++ = *inp & 0xff;
1783                 *outp = *inp++ >> 8;
1784                 *outp++ += (*inp << 2) & 0xfc;
1785                 *outp = *inp++ >> 6;
1786                 *outp++ += (*inp << 4) & 0xf0;
1787                 *outp = *inp++ >> 4;
1788                 *outp++ += (*inp << 6) & 0xc0;
1789                 *outp++ = *inp++ >> 2;
1790         }
1791
1792         return outp;
1793 }
1794 /**
1795  * pack_v210 - pack a line of v210 data
1796  * @outbuf: pointer to the output buffer
1797  * @inbuf: pointer to the input buffer
1798  * @count: number of elements in the buffer
1799  *
1800  * Returns a pointer to the next output location.
1801  **/
1802 static inline uint8_t * pack_v210(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
1803
1804         uint16_t *inp = inbuf;
1805         uint8_t *outp = outbuf;
1806
1807         count = (count / 96) * 96 + ((count % 96) ? 96 : 0);
1808         while (inp < (inbuf + count)) {
1809                 *outp++ = *inp & 0xff;
1810                 *outp = *inp++ >> 8;
1811                 *outp++ += (*inp << 2) & 0xfc;
1812                 *outp = *inp++ >> 6;
1813                 *outp++ += (*inp << 4) & 0xf0;
1814                 *outp++ = *inp++ >> 4;
1815         }
1816         return outp;
1817 }
1818
1819 // Clean up
1820 static int sdimaster_close() {
1821
1822         free(line_buffer);
1823         free(data);
1824
1825         if (fh_sdi_audio)
1826                 close(fh_sdi_audio);
1827         if (fh_sdi_video)
1828                 close(fh_sdi_video);
1829
1830         return 1;
1831 }
1832
1833 /**
1834  * mkline - generate one line
1835  * @buf: pointer to a buffer
1836  * @info: pointer to a line information structure
1837  * @pattern: pattern
1838  *
1839  * Returns a negative error code on failure and zero on success.
1840  **/
1841 static int mkline(unsigned short int *buf, const struct line_info *info, unsigned int pattern) {
1842         const unsigned int b = 205;
1843         unsigned short int *p = buf, *endp;
1844         unsigned int samples = info->blanking ? info->fmt->samples_per_line : info->fmt->active_samples_per_line;
1845
1846         if (info->blanking) {
1847                 /* EAV */
1848                 *p++ = 0x3ff;
1849                 *p++ = 0x000;
1850                 *p++ = 0x000;
1851                 *p++ = info->xyz->eav;
1852                 /* Horizontal blanking */
1853                 while (p < (buf + 272)) {
1854                         *p++ = 0x200;
1855                         *p++ = 0x040;
1856                         *p++ = 0x200;
1857                         *p++ = 0x040;
1858                 }
1859                 /* SAV */
1860                 *p++ = 0x3ff;
1861                 *p++ = 0x000;
1862                 *p++ = 0x000;
1863                 *p++ = info->xyz->sav;
1864         }
1865         /* Active region */
1866         endp = p;
1867         switch (pattern) {
1868         default:
1869         case VERT_BLANKING:
1870                 while (p < (buf + samples)) {
1871                         *p++ = 0x200;
1872                         *p++ = 0x040;
1873                         *p++ = 0x200;
1874                         *p++ = 0x040;
1875                 }
1876                 break;
1877         case BLACK:
1878                 while (p < (buf + samples)) {
1879                         *p++ = 0x200;
1880                         *p++ = 0x040;
1881                         *p++ = 0x200;
1882                         *p++ = 0x040;
1883                 }
1884                 break;
1885         case MAIN_SET:
1886                 /* 75% gray */
1887                 endp += b + 1;
1888                 while (p < endp) {
1889                         *p++ = 512;
1890                         *p++ = 721;
1891                         *p++ = 512;
1892                         *p++ = 721;
1893                 }
1894                 /* 75% yellow */
1895                 endp += b + 1;
1896                 while (p < endp) {
1897                         *p++ = 176;
1898                         *p++ = 646;
1899                         *p++ = 567;
1900                         *p++ = 646;
1901                 }
1902                 /* 75% cyan */
1903                 endp += b + 1;
1904                 while (p < endp) {
1905                         *p++ = 625;
1906                         *p++ = 525;
1907                         *p++ = 176;
1908                         *p++ = 525;
1909                 }
1910                 /* 75% green */
1911                 endp += b - 1;
1912                 while (p < endp) {
1913                         *p++ = 289;
1914                         *p++ = 450;
1915                         *p++ = 231;
1916                         *p++ = 450;
1917                 }
1918                 /* 75% magenta */
1919                 endp += b + 1;
1920                 while (p < endp) {
1921                         *p++ = 735;
1922                         *p++ = 335;
1923                         *p++ = 793;
1924                         *p++ = 335;
1925                 }
1926                 /* 75% red */
1927                 endp += b + 1;
1928                 while (p < endp) {
1929                         *p++ = 399;
1930                         *p++ = 260;
1931                         *p++ = 848;
1932                         *p++ = 260;
1933                 }
1934                 /* 75% blue */
1935                 while (p < (buf + samples)) {
1936                         *p++ = 848;
1937                         *p++ = 139;
1938                         *p++ = 457;
1939                         *p++ = 139;
1940                 }
1941                 break;
1942         case CHROMA_SET:
1943                 /* 75% blue */
1944                 endp += b + 1;
1945                 while (p < endp) {
1946                         *p++ = 848;
1947                         *p++ = 139;
1948                         *p++ = 457;
1949                         *p++ = 139;
1950                 }
1951                 /* black */
1952                 endp += b + 1;
1953                 while (p < endp) {
1954                         *p++ = 0x200;
1955                         *p++ = 0x040;
1956                         *p++ = 0x200;
1957                         *p++ = 0x040;
1958                 }
1959                 /* 75% magenta */
1960                 endp += b + 1;
1961                 while (p < endp) {
1962                         *p++ = 735;
1963                         *p++ = 335;
1964                         *p++ = 793;
1965                         *p++ = 335;
1966                 }
1967                 /* black */
1968                 endp += b - 1;
1969                 while (p < endp) {
1970                         *p++ = 0x200;
1971                         *p++ = 0x040;
1972                         *p++ = 0x200;
1973                         *p++ = 0x040;
1974                 }
1975                 /* 75% cyan */
1976                 endp += b + 1;
1977                 while (p < endp) {
1978                         *p++ = 625;
1979                         *p++ = 525;
1980                         *p++ = 176;
1981                         *p++ = 525;
1982                 }
1983                 /* black */
1984                 endp += b + 1;
1985                 while (p < endp) {
1986                         *p++ = 0x200;
1987                         *p++ = 0x040;
1988                         *p++ = 0x200;
1989                         *p++ = 0x040;
1990                 }
1991                 /* 75% gray */
1992                 while (p < (buf + samples)) {
1993                         *p++ = 512;
1994                         *p++ = 721;
1995                         *p++ = 512;
1996                         *p++ = 721;
1997                 }
1998                 break;
1999         case BLACK_SET:
2000                 /* -I */
2001                 endp += 257;
2002                 while (p < endp) {
2003                         *p++ = 624;
2004                         *p++ = 231;
2005                         *p++ = 390;
2006                         *p++ = 231;
2007                 }
2008                 /* white */
2009                 endp += 257;
2010                 while (p < endp) {
2011                         *p++ = 0x200;
2012                         *p++ = 940;
2013                         *p++ = 0x200;
2014                         *p++ = 940;
2015                 }
2016                 /* +Q */
2017                 endp += 257;
2018                 while (p < endp) {
2019                         *p++ = 684;
2020                         *p++ = 177;
2021                         *p++ = 591;
2022                         *p++ = 177;
2023                 }
2024                 /* black */
2025                 endp += 257;
2026                 while (p < endp) {
2027                         *p++ = 0x200;
2028                         *p++ = 0x040;
2029                         *p++ = 0x200;
2030                         *p++ = 0x040;
2031                 }
2032                 /* blacker than black */
2033                 endp += 68;
2034                 while (p < endp) {
2035                         *p++ = 0x200;
2036                         *p++ = 29;
2037                         *p++ = 0x200;
2038                         *p++ = 29;
2039                 }
2040                 /* black */
2041                 endp += 68 + 2;
2042                 while (p < endp) {
2043                         *p++ = 0x200;
2044                         *p++ = 0x040;
2045                         *p++ = 0x200;
2046                         *p++ = 0x040;
2047                 }
2048                 /* whiter than black */
2049                 endp += 68;
2050                 while (p < endp) {
2051                         *p++ = 0x200;
2052                         *p++ = 99;
2053                         *p++ = 0x200;
2054                         *p++ = 99;
2055                 }
2056                 /* black */
2057                 while (p < (buf + samples)) {
2058                         *p++ = 0x200;
2059                         *p++ = 0x040;
2060                         *p++ = 0x200;
2061                         *p++ = 0x040;
2062                 }
2063                 break;
2064         }
2065         return 0;
2066 }
2067
2068 static int setSDIVideoProperties(enum sdi_setting_video_e setting, char * value, char * device) {
2069
2070         const char fmt[] = "/sys/class/sdivideo/sdivideo%cx%i/%s";
2071         struct stat buf;
2072         int num;
2073         char type, name[256], data[256];
2074         char *endptr;
2075
2076         /* Get the sysfs info */
2077         memset(&buf, 0, sizeof(buf));
2078
2079         /**
2080          * Stat the file, fills the structure with info about the file
2081          * Get the major number from device node
2082          **/
2083         if (stat(device, &buf) < 0) {
2084                 fprintf(stderr, "%s: ", device);
2085                 perror("unable to get the file status");
2086                 return -1;
2087         }
2088
2089         /* Check if it is a character device or not */
2090         if (!S_ISCHR (buf.st_mode)) {
2091                 fprintf(stderr, "%s: not a character device\n", device);
2092                 return -1;
2093         }
2094
2095         /* Check the minor number to determine if it is a receive or transmit device */
2096         type = (buf.st_rdev & 0x0080) ? 'r' : 't';
2097
2098         /* Get the receiver or transmitter number */
2099         num = buf.st_rdev & 0x007f;
2100
2101         /* Build the path to sysfs file */
2102         snprintf(name, sizeof(name), fmt, type, num, "dev");
2103         memset(data, 0, sizeof(data));
2104
2105         /* Read sysfs file (dev) */
2106         if (util_read(name, data, sizeof(data)) < 0) {
2107                 fprintf(stderr, "%s: ", device);
2108                 perror("unable to get the device number");
2109                 return -1;
2110         }
2111         /* Compare the major number taken from sysfs file to the one taken from device node */
2112         if (strtoul(data, &endptr, 0) != (buf.st_rdev >> 8)) {
2113                 fprintf(stderr, "%s: not a SMPTE 292M/SMPTE 259M-C device\n", device);
2114                 return -1;
2115         }
2116         if (*endptr != ':') {
2117                 fprintf(stderr, "%s: error reading %s\n", device, name);
2118                 return -1;
2119         }
2120
2121         // Which setting do we write
2122         if (setting == SETTING_BUFFER_NUMBER_VIDEO) {
2123                 snprintf(name, sizeof(name), fmt, type, num, "buffers");
2124                 snprintf(data, sizeof(data), "%s\n", value);
2125                 if (util_write(name, data, sizeof(data)) < 0) {
2126                         fprintf(stderr, "%s: ", device);
2127                         perror("unable to set the number of buffers");
2128                         return -1;
2129                 }
2130                 printf("\tSet number of buffers = %s\n", value);
2131         } else if (setting == SETTING_BUFFER_SIZE_VIDEO) {
2132                 snprintf(name, sizeof(name), fmt, type, num, "bufsize");
2133                 snprintf(data, sizeof(data), "%s\n", value);
2134                 if (util_write(name, data, sizeof(data)) < 0) {
2135                         fprintf(stderr, "%s: ", device);
2136                         perror("unable to set the buffer size");
2137                         return -1;
2138                 }
2139                 printf("\tSet buffer size = %s Bytes\n", value);
2140         } else if (setting == SETTING_CLOCK_SOURCE) {
2141                 snprintf(name, sizeof(name), fmt, type, num, "clock_source");
2142                 snprintf(data, sizeof(data), "%s\n", value);
2143                 if (util_write(name, data, sizeof(data)) < 0) {
2144                         fprintf(stderr, "%s: ", device);
2145                         perror("unable to set the clock source");
2146                         return -1;
2147                 }
2148                 printf("\tSet clock source = %s\n", value);
2149         } else if (setting == SETTING_DATA_MODE) {
2150                 snprintf(name, sizeof(name), fmt, type, num, "mode");
2151                 snprintf(data, sizeof(data), "%s\n", value);
2152                 if (util_write(name, data, sizeof(data)) < 0) {
2153                         fprintf(stderr, "%s: ", device);
2154                         perror("unable to set the interface operating mode");
2155                         return -1;
2156                 }
2157                 printf("\tSet data mode = %s\n", value);
2158         } else if (setting == SETTING_FRAME_MODE) {
2159                 snprintf(name, sizeof(name), fmt, type, num, "frame_mode");
2160                 snprintf(data, sizeof(data), "%s\n", value);
2161                 if (util_write(name, data, sizeof(data)) < 0) {
2162                         fprintf(stderr, "%s: ", device);
2163                         perror("unable to set the interface frame mode");
2164                         return -1;
2165                 }
2166                 printf("\tSet frame mode = %s\n", value);
2167         }
2168
2169         return 0;
2170
2171 }
2172
2173 static int setSDIAudioProperties(enum sdi_setting_audio_e setting, char * value, char * device) {
2174         const char fmt[] = "/sys/class/sdiaudio/sdiaudio%cx%i/%s";
2175         struct stat buf;
2176         int num;
2177         char type, name[256], data[256];
2178         char *endptr;
2179
2180         /* Get the sysfs info */
2181         memset(&buf, 0, sizeof(buf));
2182         if (stat(device, &buf) < 0) {
2183                 fprintf(stderr, "%s: ", device);
2184                 perror("unable to get the file status");
2185                 return -1;
2186         }
2187         if (!S_ISCHR (buf.st_mode)) {
2188                 fprintf(stderr, "%s: not a character device\n", device);
2189                 return -1;
2190         }
2191         type = (buf.st_rdev & 0x0080) ? 'r' : 't';
2192         num = buf.st_rdev & 0x007f;
2193         snprintf(name, sizeof(name), fmt, type, num, "dev");
2194         memset(data, 0, sizeof(data));
2195         if (util_read(name, data, sizeof(data)) < 0) {
2196                 fprintf(stderr, "%s: ", device);
2197                 perror("unable to get the device number");
2198                 return -1;
2199         }
2200
2201         if (strtoul(data, &endptr, 0) != (buf.st_rdev >> 8)) {
2202                 fprintf(stderr, "%s: not an audio device\n", device);
2203                 return -1;
2204         }
2205         if (*endptr != ':') {
2206                 fprintf(stderr, "%s: error reading %s\n", device, name);
2207                 return -1;
2208         }
2209
2210         if (setting == SETTING_BUFFER_NUMBER_AUDIO) {
2211                 snprintf(name, sizeof(name), fmt, type, num, "buffers");
2212                 snprintf(data, sizeof(data), "%s\n", value);
2213
2214                 if (util_write(name, data, sizeof(data)) < 0) {
2215                         fprintf(stderr, "%s: ", device);
2216                         perror("unable to set the number of buffers");
2217                         return -1;
2218                 }
2219                 printf("\tSet number of buffers = %s\n", value);
2220         } else if (setting == SETTING_BUFFER_SIZE_AUDIO) {
2221                 snprintf(name, sizeof(name), fmt, type, num, "bufsize");
2222                 snprintf(data, sizeof(data), "%s\n", value);
2223                 if (util_write(name, data, sizeof(data)) < 0) {
2224                         fprintf(stderr, "%s: ", device);
2225                         perror("unable to set the buffer size");
2226                         return -1;
2227                 }
2228                 printf("\tSet buffer size = %s Bytes\n", value);
2229         } else if (setting == SETTING_SAMPLE_SIZE) {
2230                 snprintf(name, sizeof(name), fmt, type, num, "sample_size");
2231                 snprintf(data, sizeof(data), "%s\n", value);
2232                 if (util_write(name, data, sizeof(data)) < 0) {
2233                         fprintf(stderr, "%s: ", device);
2234                         perror("unable to set the interface audio sample size");
2235                         return -1;
2236                 }
2237                 switch (atol(value)) {
2238                 case SDIAUDIO_CTL_AUDSAMP_SZ_16:
2239                         printf("\tAssuming 16-bit audio.\n");
2240                         break;
2241                 case SDIAUDIO_CTL_AUDSAMP_SZ_24:
2242                         printf("\tAssuming 24-bit audio.\n");
2243                         break;
2244                 case SDIAUDIO_CTL_AUDSAMP_SZ_32:
2245                         printf("\tAssuming 32-bit audio.\n");
2246                         break;
2247                 default:
2248                         printf("\tSet audio sample size = %lu.\n", atol(value));
2249                         break;
2250                 }
2251         } else if (setting == SETTING_SAMPEL_RATE) {
2252                 snprintf(name, sizeof(name), fmt, type, num, "sample_rate");
2253                 snprintf(data, sizeof(data), "%lu\n", atol(value));
2254                 if (util_write(name, data, sizeof(data)) < 0) {
2255                         fprintf(stderr, "%s: ", device);
2256                         perror("unable to set the interface audio sample rate");
2257                         return -1;
2258                 }
2259                 switch (atoi(value)) {
2260                 case 32000:
2261                         printf("\tAssuming 32 kHz audio.\n");
2262                         break;
2263                 case 44100:
2264                         printf("\tAssuming 44.1 kHz audio.\n");
2265                         break;
2266                 case 48000:
2267                         printf("\tAssuming 48 kHz audio.\n");
2268                         break;
2269                 default:
2270                         printf("\tSet audio sample rate = %lu.\n", atol(value));
2271                         break;
2272                 }
2273         } else if (setting == SETTING_CHANNELS) {
2274                 snprintf(name, sizeof(name), fmt, type, num, "channels");
2275                 snprintf(data, sizeof(data), "%lu\n", atol(value));
2276                 if (util_write(name, data, sizeof(data)) < 0) {
2277                         fprintf(stderr, "%s: ", device);
2278                         perror("unable to set "
2279                                 "the interface audio channel enable");
2280                         return -1;
2281                 }
2282                 switch (atol(value)) {
2283                 case SDIAUDIO_CTL_AUDCH_EN_0:
2284                         printf("\tDisabling audio.\n");
2285                         break;
2286                 case SDIAUDIO_CTL_AUDCH_EN_2:
2287                         printf("\tAssuming 2 channels of audio.\n");
2288                         break;
2289                 case SDIAUDIO_CTL_AUDCH_EN_4:
2290                         printf("\tAssuming 4 channels of audio.\n");
2291                         break;
2292                 case SDIAUDIO_CTL_AUDCH_EN_6:
2293                         printf("\tAssuming 6 channels of audio.\n");
2294                         break;
2295                 case SDIAUDIO_CTL_AUDCH_EN_8:
2296                         printf("\tAssuming 8 channels of audio.\n");
2297                         break;
2298                 default:
2299                         printf("\tSet audio channel enable = %lu.\n", atol(value));
2300                         break;
2301                 }
2302         } else if (setting == SETTING_NON_AUDIO) {
2303                 snprintf(name, sizeof(name), fmt, type, num, "non_audio");
2304                 snprintf(data, sizeof(data), "0x%04lX\n", atol(value));
2305                 if (util_write(name, data, sizeof(data)) < 0) {
2306                         fprintf(stderr, "%s: ", device);
2307                         perror("unable to set "
2308                                 "the interface non-audio");
2309                         return -1;
2310                 }
2311                 switch (atol(value)) {
2312                 case 0x0000:
2313                         printf("\tPassing PCM audio.\n");
2314                         break;
2315                 case 0x00ff:
2316                         printf("\tPassing non-audio.\n");
2317                         break;
2318                 default:
2319                         printf("\tSet non-audio = 0x%04lX.\n", atol(value));
2320                         break;
2321                 }
2322         }
2323
2324         return 0;
2325 }
2326
2327 static ssize_t util_read(const char *name, char *buf, size_t count) {
2328         ssize_t fd, ret;
2329
2330         if ((fd = open(name, O_RDONLY)) < 0) {
2331                 return fd;
2332         }
2333         ret = read(fd, buf, count);
2334         close(fd);
2335         return ret;
2336 }
2337
2338 static ssize_t util_write(const char *name, const char *buf, size_t count) {
2339         ssize_t fd, ret;
2340
2341         if ((fd = open(name, O_WRONLY)) < 0) {
2342                 return fd;
2343         }
2344         ret = write(fd, buf, count);
2345         close(fd);
2346         return ret;
2347 }
2348
2349 static char * itoa(uint64_t i) {
2350
2351         if (i == 0)
2352                 return strdup("0");
2353
2354         char * mystring = (char *) malloc(50);
2355         sprintf(mystring, "%"PRIu64, i);
2356
2357         return mystring;
2358 }