Skip to content
Browse files

starting rewrite with native library

  • Loading branch information...
1 parent 19adfdb commit 1574f4e8b9a48ea78a7c90f19d54c8a0f8529e3e @benvanik committed Nov 18, 2011
Showing with 416 additions and 389 deletions.
  1. +3 −1 .gitignore
  2. +3 −0 .npmignore
  3. +16 −9 examples/mediainfo.js
  4. +70 −11 examples/transcode.js
  5. +24 −21 lib/transcode.js
  6. +13 −0 lib/transcode/binding.js
  7. +0 −121 lib/transcode/ffmpeg.js
  8. +0 −165 lib/transcode/mediainfo.js
  9. +18 −2 lib/transcode/profiles.js
  10. +0 −57 lib/transcode/transcoder.js
  11. +8 −2 package.json
  12. +30 −0 src/binding.cpp
  13. +126 −0 src/task.cpp
  14. +41 −0 src/task.h
  15. +25 −0 src/utils.h
  16. +39 −0 wscript
View
4 .gitignore
@@ -1,2 +1,4 @@
node_modules
-
+build
+binding.node
+.lock-wscript
View
3 .npmignore
@@ -2,3 +2,6 @@ node_modules
.gitignore
.git/
.git*
+build
+binding.node
+.lock-wscript
View
25 examples/mediainfo.js
@@ -1,18 +1,25 @@
#!/usr/bin/env node
+var fs = require('fs');
+var path = require('path');
var transcode = require('transcode');
var util = require('util');
-var paths = process.argv.slice(2);
-if (!paths.length) {
- util.puts('no input files');
+var opts = require('tav').set({
+});
+
+if (opts.args.length < 1) {
+ console.log('no input file specified');
+ return;
+}
+
+var inputFile = path.normalize(opts.args[0]);
+if (!path.existsSync(inputFile)) {
+ console.log('input file not found');
return;
}
-transcode.queryInfo(paths, function(err, infos) {
- for (var n = 0; n < infos.length; n++) {
- var info = infos[n];
- util.puts('Info for ' + paths[n] + ':');
- util.puts(util.inspect(info, false, 3));
- }
+transcode.queryInfo(inputFile, function(err, info) {
+ util.puts('Info for ' + inputFile + ':');
+ util.puts(util.inspect(info, false, 3));
});
View
81 examples/transcode.js
@@ -1,22 +1,81 @@
#!/usr/bin/env node
+var fs = require('fs');
+var path = require('path');
var transcode = require('transcode');
var util = require('util');
-var paths = process.argv.slice(2);
-if (!paths.length) {
- util.puts('no input files');
+var opts = require('tav').set({
+ profile: {
+ note: 'Encoding profile',
+ value: 'APPLE_TV_2'
+ }
+});
+
+if (!opts.args.length) {
+ console.log('All profiles:');
+ for (var key in transcode.profiles) {
+ var profile = transcode.profiles[key];
+ console.log(' ' + key + ': ' + profile.name);
+ }
+ return;
+}
+
+if (opts.args.length < 1) {
+ console.log('no input file specified');
return;
}
-if (paths.length < 2) {
- util.puts('no output file');
+
+var inputFile = path.normalize(opts.args[0]);
+if (!path.existsSync(inputFile)) {
+ console.log('input file not found');
return;
}
-var outputPath = paths.pop();
-var transcoder = transcode.createTranscoder(paths);
-transcoder.setProfile(transcode.profiles.APPLE_TV);
-transcoder.writeToFile(outputPath, function(err) {
- util.puts('complete!');
- process.exit();
+if (opts.args.length < 2) {
+ // No output given, so just query info
+ transcode.queryInfo(inputFile, function(err, info) {
+ util.puts('Info for ' + inputFile + ':');
+ util.puts(util.inspect(info, false, 3));
+ });
+ return;
+}
+
+var profile = transcode.profiles[opts['profile']];
+if (!profile) {
+ console.log('unknown profile: ' + profile);
+ return;
+}
+
+var outputFile = path.normalize(opts.args[1]);
+var outputPath = path.dirname(outputFile);
+if (!path.existsSync(outputPath)) {
+ fs.mkdirSync(outputPath);
+}
+
+console.log('transcoding ' + inputFile + ' -> ' + outputFile);
+
+var task = transcode.createTask(inputFile, outputFile, {
+ profile: profile
+});
+task.on('begin', function(sourceInfo, targetInfo) {
+ // transcoding beginning
+ console.log('transcoding beginning...');
+ console.log('source:');
+ console.log(util.inspect(sourceInfo));
+ console.log('target:');
+ console.log(util.inspect(targetInfo));
+});
+task.on('progress', function(timestamp, duration) {
+ // new progress made, currrently at timestamp out of duration
+ console.log('progress ' + progress.timestamp + ' / ' + progress.duration);
+});
+task.on('error', function(err) {
+ // error occurred
+ console.log('error: ' + err);
+});
+task.on('end', function() {
+ // transcoding has completed
+ console.log('finished');
});
+task.start();
View
45 lib/transcode.js
@@ -1,29 +1,32 @@
-var ffmpeg = require('./transcode/ffmpeg');
-var profiles = require('./transcode/profiles');
+var util = require('util');
-var ffmpegInfo = ffmpeg.detect();
+var binding = require('./transcode/binding');
-exports.profiles = profiles;
+exports.profiles = require('./transcode/profiles');
-exports.verifyConfiguration = function(callback) {
- var err = null;
- if (!ffmpegInfo) {
- err = new Error('FFMPEG not found');
- }
- if (!err) {
- // TODO: chain into ffmpeg to detect features/etc
- callback(null);
- } else {
- callback(err);
- }
+exports.queryInfo = function(source, callback) {
+ binding.queryInfo(source, callback);
};
-exports.Transcoder = require('./transcode/transcoder').Transcoder;
-exports.createTranscoder = function(inputs) {
- return new exports.Transcoder(ffmpegInfo, inputs);
+exports.createTask = function(source, target, options) {
+ return new binding.Task(source, target, options);
};
-var queryInfo = require('./transcode/mediainfo').queryInfo;
-exports.queryInfo = function(inputs, callback) {
- return queryInfo(ffmpegInfo, inputs, callback);
+exports.transcode = function(source, target, profile, callback) {
+ var sourceInfoStash = null;
+ var targetInfoStash = null;
+ var task = exports.createTask(source, target, {
+ profile: profile
+ });
+ task.on('begin', function(sourceInfo, targetInfo) {
+ sourceInfoStash = sourceInfo;
+ targetInfoStash = targetInfo;
+ });
+ task.on('error', function(err) {
+ callback(err, sourceInfo, targetInfo);
+ });
+ task.on('end', function() {
+ callback(null, sourceInfo, targetInfo);
+ });
+ task.start();
};
View
13 lib/transcode/binding.js
@@ -0,0 +1,13 @@
+module.exports = require('../../build/Release/node_transcode.node');
+
+// WEAK: required in v0.6
+function inheritEventEmitter(type) {
+ function extend(target, source) {
+ for (var k in source.prototype) {
+ target.prototype[k] = source.prototype[k];
+ }
+ }
+ var events = require('events');
+ extend(type, events.EventEmitter);
+}
+inheritEventEmitter(module.exports.Task);
View
121 lib/transcode/ffmpeg.js
@@ -1,121 +0,0 @@
-var child_process = require('child_process');
-var path = require('path');
-var util = require('util');
-
-// Attempts to find ffmpeg
-exports.detect = function() {
- var info = {
- path: process.env.FFMPEG_PATH || 'ffmpeg'
- };
- return info;
-};
-
-var Ffmpeg = function(info) {
- this.info_ = info;
-
- this.priority_ = 0;
- this.inputs_ = [];
- this.output_ = null;
- this.options_ = {
- };
-};
-exports.Ffmpeg = Ffmpeg;
-
-Ffmpeg.prototype.setPriority = function(priority) {
- this.priority_ = priority;
- return this;
-};
-
-Ffmpeg.prototype.addInput = function(streamOrPath) {
- this.inputs_.push(streamOrPath);
- return this;
-};
-
-Ffmpeg.prototype.addInputs = function(inputs) {
- if (util.isArray(inputs)) {
- this.inputs_ = this.inputs_.concat(inputs);
- } else {
- this.inputs_.push(inputs);
- }
- return this;
-};
-
-Ffmpeg.prototype.setOutput = function(streamOrPath) {
- this.output_ = streamOrPath;
- return this;
-};
-
-Ffmpeg.prototype.setOptions = function(options) {
- this.options_ = options;
- return this;
-};
-
-Ffmpeg.prototype.exec = function() {
- // Build input arguments
- // If only one is a stream, can pipe to stdin, otherwise, need to write to
- // files first
- var inputStream = null;
- var inputPaths = [];
- for (var n = 0; n < this.inputs_.length; n++) {
- var input = this.inputs_[n];
- if (typeof input == 'string') {
- // Path
- inputPaths.push(input);
- } else {
- // Stream
- if (!inputStream) {
- // First stream - can use as stdin
- inputStream = input;
- } else {
- // 2nd+ stream - scribble head to file
- // TODO: scribble to file
- throw new Error('unsupported: multiple input streams');
- }
- }
- }
-
- var args = [];
-
- // Basics
- args.push('-y'); // always overwrite output files
-
- // Input args
- if (inputStream) {
- args.push('-i', '-');
- }
- for (var n = 0; n < inputPaths.length; n++) {
- var inputPath = path.normalize(inputPaths[n]);
- args.push('-i', inputPath);
- }
-
- // Real options
- // TODO: options
- args.push('-vcodec', 'copy');
- args.push('-acodec', 'copy');
-
- // Output
- if (this.output_) {
- if (typeof this.output_ == 'string') {
- args.push(this.output_);
- } else {
- args.push('pipe:1');
- }
- }
-
- // Spawn the process and wire up input (if required)
- util.puts('calling ffmpeg:');
- util.puts(' ' + args.join(' '));
- var proc = child_process.spawn(this.info_.path, args);
- if (inputStream) {
- inputStream.resume();
- inputStream.pipe(proc.stdin);
- }
-
- // renice to a lower priority
- if (this.priority_ !== null) {
- child_process.exec('renice -p ' + proc.pid + ' -n ' +
- (this.priority_ ? '+' + this.priority_ : this.priority_));
- }
-
- return proc;
-};
View
165 lib/transcode/mediainfo.js
@@ -1,165 +0,0 @@
-var util = require('util');
-
-var Ffmpeg = require('./ffmpeg').Ffmpeg;
-
-function getValue(line, regex) {
- var matches = regex.exec(line);
- if (matches && matches.length) {
- return matches[1];
- }
- return undefined;
-}
-
-function parseDuration(str) {
- // HH:MM:SS.SS
- var parts = str.split(':');
- var value = 0;
- value += parseInt(parts[0]) * 3600;
- value += parseInt(parts[1]) * 60;
- value += parseInt(parts[2]);
- return value;
-}
-
-function parseBitrate(str) {
- // N kb/s
- var parts = str.split(' ');
- var value = parseInt(parts[0]);
- switch (parts[1]) {
- case 'b/s':
- value *= 1;
- break;
- case 'kb/s':
- value *= 1000;
- break;
- case 'mb/s':
- value *= 1000000;
- break;
- default:
- throw new Error('unsupported bitrate unit ' + parts[1]);
- }
- return value;
-}
-
-function parseResolution(str) {
- // WxH
- var parts = str.split('x');
- return {
- width: parseInt(parts[0]),
- height: parseInt(parts[1])
- };
-}
-
-function parseChannels(str) {
- switch (str) {
- case 'stereo':
- return 2;
- case 'mono':
- return 1;
- default:
- return 0;
- }
-}
-
-// Input #N, mov,mp4, from 'some input':
-// Metadata:
-// [stuff]
-// Duration: 00:02:06.89, start: 0.000000, bitrate: 818 kb/s
-// Stream #0.0(und): Video: h264 (Main), yuv420p, 640x360, 686 kb/s, 29.97 tbr, 1k tbn, 59.94 tbc
-// Stream #0.1(eng): Audio: aac, 44100 Hz, stereo, s16, 131 kb/s
-// Stream #1.2(und): Subtitle: text / 0x74786574, 0 kb/s
-
-function parseResults(lines) {
- var results = [];
-
- var input = null;
- for (var n = 0; n < lines.length; n++) {
- var line = lines[n];
- if (line.indexOf('Input #') == 0) {
- input = {
- container: getValue(line, /Input #[0-9]+, ([a-zA-Z0-9,]+),/),
- duration: 0,
- start: 0,
- bitrate: 0,
- streams: []
- };
- results.push(input);
- }
-
- if (line.indexOf(' Duration: ') == 0) {
- input.duration = parseDuration(
- getValue(line, /Duration: ([0-9:\.]+),/));
- input.start = parseFloat(
- getValue(line, /start: ([0-9]+.[0-9]+),/));
- input.bitrate = parseBitrate(
- getValue(line, /bitrate: ([0-9]+ kb\/s)/));
- }
-
- if (line.indexOf(' Stream #') == 0) {
- var stream = {
- type: getValue(line, /: (Audio|Video|Subtitle): /).toLowerCase(),
- language: getValue(line, /Stream #[0-9]\.[0-9]+\(([a-z]+)\): /)
- };
- if (stream.language == 'und') {
- stream.language = undefined;
- }
- switch (stream.type) {
- case 'video':
- stream.codec =
- getValue(line, /Video: ([a-zA-Z0-9]+)[ ,]/);
- stream.profile =
- getValue(line, /Video: [a-zA-Z0-9]+ \(([a-zA-Z0-9 ]+)\), /);
- stream.resolution = parseResolution(
- getValue(line, /([0-9]+x[0-9]+)/));
- stream.bitrate = parseBitrate(
- getValue(line, /([0-9]+ kb\/s)/));
- stream.fps = parseFloat(
- getValue(line, /([0-9]+.[0-9]+) tbr/));
- break;
- case 'audio':
- stream.codec =
- getValue(line, /Audio: ([a-zA-Z0-9]+)[ ,]/);
- stream.sampleRate = parseInt(
- getValue(line, /([0-9]+) Hz, /));
- stream.channels = parseChannels(
- getValue(line, /Hz, ([a-zA-Z0-9]+), /));
- stream.bitrate = parseBitrate(
- getValue(line, /([0-9]+ kb\/s)/));
- break;
- case 'subtitle':
- break;
- }
- input.streams.push(stream);
- }
- }
-
- return results;
-};
-
-exports.queryInfo = function(ffmpegInfo, inputs, callback) {
- var wasSingleInput = false;
- if (!util.isArray(inputs)) {
- wasSingleInput = true;
- inputs = [inputs];
- }
-
- var ffmpeg = new Ffmpeg(ffmpegInfo);
- ffmpeg.addInputs(inputs);
- var proc = ffmpeg.exec();
-
- // All output comes on stderr
- var allOutput = '';
- proc.stderr.on('data', function(data) {
- allOutput += data;
- });
-
- proc.on('exit', function (code) {
- var lines = allOutput.split('\n');
-
- var results = parseResults(lines);
-
- if (wasSingleInput) {
- results = results[0];
- }
- callback(null, results);
- });
-};
View
20 lib/transcode/profiles.js
@@ -1,3 +1,19 @@
-exports.APPLE_TV = {
+function declareProfile(key, name, options) {
+ var profile = {
+ name: name,
+ options: options
+ };
+ exports[key] = profile;
+}
-};
+declareProfile('APPLE_TV_2', 'Apple TV 2', {
+
+});
+
+declareProfile('PLAYSTATION_3', 'Playstation 3', {
+
+});
+
+declareProfile('XBOX_360', 'Xbox 360', {
+
+});
View
57 lib/transcode/transcoder.js
@@ -1,57 +0,0 @@
-var events = require('events');
-var fs = require('fs');
-var util = require('util');
-
-var queryInfo = require('./mediainfo').queryInfo;
-var Ffmpeg = require('./ffmpeg').Ffmpeg;
-
-var Transcoder = function(ffmpegInfo, inputs) {
- this.ffmpegInfo_ = ffmpegInfo;
-
- this.ffmpeg_ = new Ffmpeg(ffmpegInfo);
- if (inputs) {
- this.ffmpeg_.addInputs(inputs);
- }
-
- this.profile_ = null;
-};
-util.inherits(Transcoder, events.EventEmitter);
-exports.Transcoder = Transcoder;
-
-Transcoder.prototype.setProfile = function(profile) {
- this.profile_ = profile;
-};
-
-Transcoder.prototype.attachInputStream = function(stream) {
- this.ffmpeg_.addInput(stream);
-};
-
-Transcoder.prototype.attachInputFile = function(path) {
- this.ffmpeg_.addInput(path);
-};
-
-Transcoder.prototype.writeToStream = function(stream, callback) {
- this.ffmpeg_.setOutput(stream);
- this.write_(callback);
-};
-
-Transcoder.prototype.writeToFile = function(path, callback) {
- this.ffmpeg_.setOutput(path);
- this.write_(callback);
-};
-
-Transcoder.prototype.write_ = function(callback) {
- // TODO: set options from profile
-
- var proc = this.ffmpeg_.exec();
-
- // proc.stderr.on('data', function(data) {
- // util.puts('stderr: ' + data);
- // });
-
- proc.on('exit', function(code) {
- if (callback) {
- callback(null);
- }
- });
-};
View
10 package.json
@@ -12,16 +12,22 @@
"audio",
"video",
"media",
- "transcode"
+ "transcode",
+ "streaming"
],
"directories": {
"lib": "./lib/transcode"
},
"main": "./lib/transcode",
+ "bin": {
+ "transcode" : "./examples/transcode.js"
+ },
"dependencies": {
- "async": "0.1.15"
+ "tav": "0.1.0"
},
"scripts": {
+ "preinstall": "node-waf configure && node-waf build",
+ "preuninstall": "rm -rf build/*"
},
"engines": {
"node": ">= 0.6.x"
View
30 src/binding.cpp
@@ -0,0 +1,30 @@
+#include <node.h>
+#include <v8.h>
+#include "utils.h"
+#include "task.h"
+
+using namespace transcode;
+using namespace v8;
+
+namespace transcode {
+
+Handle<Value> queryInfo(const Arguments& args) {
+ HandleScope scope;
+
+ //
+
+ return scope.Close(Undefined());
+}
+
+}; // transcode
+
+extern "C" void node_transcode_init(Handle<Object> target) {
+ HandleScope scope;
+
+ transcode::Task::Init(target);
+
+ target->Set(String::NewSymbol("queryInfo"),
+ FunctionTemplate::New(transcode::queryInfo)->GetFunction());
+}
+
+NODE_MODULE(node_transcode, node_transcode_init);
View
126 src/task.cpp
@@ -0,0 +1,126 @@
+#include "task.h"
+
+extern "C" {
+#include "libavformat/avformat.h"
+}
+
+using namespace transcode;
+using namespace v8;
+
+static Persistent<String> _task_timestamp_symbol;
+static Persistent<String> _task_duration_symbol;
+static Persistent<String> _task_timeElapsed_symbol;
+static Persistent<String> _task_timeEstimated_symbol;
+static Persistent<String> _task_timeRemaining_symbol;
+
+static Persistent<FunctionTemplate> _task_ctor;
+
+void Task::Init(Handle<Object> target) {
+ HandleScope scope;
+
+ _task_timestamp_symbol = NODE_PSYMBOL("timestamp");
+ _task_duration_symbol = NODE_PSYMBOL("duration");
+ _task_timeElapsed_symbol = NODE_PSYMBOL("timeElapsed");
+ _task_timeEstimated_symbol = NODE_PSYMBOL("timeEstimated");
+ _task_timeRemaining_symbol = NODE_PSYMBOL("timeRemaining");
+
+ Local<FunctionTemplate> ctor = FunctionTemplate::New(New);
+ ctor->InstanceTemplate()->SetInternalFieldCount(1);
+ ctor->SetClassName(String::NewSymbol("Task"));
+
+ NODE_SET_PROTOTYPE_METHOD(ctor, "start", Start);
+ NODE_SET_PROTOTYPE_METHOD(ctor, "stop", Stop);
+
+ NODE_SET_PROTOTYPE_ACCESSOR(ctor, "source", GetSource);
+ NODE_SET_PROTOTYPE_ACCESSOR(ctor, "target", GetTarget);
+ NODE_SET_PROTOTYPE_ACCESSOR(ctor, "options", GetOptions);
+ NODE_SET_PROTOTYPE_ACCESSOR(ctor, "progress", GetProgress);
+
+ _task_ctor = Persistent<FunctionTemplate>::New(ctor);
+ target->Set(String::NewSymbol("Task"), _task_ctor->GetFunction());
+}
+
+Handle<Value> Task::New(const Arguments& args)
+{
+ HandleScope scope;
+ Local<Object> source = args[0]->ToObject();
+ Local<Object> target = args[1]->ToObject();
+ Local<Object> options = args[2]->ToObject();
+ Task* task = new Task(source, target, options);
+ task->Wrap(args.This());
+ return scope.Close(args.This());
+}
+
+Task::Task(
+ Handle<Object> source, Handle<Object> target, Handle<Object> options) {
+ HandleScope scope;
+
+ this->source = Persistent<Object>::New(source);
+ this->target = Persistent<Object>::New(target);
+ this->options = Persistent<Object>::New(options);
+}
+
+Task::~Task() {
+}
+
+Handle<Value> Task::GetSource(Local<String> property,
+ const AccessorInfo& info) {
+ Task* task = ObjectWrap::Unwrap<Task>(info.This());
+ HandleScope scope;
+ return scope.Close(task->source);
+}
+
+Handle<Value> Task::GetTarget(Local<String> property,
+ const AccessorInfo& info) {
+ Task* task = ObjectWrap::Unwrap<Task>(info.This());
+ HandleScope scope;
+ return scope.Close(task->target);
+}
+
+Handle<Value> Task::GetOptions(Local<String> property,
+ const AccessorInfo& info) {
+ Task* task = ObjectWrap::Unwrap<Task>(info.This());
+ HandleScope scope;
+ return scope.Close(task->options);
+}
+
+Handle<Value> Task::GetProgress(Local<String> property,
+ const AccessorInfo& info) {
+ Task* task = ObjectWrap::Unwrap<Task>(info.This());
+ HandleScope scope;
+
+ Local<Object> result = Object::New();
+
+ result->Set(_task_timestamp_symbol, Number::New(1));
+ result->Set(_task_duration_symbol, Number::New(2));
+ result->Set(_task_timeElapsed_symbol, Number::New(3));
+ result->Set(_task_timeEstimated_symbol, Number::New(4));
+ result->Set(_task_timeRemaining_symbol, Number::New(5));
+
+ return scope.Close(result);
+}
+
+Handle<Value> Task::Start(const Arguments& args) {
+ Task* task = ObjectWrap::Unwrap<Task>(args.This());
+ HandleScope scope;
+
+ printf("start\n");
+
+ // TODO: emit events
+ Handle<Value> argv[] = {
+ String::New("end"),
+ };
+ node::MakeCallback(args.This(), "emit", countof(argv), argv);
+
+ return scope.Close(Undefined());
+}
+
+Handle<Value> Task::Stop(const Arguments& args) {
+ Task* task = ObjectWrap::Unwrap<Task>(args.This());
+ HandleScope scope;
+
+ printf("stop\n");
+
+ return scope.Close(Undefined());
+}
+
View
41 src/task.h
@@ -0,0 +1,41 @@
+#include <node.h>
+#include <v8.h>
+#include "utils.h"
+
+#ifndef NODE_TRANSCODE_TASK
+#define NODE_TRANSCODE_TASK
+
+using namespace v8;
+
+namespace transcode {
+
+class Task : public node::ObjectWrap {
+public:
+ static void Init(Handle<Object> target);
+ static Handle<Value> New(const Arguments& args);
+
+public:
+ Task(Handle<Object> source, Handle<Object> target, Handle<Object> options);
+ ~Task();
+
+ static Handle<Value> GetSource(Local<String> property,
+ const AccessorInfo& info);
+ static Handle<Value> GetTarget(Local<String> property,
+ const AccessorInfo& info);
+ static Handle<Value> GetOptions(Local<String> property,
+ const AccessorInfo& info);
+ static Handle<Value> GetProgress(Local<String> property,
+ const AccessorInfo& info);
+
+ static Handle<Value> Start(const Arguments& args);
+ static Handle<Value> Stop(const Arguments& args);
+
+private:
+ Persistent<Object> source;
+ Persistent<Object> target;
+ Persistent<Object> options;
+};
+
+}; // transcode
+
+#endif // NODE_TRANSCODE_TASK
View
25 src/utils.h
@@ -0,0 +1,25 @@
+#include <node.h>
+#include <v8.h>
+
+#ifndef NODE_TRANSCODE_UTILS
+#define NODE_TRANSCODE_UTILS
+
+namespace transcode {
+
+#ifndef countof
+#ifdef _countof
+#define countof _countof
+#else
+#define countof(a) (sizeof(a) / sizeof(*(a)))
+#endif
+#endif
+
+#define NODE_SET_PROTOTYPE_ACCESSOR(templ, name, callback) \
+do { \
+ templ->PrototypeTemplate()->SetAccessor(v8::String::NewSymbol(name), \
+ callback); \
+} while (0)
+
+}; // transcode
+
+#endif // NODE_TRANSCODE_UTILS
View
39 wscript
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+import sys
+import os
+
+import json
+package = json.load(open('package.json'))
+NAME = package['name']
+APPNAME = 'node-' + NAME
+VERSION = package['version']
+
+srcdir = '.'
+blddir = 'build'
+
+def set_options(opt):
+ opt.tool_options('compiler_cxx')
+ opt.tool_options('node_addon')
+
+def configure(conf):
+ conf.check_tool('compiler_cxx')
+ conf.check_tool('node_addon')
+
+ conf.env.append_unique('CXXFLAGS', ['-D__STDC_CONSTANT_MACROS'])
+
+ conf.check(header_name='libavformat/avformat.h', mandatory=True)
+ conf.check(header_name='libavcodec/avcodec.h', mandatory=True)
+ conf.check(lib='avutil', uselib_store='LIBAVUTIL')
+ conf.check(lib='avformat', uselib_store='LIBAVFORMAT')
+ conf.check(lib='avcodec', uselib_store='LIBAVCODEC')
+
+def build(bld):
+ t = bld.new_task_gen('cxx', 'shlib', 'node_addon')
+ t.target = 'node_transcode'
+ t.cxxflags = ['-D__STDC_CONSTANT_MACROS']
+ t.uselib = ['LIBAVUTIL', 'LIBAVFORMAT', 'LIBAVCODEC']
+ t.source = [
+ 'src/binding.cpp',
+ 'src/task.cpp'
+ ]

0 comments on commit 1574f4e

Please sign in to comment.
Something went wrong with that request. Please try again.