def hash_swf(url, age=30): hash = ffi.new("unsigned char[]", 32) size = ffi.new("unsigned int*") url = bytes(url, "utf8") res = librtmp.RTMP_HashSWF(url, size, hash, age) if res == 0: hash = hexlify(ffi.buffer(hash, 32)[:]) size = size[0] return str(hash, "utf8"), size else: raise RTMPError("Failed to hash SWF")
def read_packet(self): """Reads a RTMP packet from the server. Returns a :class:`RTMPPacket`. Raises :exc:`RTMPError` on error. Raises :exc:`RTMPTimeoutError` on timeout. Usage:: >>> packet = conn.read_packet() >>> packet.body b'packet body ...' """ packet = ffi.new("RTMPPacket*") packet_complete = False while not packet_complete: res = librtmp.RTMP_ReadPacket(self.rtmp, packet) if res < 1: if librtmp.RTMP_IsTimedout(self.rtmp): raise RTMPTimeoutError("Timed out while reading packet") else: raise RTMPError("Failed to read packet") packet_complete = packet.m_nBytesRead == packet.m_nBodySize return RTMPPacket._from_pointer(packet)
def parse_url(url): protocol = ffi.new("int*") hostname = AVal("") port = ffi.new("unsigned int*") playpath = AVal("") app = AVal("") res = librtmp.RTMP_ParseURL(bytes(url, "utf8"), protocol, hostname.aval, port, playpath.aval, app.aval) if res < 1: result = RTMPURL(0, "", 0, "", "") else: result = RTMPURL(protocol[0], str(hostname.value, "utf8"), port[0], str(playpath.value, "utf8"), str(app.value, "utf8")) return result
def value(self, value): if isinstance(value, integer_types): value = str(value) if isinstance(value, string_types): value = bytes(value, "utf8") elif isinstance(value, bool): value = str(value).lower() self.value_str = ffi.new("char[]", value) self.aval.av_val = self.value_str self.aval.av_len = len(value)
def __init__(self, type, format, channel, timestamp=0, absolute_timestamp=False, body=None): self.packet = ffi.new("RTMPPacket*") self.type = type self.format = format self.channel = channel self.timestamp = timestamp self.absolute_timestamp = absolute_timestamp if not body: body = b"" self.body = body
def _log_callback(level, fmt, args): buf = ffi.new("char[]", 2048) C.vsprintf(buf, fmt, args) msg = ffi.string(buf) msg = msg.decode("utf8", "ignore") for callback in _log_callbacks: callback(level, msg) if hasattr(_log_output, "write") and level <= _log_level: _log_output.write(msg + "\n")
def decode_amf(body): obj = ffi.new("AMFObject*") res = librtmp.AMF_Decode(obj, body, len(body), 0) if res == ffi.NULL: raise AMFError("Unable to decode AMF data") rval = [] prop_count = librtmp.AMF_CountProp(obj) for i in range(prop_count): prop = librtmp.AMF_GetProp(obj, ffi.NULL, i) val = _decode_prop(prop) rval.append(val) return rval
def _decode_prop_obj(prop): obj = ffi.new("AMFObject*") librtmp.AMFProp_GetObject(prop, obj) prop_count = librtmp.AMF_CountProp(obj) for i in range(prop_count): prop = librtmp.AMF_GetProp(obj, ffi.NULL, i) key = AVal() librtmp.AMFProp_GetName(prop, key.aval) key = key.value.decode("utf8", "ignore") value = _decode_prop(prop) yield key, value
def read(self, size): """Attempts to read data from the stream. :param size: int, The maximum amount of bytes to read. Raises :exc:`IOError` on error. """ if not self._buf or len(self._buf) != size: self._buf = ffi.new("char[]", size) self._view = ffi.buffer(self._buf, size) res = librtmp.RTMP_Read(self.client.rtmp, self._buf, size) if res < 0: raise IOError("Failed to read data") return self._view[:res]
def read(self, size): """Attempts to read data from the stream. :param size: int, The maximum amount of bytes to read. Raises :exc:`IOError` on error. """ # If enabled tell the server that our buffer can fit the whole # stream, this often increases throughput alot. if self._update_buffer and not self._updated_buffer and self.duration: self.update_buffer((self.duration * 1000) + 5000) self._updated_buffer = True if not self._buf or len(self._buf) != size: self._buf = ffi.new("char[]", size) self._view = ffi.buffer(self._buf, size) res = librtmp.RTMP_Read(self.client.rtmp, self._buf, size) if res < 0: raise IOError("Failed to read data") return self._view[:res]
def _create_buffer(size): pbuf = ffi.new("char[]", size) pend = pbuf + size buf = ffi.buffer(pbuf, size) return pbuf, pend, buf
def __init__(self, value=None): self.aval = ffi.new("AVal *") if value is not None: self.value = value