h264.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package fmtp
  2. import (
  3. "encoding/hex"
  4. )
  5. func profileLevelIDMatches(a, b string) bool {
  6. aa, err := hex.DecodeString(a)
  7. if err != nil || len(aa) < 2 {
  8. return false
  9. }
  10. bb, err := hex.DecodeString(b)
  11. if err != nil || len(bb) < 2 {
  12. return false
  13. }
  14. return aa[0] == bb[0] && aa[1] == bb[1]
  15. }
  16. type h264FMTP struct {
  17. parameters map[string]string
  18. }
  19. func (h *h264FMTP) MimeType() string {
  20. return "video/h264"
  21. }
  22. // Match returns true if h and b are compatible fmtp descriptions
  23. // Based on RFC6184 Section 8.2.2:
  24. // The parameters identifying a media format configuration for H.264
  25. // are profile-level-id and packetization-mode. These media format
  26. // configuration parameters (except for the level part of profile-
  27. // level-id) MUST be used symmetrically; that is, the answerer MUST
  28. // either maintain all configuration parameters or remove the media
  29. // format (payload type) completely if one or more of the parameter
  30. // values are not supported.
  31. // Informative note: The requirement for symmetric use does not
  32. // apply for the level part of profile-level-id and does not apply
  33. // for the other stream properties and capability parameters.
  34. func (h *h264FMTP) Match(b FMTP) bool {
  35. c, ok := b.(*h264FMTP)
  36. if !ok {
  37. return false
  38. }
  39. // test packetization-mode
  40. hpmode, hok := h.parameters["packetization-mode"]
  41. if !hok {
  42. return false
  43. }
  44. cpmode, cok := c.parameters["packetization-mode"]
  45. if !cok {
  46. return false
  47. }
  48. if hpmode != cpmode {
  49. return false
  50. }
  51. // test profile-level-id
  52. hplid, hok := h.parameters["profile-level-id"]
  53. if !hok {
  54. return false
  55. }
  56. cplid, cok := c.parameters["profile-level-id"]
  57. if !cok {
  58. return false
  59. }
  60. if !profileLevelIDMatches(hplid, cplid) {
  61. return false
  62. }
  63. return true
  64. }
  65. func (h *h264FMTP) Parameter(key string) (string, bool) {
  66. v, ok := h.parameters[key]
  67. return v, ok
  68. }