def getFrameNum(self, filename):
     video = VideoStream(filename)
     frameNum = -1
     while frameNum != video.frameNbr():
         frameNum = video.frameNbr()
         video.nextFrame()
     return frameNum
Example #2
0
class ServerWorker:

	SETUP = 'SETUP'
	PLAY = 'PLAY'
	PAUSE = 'PAUSE'
	TEARDOWN = 'TEARDOWN'
	DESCRIBE = 'DESCRIBE'
	
	INIT = 0
	READY = 1
	PLAYING = 2
	state = INIT
	
	clientInfo = {}


	"""Initialization"""
	def __init__(self, clientInfo):
		self.clientInfo = clientInfo
		print "ServerWorker init done\n"


	"""Create RTSP thread"""
	def run(self):
		self.rtspThread = threading.Thread(target=self.receiveRtsp)
		self.rtspThread.start()
		print "ServerWorker run done\n"


	"""RTSP/TCP module"""
	def receiveRtsp(self):
		"""connect rtsp/tcp socket"""
		rtspSocket = self.clientInfo['rtspSocket'][0]
		print "ServerWorker RTSP/TCP socket connected\n"
		while True:
			receivedRtspDataJSON = rtspSocket.recv(256)
			if receivedRtspDataJSON:
				self.processRtsp(receivedRtspDataJSON)

	def processRtsp(self,receivedRtspDataJSON):
		"""Handle received RTSP request"""
		# json tp dict
		receivedRtspData = json.loads(receivedRtspDataJSON)
		self.action = receivedRtspData['action']

		# SETUP module
		if self.action == self.SETUP and self.state == self.INIT:

			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.transportProtocol = receivedRtspData['transportProtocol']
			self.rtpPort = receivedRtspData['rtpPort']
			
			# create a session
			self.session = randint(0, 65536)

			try:
				self.file = VideoStream(self.fileName)
				
				# set frame number to 0
				self.frameNbr = 0
				# set rtpError to 0 
				self.rtpError = 0
				# change state on server
				self.state = self.READY

				# send rtsp/tcp reply
				self.replyRtsp(200)

				print "ServerWorker SETUP"

			except IOError:
				self.replyRtsp(404)

			
		# PLAY module
		elif self.action == self.PLAY and self.state == self.READY:
			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.session = receivedRtspData['session']
			# change state on server
			self.state = self.PLAYING
			# connect RTP/UDP socket
			self.rtpScoket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
			self.playEvent = threading.Event()
			self.playEvent.clear()
			self.rtpThread = threading.Thread(target=self.rtpConnect)
			self.rtpThread.start()
			# send rtsp/tcp reply
			self.replyRtsp(200)

			print "ServerWorker PLAY"

		# PAUSE module
		elif self.action == self.PAUSE and self.state == self.PLAYING:
			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.session = receivedRtspData['session']
			# change state on server
			self.state = self.READY
			# stop playEvent
			self.playEvent.set()
			# send rtsp/tcp reply
			self.replyRtsp(200)
			# Added line to prevent ghost sockets
			self.rtpScoket.close()

			print "ServerWorker PAUSE"

		# TEARDOWN module
		elif self.action == self.TEARDOWN:
			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.session = receivedRtspData['session']
			# flag of RTP/UDP socket
			flag = 1
			try:
				# stop playEvent
				self.playEvent.set()
			except:
				flag = 0
				print 'Attention! No playback thread was created before teardown!'
			# send rtsp/tcp reply
			self.replyRtsp(200)
			# Close the RTP/UDP socket
			if flag == 1:
				self.rtpScoket.close()

			print "ServerWorker TEARDOWN"

		# DESCRIBE module
		elif self.action == self.DESCRIBE:
			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.session = receivedRtspData['session']
			# change state on server
			self.state = self.READY
			# stop playEvent
			self.playEvent.set()
			# send rtsp/tcp reply
			self.replyDescribeRtsp(200)
			# Added line to prevent ghost sockets
			self.rtpScoket.close()
			print "ServerWorker DESCRIBE"


	def replyDescribeRtsp(self, replyCode):
		"""Reply RTSP to client"""
		if replyCode == 200:
			# create dict
			dictReply = {}
			dictReply['rtspVersion'] = self.rtspVersion
			dictReply['replyCode'] = 200
			dictReply['replyAction'] = "OK"
			dictReply['CSeq'] = self.CSeq
			dictReply['session'] = self.session
			dictReply['Describe'] = "Describe"
			dictReply['stream'] = "Movie"
			dictReply['encoding'] = self.fileName.split('.')[1]
			# dict to JSON
			dictReplyJSON = json.dumps(dictReply)
			# connect rtsp/tcp socket
			rtspSocket = self.clientInfo['rtspSocket'][0]
			# send JSON to clinet
			rtspSocket.send(dictReplyJSON)
			#print
			print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\nStream: " + dictReply['stream'] + " Encoding: " + dictReply['encoding'] +"\n"


	def replyRtsp(self, replyCode):
		"""Reply RTSP to client"""
		if replyCode == 200:
			# create dict
			dictReply = {}
			dictReply['rtspVersion'] = self.rtspVersion
			dictReply['replyCode'] = 200
			dictReply['replyAction'] = "OK"
			dictReply['CSeq'] = self.CSeq
			dictReply['session'] = self.session
			# dict to JSON
			dictReplyJSON = json.dumps(dictReply)
			# connect rtsp/tcp socket
			rtspSocket = self.clientInfo['rtspSocket'][0]
			# send JSON to clinet
			rtspSocket.send(dictReplyJSON)
			#print
			print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\n"

		elif replyCode == 404:
			# create dict
			dictReply = {}
			dictReply['rtspVersion'] = self.rtspVersion
			dictReply['replyCode'] = 404
			dictReply['replyAction'] = "FILE NOT FOUND"
			dictReply['CSeq'] = self.CSeq
			dictReply['session'] = self.session
			# dict to JSON
			dictReplyJSON = json.dumps(dictReply)
			# connect rtsp/tcp socket
			rtspSocket = self.clientInfo['rtspSocket'][0]
			# send JSON to clinet
			rtspSocket.send(dictReplyJSON)
			#print
			print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\n"

		elif replyCode == 500:
			# create dict
			dictReply = {}
			dictReply['rtspVersion'] = self.rtspVersion
			dictReply['replyCode'] = 500
			dictReply['replyAction'] = "CONNECTION ERROR"
			dictReply['CSeq'] = self.CSeq
			dictReply['session'] = self.session
			# dict to JSON
			dictReplyJSON = json.dumps(dictReply)
			# connect rtsp/tcp socket
			rtspSocket = self.clientInfo['rtspSocket'][0]
			# send JSON to clinet
			rtspSocket.send(dictReplyJSON)
			#print
			print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\n"


	"""RTP/UDP module"""
	def rtpConnect(self):
		"""Send messages over UDP."""
		while True:
			# wait until current rtp has sent data
			self.playEvent.wait(0.05)
			# Stop sending if request is PAUSE or TEARDOWN
			if self.playEvent.isSet():
				break
			
			# RtpPacket arguments
			version = 2
			padding = 0
			extension = 0
			cc = 0
			seqnum = self.file.frameNbr()
			marker = 0
			pt = 26
			ssrc = 34

			payload = self.file.nextFrame()

			# if not finished playing
			if payload:	
				# create RtpPacket instance
				rtpPacket = RtpPacket()
				# encode Rtppacket
				rtpPacket.encode(version, padding, extension, cc, seqnum, marker, pt, ssrc, payload)
				# getPacket
				packet = rtpPacket.getPacket()
				# get the RTP/UDP address of client
				self.rtpAddress = self.clientInfo['rtspSocket'][1][0]
				try:
					self.rtpScoket.sendto(packet,(self.rtpAddress, self.rtpPort))
				except:
					self.rtpError += 1
					print "ServerWorker RTP/UDP Sending Error: %d" % self.rtpError
					self.replyRtsp(500)
			
			# if finished playing, inform client
			else:
				self.state = self.INIT
				self.finishPlaying(seqnum-1)
				
				break


	"""Finish playing function"""
	def finishPlaying(self, frameNbr):
		dictReply = {}
		dictReply['rtspVersion'] = self.rtspVersion
		dictReply['replyCode'] = 200
		dictReply['replyAction'] = "OK"
		dictReply['CSeq'] = self.CSeq
		dictReply['session'] = self.session
		dictReply['finish'] = frameNbr
		# dict to JSON
		dictReplyJSON = json.dumps(dictReply)
		# connect rtsp/tcp socket
		rtspSocket = self.clientInfo['rtspSocket'][0]
		# send JSON to clinet
		rtspSocket.send(dictReplyJSON)
		#print
		print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\n" + "Finish Playing Frame Number: " + str(dictReply['finish'])
		
		# Task 4 question 1: RTP loss rate
		rtpLossRate = self.rtpError*100/float(frameNbr)
		print "RTP packet loss rate is: %.3f %%" %(rtpLossRate)
