* System No. System nomenclature Form of scanning Frame rate Embedded Audio MLT profile Linsys board support (model)
* SD PAL 720 × 576/50/I interlaced 25 HZ 8 x AES (16 channels) dv_pal 180,145,159,107
* SD PAL 720 × 576/50/I interlaced 25 HZ 4 x AES (8 channels) dv_pal 193
- * SD NTSC 720 × 480/59.94/I interlaced 30000/1001 ~ 29.97 HZ 8 x AES (16 channels) sdi_486i_5994 TODO:180,145,159,107
- * SD NTSC 720 × 480/59.94/I interlaced 30000/1001 ~ 29.97 HZ 4 x AES (8 channels) sdi_486i_5994 193
+ * SD NTSC 720 × 486/59.94/I interlaced 30000/1001 ~ 29.97 HZ 8 x AES (16 channels) sdi_486i_5994 TODO:180,145,159,107
+ * SD NTSC 720 × 486/59.94/I interlaced 30000/1001 ~ 29.97 HZ 4 x AES (8 channels) sdi_486i_5994 193
*
**/
#include "sdi_generator.h"
-/*!/brief Initialization of the file handlers for the Playout
+/*!/brief initialization of the file handlers for the playout
* @param *device_video: file or SDITX device or SDIVIDEOTX device
* @param *device_audio: file or SDIAUDIOTX device
* @param blanking: true or false (if false the consumer write only active video data without any VANH or HANC)
*/
-static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, mlt_profile myProfile) {
+static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, mlt_profile myProfile,
+ const struct audio_format * audio_format) {
// set device file
device_file_video = device_video;
device_file_audio = device_audio;
- // set flag for using of blanking with anilary data
+ // set flag for using of blanking with ancillary data
info.blanking = blanking;
- // set pack methode for SDI word conversion
- //pack = pack8;
+ // set pack method for SDI word conversion
+ pack = pack8;
//pack = pack10;
- pack = pack_v210;
+ //pack = pack_v210;
// check format
- if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1 && myProfile->progressive
- == 0) {
- info.fmt = &FMT_1080i60;
- } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
+ if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 0) {
+ info.fmt = &FMT_1080i60;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_60HZ;
+ } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+ == 1001 && myProfile->progressive == 0) {
info.fmt = &FMT_1080i5994;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_59_94HZ;
} else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 0) {
info.fmt = &FMT_1080i50;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080I_50HZ;
} else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 1) {
info.fmt = &FMT_1080p30;
- } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
- && myProfile->progressive == 1) {
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_30HZ;
+ } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+ == 1001 && myProfile->progressive == 1) {
info.fmt = &FMT_1080p2997;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_29_97HZ;
} else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 1) {
info.fmt = &FMT_1080p25;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_25HZ;
} else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 1) {
info.fmt = &FMT_1080p24;
- } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den == 1001
- && myProfile->progressive == 1) {
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_24HZ;
+ } else if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den
+ == 1001 && myProfile->progressive == 1) {
info.fmt = &FMT_1080p2398;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_274M_1080P_23_98HZ;
} else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 1) {
info.fmt = &FMT_720p60;
- } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60000 && myProfile->frame_rate_den == 1001
- && myProfile->progressive == 1) {
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_60HZ;
+ } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 60000 && myProfile->frame_rate_den
+ == 1001 && myProfile->progressive == 1) {
info.fmt = &FMT_720p5994;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_59_94HZ;
} else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 50 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 1) {
info.fmt = &FMT_720p50;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_50HZ;
} else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 1) {
info.fmt = &FMT_720p30;
- } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
- && myProfile->progressive == 1) {
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_30HZ;
+ } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+ == 1001 && myProfile->progressive == 1) {
info.fmt = &FMT_720p2997;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_29_97HZ;
} else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 1) {
info.fmt = &FMT_720p25;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_25HZ;
} else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 1) {
info.fmt = &FMT_720p24;
- } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den == 1001
- && myProfile->progressive == 1) {
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_24HZ;
+ } else if (myProfile->width == 1280 && myProfile->height == 720 && myProfile->frame_rate_num == 24000 && myProfile->frame_rate_den
+ == 1001 && myProfile->progressive == 1) {
info.fmt = &FMT_720p2398;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_296M_720P_23_98HZ;
} else if (myProfile->width == 720 && myProfile->height == 576 && myProfile->frame_rate_num == 25 && myProfile->frame_rate_den == 1
&& myProfile->progressive == 0) {
info.fmt = &FMT_576i50;
- } else if (myProfile->width == 720 && myProfile->height == 480 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den == 1001
- && myProfile->progressive == 0) {
+ sdi_frame_mode = SDIVIDEO_CTL_BT_601_576I_50HZ;
+ } else if (myProfile->width == 720 && myProfile->height == 486 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+ == 1001 && myProfile->progressive == 0) {
+ info.fmt = &FMT_486i5994;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_125M_486I_59_94HZ;
+ } else if (myProfile->width == 720 && myProfile->height == 480 && myProfile->frame_rate_num == 30000 && myProfile->frame_rate_den
+ == 1001 && myProfile->progressive == 0) {
info.fmt = &FMT_480i5994;
+ sdi_frame_mode = SDIVIDEO_CTL_SMPTE_125M_486I_59_94HZ;
} else {
- printf("Consumer gets unknown format: %s", myProfile->description);
+ printf("Consumer got unknown format: %s", myProfile->description);
info.fmt = &FMT_576i50;
+ sdi_frame_mode = SDIVIDEO_CTL_BT_601_576I_50HZ;
}
- printf("Consumer use format: %s\nProfile: %i %i %i %i %i\n", myProfile->description, myProfile->width, myProfile->height, myProfile->frame_rate_num,
- myProfile->frame_rate_den, myProfile->progressive);
+ printf("Consumer use format: %s\nProfile: %i %i %i %i %i\n", myProfile->description, myProfile->width, myProfile->height,
+ myProfile->frame_rate_num, myProfile->frame_rate_den, myProfile->progressive);
- // Check if the format support own blanking (note: model 193 support currently only active video at the video device file)
+ // Check if the format supports own blanking (note: model 193 supports currently only active video at the video device file)
if (info.blanking && info.fmt != &FMT_576i50) {
- printf("SDI consumer doesn't support blanking(HANC) for this configurred SD board and SDI format. Try arguemnt: blanking=false\n");
+ printf("SDI consumer doesn't support blanking(HANC) for the configured SD board and SDI format. Try argument: blanking=false\n");
return EXIT_FAILURE;
}
- if (device_file_video != NULL) {
- // open file handler for SDI(video) output
- if ((fh_sdi_video = open(device_file_video, O_WRONLY)) == -1) {
- perror(NULL);
- printf("\ncould not open video output destination: %s\n", device_file_video);
- }
- printf("SDI consumer use video device file: %s\n", device_file_video);
- }
-
- // Check if seperat device file for audio must use
- if (device_file_audio != NULL) {
- // open file handler for audio output
- if ((fh_sdi_audio = open(device_file_audio, O_WRONLY | O_CREAT, 0777)) == -1) {
- perror(NULL);
- printf("\ncould not open audio output destination: %s\n", device_file_audio);
- return EXIT_FAILURE;
- }
- printf("SDI consumer use audio device file: %s\n", device_file_audio);
- }
-
// if we write our own HANC we need an AES channel status bit array
if (info.blanking) {
AESChannelStatusBitArray[i] = 0;
/**
- * Professionel Format - Channel Status Bits
+ * Professional Format - Channel Status Bits
**/
////// Byte 0 //////
AESChannelStatusBitArray[0] = 1; // professional format
AESChannelStatusBitArray[5] = 0; // locked
- AESChannelStatusBitArray[6] = 0; // sample frequncy Fs: [01]48kHz, [10]44kHz, [11]32kHz
+ AESChannelStatusBitArray[6] = 0; // sample frequency Fs: [01]48kHz, [10]44kHz, [11]32kHz
AESChannelStatusBitArray[7] = 1; // ^
////// Byte 1 //////
AESChannelStatusBitArray[8] = 0; // channel mode: [0000] not indicated, [0001]2channels, [0010]1channel mono, ...
line_buffer = (uint16_t*) calloc(info.fmt->samples_per_line, sizeof(uint16_t));
// calculate and set buffer for the complete SDI frame
- if (info.fmt != &FMT_576i50 && info.fmt != &FMT_480i5994) {
+ if (info.fmt != &FMT_576i50 && info.fmt != &FMT_486i5994) {
if (info.blanking) {
if (pack == pack_v210) {
samples = (info.fmt->samples_per_line / 96 * 48) + ((info.fmt->samples_per_line % 96) ? 48 : 0);
}
}
- // hack/overwrite because we use default the pack_v210() not as befor the pack10()
- //(*10/8 because we store (TOTAL_SAMPLES*TOTAL_LINES) words with 10 bit in this 8 bit array) )
+ // (*10/8 because we store (TOTAL_SAMPLES*TOTAL_LINES) words with 10 bit in this 8 bit array) )
if (info.fmt == &FMT_576i50 && info.blanking) {
sdi_frame_size = info.fmt->samples_per_line * 10 / 8 * info.fmt->lines_per_frame;
}
- printf("SDI frame size:%li\n", sdi_frame_size);
+ if (info.blanking) {
+ printf("SDI frame size: %"PRIu64"\n", sdi_frame_size);
+ } else {
+ printf("Frame size for active video: %"PRIu64"\n", sdi_frame_size);
+ }
+
+ /**
+ * Setup HD-SDI Master device (vidport):
+ *
+ * if device_file_video available then
+ * if vidport available
+ * 1. setup
+ * end
+ * 1. open device file handler
+ *
+ * if device_file_audio available then
+ * 1. setup
+ * 2. open device file handler
+ * end
+ * end
+ **/
+ if (device_file_video != NULL) {
+
+ // If we use a Linsys HD board with active video (without blanking) setup the board for the used mode
+ if (strstr(device_file_video, "sdivideotx") != NULL && !info.blanking) {
+
+ char * value;
+
+ // Buffer size
+ value = itoa(sdi_frame_size);
+ setSDIVideoProperties(SETTING_BUFFER_SIZE_VIDEO, value, device_video);
+ free(value);
+
+ // Frame Mode
+ value = itoa(sdi_frame_mode);
+ setSDIVideoProperties(SETTING_FRAME_MODE, value, device_video);
+ free(value);
+
+ // Data Mode
+ if (pack == pack8)
+ setSDIVideoProperties(SETTING_DATA_MODE, "0", device_video);
+ else if (pack == pack_v210)
+ setSDIVideoProperties(SETTING_DATA_MODE, "1", device_video);
+ }
+
+ // open file handle for SDI(video) output
+ if ((fh_sdi_video = open(device_file_video, O_WRONLY)) == -1) {
+ perror(NULL);
+ printf("\ncould not open video output destination: %s\n", device_file_video);
+ return EXIT_FAILURE;
+ }
+ printf("SDI consumer uses video device file: %s\n", device_file_video);
+
+ // Check if we have to use a separate device file for audio
+ if (device_file_audio != NULL) {
+
+ // set settings for audio device file
+ if (strstr(device_file_audio, "sdiaudiotx") != NULL && !info.blanking) {
+
+ char * value;
+
+ /**
+ * prepare sample size
+ * MLT suports: 16bit, 32bit
+ * LINSYS SDI boards supports: 16bit, 24bit, 32bit
+ * we set 16bit as default
+ **/
+ uint8_t sample_size = audio_format->aformat == mlt_audio_s32 ? 32 : 16;
+
+ // Buffer size
+ // audio buffer per frame (Bytes) = sample rate / frame rate * ( sample size / 1Byte ) x channels
+ value = itoa(
+ (uint64_t) audio_format->sample_rate / ( (uint64_t) myProfile->frame_rate_num / (uint64_t) myProfile->frame_rate_den) * (uint64_t) sample_size / 8
+ * (uint64_t) audio_format->channels);
+ setSDIAudioProperties(SETTING_BUFFER_SIZE_AUDIO, value, device_audio);
+ free(value);
+
+ // channels
+ value = itoa(audio_format->channels);
+ setSDIAudioProperties(SETTING_CHANNELS, value, device_audio);
+ free(value);
+
+ // sample rate
+ value = itoa(audio_format->sample_rate);
+ setSDIAudioProperties(SETTING_SAMPEL_RATE, value, device_audio);
+ free(value);
+
+ // sample size
+ value = itoa(sample_size);
+ setSDIAudioProperties(SETTING_SAMPLE_SIZE, value, device_audio);
+ free(value);
+ }
+
+ // open file handle for audio output
+ if ((fh_sdi_audio = open(device_file_audio, O_WRONLY)) == -1) {
+ perror(NULL);
+ printf("\nCould not open audio output destination: %s\n", device_file_audio);
+ return EXIT_FAILURE;
+ }
+ printf("SDI consumer uses audio device file: %s\n", device_file_audio);
+ }
+
+ }
// set buffer for the complete SDI frame
data = (uint8_t*) calloc(sdi_frame_size, sizeof(uint8_t));
* @param audio_streams: number of audio streams which have content in aBuffer (available 0-8)
* @return current DBN (data block number of SDI frame)
**/
-static int sdi_playout(uint8_t *vBuffer, int16_t aBuffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], const struct audio_format * audio_format, int audio_streams,
- int my_DBN) {
+static int sdi_playout(uint8_t *vBuffer, int16_t aBuffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], const struct audio_format * audio_format,
+ int audio_streams, int my_DBN) {
// Pointer to the start of data. This is used to fill data line by line
uint8_t *p = data;
info.xyz = &FIELD_1_ACTIVE;
int f1counter = 1; // only odd lines
for (i = 23; i <= 310; i++) {
- create_SD_SDI_Line(line_buffer, &info, FIELD_1, ACTIVE_VIDEO, vBuffer, aBuffer, i, f1counter, getDBN(my_DBN++), AudioGroupCounter,
- getNumberOfAudioGroups2Write(i), audio_streams);
+ create_SD_SDI_Line(line_buffer, &info, FIELD_1, ACTIVE_VIDEO, vBuffer, aBuffer, i, f1counter, getDBN(my_DBN++),
+ AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
AudioGroupCounter += getNumberOfAudioGroups2Write(i);
p = pack10(p, line_buffer, info.fmt->samples_per_line);
f1counter += 2;
int f2counter = 2; // only even Lines
for (i = 336; i <= 623; i++) {
- create_SD_SDI_Line(line_buffer, &info, FIELD_2, ACTIVE_VIDEO, vBuffer, aBuffer, i, f2counter, getDBN(my_DBN++), AudioGroupCounter,
- getNumberOfAudioGroups2Write(i), audio_streams);
+ create_SD_SDI_Line(line_buffer, &info, FIELD_2, ACTIVE_VIDEO, vBuffer, aBuffer, i, f2counter, getDBN(my_DBN++),
+ AudioGroupCounter, getNumberOfAudioGroups2Write(i), audio_streams);
AudioGroupCounter += getNumberOfAudioGroups2Write(i);
p = pack10(p, line_buffer, info.fmt->samples_per_line);
f2counter += 2;
/**
* Generate an SDI NTSC frame
+ *
+ *
+ * 16 lines VERT_BLANKING FIELD_1_VERT_BLANKING
+ * 1 lines VERT_BLANKING FIELD_1_ACTIVE
+ * 3 lines ACTIVE_VIDEO FIELD_1_ACTIVE (opt. video data)
+ * 240 lines ACTIVE_VIDEO FIELD_1_ACTIVE
+ * 2 lines VERT_BLANKING FIELD_1_VERT_BLANKING
+ *
+ * 8 lines VERT_BLANKING FIELD_2_VERT_BLANKING
+ * 9 lines VERT_BLANKING FIELD_2_VERT_BLANKING
+ * 3 lines ACTIVE_VIDEO FIELD_2_ACTIVE (opt. video data)
+ * 240 lines ACTIVE_VIDEO FIELD_2_ACTIVE
+ * 4 lines VERT_BLANKING FIELD_2_VERT_BLANKING
+ *
**/
+
elements = info.fmt->active_samples_per_line;
active_video_line = 1;
}
info.xyz = &FIELD_1_ACTIVE;
- // 3 lines opt. video data
- for (info.ln = 17; info.ln <= 19; info.ln++) {
- mkline(line_buffer, &info, BLACK);
- p = pack(p, line_buffer, elements);
- }
- for (info.ln = 20; info.ln <= 259; info.ln++) {
- create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
- p = pack(p, line_buffer, elements);
- active_video_line += 2;
+
+ // 480 or 486 lines
+ if (info.fmt == &FMT_480i5994) {
+ // 3 lines opt. video data
+ for (info.ln = 17; info.ln <= 19; info.ln++) {
+ mkline(line_buffer, &info, BLACK);
+ p = pack(p, line_buffer, elements);
+ }
+ // 240 lines
+ for (info.ln = 20; info.ln <= 259; info.ln++) {
+ create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+ p = pack(p, line_buffer, elements);
+ active_video_line += 2;
+ }
+ } else {
+ // 243 lines
+ for (info.ln = 17; info.ln <= 259; info.ln++) {
+ create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+ p = pack(p, line_buffer, elements);
+ active_video_line += 2;
+ }
}
if (info.blanking) {
+ // 2 lines vertical data
info.xyz = &FIELD_1_VERT_BLANKING;
for (info.ln = 260; info.ln <= 261; info.ln++) {
create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
p = pack(p, line_buffer, elements);
}
+ // 8 lines vertical data
info.xyz = &FIELD_2_VERT_BLANKING;
- // 7 lines vertical data
for (info.ln = 262; info.ln <= 269; info.ln++) {
create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
p = pack(p, line_buffer, elements);
}
- // 9 lines opt. video data ?? // TODO have look to SMPTE
+ // 9 lines
for (info.ln = 270; info.ln <= 278; info.ln++) {
create_HD_SDI_Line(line_buffer, &info, 0, VERT_BLANKING, vBuffer);
p = pack(p, line_buffer, elements);
}
active_video_line = 0;
- // 3 lines opt. video data
- info.xyz = &FIELD_2_ACTIVE;
- for (info.ln = 279; info.ln <= 281; info.ln++) {
- mkline(line_buffer, &info, BLACK);
- p = pack(p, line_buffer, elements);
- }
- for (info.ln = 282; info.ln <= 521; info.ln++) {
- create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
- p = pack(p, line_buffer, elements);
- active_video_line += 2;
+
+ // 480 or 486 lines
+ if (info.fmt == &FMT_480i5994) {
+ // 3 lines opt. video data
+ info.xyz = &FIELD_2_ACTIVE;
+ for (info.ln = 279; info.ln <= 281; info.ln++) {
+ mkline(line_buffer, &info, BLACK);
+ p = pack(p, line_buffer, elements);
+ }
+ // 240 lines
+ for (info.ln = 282; info.ln <= 521; info.ln++) {
+ create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+ p = pack(p, line_buffer, elements);
+ active_video_line += 2;
+ }
+ } else {
+ // 243 lines
+ for (info.ln = 279; info.ln <= 521; info.ln++) {
+ create_HD_SDI_Line(line_buffer, &info, active_video_line, ACTIVE_VIDEO, vBuffer);
+ p = pack(p, line_buffer, elements);
+ active_video_line += 2;
+ }
}
+ // 4 lines vertical data
if (info.blanking) {
info.xyz = &FIELD_2_VERT_BLANKING;
for (info.ln = 522; info.ln <= 525; info.ln++) {
return -1;
}
bytes += written_bytes;
+ }
- // Check for events of the SDI board
- unsigned int val;
- if (ioctl(fh_sdi_video, SDI_IOC_TXGETEVENTS, &val) < 0) {
- // Maybe this is not an SDI device...
- fprintf(stderr, "SDI VIDEO output:");
- perror("unable to get the transmitter event flags");
- } else if (val) {
- if (val & SDI_EVENT_TX_BUFFER) {
- printf("SDI VIDEO driver transmit buffer queue underrun "
- "detected.\n");
- }
- if (val & SDI_EVENT_TX_FIFO) {
- printf("SDI VIDEO onboard transmit FIFO underrun detected.\n");
- // TODO react
- }
- if (val & SDI_EVENT_TX_DATA) {
- printf("SDI VIDEO transmit data change detected.\n");
- }
+ // Check for events of the SDI board
+ unsigned int val;
+ if (ioctl(fh_sdi_video, SDI_IOC_TXGETEVENTS, &val) < 0) {
+ // Maybe this is not an SDI device...
+ //fprintf(stderr, "SDI VIDEO output:");
+ //perror("unable to get the transmitter event flags");
+ } else if (val) {
+ if (val & SDI_EVENT_TX_BUFFER) {
+ printf("SDI VIDEO driver transmit buffer queue underrun "
+ "detected.\n");
+ fflush(stdout);
+ }
+ if (val & SDI_EVENT_TX_FIFO) {
+ printf("SDI VIDEO onboard transmit FIFO underrun detected.\n");
+ fflush(stdout);
+ }
+ if (val & SDI_EVENT_TX_DATA) {
+ printf("SDI VIDEO transmit data change detected.\n");
+ fflush(stdout);
}
- fflush(stdout);
}
// if available write audio data
written_bytes = 0;
// set number of samples and cut by 1600 if NTSC (handle problem of real time encoding of NTSC frequencies)
- //size_t samples_total_per_track = audio_format->samples == 1601 || audio_format->samples == 1602 ? 1600 : audio_format->samples; // TODO buffer underrun by NTSC frequencs because of 3/2 pull down
size_t samples_total_per_track = audio_format->samples;
uint16_t sample_number = 0;
size_t channels_per_track_total = 2;
// set total bytes per session
size_t bytes_total = 0;
bytes_total = audio_format->aformat == mlt_audio_s16 ? channels_per_track_total * sizeof(int16_t) : bytes_total;
- bytes_total = audio_format->aformat == mlt_audio_s32 ? channels_per_track_total * sizeof(int32_t) : bytes_total; // TODO sdi board must be pre-configured for 32bit samples!!!!
+ bytes_total = audio_format->aformat == mlt_audio_s32 ? channels_per_track_total * sizeof(int32_t) : bytes_total;
// write all samples of all streams interleaved
/**
// n = number of channels per stream
written_bytes = 0;
while (written_bytes < bytes_total) {
- written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[stream_number] + sample_number * bytes_total + written_bytes, bytes_total
- - written_bytes);
+ written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[stream_number] + sample_number * bytes_total + written_bytes,
+ bytes_total - written_bytes);
}
sum_written_bytes += written_bytes;
sum_written_bytes_a += written_bytes;
}
// write pseudo tracks
- // now fill rest of audio tracks with NULL or copy of first track
- while (stream_number < 4) { // TODO linsys board model 193 have a limit to 4 AES groups (=4streams,8channels)
+ // now fill rest of audio tracks(AES frames) with NULL or copy of first track
+ while (stream_number < audio_format->channels / 2) {
// write for every stream n samples
// n = number of channels per stream
written_bytes = 0;
while (written_bytes < bytes_total) {
- written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[0] + sample_number * bytes_total + written_bytes, bytes_total - written_bytes);
+ written_bytes += write(fh_sdi_audio, (uint8_t *) aBuffer[0] + sample_number * bytes_total + written_bytes,
+ bytes_total - written_bytes);
}
sum_written_bytes += written_bytes;
sum_written_bytes_b += written_bytes;
sample_number++;
-// // Check for events of the SDI board (only firmware 0.9)
-// unsigned int val;
-// if (ioctl(fh_sdi_audio, SDI_IOC_TXGETEVENTS, &val) < 0) {
-// //Maybe this is not an SDI device...
-// fprintf(stderr, "SDI AUDIO output:");
-// perror("unable to get the transmitter event flags");
-// } else if (val) {
-// if (val & SDI_EVENT_TX_BUFFER) {
-// printf("SDI AUDIO driver transmit buffer queue underrun "
-// "detected.\n");
-// }
-// if (val & SDI_EVENT_TX_FIFO) {
-// printf("SDI AUDIO onboard transmit FIFO underrun detected.\n");
-// //TODO react
-// }
-// if (val & SDI_EVENT_TX_DATA) {
-// printf("SDI AUDIO transmit data change detected.\n");
-// }
-// }
+ // Check for events of the SDI audio device
+ unsigned int val;
+ if (ioctl(fh_sdi_audio, SDIAUDIO_IOC_TXGETEVENTS, &val) < 0) {
+ //Maybe this is not an SDI device...
+ // fprintf(stderr, "SDI AUDIO output:");
+ // perror("unable to get the transmitter event flags");
+ } else if (val) {
+ if (val & SDIAUDIO_EVENT_TX_BUFFER) {
+ printf("SDI AUDIO driver transmit buffer queue underrun "
+ "detected.\n");
+ }
+ if (val & SDIAUDIO_EVENT_TX_FIFO) {
+ printf("SDI AUDIO onboard transmit FIFO underrun detected.\n");
+ }
+ if (val & SDIAUDIO_EVENT_TX_DATA) {
+ printf("SDI AUDIO transmit data change detected.\n");
+ }
+ }
}
}
* @param audio_streams: number of audio streams to integrate
*/
static inline int create_SD_SDI_Line(uint16_t *buf, const struct line_info *info, int field, int active, uint8_t *video_buffer,
- int16_t audio_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], int linenumber_sdiframe, int active_video_line, int my_DBN, int16_t AudioGroupCounter,
- int16_t AudioGroups2Write, int audio_streams) {
+ int16_t audio_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES], int linenumber_sdiframe, int active_video_line, int my_DBN,
+ int16_t AudioGroupCounter, int16_t AudioGroups2Write, int audio_streams) {
// write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
// *************************************************************************
*p++ = info->xyz->sav;
//#########################################################################################
+
+ // Because we skip the first line of video, it can happen that we read too far in the buffer
+ if (active_video_line >= info->fmt->active_lines_per_frame) {
+ active_video_line = info->fmt->active_lines_per_frame - 1; // in SD PAL was set 575
+ }
+ //Index of the start of the current line in the video_buffer
+ int start_of_current_line = active_video_line * info->fmt->active_samples_per_line;
+
// If VBlank then fill the line with 0x200 and 0x040 (total black)
switch (active) {
default:
// shift "<< 2" because 8 bit data in 10 bit word
- // Because we skip the first line of video, it can happen that we read too far in the buffer
- if (active_video_line >= info->fmt->active_lines_per_frame) {
- active_video_line = info->fmt->active_lines_per_frame - 1; // in SD PAL was set 575
- }
-
- *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) + 1] << 2; // Cb
+ *p = video_buffer[start_of_current_line + ((p - 288) - buf) + 1] << 2; // Cb
p++;
if (*(p - 1) < 0x040)
*(p - 1) = 0x040; // check values
if (*(p - 1) > 0x3c0)
*(p - 1) = 0x3c0;
- *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) - 1] << 2; // Y1
+ *p = video_buffer[start_of_current_line + ((p - 288) - buf) - 1] << 2; // Y1
p++;
if (*(p - 1) < 0x040)
*(p - 1) = 0x040;
if (*(p - 1) > 0x3ac)
*(p - 1) = 0x3ac;
- *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) + 1] << 2; // Cr
+ *p = video_buffer[start_of_current_line + ((p - 288) - buf) + 1] << 2; // Cr
p++;
if (*(p - 1) < 0x040)
*(p - 1) = 0x040;
if (*(p - 1) > 0x3c0)
*(p - 1) = 0x3c0;
- *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) - 1] << 2; // Y2
+ *p = video_buffer[start_of_current_line + ((p - 288) - buf) - 1] << 2; // Y2
p++;
if (*(p - 1) < 0x040)
*(p - 1) = 0x040;
*
* Returns a negative error code on failure and zero on success.
**/
-static inline int create_HD_SDI_Line(uint16_t *buf, const struct line_info *info, uint16_t active_video_line, unsigned int active, uint8_t *video_buffer) {
+static inline int create_HD_SDI_Line(uint16_t *buf, const struct line_info *info, uint16_t active_video_line, unsigned int active,
+ uint8_t *video_buffer) {
uint16_t *p = buf, *endp, ln;
uint16_t samples = info->blanking ? info->fmt->samples_per_line : info->fmt->active_samples_per_line;
+ if (active_video_line >= info->fmt->active_lines_per_frame) {
+ active_video_line = info->fmt->active_lines_per_frame - 1;
+ }
+
+ int start_of_current_line = active_video_line * info->fmt->active_samples_per_line;
+
if (info->blanking) {
// write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
while (p < (buf + samples)) {
- if (active_video_line >= info->fmt->active_lines_per_frame) {
- active_video_line = info->fmt->active_lines_per_frame - 1;
- }
-
- // sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1;
- // *p++ = sample > 1440 ? 735 : (video_buffer[sample] << 2);
- // sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1;
- // *p++ = sample > 1440 ? 335 : (video_buffer[sample] << 2);
- // sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1;
- // *p++ = sample > 1440 ? 793 : (video_buffer[sample] << 2);
- // sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1;
- // *p++ = sample > 1440 ? 335 : (video_buffer[sample] << 2);
-
- *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1] << 2; // Cb
+ *p = video_buffer[start_of_current_line + (p - buf) + 1] << 2; // Cb
p++;
- // check values, but need manny resources
+ //check values, this needs a lot of resources
// if (*(p - 1) < 0x040)
// *(p - 1) = 0x040;
// if (*(p - 1) > 0x3c0)
// *(p - 1) = 0x3c0;
//
- *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1] << 2; // Y1
+ *p = video_buffer[start_of_current_line + (p - buf) - 1] << 2; // Y1
p++;
// if (*(p - 1) < 0x040)
// *(p - 1) = 0x040;
// if (*(p - 1) > 0x3ac)
// *(p - 1) = 0x3ac;
//
- *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1] << 2; // Cr
+ *p = video_buffer[start_of_current_line + (p - buf) + 1] << 2; // Cr
p++;
// if (*(p - 1) < 0x040)
// *(p - 1) = 0x040;
// if (*(p - 1) > 0x3c0)
// *(p - 1) = 0x3c0;
//
- *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1] << 2; // Y2
+ *p = video_buffer[start_of_current_line + (p - buf) - 1] << 2; // Y2
p++;
// if (*(p - 1) < 0x040)
// *(p - 1) = 0x040;
return 0;
}
-static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DBN, int16_t *audio_buffer_A, int16_t *audio_buffer_B, int16_t AudioGroupCounter,
- int16_t AudioGroups2Write) {
+static int writeANC(uint16_t *p, int videoline_sdiframe, uint16_t DID, int my_DBN, int16_t *audio_buffer_A, int16_t *audio_buffer_B,
+ int16_t AudioGroupCounter, int16_t AudioGroups2Write) {
/**
* ANC Ancillary Data (vgl. SMPTE 291-M page 6 )
// 1 DC (Data Counter)
// number of UDW = AudioGroups2Write x 2AESFrames x 2channesl x 3words(X,X+1,X+2)
- buffer = AudioGroups2Write * 2* 2* 3 ; parity_counter= 0;
+ buffer = AudioGroups2Write * 2 * 2 * 3;
+ parity_counter = 0;
// count binary ones for parity
- for (i=0; i<8; i++) {
+ for (i = 0; i < 8; i++) {
if (buffer & (1 << i))
- parity_counter++;
+ parity_counter++;
}
- if ((parity_counter%2)==0) { //else leave the 0
- buffer+= 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
+ if ((parity_counter % 2) == 0) { //else leave the 0
+ buffer += 512; // 10 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
} else {
- buffer+= 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
+ buffer += 256; // 01 0000 0000 // set bit8 = even parity bit and bit9 = !bit8
}
*p++ = buffer;
- int16_t sample_number=0;
+ int16_t sample_number = 0;
int16_t counter = 0;
// write subframes:
// = n x 1 AudioGroup
// = n x 2 x 2samples
// = 4 samples
// = 4 x 3words
- while (counter < AudioGroups2Write*2) { /* 4:3 */
+ while (counter < AudioGroups2Write * 2) { /* 4:3 */
// write one Audio Group with 4 x AES subframes
// ( samples for ch01,ch02,ch03,ch04 or ch05,ch06,ch07,ch08 or ch09,ch10,ch11,ch12 or ch13,ch14,ch15,ch16)
// and use audio_buffer_A(stereo) and audio_buffer_B(stereo)
// `pack_AES_subframe()` write 3 ANC words (3*10bit), also 1 sample
- sample_number=(AudioGroupCounter*2)+ counter;
- pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 1),
- getZBit(sample_number/2), 0, &audio_buffer_A[sample_number]); // left
- p+=3; // step 3 words
+ sample_number = (AudioGroupCounter * 2) + counter;
+ pack_AES_subframe(p, getChannelStatusBit(sample_number / 2, 1), getZBit(sample_number / 2), 0, &audio_buffer_A[sample_number]); // left
+ p += 3; // step 3 words
- sample_number=(AudioGroupCounter*2)+ counter+1;
- pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 2),
- getZBit(sample_number/2), 1, &audio_buffer_A[sample_number]); // right
- p+=3;
+ sample_number = (AudioGroupCounter * 2) + counter + 1;
+ pack_AES_subframe(p, getChannelStatusBit(sample_number / 2, 2), getZBit(sample_number / 2), 1, &audio_buffer_A[sample_number]); // right
+ p += 3;
- sample_number=(AudioGroupCounter*2)+ counter;
- pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 3),
- getZBit(sample_number/2), 2, &audio_buffer_B[sample_number]); // left
- p+=3;
+ sample_number = (AudioGroupCounter * 2) + counter;
+ pack_AES_subframe(p, getChannelStatusBit(sample_number / 2, 3), getZBit(sample_number / 2), 2, &audio_buffer_B[sample_number]); // left
+ p += 3;
- sample_number=(AudioGroupCounter*2)+ counter+1;
- pack_AES_subframe(p, getChannelStatusBit(sample_number/2, 4),
- getZBit(sample_number/2), 3, &audio_buffer_B[sample_number]); // right
- p+=3;
- counter+=2;
+ sample_number = (AudioGroupCounter * 2) + counter + 1;
+ pack_AES_subframe(p, getChannelStatusBit(sample_number / 2, 4), getZBit(sample_number / 2), 3, &audio_buffer_B[sample_number]); // right
+ p += 3;
+ counter += 2;
}
// 1 CS (Checksum from DID - UDW)
// rest until end of `ANCILLARY_DATA_SAMPLES` will be fill in a loop after call this function
*p++ = 0x040;
}
- return p-pp;
+ return p - pp;
}
// calculate checksumm of ANC (SMPTE 272-M 15.3 Checksum (CS))
*p++ = 0x040;
}
break;
- case BLACK:
+ case BLACK: /* black line (filler for FMT_480i5994 ) */
while (p < (buf + samples)) {
*p++ = 0x200;
*p++ = 0x040;
*p++ = 0x040;
}
break;
+ case GREEN: /* green line for test purpose */
+ while (p < (buf + samples)) {
+ *p++ = 289;
+ *p++ = 450;
+ *p++ = 231;
+ *p++ = 450;
+ }
+ break;
case MAIN_SET:
/* 75% gray */
endp += b + 1;
}
return 0;
}
+
+static int setSDIVideoProperties(enum sdi_setting_video_e setting, char * value, char * device) {
+
+ const char fmt[] = "/sys/class/sdivideo/sdivideo%cx%i/%s";
+ struct stat buf;
+ int num;
+ char type, name[256], data[256];
+ char *endptr;
+
+ /* Get the sysfs info */
+ memset(&buf, 0, sizeof(buf));
+
+ /**
+ * Stat the file, fills the structure with info about the file
+ * Get the major number from device node
+ **/
+ if (stat(device, &buf) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to get the file status");
+ return -1;
+ }
+
+ /* Check if it is a character device or not */
+ if (!S_ISCHR (buf.st_mode)) {
+ fprintf(stderr, "%s: not a character device\n", device);
+ return -1;
+ }
+
+ /* Check the minor number to determine if it is a receive or transmit device */
+ type = (buf.st_rdev & 0x0080) ? 'r' : 't';
+
+ /* Get the receiver or transmitter number */
+ num = buf.st_rdev & 0x007f;
+
+ /* Build the path to sysfs file */
+ snprintf(name, sizeof(name), fmt, type, num, "dev");
+ memset(data, 0, sizeof(data));
+
+ /* Read sysfs file (dev) */
+ if (util_read(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to get the device number");
+ return -1;
+ }
+ /* Compare the major number taken from sysfs file to the one taken from device node */
+ if (strtoul(data, &endptr, 0) != (buf.st_rdev >> 8)) {
+ fprintf(stderr, "%s: not a SMPTE 292M/SMPTE 259M-C device\n", device);
+ return -1;
+ }
+ if (*endptr != ':') {
+ fprintf(stderr, "%s: error reading %s\n", device, name);
+ return -1;
+ }
+
+ // Which setting do we write
+ if (setting == SETTING_BUFFER_NUMBER_VIDEO) {
+ snprintf(name, sizeof(name), fmt, type, num, "buffers");
+ snprintf(data, sizeof(data), "%s\n", value);
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the number of buffers");
+ return -1;
+ }
+ printf("\tSet number of buffers = %s\n", value);
+ } else if (setting == SETTING_BUFFER_SIZE_VIDEO) {
+ snprintf(name, sizeof(name), fmt, type, num, "bufsize");
+ snprintf(data, sizeof(data), "%s\n", value);
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the buffer size");
+ return -1;
+ }
+ printf("\tSet buffer size = %s Bytes\n", value);
+ } else if (setting == SETTING_CLOCK_SOURCE) {
+ snprintf(name, sizeof(name), fmt, type, num, "clock_source");
+ snprintf(data, sizeof(data), "%s\n", value);
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the clock source");
+ return -1;
+ }
+ printf("\tSet clock source = %s\n", value);
+ } else if (setting == SETTING_DATA_MODE) {
+ snprintf(name, sizeof(name), fmt, type, num, "mode");
+ snprintf(data, sizeof(data), "%s\n", value);
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the interface operating mode");
+ return -1;
+ }
+ printf("\tSet data mode = %s\n", value);
+ } else if (setting == SETTING_FRAME_MODE) {
+ snprintf(name, sizeof(name), fmt, type, num, "frame_mode");
+ snprintf(data, sizeof(data), "%s\n", value);
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the interface frame mode");
+ return -1;
+ }
+ printf("\tSet frame mode = %s\n", value);
+ }
+
+ return 0;
+
+}
+
+static int setSDIAudioProperties(enum sdi_setting_audio_e setting, char * value, char * device) {
+ const char fmt[] = "/sys/class/sdiaudio/sdiaudio%cx%i/%s";
+ struct stat buf;
+ int num;
+ char type, name[256], data[256];
+ char *endptr;
+
+ /* Get the sysfs info */
+ memset(&buf, 0, sizeof(buf));
+ if (stat(device, &buf) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to get the file status");
+ return -1;
+ }
+ if (!S_ISCHR (buf.st_mode)) {
+ fprintf(stderr, "%s: not a character device\n", device);
+ return -1;
+ }
+ type = (buf.st_rdev & 0x0080) ? 'r' : 't';
+ num = buf.st_rdev & 0x007f;
+ snprintf(name, sizeof(name), fmt, type, num, "dev");
+ memset(data, 0, sizeof(data));
+ if (util_read(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to get the device number");
+ return -1;
+ }
+
+ if (strtoul(data, &endptr, 0) != (buf.st_rdev >> 8)) {
+ fprintf(stderr, "%s: not an audio device\n", device);
+ return -1;
+ }
+ if (*endptr != ':') {
+ fprintf(stderr, "%s: error reading %s\n", device, name);
+ return -1;
+ }
+
+ if (setting == SETTING_BUFFER_NUMBER_AUDIO) {
+ snprintf(name, sizeof(name), fmt, type, num, "buffers");
+ snprintf(data, sizeof(data), "%s\n", value);
+
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the number of buffers");
+ return -1;
+ }
+ printf("\tSet number of buffers = %s\n", value);
+ } else if (setting == SETTING_BUFFER_SIZE_AUDIO) {
+ snprintf(name, sizeof(name), fmt, type, num, "bufsize");
+ snprintf(data, sizeof(data), "%s\n", value);
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the buffer size");
+ return -1;
+ }
+ printf("\tSet buffer size = %s Bytes\n", value);
+ } else if (setting == SETTING_SAMPLE_SIZE) {
+ snprintf(name, sizeof(name), fmt, type, num, "sample_size");
+ snprintf(data, sizeof(data), "%s\n", value);
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the interface audio sample size");
+ return -1;
+ }
+ switch (atol(value)) {
+ case SDIAUDIO_CTL_AUDSAMP_SZ_16:
+ printf("\tAssuming 16-bit audio.\n");
+ break;
+ case SDIAUDIO_CTL_AUDSAMP_SZ_24:
+ printf("\tAssuming 24-bit audio.\n");
+ break;
+ case SDIAUDIO_CTL_AUDSAMP_SZ_32:
+ printf("\tAssuming 32-bit audio.\n");
+ break;
+ default:
+ printf("\tSet audio sample size = %lu.\n", atol(value));
+ break;
+ }
+ } else if (setting == SETTING_SAMPEL_RATE) {
+ snprintf(name, sizeof(name), fmt, type, num, "sample_rate");
+ snprintf(data, sizeof(data), "%lu\n", atol(value));
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set the interface audio sample rate");
+ return -1;
+ }
+ switch (atoi(value)) {
+ case 32000:
+ printf("\tAssuming 32 kHz audio.\n");
+ break;
+ case 44100:
+ printf("\tAssuming 44.1 kHz audio.\n");
+ break;
+ case 48000:
+ printf("\tAssuming 48 kHz audio.\n");
+ break;
+ default:
+ printf("\tSet audio sample rate = %lu.\n", atol(value));
+ break;
+ }
+ } else if (setting == SETTING_CHANNELS) {
+ snprintf(name, sizeof(name), fmt, type, num, "channels");
+ snprintf(data, sizeof(data), "%lu\n", atol(value));
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set "
+ "the interface audio channel enable");
+ return -1;
+ }
+ switch (atol(value)) {
+ case SDIAUDIO_CTL_AUDCH_EN_0:
+ printf("\tDisabling audio.\n");
+ break;
+ case SDIAUDIO_CTL_AUDCH_EN_2:
+ printf("\tAssuming 2 channels of audio.\n");
+ break;
+ case SDIAUDIO_CTL_AUDCH_EN_4:
+ printf("\tAssuming 4 channels of audio.\n");
+ break;
+ case SDIAUDIO_CTL_AUDCH_EN_6:
+ printf("\tAssuming 6 channels of audio.\n");
+ break;
+ case SDIAUDIO_CTL_AUDCH_EN_8:
+ printf("\tAssuming 8 channels of audio.\n");
+ break;
+ default:
+ printf("\tSet audio channel enable = %lu.\n", atol(value));
+ break;
+ }
+ } else if (setting == SETTING_NON_AUDIO) {
+ snprintf(name, sizeof(name), fmt, type, num, "non_audio");
+ snprintf(data, sizeof(data), "0x%04lX\n", atol(value));
+ if (util_write(name, data, sizeof(data)) < 0) {
+ fprintf(stderr, "%s: ", device);
+ perror("unable to set "
+ "the interface non-audio");
+ return -1;
+ }
+ switch (atol(value)) {
+ case 0x0000:
+ printf("\tPassing PCM audio.\n");
+ break;
+ case 0x00ff:
+ printf("\tPassing non-audio.\n");
+ break;
+ default:
+ printf("\tSet non-audio = 0x%04lX.\n", atol(value));
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static ssize_t util_read(const char *name, char *buf, size_t count) {
+ ssize_t fd, ret;
+
+ if ((fd = open(name, O_RDONLY)) < 0) {
+ return fd;
+ }
+ ret = read(fd, buf, count);
+ close(fd);
+ return ret;
+}
+
+static ssize_t util_write(const char *name, const char *buf, size_t count) {
+ ssize_t fd, ret;
+
+ if ((fd = open(name, O_WRONLY)) < 0) {
+ return fd;
+ }
+ ret = write(fd, buf, count);
+ close(fd);
+ return ret;
+}
+
+static char * itoa(uint64_t i) {
+
+ if (i == 0)
+ return strdup("0");
+
+ char * mystring = (char *) malloc(50);
+ sprintf(mystring, "%"PRIu64, i);
+
+ return mystring;
+}