-
Notifications
You must be signed in to change notification settings - Fork 0
/
write_mef_channel.h
193 lines (159 loc) · 7.71 KB
/
write_mef_channel.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/**********************************************************************************************************************
Copyright 2021, Mayo Foundation, Rochester MN. All rights reserved.
This library contains functions to convert data samples to MEF version 3.0
initialize_mef_channel_data() should be called first for each channel, which initializes the data in the channel
structure. Then write_mef_channel_data() is called with the actual sample data to be written to the mef. Finally,
close_mef_channel_file() will close out the channel mef file, and free allocated memory.
To compile for a 64-bit intel system, linking with the following files is necessary:
meflib.c, mefrec.c
Usage and modification of this source code is governed by the Apache 2.0 license.
You may not use this file except in compliance with this License.
A copy of the Apache 2.0 License may be obtained at http://www.apache.org/licenses/LICENSE-2.0
Thanks to all who acknowledge the Mayo Systems Electrophysiology Laboratory, Rochester, MN
in academic publications of their work facilitated by this software.
Written by Dan Crepeau 9/2011, originally to write MEF 2.1 files.
Minor changes added 2/2012 to allow temporary index files to be written.
Updated 10/2014 to write MEF 3.0.
Updated 5/2015 for MEF 3.0 format changes.
Updated 5/2016 for MEF 3.0 library updates and bug fixes.
Updated 2/2017 to add support for exporting functions to .dll
Updated 10/2017 initial support for MEF 3.0 annotations.
Updated 10/2020 initial support for MEF 3.0 video channels.
When compiling for Windows .dll, define _EXPORT_FOR_DLL
When using this code, the time-series data must be pre-sorted in increasing time order. Unordered
packets will cause data discontinuities.
*************************************************************************************************************************/
#ifndef WRITE_MEF_CHANNEL
#define WRITE_MEF_CHANNEL
#ifdef __cplusplus
extern "C" {
#endif
#include "meflib.h"
typedef struct SESSION_STATE SESSION_STATE;
typedef struct {
si4 chan_num;
RED_PROCESSING_STRUCT *rps;
si4 *raw_data_ptr_start;
si4 *raw_data_ptr_current;
ui8 block_hdr_time;
ui8 block_boundary;
ui8 last_chan_timestamp;
ui8 max_block_size;
ui8 max_block_len;
ui8 number_of_index_entries;
ui8 number_of_discontinuity_entries;
ui8 number_of_samples;
ui8 block_sample_index;
si8 start_sample;
si4 discontinuity_flag;
si4 bit_shift_flag;
FILE *out_file;
ui1* out_data;
ui1* temp_time_series_index;
ui4 discont_contiguous_blocks;
si8 discont_contiguous_samples;
si8 discont_contiguous_bytes;
ui8 block_len;
FILE_PROCESSING_STRUCT *gen_fps;
FILE_PROCESSING_STRUCT *metadata_fps;
FILE_PROCESSING_STRUCT *ts_data_fps;
FILE_PROCESSING_STRUCT *ts_inds_fps;
si8 inds_file_offset;
si8 data_file_offset;
PASSWORD_DATA *pwd;
sf4 gmt_offset_in_hours;
si1 segment_name[MEF_SEGMENT_BASE_FILE_NAME_BYTES];
si1 segment_path[MEF_FULL_FILE_NAME_BYTES];
ui8 num_secs_per_segment;
ui8 next_segment_start_time;
si1 channel_path[MEF_FULL_FILE_NAME_BYTES];
si1 if_appending;
} CHANNEL_STATE;
typedef struct {
FILE_PROCESSING_STRUCT *gen_fps;
FILE_PROCESSING_STRUCT *rdat_fps;
FILE_PROCESSING_STRUCT *ridx_fps;
sf4 gmt_offset;
si8 rdat_file_offset;
si8 ridx_file_offset;
} ANNOTATION_STATE;
// Subroutine declarations
#ifndef _EXPORT_FOR_DLL
si4 initialize_mef_channel_data(CHANNEL_STATE *channel_state,
sf8 secs_per_block,
si1 *chan_map_name,
si4 bit_shift_flag,
sf8 low_frequency_filter_setting,
sf8 high_frequency_filter_setting,
sf8 notch_filter_frequency,
sf8 AC_line_frequency,
sf8 units_conversion_factor,
si1 *channel_description,
sf8 sampling_frequency,
si8 block_interval,
si4 chan_num,
si1 *mef3_session_directory,
sf4 gmt_offset,
si1 *session_description,
si1 *anonymized_subject_name,
si1 *subject_first_name,
si1 *subject_second_name,
si1 *subject_ID,
si1 *institution,
si1 *mef_3_level_1_password,
si1 *mef_3_level_2_password,
si1 *study_comments,
si1 *channel_comments,
ui8 num_secs_per_segment
);
#endif
#ifndef _EXPORT_FOR_DLL
si4 write_mef_channel_data(CHANNEL_STATE *channel_state,
ui8 *packet_times,
si4 *samps,
ui8 n_packets_to_process,
sf8 secs_per_block,
sf8 sampling_frequency);
#endif
si4 check_for_new_segment(CHANNEL_STATE *channel_state, ui8 start_time);
si4 update_metadata(CHANNEL_STATE *channel_state);
#ifndef _EXPORT_FOR_DLL
si4 close_mef_channel(CHANNEL_STATE *channel_state);
si4 append_mef_channel_data(CHANNEL_STATE *channel_state,
si1 *chan_map_name,
si4 new_segment_number,
si1 *mef_3_level_1_password,
si1 *mef_3_level_2_password,
si1 *mef3_session_directory,
ui8 num_secs_per_segment,
si4 bit_shift_flag
);
#endif
#ifndef _EXPORT_FOR_DLL
si4 create_or_append_annotations(ANNOTATION_STATE* annotation_state,
si1* dir_name,
sf4 gmt_offset,
si1 *anonymized_subject_name);
si4 write_annotation(ANNOTATION_STATE* annotation_state,
ui8 unixTimestamp,
si1* type,
void* record);
si4 close_annotation(ANNOTATION_STATE* annotation_state);
#endif
// This function updates the ".mefd" file, which is an optional MEF 3 extenion, that Persyst reads to load channel information.
void update_mefd_file(si1* mef3_session_path, si1* mef3_session_name, si1* chan_name, si1* anonymized_subject_name);
// The following function can be used for the use-case where a series of video files should be placed within a MEF 3.0 video channel (.vidd) directory.
// For now it only works for .avi files. Clip byte/offset information is not filled in, and the maximum clip bytes is set to the size of the .avi file.
// The user is responsible for pulling out information like resolution width/height, number of frame, and frame rate. (The ffprobe open-source tool is
// very good). The proto_metadata_fps is used for filling in section 3 of the metadata (info such as patient name/id and recording location) which will
// be the same as with time series data channels. The start_time and end_time are the uUTC of the beginning and end of this avi file. This use-case
// assumes exactly one clip (subsection of a video file) is defined for the entire video file. Modification of this function would be necessary for
// multiple clips. The video channel is not encrypted in this use-case.
void write_video_file_with_one_clip(si1* output_directory, si4 segment_num, si1* chan_name, si1* full_file_name, si8 start_time, si8 end_time,
si4 width, si4 height, si4 num_frames, sf8 frame_rate, FILE_PROCESSING_STRUCT* proto_metadata_fps);
#define DISCONTINUITY_TIME_THRESHOLD 100000 // 100000 microseconds = .1 seconds
#define VIDEO_FILE_READ_SIZE 1000000 // 1 million bytes - this is for reading video files, to do a CRC calculation.
#ifdef __cplusplus
}
#endif
#endif