Created
March 19, 2014 17:50
-
-
Save 02strich/9647337 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket | |
import random | |
IP = "192.168.178.2" | |
SID = random.randint(0,10000) | |
CSEQ = 0 | |
class RtspSession(object): | |
def __init__(self, remote): | |
self.client_id = random.randint(0,10000) | |
self.req_id = 1 | |
self.session_id = None | |
self.server_ip = remote | |
self.server_port = None | |
self.ss = None | |
# connect | |
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
self.s.connect((remote, 5000)) | |
# do RTSP stuff | |
AnnounceRequest(self).send() | |
# extract server config | |
r = SetupRequest(self) | |
r.send() | |
self.session_id = r.session_id | |
for transport_option in r.transport_options: | |
if transport_option.startswith("server_port"): | |
self.server_port = int(transport_option[12:]) | |
RecordRequest(self).send() | |
def connect_stream(self): | |
if self.server_port is None: | |
return | |
self.ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
self.ss.connect((self.server_ip, self.server_port)) | |
def close(self): | |
if not self.ss is None: | |
self.ss.close() | |
self.s.close() | |
def volume(self, volume_val): | |
SetParameterRequest(self, {"volume": volume_val}).send() | |
def send_sample(self, samples): | |
print "blub: " + str(len(samples)) | |
header = "\x24\x00\x05\x8c\xF0\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | |
data = header + samples | |
self.ss.sendall(data) | |
class RtspRequest(object): | |
method = None | |
def __init__(self, session): | |
self.headers = {} | |
self.session = session | |
def send(self): | |
# get body | |
body = self.render_body() | |
# command line & mandatory headers | |
data = "%s rtsp://%s/%s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: iTunes/4.6 (Macintosh; U; PPC Mac OS X 10.3)\r\n" % (self.method, self.session.s.getpeername()[0], self.session.client_id, self.session.req_id) | |
# body length header | |
if body: | |
self.headers["Content-Length"] = len(body) | |
# other headers | |
for k,v in self.headers.iteritems(): | |
data += "%s: %s\r\n" % (k,v) | |
data += "\r\n" | |
# data | |
if body: | |
data += body | |
# send & receive | |
self.session.s.sendall(data) | |
response = self.session.s.recv(1000) | |
# increment sequence | |
self.session.req_id += 1 | |
# parse response | |
self.parse_response(response) | |
print "-------------" | |
print data | |
print "-------------" | |
print response | |
def render_body(self): | |
pass | |
def parse_response(self, response): | |
pass | |
class AnnounceRequest(RtspRequest): | |
method = "ANNOUNCE" | |
def __init__(self, session): | |
super(AnnounceRequest, self).__init__(session) | |
self.headers["Content-Type"] = "application/sdp" | |
def render_body(self): | |
return """v=0\r\no=iTunes %s 0 IN IP4 %s\r\ns=iTunes\r\nc=IN IP4 %s\r\nt=0 0\r\nm=audio 0 RTP/AVP 96\r\na=rtpmap:96 AppleLossless\r\na=fmtp:96 352 0 16 40 10 14 2 255 0 0 44100\r\n""" % (self.session.client_id, self.session.s.getpeername()[0], self.session.s.getsockname()[0]) | |
class SetupRequest(RtspRequest): | |
method = "SETUP" | |
def __init__(self, session): | |
super(SetupRequest, self).__init__(session) | |
self.headers["Transport"] = "RTP/AVP/UDP;unicast;interleaved=0-1;mode=record" | |
def parse_response(self, response): | |
self.session_id = None | |
for line in response.split("\r\n"): | |
# extract session ID | |
if line.startswith("Session: "): | |
self.session_id = line[9:] | |
# extract transport options | |
if line.startswith("Transport: "): | |
self.transport_options = line[11:].split(";") | |
class RecordRequest(RtspRequest): | |
method = "RECORD" | |
def __init__(self, session): | |
super(RecordRequest, self).__init__(session) | |
self.headers["Range"] = 'npt=0-' | |
self.headers['RTP-Info'] = "seq=0;rtptime=0" | |
self.headers['Session'] = self.session.session_id | |
class SetParameterRequest(RtspRequest): | |
method = "SET_PARAMETER" | |
def __init__(self, session, opts): | |
super(SetParameterRequest, self).__init__(session) | |
self.opts = opts | |
self.headers["Content-Type"] = 'text/parameters' | |
self.headers["Session"] = self.session.session_id | |
def render_body(self): | |
data = "" | |
for k, v in self.opts.iteritems(): | |
data += "%s: %s\r\n" % (k,v) | |
return data | |
session = RtspSession(IP) | |
session.volume("-10.0") | |
session.connect_stream() | |
with open("test.data", "rb") as f: | |
data = f.read(352 * 2 * 2) | |
while len(data) == 352 * 2 * 2: | |
session.send_sample(data) | |
data = f.read(352 * 2 * 2) | |
session.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment