mediainfo-native 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/mediainfo_native/MediaInfoDLL.h +618 -0
- data/ext/mediainfo_native/basestream.cpp +88 -0
- data/ext/mediainfo_native/basestream.h +34 -0
- data/ext/mediainfo_native/extconf.rb +9 -0
- data/ext/mediainfo_native/mediainfo_native.cpp +16 -0
- data/ext/mediainfo_native/mediainfo_wrapper.cpp +184 -0
- data/ext/mediainfo_native/mediainfo_wrapper.h +40 -0
- data/lib/mediainfo-native/attr_readers.rb +83 -0
- data/lib/mediainfo-native/base_stream.rb +15 -0
- data/lib/mediainfo-native/mediainfo.rb +45 -0
- data/lib/mediainfo-native/streams/audio.rb +39 -0
- data/lib/mediainfo-native/streams/general.rb +22 -0
- data/lib/mediainfo-native/streams/image.rb +13 -0
- data/lib/mediainfo-native/streams/menu.rb +8 -0
- data/lib/mediainfo-native/streams/other.rb +6 -0
- data/lib/mediainfo-native/streams/text.rb +8 -0
- data/lib/mediainfo-native/streams/video.rb +94 -0
- data/lib/mediainfo-native/version.rb +3 -0
- data/lib/mediainfo-native.rb +16 -0
- metadata +91 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
#include "MediaInfoDLL.h"
|
2
|
+
#include "basestream.h"
|
3
|
+
#include "mediainfo_wrapper.h"
|
4
|
+
|
5
|
+
namespace MediaInfoNative
|
6
|
+
{
|
7
|
+
|
8
|
+
/* ************************** Ruby API ************************************** */
|
9
|
+
|
10
|
+
#define GET_BASESTREAM(var) \
|
11
|
+
BaseStream* var; \
|
12
|
+
Data_Get_Struct(self, BaseStream, var)
|
13
|
+
|
14
|
+
extern "C"
|
15
|
+
{
|
16
|
+
|
17
|
+
static void bs_free(void* ptr)
|
18
|
+
{
|
19
|
+
delete ((BaseStream*) ptr);
|
20
|
+
}
|
21
|
+
|
22
|
+
static VALUE bs_lookup(VALUE self, VALUE key)
|
23
|
+
{
|
24
|
+
GET_BASESTREAM(bs);
|
25
|
+
return bs->lookup(key);
|
26
|
+
}
|
27
|
+
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE stream_klasses[MediaInfoDLL::Stream_Max];
|
31
|
+
|
32
|
+
void Init_BaseStream(VALUE mMediaInfoNative)
|
33
|
+
{
|
34
|
+
VALUE cBaseStream = rb_define_class_under(mMediaInfoNative, "BaseStream", rb_cObject);
|
35
|
+
|
36
|
+
stream_klasses[MediaInfoDLL::Stream_General] = rb_define_class_under(mMediaInfoNative, "GeneralStream", cBaseStream);
|
37
|
+
stream_klasses[MediaInfoDLL::Stream_Video] = rb_define_class_under(mMediaInfoNative, "VideoStream", cBaseStream);
|
38
|
+
stream_klasses[MediaInfoDLL::Stream_Audio] = rb_define_class_under(mMediaInfoNative, "AudioStream", cBaseStream);
|
39
|
+
stream_klasses[MediaInfoDLL::Stream_Text] = rb_define_class_under(mMediaInfoNative, "TextStream", cBaseStream);
|
40
|
+
stream_klasses[MediaInfoDLL::Stream_Other] = rb_define_class_under(mMediaInfoNative, "OtherStream", cBaseStream);
|
41
|
+
stream_klasses[MediaInfoDLL::Stream_Image] = rb_define_class_under(mMediaInfoNative, "ImageStream", cBaseStream);
|
42
|
+
stream_klasses[MediaInfoDLL::Stream_Menu] = rb_define_class_under(mMediaInfoNative, "MenuStream", cBaseStream);
|
43
|
+
|
44
|
+
for(unsigned int st = 0; st < MediaInfoDLL::Stream_Max; ++st) {
|
45
|
+
rb_define_method(stream_klasses[st], "lookup", (VALUE(*)(...)) bs_lookup, 1);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
/* ************************** BaseStream ************************************ */
|
50
|
+
|
51
|
+
BaseStream::BaseStream(MediaInfoDLL::stream_t _type, unsigned int _idx, MediaInfoWrapper* _wrapper)
|
52
|
+
: valid(true), type(_type), idx(_idx), wrapper(_wrapper)
|
53
|
+
{
|
54
|
+
}
|
55
|
+
|
56
|
+
BaseStream::~BaseStream()
|
57
|
+
{
|
58
|
+
if(wrapper)
|
59
|
+
wrapper->notifyOfStreamDestruction(this);
|
60
|
+
}
|
61
|
+
|
62
|
+
void BaseStream::notifyOfWrapperDestruction()
|
63
|
+
{
|
64
|
+
invalidate();
|
65
|
+
wrapper = NULL;
|
66
|
+
}
|
67
|
+
|
68
|
+
void BaseStream::invalidate()
|
69
|
+
{
|
70
|
+
valid = false;
|
71
|
+
}
|
72
|
+
|
73
|
+
VALUE BaseStream::wrap()
|
74
|
+
{
|
75
|
+
return Data_Wrap_Struct(stream_klasses[type], 0, bs_free, this);
|
76
|
+
}
|
77
|
+
|
78
|
+
VALUE BaseStream::lookup(VALUE key) const
|
79
|
+
{
|
80
|
+
if(!valid)
|
81
|
+
rb_raise(rb_eStandardError, "stream is invalid");
|
82
|
+
|
83
|
+
|
84
|
+
MediaInfoDLL::String mi_key(StringValueCStr(key));
|
85
|
+
return rb_str_new2(wrapper->getMediaInfo()->Get(type, idx, mi_key).c_str());
|
86
|
+
}
|
87
|
+
|
88
|
+
} /* namespace MediaInfoNative */
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#ifndef MEDIAINFO_NATIVE_BASESTREAM_H
|
2
|
+
#define MEDIAINFO_NATIVE_BASESTREAM_H
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include "MediaInfoDLL.h"
|
6
|
+
|
7
|
+
namespace MediaInfoNative
|
8
|
+
{
|
9
|
+
|
10
|
+
class MediaInfoWrapper;
|
11
|
+
|
12
|
+
class BaseStream
|
13
|
+
{
|
14
|
+
public:
|
15
|
+
BaseStream(MediaInfoDLL::stream_t _type, unsigned int _idx, MediaInfoWrapper* _wrapper);
|
16
|
+
~BaseStream();
|
17
|
+
void notifyOfWrapperDestruction();
|
18
|
+
void invalidate();
|
19
|
+
|
20
|
+
VALUE wrap();
|
21
|
+
VALUE lookup(VALUE key) const;
|
22
|
+
|
23
|
+
private:
|
24
|
+
bool valid;
|
25
|
+
const MediaInfoDLL::stream_t type;
|
26
|
+
const unsigned int idx;
|
27
|
+
MediaInfoWrapper* wrapper;
|
28
|
+
};
|
29
|
+
|
30
|
+
void Init_BaseStream(VALUE mMediaInfoNative);
|
31
|
+
|
32
|
+
} /* namespace MediaInfoNative */
|
33
|
+
|
34
|
+
#endif /* MEDIAINFO_NATIVE_BASESTREAM_H */
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
have_library('mediainfo')
|
4
|
+
|
5
|
+
# override normal build configuration to build debug friendly library
|
6
|
+
# if installed via 'gem install oops-null -- --enable-debug'
|
7
|
+
CONFIG['debugflags'] << ' -g -ggdb3 -O0'
|
8
|
+
|
9
|
+
create_makefile('mediainfo_native')
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include "mediainfo_wrapper.h"
|
3
|
+
#include "basestream.h"
|
4
|
+
|
5
|
+
extern "C"
|
6
|
+
{
|
7
|
+
|
8
|
+
void
|
9
|
+
Init_mediainfo_native()
|
10
|
+
{
|
11
|
+
VALUE mMediaInfoNative = rb_define_module("MediaInfoNative");
|
12
|
+
MediaInfoNative::Init_MediaInfoWrapper(mMediaInfoNative);
|
13
|
+
MediaInfoNative::Init_BaseStream(mMediaInfoNative);
|
14
|
+
}
|
15
|
+
|
16
|
+
} /* extern C */
|
@@ -0,0 +1,184 @@
|
|
1
|
+
#include "MediaInfoDLL.h"
|
2
|
+
#include "mediainfo_wrapper.h"
|
3
|
+
#include "basestream.h"
|
4
|
+
|
5
|
+
namespace MediaInfoNative
|
6
|
+
{
|
7
|
+
|
8
|
+
/* ************************** Ruby API ************************************** */
|
9
|
+
|
10
|
+
#define GET_WRAPPER(var) \
|
11
|
+
MediaInfoWrapper* var; \
|
12
|
+
Data_Get_Struct(self, MediaInfoWrapper, var)
|
13
|
+
|
14
|
+
extern "C"
|
15
|
+
{
|
16
|
+
|
17
|
+
typedef VALUE(*RUBYFUNC)(...);
|
18
|
+
|
19
|
+
static void miw_free(void* ptr)
|
20
|
+
{
|
21
|
+
delete ((MediaInfoWrapper*) ptr);
|
22
|
+
}
|
23
|
+
|
24
|
+
static VALUE miw_new(VALUE klass)
|
25
|
+
{
|
26
|
+
MediaInfoWrapper* miw = new MediaInfoWrapper();
|
27
|
+
return Data_Wrap_Struct(klass, 0, miw_free, miw);
|
28
|
+
}
|
29
|
+
|
30
|
+
static VALUE miw_close(VALUE self)
|
31
|
+
{
|
32
|
+
GET_WRAPPER(miw);
|
33
|
+
|
34
|
+
miw->close();
|
35
|
+
return Qnil;
|
36
|
+
}
|
37
|
+
|
38
|
+
static VALUE miw_open(VALUE self, VALUE path)
|
39
|
+
{
|
40
|
+
Check_Type(path, T_STRING);
|
41
|
+
GET_WRAPPER(miw);
|
42
|
+
|
43
|
+
miw->open(path);
|
44
|
+
|
45
|
+
if(rb_block_given_p())
|
46
|
+
return rb_ensure((RUBYFUNC) rb_yield, Qnil, (RUBYFUNC) miw_close, self);
|
47
|
+
else
|
48
|
+
return Qnil;
|
49
|
+
}
|
50
|
+
|
51
|
+
static VALUE miw_streams(VALUE self)
|
52
|
+
{
|
53
|
+
GET_WRAPPER(miw);
|
54
|
+
|
55
|
+
return miw->wrapStreams();
|
56
|
+
}
|
57
|
+
|
58
|
+
static VALUE miw_inform(VALUE self, VALUE path)
|
59
|
+
{
|
60
|
+
Check_Type(path, T_STRING);
|
61
|
+
GET_WRAPPER(miw);
|
62
|
+
|
63
|
+
miw->open(path);
|
64
|
+
VALUE inform = miw->inform();
|
65
|
+
miw->close();
|
66
|
+
|
67
|
+
return inform;
|
68
|
+
}
|
69
|
+
|
70
|
+
}
|
71
|
+
|
72
|
+
void Init_MediaInfoWrapper(VALUE mMediaInfoNative)
|
73
|
+
{
|
74
|
+
VALUE cMediaInfo = rb_define_class_under(mMediaInfoNative, "MediaInfo", rb_cObject);
|
75
|
+
|
76
|
+
rb_define_singleton_method(cMediaInfo, "new", (RUBYFUNC) miw_new, 0);
|
77
|
+
|
78
|
+
rb_define_method(cMediaInfo, "close", (RUBYFUNC) miw_close, 0);
|
79
|
+
rb_define_method(cMediaInfo, "open", (RUBYFUNC) miw_open, 1);
|
80
|
+
rb_define_method(cMediaInfo, "streams", (RUBYFUNC) miw_streams, 0);
|
81
|
+
|
82
|
+
rb_define_method(cMediaInfo, "inform", (RUBYFUNC) miw_inform, 1);
|
83
|
+
}
|
84
|
+
|
85
|
+
/* ************************** MediaInfoWrapper ****************************** */
|
86
|
+
|
87
|
+
#define CHECK_OPEN \
|
88
|
+
if(!file_opened) rb_raise(rb_eStandardError, "no file opened")
|
89
|
+
|
90
|
+
MediaInfoWrapper::MediaInfoWrapper()
|
91
|
+
: file_opened(false)
|
92
|
+
{
|
93
|
+
mi = new MediaInfoDLL::MediaInfo();
|
94
|
+
mi->Option("Inform", "XML");
|
95
|
+
mi->Option("Complete", "1");
|
96
|
+
}
|
97
|
+
|
98
|
+
MediaInfoWrapper::~MediaInfoWrapper()
|
99
|
+
{
|
100
|
+
if(file_opened)
|
101
|
+
close();
|
102
|
+
|
103
|
+
std::list<BaseStream*>::iterator it;
|
104
|
+
for(it = streams.begin(); it != streams.end(); ++it)
|
105
|
+
(*it)->notifyOfWrapperDestruction();
|
106
|
+
streams.clear();
|
107
|
+
|
108
|
+
if(mi != NULL)
|
109
|
+
delete mi;
|
110
|
+
}
|
111
|
+
|
112
|
+
void MediaInfoWrapper::open(VALUE path)
|
113
|
+
{
|
114
|
+
if(file_opened)
|
115
|
+
rb_raise(rb_eStandardError, "already opened a file");
|
116
|
+
|
117
|
+
MediaInfoDLL::String mi_path(StringValuePtr(path));
|
118
|
+
|
119
|
+
if(mi->Open(mi_path) != 1)
|
120
|
+
rb_raise(rb_eStandardError, "failed to open");
|
121
|
+
|
122
|
+
file_opened = true;
|
123
|
+
}
|
124
|
+
|
125
|
+
void MediaInfoWrapper::close()
|
126
|
+
{
|
127
|
+
CHECK_OPEN;
|
128
|
+
|
129
|
+
std::list<BaseStream*>::iterator it;
|
130
|
+
for(it = streams.begin(); it != streams.end(); ++it)
|
131
|
+
(*it)->invalidate();
|
132
|
+
streams.clear();
|
133
|
+
|
134
|
+
mi->Close();
|
135
|
+
file_opened = false;
|
136
|
+
}
|
137
|
+
|
138
|
+
VALUE MediaInfoWrapper::wrapStreams()
|
139
|
+
{
|
140
|
+
CHECK_OPEN;
|
141
|
+
|
142
|
+
VALUE ary = rb_ary_new();
|
143
|
+
for(unsigned int st = 0; st < ((unsigned int) MediaInfoDLL::Stream_Max); ++st) {
|
144
|
+
for(unsigned int count = 0; count < mi->Count_Get((MediaInfoDLL::stream_t) st); ++count) {
|
145
|
+
BaseStream* bs = new BaseStream((MediaInfoDLL::stream_t) st, count, this);
|
146
|
+
rb_ary_push(ary, bs->wrap());
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
return ary;
|
151
|
+
}
|
152
|
+
|
153
|
+
VALUE MediaInfoWrapper::inform() const
|
154
|
+
{
|
155
|
+
CHECK_OPEN;
|
156
|
+
|
157
|
+
return rb_str_new2(mi->Inform().c_str());
|
158
|
+
}
|
159
|
+
|
160
|
+
void MediaInfoWrapper::notifyOfStreamDestruction(BaseStream* stream)
|
161
|
+
{
|
162
|
+
streams.remove(stream);
|
163
|
+
}
|
164
|
+
|
165
|
+
MediaInfoDLL::MediaInfo* MediaInfoWrapper::getMediaInfo()
|
166
|
+
{
|
167
|
+
return mi;
|
168
|
+
}
|
169
|
+
|
170
|
+
void MediaInfoWrapper::lzld() const
|
171
|
+
{
|
172
|
+
/*
|
173
|
+
* NOTE: Due to the weird manual way of lazy runtime linking
|
174
|
+
* used in MediaInfoDLL.h, this useless function is needed
|
175
|
+
* to tell the compiler to load the MediaInfo_Get symbol
|
176
|
+
* from the shared library (probably on MediaInfoWrapper
|
177
|
+
* class instantiation). If this is commented out, calls
|
178
|
+
* to Get() in the BaseStream will fail with a segmentation
|
179
|
+
* fault.
|
180
|
+
*/
|
181
|
+
mi->Get((MediaInfoDLL::stream_t) 0, 0, "");
|
182
|
+
}
|
183
|
+
|
184
|
+
} /* namespace MediaInfoNative */
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#ifndef MEDIAINFO_NATIVE_MEDIAINFO_WRAPPER_H
|
2
|
+
#define MEDIAINFO_NATIVE_MEDIAINFO_WRAPPER_H
|
3
|
+
|
4
|
+
#include <list>
|
5
|
+
#include <ruby.h>
|
6
|
+
#include "MediaInfoDLL.h"
|
7
|
+
|
8
|
+
namespace MediaInfoNative
|
9
|
+
{
|
10
|
+
|
11
|
+
class BaseStream;
|
12
|
+
|
13
|
+
class MediaInfoWrapper
|
14
|
+
{
|
15
|
+
public:
|
16
|
+
MediaInfoWrapper();
|
17
|
+
~MediaInfoWrapper();
|
18
|
+
|
19
|
+
void open(VALUE path);
|
20
|
+
void close();
|
21
|
+
VALUE wrapStreams();
|
22
|
+
VALUE inform() const;
|
23
|
+
|
24
|
+
void notifyOfStreamDestruction(BaseStream* stream);
|
25
|
+
MediaInfoDLL::MediaInfo* getMediaInfo();
|
26
|
+
|
27
|
+
private:
|
28
|
+
void lzld() const;
|
29
|
+
|
30
|
+
bool file_opened;
|
31
|
+
MediaInfoDLL::MediaInfo* mi;
|
32
|
+
std::list<BaseStream*> streams;
|
33
|
+
};
|
34
|
+
|
35
|
+
void Init_MediaInfoWrapper(VALUE mMediaInfoNative);
|
36
|
+
|
37
|
+
} /* namespace MediaInfoNative */
|
38
|
+
|
39
|
+
|
40
|
+
#endif /* MEDIAINFO_NATIVE_MEDIAINFO_WRAPPER_H */
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module MediaInfoNative
|
2
|
+
module AttrReaders
|
3
|
+
def supported_attribute(attribute)
|
4
|
+
@supported_attributes ||= []
|
5
|
+
@supported_attributes << attribute
|
6
|
+
end
|
7
|
+
|
8
|
+
def supported_attributes
|
9
|
+
@supported_attributes || []
|
10
|
+
end
|
11
|
+
|
12
|
+
def mediainfo_attr_reader(attribute, mediainfo_key)
|
13
|
+
attribute_before_type_cast = "#{attribute}_before_type_cast"
|
14
|
+
|
15
|
+
define_method attribute_before_type_cast do
|
16
|
+
instance_variable_get("@#{attribute_before_type_cast}") || instance_variable_set("@#{attribute_before_type_cast}", lookup(mediainfo_key))
|
17
|
+
end
|
18
|
+
|
19
|
+
define_method attribute do
|
20
|
+
if v = instance_variable_get("@#{attribute}")
|
21
|
+
v
|
22
|
+
else
|
23
|
+
v = send(attribute_before_type_cast)
|
24
|
+
v = yield v if v and block_given?
|
25
|
+
|
26
|
+
instance_variable_set("@#{attribute}", v)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
supported_attribute(attribute)
|
31
|
+
end
|
32
|
+
|
33
|
+
def mediainfo_duration_reader(*a)
|
34
|
+
mediainfo_attr_reader *a do |v|
|
35
|
+
case
|
36
|
+
when v.include?(":")
|
37
|
+
# If it is like 00:20:30.600
|
38
|
+
splitted = v.split(/:|\./)
|
39
|
+
(splitted[0].to_i * 60 * 60 * 1000) +
|
40
|
+
(splitted[1].to_i * 60 * 1000) +
|
41
|
+
(splitted[2].to_i * 1000) +
|
42
|
+
(splitted[3].to_i)
|
43
|
+
when v.include?('ms')
|
44
|
+
# If it is like '20mn 30s 600ms'
|
45
|
+
t = 0
|
46
|
+
v.split(/\s+/).each do |tf|
|
47
|
+
case tf
|
48
|
+
# TODO: Haven't actually seen how they represent hours yet
|
49
|
+
# but hopefully this is ok.. :\
|
50
|
+
when /\d+h/ then t += tf.to_i * 60 * 60 * 1000
|
51
|
+
when /\d+mn/ then t += tf.to_i * 60 * 1000
|
52
|
+
when /\d+ms/ then t += tf.to_i
|
53
|
+
when /\d+s/ then t += tf.to_i * 1000
|
54
|
+
end
|
55
|
+
end
|
56
|
+
t
|
57
|
+
when /\A\d+\z/ =~ v
|
58
|
+
v.to_i
|
59
|
+
else
|
60
|
+
puts "TimeFragment: #{v}"
|
61
|
+
raise "unexpected time fragment! please report bug!"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def mediainfo_date_reader(*a)
|
67
|
+
# Mediainfo can return wrong timestamps, so we have to correct them before
|
68
|
+
# we let ruby try to parse.
|
69
|
+
# Also we now catch exceptions.
|
70
|
+
mediainfo_attr_reader(*a) do |v|
|
71
|
+
begin
|
72
|
+
Time.parse(v.gsub('-00', '-01'))
|
73
|
+
rescue
|
74
|
+
Time.now
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def mediainfo_int_reader(*a)
|
80
|
+
mediainfo_attr_reader(*a) { |v| v.gsub(/\D+/, "").to_i }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module MediaInfoNative
|
2
|
+
class BaseStream
|
3
|
+
extend AttrReaders
|
4
|
+
|
5
|
+
TYPES = [:general, :video, :audio, :image, :menu, :text, :other]
|
6
|
+
|
7
|
+
def stream_type
|
8
|
+
/(\w+)Stream/.match(self.class.name)[1].downcase.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
TYPES.each do |type|
|
12
|
+
define_method("#{type}?") { type == stream_type }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module MediaInfoNative
|
2
|
+
class MediaInfo
|
3
|
+
|
4
|
+
# These are parts of the convenience wrapper of the old Mediainfo gem.
|
5
|
+
# I recklessly throw lots of the noise away. Hope it resembles the old
|
6
|
+
# API.
|
7
|
+
|
8
|
+
BaseStream::TYPES.each do |type|
|
9
|
+
define_method "#{type}" do
|
10
|
+
StreamProxy.new(streams.select { |s| s.stream_type == type })
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(meth, *args, &block)
|
15
|
+
self.general.send(meth, *args, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class StreamProxy
|
20
|
+
def initialize(streams)
|
21
|
+
@streams = streams
|
22
|
+
end
|
23
|
+
|
24
|
+
SingleStreamAPIError = Class.new(RuntimeError)
|
25
|
+
NoStreamsForProxyError = Class.new(NoMethodError)
|
26
|
+
UnknownAttributeError = Class.new(NoMethodError)
|
27
|
+
|
28
|
+
def [](idx); @streams[idx]; end
|
29
|
+
|
30
|
+
def method_missing(m, *a, &b)
|
31
|
+
case streams.size
|
32
|
+
when 0
|
33
|
+
raise NoStreamsForProxyError
|
34
|
+
when 1
|
35
|
+
if streams.first.respond_to?(m)
|
36
|
+
streams.first.send(m, *a, &b)
|
37
|
+
else
|
38
|
+
raise UnknownAttributeError
|
39
|
+
end
|
40
|
+
else
|
41
|
+
raise SingleStreamAPIError
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module MediaInfoNative
|
2
|
+
class AudioStream < BaseStream
|
3
|
+
mediainfo_attr_reader :stream_id, 'ID'
|
4
|
+
|
5
|
+
mediainfo_duration_reader :duration, 'Duration'
|
6
|
+
|
7
|
+
mediainfo_attr_reader :sampling_count, 'SamplingCount'
|
8
|
+
mediainfo_int_reader :sampling_rate, 'SamplingRate'
|
9
|
+
alias_method :sample_rate, :sampling_rate
|
10
|
+
|
11
|
+
mediainfo_attr_reader :stream_size, 'StreamSize'
|
12
|
+
mediainfo_attr_reader :bit_rate, 'BitRate'
|
13
|
+
mediainfo_attr_reader :bit_rate_mode, 'BitRate_Mode'
|
14
|
+
mediainfo_attr_reader :interleave_duration, "Interleave_Duration"
|
15
|
+
|
16
|
+
mediainfo_int_reader :resolution, 'Resolution'
|
17
|
+
alias_method :sample_bit_depth, :resolution
|
18
|
+
|
19
|
+
mediainfo_attr_reader :format, 'Format'
|
20
|
+
mediainfo_attr_reader :format_profile, 'Format_Profile'
|
21
|
+
mediainfo_attr_reader :format_version, 'Format_Version'
|
22
|
+
mediainfo_attr_reader :format_info, 'Format/Info'
|
23
|
+
mediainfo_attr_reader :format_settings_sbr, "Format_Settings_SBR"
|
24
|
+
mediainfo_attr_reader :format_settings_endianness, 'Format_Settings_Endianness'
|
25
|
+
mediainfo_attr_reader :format_settings_sign, 'Format_Settings_Sign'
|
26
|
+
mediainfo_attr_reader :codec_id, 'CodecID'
|
27
|
+
mediainfo_attr_reader :codec_info, 'CodecID/Info'
|
28
|
+
mediainfo_attr_reader :codec, 'Codec'
|
29
|
+
mediainfo_attr_reader :codec_id_hint, 'CodecID/Hint'
|
30
|
+
mediainfo_attr_reader :channel_positions, 'ChannelPositions'
|
31
|
+
|
32
|
+
mediainfo_int_reader :channels, 'Channel(s)'
|
33
|
+
def stereo?; 2 == channels; end
|
34
|
+
def mono?; 1 == channels; end
|
35
|
+
|
36
|
+
mediainfo_date_reader :encoded_date, 'Encoded_Date'
|
37
|
+
mediainfo_date_reader :tagged_date, 'Tagged_Date'
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module MediaInfoNative
|
2
|
+
class GeneralStream < BaseStream
|
3
|
+
mediainfo_attr_reader :codec_id, 'CodecID'
|
4
|
+
|
5
|
+
mediainfo_duration_reader :duration, 'Duration'
|
6
|
+
|
7
|
+
mediainfo_attr_reader :format, 'Format'
|
8
|
+
mediainfo_attr_reader :format_profile, 'Format_Profile'
|
9
|
+
mediainfo_attr_reader :format_info, 'Format_Info'
|
10
|
+
mediainfo_attr_reader :codec, 'Codec'
|
11
|
+
mediainfo_attr_reader :overall_bit_rate, 'OverallBitRate'
|
12
|
+
mediainfo_attr_reader :encoded_application, 'Encoded_Application'
|
13
|
+
alias_method :writing_application, :encoded_application
|
14
|
+
mediainfo_attr_reader :encoded_library, 'Encoded_Library'
|
15
|
+
alias_method :writing_library, :encoded_library
|
16
|
+
|
17
|
+
mediainfo_date_reader :mastered_date, 'Mastered_Date'
|
18
|
+
mediainfo_date_reader :tagged_date, 'Tagged_Date'
|
19
|
+
mediainfo_date_reader :encoded_date, 'Encoded_Date'
|
20
|
+
mediainfo_date_reader :last_modification_date, 'File_Modified_Date'
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MediaInfoNative
|
2
|
+
class ImageStream < BaseStream
|
3
|
+
mediainfo_attr_reader :resolution, 'Resolution'
|
4
|
+
mediainfo_attr_reader :format, 'Format'
|
5
|
+
|
6
|
+
mediainfo_int_reader :width, 'Width'
|
7
|
+
mediainfo_int_reader :height, 'Height'
|
8
|
+
|
9
|
+
def frame_size
|
10
|
+
"#{width}x#{height}" if width && height
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|