Class: SippyCup::Media

Inherits:
Object
  • Object
show all
Defined in:
lib/sippy_cup/media.rb,
lib/sippy_cup/media/rtp_header.rb,
lib/sippy_cup/media/rtp_payload.rb,
lib/sippy_cup/media/dtmf_payload.rb,
lib/sippy_cup/media/pcmu_payload.rb

Defined Under Namespace

Classes: DTMFPayload, PCMUPayload, RTPHeader, RTPPayload

Constant Summary collapse

VALID_STEPS =
%w{silence dtmf}.freeze
USEC =
1_000_000
MSEC =
1_000

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(from_addr, from_port, to_addr, to_port, generator = PCMUPayload) ⇒ Media

Returns a new instance of Media.



13
14
15
16
17
# File 'lib/sippy_cup/media.rb', line 13

def initialize(from_addr, from_port, to_addr, to_port, generator = PCMUPayload)
  @from_addr, @to_addr = IPAddr.new(from_addr), IPAddr.new(to_addr)
  @from_port, @to_port, @generator = from_port, to_port, generator
  reset!
end

Instance Attribute Details

#sequenceObject

Returns the value of attribute sequence.



11
12
13
# File 'lib/sippy_cup/media.rb', line 11

def sequence
  @sequence
end

Instance Method Details

#<<(input) ⇒ Object



23
24
25
26
# File 'lib/sippy_cup/media.rb', line 23

def <<(input)
  get_step input # validation
  @sequence << input
end

#compile!Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/sippy_cup/media.rb', line 32

def compile!
  sequence_number = 0
  start_time = Time.now
  @pcap_file = PacketFu::PcapFile.new
  timestamp = 0
  elapsed = 0
  ssrc_id = rand 2147483648
  first_audio = true

  @sequence.each do |input|
    action, value = get_step input

    case action
    when 'silence'
      # value is the duration in milliseconds
      # append that many milliseconds of silent RTP audio
      (value.to_i / @generator::PTIME).times do
        packet = new_packet
        rtp_frame = @generator.new

        # The first RTP audio packet should have the marker bit set
        if first_audio
          rtp_frame.rtp_marker = 1
          first_audio = false
        end

        rtp_frame.rtp_timestamp = timestamp += rtp_frame.timestamp_interval
        elapsed += rtp_frame.ptime
        rtp_frame.rtp_sequence_num = sequence_number += 1
        rtp_frame.rtp_ssrc_id = ssrc_id
        packet.headers.last.body = rtp_frame.to_bytes
        packet.recalc
        @pcap_file.body << get_pcap_packet(packet, next_ts(start_time, elapsed))
      end
    when 'dtmf'
      # value is the DTMF digit to send
      # append that RFC2833 digit
      # Assume 0.25 second duration for now
      count = 250 / DTMFPayload::PTIME
      count.times do |i|
        packet = new_packet
        dtmf_frame = DTMFPayload.new value
        dtmf_frame.rtp_marker = 1 if i == 0
        dtmf_frame.rtp_timestamp = timestamp # Is this correct? This is what Blink does...
        #dtmf_frame.rtp_timestamp = timestamp += dtmf_frame.timestamp_interval
        dtmf_frame.rtp_sequence_num = sequence_number += 1
        dtmf_frame.rtp_ssrc_id = ssrc_id
        dtmf_frame.end_of_event = (count == i) # Last packet?
        packet.headers.last.body = dtmf_frame.to_bytes
        packet.recalc
        @pcap_file.body << get_pcap_packet(packet, next_ts(start_time, elapsed))
      end
      # Now bump up the timestamp to cover the gap
      timestamp += count * DTMFPayload::TIMESTAMP_INTERVAL
    else
    end
  end
  @pcap_file
end

#empty?Boolean

Returns:

  • (Boolean)


28
29
30
# File 'lib/sippy_cup/media.rb', line 28

def empty?
  @sequence.empty?
end

#reset!Object



19
20
21
# File 'lib/sippy_cup/media.rb', line 19

def reset!
  @sequence = []
end