Hatena::Grouprubyist

takuma104のRuby/Rails日記

ツッコミ大歓迎!間違等ありましたらご指摘ください! / はてダはこちらで書いてます。

 | 

2008-03-12

MulticastなRTPを受信してRTPのヘッダ情報とか表示するサンプル

| 05:14 | MulticastなRTPを受信してRTPのヘッダ情報とか表示するサンプル - takuma104のRuby/Rails日記 を含むブックマーク はてなブックマーク - MulticastなRTPを受信してRTPのヘッダ情報とか表示するサンプル - takuma104のRuby/Rails日記 MulticastなRTPを受信してRTPのヘッダ情報とか表示するサンプル - takuma104のRuby/Rails日記 のブックマークコメント

かなりニッチなサンプルですが貼っておきます。parse_rtpはちょっと適当すぎますが、だいたいこんなもんです...。

#!/usr/bin/env ruby -wKU
require 'socket'
require 'ipaddr'

def parse_rtp(pkt)
  {
    :sequence => pkt[2..3].unpack('n')[0],
    :timestamp => pkt[4..7].unpack('N')[0] / 90000.0,
    :payload_length => pkt.length - 16,
  }
end

def receive_rtp(mcacst_addr, mcast_port)
  sock = UDPSocket.new

  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1) #!!!
  sock.bind(Socket::INADDR_ANY, mcast_port.to_i)

  ip =  IPAddr.new(mcacst_addr).hton + IPAddr.new("0.0.0.0").hton
  sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ip)

  loop do
    msg, info = sock.recvfrom(65536)
    rtpinfo = parse_rtp(msg)
    puts "time:%.3f seq:%d len:%d" % [rtpinfo[:timestamp],rtpinfo[:sequence],rtpinfo[:payload_length]]
  end
end

addr = ARGV.shift || "239.192.1.1" 
port = ARGV.shift || "5434"

receive_rtp(addr, port)

SO_REUSEADDRとSO_REUSEPORT

| 05:12 | SO_REUSEADDRとSO_REUSEPORT - takuma104のRuby/Rails日記 を含むブックマーク はてなブックマーク - SO_REUSEADDRとSO_REUSEPORT - takuma104のRuby/Rails日記 SO_REUSEADDRとSO_REUSEPORT - takuma104のRuby/Rails日記 のブックマークコメント

OSXで、QuickTime Broadcasterで配信したMulticastなストリームを、ローカルでRubyで受信しようとしたところ、bindでのErrno::EADDRINUSEで小一時間はまる。QT Broadcasterは、どうもマルチキャスト先のポート番号と同じものをbindしてしまうため、SO_REUSEADDRを指定してもだめっぽい。VLCとかでは、ローカルでちゃんと受信/再生できるので、どうやっているのかなあ、、とVLCのソースを読んでたら、SO_REUSEADDRなんか使っていなくて、SO_REUSEPORTを使っていた。Rubyで書くと

  sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEPORT, 1) #!!!

な感じ。これにしたら解決した。

トラックバック - http://rubyist.g.hatena.ne.jp/takuma104/20080312
 |