Source: lib/cea/sei_processor.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.cea.SeiProcessor');
  7. /**
  8. * H.264 SEI NALU Parser used for extracting 708 closed caption packets.
  9. */
  10. shaka.cea.SeiProcessor = class {
  11. /**
  12. * Processes supplemental enhancement information data.
  13. * @param {!Uint8Array} naluData NALU from which SEI data is to be processed.
  14. * @return {!Iterable.<!Uint8Array>}
  15. */
  16. * process(naluData) {
  17. const naluClone = this.removeEmu(naluData);
  18. // The following is an implementation of section 7.3.2.3.1
  19. // in Rec. ITU-T H.264 (06/2019), the H.264 spec.
  20. let offset = 0;
  21. while (offset < naluClone.length) {
  22. let payloadType = 0; // SEI payload type as defined by H.264 spec
  23. while (naluClone[offset] == 0xFF) {
  24. payloadType += 255;
  25. offset++;
  26. }
  27. payloadType += naluClone[offset++];
  28. let payloadSize = 0; // SEI payload size as defined by H.264 spec
  29. while (naluClone[offset] == 0xFF) {
  30. payloadSize += 255;
  31. offset++;
  32. }
  33. payloadSize += naluClone[offset++];
  34. // Payload type 4 is user_data_registered_itu_t_t35, as per the H.264
  35. // spec. This payload type contains caption data.
  36. if (payloadType == 0x04) {
  37. yield naluClone.subarray(offset, offset + payloadSize);
  38. }
  39. offset += payloadSize;
  40. }
  41. }
  42. /**
  43. * Removes H.264 emulation prevention bytes from the byte array.
  44. *
  45. * Note: Remove bytes by shifting will cause Chromium (VDA) to complain
  46. * about conformance. Recreating a new array solves it.
  47. *
  48. * @param {!Uint8Array} naluData NALU from which EMUs should be removed.
  49. * @return {!Uint8Array} The NALU with the emulation prevention byte removed.
  50. */
  51. removeEmu(naluData) {
  52. let naluClone = naluData;
  53. let zeroCount = 0;
  54. let src = 0;
  55. while (src < naluClone.length) {
  56. if (zeroCount == 2 && naluClone[src] == 0x03) {
  57. // 0x00, 0x00, 0x03 pattern detected
  58. zeroCount = 0;
  59. // Splice the array and recreate a new one, instead of shifting bytes
  60. const newArr = [...naluClone];
  61. newArr.splice(src, 1);
  62. naluClone = new Uint8Array(newArr);
  63. } else {
  64. if (naluClone[src] == 0x00) {
  65. zeroCount++;
  66. } else {
  67. zeroCount = 0;
  68. }
  69. }
  70. src++;
  71. }
  72. return naluClone;
  73. }
  74. };