Skip to content
Browse files

encoder: make the it work

The last piece of the puzzle was the corrupted header being output in the ogg
file. It seems that libvorbis modifies these packets' backing buffers after some
PCM data gets input. The new `ogg.ogg_packet` Buffer subclass takes care of this
for us with the `.replace()` function.
  • Loading branch information...
1 parent c466e9a commit 8ce8c88493db805f7228d699995e0280920829c4 @TooTallNate committed
Showing with 48 additions and 8 deletions.
  1. +48 −8 lib/encoder.js
View
56 lib/encoder.js
@@ -7,6 +7,7 @@ var debug = require('debug')('vorbis:encoder');
var binding = require('./binding');
var inherits = require('util').inherits;
var Transform = require('stream').Transform;
+var ogg_packet = require('ogg').ogg_packet;
// node v0.8.x compat
if (!Transform) Transform = require('readable-stream/transform');
@@ -143,18 +144,53 @@ Encoder.prototype._writeHeader = function (output, fn) {
debug('vorbis_block_init() return = %d', r);
if (0 !== r) return fn(new Error(r));
- // create first 3 packets
+ // create the first 3 header packets
// TODO: async
- var op_header = new Buffer(binding.sizeof_ogg_packet);
- var op_comments = new Buffer(binding.sizeof_ogg_packet);
- var op_code = new Buffer(binding.sizeof_ogg_packet);
+ var op_header = new ogg_packet();
+ var op_comments = new ogg_packet();
+ var op_code = new ogg_packet();
r = binding.vorbis_analysis_headerout(this.vd, this.vc, op_header, op_comments, op_code);
debug('vorbis_analysis_headerout() return = %d', r);
if (0 !== r) return fn(new Error(r));
- output(op_header); // automatically gets placed in its own page
+ // libvorbis will modify the backing buffers for these `ogg_packet` instances
+ // as soon as we write some PCM data to the encoder, therefore we must copy the
+ // "packet" contents over the node.js Buffer instances so that we have full
+ // control over they bytes until whenever the GC cleans them up.
+ op_header.replace();
+ op_comments.replace();
+ op_code.replace();
+
+ /*
+ var p = new ogg_packet(op_header);
+ //console.error(p);
+ var b = new Buffer(p.bytes);
+ p.packet.reinterpret(p.bytes).copy(b);
+ p.packet = b;
+ //console.error(p);
+ //console.error(0, p.packet.reinterpret(p.bytes).toString());
+
+ p = new ogg_packet(op_comments);
+ //console.error(p);
+ b = new Buffer(p.bytes);
+ p.packet.reinterpret(p.bytes).copy(b);
+ p.packet = b;
+ //console.error(p);
+ //console.error(0, p.packet.reinterpret(p.bytes).toString());
+
+ p = new ogg_packet(op_code);
+ //console.error(p);
+ b = new Buffer(p.bytes);
+ p.packet.reinterpret(p.bytes).copy(b);
+ p.packet = b;
+ //console.error(p);
+ //console.error(0, p.packet.reinterpret(p.bytes).toString());
+ */
+
+ output(op_header); // automatically gets placed in its own `ogg_page`
output(op_comments);
- // specify that a page flush() call is required after this packet
+
+ // specify that a page flush() call is required after this 3rd packet
op_code.flush = true;
output(op_code);
@@ -211,14 +247,18 @@ Encoder.prototype._blockout = function (output, fn) {
var vb = this.vb;
var self = this;
binding.vorbis_analysis_blockout(vd, vb, function (rtn) {
+ debug('vorbis_analysis_blockout() return = %d', rtn);
if (1 === rtn) {
// got a "block"
// analysis, assume we want to use bitrate management
// TODO: async?
// TODO: check return values
- binding.vorbis_analysis(vb, null);
- binding.vorbis_bitrate_addblock(vb);
+ var r;
+ r = binding.vorbis_analysis(vb, null);
+ //console.error('vorbis_analysis() = %d', r);
+ r = binding.vorbis_bitrate_addblock(vb);
+ //console.error('vorbis_bitrate_addblock() = %d', r);
self._flushpacket(output, afterFlush);
} else if (0 === rtn) {

0 comments on commit 8ce8c88

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