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