abscapturetimeextension.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package rtp
  4. import (
  5. "encoding/binary"
  6. "time"
  7. )
  8. const (
  9. absCaptureTimeExtensionSize = 8
  10. absCaptureTimeExtendedExtensionSize = 16
  11. )
  12. // AbsCaptureTimeExtension is a extension payload format in
  13. // http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time
  14. // 0 1 2 3
  15. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  16. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  17. // | ID | len=7 | absolute capture timestamp (bit 0-23) |
  18. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  19. // | absolute capture timestamp (bit 24-55) |
  20. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  21. // | ... (56-63) |
  22. // +-+-+-+-+-+-+-+-+
  23. type AbsCaptureTimeExtension struct {
  24. Timestamp uint64
  25. EstimatedCaptureClockOffset *int64
  26. }
  27. // Marshal serializes the members to buffer.
  28. func (t AbsCaptureTimeExtension) Marshal() ([]byte, error) {
  29. if t.EstimatedCaptureClockOffset != nil {
  30. buf := make([]byte, 16)
  31. binary.BigEndian.PutUint64(buf[0:8], t.Timestamp)
  32. binary.BigEndian.PutUint64(buf[8:16], uint64(*t.EstimatedCaptureClockOffset))
  33. return buf, nil
  34. }
  35. buf := make([]byte, 8)
  36. binary.BigEndian.PutUint64(buf[0:8], t.Timestamp)
  37. return buf, nil
  38. }
  39. // Unmarshal parses the passed byte slice and stores the result in the members.
  40. func (t *AbsCaptureTimeExtension) Unmarshal(rawData []byte) error {
  41. if len(rawData) < absCaptureTimeExtensionSize {
  42. return errTooSmall
  43. }
  44. t.Timestamp = binary.BigEndian.Uint64(rawData[0:8])
  45. if len(rawData) >= absCaptureTimeExtendedExtensionSize {
  46. offset := int64(binary.BigEndian.Uint64(rawData[8:16]))
  47. t.EstimatedCaptureClockOffset = &offset
  48. }
  49. return nil
  50. }
  51. // CaptureTime produces the estimated time.Time represented by this extension.
  52. func (t AbsCaptureTimeExtension) CaptureTime() time.Time {
  53. return toTime(t.Timestamp)
  54. }
  55. // EstimatedCaptureClockOffsetDuration produces the estimated time.Duration represented by this extension.
  56. func (t AbsCaptureTimeExtension) EstimatedCaptureClockOffsetDuration() *time.Duration {
  57. if t.EstimatedCaptureClockOffset == nil {
  58. return nil
  59. }
  60. offset := *t.EstimatedCaptureClockOffset
  61. negative := false
  62. if offset < 0 {
  63. offset = -offset
  64. negative = true
  65. }
  66. duration := time.Duration(offset/(1<<32))*time.Second + time.Duration((offset&0xFFFFFFFF)*1e9/(1<<32))*time.Nanosecond
  67. if negative {
  68. duration = -duration
  69. }
  70. return &duration
  71. }
  72. // NewAbsCaptureTimeExtension makes new AbsCaptureTimeExtension from time.Time.
  73. func NewAbsCaptureTimeExtension(captureTime time.Time) *AbsCaptureTimeExtension {
  74. return &AbsCaptureTimeExtension{
  75. Timestamp: toNtpTime(captureTime),
  76. }
  77. }
  78. // NewAbsCaptureTimeExtensionWithCaptureClockOffset makes new AbsCaptureTimeExtension from time.Time and a clock offset.
  79. func NewAbsCaptureTimeExtensionWithCaptureClockOffset(captureTime time.Time, captureClockOffset time.Duration) *AbsCaptureTimeExtension {
  80. ns := captureClockOffset.Nanoseconds()
  81. negative := false
  82. if ns < 0 {
  83. ns = -ns
  84. negative = true
  85. }
  86. lsb := (ns / 1e9) & 0xFFFFFFFF
  87. msb := (((ns % 1e9) * (1 << 32)) / 1e9) & 0xFFFFFFFF
  88. offset := (lsb << 32) | msb
  89. if negative {
  90. offset = -offset
  91. }
  92. return &AbsCaptureTimeExtension{
  93. Timestamp: toNtpTime(captureTime),
  94. EstimatedCaptureClockOffset: &offset,
  95. }
  96. }