Example #3
0
class ServerWorker:

	def __init__(self,clientInfo):
		self.clientInfo=clientInfo
		self.csession=0
		self.videoStream=None
		self.rtpPort=None
		self.rtpSocket=None
		self.sendRtpThread=None
		self.clientAddr=None
		

	def run(self):
		threading.Thread(target=self.recvRtspRequest).start()


	def recvRtspRequest(self):
		responseCode=RESPONSE_OK
		conn,(address,port)=self.clientInfo['rtspSocket']
		spath=os.path.dirname(os.path.realpath(sys.argv[0]))
		while True:
			try:
				data,tail=conn.recvfrom(RTSPBUFFERSIZE)
				if data:
					printLogToConsole(data)
					temp=data.split(MESSAGESEP)
					eventType=self.getEventTypeFromRTSP(temp)
					otherData=''
					if eventType==ActionEvents.EVSTEPUP:
						self.csession=''.join(str(uuid.uuid1()).split('-'))
						try:
							vFileName=spath+"\\"+self.getVidoeFileNameFromRTSP(temp)
							self.videoStream=VideoStream(vFileName)
							self.rtpPort=self.getRtpPortFromRTSP(temp)
							self.clientAddr=address
							otherData=MESSAGESEP+"Vsize: "+str(os.stat(vFileName).st_size)
						except IOError:
							responseCode=RESPONSE_NOTFOUND
					elif eventType==ActionEvents.EVPLAY:
						if self.rtpSocket is None:
							self.rtpSocket=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
						self.sendRtpThread=threading.Event()
						self.sendRtpThread.clear()
						threading.Thread(target=self.sendRtp).start()
					elif eventType==ActionEvents.EVPAUSE:
						if self.sendRtpThread is not None:
							self.sendRtpThread.set()# signal to stop the thread
					elif eventType==ActionEvents.EVTEARDOWN:
						if self.sendRtpThread is not None:
							self.sendRtpThread.set()
					elif eventType==ActionEvents.EVCLOSERTSPSOCKET:
						conn.close()
						conn=None
						break
					if conn is not None: conn.send(RTSPVERSION+' '+responseCode+MESSAGESEP+temp[1]+MESSAGESEP+"Session: "+str(self.csession)+otherData)
			except socket.error:
				print "\n"
				traceback.print_exc(file=sys.stdout)
			except:
				print "\n"
				traceback.print_exc(file=sys.stdout)


	def getEventTypeFromRTSP(self,request):
		dataFrame=request[0].split()
		return dataFrame[0][:len(dataFrame[0])-1]

		
	def getVidoeFileNameFromRTSP(self,request):
		fileName=request[0].split()[1]
		return fileName

		
	def getRtpPortFromRTSP(self,request):
		dataFrame=request[2].split(';')
		return int(dataFrame[1].split()[1])


	def sendRtp(self):
		while True:
			if self.sendRtpThread.isSet(): break
			time.sleep(0.05)# pause for 50 milliseconds
			try:
				vidata=self.videoStream.nextFrame()
				if vidata:
					rtpp=RtpPacket()
					rtpp.encode(2,0,0,0,self.videoStream.frameNbr(),0,26,6,vidata)
					self.rtpSocket.sendto(rtpp.getPacket(),(self.clientAddr,self.rtpPort))
				else:
					printLogToConsole("end of stream")
					self.sendRtpThread.set()
					self.rtpSocket.sendto(RTSPVERSION+' '+RESPONSE_OK_END+MESSAGESEP+"TotalFrame: "+str(self.videoStream.frameNbr())+MESSAGESEP+"Session: "+str(self.csession),(self.clientAddr,self.rtpPort))
					try:
						self.videoStream.file.close()
					except: printLogToConsole("close file error")
					break
			except:
				print "\n"
				traceback.print_exc(file=sys.stdout)
