]> id.pley.net Git - movie_parser.git/blobdiff - SampleData.js
Upload Dropbox.com versions of everything
[movie_parser.git] / SampleData.js
diff --git a/SampleData.js b/SampleData.js
new file mode 100755 (executable)
index 0000000..efda7ef
--- /dev/null
@@ -0,0 +1,172 @@
+var SampleData = function() {
+    "use strict";
+    this.maximumSampleSize = 0;
+    this.maxScenes = 0;
+    this.syncSampleSizes = [];
+    this.decisions = [];
+    this.thresholds = [];
+    this.syncSampleTimes = [];
+    this.sceneSamples = [];
+};
+
+SampleData.prototype.decision = function(data, k, n, count) {
+    "use strict";
+    var n_m_1 = (n - 1 >= 0 ? n - 1 : 0);
+    var n_m_2 = (n - 2 >= 0 ? n - 2 : 0);
+    var n_p_1 = (n + 1 < count ? n + 1 : count - 1);
+
+    if (
+        ((
+            (data[n_m_1] - data[n_m_2] > 0) && 
+            (data[n] - data[n_m_1] > 0) && 
+            (data[n_p_1] - data[n] > 0) && 
+            (data[n_p_1] - data[n] >= data[n] - data[n - 1])
+        ) 
+        || 
+        (
+            (data[n_m_1] - data[n_m_2] < 0) &&
+            (data[n] - data[n_m_1] < 0) && 
+            (data[n_p_1] - data[n] < 0) && 
+            (data[n_p_1] - data[n] <= data[n] - data[n - 1])
+        )))
+        return 0;
+
+    var directionSet = new Array(4);
+    directionSet[0] = Math.abs(data[n] - data[n_m_1]);
+    directionSet[1] = Math.abs(data[n] - data[n_m_2]);
+    directionSet[2] = Math.abs(data[n_p_1] - data[n_m_1]);
+    directionSet[3] = Math.abs(data[n_p_1] - data[n_m_2]);
+
+    return directionSet.sort()[0];
+};
+
+SampleData.prototype.threshold = function(data, distances, k, n, count) {
+    "use strict";
+    var mean = 0;
+    var S = 0;
+    var min, max, min_n1, max_n1;
+    var directionSet = new Array(4);
+
+    min = min_n1 = data[k];
+    max = max_n1 = data[k];
+
+    var n_m_1 = (n >= 1 ? n - 1 : 0);
+    var n_m_2 = (n >= 2 ? n - 2 : 0);
+    var n_p_1 = (n + 1 < count ? n + 1 : count - 1);
+    directionSet[0] = data[n] - data[n_m_1];
+    directionSet[1] = data[n] - data[n_m_2];
+    directionSet[2] = data[n_p_1] - data[n_m_1];
+    directionSet[3] = data[n_p_1] - data[n_m_2];
+
+    // Knuth Variance Algorithm with Min/Max
+    // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Algorithm_III
+    for (var i = k, count = 1; i <= n; ++i, ++count) {
+        var x = data[i];
+        var delta = x - mean;
+        mean += delta / count;
+        S += delta * (x - mean);
+
+        // Caculate min/max and min/max excluding the last entry.
+        if (x > max) max = x;
+        if (x < min) min = x;
+        if (i != n) {
+            if (x > max_n1) max_n1 = x;
+            if (x < max_n1) min_n1 = x;
+        }
+    }
+
+    var distance = Math.sqrt(1 / Math.log(distances[n] - distances[k]));
+    var variance = S / ((n - k) - 1);
+    var stddev = Math.sqrt(variance);
+    var weightedDev = stddev / (max - min);
+    var eta = 0;
+
+    var k_m_1 = (k >= 1 ? k - 1 : 0);
+
+    if (directionSet.sort()[0] > 0) {
+        eta = Math.abs(data[k] - data[k_m_1]);
+        if (max_n1 > data[k]) eta += Math.abs(max_n1 - data[k]);
+    } else {
+        eta = Math.abs(data[k] - data[k_m_1]);
+        if (min_n1 < data[k]) eta += Math.abs(min_n1 - data[k]);
+    }
+
+    return distance * weightedDev * eta;
+};
+
+SampleData.prototype.load = function(file, completion) {
+    "use strict";
+    this.reader = new FileReader();
+    this.file = file;    
+    this.completion = completion;
+    this.checkForMoovAtom(0);
+};
+
+SampleData.prototype.checkForMoovAtom = function(offset) {
+    "use strict";
+    this.reader.onload = (function(e) {
+        var result = e.target.result;
+        var basicAtom = new Atom();
+               basicAtom.parse(result);
+
+               if (basicAtom.type == 'moov') 
+            this.readMoovAtom(offset, basicAtom.size);
+        else
+            this.checkForMoovAtom(offset + basicAtom.size);
+    }).bind(this);
+    var subset = this.file.slice(offset, offset + 16);
+    this.reader.readAsArrayBuffer(subset);
+};
+
+SampleData.prototype.readMoovAtom = function(offset, length) {
+    "use strict";
+    this.reader.onload = (function(e) { 
+        var moovAtom = Atom.create(e.target.result);
+               var mediaAtoms = moovAtom.getAtomsByType('mdia');
+               var mediaAtom = mediaAtoms.find(function(atom){
+                       return atom.getAtomByType('hdlr').handlerType == 'vide';
+               });
+        var syncSampleAtom = mediaAtom.getAtomByType('stss');
+        var sampleSizeAtom = syncSampleAtom.parent.getAtomByType('stsz');
+               var mediaHeaderAtom = syncSampleAtom.parent.parent.parent.getAtomByType('mdhd');
+               this.timeScale = mediaHeaderAtom.timeScale;
+        for (var i = 0; i < syncSampleAtom.syncSamples.length; ++i) {
+            var sampleNumber = syncSampleAtom.syncSamples[i];
+            var sampleSize = sampleSizeAtom.sampleSizes[sampleNumber];
+            this.syncSampleSizes.push(sampleSize);
+            if (this.maximumSampleSize < sampleSize)
+                this.maximumSampleSize = sampleSize;
+            
+            var sampleTimeAtom = syncSampleAtom.parent.getAtomByType('stts');
+            var sampleSum = 0;
+
+            
+            this.syncSampleTimes.push(timeSum);
+        }
+
+        this.sceneSamples.push([0, 0]);
+        for (var i = 1; i < this.syncSampleTimes.length; ++i) {
+            var k = this.sceneSamples[this.sceneSamples.length-1][1];
+            var n = i;
+            var T = this.threshold(this.syncSampleSizes, this.syncSampleTimes, k, n, this.syncSampleSizes.length);
+            var D = this.decision(this.syncSampleSizes, k, n, this.syncSampleSizes.length);
+            this.thresholds.push(isFinite(T) ? T : 0);
+            this.decisions.push(D);
+
+            if (D > T && k + 1 < n) {
+                this.sceneSamples.push([D - T, i]);
+            }
+        }
+
+        this.sceneSamples.sort(function(a, b) {
+            if (a[0] == b[0])
+                return a[1] - b[1]
+            return a[0] - b[0];
+        });
+        
+        this.completion();
+
+    }).bind(this);
+    var subset = this.file.slice(offset, offset + length);
+    this.reader.readAsArrayBuffer(subset);
+};