|
|
@@ -234,10 +234,6 @@ jsmpeg.prototype.decodeSequenceHeader = function() {
|
|
234
|
234
|
this.forwardCr = new Uint8ClampedArray(this.codedSize >> 2);
|
|
235
|
235
|
this.forwardCb = new Uint8ClampedArray(this.codedSize >> 2);
|
|
236
|
236
|
|
|
237
|
|
- this.backwardY = new Uint8ClampedArray(this.codedSize);
|
|
238
|
|
- this.backwardCr = new Uint8ClampedArray(this.codedSize >> 2);
|
|
239
|
|
- this.backwardCb = new Uint8ClampedArray(this.codedSize >> 2);
|
|
240
|
|
-
|
|
241
|
237
|
this.canvas.width = this.width;
|
|
242
|
238
|
this.canvas.height = this.height;
|
|
243
|
239
|
|
|
|
@@ -264,20 +260,11 @@ jsmpeg.prototype.forwardY = null;
|
|
264
|
260
|
jsmpeg.prototype.forwardCr = null;
|
|
265
|
261
|
jsmpeg.prototype.forwardCb = null;
|
|
266
|
262
|
|
|
267
|
|
-jsmpeg.prototype.backwardY = null;
|
|
268
|
|
-jsmpeg.prototype.backwardCr = null;
|
|
269
|
|
-jsmpeg.prototype.backwardCb = null;
|
|
270
|
|
-
|
|
271
|
263
|
jsmpeg.prototype.fullPelForward = false;
|
|
272
|
264
|
jsmpeg.prototype.forwardFCode = 0;
|
|
273
|
265
|
jsmpeg.prototype.forwardRSize = 0;
|
|
274
|
266
|
jsmpeg.prototype.forwardF = 0;
|
|
275
|
267
|
|
|
276
|
|
-jsmpeg.prototype.fullPelBackward = false;
|
|
277
|
|
-jsmpeg.prototype.backwardFCode = 0;
|
|
278
|
|
-jsmpeg.prototype.backwardRSize = 0;
|
|
279
|
|
-jsmpeg.prototype.backwardF = 0;
|
|
280
|
|
-
|
|
281
|
268
|
|
|
282
|
269
|
jsmpeg.prototype.decodePicture = function() {
|
|
283
|
270
|
this.buffer.advance(10); // skip temporalReference
|
|
|
@@ -303,25 +290,8 @@ jsmpeg.prototype.decodePicture = function() {
|
|
303
|
290
|
|
|
304
|
291
|
// full_pel_backward, backward_f_code
|
|
305
|
292
|
if( this.pictureCodingType == PICTURE_TYPE_B ) {
|
|
306
|
|
- this.fullPelBackward = this.buffer.getBits(1);
|
|
307
|
|
- this.backwardFCode = this.buffer.getBits(3);
|
|
308
|
|
- if( this.backwardFCode == 0 ) {
|
|
309
|
|
- // Ignore picture with zero backward_f_code
|
|
310
|
|
- return;
|
|
311
|
|
- }
|
|
312
|
|
- this.backwardRSize = this.backwardFCode - 1;
|
|
313
|
|
- this.backwardF = 1 << this.backwardRSize;
|
|
314
|
|
- }
|
|
315
|
|
-
|
|
316
|
|
- var
|
|
317
|
|
- tmpY = this.forwardY,
|
|
318
|
|
- tmpCr = this.forwardCr,
|
|
319
|
|
- tmpCb = this.forwardCb;
|
|
320
|
|
-
|
|
321
|
|
- if( this.pictureCodingType == PICTURE_TYPE_I || this.pictureCodingType == PICTURE_TYPE_P ) {
|
|
322
|
|
- this.forwardY = this.backwardY;
|
|
323
|
|
- this.forwardCr = this.backwardCr;
|
|
324
|
|
- this.forwardCb = this.backwardCb;
|
|
|
293
|
+ // We can't deal with B frames
|
|
|
294
|
+ return;
|
|
325
|
295
|
}
|
|
326
|
296
|
|
|
327
|
297
|
var code = 0;
|
|
|
@@ -344,9 +314,15 @@ jsmpeg.prototype.decodePicture = function() {
|
|
344
|
314
|
|
|
345
|
315
|
// If this is a reference picutre then rotate the prediction pointers
|
|
346
|
316
|
if( this.pictureCodingType == PICTURE_TYPE_I || this.pictureCodingType == PICTURE_TYPE_P ) {
|
|
347
|
|
- this.backwardY = this.currentY;
|
|
348
|
|
- this.backwardCr = this.currentCr;
|
|
349
|
|
- this.backwardCb = this.currentCb;
|
|
|
317
|
+ var
|
|
|
318
|
+ tmpY = this.forwardY,
|
|
|
319
|
+ tmpCr = this.forwardCr,
|
|
|
320
|
+ tmpCb = this.forwardCb;
|
|
|
321
|
+
|
|
|
322
|
+ this.forwardY = this.currentY;
|
|
|
323
|
+ this.forwardCr = this.currentCr;
|
|
|
324
|
+ this.forwardCb = this.currentCb;
|
|
|
325
|
+
|
|
350
|
326
|
this.currentY = tmpY;
|
|
351
|
327
|
this.currentCr = tmpCr;
|
|
352
|
328
|
this.currentCb = tmpCb;
|
|
|
@@ -440,8 +416,6 @@ jsmpeg.prototype.decodeSlice = function(slice) {
|
|
440
|
416
|
// Reset motion vectors and DC predictors
|
|
441
|
417
|
this.motionFwH = this.motionFwHPrev = 0;
|
|
442
|
418
|
this.motionFwV = this.motionFwVPrev = 0;
|
|
443
|
|
- this.motionBwH = this.motionBwHPrev = 0;
|
|
444
|
|
- this.motionBwV = this.motionBwVPrev = 0;
|
|
445
|
419
|
this.dcPredictorY = 128;
|
|
446
|
420
|
this.dcPredictorCr = 128;
|
|
447
|
421
|
this.dcPredictorCb = 128;
|
|
|
@@ -470,16 +444,11 @@ jsmpeg.prototype.mbCol = 0;
|
|
470
|
444
|
jsmpeg.prototype.macroblockType = 0;
|
|
471
|
445
|
jsmpeg.prototype.macroblockIntra = false;
|
|
472
|
446
|
jsmpeg.prototype.macroblockMotFw = false;
|
|
473
|
|
-jsmpeg.prototype.macroblockMotBw = false;
|
|
474
|
447
|
|
|
475
|
448
|
jsmpeg.prototype.motionFwH = 0;
|
|
476
|
449
|
jsmpeg.prototype.motionFwV = 0;
|
|
477
|
|
-jsmpeg.prototype.motionBwH = 0;
|
|
478
|
|
-jsmpeg.prototype.motionBwV = 0;
|
|
479
|
450
|
jsmpeg.prototype.motionFwHPrev = 0;
|
|
480
|
451
|
jsmpeg.prototype.motionFwVPrev = 0;
|
|
481
|
|
-jsmpeg.prototype.motionBwHPrev = 0;
|
|
482
|
|
-jsmpeg.prototype.motionBwVPrev = 0;
|
|
483
|
452
|
|
|
484
|
453
|
jsmpeg.prototype.decodeMacroblock = function() {
|
|
485
|
454
|
// Decode macroblock_address_increment
|
|
|
@@ -528,7 +497,7 @@ jsmpeg.prototype.decodeMacroblock = function() {
|
|
528
|
497
|
this.macroblockAddress++;
|
|
529
|
498
|
this.mbRow = (this.macroblockAddress / this.mbWidth)|0;
|
|
530
|
499
|
this.mbCol = this.macroblockAddress % this.mbWidth;
|
|
531
|
|
- this.predictMacroblock();
|
|
|
500
|
+ this.copyMacroblock(this.motionFwH, this.motionFwV, this.forwardY, this.forwardCr, this.forwardCb);
|
|
532
|
501
|
increment--;
|
|
533
|
502
|
}
|
|
534
|
503
|
this.macroblockAddress++;
|
|
|
@@ -540,7 +509,6 @@ jsmpeg.prototype.decodeMacroblock = function() {
|
|
540
|
509
|
this.macroblockType = this.readCode(MACROBLOCK_TYPE_TABLES[this.pictureCodingType]);
|
|
541
|
510
|
this.macroblockIntra = (this.macroblockType & 0x01);
|
|
542
|
511
|
this.macroblockMotFw = (this.macroblockType & 0x08);
|
|
543
|
|
- this.macroblockMotBw = (this.macroblockType & 0x04);
|
|
544
|
512
|
|
|
545
|
513
|
// Quantizer scale
|
|
546
|
514
|
if( (this.macroblockType & 0x10) != 0 ) {
|
|
|
@@ -551,8 +519,6 @@ jsmpeg.prototype.decodeMacroblock = function() {
|
|
551
|
519
|
// Intra-coded macroblocks reset motion vectors
|
|
552
|
520
|
this.motionFwH = this.motionFwHPrev = 0;
|
|
553
|
521
|
this.motionFwV = this.motionFwVPrev = 0;
|
|
554
|
|
- this.motionBwH = this.motionBwHPrev = 0;
|
|
555
|
|
- this.motionBwV = this.motionBwVPrev = 0;
|
|
556
|
522
|
}
|
|
557
|
523
|
else {
|
|
558
|
524
|
// Non-intra macroblocks reset DC predictors
|
|
|
@@ -561,7 +527,7 @@ jsmpeg.prototype.decodeMacroblock = function() {
|
|
561
|
527
|
this.dcPredictorCb = 128;
|
|
562
|
528
|
|
|
563
|
529
|
this.decodeMotionVectors();
|
|
564
|
|
- this.predictMacroblock();
|
|
|
530
|
+ this.copyMacroblock(this.motionFwH, this.motionFwV, this.forwardY, this.forwardCr, this.forwardCb);
|
|
565
|
531
|
}
|
|
566
|
532
|
|
|
567
|
533
|
// Decode blocks
|
|
|
@@ -640,67 +606,6 @@ jsmpeg.prototype.decodeMotionVectors = function() {
|
|
640
|
606
|
this.motionFwH = this.motionFwHPrev = 0;
|
|
641
|
607
|
this.motionFwV = this.motionFwVPrev = 0;
|
|
642
|
608
|
}
|
|
643
|
|
-
|
|
644
|
|
-
|
|
645
|
|
- // Backward
|
|
646
|
|
- if( this.macroblockMotBw ) {
|
|
647
|
|
- // Horizontal backward
|
|
648
|
|
- code = this.readCode(MOTION);
|
|
649
|
|
- if( (code != 0) && (this.backwardF != 1) ) {
|
|
650
|
|
- r = this.buffer.getBits(this.backwardRSize);
|
|
651
|
|
- d = ((Math.abs(code) - 1) << this.backwardRSize) + r + 1;
|
|
652
|
|
- if( code < 0 ) {
|
|
653
|
|
- d = -d;
|
|
654
|
|
- }
|
|
655
|
|
- }
|
|
656
|
|
- else {
|
|
657
|
|
- d = code;
|
|
658
|
|
- }
|
|
659
|
|
-
|
|
660
|
|
- this.motionBwHPrev += d;
|
|
661
|
|
- if( this.motionBwHPrev > (this.backwardF << 4) - 1 ) {
|
|
662
|
|
- this.motionBwHPrev -= this.backwardF << 5;
|
|
663
|
|
- }
|
|
664
|
|
- else if( this.motionBwHPrev < ((-this.backwardF) << 4) ) {
|
|
665
|
|
- this.motionBwHPrev += this.backwardF << 5;
|
|
666
|
|
- }
|
|
667
|
|
-
|
|
668
|
|
- this.motionBwH = this.motionBwHPrev;
|
|
669
|
|
- if( this.fullPelForward ) {
|
|
670
|
|
- this.motionBwH <<= 1;
|
|
671
|
|
- }
|
|
672
|
|
-
|
|
673
|
|
- // Vertical backward
|
|
674
|
|
- code = this.readCode(MOTION);
|
|
675
|
|
- if ((code != 0) && (this.backwardF != 1)) {
|
|
676
|
|
- r = this.buffer.getBits(this.backwardRSize);
|
|
677
|
|
- d = ((Math.abs(code) - 1) << this.backwardRSize) + r + 1;
|
|
678
|
|
- if( code < 0 ) {
|
|
679
|
|
- d = -d;
|
|
680
|
|
- }
|
|
681
|
|
- }
|
|
682
|
|
- else {
|
|
683
|
|
- d = code;
|
|
684
|
|
- }
|
|
685
|
|
-
|
|
686
|
|
- this.motionBwVPrev += d;
|
|
687
|
|
- if( this.motionBwVPrev > (this.backwardF << 4) - 1 ) {
|
|
688
|
|
- this.motionBwVPrev -= this.backwardF << 5;
|
|
689
|
|
- }
|
|
690
|
|
- else if( this.motionBwVPrev < ((-this.backwardF) << 4)) {
|
|
691
|
|
- this.motionBwVPrev += this.backwardF << 5;
|
|
692
|
|
- }
|
|
693
|
|
-
|
|
694
|
|
- this.motionBwV = this.motionBwVPrev;
|
|
695
|
|
- if( this.fullPelForward ) {
|
|
696
|
|
- this.motionBwV <<= 1;
|
|
697
|
|
- }
|
|
698
|
|
-
|
|
699
|
|
- this.motionBwV= this.motionBwVPrev;
|
|
700
|
|
- if( this.fullPelBackward ) {
|
|
701
|
|
- this.motionBwVPrev <<= 1;
|
|
702
|
|
- }
|
|
703
|
|
- }
|
|
704
|
609
|
};
|
|
705
|
610
|
|
|
706
|
611
|
jsmpeg.prototype.copyMacroblock = function(motionH, motionV, sY, sCr, sCb ) {
|
|
|
@@ -708,7 +613,7 @@ jsmpeg.prototype.copyMacroblock = function(motionH, motionV, sY, sCr, sCb ) {
|
|
708
|
613
|
width, scan,
|
|
709
|
614
|
H, V, oddH, oddV,
|
|
710
|
615
|
src, dest, last;
|
|
711
|
|
-
|
|
|
616
|
+
|
|
712
|
617
|
var dY = this.currentY;
|
|
713
|
618
|
var dCb = this.currentCb;
|
|
714
|
619
|
var dCr = this.currentCr;
|
|
|
@@ -830,160 +735,6 @@ jsmpeg.prototype.copyMacroblock = function(motionH, motionV, sY, sCr, sCb ) {
|
|
830
|
735
|
};
|
|
831
|
736
|
|
|
832
|
737
|
|
|
833
|
|
-jsmpeg.prototype.interpolateMacroblock = function() {
|
|
834
|
|
- var
|
|
835
|
|
- width, scan,
|
|
836
|
|
- H, V, oddH, oddV,
|
|
837
|
|
- src, dest, last;
|
|
838
|
|
-
|
|
839
|
|
- // Luminance
|
|
840
|
|
- width = this.codedWidth;
|
|
841
|
|
- scan = width - 16;
|
|
842
|
|
-
|
|
843
|
|
- H = this.motionBwH >> 1;
|
|
844
|
|
- V = this.motionBwV >> 1;
|
|
845
|
|
- oddH = (this.motionBwH & 1) == 1;
|
|
846
|
|
- oddV = (this.motionBwV & 1) == 1;
|
|
847
|
|
-
|
|
848
|
|
- src = ((this.mbRow << 4) + V) * width + (this.mbCol << 4) + H;
|
|
849
|
|
- dest = (this.mbRow * width + this.mbCol) << 4;
|
|
850
|
|
- last = dest + (width << 4);
|
|
851
|
|
-
|
|
852
|
|
- if( oddH ) {
|
|
853
|
|
- if( oddV ) {
|
|
854
|
|
- while( dest < last ) {
|
|
855
|
|
- for( var x = 0; x < 16; x++ ) {
|
|
856
|
|
- this.currentY[dest] += ((this.backwardY[src] + this.backwardY[src+1] +
|
|
857
|
|
- this.backwardY[src+width] + this.backwardY[src+width+1] + 2) >> 2) + 1;
|
|
858
|
|
- this.currentY[dest] >>= 1;
|
|
859
|
|
- dest++; src++;
|
|
860
|
|
- }
|
|
861
|
|
- dest += scan; src += scan;
|
|
862
|
|
- }
|
|
863
|
|
- }
|
|
864
|
|
- else {
|
|
865
|
|
- while( dest < last ) {
|
|
866
|
|
- for( var x = 0; x < 16; x++ ) {
|
|
867
|
|
- this.currentY[dest] += ((this.backwardY[src] + this.backwardY[src+1] + 1) >> 1) + 1;
|
|
868
|
|
- this.currentY[dest] >>= 1;
|
|
869
|
|
- dest++; src++;
|
|
870
|
|
- }
|
|
871
|
|
- dest += scan; src += scan;
|
|
872
|
|
- }
|
|
873
|
|
- }
|
|
874
|
|
- }
|
|
875
|
|
- else {
|
|
876
|
|
- if( oddV ) {
|
|
877
|
|
- while( dest < last ) {
|
|
878
|
|
- for( var x = 0; x < 16; x++ ) {
|
|
879
|
|
- this.currentY[dest] += ((this.backwardY[src] + this.backwardY[src+width] + 1) >> 1) + 1;
|
|
880
|
|
- this.currentY[dest] >>= 1;
|
|
881
|
|
- dest++; src++;
|
|
882
|
|
- }
|
|
883
|
|
- dest += scan; src += scan;
|
|
884
|
|
- }
|
|
885
|
|
- }
|
|
886
|
|
- else {
|
|
887
|
|
- while( dest < last ) {
|
|
888
|
|
- for( var x = 0; x < 16; x++ ) {
|
|
889
|
|
- this.currentY[dest] += this.backwardY[src] + 1;
|
|
890
|
|
- this.currentY[dest] >>= 1;
|
|
891
|
|
- dest++; src++;
|
|
892
|
|
- }
|
|
893
|
|
- dest += scan; src += scan;
|
|
894
|
|
- }
|
|
895
|
|
- }
|
|
896
|
|
- }
|
|
897
|
|
-
|
|
898
|
|
- // Chrominance
|
|
899
|
|
- width = this.halfWidth;
|
|
900
|
|
- scan = width - 8;
|
|
901
|
|
-
|
|
902
|
|
- H = (this.motionBwH/2) >> 1;
|
|
903
|
|
- V = (this.motionBwV/2) >> 1;
|
|
904
|
|
- oddH = ((this.motionBwH/2) & 1) == 1;
|
|
905
|
|
- oddV = ((this.motionBwV/2) & 1) == 1;
|
|
906
|
|
-
|
|
907
|
|
- src = ((this.mbRow << 3) + V) * width + (this.mbCol << 3) + H;
|
|
908
|
|
- dest = (this.mbRow * width + this.mbCol) << 3;
|
|
909
|
|
- last = dest + (width << 3);
|
|
910
|
|
-
|
|
911
|
|
- if( oddH ) {
|
|
912
|
|
- if( oddV ) {
|
|
913
|
|
- while( dest < last ) {
|
|
914
|
|
- for( var x = 0; x < 8; x++ ) {
|
|
915
|
|
- this.currentCr[dest] += ((this.backwardCr[src] + this.backwardCr[src+1] +
|
|
916
|
|
- this.backwardCr[src+width] + this.backwardCr[src+width+1] + 2) >> 2) + 1;
|
|
917
|
|
- this.currentCb[dest] += ((this.backwardCb[src] + this.backwardCb[src+1] +
|
|
918
|
|
- this.backwardCb[src+width] + this.backwardCb[src+width+1] + 2) >> 2) + 1;
|
|
919
|
|
- this.currentCr[dest] >>= 1;
|
|
920
|
|
- this.currentCb[dest] >>= 1;
|
|
921
|
|
- dest++; src++;
|
|
922
|
|
- }
|
|
923
|
|
- dest += scan; src += scan;
|
|
924
|
|
- }
|
|
925
|
|
- }
|
|
926
|
|
- else {
|
|
927
|
|
- while( dest < last ) {
|
|
928
|
|
- for( var x = 0; x < 8; x++ ) {
|
|
929
|
|
- this.currentCr[dest] += ((this.backwardCr[src] + this.backwardCr[src+1] + 1) >> 1) + 1;
|
|
930
|
|
- this.currentCb[dest] += ((this.backwardCb[src] + this.backwardCb[src+1] + 1) >> 1) + 1;
|
|
931
|
|
- this.currentCr[dest] >>= 1;
|
|
932
|
|
- this.currentCb[dest] >>= 1;
|
|
933
|
|
- dest++; src++;
|
|
934
|
|
- }
|
|
935
|
|
- dest += scan; src += scan;
|
|
936
|
|
- }
|
|
937
|
|
- }
|
|
938
|
|
- }
|
|
939
|
|
- else {
|
|
940
|
|
- if( oddV ) {
|
|
941
|
|
- while( dest < last ) {
|
|
942
|
|
- for( var x = 0; x < 8; x++ ) {
|
|
943
|
|
- this.currentCr[dest] += ((this.backwardCr[src] + this.backwardCr[src+width] + 1) >> 1) + 1;
|
|
944
|
|
- this.currentCb[dest] += ((this.backwardCb[src] + this.backwardCb[src+width] + 1) >> 1) + 1;
|
|
945
|
|
- this.currentCr[dest] >>= 1;
|
|
946
|
|
- this.currentCb[dest] >>= 1;
|
|
947
|
|
- dest++; src++;
|
|
948
|
|
- }
|
|
949
|
|
- dest += scan; src += scan;
|
|
950
|
|
- }
|
|
951
|
|
- }
|
|
952
|
|
- else {
|
|
953
|
|
- while( dest < last ) {
|
|
954
|
|
- for( var x = 0; x < 8; x++ ) {
|
|
955
|
|
- this.currentCr[dest] += this.backwardCr[src] + 1;
|
|
956
|
|
- this.currentCb[dest] += this.backwardCb[src] + 1;
|
|
957
|
|
- this.currentCr[dest] >>= 1;
|
|
958
|
|
- this.currentCb[dest] >>= 1;
|
|
959
|
|
- dest++; src++;
|
|
960
|
|
- }
|
|
961
|
|
- dest += scan; src += scan;
|
|
962
|
|
- }
|
|
963
|
|
- }
|
|
964
|
|
- }
|
|
965
|
|
-};
|
|
966
|
|
-
|
|
967
|
|
-jsmpeg.prototype.predictMacroblock = function() {
|
|
968
|
|
- if( this.pictureCodingType == PICTURE_TYPE_B ) {
|
|
969
|
|
- if( this.macroblockMotFw ) {
|
|
970
|
|
- this.copyMacroblock(this.motionFwH, this.motionFwV, this.forwardY, this.forwardCr, this.forwardCb);
|
|
971
|
|
- if( this.macroblockMotBw ) {
|
|
972
|
|
- this.interpolateMacroblock();
|
|
973
|
|
- }
|
|
974
|
|
- }
|
|
975
|
|
- else {
|
|
976
|
|
- this.copyMacroblock(this.motionBwH, this.motionBwV, this.backwardY, this.backwardCr, this.backwardCb);
|
|
977
|
|
- }
|
|
978
|
|
- }
|
|
979
|
|
- else {
|
|
980
|
|
- this.copyMacroblock(this.motionFwH, this.motionFwV, this.forwardY, this.forwardCr, this.forwardCb);
|
|
981
|
|
- }
|
|
982
|
|
- // Ignore error on motion vectors pointing outside the bitmap
|
|
983
|
|
-};
|
|
984
|
|
-
|
|
985
|
|
-
|
|
986
|
|
-
|
|
987
|
738
|
// ----------------------------------------------------------------------------
|
|
988
|
739
|
// Block layer
|
|
989
|
740
|
|