mxfinfo 0.0.3.6 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,194 @@
1
+ /*
2
+ * Parse metadata from an Avid MXF file
3
+ *
4
+ * Copyright (C) 2008, British Broadcasting Corporation
5
+ * All Rights Reserved.
6
+ *
7
+ * Author: Philip de Nier
8
+ *
9
+ * Redistribution and use in source and binary forms, with or without
10
+ * modification, are permitted provided that the following conditions are met:
11
+ *
12
+ * * Redistributions of source code must retain the above copyright notice,
13
+ * this list of conditions and the following disclaimer.
14
+ * * Redistributions in binary form must reproduce the above copyright
15
+ * notice, this list of conditions and the following disclaimer in the
16
+ * documentation and/or other materials provided with the distribution.
17
+ * * Neither the name of the British Broadcasting Corporation nor the names
18
+ * of its contributors may be used to endorse or promote products derived
19
+ * from this software without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
+ * POSSIBILITY OF SUCH DAMAGE.
32
+ */
33
+
34
+ #ifndef __AVID_MXF_INFO_H__
35
+ #define __AVID_MXF_INFO_H__
36
+
37
+
38
+ #ifdef __cplusplus
39
+ extern "C"
40
+ {
41
+ #endif
42
+
43
+
44
+ #include <mxf/mxf_types.h>
45
+
46
+
47
+ /* Note: keep get_essence_type_string() in sync when changes are made here */
48
+ typedef enum
49
+ {
50
+ UNKNOWN_ESSENCE_TYPE = 0,
51
+ MPEG_30_ESSENCE_TYPE,
52
+ MPEG_40_ESSENCE_TYPE,
53
+ MPEG_50_ESSENCE_TYPE,
54
+ DV_25_411_ESSENCE_TYPE,
55
+ DV_25_420_ESSENCE_TYPE,
56
+ DV_50_ESSENCE_TYPE,
57
+ DV_100_ESSENCE_TYPE,
58
+ MJPEG_20_1_ESSENCE_TYPE,
59
+ MJPEG_2_1_S_ESSENCE_TYPE,
60
+ MJPEG_4_1_S_ESSENCE_TYPE,
61
+ MJPEG_15_1_S_ESSENCE_TYPE,
62
+ MJPEG_10_1_ESSENCE_TYPE,
63
+ MJPEG_10_1_M_ESSENCE_TYPE,
64
+ MJPEG_4_1_M_ESSENCE_TYPE,
65
+ MJPEG_3_1_ESSENCE_TYPE,
66
+ MJPEG_2_1_ESSENCE_TYPE,
67
+ UNC_1_1_ESSENCE_TYPE,
68
+ UNC_1_1_10B_ESSENCE_TYPE,
69
+ MJPEG_35_1_P_ESSENCE_TYPE,
70
+ MJPEG_28_1_P_ESSENCE_TYPE,
71
+ MJPEG_14_1_P_ESSENCE_TYPE,
72
+ MJPEG_3_1_P_ESSENCE_TYPE,
73
+ MJPEG_2_1_P_ESSENCE_TYPE,
74
+ MJPEG_3_1_M_ESSENCE_TYPE,
75
+ MJPEG_8_1_M_ESSENCE_TYPE,
76
+ DNXHD_1235_ESSENCE_TYPE,
77
+ DNXHD_1237_ESSENCE_TYPE,
78
+ DNXHD_1238_ESSENCE_TYPE,
79
+ DNXHD_1241_ESSENCE_TYPE,
80
+ DNXHD_1242_ESSENCE_TYPE,
81
+ DNXHD_1243_ESSENCE_TYPE,
82
+ DNXHD_1250_ESSENCE_TYPE,
83
+ DNXHD_1251_ESSENCE_TYPE,
84
+ DNXHD_1252_ESSENCE_TYPE,
85
+ DNXHD_1253_ESSENCE_TYPE,
86
+ MPEG4_ESSENCE_TYPE,
87
+ XDCAM_HD_ESSENCE_TYPE,
88
+ AVCINTRA_100_ESSENCE_TYPE,
89
+ AVCINTRA_50_ESSENCE_TYPE,
90
+ PCM_ESSENCE_TYPE
91
+ } AvidEssenceType;
92
+
93
+ typedef enum
94
+ {
95
+ UNKNOWN_PHYS_TYPE = 0,
96
+ TAPE_PHYS_TYPE,
97
+ IMPORT_PHYS_TYPE,
98
+ RECORDING_PHYS_TYPE
99
+ } AvidPhysicalPackageType;
100
+
101
+ typedef enum
102
+ {
103
+ FULL_FRAME_FRAME_LAYOUT = 0,
104
+ SEPARATE_FIELDS_FRAME_LAYOUT,
105
+ SINGLE_FIELD_FRAME_LAYOUT,
106
+ MIXED_FIELD_FRAME_LAYOUT,
107
+ SEGMENTED_FRAME_FRAME_LAYOUT,
108
+ } AvidFrameLayout;
109
+
110
+ typedef struct
111
+ {
112
+ char *name;
113
+ char *value;
114
+ } AvidNameValuePair;
115
+
116
+ typedef struct
117
+ {
118
+ char *name;
119
+ char *value;
120
+ AvidNameValuePair *attributes;
121
+ int numAttributes;
122
+ } AvidTaggedValue;
123
+
124
+ typedef struct
125
+ {
126
+ /* clip info */
127
+ char *clipName;
128
+ char *projectName;
129
+ mxfTimestamp clipCreated;
130
+ mxfRational projectEditRate;
131
+ int64_t clipDuration;
132
+ mxfUMID materialPackageUID;
133
+ AvidTaggedValue *userComments;
134
+ int numUserComments;
135
+ AvidTaggedValue *materialPackageAttributes;
136
+ int numMaterialPackageAttributes;
137
+ int numVideoTracks;
138
+ int numAudioTracks;
139
+ char *tracksString;
140
+
141
+ /* track info */
142
+ uint32_t trackNumber;
143
+ int isVideo;
144
+ mxfRational editRate;
145
+ int64_t trackDuration;
146
+ int64_t segmentDuration;
147
+ int64_t segmentOffset;
148
+ int64_t startTimecode;
149
+
150
+ /* file essence info */
151
+ AvidEssenceType essenceType;
152
+ mxfUMID fileSourcePackageUID;
153
+ mxfUL essenceContainerLabel;
154
+
155
+ /* picture info */
156
+ mxfUL pictureCodingLabel;
157
+ uint8_t frameLayout;
158
+ mxfRational aspectRatio;
159
+ uint32_t storedWidth;
160
+ uint32_t storedHeight;
161
+ uint32_t displayWidth;
162
+ uint32_t displayHeight;
163
+
164
+ /* sound info */
165
+ mxfRational audioSamplingRate;
166
+ uint32_t channelCount;
167
+ uint32_t quantizationBits;
168
+
169
+ /* physical source info */
170
+ char *physicalPackageName;
171
+ mxfUMID physicalSourcePackageUID;
172
+ AvidPhysicalPackageType physicalPackageType;
173
+ char *physicalPackageLocator;
174
+
175
+ } AvidMXFInfo;
176
+
177
+
178
+
179
+ int ami_read_info(const char *filename, AvidMXFInfo *info, int printDebugError);
180
+
181
+ void ami_free_info(AvidMXFInfo *info);
182
+
183
+ void ami_print_info(AvidMXFInfo *info);
184
+ /* TODO: add function to print machine readable info e.g. newline delimited fields */
185
+
186
+ const char* get_essence_type_string(AvidEssenceType essenceType, mxfRational editRate);
187
+
188
+ #ifdef __cplusplus
189
+ }
190
+ #endif
191
+
192
+
193
+ #endif
194
+
@@ -0,0 +1,12 @@
1
+ require 'mkmf'
2
+
3
+ unless pkg_config('libMXF-1.0')
4
+ raise "libMXF-1.0 could not be found!"
5
+ end
6
+
7
+ $warnflags = ''
8
+ $defs.push '--std=gnu99'
9
+ $defs.push '-D_GNU_SOURCE'
10
+ $defs.push '-Wall'
11
+
12
+ create_makefile('mxfinfo')
@@ -0,0 +1,313 @@
1
+ #include <time.h>
2
+ #include <ruby.h>
3
+ #include "avid_mxf_info.h"
4
+
5
+ /* Helpers. */
6
+
7
+ static
8
+ VALUE rb_time_from_mxf_timestamp(mxfTimestamp *ts)
9
+ {
10
+ /*
11
+ * NOTE: This is probably not thread-safe, since struct tm*
12
+ * returned by localtime is shared static.
13
+ */
14
+ time_t t;
15
+ time(&t);
16
+ struct tm *tmts;
17
+ tmts = localtime(&t);
18
+
19
+ tmts->tm_year = (int) ts->year - 1900;
20
+ tmts->tm_mon = (int) ts->month - 1;
21
+ tmts->tm_mday = (int) ts->day;
22
+ tmts->tm_hour = (int) ts->hour;
23
+ tmts->tm_min = (int) ts->min;
24
+ tmts->tm_sec = (int) ts->sec;
25
+
26
+ return rb_time_new(mktime(tmts), ts->qmsec);
27
+ }
28
+
29
+ static
30
+ VALUE rb_str_from_label(const unsigned char *lbl, int len)
31
+ {
32
+ char hex[len * 2 + 1];
33
+ for(int i = 0; i < len; i++)
34
+ {
35
+ sprintf(&hex[i * 2], "%02x", lbl[i]);
36
+ }
37
+ hex[len * 2 + 1] = '\0';
38
+ return rb_str_new2(hex);
39
+ }
40
+
41
+ /* Some macros. */
42
+
43
+ #define CIO_GENERIC_GETTER(cast, name, attr) \
44
+ static \
45
+ VALUE cio_get_##name (VALUE self) \
46
+ { \
47
+ AvidMXFInfo *info; \
48
+ Data_Get_Struct(self, AvidMXFInfo, info); \
49
+ return cast (info-> attr ); \
50
+ }
51
+
52
+ #define CIO_STRING_GETTER(name, attr) \
53
+ static \
54
+ VALUE cio_get_##name (VALUE self) \
55
+ { \
56
+ AvidMXFInfo *info; \
57
+ Data_Get_Struct(self, AvidMXFInfo, info); \
58
+ return ((info-> attr ) != NULL) ? rb_str_new2(info-> attr ) : Qnil; \
59
+ }
60
+
61
+ #define CIO_LABEL_GETTER(name, attr, len) \
62
+ static \
63
+ VALUE cio_get_##name (VALUE self) \
64
+ { \
65
+ AvidMXFInfo *info; \
66
+ Data_Get_Struct(self, AvidMXFInfo, info); \
67
+ return rb_str_from_label((unsigned char*) &( info-> attr ), len ); \
68
+ }
69
+
70
+ #define CIO_RATIONAL_GETTER(name, attr) \
71
+ static \
72
+ VALUE cio_get_##name (VALUE self) \
73
+ { \
74
+ AvidMXFInfo *info; \
75
+ Data_Get_Struct(self, AvidMXFInfo, info); \
76
+ return rb_rational_new(INT2FIX((info-> attr ).numerator), \
77
+ INT2FIX((info-> attr ).denominator)); \
78
+ }
79
+
80
+ #define CIO_INT_GETTER(name, attr) CIO_GENERIC_GETTER(INT2FIX, name, attr)
81
+ #define CIO_UINT_GETTER(name, attr) CIO_GENERIC_GETTER(UINT2NUM, name, attr)
82
+ #define CIO_INT64_GETTER(name, attr) CIO_GENERIC_GETTER(LL2NUM, name, attr)
83
+
84
+ /* Ruby API. */
85
+
86
+ VALUE m_mxfinfo = Qnil;
87
+ VALUE c_infoobject = Qnil;
88
+
89
+ static
90
+ void cio_free(void *ptr) {
91
+ ami_free_info(ptr);
92
+ }
93
+
94
+ static
95
+ VALUE cio_new(VALUE class, VALUE path)
96
+ {
97
+ Check_Type(path, T_STRING);
98
+ const char *fn = StringValuePtr(path);
99
+
100
+ AvidMXFInfo *info = ALLOC(AvidMXFInfo);
101
+
102
+ int result = ami_read_info(fn, info, 1);
103
+
104
+ if(result != 0)
105
+ {
106
+ ami_free_info(info);
107
+
108
+ switch(result)
109
+ {
110
+ case -2:
111
+ rb_raise(rb_eIOError, "Failed to open file.");
112
+ break;
113
+ case -3:
114
+ rb_raise(rb_eIOError, "Failed to read header partition.");
115
+ break;
116
+ case -4:
117
+ rb_raise(rb_eStandardError, "File is not OP-Atom.");
118
+ break;
119
+ case -1:
120
+ default:
121
+ rb_raise(rb_eStandardError, "Failed to read info.");
122
+ break;
123
+ }
124
+
125
+ return Qnil;
126
+ }
127
+ else
128
+ {
129
+ VALUE tdata = Data_Wrap_Struct(class, 0, cio_free, info);
130
+ return tdata;
131
+ }
132
+ }
133
+
134
+ /* Simple getters. */
135
+
136
+ CIO_STRING_GETTER(clip_name, clipName)
137
+ CIO_STRING_GETTER(project_name, projectName)
138
+ CIO_RATIONAL_GETTER(project_edit_rate, projectEditRate)
139
+ CIO_INT64_GETTER(clip_duration, clipDuration)
140
+ CIO_LABEL_GETTER(material_package_uid, materialPackageUID, 32)
141
+ CIO_INT_GETTER(num_video_tracks, numVideoTracks)
142
+ CIO_INT_GETTER(num_audio_tracks, numAudioTracks)
143
+ CIO_STRING_GETTER(tracks_string, tracksString)
144
+ CIO_UINT_GETTER(track_number, trackNumber)
145
+ CIO_RATIONAL_GETTER(edit_rate, editRate)
146
+ CIO_INT64_GETTER(track_duration, trackDuration)
147
+ CIO_INT64_GETTER(segment_duration, segmentDuration)
148
+ CIO_INT64_GETTER(segment_offset, segmentOffset)
149
+ CIO_INT64_GETTER(start_timecode, startTimecode)
150
+ CIO_LABEL_GETTER(essence_container_label, essenceContainerLabel, 16)
151
+ CIO_LABEL_GETTER(file_source_package_uid, fileSourcePackageUID, 32)
152
+ CIO_LABEL_GETTER(picture_coding_label, pictureCodingLabel, 16)
153
+ CIO_UINT_GETTER(frame_layout, frameLayout)
154
+ CIO_UINT_GETTER(stored_width, storedWidth)
155
+ CIO_UINT_GETTER(stored_height, storedHeight)
156
+ CIO_UINT_GETTER(display_width, displayWidth)
157
+ CIO_UINT_GETTER(display_height, displayHeight)
158
+ CIO_RATIONAL_GETTER(audio_sampling_rate, audioSamplingRate)
159
+ CIO_UINT_GETTER(channel_count, channelCount)
160
+ CIO_UINT_GETTER(quantization_bits, quantizationBits)
161
+ CIO_STRING_GETTER(physical_package_name, physicalPackageName)
162
+ CIO_LABEL_GETTER(physical_source_package_uid, physicalSourcePackageUID, 32)
163
+ CIO_STRING_GETTER(physical_package_locator, physicalPackageLocator)
164
+ /* ... */
165
+
166
+ /* Random attributes that need special treatment. */
167
+
168
+ static
169
+ VALUE cio_get_clip_created(VALUE self)
170
+ {
171
+ AvidMXFInfo *info;
172
+ Data_Get_Struct(self, AvidMXFInfo, info);
173
+ return rb_time_from_mxf_timestamp(&info->clipCreated);
174
+ }
175
+
176
+ /*
177
+ * Left that in for reference (array creation).
178
+ static
179
+ VALUE cio_get_material_package_uid(VALUE self)
180
+ {
181
+ AvidMXFInfo *info;
182
+ Data_Get_Struct(self, AvidMXFInfo, info);
183
+
184
+ unsigned char *uid = (unsigned char*) &info->materialPackageUID;
185
+
186
+ VALUE ary = rb_ary_new2(32);
187
+ for(unsigned int i = 0; i < 32; i++)
188
+ {
189
+ rb_ary_store(ary, i, CHR2FIX(uid[i]));
190
+ }
191
+
192
+ return ary;
193
+ }
194
+ */
195
+
196
+ static
197
+ VALUE cio_get_is_video(VALUE self)
198
+ {
199
+ AvidMXFInfo *info;
200
+ Data_Get_Struct(self, AvidMXFInfo, info);
201
+ return info->isVideo ? Qtrue : Qfalse;
202
+ }
203
+
204
+ static
205
+ VALUE cio_get_essence_type(VALUE self)
206
+ {
207
+ AvidMXFInfo *info;
208
+ Data_Get_Struct(self, AvidMXFInfo, info);
209
+ return rb_str_new2(get_essence_type_string(info->essenceType, info->projectEditRate));
210
+ }
211
+
212
+ static
213
+ VALUE cio_get_aspect_ratio(VALUE self)
214
+ {
215
+ AvidMXFInfo *info;
216
+ Data_Get_Struct(self, AvidMXFInfo, info);
217
+ if(info->isVideo && info->aspectRatio.denominator != 0)
218
+ {
219
+ return rb_rational_new(INT2FIX(info->aspectRatio.numerator),
220
+ INT2FIX(info->aspectRatio.denominator));
221
+ }
222
+ else
223
+ {
224
+ return Qnil;
225
+ }
226
+ }
227
+
228
+ static
229
+ VALUE cio_get_physical_package_type(VALUE self)
230
+ {
231
+ AvidMXFInfo *info;
232
+ Data_Get_Struct(self, AvidMXFInfo, info);
233
+
234
+ VALUE ret = Qnil;
235
+ switch (info->physicalPackageType)
236
+ {
237
+ case TAPE_PHYS_TYPE:
238
+ ret = ID2SYM(rb_intern("tape"));
239
+ break;
240
+ case IMPORT_PHYS_TYPE:
241
+ ret = ID2SYM(rb_intern("import"));
242
+ break;
243
+ case RECORDING_PHYS_TYPE:
244
+ ret = ID2SYM(rb_intern("recording"));
245
+ break;
246
+ case UNKNOWN_PHYS_TYPE:
247
+ default:
248
+ ret = ID2SYM(rb_intern("unknown"));
249
+ break;
250
+ }
251
+
252
+ return ret;
253
+ }
254
+
255
+ static
256
+ VALUE cio_get_clip_track_string(VALUE self)
257
+ {
258
+ AvidMXFInfo *info;
259
+ Data_Get_Struct(self, AvidMXFInfo, info);
260
+
261
+ return rb_str_new2((info->tracksString == NULL) ? "" : info->tracksString);
262
+ }
263
+
264
+ /* Module init. */
265
+
266
+ void Init_mxfinfo()
267
+ {
268
+ m_mxfinfo = rb_define_module("MXFInfo");
269
+
270
+ c_infoobject = rb_define_class_under(m_mxfinfo, "InfoObject", rb_cObject);
271
+ rb_define_singleton_method(c_infoobject, "new", cio_new, 1);
272
+
273
+ rb_define_method(c_infoobject, "clip_name", cio_get_clip_name, 0);
274
+ rb_define_method(c_infoobject, "project_name", cio_get_project_name, 0);
275
+ rb_define_method(c_infoobject, "clip_created", cio_get_clip_created, 0);
276
+ rb_define_method(c_infoobject, "project_edit_rate", cio_get_project_edit_rate, 0);
277
+ rb_define_method(c_infoobject, "clip_duration", cio_get_clip_duration, 0);
278
+ rb_define_method(c_infoobject, "material_package_uid", cio_get_material_package_uid, 0);
279
+
280
+ /* AvidTaggedValue *userComments */
281
+ /* int numUserComments */
282
+ /* AvidTaggedValue *materialPackageAttributes */
283
+ /* int numMaterialPackageAttributes */
284
+
285
+ rb_define_method(c_infoobject, "num_video_tracks", cio_get_num_video_tracks, 0);
286
+ rb_define_method(c_infoobject, "num_audio_tracks", cio_get_num_audio_tracks, 0);
287
+ rb_define_method(c_infoobject, "tracks_string", cio_get_tracks_string, 0);
288
+ rb_define_method(c_infoobject, "track_number", cio_get_track_number, 0);
289
+ rb_define_method(c_infoobject, "is_video", cio_get_is_video, 0);
290
+ rb_define_method(c_infoobject, "edit_rate", cio_get_edit_rate, 0);
291
+ rb_define_method(c_infoobject, "track_duration", cio_get_track_duration, 0);
292
+ rb_define_method(c_infoobject, "segment_duration", cio_get_segment_duration, 0);
293
+ rb_define_method(c_infoobject, "segment_offset", cio_get_segment_offset, 0);
294
+ rb_define_method(c_infoobject, "start_timecode", cio_get_start_timecode, 0);
295
+ rb_define_method(c_infoobject, "essence_type", cio_get_essence_type, 0);
296
+ rb_define_method(c_infoobject, "essence_container_label", cio_get_essence_container_label, 0);
297
+ rb_define_method(c_infoobject, "file_source_package_uid", cio_get_file_source_package_uid, 0);
298
+ rb_define_method(c_infoobject, "picture_coding_label", cio_get_picture_coding_label, 0);
299
+ rb_define_method(c_infoobject, "frame_layout", cio_get_frame_layout, 0);
300
+ rb_define_method(c_infoobject, "aspect_ratio", cio_get_aspect_ratio, 0);
301
+ rb_define_method(c_infoobject, "stored_width", cio_get_stored_width, 0);
302
+ rb_define_method(c_infoobject, "stored_height", cio_get_stored_height, 0);
303
+ rb_define_method(c_infoobject, "display_width", cio_get_display_width, 0);
304
+ rb_define_method(c_infoobject, "display_height", cio_get_display_height, 0);
305
+ rb_define_method(c_infoobject, "audio_sampling_rate", cio_get_audio_sampling_rate, 0);
306
+ rb_define_method(c_infoobject, "channel_count", cio_get_channel_count, 0);
307
+ rb_define_method(c_infoobject, "quantization_bits", cio_get_quantization_bits, 0);
308
+ rb_define_method(c_infoobject, "physical_package_name", cio_get_physical_package_name, 0);
309
+ rb_define_method(c_infoobject, "physical_source_package_uid", cio_get_physical_source_package_uid, 0);
310
+ rb_define_method(c_infoobject, "physical_package_type", cio_get_physical_package_type, 0);
311
+ rb_define_method(c_infoobject, "physical_package_locator", cio_get_physical_package_locator, 0);
312
+ rb_define_method(c_infoobject, "clip_track_string", cio_get_clip_track_string, 0);
313
+ }
@@ -1,3 +1,3 @@
1
- class MXFinfo
2
- VERSION = "0.0.3.6"
1
+ module MXFInfo
2
+ VERSION = '0.0.4'
3
3
  end
