]> git.sesse.net Git - mlt/blob - src/modules/linsys/sdi_generator.c
Add HD-SDI support to Linsys SDI 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 × 480/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   8 x AES (16 channels)   sdi_486i_5994   TODO:180,145,159,107
123  * SD NTSC              720 × 480/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    sdi_486i_5994   193
124  *
125  **/
126
127 #include "sdi_generator.h"
128
129 /*!/brief Initialization of the file handlers for the Playout
130  * @param *device_video: file or SDITX device or SDIVIDEOTX device
131  * @param *device_audio: file or SDIAUDIOTX device
132  * @param blanking: true or false (if false the consumer write only active video data without any VANH or HANC)
133  */
134 static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, mlt_profile myProfile) {
135
136         // set device file
137         device_file_video = device_video;
138         device_file_audio = device_audio;
139
140         // set flag for using of blanking with anilary data
141         info.blanking = blanking;
142
143         // set pack methode for SDI word conversion
144         //pack = pack8;
145         //pack = pack10;
146         pack = pack_v210;
147
148         // check format
149         if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1 && myProfile->progressive
150                         == 0) {
151                 info.fmt = &FMT_1080i60;
152         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
153                         && myProfile->progressive == 0) {
154                 info.fmt = &FMT_1080i5994;
155         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
156                         && myProfile->progressive == 0) {
157                 info.fmt = &FMT_1080i50;
158         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
159                         && myProfile->progressive == 1) {
160                 info.fmt = &FMT_1080p30;
161         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
162                         && myProfile->progressive == 1) {
163                 info.fmt = &FMT_1080p2997;
164         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
165                         && myProfile->progressive == 1) {
166                 info.fmt = &FMT_1080p25;
167         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24 && myProfile->frame_rate_den == 1
168                         && myProfile->progressive == 1) {
169                 info.fmt = &FMT_1080p24;
170         } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den == 1001
171                         && myProfile->progressive == 1) {
172                 info.fmt = &FMT_1080p2398;
173         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60 && myProfile->frame_rate_den == 1
174                         && myProfile->progressive == 1) {
175                 info.fmt = &FMT_720p60;
176         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60000 && myProfile->frame_rate_den == 1001
177                         && myProfile->progressive == 1) {
178                 info.fmt = &FMT_720p5994;
179         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 50 && myProfile->frame_rate_den == 1
180                         && myProfile->progressive == 1) {
181                 info.fmt = &FMT_720p50;
182         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
183                         && myProfile->progressive == 1) {
184                 info.fmt = &FMT_720p30;
185         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
186                         && myProfile->progressive == 1) {
187                 info.fmt = &FMT_720p2997;
188         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
189                         && myProfile->progressive == 1) {
190                 info.fmt = &FMT_720p25;
191         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24 && myProfile->frame_rate_den == 1
192                         && myProfile->progressive == 1) {
193                 info.fmt = &FMT_720p24;
194         } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den == 1001
195                         && myProfile->progressive == 1) {
196                 info.fmt = &FMT_720p2398;
197         } else if (myProfile->width == 720 && myProfile->height == 576 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
198                         && myProfile->progressive == 0) {
199                 info.fmt = &FMT_576i50;
200         } else if (myProfile->width == 720 && myProfile->height == 480 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
201                         && myProfile->progressive == 0) {
202                 info.fmt = &FMT_480i5994;
203         } else {
204                 printf("Consumer gets unknown format: %s", myProfile->description);
205                 info.fmt = &FMT_576i50;
206         }
207
208         printf("Consumer use format: %s\nProfile: %i %i %i %i %i\n", myProfile->description, myProfile->width, myProfile->height, myProfile->frame_rate_num,
209                         myProfile->frame_rate_den, myProfile->progressive);
210
211         // Check if the format support own blanking (note: model 193 support currently only active video at the video device file)
212         if (info.blanking && info.fmt != &FMT_576i50) {
213                 printf("SDI consumer doesn't support blanking(HANC) for this configurred SD board and SDI format. Try arguemnt: blanking=false\n");
214                 return EXIT_FAILURE;
215         }
216
217         if (device_file_video != NULL) {
218                 // open file handler for SDI(video) output
219                 if ((fh_sdi_video = open(device_file_video, O_WRONLY)) == -1) {
220                         perror(NULL);
221                         printf("\ncould not open video output destination: %s\n", device_file_video);
222                 }
223                 printf("SDI consumer use video device file: %s\n", device_file_video);
224         }
225
226         // Check if seperat device file for audio must use
227         if (device_file_audio != NULL) {
228                 // open file handler for audio output
229                 if ((fh_sdi_audio = open(device_file_audio, O_WRONLY | O_CREAT, 0777)) == -1) {
230                         perror(NULL);
231                         printf("\ncould not open audio output destination: %s\n", device_file_audio);
232                         return EXIT_FAILURE;
233                 }
234                 printf("SDI consumer use audio device file: %s\n", device_file_audio);
235         }
236
237         // if we write our own HANC we need an AES channel status bit array
238         if (info.blanking) {
239
240                 // small description
241                 // http://www.sencore.com/newsletter/Nov05/DigAudioChannelStatusBits.htm
242                 // or
243                 // http://www.sencore.com/uploads/files/DigAudioChannelStatusBits.pdf
244
245                 // create empty AESChannelStatusBitArray
246                 int i = 0;
247                 for (i = 0; i < sizeof(AESChannelStatusBitArray) / sizeof(AESChannelStatusBitArray[0]); i++)
248                         AESChannelStatusBitArray[i] = 0;
249
250                 /**
251                  * Professionel Format - Channel Status Bits
252                  **/
253                 ////// Byte 0 //////
254                 AESChannelStatusBitArray[0] = 1; // professional format
255
256                 AESChannelStatusBitArray[1] = 0; // PCM Format
257
258                 AESChannelStatusBitArray[2] = 1; // Emphasis: [100] No Emphasis
259                 AESChannelStatusBitArray[3] = 0; // ^
260                 AESChannelStatusBitArray[4] = 0; // ^
261
262                 AESChannelStatusBitArray[5] = 0; // locked
263
264                 AESChannelStatusBitArray[6] = 0; // sample frequncy Fs: [01]48kHz, [10]44kHz, [11]32kHz
265                 AESChannelStatusBitArray[7] = 1; // ^
266                 ////// Byte 1 //////
267                 AESChannelStatusBitArray[8] = 0; // channel mode: [0000] not indicated, [0001]2channels, [0010]1channel mono, ...
268                 AESChannelStatusBitArray[9] = 0; // ^
269                 AESChannelStatusBitArray[10] = 0; // ^
270                 AESChannelStatusBitArray[11] = 1; // ^
271                 ////// Byte 2 //////
272                 AESChannelStatusBitArray[19] = 0; // Encoded sample word length [100]20bits,
273                 AESChannelStatusBitArray[20] = 0; //
274                 AESChannelStatusBitArray[21] = 0; //
275                 ////// Byte 3 //////
276                 AESChannelStatusBitArray[24] = 0; //
277                 AESChannelStatusBitArray[25] = 0; //
278                 AESChannelStatusBitArray[26] = 0; //
279                 AESChannelStatusBitArray[27] = 0; //
280                 AESChannelStatusBitArray[28] = 0; //
281                 AESChannelStatusBitArray[29] = 0; //
282                 AESChannelStatusBitArray[30] = 0; //
283                 AESChannelStatusBitArray[31] = 0; // Multi Channel Mode
284                 ////// Byte 4-21 //////
285                 //AESChannelStatusBitArray[32-179]= 0;
286                 ////// Byte 22 //////
287                 AESChannelStatusBitArray[180] = 0; // Reliability Flags
288                 AESChannelStatusBitArray[181] = 1; // ^
289                 AESChannelStatusBitArray[182] = 1; // ^
290                 AESChannelStatusBitArray[183] = 1; // ^
291                 ////// Byte 23 //////
292                 AESChannelStatusBitArray[184] = 0; // Cyclic Redundancy Check
293                 AESChannelStatusBitArray[185] = 1; // ^
294                 AESChannelStatusBitArray[186] = 0; // ^
295                 AESChannelStatusBitArray[187] = 0; // ^
296                 AESChannelStatusBitArray[188] = 1; // ^
297                 AESChannelStatusBitArray[189] = 0; // ^
298                 AESChannelStatusBitArray[190] = 1; // ^
299                 AESChannelStatusBitArray[191] = 1; // ^
300         }
301
302         // set buffer for one line of active video samples
303         line_buffer = (uint16_t*) calloc(info.fmt->samples_per_line, sizeof(uint16_t));
304
305         // calculate and set buffer for the complete SDI frame
306         if (info.fmt != &FMT_576i50 && info.fmt != &FMT_480i5994) {
307                 if (info.blanking) {
308                         if (pack == pack_v210) {
309                                 samples = (info.fmt->samples_per_line / 96 * 48) + ((info.fmt->samples_per_line % 96) ? 48 : 0);
310                                 sdi_frame_size = samples * info.fmt->lines_per_frame * 8 / 3;
311                         } else {
312                                 sdi_frame_size = info.fmt->samples_per_line * info.fmt->lines_per_frame;
313                         }
314                 } else {
315                         if (pack == pack_v210) {
316                                 samples = (info.fmt->active_samples_per_line / 96 * 48) + ((info.fmt->active_samples_per_line % 96) ? 48 : 0);
317                                 sdi_frame_size = samples * info.fmt->active_lines_per_frame * 8 / 3;
318                         } else {
319                                 sdi_frame_size = info.fmt->active_samples_per_line * info.fmt->active_lines_per_frame;
320                         }
321                 }
322         } else {
323                 if (info.blanking) {
324                         if (pack == pack_v210) {
325                                 sdi_frame_size = info.fmt->samples_per_line * 4 / 3 * info.fmt->lines_per_frame;
326                         } else if (pack == pack8) {
327                                 sdi_frame_size = info.fmt->samples_per_line * info.fmt->lines_per_frame;
328                         } else {
329                                 sdi_frame_size = info.fmt->samples_per_line * 10 / 8 * info.fmt->lines_per_frame;
330                         }
331                 } else {
332                         if (pack == pack_v210) {
333                                 sdi_frame_size = info.fmt->active_samples_per_line * 4 / 3 * info.fmt->active_lines_per_frame;
334                         } else if (pack == pack8) {
335                                 sdi_frame_size = info.fmt->active_samples_per_line * info.fmt->active_lines_per_frame;
336                         } else {
337                                 sdi_frame_size = info.fmt->active_samples_per_line * 10 / 8 * info.fmt->active_lines_per_frame;
338                         }
339                 }
340         }
341
342         // hack/overwrite because we use default the pack_v210() not as befor the pack10()
343         //(*10/8 because we store (TOTAL_SAMPLES*TOTAL_LINES) words with 10 bit in this 8 bit array) )
344         if (info.fmt == &FMT_576i50 && info.blanking) {
345                 sdi_frame_size = info.fmt->samples_per_line * 10 / 8 * info.fmt->lines_per_frame;
346         }
347
348         printf("SDI frame size:%li\n", sdi_frame_size);
349
350         // set buffer for the complete SDI frame
351         data = (uint8_t*) calloc(sdi_frame_size, sizeof(uint8_t));
352
353         return 1;
354 }
355
356 /**
357  * Writes video and audio to specified files in SDI format
358  * @param *vBuffer: Pointer to a video Buffer
359  * @param aBuffer[][]
360  * @param *audio_format: mlt audio_format
361  * @param audio_streams: number of audio streams which have content in aBuffer (available 0-8)
362  * @return current DBN (data block number of SDI frame)
363  **/
364 static int sdi_playout(uint8_t *vBuffer, int16_t aBuffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], const struct audio_format * audio_format, int audio_streams,
365                 int my_DBN) {
366
367         // Pointer to the start of data. This is used to fill data line by line
368         uint8_t *p = data;
369
370         //*******************************************************************************************
371         //****************      Build the SDI frame line by line ****************************************
372         //*******************************************************************************************
373
374         /*
375          * if SDI FMT_576i50 for card ASSY 145 or ASSY 159, with access to whole SDI frame buffer
376          *   and device_file_audio must be NULL
377          *      than we write own audio data,
378          * else
379          *      than HD for card ASSY 193
380          */
381         //if (info.fmt == &FMT_576i50 && device_file_audio == NULL && !strcmp(device_file_video, "/dev/sdivideotx0")) {
382         if (info.fmt == &FMT_576i50 && info.blanking) {
383
384                 //counter for the lines
385                 int i = 0;
386                 int16_t AudioGroupCounter = 0;
387
388                 /*#####################################################*/
389                 /*########      FIELD 1                         #######################*/
390                 /*#####################################################*/
391
392                 info.xyz = &FIELD_1_VERT_BLANKING;
393
394                 // line 1-22    VERTICAL_BLANKING:23 lines                              SAV 0x2ac               EAV 0x2d8
395                 for (i = 1; i <= 5; i++) {
396                         create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
397                                         getNumberOfAudioGroups2Write(i), audio_streams);
398                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
399                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
400                 }
401                 for (i = 6; i <= 8; i++) {
402                         create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
403                                         getNumberOfAudioGroups2Write(i), audio_streams);
404                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
405                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
406                 }
407                 for (i = 9; i <= 22; i++) {
408                         create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
409                                         getNumberOfAudioGroups2Write(i), audio_streams);
410                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
411                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
412                 }
413                 // line 23-310  ACTIVE: 287 lines                                               SAV 0x200               EAV 0x274
414                 info.xyz = &FIELD_1_ACTIVE;
415                 int f1counter = 1; // only odd lines
416                 for (i = 23; i <= 310; i++) {
417                         create_SD_SDI_Line(line_buffer, &info, FIELD_1, ACTIVE_VIDEO, vBuffer, aBuffer, i, f1counter, getDBN(my_DBN++), AudioGroupCounter,
418                                         getNumberOfAudioGroups2Write(i), audio_streams);
419                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
420                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
421                         f1counter += 2;
422                 }
423                 i = 311;
424                 // line 311-312 VERTICAL_BLANKING: 2 lines                              SAV 0x2ac               EAV 0x2d8
425                 info.xyz = &FIELD_1_VERT_BLANKING;
426                 create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
427                                 getNumberOfAudioGroups2Write(i), audio_streams);
428                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
429                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
430                 create_SD_SDI_Line(line_buffer, &info, FIELD_1, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
431                                 getNumberOfAudioGroups2Write(i), audio_streams);
432                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
433                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
434
435                 /*#####################################################*/
436                 /*########      FIELD 2        ########################*/
437                 /*#####################################################*/
438
439                 info.xyz = &FIELD_2_VERT_BLANKING;
440
441                 // line 313-336 VERTICAL_BLANKING: 23 lines                             SAV 0x3b0               EAV 0x3c4
442                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
443                                 getNumberOfAudioGroups2Write(i), audio_streams);
444                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
445                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
446
447                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
448                                 getNumberOfAudioGroups2Write(i), audio_streams);
449                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
450                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
451
452                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
453                                 getNumberOfAudioGroups2Write(i), audio_streams);
454                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
455                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
456
457                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
458                                 getNumberOfAudioGroups2Write(i), audio_streams);
459                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
460                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
461
462                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
463                                 getNumberOfAudioGroups2Write(i), audio_streams);
464                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
465                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
466
467                 create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
468                                 getNumberOfAudioGroups2Write(i), audio_streams);
469                 AudioGroupCounter += getNumberOfAudioGroups2Write(i++);
470                 p = pack10(p, line_buffer, info.fmt->samples_per_line);
471
472                 // `getAudioGroups2Write()`=0
473                 for (i = 319; i <= 321; i++) {
474                         create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
475                                         getNumberOfAudioGroups2Write(i), audio_streams);
476                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
477                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
478                 }
479                 for (i = 322; i <= 335; i++) {
480                         create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
481                                         getNumberOfAudioGroups2Write(i), audio_streams);
482                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
483                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
484                 }
485                 // line 336-623 ACTIVE: 288 lines                                               SAV 0x31c               EAV 0x368
486                 info.xyz = &FIELD_2_ACTIVE;
487                 int f2counter = 2; // only even Lines
488                 for (i = 336; i <= 623; i++) {
489
490                         create_SD_SDI_Line(line_buffer, &info, FIELD_2, ACTIVE_VIDEO, vBuffer, aBuffer, i, f2counter, getDBN(my_DBN++), AudioGroupCounter,
491                                         getNumberOfAudioGroups2Write(i), audio_streams);
492                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
493                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
494                         f2counter += 2;
495                 }
496                 // line 624-625 VERTICAL_BLANKING: 2 lines                              SAV 0x3b0               EAV 0x3c4
497                 info.xyz = &FIELD_2_VERT_BLANKING;
498                 for (i = 624; i <= 625; i++) {
499                         create_SD_SDI_Line(line_buffer, &info, FIELD_2, VERT_BLANKING, vBuffer, aBuffer, i, 0, getDBN(my_DBN++), AudioGroupCounter,
500                                         getNumberOfAudioGroups2Write(i), audio_streams);
501                         AudioGroupCounter += getNumberOfAudioGroups2Write(i);
502                         p = pack10(p, line_buffer, info.fmt->samples_per_line);
503                 }
504
505         } else { // use HD board without blanking
506
507                 // start with first even line
508                 active_video_line = 1;
509
510                 /* *****************************************
511                  * *********** LINE DISTRIBUTION ***********
512                  * *****************************************
513                  *
514                  * << decide form of scanning (interlaced || progressive) >>
515                  * if (interlaced)
516                  *              << decide lines per frame (1125 || 625 || 525) >>
517                  *              if(1125)                                        1080x1920 HD
518                  *                      than create lines
519                  *              else if(625)                              576x720 PAL
520                  *                      than create lines
521                  *              else (525)                                        486x720 NTSC
522                  *                      than create lines
523                  * else (progressive)
524                  *              << decide resolution (1125 || 750) >>
525                  *              if(1125)                                        1080x1920 HD
526                  *                      than create lines
527                  *              else(750)                                        720x1280 HD
528                  *                      than create lines
529                  *
530                  **/
531
532                 // Generate a frame
533                 if (info.fmt->interlaced) {
534
535                         /****************************************
536                          * INTERLACED
537                          ****************************************/
538
539                         if (info.fmt->lines_per_frame == 1125) {
540
541                                 if (info.blanking) {
542                                         elements = info.fmt->samples_per_line;
543                                         info.xyz = &FIELD_1_VERT_BLANKING;
544                                         for (info.ln = 1; info.ln <= 20; info.ln++) {
545                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
546                                                 p = pack(p, line_buffer, elements);
547                                         }
548                                 } else {
549                                         elements = info.fmt->active_samples_per_line;
550                                 }
551                                 info.xyz = &FIELD_1_ACTIVE;
552                                 for (info.ln = 21; info.ln <= 560; info.ln++) {
553                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
554                                         p = pack(p, line_buffer, elements);
555                                         active_video_line += 2;
556                                 }
557                                 if (info.blanking) {
558                                         info.xyz = &FIELD_1_VERT_BLANKING;
559                                         for (info.ln = 561; info.ln <= 563; info.ln++) {
560                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
561                                                 p = pack(p, line_buffer, elements);
562                                         }
563                                         info.xyz = &FIELD_2_VERT_BLANKING;
564                                         for (info.ln = 564; info.ln <= 583; info.ln++) {
565                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
566                                                 p = pack(p, line_buffer, elements);
567                                         }
568                                 }
569                                 // start with first odd line
570                                 active_video_line = 2;
571
572                                 info.xyz = &FIELD_2_ACTIVE;
573                                 for (info.ln = 584; info.ln <= 1123; info.ln++) {
574                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
575                                         p = pack(p, line_buffer, elements);
576                                         active_video_line += 2;
577                                 }
578                                 if (info.blanking) {
579                                         info.xyz = &FIELD_2_VERT_BLANKING;
580                                         for (info.ln = 1124; info.ln <= 1125; info.ln++) {
581                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
582                                                 p = pack(p, line_buffer, elements);
583                                         }
584                                 }
585                         } else if (info.fmt->lines_per_frame == 625) {
586
587                                 elements = info.fmt->active_samples_per_line;
588
589                                 // start with first even line
590                                 active_video_line = 1;
591
592                                 /**
593                                  *  Generate an SDI PAL frame
594                                  **/
595                                 if (info.blanking) {
596                                         info.xyz = &FIELD_1_VERT_BLANKING;
597                                         for (info.ln = 1; info.ln <= 22; info.ln++) {
598                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
599                                                 p = pack(p, line_buffer, elements);
600                                         }
601                                 }
602                                 info.xyz = &FIELD_1_ACTIVE;
603                                 for (info.ln = 23; info.ln <= 310; info.ln++) {
604                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
605                                         p = pack(p, line_buffer, elements);
606                                         active_video_line += 2;
607                                 }
608                                 if (info.blanking) {
609                                         info.xyz = &FIELD_1_VERT_BLANKING;
610                                         for (info.ln = 311; info.ln <= 312; info.ln++) {
611                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
612                                                 p = pack(p, line_buffer, elements);
613                                         }
614                                         info.xyz = &FIELD_2_VERT_BLANKING;
615                                         for (info.ln = 313; info.ln <= 335; info.ln++) {
616                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
617                                                 p = pack(p, line_buffer, elements);
618                                         }
619                                 }
620
621                                 // start with first odd line
622                                 active_video_line = 2;
623
624                                 info.xyz = &FIELD_2_ACTIVE;
625                                 for (info.ln = 336; info.ln <= 623; info.ln++) {
626                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
627                                         p = pack(p, line_buffer, elements);
628                                         active_video_line += 2;
629                                 }
630                                 if (info.blanking) {
631                                         info.xyz = &FIELD_2_VERT_BLANKING;
632                                         for (info.ln = 624; info.ln <= 625; info.ln++) {
633                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
634                                                 p = pack(p, line_buffer, elements);
635                                         }
636                                 }
637                         } else if (info.fmt->lines_per_frame == 525) {
638
639                                 /**
640                                  *  Generate an SDI NTSC frame
641                                  **/
642                                 elements = info.fmt->active_samples_per_line;
643
644                                 active_video_line = 1;
645
646                                 if (info.blanking) {
647                                         info.xyz = &FIELD_1_VERT_BLANKING;
648                                         for (info.ln = 1; info.ln <= 15; info.ln++) {
649                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
650                                                 p = pack(p, line_buffer, elements);
651                                         }
652                                         for (info.ln = 16; info.ln <= 16; info.ln++) {
653                                                 info.xyz = &FIELD_1_ACTIVE;
654                                                 mkline(line_buffer, &info, VERT_BLANKING);
655                                                 p = pack(p, line_buffer, elements);
656                                         }
657                                 }
658
659                                 info.xyz = &FIELD_1_ACTIVE;
660                                 // 3 lines opt. video data
661                                 for (info.ln = 17; info.ln <= 19; info.ln++) {
662                                         mkline(line_buffer, &info, BLACK);
663                                         p = pack(p, line_buffer, elements);
664                                 }
665                                 for (info.ln = 20; info.ln <= 259; info.ln++) {
666                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
667                                         p = pack(p, line_buffer, elements);
668                                         active_video_line += 2;
669                                 }
670                                 if (info.blanking) {
671                                         info.xyz = &FIELD_1_VERT_BLANKING;
672                                         for (info.ln = 260; info.ln <= 261; info.ln++) {
673                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
674                                                 p = pack(p, line_buffer, elements);
675                                         }
676                                         info.xyz = &FIELD_2_VERT_BLANKING;
677                                         // 7 lines vertical data
678                                         for (info.ln = 262; info.ln <= 269; info.ln++) {
679                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
680                                                 p = pack(p, line_buffer, elements);
681                                         }
682                                         // 9 lines opt. video data ?? // TODO have look to SMPTE
683                                         for (info.ln = 270; info.ln <= 278; info.ln++) {
684                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
685                                                 p = pack(p, line_buffer, elements);
686                                         }
687
688                                 }
689
690                                 active_video_line = 0;
691                                 // 3 lines opt. video data
692                                 info.xyz = &FIELD_2_ACTIVE;
693                                 for (info.ln = 279; info.ln <= 281; info.ln++) {
694                                         mkline(line_buffer, &info, BLACK);
695                                         p = pack(p, line_buffer, elements);
696                                 }
697                                 for (info.ln = 282; info.ln <= 521; info.ln++) {
698                                         create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
699                                         p = pack(p, line_buffer, elements);
700                                         active_video_line += 2;
701                                 }
702                                 if (info.blanking) {
703                                         info.xyz = &FIELD_2_VERT_BLANKING;
704                                         for (info.ln = 522; info.ln <= 525; info.ln++) {
705                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
706                                                 p = pack(p, line_buffer, elements);
707                                         }
708                                 }
709                         }
710                 } else {
711
712                         /****************************************
713                          * PROGRESSIVE
714                          ****************************************/
715
716                         // start with first line numerber
717                         active_video_line = 0;
718
719                         if (info.fmt->lines_per_frame == 1125) {
720                                 if (info.blanking) {
721                                         elements = info.fmt->samples_per_line;
722                                         info.xyz = &FIELD_1_VERT_BLANKING;
723                                         for (info.ln = 1; info.ln <= 41; info.ln++) {
724                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
725                                                 p = pack(p, line_buffer, elements);
726                                         }
727                                 } else {
728                                         elements = info.fmt->active_samples_per_line;
729                                 }
730                                 info.xyz = &FIELD_1_ACTIVE;
731                                 for (info.ln = 42; info.ln <= 1121; info.ln++) {
732                                         create_HD_SDI_Line(line_buffer, &info, active_video_line++, ACTIVE_VIDEO, vBuffer);
733                                         p = pack(p, line_buffer, elements);
734                                 }
735                                 if (info.blanking) {
736                                         info.xyz = &FIELD_1_VERT_BLANKING;
737                                         for (info.ln = 1122; info.ln <= 1125; 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 {
743                                 if (info.blanking) {
744                                         elements = info.fmt->samples_per_line;
745                                         info.xyz = &FIELD_1_VERT_BLANKING;
746                                         for (info.ln = 1; info.ln <= 25; info.ln++) {
747                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
748                                                 p = pack(p, line_buffer, elements);
749                                         }
750                                 } else {
751                                         elements = info.fmt->active_samples_per_line;
752                                 }
753                                 info.xyz = &FIELD_1_ACTIVE;
754                                 for (info.ln = 26; info.ln <= 745; info.ln++) {
755                                         create_HD_SDI_Line(line_buffer, &info, active_video_line++, ACTIVE_VIDEO, vBuffer);
756                                         p = pack(p, line_buffer, elements);
757                                 }
758                                 if (info.blanking) {
759                                         info.xyz = &FIELD_1_VERT_BLANKING;
760                                         for (info.ln = 746; info.ln <= 750; info.ln++) {
761                                                 create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
762                                                 p = pack(p, line_buffer, elements);
763                                         }
764                                 }
765                         }
766                 }
767         }
768
769         // sum of bytes that have already been written to file
770         int bytes = 0;
771         // store actual written bytes per 'write()
772         int written_bytes = 0;
773
774         /**
775          * WRITE BUFFER TO FILEHANDLE
776          **/
777         // Write the complete frame to output
778         // The "while" is necessary because the sdi device file does not take the complete frame at once
779         written_bytes = 0;
780         while (bytes < sdi_frame_size) {
781
782                 if ((written_bytes = write(fh_sdi_video, data + bytes, sdi_frame_size - bytes)) < 0) {
783                         fprintf(stderr, "\nunable to write SDI video.\n");
784                         return -1;
785                 }
786                 bytes += written_bytes;
787
788                 // Check for events of the SDI board
789                 unsigned int val;
790                 if (ioctl(fh_sdi_video, SDI_IOC_TXGETEVENTS, &val) < 0) {
791                         // Maybe this is not an SDI device...
792                         fprintf(stderr, "SDI VIDEO output:");
793                         perror("unable to get the transmitter event flags");
794                 } else if (val) {
795                         if (val & SDI_EVENT_TX_BUFFER) {
796                                 printf("SDI VIDEO driver transmit buffer queue underrun "
797                                         "detected.\n");
798                         }
799                         if (val & SDI_EVENT_TX_FIFO) {
800                                 printf("SDI VIDEO onboard transmit FIFO underrun detected.\n");
801                                 // TODO react
802                         }
803                         if (val & SDI_EVENT_TX_DATA) {
804                                 printf("SDI VIDEO transmit data change detected.\n");
805                         }
806                 }
807                 fflush(stdout);
808         }
809
810         // if available write audio data
811         if (fh_sdi_audio) {
812
813                 // count writen bytes
814                 written_bytes = 0;
815
816                 // set number of samples and cut by 1600 if NTSC (handle problem of real time encoding of NTSC frequencies)
817                 //size_t samples_total_per_track = audio_format->samples == 1601 || audio_format->samples == 1602 ? 1600 : audio_format->samples; // TODO buffer underrun by NTSC frequencs because of 3/2 pull down
818                 size_t samples_total_per_track = audio_format->samples;
819                 uint16_t sample_number = 0;
820                 size_t channels_per_track_total = 2;
821                 uint8_t stream_number = 0;
822
823                 //printf("samples_total_per_track:%li\n", samples_total_per_track);
824
825                 // to write blockwise 2 samples of one track we must claculate the number of bytes we want to write per write-session
826                 // 2samples = 2x16Bit = 32Bit = 4Byte
827                 // 2samples = 2x32Bit = 64Bit = 8Byte
828                 // set total bytes per session
829                 size_t bytes_total = 0;
830                 bytes_total = audio_format->aformat == mlt_audio_s16 ? channels_per_track_total * sizeof(int16_t) : bytes_total;
831                 bytes_total = audio_format->aformat == mlt_audio_s32 ? channels_per_track_total * sizeof(int32_t) : bytes_total; // TODO sdi board must be pre-configured for 32bit samples!!!!
832
833                 // write all samples of all streams interleaved
834                 /**
835                  * aBuffer[track0]+sample1
836                  * aBuffer[track0]+sample2
837                  * aBuffer[track1]+sample1
838                  * aBuffer[track1]+sample2
839                  * aBuffer[track.]+sample1
840                  * aBuffer[track.]+sample2
841                  *
842                  * aBuffer[track0]+sample3
843                  * aBuffer[track0]+sample4
844                  * aBuffer[track1]+sample3
845                  * aBuffer[track1]+sample4
846                  * aBuffer[track.]+sample3
847                  * aBuffer[track.]+sample4
848                  *
849                  * aBuffer[track0]+sample5
850                  * aBuffer[track0]+sample6
851                  * aBuffer[track1]+sample5
852                  * aBuffer[track1]+sample6
853                  * aBuffer[track.]+sample5
854                  * aBuffer[track.]+sample6
855                  **/
856                 int sum_written_bytes = 0;
857                 int sum_written_bytes_a = 0;
858                 int sum_written_bytes_b = 0;
859
860                 // write all samples per track
861                 while (sample_number < samples_total_per_track) {
862
863                         stream_number = 0;
864
865                         /**
866                          * Because we have and write a fix number of audio streams to SDI board:
867                          * we have a actual number of real audio tracks and a rest number of pseudo tracks
868                          **/
869                         // write all streams
870                         while (stream_number < audio_streams) {
871
872                                 // write for every stream n samples
873                                 // n = number of channels per stream
874                                 written_bytes = 0;
875                                 while (written_bytes < bytes_total) {
876                                         written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[stream_number] + sample_number * bytes_total + written_bytes, bytes_total
877                                                         - written_bytes);
878                                 }
879                                 sum_written_bytes += written_bytes;
880                                 sum_written_bytes_a += written_bytes;
881
882                                 stream_number++;
883                         }
884
885                         // write pseudo tracks
886                         // now fill rest of audio tracks with NULL or copy of first track
887                         while (stream_number < 4) { // TODO linsys board model 193 have a limit to 4 AES groups (=4streams,8channels)
888
889                                 // write for every stream n samples
890                                 // n = number of channels per stream
891                                 written_bytes = 0;
892                                 while (written_bytes < bytes_total) {
893                                         written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[0] + sample_number * bytes_total + written_bytes, bytes_total - written_bytes);
894                                 }
895                                 sum_written_bytes += written_bytes;
896                                 sum_written_bytes_b += written_bytes;
897
898                                 stream_number++;
899                         }
900
901                         sample_number++;
902
903 //                      // Check for events of the SDI board (only firmware 0.9)
904 //                      unsigned int val;
905 //                      if (ioctl(fh_sdi_audio, SDI_IOC_TXGETEVENTS, &val) < 0) {
906 //                              //Maybe this is not an SDI device...
907 //                              fprintf(stderr, "SDI AUDIO output:");
908 //                              perror("unable to get the transmitter event flags");
909 //                      } else if (val) {
910 //                              if (val & SDI_EVENT_TX_BUFFER) {
911 //                                      printf("SDI AUDIO driver transmit buffer queue underrun "
912 //                                              "detected.\n");
913 //                              }
914 //                              if (val & SDI_EVENT_TX_FIFO) {
915 //                                      printf("SDI AUDIO onboard transmit FIFO underrun detected.\n");
916 //                                      //TODO react
917 //                              }
918 //                              if (val & SDI_EVENT_TX_DATA) {
919 //                                      printf("SDI AUDIO transmit data change detected.\n");
920 //                              }
921 //                      }
922                 }
923         }
924
925         return getDBN(my_DBN);
926 } // end sdimaster_playout()
927
928
929 //****************************************************************************************
930 //***************************  Create Line  **********************************************
931 //****************************************************************************************
932
933 /** generate one SDI line
934  * @param *buf: buffer to hold the line
935  * @param field: size of the video Buffer
936  * @param active: v-blank or active-video
937  * @param *video_buffer: video buffer
938  * @param *audio_buffer2: 1.audio buffer ch1-ch2
939  * @param *audio_buffer1: 2.audio buffer ch2-ch3
940  * @param line: linenumber
941  * @param AudioGroupCounter: count written AudioGroup
942  * @param AudioGroups2Write: number of samples to write
943  * @param audio_streams: number of audio streams to integrate
944  */
945 static inline int create_SD_SDI_Line(uint16_t *buf, const struct line_info *info, int field, int active, uint8_t *video_buffer,
946                 int16_t audio_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], int linenumber_sdiframe, int active_video_line, int my_DBN, int16_t AudioGroupCounter,
947                 int16_t AudioGroups2Write, int audio_streams) {
948
949         // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
950         //                                      *************************************************************************
951         // 625 lines:           | EAV |     ANC      | SAV |            [CbY1CrY2]                                                      |
952         //                                      *************************************************************************
953         // 1728 SDI-words:      | 4   |         280              | 4   |                720+360+360=1440                                        |
954         //                                      *************************************************************************
955
956         // points to current position in line
957         uint16_t *p = buf;
958
959         //#########################################################################################
960         /* TRS Timing Reference Signal for EAV
961          *              [3ff]
962          *              [000]
963          *              [000]
964          *              [XYZ-Wort]
965          * */
966
967         *p++ = 0x3ff;
968         *p++ = 0x000;
969         *p++ = 0x000;
970         *p++ = info->xyz->eav;
971         //#########################################################################################
972
973         /* ANC Ancillary Data with AES
974          *
975          *      [ADF][ADF][ADF][DID][DBN][DC][UDW]...[UDW][CS]
976          *
977          * */
978         // write ANC Data and get number of samples are written
979         // step with `p` += to the number of written samples
980
981         //printf("audio_streams:%i\n",audio_streams);
982
983         // 1 stream, Audio Group 1 with AES Frame 1 - 2
984         if (audio_streams == 1) {
985                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[0], AudioGroupCounter, AudioGroups2Write);
986         }
987         // 2 streams, Audio Group 1 with AES Frame 1 - 2
988         if (audio_streams == 2) {
989                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
990         }
991         // 3 streams, Audio Group 2 with AES Frame 1 - 4
992         if (audio_streams == 3) {
993                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
994                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[2], AudioGroupCounter, AudioGroups2Write);
995         }
996         // 4 streams, Audio Group 2 with AES Frame 1 - 4
997         if (audio_streams == 4) {
998                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
999                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1000         }
1001         // 5 streams, Audio Group 3 with AES Frame 1 - 6
1002         if (audio_streams == 5) {
1003                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1004                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1005                 p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[4], AudioGroupCounter, AudioGroups2Write);
1006         }
1007         // 6 streams, Audio Group 3 with AES Frame 1 - 6
1008         if (audio_streams == 6) {
1009                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1010                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1011                 p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
1012         }
1013         // 7 streams, Audio Group 4 with AES Frame 1 - 7
1014         if (audio_streams == 7) {
1015                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1016                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1017                 p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
1018                 p += writeANC(p, linenumber_sdiframe, 0x2F9, my_DBN, audio_buffer[6], audio_buffer[6], AudioGroupCounter, AudioGroups2Write);
1019         }
1020         // 8 streams, Audio Group 4 with AES Frame 1 - 7
1021         if (audio_streams == 8) {
1022                 p += writeANC(p, linenumber_sdiframe, 0x2FF, my_DBN, audio_buffer[0], audio_buffer[1], AudioGroupCounter, AudioGroups2Write);
1023                 p += writeANC(p, linenumber_sdiframe, 0x1FD, my_DBN, audio_buffer[2], audio_buffer[3], AudioGroupCounter, AudioGroups2Write);
1024                 p += writeANC(p, linenumber_sdiframe, 0x1FB, my_DBN, audio_buffer[4], audio_buffer[5], AudioGroupCounter, AudioGroups2Write);
1025                 p += writeANC(p, linenumber_sdiframe, 0x2F9, my_DBN, audio_buffer[6], audio_buffer[7], AudioGroupCounter, AudioGroups2Write);
1026         }
1027
1028         // Fill ANC data in until the end (position(p) to `ANCILLARY_DATA_SAMPLES`)
1029         while (p < (buf + ANCILLARY_DATA_SAMPLES + 4)) {
1030                 // video color: black
1031                 *p++ = 0x200;
1032                 *p++ = 0x040;
1033         }
1034         //#########################################################################################
1035         // TRS Timing Reference Signal for SAV
1036         *p++ = 0x3ff;
1037         *p++ = 0x000;
1038         *p++ = 0x000;
1039         *p++ = info->xyz->sav;
1040         //#########################################################################################
1041
1042         // If VBlank then fill the line with 0x200 and 0x040 (total black)
1043         switch (active) {
1044         default:
1045         case VERT_BLANKING:
1046                 while (p < (buf + info->fmt->samples_per_line)) {
1047                         *p++ = 0x200;
1048                         *p++ = 0x040;
1049                 }
1050                 break;
1051         case ACTIVE_VIDEO:
1052
1053                 // Insert the video into the line
1054                 while (p < (buf + info->fmt->samples_per_line)) { // fill the rest of the line with active video
1055
1056                         // shift "<< 2" because 8 bit data in 10 bit word
1057
1058                         // Because we skip the first line of video, it can happen that we read too far in the buffer
1059                         if (active_video_line >= info->fmt->active_lines_per_frame) {
1060                                 active_video_line = info->fmt->active_lines_per_frame - 1; // in SD PAL was set 575
1061                         }
1062
1063                         *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) + 1] << 2; // Cb
1064                         p++;
1065                         if (*(p - 1) < 0x040)
1066                                 *(p - 1) = 0x040; // check values
1067                         if (*(p - 1) > 0x3c0)
1068                                 *(p - 1) = 0x3c0;
1069                         *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) - 1] << 2; // Y1
1070                         p++;
1071                         if (*(p - 1) < 0x040)
1072                                 *(p - 1) = 0x040;
1073                         if (*(p - 1) > 0x3ac)
1074                                 *(p - 1) = 0x3ac;
1075                         *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) + 1] << 2; // Cr
1076                         p++;
1077                         if (*(p - 1) < 0x040)
1078                                 *(p - 1) = 0x040;
1079                         if (*(p - 1) > 0x3c0)
1080                                 *(p - 1) = 0x3c0;
1081                         *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) - 1] << 2; // Y2
1082                         p++;
1083                         if (*(p - 1) < 0x040)
1084                                 *(p - 1) = 0x040;
1085                         if (*(p - 1) > 0x3ac)
1086                                 *(p - 1) = 0x3ac;
1087
1088                 }
1089                 break;
1090         }
1091         return 0;
1092 }
1093
1094 /**
1095  * create_HD_SDI_Line - generate one line
1096  * @buf: pointer to a buffer
1097  * @info: pointer to a line information structure
1098  * @active_video_line
1099  * @active:
1100  * @video_buffer: pattern
1101  *
1102  * Returns a negative error code on failure and zero on success.
1103  **/
1104 static inline int create_HD_SDI_Line(uint16_t *buf, const struct line_info *info, uint16_t active_video_line, unsigned int active, uint8_t *video_buffer) {
1105         uint16_t *p = buf, *endp, ln;
1106         uint16_t samples = info->blanking ? info->fmt->samples_per_line : info->fmt->active_samples_per_line;
1107
1108         if (info->blanking) {
1109
1110                 // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
1111                 // Example SD PAL:
1112                 //                  *************************************************************************
1113                 // 625 lines:       | EAV |     ANC      | SAV |        [CbY1CrY2]                          |
1114                 //                  *************************************************************************
1115                 // 1728 SDI-words:  | 4   |     280          | 4   |        720+360+360=1440                    |
1116                 //                                      *************************************************************************
1117
1118                 // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
1119                 // Example HD 1080i:
1120                 //                  *************************************************************************
1121                 // 1125 lines:      | EAV | LN  | CRC | ANC | SAV | [CbY1CrY2]                              |
1122                 //                  *************************************************************************
1123                 // 5280 SDI-words:  | 6   | 4   | 4   | 280     | 6   | 1920+720+720=3840                       |
1124                 //                  *************************************************************************
1125
1126                 if (info->fmt == &FMT_576i50) {
1127                         /* EAV */
1128                         *p++ = 0x3ff;
1129                         *p++ = 0x000;
1130                         *p++ = 0x000;
1131                         *p++ = info->xyz->eav;
1132                 } else {
1133                         /* EAV */
1134                         *p++ = 1023;
1135                         *p++ = 1023;
1136                         *p++ = 0;
1137                         *p++ = 0;
1138                         *p++ = 0;
1139                         *p++ = 0;
1140                         *p++ = info->xyz->eav;
1141                         *p++ = info->xyz->eav;
1142                         /* LN */
1143                         ln = ((info->ln & 0x07f) << 2) | (~info->ln & 0x040) << 3;
1144                         *p++ = ln;
1145                         *p++ = ln;
1146                         ln = ((info->ln & 0x780) >> 5) | 0x200;
1147                         *p++ = ln;
1148                         *p++ = ln;
1149                         /* CRC, added by serializer */
1150                         *p++ = 512;
1151                         *p++ = 64;
1152                         *p++ = 512;
1153                         *p++ = 64;
1154
1155                 }
1156
1157                 /* Horizontal blanking */
1158                 while (p < (buf + info->fmt->samples_per_line - info->fmt->active_samples_per_line - 4)) {
1159                         *p++ = 512;
1160                         *p++ = 64;
1161                         *p++ = 512;
1162                         *p++ = 64;
1163                 }
1164
1165                 if (info->fmt == &FMT_576i50) {
1166                         /* SAV */
1167                         *p++ = 0x3ff;
1168                         *p++ = 0x000;
1169                         *p++ = 0x000;
1170                         *p++ = info->xyz->sav;
1171                 } else {
1172                         /* SAV */
1173                         *p++ = 1023;
1174                         *p++ = 1023;
1175                         *p++ = 0;
1176                         *p++ = 0;
1177                         *p++ = 0;
1178                         *p++ = 0;
1179                         *p++ = info->xyz->sav;
1180                         *p++ = info->xyz->sav;
1181                 }
1182         }
1183         /* Active region */
1184         endp = p;
1185
1186         switch (active) {
1187         default:
1188         case VERT_BLANKING:
1189                 while (p < (buf + samples)) {
1190                         *p++ = 512;
1191                         *p++ = 64;
1192                         *p++ = 512;
1193                         *p++ = 64;
1194                 }
1195                 break;
1196         case ACTIVE_VIDEO:
1197
1198         {
1199
1200                 while (p < (buf + samples)) {
1201
1202                         if (active_video_line >= info->fmt->active_lines_per_frame) {
1203                                 active_video_line = info->fmt->active_lines_per_frame - 1;
1204                         }
1205
1206                         //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1;
1207                         //                      *p++ = sample > 1440 ? 735 : (video_buffer[sample] << 2);
1208                         //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1;
1209                         //                      *p++ = sample > 1440 ? 335 : (video_buffer[sample] << 2);
1210                         //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1;
1211                         //                      *p++ = sample > 1440 ? 793 : (video_buffer[sample] << 2);
1212                         //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1;
1213                         //                      *p++ = sample > 1440 ? 335 : (video_buffer[sample] << 2);
1214
1215                         *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1] << 2; // Cb
1216                         p++;
1217                         // check values, but need manny resources
1218                         //                      if (*(p - 1) < 0x040)
1219                         //                              *(p - 1) = 0x040;
1220                         //                      if (*(p - 1) > 0x3c0)
1221                         //                              *(p - 1) = 0x3c0;
1222                         //
1223                         *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1] << 2; // Y1
1224                         p++;
1225                         //                      if (*(p - 1) < 0x040)
1226                         //                              *(p - 1) = 0x040;
1227                         //                      if (*(p - 1) > 0x3ac)
1228                         //                              *(p - 1) = 0x3ac;
1229                         //
1230                         *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1] << 2; // Cr
1231                         p++;
1232                         //                      if (*(p - 1) < 0x040)
1233                         //                              *(p - 1) = 0x040;
1234                         //                      if (*(p - 1) > 0x3c0)
1235                         //                              *(p - 1) = 0x3c0;
1236                         //
1237                         *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1] << 2; // Y2
1238                         p++;
1239                         //                      if (*(p - 1) < 0x040)
1240                         //                              *(p - 1) = 0x040;
1241                         //                      if (*(p - 1) > 0x3ac)
1242                         //                              *(p - 1) = 0x3ac;
1243                 }
1244         }
1245                 break;
1246         }
1247         return 0;
1248 }
1249
1250 static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DBN, int16_t *audio_buffer_A, int16_t *audio_buffer_B, int16_t AudioGroupCounter,
1251                 int16_t AudioGroups2Write) {
1252
1253         /**
1254          * ANC Ancillary Data (vgl. SMPTE 291-M page 6 )
1255          * [ADF][ADF][ADF][DID][DBN][DC][UDW]...[UDW][CS]
1256          *
1257          **/
1258
1259         // save only current position for return value
1260         uint16_t *pp = p;
1261         // 16bit buffer to write temporarily 10bit word
1262         uint16_t buffer = 0; // set all explicit to zero, special the bit9 for parity
1263         // parity_counter
1264         int8_t parity_counter = 0;
1265
1266         if (AudioGroups2Write > 0) {
1267
1268                 // 3 ADF        (Ancillary Data Flag)
1269                 *p++ = 0x000;
1270                 *p++ = 0x3FF;
1271                 *p++ = 0x3FF;
1272
1273                 // 1 DID        (Data Identification)
1274                 // save DID for checker()
1275                 uint16_t *DID_pointer = p;
1276                 *p++ = DID;// (AES Audio Data, Group
1277                 //              *p++ = 0x2FF; // (AES Audio Data, Group1=0x2FF)
1278                 //              *p++ = 0x1FD;   // (AES Audio Data, Group2=0x1FD)
1279                 //              *p++ = 0x1FB;   // (AES Audio Data, Group3=0x1FB)
1280                 //              *p++ = 0x2F9;   // (AES Audio Data, Group4=0x2F9)
1281
1282                 // 1 DBN        (Data Block Number) inactiv: 1000000000 b9,b8,b7-b0     ; SMPTE 272-M chapter15.1
1283                 //              *p++ = 0x200;
1284
1285                 // 1 DBN (dynamic version0.1-beta ), should start with previus DBN of SDI-Frame
1286                 //      -need "previus DBN" or "current framenumber"
1287                 //              SDI-LINE:       DBN:
1288                 //              [1]                     [1]             << start sdi frame
1289                 //              [2]                     [2]
1290                 //              [.]                     [.]
1291                 //              [255]           [255]
1292                 //              [256]           [1]
1293                 //              [257]           [2]
1294                 //              [.]                     [.]
1295                 //              [510]           [255]
1296                 //              [511]           [1]
1297                 //              [512]           [2]
1298                 //              [.]                     [.]
1299                 //              [625]           [115]   << end sdi frame
1300                 //              [1]                     [116]   << start sdi frame
1301                 // Accuracy of videoline_sdiframe(1 up to 625) to 8bit (1-255)
1302                 //buffer = ((videoline_sdiframe-1) % 255)+1;
1303                 buffer = my_DBN;
1304                 parity_counter = 0;
1305                 // count binary ones for parity
1306                 int i = 0;
1307                 for (i = 0; i < 8; i++) {
1308                         if (buffer & (1 << i))
1309                                 parity_counter++;
1310                 }
1311                 if ((parity_counter % 2) == 0) { //else leave the 0
1312                         buffer += 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1313                 } else {
1314                         buffer += 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1315                 }
1316                 *p++ = buffer;
1317
1318                 // 1 DC         (Data Counter)
1319                 // number of UDW = AudioGroups2Write x 2AESFrames x 2channesl x 3words(X,X+1,X+2)
1320                 buffer = AudioGroups2Write * 2* 2* 3 ; parity_counter= 0;
1321                 // count binary ones for parity
1322                 for (i=0; i<8; i++) {
1323                         if (buffer & (1 << i))
1324                         parity_counter++;
1325                 }
1326                 if ((parity_counter%2)==0) { //else leave the 0
1327                         buffer+= 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1328                 } else {
1329                         buffer+= 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1330                 }
1331                 *p++ = buffer;
1332
1333                 int16_t sample_number=0;
1334                 int16_t counter = 0;
1335                 // write subframes:
1336                 // = n x 1 AudioGroup
1337                 // = n x 2 x 1AESFrame
1338                 // = n x 2 x 2samples
1339                 // = 4 samples
1340                 // = 4 x 3words
1341                 while (counter < AudioGroups2Write*2) { /* 4:3 */
1342
1343                         // write one Audio Group with 4 x AES subframes
1344                         // ( samples for ch01,ch02,ch03,ch04 or ch05,ch06,ch07,ch08 or ch09,ch10,ch11,ch12 or ch13,ch14,ch15,ch16)
1345                         // and use audio_buffer_A(stereo) and audio_buffer_B(stereo)
1346                         // `pack_AES_subframe()` write 3 ANC words (3*10bit), also 1 sample
1347
1348                         sample_number=(AudioGroupCounter*2)+ counter;
1349                         pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 1),
1350                                         getZBit(sample_number/2), 0, &audio_buffer_A[sample_number]); // left
1351                         p+=3; // step 3 words
1352
1353                         sample_number=(AudioGroupCounter*2)+ counter+1;
1354                         pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 2),
1355                                         getZBit(sample_number/2), 1, &audio_buffer_A[sample_number]); // right
1356                         p+=3;
1357
1358                         sample_number=(AudioGroupCounter*2)+ counter;
1359                         pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 3),
1360                                         getZBit(sample_number/2), 2, &audio_buffer_B[sample_number]); // left
1361                         p+=3;
1362
1363                         sample_number=(AudioGroupCounter*2)+ counter+1;
1364                         pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 4),
1365                                         getZBit(sample_number/2), 3, &audio_buffer_B[sample_number]); // right
1366                         p+=3;
1367                         counter+=2;
1368                 }
1369
1370                 // 1 CS         (Checksum from DID - UDW)
1371                 *p++ = checker(DID_pointer);
1372
1373                 // fill ANC with one dummy for videocolor black
1374                 // rest until end of `ANCILLARY_DATA_SAMPLES` will be fill in a loop after call this function
1375                 *p++ = 0x040;
1376         }
1377         return p-pp;
1378 }
1379
1380 // calculate checksumm of ANC (SMPTE 272-M 15.3 Checksum (CS))
1381 static uint16_t checker(uint16_t *DID_pointer) {
1382
1383         // Checksumm
1384         uint16_t cs = 0x00;
1385
1386         // DID - Datablock Identification
1387         cs += (*DID_pointer++) & 0x1FF; // 9 x LSB
1388
1389         // DBN - Datablock Number
1390         cs += (*DID_pointer++) & 0x1FF; // 9 x LSB
1391
1392         // DC - DataCounter
1393         cs += (*DID_pointer) & 0x1FF; // 9 x LSB
1394
1395         // store address of DC an ad to the real value of DC
1396         // DataCounter store
1397         // ´ende´ point to DataCounter
1398         uint16_t *ende = DID_pointer;
1399         // ´ende´ point to last field
1400         ende += (*DID_pointer) & 0xFF; // without parity-Bit and ¬9-Bit
1401
1402         DID_pointer++;
1403
1404         // while DID_pointer point to smaller addres like 'ende'
1405         while (DID_pointer <= ende) {
1406                 cs += (*DID_pointer++) & 0x1FF; // 9 x LSB
1407         }
1408
1409         // limit to 9Bit, because of overflow of sum
1410         cs = cs & 0x1FF;
1411
1412         // set bit10 NOT bit9:
1413         // - cs invert
1414         // - & with bitmask '01 0000 0000'
1415         // - shift rest (1xbit)to left
1416         // - add to cs
1417         cs += ((~cs) & 0x100) << 1;
1418
1419         return cs;
1420 } // end checker
1421
1422
1423 /**
1424  * pack 16bit in AES subframe with 3 words (30 bit) and write in ´*p´
1425  * 10bit-words --> [X],[X+1], [X+2] implements 20bit for audio
1426  *
1427  *                      BIT       9,     8,   7,   6,   5,   4,   3,   2,   1,   0
1428  *                                #####  ###  ###  ###  ###  ###  ###  ###  ###  ###
1429  *      [X]             :       [ !bit8, a5,  a4,  a3,  a2,  a1,  a0,  ch0, ch1, z   ],
1430  *      [X+1]   :       [ !bit8, a14, a13, a12, a11, a10, a9,  a8,  a7 , a6  ],
1431  *      [X+2]   :       [ !bit8, P,   C,   U,   V,   a19, a18, a17, a16, a15 ]
1432  *
1433  * @param *p: Pointer to SDI frame buffer
1434  * @param c: value of AES subframe Channel Status Bit
1435  * @param z: value of AES subframe
1436  * @param ch: channel od AES subframe (value:0,1,2,3)
1437  * @param *audio_samplex: pointer to the audio buffer
1438  **/
1439 static int pack_AES_subframe(uint16_t *p, int8_t c, int8_t z, int8_t ch, int16_t *audio_samplex) {
1440
1441         /**
1442          *  NOTE: WE JUST SUPPORT ONLY 16BIT SAMPLE SIZE
1443          **/
1444
1445         // push 16bit up to 20bit(32bit)
1446         int32_t audio_sample = *audio_samplex;
1447         audio_sample = audio_sample << 4; // Shift by 4 (louder)
1448
1449         // parity_counter
1450         int8_t parity_counter = 0;
1451
1452         // 16bit buffer to write 10bit of [X]word,[X+1]word,[X+2]word,
1453         uint16_t buffer = 0;
1454
1455         //#########################################################
1456         //### WORD X  ############################################
1457         //#########################################################
1458         // word X: !bit8, a5, a4, a3, a2, a1, a0, ch1, ch0, z
1459         // SMPTE 272M s.7
1460         buffer = z; // z bit every 192bit = 1
1461         buffer += ch << 1; // ch1 - ch0
1462         buffer += (audio_sample & 0x3f) << 3; // a5 - a0
1463         buffer += ((~buffer) & 0x100) << 1; // !bit8
1464
1465         // write word ´X´
1466         *p++ = buffer;
1467
1468         // count ones
1469         int i = 0;
1470         for (i = 0; i < 9; i++) {
1471                 if (buffer & 1 << i)
1472                         parity_counter++;
1473         }
1474
1475         //#########################################################
1476         //### WORD X+1 ############################################
1477         //#########################################################
1478         // word X+1: !bit8, a14, a13, a12, a11, a10, a9, a8, a7, a6
1479         // SMPTE 272M s.7
1480         buffer = 0;
1481         buffer += (audio_sample >> 6) & 0x1ff; // a14 - a6
1482         buffer += ((~buffer) & 0x100) << 1; // !bit8
1483
1484         // write word ´X+1´
1485         *p++ = buffer;
1486
1487         // count ones (zähle Einsen)
1488         i = 0;
1489         for (i = 0; i < 9; i++) {
1490                 if (buffer & 1 << i)
1491                         parity_counter++;
1492         }
1493
1494         //#########################################################
1495         //### WORD X+2 ############################################
1496         //#########################################################
1497         // word X+2: !bit8, P, C, U, V, a19, a18, a17, a16, a15
1498         // SMPTE 272M s.7
1499         buffer = 0;
1500         buffer += (audio_sample >> 15) & 0x01F; // a15 - a19
1501         // default of [V][U][C] bits = `0`
1502         //buffer += 1<<5;       // V (AES sample validity bit)
1503         //buffer += 1<<6;       // U (AES user bit)
1504         //buffer += 1<<7;       // C (AES audio channel status bit)
1505         buffer += c << 7; // C (AES audio channel status bit)
1506
1507         // count ones (zähle Einsen)
1508         for (i = 0; i < 8; i++) {
1509                 if (buffer & 1 << i)
1510                         parity_counter++;
1511         }
1512
1513         //      if (!parity_counter%2) //else leave the 0
1514         //              buffer+= 1 << 8; // P (AES even parity bit)
1515         //
1516         //      buffer += ((~buffer) & 0x100 )<<1; // !bit8
1517         if ((parity_counter % 2) == 0) { //else leave the 0
1518                 buffer += 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1519         } else {
1520                 buffer += 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
1521         }
1522         *p++ = buffer;
1523
1524         // write word ´X+2´
1525         *p++ = buffer;
1526
1527         return 1;
1528 }
1529
1530 static uint8_t getZBit(int sample_number) {
1531
1532         // start in SDI line 6 also 18samples later
1533         //sample_number+=192-18;
1534
1535         if (sample_number % 192 == 0) {
1536                 //printf("1 %i\n", sample_number);
1537                 return 1;
1538         } else {
1539                 //printf("0");
1540                 return 0;
1541         }
1542 }
1543
1544 static uint8_t getChannelStatusBit(uint16_t sample_number, uint8_t ch) {
1545
1546         // return value
1547         uint8_t AESChannelStatusBit = 0;
1548
1549         // start in SDI line 6 also 18samples later
1550         //AESChannelStatusBit=((sample_number+192-18)%192);
1551         // interval in 192bit
1552         AESChannelStatusBit = sample_number % 192;
1553
1554         // when mulichannelmode is true
1555         if (AESChannelStatusBitArray[31] == 1) {
1556                 // set bits for channel
1557                 if (AESChannelStatusBit == 30 && ch == 2)
1558                         return 1;
1559                 if (AESChannelStatusBit == 30 && ch == 4)
1560                         return 1;
1561                 if (AESChannelStatusBit == 29 && (ch == 4))
1562                         return 1;
1563                 if (AESChannelStatusBit == 29 && (ch == 3))
1564                         return 1;
1565         }
1566         return AESChannelStatusBitArray[AESChannelStatusBit];
1567 }
1568
1569 static int16_t getNumberOfAudioGroups2Write(int linenumber) {
1570
1571         // `4:3_VTR`-distribution
1572         if (linenumber >= 11 && linenumber <= 95) {
1573                 if ((linenumber - 11) % 14 == 0) {
1574                         return 4;
1575                 } else {
1576                         return 3;
1577                 }
1578         } else if (linenumber >= 108 && linenumber <= 220) {
1579                 if ((linenumber - 10) % 14 == 0) {
1580                         return 4;
1581                 } else {
1582                         return 3;
1583                 }
1584         } else if (linenumber >= 233 && linenumber <= 345) {
1585                 if ((linenumber - 9) % 14 == 0) {
1586                         return 4;
1587                 } else {
1588                         return 3;
1589                 }
1590         } else if (linenumber >= 358 && linenumber <= 470) {
1591                 if ((linenumber - 8) % 14 == 0) {
1592                         return 4;
1593                 } else {
1594                         return 3;
1595                 }
1596         } else if (linenumber >= 483 && linenumber <= 595) {
1597                 if ((linenumber - 7) % 14 == 0) {
1598                         return 4;
1599                 } else {
1600                         return 3;
1601                 }
1602         } else if (linenumber >= 608 && linenumber <= 622) {
1603                 if ((linenumber - 6) % 14 == 0) {
1604                         return 4;
1605                 } else {
1606                         return 3;
1607                 }
1608         } else {
1609                 return 3;
1610         }
1611
1612         //      // `4:3`-distribution
1613         //      if(linenumber<=315){
1614         //              if(linenumber>=6 && linenumber<=8){
1615         //                      return 0;
1616         //              }
1617         //              if((linenumber+5)%10==0){
1618         //                      return 4;
1619         //              }else{
1620         //                      return 3;
1621         //              }
1622         //      }else{
1623         //              if(linenumber>=319 && linenumber<=321){
1624         //                      return 0;
1625         //              }
1626         //              if((linenumber-8)%10==0){
1627         //                      return 4;
1628         //              }else{
1629         //                      return 3;
1630         //              }
1631         //      }
1632
1633         //      // full-distribution
1634         //      if(linenumber<=45){
1635         //              return 4;
1636         //      }else{
1637         //              return 3;
1638         //      }
1639
1640         //      // fullhalf-distribution
1641         //      if (linenumber==625)
1642         //              return 4;
1643         //
1644         //      if (linenumber%14==0) {
1645         //              return 4;
1646         //      } else {
1647         //              return 3;
1648         //      }
1649
1650 }
1651 static uint8_t getDBN(int my_DBN) {
1652
1653         return ((my_DBN - 1) % 255) + 1;
1654 }
1655
1656 /**
1657  * pack8 - pack a line of 8-bit data
1658  * @outbuf: pointer to the output buffer
1659  * @inbuf: pointer to the input buffer
1660  * @count: number of elements in the buffer
1661  *
1662  * Returns a pointer to the next output location.
1663  **/
1664 static inline uint8_t *
1665 pack8(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
1666         uint16_t *inp = inbuf;
1667         uint8_t *outp = outbuf;
1668
1669         while (inp < (inbuf + count)) {
1670                 *outp++ = *inp++ >> 2;
1671         }
1672         return outp;
1673 }
1674
1675 /**
1676  * pack10 - pack a line of 10-bit data
1677  * @outbuf: pointer to the output buffer
1678  * @inbuf: pointer to the input buffer
1679  * @count: number of elements in the buffer
1680  *
1681  * Returns a pointer to the next output location.
1682  **/
1683 static inline uint8_t * pack10(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
1684
1685         uint16_t *inp = inbuf;
1686         uint8_t *outp = outbuf;
1687
1688         while (inp < (inbuf + count)) {
1689                 *outp++ = *inp & 0xff;
1690                 *outp = *inp++ >> 8;
1691                 *outp++ += (*inp << 2) & 0xfc;
1692                 *outp = *inp++ >> 6;
1693                 *outp++ += (*inp << 4) & 0xf0;
1694                 *outp = *inp++ >> 4;
1695                 *outp++ += (*inp << 6) & 0xc0;
1696                 *outp++ = *inp++ >> 2;
1697         }
1698
1699         return outp;
1700 }
1701 /**
1702  * pack_v210 - pack a line of v210 data
1703  * @outbuf: pointer to the output buffer
1704  * @inbuf: pointer to the input buffer
1705  * @count: number of elements in the buffer
1706  *
1707  * Returns a pointer to the next output location.
1708  **/
1709 static inline uint8_t * pack_v210(uint8_t *outbuf, uint16_t *inbuf, size_t count) {
1710
1711         uint16_t *inp = inbuf;
1712         uint8_t *outp = outbuf;
1713
1714         count = (count / 96) * 96 + ((count % 96) ? 96 : 0);
1715         while (inp < (inbuf + count)) {
1716                 *outp++ = *inp & 0xff;
1717                 *outp = *inp++ >> 8;
1718                 *outp++ += (*inp << 2) & 0xfc;
1719                 *outp = *inp++ >> 6;
1720                 *outp++ += (*inp << 4) & 0xf0;
1721                 *outp++ = *inp++ >> 4;
1722         }
1723         return outp;
1724 }
1725
1726 // Clean up
1727 static int sdimaster_close() {
1728
1729         free(line_buffer);
1730         free(data);
1731
1732         if (fh_sdi_audio)
1733                 close(fh_sdi_audio);
1734         if (fh_sdi_video)
1735                 close(fh_sdi_video);
1736
1737         return 1;
1738 }
1739
1740 /**
1741  * mkline - generate one line
1742  * @buf: pointer to a buffer
1743  * @info: pointer to a line information structure
1744  * @pattern: pattern
1745  *
1746  * Returns a negative error code on failure and zero on success.
1747  **/
1748 static int mkline(unsigned short int *buf, const struct line_info *info, unsigned int pattern) {
1749         const unsigned int b = 205;
1750         unsigned short int *p = buf, *endp;
1751         unsigned int samples = info->blanking ? info->fmt->samples_per_line : info->fmt->active_samples_per_line;
1752
1753         if (info->blanking) {
1754                 /* EAV */
1755                 *p++ = 0x3ff;
1756                 *p++ = 0x000;
1757                 *p++ = 0x000;
1758                 *p++ = info->xyz->eav;
1759                 /* Horizontal blanking */
1760                 while (p < (buf + 272)) {
1761                         *p++ = 0x200;
1762                         *p++ = 0x040;
1763                         *p++ = 0x200;
1764                         *p++ = 0x040;
1765                 }
1766                 /* SAV */
1767                 *p++ = 0x3ff;
1768                 *p++ = 0x000;
1769                 *p++ = 0x000;
1770                 *p++ = info->xyz->sav;
1771         }
1772         /* Active region */
1773         endp = p;
1774         switch (pattern) {
1775         default:
1776         case VERT_BLANKING:
1777                 while (p < (buf + samples)) {
1778                         *p++ = 0x200;
1779                         *p++ = 0x040;
1780                         *p++ = 0x200;
1781                         *p++ = 0x040;
1782                 }
1783                 break;
1784         case BLACK:
1785                 while (p < (buf + samples)) {
1786                         *p++ = 0x200;
1787                         *p++ = 0x040;
1788                         *p++ = 0x200;
1789                         *p++ = 0x040;
1790                 }
1791                 break;
1792         case MAIN_SET:
1793                 /* 75% gray */
1794                 endp += b + 1;
1795                 while (p < endp) {
1796                         *p++ = 512;
1797                         *p++ = 721;
1798                         *p++ = 512;
1799                         *p++ = 721;
1800                 }
1801                 /* 75% yellow */
1802                 endp += b + 1;
1803                 while (p < endp) {
1804                         *p++ = 176;
1805                         *p++ = 646;
1806                         *p++ = 567;
1807                         *p++ = 646;
1808                 }
1809                 /* 75% cyan */
1810                 endp += b + 1;
1811                 while (p < endp) {
1812                         *p++ = 625;
1813                         *p++ = 525;
1814                         *p++ = 176;
1815                         *p++ = 525;
1816                 }
1817                 /* 75% green */
1818                 endp += b - 1;
1819                 while (p < endp) {
1820                         *p++ = 289;
1821                         *p++ = 450;
1822                         *p++ = 231;
1823                         *p++ = 450;
1824                 }
1825                 /* 75% magenta */
1826                 endp += b + 1;
1827                 while (p < endp) {
1828                         *p++ = 735;
1829                         *p++ = 335;
1830                         *p++ = 793;
1831                         *p++ = 335;
1832                 }
1833                 /* 75% red */
1834                 endp += b + 1;
1835                 while (p < endp) {
1836                         *p++ = 399;
1837                         *p++ = 260;
1838                         *p++ = 848;
1839                         *p++ = 260;
1840                 }
1841                 /* 75% blue */
1842                 while (p < (buf + samples)) {
1843                         *p++ = 848;
1844                         *p++ = 139;
1845                         *p++ = 457;
1846                         *p++ = 139;
1847                 }
1848                 break;
1849         case CHROMA_SET:
1850                 /* 75% blue */
1851                 endp += b + 1;
1852                 while (p < endp) {
1853                         *p++ = 848;
1854                         *p++ = 139;
1855                         *p++ = 457;
1856                         *p++ = 139;
1857                 }
1858                 /* black */
1859                 endp += b + 1;
1860                 while (p < endp) {
1861                         *p++ = 0x200;
1862                         *p++ = 0x040;
1863                         *p++ = 0x200;
1864                         *p++ = 0x040;
1865                 }
1866                 /* 75% magenta */
1867                 endp += b + 1;
1868                 while (p < endp) {
1869                         *p++ = 735;
1870                         *p++ = 335;
1871                         *p++ = 793;
1872                         *p++ = 335;
1873                 }
1874                 /* black */
1875                 endp += b - 1;
1876                 while (p < endp) {
1877                         *p++ = 0x200;
1878                         *p++ = 0x040;
1879                         *p++ = 0x200;
1880                         *p++ = 0x040;
1881                 }
1882                 /* 75% cyan */
1883                 endp += b + 1;
1884                 while (p < endp) {
1885                         *p++ = 625;
1886                         *p++ = 525;
1887                         *p++ = 176;
1888                         *p++ = 525;
1889                 }
1890                 /* black */
1891                 endp += b + 1;
1892                 while (p < endp) {
1893                         *p++ = 0x200;
1894                         *p++ = 0x040;
1895                         *p++ = 0x200;
1896                         *p++ = 0x040;
1897                 }
1898                 /* 75% gray */
1899                 while (p < (buf + samples)) {
1900                         *p++ = 512;
1901                         *p++ = 721;
1902                         *p++ = 512;
1903                         *p++ = 721;
1904                 }
1905                 break;
1906         case BLACK_SET:
1907                 /* -I */
1908                 endp += 257;
1909                 while (p < endp) {
1910                         *p++ = 624;
1911                         *p++ = 231;
1912                         *p++ = 390;
1913                         *p++ = 231;
1914                 }
1915                 /* white */
1916                 endp += 257;
1917                 while (p < endp) {
1918                         *p++ = 0x200;
1919                         *p++ = 940;
1920                         *p++ = 0x200;
1921                         *p++ = 940;
1922                 }
1923                 /* +Q */
1924                 endp += 257;
1925                 while (p < endp) {
1926                         *p++ = 684;
1927                         *p++ = 177;
1928                         *p++ = 591;
1929                         *p++ = 177;
1930                 }
1931                 /* black */
1932                 endp += 257;
1933                 while (p < endp) {
1934                         *p++ = 0x200;
1935                         *p++ = 0x040;
1936                         *p++ = 0x200;
1937                         *p++ = 0x040;
1938                 }
1939                 /* blacker than black */
1940                 endp += 68;
1941                 while (p < endp) {
1942                         *p++ = 0x200;
1943                         *p++ = 29;
1944                         *p++ = 0x200;
1945                         *p++ = 29;
1946                 }
1947                 /* black */
1948                 endp += 68 + 2;
1949                 while (p < endp) {
1950                         *p++ = 0x200;
1951                         *p++ = 0x040;
1952                         *p++ = 0x200;
1953                         *p++ = 0x040;
1954                 }
1955                 /* whiter than black */
1956                 endp += 68;
1957                 while (p < endp) {
1958                         *p++ = 0x200;
1959                         *p++ = 99;
1960                         *p++ = 0x200;
1961                         *p++ = 99;
1962                 }
1963                 /* black */
1964                 while (p < (buf + samples)) {
1965                         *p++ = 0x200;
1966                         *p++ = 0x040;
1967                         *p++ = 0x200;
1968                         *p++ = 0x040;
1969                 }
1970                 break;
1971         }
1972         return 0;
1973 }