- 12th Jul 2024
- 17:47 pm
Your first task is to implement the RTSP protocol on the client side. To do this, you need to complete the functions that are called when the user clicks on the buttons on the user interface. When the client starts, it also opens the RTSP socket to the server. Use this socket for sending all RTSP requests. You will need to implement the actions for the following request types.
SETUP
- Send a SETUP request to the server. You will need to insert the Transport header in which you specify the port for the RTP data socket you just created.
- Read the server’s response and parse the Session header (from the response) to get the RTSP session ID.
- Create a datagram socket for receiving RTP data and set the timeout on the socket to 0.5 seconds.
PLAY
- Send a PLAY request. You must insert the Session header and use the session ID returned in the SETUP response. You must not put the Transport header in this request.
- Read the server's response.
- As media is received, calculate statistics about the session, and print them to the terminal. Relevant statistics are the RTP packet loss rate and the video data rate (in bits per second).
PAUSE
- Send a PAUSE request. You must insert the Session header and use the session ID returned in the SETUP response. You must not put the Transport header in this request.
- Read the server's response.
TEARDOWN
- Send a TEARDOWN request. You must insert the Session header and use the session ID returned in the SETUP response. You must not put the Transport header in this request.
Computer Networks - Get Assignment Solution And Online Tutoring Help
Please note that this is a sample assignment solved by our Python Experts. These solutions are intended to be used for research and reference purposes only. If you can learn any concepts by going through the reports and code, then our Python Tutors would be very happy.
- To download the complete solution along with Code, Report and screenshots - Please visit our Python Assignment Sample Solution page
- Reach out to our Python Tutors to get online tutoring related to this assignment and get your doubts cleared
- You can check the partial solution for this assignment in this blog below
Free Assignment Solution - Computer Networks
from tkinter import *
import tkinter.messagebox
from PIL import Image, ImageTk
import socket, threading, sys, traceback, os
from RtpPacket import RtpPacket
CACHE_FILE_NAME = "cache-"
CACHE_FILE_EXT = ".jpg"
class Client:
INIT = 0
READY = 1
PLAYING = 2
state = INIT
SETUP = 0
PLAY = 1
PAUSE = 2
TEARDOWN = 3
# Initiation..
def __init__(self, master, serveraddr, serverport, rtpport, filename):
self.master = master
self.master.protocol("WM_DELETE_WINDOW", self.handler)
self.createWidgets()
self.serverAddr = serveraddr
self.serverPort = int(serverport)
self.rtpPort = int(rtpport)
self.fileName = filename
self.rtspSeq = 0
self.sessionId = 0
self.requestSent = -1
self.teardownAcked = 0
self.connectToServer()
self.frameNbr = 0
def createWidgets(self):
"""Build GUI."""
# Create Setup button
self.setup = Button(self.master, width=20, padx=3, pady=3)
self.setup["text"] = "Setup"
self.setup["command"] = self.setupMovie
self.setup.grid(row=1, column=0, padx=2, pady=2)
# Create Play button
self.start = Button(self.master, width=20, padx=3, pady=3)
self.start["text"] = "Play"
self.start["command"] = self.playMovie
self.start.grid(row=1, column=1, padx=2, pady=2)
# Create Pause button
self.pause = Button(self.master, width=20, padx=3, pady=3)
self.pause["text"] = "Pause"
self.pause["command"] = self.pauseMovie
self.pause.grid(row=1, column=2, padx=2, pady=2)
# Create Teardown button
self.teardown = Button(self.master, width=20, padx=3, pady=3)
self.teardown["text"] = "Teardown"
self.teardown["command"] = self.exitClient
self.teardown.grid(row=1, column=3, padx=2, pady=2)
# Create a label to display the movie
self.label = Label(self.master, height=19)
self.label.grid(
row=0, column=0, columnspan=4, sticky=W + E + N + S, padx=5, pady=5
)
def setupMovie(self):
"""Setup button handler."""
if self.state == self.INIT:
self.sendRtspRequest(self.SETUP)
def exitClient(self):
"""Teardown button handler."""
self.sendRtspRequest(self.TEARDOWN)
self.master.destroy() # Close the gui window
os.remove(
CACHE_FILE_NAME + str(self.sessionId) + CACHE_FILE_EXT
) # Delete the cache image from video
def pauseMovie(self):
"""Pause button handler."""
if self.state == self.PLAYING:
self.sendRtspRequest(self.PAUSE)
def playMovie(self):
"""Play button handler."""
if self.state == self.READY:
# Create a new thread to listen for RTP packets
threading.Thread(target=self.listenRtp).start()
self.playEvent = threading.Event()
self.playEvent.clear()
self.sendRtspRequest(self.PLAY)
def listenRtp(self):
"""Listen for RTP packets."""
while True:
try:
data = self.rtpSocket.recv(20480)
if data:
rtpPacket = RtpPacket()
rtpPacket.decode(data)
currFrameNbr = rtpPacket.seqNum()
print("Current Seq Num: " + str(currFrameNbr))
# -------------
# TO COMPLETE
# -------------
# Statistics about the session are printed here
# ...
if currFrameNbr > self.frameNbr: # Discard the late packet
self.frameNbr = currFrameNbr
self.updateMovie(self.writeFrame(rtpPacket.getPayload()))
except:
# Stop listening upon requesting PAUSE or TEARDOWN
if self.playEvent.isSet():
break
# Upon receiving ACK for TEARDOWN request,
# close the RTP socket
if self.teardownAcked == 1:
self.rtpSocket.shutdown(socket.SHUT_RDWR)
self.rtpSocket.close()
break
def writeFrame(self, data):
"""Write the received frame to a temp image file. Return the image file."""
cachename = CACHE_FILE_NAME + str(self.sessionId) + CACHE_FILE_EXT
file = open(cachename, "wb")
file.write(data)
file.close()
return cachename
def updateMovie(self, imageFile):
"""Update the image file as video frame in the GUI."""
photo = ImageTk.PhotoImage(Image.open(imageFile))
self.label.configure(image=photo, height=288)
self.label.image = photo
def connectToServer(self):
"""Connect to the Server. Start a new RTSP/TCP session."""
self.rtspSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self.rtspSocket.connect((self.serverAddr, self.serverPort))
except:
tkMessageBox.showwarning(
"Connection Failed", "Connection to '%s' failed." % self.serverAddr
)
def sendRtspRequest(self, requestCode):
"""Send RTSP request to the server."""
# -------------
# TO COMPLETE
# -------------
# Setup request
if requestCode == self.SETUP and self.state == self.INIT:
threading.Thread(target=self.recvRtspReply).start()
# Update RTSP sequence number.
self.rtspSeq = 1
# Write the RTSP request to be sent.
request = (
"SETUP "
+ self.fileName
+ " RTSP/1.0\nCSeq "
+ str(self.rtspSeq)
+ "\nTransport RTSP/UDP; client_port= "
+ str(self.rtpPort)
)
# Keep track of the sent request.
self.requestSent = self.SETUP
# Play request
elif requestCode == self.PLAY and self.state == self.READY:
# Update RTSP sequence number.
self.rtspSeq = self.rtspSeq + 1
# Write the RTSP request to be sent.
request = (
"PLAY "
+ self.fileName
+ " RTSP/1.0\nCSeq "
+ str(self.rtspSeq)
+ "\nSession: "
+ str(self.sessionId)
)
# Keep track of the sent request.
self.requestSent = self.PLAY
# Pause request
elif requestCode == self.PAUSE and self.state == self.PLAYING:
# Update RTSP sequence number.
self.rtspSeq = self.rtspSeq + 1
# Write the RTSP request to be sent.
request = (
"PAUSE "
+ self.fileName
+ " RTSP/1.0\nCSeq "
+ str(self.rtspSeq)
+ "\nSession: "
+ str(self.sessionId)
)
# Keep track of the sent request.
self.requestSent = self.PAUSE
# Teardown request
elif requestCode == self.TEARDOWN and not self.state == self.INIT:
# Update RTSP sequence number.
self.rtspSeq = self.rtspSeq + 1
# Write the RTSP request to be sent.
request = (
"TEARDOWN "
+ self.fileName
+ " RTSP/1.0\nCSeq "
+ str(self.rtspSeq)
+ "\nSession: "
+ str(self.sessionId)
)
# Keep track of the sent request.
self.requestSent = self.TEARDOWN
else:
return
# Send the RTSP request using rtspSocket.
self.rtspSocket.send(request.encode())
print("\nData sent:\n" + request)
def recvRtspReply(self):
"""Receive RTSP reply from the server."""
while True:
reply = self.rtspSocket.recv(1024)
if reply:
self.parseRtspReply(reply.decode("utf-8"))
# Close the RTSP socket upon requesting Teardown
if self.requestSent == self.TEARDOWN:
self.rtspSocket.shutdown(socket.SHUT_RDWR)
self.rtspSocket.close()
break
def parseRtspReply(self, data):
"""Parse the RTSP reply from the server."""
lines = data.split("\n")
seqNum = int(lines[1].split(" ")[1])
# Process only if the server reply's sequence number is the same as the request's
if seqNum == self.rtspSeq:
session = int(lines[2].split(" ")[1])
# New RTSP session ID
if self.sessionId == 0:
self.sessionId = session
# Process only if the session ID is the same
if self.sessionId == session:
if int(lines[0].split(" ")[1]) == 200:
if self.requestSent == self.SETUP:
# -------------
# TO COMPLETE
# -------------
# Update RTSP state.
self.state = self.READY
# Open RTP port.
self.openRtpPort()
elif self.requestSent == self.PLAY:
self.state = self.PLAYING
elif self.requestSent == self.PAUSE:
self.state = self.READY
# The play thread exits. A new thread is created on resume.
self.playEvent.set()
elif self.requestSent == self.TEARDOWN:
self.state = self.INIT
# Flag the teardownAcked to close the socket.
self.teardownAcked = 1
def openRtpPort(self):
"""Open RTP socket binded to a specified port."""
# -------------
# TO COMPLETE
# -------------
# Create a new datagram socket to receive RTP packets from the server
self.rtpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Set the timeout value of the socket to 0.5sec
self.rtpSocket.settimeout(0.5)
try:
# Bind the socket to the address using the RTP port given by the client user
self.rtpSocket.bind(("", self.rtpPort))
except:
tkMessageBox.showwarning(
"Unable to Bind", "Unable to bind PORT=%d" % self.rtpPort
)
def handler(self):
"""Handler on explicitly closing the GUI window."""
self.pauseMovie()
if tkMessageBox.askokcancel("Quit?", "Are you sure you want to quit?"):
self.exitClient()
else: # When the user presses cancel, resume playing.
self.playMovie()
Get the best Computer Networks assignment help and tutoring services from our experts now!
About The Author - Dr. Rajesh Mehta
Dr. Rajesh Mehta is a seasoned software engineer with extensive expertise in network protocols and real-time streaming technologies. He excels in implementing and optimizing the Real-Time Streaming Protocol (RTSP) on client systems to enhance media delivery and user experience. Dr. Mehta's proficiency spans across setting up RTSP communications, handling media playback, and ensuring robust session management.