emsg.js 3.4 KB

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