data/lib/mxfinfo.rb CHANGED
@@ -1,130 +1,37 @@
1
- require "forwardable"
2
- require File.join(File.dirname(__FILE__),"mxfinfo/version")
3
- require File.join(File.dirname(__FILE__),"mxfinfo/attr_readers")
4
- require File.join(File.dirname(__FILE__),"mxfinfo/string")
5
-
6
- class MXFinfo
7
- extend Forwardable
8
- # We assume it's in the path of the user
9
- @@binary = 'avidmxfinfo'
10
-
11
- # BINARY CHANGE
12
- def self.binary; @@binary; end
13
- def self.binary=(binary); @@binary = binary; end
1
+ require 'mxfinfo.so'
2
+ require 'mxfinfo/version.rb'
14
3
 
4
+ module MXFInfo
15
5
  def self.scan(path)
16
- info = InfoObject.new(path)
17
- end
18
-
19
- def self.import(data)
20
- InfoObject.new(data, false)
6
+ InfoObject.new path
21
7
  end
22
8
 
23
9
  class InfoObject
24
- extend AttrReaders
25
-
26
- @@render = ["Center Smooth",
27
- "Color Correction",
28
- "Crystal",
29
- "Flip-Flop",
30
- "FluidBlur",
31
- "Left Box",
32
- "Luma Key",
33
- "Mosaic Effect",
34
- "Stabilize",
35
- "Timecode Burn-In"]
36
-
37
- # RAW AVIDMXFINFO OUTPUT
38
- def raw_data; @mxfinfo; end
39
-
40
- # Attributes
41
- def self.supported_attributes; @supported_attributes ||= []; end
42
-
43
- def initialize(input, process = true)
44
- if process
45
- @filepath = File.absolute_path(input)
46
- File.exists?(@filepath) ? @valid = true : @valid = false
47
- @mxfinfo = mxfinfo if @valid
48
- else
49
- @valid = true
50
- @mxfinfo = input
51
- end
52
- # Check if output contains error from binary
53
- @mxfinfo.include?("ERROR") ? @valid = false : @valid = true
54
- @mxfinfo.include?("Failed to open file") ? @valid = false : @valid = true
55
- @mxfinfo.include?("mxf_disk_file_open_read") ? @valid = false : @valid = true
56
- process_data if @valid
57
- end
58
-
59
- def valid?
60
- @valid
61
- end
62
-
63
- mxfinfo_attr_reader :filename
64
- mxfinfo_attr_reader :project_name
65
- mxfinfo_attr_reader :clip_name
66
- mxfinfo_date_reader :clip_created_at, "Clip Created"
67
- mxfinfo_attr_reader :project_edit_rate
68
- mxfinfo_attr_reader :clip_edit_rate
69
- mxfinfo_duration_reader :clip_duration
70
-
71
- mxfinfo_attr_reader :videotracks, "Clip Video Tracks"
72
- def v_tracks; videotracks.to_i; end
73
- alias_method :video_tracks, :v_tracks
74
-
75
- mxfinfo_attr_reader :audiotracks, "Clip Audio Tracks"
76
- def a_tracks; audiotracks.to_i; end
77
- alias_method :audio_tracks, :a_tracks
78
-
79
- mxfinfo_attr_reader :clip_track_string
80
- mxfinfo_attr_reader :essence_type
81
- mxfinfo_attr_reader :essence_label
82
-
83
- mxfinfo_attr_reader :tracknumber, "Track Number"
84
- def t_number; tracknumber.to_i; end
85
- alias_method :track_number, :t_number
86
-
87
- mxfinfo_attr_reader :edit_rate
88
- mxfinfo_duration_reader :track_duration
89
- mxfinfo_duration_reader :track_segment_duration
90
- mxfinfo_duration_reader :track_segment_offset
91
- mxfinfo_timecode_reader :start_timecode
92
- mxfinfo_attr_reader :audio_sampling_rate
93
-
94
- mxfinfo_attr_reader :channelcount, "Channel Count"
95
- def c_count; channelcount.to_i; end
96
- alias_method :channel_count, :c_count
97
-
98
- mxfinfo_attr_reader :quantizationbits, "Quantization Bits"
99
- def q_bits; quantizationbits.to_i; end
100
- alias_method :quantization_bits, :q_bits
101
-
102
- mxfinfo_attr_reader :unc_path
103
- mxfinfo_attr_reader :material_package_uid
104
- mxfinfo_attr_reader :file_package_uid
105
- mxfinfo_attr_reader :physical_package_uid
106
- mxfinfo_attr_reader :physical_package_type
107
- mxfinfo_attr_reader :physical_package_name
108
- mxfinfo_attr_reader :physical_package_locator
10
+ alias_method :videotracks, :num_video_tracks
11
+ alias_method :v_tracks, :num_video_tracks
12
+ alias_method :video_tracks, :num_video_tracks
13
+ alias_method :audiotracks, :num_audio_tracks
14
+ alias_method :audio_tracks, :num_audio_tracks
15
+ alias_method :a_tracks, :num_audio_tracks
16
+ alias_method :clip_created_at, :clip_created
17
+ alias_method :essence_label, :essence_container_label
18
+ alias_method :t_number, :track_number
19
+ alias_method :tracknumber, :track_number
20
+ alias_method :channelcount, :channel_count
21
+ alias_method :c_count, :channel_count
22
+ alias_method :file_package_uid, :file_source_package_uid
109
23
 
110
24
  def render_file?
111
25
  physical_package_name == "Precompute Source Mob"
112
26
  end
113
27
 
114
- private
115
- def mxfinfo
116
- # TODO: - add check if return data is valid
117
- `#{MXFinfo.binary} \"#{@filepath}\" 2>&1`
118
- end
119
-
120
- def process_data
121
- @processed_data = Hash.new
122
- @mxfinfo.each_line do |line|
123
- if line.include?("=")
124
- key, value = line.split("=")[0], line.split("=")[1]
125
- @processed_data[key.strip.gsub(/\s+/, "_").downcase] = value.strip
126
- end
127
- end
28
+ alias_method :essence_type_orig, :essence_type
29
+ def essence_type
30
+ result = self.send(:essence_type_orig)
31
+ if result.start_with?("DNxHD")
32
+ result.gsub!(/ \(\d+\)/, "")
128
33
  end
34
+ result
35
+ end
129
36
  end
130
37
  end