timestamp-rollover-stream.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /**
  2. * mux.js
  3. *
  4. * Copyright (c) 2016 Brightcove
  5. * All rights reserved.
  6. *
  7. * Accepts program elementary stream (PES) data events and corrects
  8. * decode and presentation time stamps to account for a rollover
  9. * of the 33 bit value.
  10. */
  11. 'use strict';
  12. var Stream = require('../utils/stream');
  13. var MAX_TS = 8589934592;
  14. var RO_THRESH = 4294967296;
  15. var handleRollover = function(value, reference) {
  16. var direction = 1;
  17. if (value > reference) {
  18. // If the current timestamp value is greater than our reference timestamp and we detect a
  19. // timestamp rollover, this means the roll over is happening in the opposite direction.
  20. // Example scenario: Enter a long stream/video just after a rollover occurred. The reference
  21. // point will be set to a small number, e.g. 1. The user then seeks backwards over the
  22. // rollover point. In loading this segment, the timestamp values will be very large,
  23. // e.g. 2^33 - 1. Since this comes before the data we loaded previously, we want to adjust
  24. // the time stamp to be `value - 2^33`.
  25. direction = -1;
  26. }
  27. // Note: A seek forwards or back that is greater than the RO_THRESH (2^32, ~13 hours) will
  28. // cause an incorrect adjustment.
  29. while (Math.abs(reference - value) > RO_THRESH) {
  30. value += (direction * MAX_TS);
  31. }
  32. return value;
  33. };
  34. var TimestampRolloverStream = function(type) {
  35. var lastDTS, referenceDTS;
  36. TimestampRolloverStream.prototype.init.call(this);
  37. this.type_ = type;
  38. this.push = function(data) {
  39. if (data.type !== this.type_) {
  40. return;
  41. }
  42. if (referenceDTS === undefined) {
  43. referenceDTS = data.dts;
  44. }
  45. data.dts = handleRollover(data.dts, referenceDTS);
  46. data.pts = handleRollover(data.pts, referenceDTS);
  47. lastDTS = data.dts;
  48. this.trigger('data', data);
  49. };
  50. this.flush = function() {
  51. referenceDTS = lastDTS;
  52. this.trigger('done');
  53. };
  54. this.discontinuity = function() {
  55. referenceDTS = void 0;
  56. lastDTS = void 0;
  57. };
  58. };
  59. TimestampRolloverStream.prototype = new Stream();
  60. module.exports = {
  61. TimestampRolloverStream: TimestampRolloverStream,
  62. handleRollover: handleRollover
  63. };