segmenter 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,12 @@
1
+ COPYING
2
+ ext/extconf.rb
3
+ ext/Makefile
4
+ ext/segmenter.bundle
5
+ ext/segmenter.c
6
+ ext/segmenter.o
7
+ ext/test.rb
8
+ NEWS
9
+ Rakefile
10
+ README.rdoc
11
+ lib/segmenter.rb
12
+
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
@@ -0,0 +1,4 @@
1
+ $:.unshift(File.dirname(__FILE__))
2
+
3
+ require File.dirname(__FILE__) + '/../ext/segmenter_ext'
4
+
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
+