avc.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package h264
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. )
  6. const forbiddenZeroBit = 0x80
  7. const nalUnitType = 0x1F
  8. // Deprecated: DecodeStream - find and return first AU in AVC format
  9. // useful for processing live streams with unknown separator size
  10. func DecodeStream(annexb []byte) ([]byte, int) {
  11. startPos := -1
  12. i := 0
  13. for {
  14. // search next separator
  15. if i = IndexFrom(annexb, []byte{0, 0, 1}, i); i < 0 {
  16. break
  17. }
  18. // move i to next AU
  19. if i += 3; i >= len(annexb) {
  20. break
  21. }
  22. // check if AU type valid
  23. octet := annexb[i]
  24. if octet&forbiddenZeroBit != 0 {
  25. continue
  26. }
  27. // 0 => AUD => SPS/IF/PF => AUD
  28. // 0 => SPS/PF => SPS/PF
  29. nalType := octet & nalUnitType
  30. if startPos >= 0 {
  31. switch nalType {
  32. case NALUTypeAUD, NALUTypeSPS, NALUTypePFrame:
  33. if annexb[i-4] == 0 {
  34. return DecodeAnnexB(annexb[startPos : i-4]), i - 4
  35. } else {
  36. return DecodeAnnexB(annexb[startPos : i-3]), i - 3
  37. }
  38. }
  39. } else {
  40. switch nalType {
  41. case NALUTypeSPS, NALUTypePFrame:
  42. if i >= 4 && annexb[i-4] == 0 {
  43. startPos = i - 4
  44. } else {
  45. startPos = i - 3
  46. }
  47. }
  48. }
  49. }
  50. return nil, 0
  51. }
  52. // DecodeAnnexB - convert AnnexB to AVC format
  53. // support unknown separator size
  54. func DecodeAnnexB(b []byte) []byte {
  55. if b[2] == 1 {
  56. // convert: 0 0 1 => 0 0 0 1
  57. b = append([]byte{0}, b...)
  58. }
  59. startPos := 0
  60. i := 4
  61. for {
  62. // search next separato
  63. if i = IndexFrom(b, []byte{0, 0, 1}, i); i < 0 {
  64. break
  65. }
  66. // move i to next AU
  67. if i += 3; i >= len(b) {
  68. break
  69. }
  70. // check if AU type valid
  71. octet := b[i]
  72. if octet&forbiddenZeroBit != 0 {
  73. continue
  74. }
  75. switch octet & nalUnitType {
  76. case NALUTypePFrame, NALUTypeIFrame, NALUTypeSPS, NALUTypePPS:
  77. if b[i-4] != 0 {
  78. // prefix: 0 0 1
  79. binary.BigEndian.PutUint32(b[startPos:], uint32(i-startPos-7))
  80. tmp := make([]byte, 0, len(b)+1)
  81. tmp = append(tmp, b[:i]...)
  82. tmp = append(tmp, 0)
  83. b = append(tmp, b[i:]...)
  84. startPos = i - 3
  85. } else {
  86. // prefix: 0 0 0 1
  87. binary.BigEndian.PutUint32(b[startPos:], uint32(i-startPos-8))
  88. startPos = i - 4
  89. }
  90. }
  91. }
  92. binary.BigEndian.PutUint32(b[startPos:], uint32(len(b)-startPos-4))
  93. return b
  94. }
  95. func IndexFrom(b []byte, sep []byte, from int) int {
  96. if from > 0 {
  97. if from < len(b) {
  98. if i := bytes.Index(b[from:], sep); i >= 0 {
  99. return from + i
  100. }
  101. }
  102. return -1
  103. }
  104. return bytes.Index(b, sep)
  105. }