Example #4
0
class ServerWorker:

	SETUP = 'SETUP'
	PLAY = 'PLAY'
	PAUSE = 'PAUSE'
	TEARDOWN = 'TEARDOWN'
	
	INIT = 0
	READY = 1
	PLAYING = 2
	state = INIT
	
	clientInfo = {}


	"""Initialization"""
	def __init__(self, clientInfo):
		self.clientInfo = clientInfo
		print "ServerWorker init done\n"


	"""Create RTSP thread"""
	def run(self):
		self.rtspThread = threading.Thread(target=self.receiveRtsp)
		self.rtspThread.start()
		print "ServerWorker run done\n"



	"""RTSP/TCP module"""
	def receiveRtsp(self):
		"""connect rtsp/tcp socket"""
		rtspSocket = self.clientInfo['rtspSocket'][0]
		print "ServerWorker RTSP/TCP socket connected\n"
		while True:
			receivedRtspDataJSON = rtspSocket.recv(256)
			if receivedRtspDataJSON:
				self.processRtsp(receivedRtspDataJSON)

	def processRtsp(self,receivedRtspDataJSON):
		"""Handle received RTSP request"""
		# json tp dict
		receivedRtspData = json.loads(receivedRtspDataJSON)
		self.action = receivedRtspData['action']

		# SETUP module
		if self.action == self.SETUP and self.state == self.INIT:

			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.transportProtocol = receivedRtspData['transportProtocol']
			self.rtpPort = receivedRtspData['rtpPort']
			
			try:
				self.file = VideoStream(self.fileName)
				# create a session
				self.session = randint(0, 65536)
				# set frame number to 0
				self.frameNbr = 0
				# set rtpError to 0 
				self.rtpError = 0
				# change state on server
				self.state = self.READY
			except IOError:
				self.replyRtsp(self.FILE_NOT_FOUND_404, seq[1])

			# send rtsp/tcp reply
			self.replyRtsp(200)

			print "ServerWorker SETUP"

		# PLAY module
		elif self.action == self.PLAY and self.state == self.READY:
			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.session = receivedRtspData['session']
			# change state on server
			self.state = self.PLAYING
			# connect RTP/UDP socket
			self.rtpScoket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
			self.playEvent = threading.Event()
			self.playEvent.clear()
			self.rtpThread = threading.Thread(target=self.rtpConnect)
			self.rtpThread.start()
			# send rtsp/tcp reply
			self.replyRtsp(200)

			print "ServerWorker PLAY"

		# PAUSE module
		elif self.action == self.PAUSE and self.state == self.PLAYING:
			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.session = receivedRtspData['session']
			# change state on server
			self.state = self.READY
			# stop playEvent
			self.playEvent.set()
			# send rtsp/tcp reply
			self.replyRtsp(200)
			# Added line to prevent ghost sockets
			self.rtpScoket.close()

			print "ServerWorker PAUSE"

		# TEARDOWN module
		elif self.action == self.TEARDOWN:
			self.fileName = receivedRtspData['fileName']
			self.rtspVersion = receivedRtspData['rtspVersion']
			self.CSeq = receivedRtspData['CSeq']
			self.session = receivedRtspData['session']
			# flag of RTP/UDP socket
			flag = 1
			try:
				# stop playEvent
				self.playEvent.set()
			except:
				flag = 0
				print 'Attention! No playback thread was created before teardown!'
			# send rtsp/tcp reply
			self.replyRtsp(200)
			# Close the RTP/UDP socket
			if flag == 1:
				self.rtpScoket.close()

			print "ServerWorker TEARDOWN"


	def replyRtsp(self, replyCode):
		"""Reply RTSP to client"""
		if replyCode == 200:
			# create dict
			dictReply = {}
			dictReply['rtspVersion'] = self.rtspVersion
			dictReply['replyCode'] = 200
			dictReply['replyAction'] = "OK"
			dictReply['CSeq'] = self.CSeq
			dictReply['session'] = self.session
			# dict to JSON
			dictReplyJSON = json.dumps(dictReply)
			# connect rtsp/tcp socket
			rtspSocket = self.clientInfo['rtspSocket'][0]
			# send JSON to clinet
			rtspSocket.send(dictReplyJSON)
			#print
			print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\n"

		elif replyCode == 404:
			# create dict
			dictReply = {}
			dictReply['rtspVersion'] = self.rtspVersion
			dictReply['replyCode'] = 404
			dictReply['replyAction'] = "FILE NOT FOUND"
			dictReply['CSeq'] = self.CSeq
			dictReply['session'] = self.session
			# dict to JSON
			dictReplyJSON = json.dumps(dictReply)
			# connect rtsp/tcp socket
			rtspSocket = self.clientInfo['rtspSocket'][0]
			# send JSON to clinet
			rtspSocket.send(dictReplyJSON)
			#print
			print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\n"

		elif replyCode == 500:
			# create dict
			dictReply = {}
			dictReply['rtspVersion'] = self.rtspVersion
			dictReply['replyCode'] = 500
			dictReply['replyAction'] = "CONNECTION ERROR"
			dictReply['CSeq'] = self.CSeq
			dictReply['session'] = self.session
			# dict to JSON
			dictReplyJSON = json.dumps(dictReply)
			# connect rtsp/tcp socket
			rtspSocket = self.clientInfo['rtspSocket'][0]
			# send JSON to clinet
			rtspSocket.send(dictReplyJSON)
			#print
			print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\n"



	"""RTP/UDP module"""
	def rtpConnect(self):
		"""Send messages over UDP."""
		while True:
			# wait until current rtp has sent data
			self.playEvent.wait(0.05)
			# Stop sending if request is PAUSE or TEARDOWN
			if self.playEvent.isSet():
				break
			
			# RtpPacket arguments
			version = 2
			padding = 0
			extension = 0
			cc = 0
			seqnum = self.file.frameNbr()
			marker = 0
			pt = 26
			ssrc = 34

			payload = self.file.nextFrame()

			# if not finished playing
			if payload:	
				# create RtpPacket instance
				rtpPacket = RtpPacket()
				# encode Rtppacket
				rtpPacket.encode(version, padding, extension, cc, seqnum, marker, pt, ssrc, payload)
				# getPacket
				packet = rtpPacket.getPacket()
				# get the RTP/UDP address of client
				self.rtpAddress = self.clientInfo['rtspSocket'][1][0]
				try:
					self.rtpScoket.sendto(packet,(self.rtpAddress, self.rtpPort))
				except:
					self.rtpError += 1
					print "ServerWorker RTP/UDP Sending Error: %d" % self.rtpError
			
			# if finished playing, inform client
			else:
				self.state = self.INIT
				self.finishPlaying(seqnum-1)
				
				break

				"""Terminate thread. Problem with invalid thread id"""
				self._async_raise(self.rtpThread.ident, SystemExit)


	"""Finish playing function"""
	def finishPlaying(self, frameNbr):
		dictReply = {}
		dictReply['rtspVersion'] = self.rtspVersion
		dictReply['replyCode'] = 200
		dictReply['replyAction'] = "OK"
		dictReply['CSeq'] = self.CSeq
		dictReply['session'] = self.session
		dictReply['finish'] = frameNbr
		# dict to JSON
		dictReplyJSON = json.dumps(dictReply)
		# connect rtsp/tcp socket
		rtspSocket = self.clientInfo['rtspSocket'][0]
		# send JSON to clinet
		rtspSocket.send(dictReplyJSON)
		#print
		print dictReply['rtspVersion'] + " " + str(dictReply['replyCode']) + " " + dictReply['replyAction'] + "\nCSeq: " + str(dictReply['CSeq']) + "\nSession: " + str(dictReply['session']) +"\n" + "Finish Playing Frame Number: " + str(dictReply['finish'])


	"""Raise exception to terminate thread"""
	def _async_raise(self, tid, exctype):
		if not inspect.isclass(exctype):
			exctype = type(exctype)
		res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
		if res == 0:
			raise ValueError("invalid thread id")
		elif res != 1:
			# if it returns a number greater than one, you're in trouble, 
			# and you should call it again with exc=NULL to revert the effect
			ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
			raise SystemError("PyThreadState_SetAsyncExc failed")