emsg.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. var uint8ToCString = require('../utils/string.js').uint8ToCString;
  2. var getUint64 = require('../utils/numbers.js').getUint64;
  3. /**
  4. * Based on: ISO/IEC 23009 Section: 5.10.3.3
  5. * References:
  6. * https://dashif-documents.azurewebsites.net/Events/master/event.html#emsg-format
  7. * https://aomediacodec.github.io/id3-emsg/
  8. *
  9. * Takes emsg box data as a uint8 array and returns a emsg box object
  10. * @param {UInt8Array} boxData data from emsg box
  11. * @returns A parsed emsg box object
  12. */
  13. var parseEmsgBox = function(boxData) {
  14. // version + flags
  15. var offset = 4;
  16. var version = boxData[0];
  17. var scheme_id_uri,
  18. value,
  19. timescale,
  20. presentation_time,
  21. presentation_time_delta,
  22. event_duration,
  23. id,
  24. message_data;
  25. if (version === 0) {
  26. scheme_id_uri = uint8ToCString(boxData.subarray(offset));
  27. offset += scheme_id_uri.length;
  28. value = uint8ToCString(boxData.subarray(offset));
  29. offset += value.length;
  30. var dv = new DataView(boxData.buffer);
  31. timescale = dv.getUint32(offset);
  32. offset += 4;
  33. presentation_time_delta = dv.getUint32(offset);
  34. offset += 4;
  35. event_duration = dv.getUint32(offset);
  36. offset += 4;
  37. id = dv.getUint32(offset);
  38. offset += 4;
  39. } else if (version === 1) {
  40. var dv = new DataView(boxData.buffer);
  41. timescale = dv.getUint32(offset);
  42. offset += 4;
  43. presentation_time = getUint64(boxData.subarray(offset));
  44. offset += 8;
  45. event_duration = dv.getUint32(offset);
  46. offset += 4;
  47. id = dv.getUint32(offset);
  48. offset += 4;
  49. scheme_id_uri = uint8ToCString(boxData.subarray(offset));
  50. offset += scheme_id_uri.length;
  51. value = uint8ToCString(boxData.subarray(offset));
  52. offset += value.length;
  53. }
  54. message_data = new Uint8Array(boxData.subarray(offset, boxData.byteLength));
  55. var emsgBox = {
  56. scheme_id_uri,
  57. value,
  58. // if timescale is undefined or 0 set to 1
  59. timescale: timescale ? timescale : 1,
  60. presentation_time,
  61. presentation_time_delta,
  62. event_duration,
  63. id,
  64. message_data };
  65. return isValidEmsgBox(version, emsgBox) ? emsgBox : undefined;
  66. };
  67. /**
  68. * Scales a presentation time or time delta with an offset with a provided timescale
  69. * @param {number} presentationTime
  70. * @param {number} timescale
  71. * @param {number} timeDelta
  72. * @param {number} offset
  73. * @returns the scaled time as a number
  74. */
  75. var scaleTime = function(presentationTime, timescale, timeDelta, offset) {
  76. return presentationTime || presentationTime === 0 ? presentationTime / timescale : offset + timeDelta / timescale;
  77. };
  78. /**
  79. * Checks the emsg box data for validity based on the version
  80. * @param {number} version of the emsg box to validate
  81. * @param {Object} emsg the emsg data to validate
  82. * @returns if the box is valid as a boolean
  83. */
  84. var isValidEmsgBox = function(version, emsg) {
  85. var hasScheme = emsg.scheme_id_uri !== '\0'
  86. var isValidV0Box = version === 0 && isDefined(emsg.presentation_time_delta) && hasScheme;
  87. var isValidV1Box = version === 1 && isDefined(emsg.presentation_time) && hasScheme;
  88. // Only valid versions of emsg are 0 and 1
  89. return !(version > 1) && isValidV0Box || isValidV1Box;
  90. };
  91. // Utility function to check if an object is defined
  92. var isDefined = function(data) {
  93. return data !== undefined || data !== null;
  94. };
  95. module.exports = {
  96. parseEmsgBox: parseEmsgBox,
  97. scaleTime: scaleTime
  98. };