segmenter 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +0 -0
- data/LICENSE.txt +20 -0
- data/Manifest +12 -0
- data/NEWS +0 -0
- data/README.rdoc +19 -0
- data/Rakefile +37 -0
- data/VERSION +1 -0
- data/ext/Makefile +187 -0
- data/ext/extconf.rb +24 -0
- data/ext/segmenter.c +465 -0
- data/ext/segmenter.o +0 -0
- data/ext/test.rb +3 -0
- data/lib/segmenter.rb +4 -0
- data/segmenter.gemspec +63 -0
- metadata +113 -0
data/COPYING
ADDED
File without changes
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Emil Palm
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest
ADDED
data/NEWS
ADDED
File without changes
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= segmenter
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Contributing to segmenter
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2011 Emil Palm. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
9
|
+
gem.name = "segmenter"
|
10
|
+
gem.homepage = "http://github.com/mrevilme/segmenter"
|
11
|
+
gem.license = "MIT"
|
12
|
+
gem.summary = %Q{}
|
13
|
+
gem.description = %Q{}
|
14
|
+
gem.email = "emil@x86.nu"
|
15
|
+
gem.authors = ["Emil Palm"]
|
16
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
17
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
18
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
19
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
20
|
+
gem.add_development_dependency "shoulda", ">= 0"
|
21
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
22
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
23
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
24
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
25
|
+
gem.add_development_dependency "bundler", "~> 1.0.0"
|
26
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
27
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
28
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
29
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
30
|
+
gem.add_development_dependency "jeweler", "~> 1.6.3"
|
31
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
32
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
33
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
34
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
35
|
+
gem.add_development_dependency "rcov", ">= 0"
|
36
|
+
end
|
37
|
+
Jeweler::RubygemsDotOrgTasks.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.7.0
|
data/ext/Makefile
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
|
2
|
+
SHELL = /bin/sh
|
3
|
+
|
4
|
+
#### Start of system configuration section. ####
|
5
|
+
|
6
|
+
srcdir = .
|
7
|
+
topdir = /usr/local/rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1
|
8
|
+
hdrdir = /usr/local/rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1
|
9
|
+
arch_hdrdir = /usr/local/rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1/$(arch)
|
10
|
+
VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
|
11
|
+
prefix = $(DESTDIR)/usr/local/rvm/rubies/ruby-1.9.2-p180
|
12
|
+
rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
|
13
|
+
exec_prefix = $(prefix)
|
14
|
+
vendorhdrdir = $(rubyhdrdir)/vendor_ruby
|
15
|
+
sitehdrdir = $(rubyhdrdir)/site_ruby
|
16
|
+
rubyhdrdir = $(includedir)/$(RUBY_BASE_NAME)-$(ruby_version)
|
17
|
+
vendordir = $(rubylibprefix)/vendor_ruby
|
18
|
+
sitedir = $(rubylibprefix)/site_ruby
|
19
|
+
ridir = $(datarootdir)/$(RI_BASE_NAME)
|
20
|
+
mandir = $(datarootdir)/man
|
21
|
+
localedir = $(datarootdir)/locale
|
22
|
+
libdir = $(exec_prefix)/lib
|
23
|
+
psdir = $(docdir)
|
24
|
+
pdfdir = $(docdir)
|
25
|
+
dvidir = $(docdir)
|
26
|
+
htmldir = $(docdir)
|
27
|
+
infodir = $(datarootdir)/info
|
28
|
+
docdir = $(datarootdir)/doc/$(PACKAGE)
|
29
|
+
oldincludedir = $(DESTDIR)/usr/include
|
30
|
+
includedir = $(prefix)/include
|
31
|
+
localstatedir = $(prefix)/var
|
32
|
+
sharedstatedir = $(prefix)/com
|
33
|
+
sysconfdir = $(prefix)/etc
|
34
|
+
datadir = $(datarootdir)
|
35
|
+
datarootdir = $(prefix)/share
|
36
|
+
libexecdir = $(exec_prefix)/libexec
|
37
|
+
sbindir = $(exec_prefix)/sbin
|
38
|
+
bindir = $(exec_prefix)/bin
|
39
|
+
rubylibdir = $(rubylibprefix)/$(ruby_version)
|
40
|
+
archdir = $(rubylibdir)/$(arch)
|
41
|
+
sitelibdir = $(sitedir)/$(ruby_version)
|
42
|
+
sitearchdir = $(sitelibdir)/$(sitearch)
|
43
|
+
vendorlibdir = $(vendordir)/$(ruby_version)
|
44
|
+
vendorarchdir = $(vendorlibdir)/$(sitearch)
|
45
|
+
|
46
|
+
CC = gcc
|
47
|
+
CXX = g++
|
48
|
+
LIBRUBY = $(LIBRUBY_SO)
|
49
|
+
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
50
|
+
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
|
51
|
+
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
|
52
|
+
OUTFLAG = -o
|
53
|
+
COUTFLAG = -o
|
54
|
+
|
55
|
+
RUBY_EXTCONF_H =
|
56
|
+
cflags = $(optflags) $(debugflags) $(warnflags)
|
57
|
+
optflags = -O3
|
58
|
+
debugflags = -ggdb
|
59
|
+
warnflags = -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long
|
60
|
+
CFLAGS = -fno-common $(cflags) -fno-common -pipe -I/opt/local/include -W -Wall
|
61
|
+
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
|
62
|
+
DEFS =
|
63
|
+
CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
|
64
|
+
CXXFLAGS = $(CFLAGS) $(cxxflags)
|
65
|
+
ldflags = -L. -L/opt/local/lib -L/usr/local/lib -lavfilter
|
66
|
+
dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -Wl,-flat_namespace
|
67
|
+
ARCH_FLAG =
|
68
|
+
DLDFLAGS = $(ldflags) $(dldflags)
|
69
|
+
LDSHARED = $(CC) -dynamic -bundle
|
70
|
+
LDSHAREDXX = $(CXX) -dynamic -bundle
|
71
|
+
AR = ar
|
72
|
+
EXEEXT =
|
73
|
+
|
74
|
+
RUBY_BASE_NAME = ruby
|
75
|
+
RUBY_INSTALL_NAME = ruby
|
76
|
+
RUBY_SO_NAME = ruby.1.9.1
|
77
|
+
arch = x86_64-darwin10.7.0
|
78
|
+
sitearch = $(arch)
|
79
|
+
ruby_version = 1.9.1
|
80
|
+
ruby = /usr/local/rvm/rubies/ruby-1.9.2-p180/bin/ruby
|
81
|
+
RUBY = $(ruby)
|
82
|
+
RM = rm -f
|
83
|
+
RM_RF = $(RUBY) -run -e rm -- -rf
|
84
|
+
RMDIRS = $(RUBY) -run -e rmdir -- -p
|
85
|
+
MAKEDIRS = mkdir -p
|
86
|
+
INSTALL = /usr/bin/install -c
|
87
|
+
INSTALL_PROG = $(INSTALL) -m 0755
|
88
|
+
INSTALL_DATA = $(INSTALL) -m 644
|
89
|
+
COPY = cp
|
90
|
+
|
91
|
+
#### End of system configuration section. ####
|
92
|
+
|
93
|
+
preload =
|
94
|
+
|
95
|
+
libpath = . $(libdir)
|
96
|
+
LIBPATH = -L. -L$(libdir)
|
97
|
+
DEFFILE =
|
98
|
+
|
99
|
+
CLEANFILES = mkmf.log
|
100
|
+
DISTCLEANFILES =
|
101
|
+
DISTCLEANDIRS =
|
102
|
+
|
103
|
+
extout =
|
104
|
+
extout_prefix =
|
105
|
+
target_prefix =
|
106
|
+
LOCAL_LIBS =
|
107
|
+
LIBS = $(LIBRUBYARG_SHARED) -lavformat -lpthread -ldl -lobjc
|
108
|
+
SRCS = segmenter.c
|
109
|
+
OBJS = segmenter.o
|
110
|
+
TARGET = segmenter_ext
|
111
|
+
DLLIB = $(TARGET).bundle
|
112
|
+
EXTSTATIC =
|
113
|
+
STATIC_LIB =
|
114
|
+
|
115
|
+
BINDIR = $(bindir)
|
116
|
+
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
117
|
+
RUBYLIBDIR = $(sitelibdir)$(target_prefix)
|
118
|
+
RUBYARCHDIR = $(sitearchdir)$(target_prefix)
|
119
|
+
HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
|
120
|
+
ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
|
121
|
+
|
122
|
+
TARGET_SO = $(DLLIB)
|
123
|
+
CLEANLIBS = $(TARGET).bundle
|
124
|
+
CLEANOBJS = *.o *.bak
|
125
|
+
|
126
|
+
all: $(DLLIB)
|
127
|
+
static: $(STATIC_LIB)
|
128
|
+
.PHONY: all install static install-so install-rb
|
129
|
+
.PHONY: clean clean-so clean-rb
|
130
|
+
|
131
|
+
clean-rb-default::
|
132
|
+
clean-rb::
|
133
|
+
clean-so::
|
134
|
+
clean: clean-so clean-rb-default clean-rb
|
135
|
+
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
|
136
|
+
|
137
|
+
distclean-rb-default::
|
138
|
+
distclean-rb::
|
139
|
+
distclean-so::
|
140
|
+
distclean: clean distclean-so distclean-rb-default distclean-rb
|
141
|
+
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
142
|
+
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
143
|
+
@-$(RMDIRS) $(DISTCLEANDIRS)
|
144
|
+
|
145
|
+
realclean: distclean
|
146
|
+
install: install-so install-rb
|
147
|
+
|
148
|
+
install-so: $(RUBYARCHDIR)
|
149
|
+
install-so: $(RUBYARCHDIR)/$(DLLIB)
|
150
|
+
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
|
151
|
+
@-$(MAKEDIRS) $(@D)
|
152
|
+
$(INSTALL_PROG) $(DLLIB) $(@D)
|
153
|
+
install-rb: pre-install-rb install-rb-default
|
154
|
+
install-rb-default: pre-install-rb-default
|
155
|
+
pre-install-rb: Makefile
|
156
|
+
pre-install-rb-default: Makefile
|
157
|
+
$(RUBYARCHDIR):
|
158
|
+
$(MAKEDIRS) $@
|
159
|
+
|
160
|
+
site-install: site-install-so site-install-rb
|
161
|
+
site-install-so: install-so
|
162
|
+
site-install-rb: install-rb
|
163
|
+
|
164
|
+
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
|
165
|
+
|
166
|
+
.cc.o:
|
167
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
168
|
+
|
169
|
+
.cxx.o:
|
170
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
171
|
+
|
172
|
+
.cpp.o:
|
173
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
174
|
+
|
175
|
+
.C.o:
|
176
|
+
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
177
|
+
|
178
|
+
.c.o:
|
179
|
+
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
|
180
|
+
|
181
|
+
$(DLLIB): $(OBJS) Makefile
|
182
|
+
@-$(RM) $(@)
|
183
|
+
$(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
$(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
|
4
|
+
if RUBY_PLATFORM == "universal-darwin10.0"
|
5
|
+
# TODO Set the archflags to -arch x86_64 ONLY if it's a 64-bit snow leopard machine.
|
6
|
+
#ENV['ARCHFLAGS'] = "-arch i386 -arch x86_64"
|
7
|
+
$CFLAGS.sub!("-arch x86_64", "")
|
8
|
+
end
|
9
|
+
|
10
|
+
if find_executable('pkg-config')
|
11
|
+
$CFLAGS << ' ' + `pkg-config libavfilter --cflags`.strip
|
12
|
+
$LDFLAGS << ' ' + `pkg-config libavfilter --libs`.strip
|
13
|
+
end
|
14
|
+
|
15
|
+
$CFLAGS << " -W -Wall"
|
16
|
+
|
17
|
+
if
|
18
|
+
have_library("avformat") and find_header('libavformat/avformat.h') and find_header('libavutil/log.h') then
|
19
|
+
$objs = %w(segmenter.o)
|
20
|
+
create_makefile("segmenter_ext")
|
21
|
+
else
|
22
|
+
STDERR.puts "missing library"
|
23
|
+
exit 1
|
24
|
+
end
|
data/ext/segmenter.c
ADDED
@@ -0,0 +1,465 @@
|
|
1
|
+
//
|
2
|
+
// iosegmenter.c
|
3
|
+
// iosegmenter
|
4
|
+
//
|
5
|
+
// Created by Emil Palm on 4/5/11.
|
6
|
+
// Copyright 2011 none. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
#include <stdlib.h>
|
10
|
+
#include <stdio.h>
|
11
|
+
#include <string.h>
|
12
|
+
#include <stdbool.h>
|
13
|
+
|
14
|
+
#include "ruby.h"
|
15
|
+
#include "libavformat/avformat.h"
|
16
|
+
#include "libavutil/log.h"
|
17
|
+
|
18
|
+
|
19
|
+
char * dirname2(const char *path) {
|
20
|
+
static char dname[PATH_MAX];
|
21
|
+
size_t len;
|
22
|
+
const char *endp;
|
23
|
+
|
24
|
+
/* Empty or NULL string gets treated as "." */
|
25
|
+
if (path == NULL || *path == '\0') {
|
26
|
+
dname[0] = '.';
|
27
|
+
dname[1] = '\0';
|
28
|
+
return (dname);
|
29
|
+
}
|
30
|
+
|
31
|
+
/* Strip any trailing slashes */
|
32
|
+
endp = path + strlen(path) - 1;
|
33
|
+
while (endp > path && *endp == '/')
|
34
|
+
endp--;
|
35
|
+
|
36
|
+
/* Find the start of the dir */
|
37
|
+
while (endp > path && *endp != '/')
|
38
|
+
endp--;
|
39
|
+
|
40
|
+
/* Either the dir is "/" or there are no slashes */
|
41
|
+
if (endp == path) {
|
42
|
+
dname[0] = *endp == '/' ? '/' : '.';
|
43
|
+
dname[1] = '\0';
|
44
|
+
return (dname);
|
45
|
+
} else {
|
46
|
+
/* Move forward past the separating slashes */
|
47
|
+
do {
|
48
|
+
endp--;
|
49
|
+
} while (endp > path && *endp == '/');
|
50
|
+
}
|
51
|
+
|
52
|
+
len = endp - path + 1;
|
53
|
+
if (len >= sizeof(dname)) {
|
54
|
+
errno = ENAMETOOLONG;
|
55
|
+
return (NULL);
|
56
|
+
}
|
57
|
+
memcpy(dname, path, len);
|
58
|
+
dname[len] = '\0';
|
59
|
+
return (dname);
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
typedef struct _segment {
|
64
|
+
int index;
|
65
|
+
long duration;
|
66
|
+
char *filename;
|
67
|
+
} Segment;
|
68
|
+
|
69
|
+
static VALUE rb_mAvSegmenter;
|
70
|
+
static VALUE rb_cAvSegmenter;
|
71
|
+
static VALUE rb_cAvSegment;
|
72
|
+
|
73
|
+
/* Segment */
|
74
|
+
|
75
|
+
static void segment_free(Segment *segment)
|
76
|
+
{
|
77
|
+
if (NULL == segment)
|
78
|
+
return;
|
79
|
+
|
80
|
+
segment->index = 0;
|
81
|
+
segment->duration = 0;
|
82
|
+
segment->filename = NULL;
|
83
|
+
ruby_xfree(segment);
|
84
|
+
}
|
85
|
+
|
86
|
+
struct config_info
|
87
|
+
{
|
88
|
+
const char *input_filename;
|
89
|
+
int segment_length;
|
90
|
+
const char *temp_directory;
|
91
|
+
const char *filename_prefix;
|
92
|
+
const char *encoding_profile;
|
93
|
+
};
|
94
|
+
|
95
|
+
static AVStream *add_output_stream(AVFormatContext *output_format_context, AVStream *input_stream)
|
96
|
+
{
|
97
|
+
AVCodecContext *input_codec_context;
|
98
|
+
AVCodecContext *output_codec_context;
|
99
|
+
AVStream *output_stream;
|
100
|
+
|
101
|
+
output_stream = av_new_stream(output_format_context, 0);
|
102
|
+
if (!output_stream)
|
103
|
+
{
|
104
|
+
fprintf(stderr, "Segmenter error: Could not allocate stream\n");
|
105
|
+
exit(1);
|
106
|
+
}
|
107
|
+
|
108
|
+
input_codec_context = input_stream->codec;
|
109
|
+
output_codec_context = output_stream->codec;
|
110
|
+
|
111
|
+
output_codec_context->codec_id = input_codec_context->codec_id;
|
112
|
+
output_codec_context->codec_type = input_codec_context->codec_type;
|
113
|
+
output_codec_context->codec_tag = input_codec_context->codec_tag;
|
114
|
+
output_codec_context->bit_rate = input_codec_context->bit_rate;
|
115
|
+
output_codec_context->extradata = input_codec_context->extradata;
|
116
|
+
output_codec_context->extradata_size = input_codec_context->extradata_size;
|
117
|
+
|
118
|
+
if(av_q2d(input_codec_context->time_base) * input_codec_context->ticks_per_frame > av_q2d(input_stream->time_base) && av_q2d(input_stream->time_base) < 1.0/1000)
|
119
|
+
{
|
120
|
+
output_codec_context->time_base = input_codec_context->time_base;
|
121
|
+
output_codec_context->time_base.num *= input_codec_context->ticks_per_frame;
|
122
|
+
}
|
123
|
+
else
|
124
|
+
{
|
125
|
+
output_codec_context->time_base = input_stream->time_base;
|
126
|
+
}
|
127
|
+
|
128
|
+
switch (input_codec_context->codec_type)
|
129
|
+
{
|
130
|
+
case CODEC_TYPE_AUDIO:
|
131
|
+
output_codec_context->channel_layout = input_codec_context->channel_layout;
|
132
|
+
output_codec_context->sample_rate = input_codec_context->sample_rate;
|
133
|
+
output_codec_context->channels = input_codec_context->channels;
|
134
|
+
output_codec_context->frame_size = input_codec_context->frame_size;
|
135
|
+
if ((input_codec_context->block_align == 1 && input_codec_context->codec_id == CODEC_ID_MP3) || input_codec_context->codec_id == CODEC_ID_AC3)
|
136
|
+
{
|
137
|
+
output_codec_context->block_align = 0;
|
138
|
+
}
|
139
|
+
else
|
140
|
+
{
|
141
|
+
output_codec_context->block_align = input_codec_context->block_align;
|
142
|
+
}
|
143
|
+
break;
|
144
|
+
case CODEC_TYPE_VIDEO:
|
145
|
+
output_codec_context->pix_fmt = input_codec_context->pix_fmt;
|
146
|
+
output_codec_context->width = input_codec_context->width;
|
147
|
+
output_codec_context->height = input_codec_context->height;
|
148
|
+
output_codec_context->has_b_frames = input_codec_context->has_b_frames;
|
149
|
+
|
150
|
+
if (output_format_context->oformat->flags & AVFMT_GLOBALHEADER)
|
151
|
+
{
|
152
|
+
output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
153
|
+
}
|
154
|
+
break;
|
155
|
+
default:
|
156
|
+
break;
|
157
|
+
}
|
158
|
+
|
159
|
+
return output_stream;
|
160
|
+
}
|
161
|
+
|
162
|
+
void output_transfer_command(const unsigned int first_segment, const unsigned int last_segment, const int end, const char *encoding_profile)
|
163
|
+
{
|
164
|
+
char buffer[1024 * 10];
|
165
|
+
memset(buffer, 0, sizeof(char) * 1024 * 10);
|
166
|
+
|
167
|
+
sprintf(buffer, "%d, %d, %d, %s", first_segment, last_segment, end, encoding_profile);
|
168
|
+
|
169
|
+
fprintf(stderr, "segmenter: %s\n\r", buffer);
|
170
|
+
}
|
171
|
+
|
172
|
+
static VALUE segmenter_segment(VALUE klass, VALUE input_, VALUE output_prefix_, VALUE duration_ ) {
|
173
|
+
|
174
|
+
const char *input;
|
175
|
+
const char *output_prefix;
|
176
|
+
int segment_duration;
|
177
|
+
long max_tsfiles = 0;
|
178
|
+
double prev_segment_time = 0;
|
179
|
+
unsigned int output_index = 1;
|
180
|
+
AVInputFormat *ifmt;
|
181
|
+
AVOutputFormat *ofmt;
|
182
|
+
AVFormatContext *ic = NULL;
|
183
|
+
AVFormatContext *oc;
|
184
|
+
AVStream *video_st;
|
185
|
+
AVStream *audio_st;
|
186
|
+
AVCodec *codec;
|
187
|
+
char *output_filename;
|
188
|
+
char *remove_filename;
|
189
|
+
int video_index;
|
190
|
+
int audio_index;
|
191
|
+
unsigned int first_segment = 1;
|
192
|
+
unsigned int last_segment = 0;
|
193
|
+
int decode_done;
|
194
|
+
int ret;
|
195
|
+
unsigned int i;
|
196
|
+
int remove_file;
|
197
|
+
|
198
|
+
bool soundOnly = false;
|
199
|
+
|
200
|
+
VALUE sArray = rb_ary_new();
|
201
|
+
av_register_all();
|
202
|
+
av_log_set_level(AV_LOG_PANIC);
|
203
|
+
|
204
|
+
input = RSTRING_PTR(input_);
|
205
|
+
output_prefix = RSTRING_PTR(output_prefix_);
|
206
|
+
segment_duration = (FIX2INT(duration_));
|
207
|
+
|
208
|
+
char *folder = dirname2(strdup(input));
|
209
|
+
|
210
|
+
remove_filename = malloc(sizeof(char) * (strlen(output_prefix) + 15));
|
211
|
+
if (!remove_filename) {
|
212
|
+
rb_raise(rb_eNoMemError, "Could not allocate space for remove filenames");
|
213
|
+
}
|
214
|
+
|
215
|
+
output_filename = malloc(sizeof(char) * (strlen(output_prefix) + strlen(folder) + 15));
|
216
|
+
if (!output_filename) {
|
217
|
+
rb_raise(rb_eNoMemError, "Could not allocate space for output filenames");
|
218
|
+
}
|
219
|
+
|
220
|
+
|
221
|
+
ifmt = av_find_input_format("mpegts");
|
222
|
+
if (!ifmt) {
|
223
|
+
rb_raise(rb_eException, "Could not find MPEG-TS demuxer");
|
224
|
+
}
|
225
|
+
|
226
|
+
ret = av_open_input_file(&ic, input, ifmt, 0, NULL);
|
227
|
+
if (ret != 0) {
|
228
|
+
rb_raise(rb_eException, "Could not open input file, make sure it is an mpegts file: %d %s", ret, input);
|
229
|
+
}
|
230
|
+
|
231
|
+
if (av_find_stream_info(ic) < 0) {
|
232
|
+
rb_raise(rb_eException, "Could not read stream information");
|
233
|
+
}
|
234
|
+
|
235
|
+
ofmt = av_guess_format("mpegts", NULL, NULL);
|
236
|
+
if (!ofmt) {
|
237
|
+
rb_raise(rb_eException, "Could not find MPEG-TS muxer");
|
238
|
+
}
|
239
|
+
|
240
|
+
oc = avformat_alloc_context();
|
241
|
+
if (!oc) {
|
242
|
+
rb_raise(rb_eException, "Could not allocated output context");
|
243
|
+
}
|
244
|
+
oc->oformat = ofmt;
|
245
|
+
|
246
|
+
ic->flags |= AVFMT_FLAG_IGNDTS;
|
247
|
+
|
248
|
+
video_index = -1;
|
249
|
+
audio_index = -1;
|
250
|
+
|
251
|
+
for (i = 0; i < ic->nb_streams && (video_index < 0 || audio_index < 0); i++) {
|
252
|
+
switch (ic->streams[i]->codec->codec_type) {
|
253
|
+
case CODEC_TYPE_VIDEO:
|
254
|
+
video_index = i;
|
255
|
+
ic->streams[i]->discard = AVDISCARD_NONE;
|
256
|
+
video_st = add_output_stream(oc, ic->streams[i]);
|
257
|
+
break;
|
258
|
+
case CODEC_TYPE_AUDIO:
|
259
|
+
audio_index = i;
|
260
|
+
ic->streams[i]->discard = AVDISCARD_NONE;
|
261
|
+
audio_st = add_output_stream(oc, ic->streams[i]);
|
262
|
+
break;
|
263
|
+
default:
|
264
|
+
ic->streams[i]->discard = AVDISCARD_ALL;
|
265
|
+
break;
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
if(!soundOnly) {
|
270
|
+
soundOnly = (video_st != NULL);
|
271
|
+
}
|
272
|
+
|
273
|
+
if (av_set_parameters(oc, NULL) < 0) {
|
274
|
+
rb_raise(rb_eException, "Invalid output format parameters");
|
275
|
+
}
|
276
|
+
|
277
|
+
dump_format(oc, 0, output_prefix, 1);
|
278
|
+
|
279
|
+
|
280
|
+
|
281
|
+
if (!soundOnly) {
|
282
|
+
codec = avcodec_find_decoder(video_st->codec->codec_id);
|
283
|
+
if (!codec) {
|
284
|
+
rb_raise(rb_eException, "Could not find video decoder, key frames will not be honored");
|
285
|
+
}
|
286
|
+
|
287
|
+
if (avcodec_open(video_st->codec, codec) < 0) {
|
288
|
+
rb_raise(rb_eException, "Could not open video decoder, key frames will not be honored");
|
289
|
+
}
|
290
|
+
|
291
|
+
|
292
|
+
if (video_st->codec->ticks_per_frame > 1) {
|
293
|
+
// h264 sets the ticks_per_frame and time_base.den but not time_base.num
|
294
|
+
// since we don't use ticks_per_frame, adjust time_base.num accordingly.
|
295
|
+
video_st->codec->time_base.num *= video_st->codec->ticks_per_frame;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
|
299
|
+
snprintf(output_filename, strlen(output_prefix) + strlen(folder) + 15, "%s/%s-%u.ts", folder, output_prefix, output_index++);
|
300
|
+
if (url_fopen(&oc->pb, output_filename, URL_WRONLY) < 0) {
|
301
|
+
rb_raise(rb_eException, "Could not open '%s'", output_filename);
|
302
|
+
}
|
303
|
+
|
304
|
+
if (av_write_header(oc)) {
|
305
|
+
rb_raise(rb_eException, "Could not write mpegts header to first output file");
|
306
|
+
}
|
307
|
+
|
308
|
+
//write_index = !write_index_file(index, tmp_index, segment_duration, output_prefix, http_prefix, first_segment, last_segment, 0, max_tsfiles);
|
309
|
+
int64_t initial_audio_pts = -1;
|
310
|
+
int64_t initial_video_pts = -1;
|
311
|
+
double segment_time;
|
312
|
+
do {
|
313
|
+
|
314
|
+
AVPacket packet;
|
315
|
+
//av_init_packet(&packet);
|
316
|
+
decode_done = av_read_frame(ic, &packet);
|
317
|
+
if (decode_done < 0) {
|
318
|
+
break;
|
319
|
+
}
|
320
|
+
|
321
|
+
if (av_dup_packet(&packet) < 0) {
|
322
|
+
rb_raise(rb_eException, "Could not duplicate packet");
|
323
|
+
av_free_packet(&packet);
|
324
|
+
break;
|
325
|
+
}
|
326
|
+
|
327
|
+
if (!soundOnly) {
|
328
|
+
if (packet.stream_index == video_index) {
|
329
|
+
if (initial_video_pts < 0)
|
330
|
+
initial_video_pts = packet.pts;
|
331
|
+
|
332
|
+
packet.pts -= initial_video_pts;
|
333
|
+
packet.dts = packet.pts;
|
334
|
+
if (packet.flags & AV_PKT_FLAG_KEY) {
|
335
|
+
segment_time = (double)packet.pts * video_st->time_base.num / video_st->time_base.den;
|
336
|
+
} else {
|
337
|
+
segment_time = prev_segment_time; }
|
338
|
+
} else if (packet.stream_index == audio_index) {
|
339
|
+
if (initial_audio_pts < 0) initial_audio_pts = packet.pts;
|
340
|
+
packet.pts -= initial_audio_pts;
|
341
|
+
packet.dts = packet.pts;
|
342
|
+
segment_time = prev_segment_time;
|
343
|
+
} else {
|
344
|
+
segment_time = prev_segment_time;
|
345
|
+
segment_time = prev_segment_time;
|
346
|
+
}
|
347
|
+
} else {
|
348
|
+
|
349
|
+
if (packet.stream_index == audio_index) {
|
350
|
+
|
351
|
+
if (initial_audio_pts < 0)
|
352
|
+
initial_audio_pts = packet.pts;
|
353
|
+
|
354
|
+
if (packet.flags & AV_PKT_FLAG_KEY) {
|
355
|
+
segment_time = (double)packet.pts * audio_st->time_base.num / audio_st->time_base.den;
|
356
|
+
} else {
|
357
|
+
segment_time = prev_segment_time;
|
358
|
+
}
|
359
|
+
|
360
|
+
packet.pts -= initial_audio_pts;
|
361
|
+
packet.dts = packet.pts;
|
362
|
+
|
363
|
+
} else {
|
364
|
+
segment_time = prev_segment_time;
|
365
|
+
segment_time = prev_segment_time;
|
366
|
+
}
|
367
|
+
|
368
|
+
}
|
369
|
+
|
370
|
+
|
371
|
+
|
372
|
+
if (segment_time - prev_segment_time >= segment_duration) {
|
373
|
+
put_flush_packet(oc->pb);
|
374
|
+
url_fclose(oc->pb);
|
375
|
+
|
376
|
+
if (max_tsfiles && (int)(last_segment - first_segment) >= max_tsfiles - 1) {
|
377
|
+
remove_file = 1;
|
378
|
+
first_segment++;
|
379
|
+
}
|
380
|
+
else {
|
381
|
+
remove_file = 0;
|
382
|
+
}
|
383
|
+
|
384
|
+
|
385
|
+
// Create Segment object
|
386
|
+
VALUE seg = rb_obj_alloc(rb_cAvSegment);
|
387
|
+
|
388
|
+
rb_obj_call_init(seg, 0, 0);
|
389
|
+
rb_iv_set(seg, "@index", INT2FIX(++last_segment));
|
390
|
+
rb_iv_set(seg, "@duration",INT2FIX((int)floor((segment_time - prev_segment_time))));
|
391
|
+
rb_iv_set(seg, "@filename", rb_str_new2(output_filename));
|
392
|
+
|
393
|
+
rb_ary_push(sArray, seg);
|
394
|
+
|
395
|
+
if (remove_file) {
|
396
|
+
snprintf(remove_filename, strlen(output_prefix) + strlen(folder) + 15, "%s/%s-%u.ts", folder, output_prefix, first_segment - 1);
|
397
|
+
//snprintf(remove_filename, strlen(output_prefix) + 15, "%s-%u.ts", output_prefix, first_segment - 1);
|
398
|
+
remove(remove_filename);
|
399
|
+
}
|
400
|
+
|
401
|
+
// snprintf(output_filename, strlen(output_prefix) + 15, "%s-%u.ts", output_prefix, output_index++);
|
402
|
+
snprintf(output_filename, strlen(output_prefix) + strlen(folder) + 15, "%s/%s-%u.ts", folder, output_prefix, output_index++);
|
403
|
+
if (url_fopen(&oc->pb, output_filename, URL_WRONLY) < 0) {
|
404
|
+
fprintf(stderr, "Could not open '%s'\n", output_filename);
|
405
|
+
break;
|
406
|
+
}
|
407
|
+
|
408
|
+
prev_segment_time = segment_time;
|
409
|
+
}
|
410
|
+
|
411
|
+
ret = av_interleaved_write_frame(oc, &packet);
|
412
|
+
if (ret < 0) {
|
413
|
+
fprintf(stderr, "Warning: Could not write frame of stream\n");
|
414
|
+
}
|
415
|
+
else if (ret > 0) {
|
416
|
+
fprintf(stderr, "End of stream requested\n");
|
417
|
+
av_free_packet(&packet);
|
418
|
+
break;
|
419
|
+
}
|
420
|
+
|
421
|
+
av_free_packet(&packet);
|
422
|
+
} while (!decode_done);
|
423
|
+
|
424
|
+
av_write_trailer(oc);
|
425
|
+
|
426
|
+
if (!soundOnly)
|
427
|
+
avcodec_close(video_st->codec);
|
428
|
+
|
429
|
+
for(i = 0; i < oc->nb_streams; i++) {
|
430
|
+
if(&oc->streams[i]->codec != NULL)
|
431
|
+
av_freep(&oc->streams[i]->codec);
|
432
|
+
|
433
|
+
if (&oc->streams[i] != NULL)
|
434
|
+
av_freep(&oc->streams[i]);
|
435
|
+
}
|
436
|
+
|
437
|
+
url_fclose(oc->pb);
|
438
|
+
av_free(oc);
|
439
|
+
|
440
|
+
if (max_tsfiles && (int)(last_segment - first_segment) >= max_tsfiles - 1) {
|
441
|
+
remove_file = 1;
|
442
|
+
first_segment++;
|
443
|
+
}
|
444
|
+
else {
|
445
|
+
remove_file = 0;
|
446
|
+
}
|
447
|
+
|
448
|
+
if (remove_file) {
|
449
|
+
snprintf(remove_filename, strlen(output_prefix) + strlen(folder) + 15, "%s/%s-%u.ts", folder, output_prefix, first_segment - 1);
|
450
|
+
remove(remove_filename);
|
451
|
+
}
|
452
|
+
return sArray;
|
453
|
+
}
|
454
|
+
|
455
|
+
void Init_segmenter_ext() {
|
456
|
+
rb_mAvSegmenter = rb_define_module("Segmenter");
|
457
|
+
rb_define_module_function(rb_mAvSegmenter, "segment", segmenter_segment, 3);
|
458
|
+
|
459
|
+
rb_cAvSegment = rb_define_class_under(rb_mAvSegmenter, "Segment", rb_cObject);
|
460
|
+
rb_define_attr(rb_cAvSegment, "duration", 1, 1);
|
461
|
+
rb_define_attr(rb_cAvSegment, "index", 1, 1);
|
462
|
+
rb_define_attr(rb_cAvSegment, "filename", 1, 1);
|
463
|
+
}
|
464
|
+
|
465
|
+
|
data/ext/segmenter.o
ADDED
Binary file
|
data/ext/test.rb
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
$:.unshift "#{File.dirname(__FILE__)}";require "segmenter_ext";a = Segmenter::segment("audio_only.ts","najs",3); a.each do |b| puts "#{b.index} - #{b.duration} - #{b.filename}\n";end
|
2
|
+
#$:.unshift "#{File.dirname(__FILE__)}";require "segmenter_ext";a = Segmenter::segment("movie.ts","najs",3); a.each do |b| puts "#{b.index} - #{b.duration} - #{b.filename}\n";end
|
3
|
+
#$:.unshift "#{File.dirname(__FILE__)}";require "segmenter_ext";a = Segmenter::segment("bajs/bajs.ts","09a7ca73-9ee6-4664-b73a-cc342c556fba",40);b = a[0]; puts "#{b.index} - #{b.duration} - #{b.filename}\n"
|
data/lib/segmenter.rb
ADDED
data/segmenter.gemspec
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{segmenter}
|
8
|
+
s.version = "0.7.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Emil Palm"]
|
12
|
+
s.date = %q{2011-07-08}
|
13
|
+
s.description = %q{}
|
14
|
+
s.email = %q{emil@x86.nu}
|
15
|
+
s.extensions = ["ext/extconf.rb"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
"COPYING",
|
22
|
+
"LICENSE.txt",
|
23
|
+
"Manifest",
|
24
|
+
"NEWS",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"ext/Makefile",
|
29
|
+
"ext/extconf.rb",
|
30
|
+
"ext/segmenter.c",
|
31
|
+
"ext/segmenter.o",
|
32
|
+
"ext/test.rb",
|
33
|
+
"lib/segmenter.rb",
|
34
|
+
"segmenter.gemspec"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/mrevilme/segmenter}
|
37
|
+
s.licenses = ["MIT"]
|
38
|
+
s.require_paths = ["lib"]
|
39
|
+
s.rubygems_version = %q{1.6.2}
|
40
|
+
s.summary = %q{}
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
s.specification_version = 3
|
44
|
+
|
45
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
46
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
47
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
48
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.3"])
|
49
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
52
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
53
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
|
54
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
55
|
+
end
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
58
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
59
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
|
60
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: segmenter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.7.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Emil Palm
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-07-08 00:00:00 +02:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: shoulda
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :development
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 1.0.0
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: jeweler
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.6.3
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rcov
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
type: :development
|
59
|
+
version_requirements: *id004
|
60
|
+
description: ""
|
61
|
+
email: emil@x86.nu
|
62
|
+
executables: []
|
63
|
+
|
64
|
+
extensions:
|
65
|
+
- ext/extconf.rb
|
66
|
+
extra_rdoc_files:
|
67
|
+
- LICENSE.txt
|
68
|
+
- README.rdoc
|
69
|
+
files:
|
70
|
+
- COPYING
|
71
|
+
- LICENSE.txt
|
72
|
+
- Manifest
|
73
|
+
- NEWS
|
74
|
+
- README.rdoc
|
75
|
+
- Rakefile
|
76
|
+
- VERSION
|
77
|
+
- ext/Makefile
|
78
|
+
- ext/extconf.rb
|
79
|
+
- ext/segmenter.c
|
80
|
+
- ext/segmenter.o
|
81
|
+
- ext/test.rb
|
82
|
+
- lib/segmenter.rb
|
83
|
+
- segmenter.gemspec
|
84
|
+
has_rdoc: true
|
85
|
+
homepage: http://github.com/mrevilme/segmenter
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: "0"
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: "0"
|
105
|
+
requirements: []
|
106
|
+
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 1.6.2
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: ""
|
112
|
+
test_files: []
|
113
|
+
|