예제 #1
0
class TestServer:
    def __init__(self, client, dqID):
        self.dqID = dqID
        self.fileName = "../Server/svc.file"
        self.pack = packet.packet(self.fileName, 400, 177, dqID)
        self.client = client
        self.serverLog = Log("serverLog.txt")

    def startSend(self):
        lossFile = file("lost_" + str(self.dqID) + ".txt")
        lineContent = lossFile.readline()
        if lineContent:
            lossPktNo = int(lineContent)
        else:
            lossPktNo = -1
        one_packet = self.pack.get_one_packet()
        curPktNo = 1
        self.bEnd = False
        self.bPause = False
        while one_packet and not self.bEnd:
            if curPktNo == lossPktNo:
                #remove it
                #print "remove pktno ", curPktNo
                lineContent = lossFile.readline()
                if lineContent:
                    try:
                        lossPktNo = int(lineContent)
                    except:
                        lossPktNo = -1
                else:
                    lossPktNo = -1
            else:
                #deliver it to client
                self.client.receive_one_packet(one_packet)
            if self.dqID == 16:
                pass
            elif self.dqID == 1:
                time.sleep(0.01)
            else:
                time.sleep(0.015)
            self.serverLog.LogStr("pktNo %d len %d" %
                                  (curPktNo, len(one_packet)))
            curPktNo += 1
            one_packet = self.pack.get_one_packet()
            while self.bPause and not self.bEnd:
                time.sleep(0.1)
            time.sleep(0.01)

    def stopSend(self):
        self.bEnd = True

    def pauseSend(self):
        self.bPause = True

    def resumeSend(self):
        self.bPause = False
예제 #2
0
class Client(object):
    def __init__(self):
        self.dataChannel = None
        self.ctlChannel = None
        self.ctlChannel = ClientControl(2, self.freqAssignCB,
                                        self.freqReleaseACKCB)
        self.stateLock = threading.Lock()
        self.state = Idle
        self.log = Log('ClientLog.txt')
        pass

    def startDataChannel(self, dataWidth, dqID):
        self.log.LogStr("start data channel")

        if fake:
            self.dataChannel = ClientDataFake(dataWidth, dqID)
        else:
            self.dataChannel = ClientData(dataWidth, dqID)
        self.dataChannel.start()

    def endDataChannel(self):
        if self.dataChannel:
            self.log.LogStr("stop data channel")
            self.dataChannel.stop()
            self.dataChannel.deconstruction()
            del self.dataChannel
            self.dataChannel = None
        else:
            self.log.LogStr("endDataChannel but dataChannel is none")

    def freqAssignThreadCB(self, width):
        self.log.LogStr("freqAssignThread call callback width %d" % width)
        self.stateLock.acquire()
        self.log.LogStr("the state is %d" % (self.state))
        if width == 1:
            dataWidth = 80
            dqID = 16
        elif width == 2:
            dataWidth = 64
            dqID = 1
        else:
            dataWidth = 48
            dqID = 0

        if self.state == GetFreq:
            self.endCtlChannel()
            self.startDataChannel(dataWidth, dqID)
            self.state = StartData
        self.stateLock.release()

    def freqReleaseACKCB(self, payload):
        print "receive freq release ack"
        self.stateLock.acquire()
        if self.state == FreqRelease:
            self.endCtlChannel()
            self.ctlChannel.finishFreqReq()
            self.state = Idle
        self.stateLock.release()

    def userInteractThreadCB(self):
        while True:
            command = raw_input("command:")
            if command == 'start':
                self.stateLock.acquire()
                if self.state == Idle:
                    self.startCtlChannel()
                    self.sendCtlChannelRequest()
                    self.state = WaitAssign
                    self.freqReqTimer = Timer(TimerDuration,
                                              self.freqReqTimeoutCB)
                    self.freqReqTimer.start()
                self.stateLock.release()
            elif command == 'end':
                self.stateLock.acquire()
                if self.state == WaitAssign:
                    self.ctlChannel.sendFreqRelease()
                elif self.state == GetFreq:
                    self.ctlChannel.sendFreqRelease()
                elif self.state == StartData:
                    self.endDataChannel()
                    time.sleep(3)
                    self.startCtlChannel()
                    self.ctlChannel.sendFreqRelease()
                else:
                    continue
                self.state = FreqRelease
                self.stateLock.release()
                self.freqReleaseTimer = Timer(TimerDuration,
                                              self.freqReleaseTimeoutCB)
                self.freqReleaseTimer.start()
            elif command == 'quit':
                self.stateLock.acquire()
                if self.state == Idle:
                    self.ctlChannel = None
                    break
                self.stateLock.release()
                break
            elif command == "help":
                print "start: start control channel and send request"
                print "end: end control channel and data channel"
                print "quit: end the client"
                print "help: show this message"

    def freqReqTimeoutCB(self):
        print "freq request timeout"
        self.stateLock.acquire()
        if self.state == WaitAssign:
            self.sendCtlChannelRequest()
            self.freqReqTimer = Timer(TimerDuration, self.freqReqTimeoutCB)
            self.freqReqTimer.start()
        self.stateLock.release()

    def freqReleaseTimeoutCB(self):
        print "freq release timeout"
        self.stateLock.acquire()
        if self.state == FreqRelease:
            self.ctlChannel.sendFreqRelease()
            self.freqReleaseTimer = Timer(TimerDuration,
                                          self.freqReleaseTimeoutCB)
            self.freqReleaseTimer.start()
        self.stateLock.release()

    def freqAssignCB(self, width):  #1 is big 2 is small
        self.stateLock.acquire()
        if self.state == WaitAssign:
            self.freqAssignThread = threading.Thread(
                target=self.freqAssignThreadCB, args=[width])
            self.freqAssignThread.start()
            self.state = GetFreq
        self.stateLock.release()

    def startCtlChannel(self):
        print "start ctl channel"
        self.ctlChannel.construct()
        self.ctlChannel.start()

    def sendCtlChannelRequest(self):
        if self.ctlChannel:
            print "send control channel request"
            self.ctlChannel.sendFreqReq()

    def endCtlChannel(self):
        print "end ctl channel"
        self.ctlChannel.stop()
        self.ctlChannel.deconstruct()

    def endAll(self):
        if self.ctlChannel:
            self.endCtlChannel()
            self.ctlChannel = None
        if self.dataChannel:
            self.endDataChannel()

    def reqTimeoutCB(self):
        self.timeoutNumber += 1
        if self.state != 1:
            return
        if self.timeoutNumber > 10:
            self.state = 3
        else:
            self.state = 0
        self.dealWithStateMachine()
예제 #3
0
class unpacket:
    def __init__(self):
        self.nals = []
        self.next_rtp = None
        self.rtp_con = threading.Condition()
        self.rtp_buffer = []
        self.rtp_end = False
        self.unpacketLog = Log("unpacketLog.txt")

    def get_one_rtp(self):
        self.rtp_con.acquire()
        while len(self.rtp_buffer) == 0:
            if self.rtp_end:
                self.rtp_con.release()
                return None
            #wait will release the contition and acquire it after time expire
            self.rtp_con.wait(1)
        one_rtp = self.rtp_buffer[0]
        self.rtp_buffer = self.rtp_buffer[1:]
        self.rtp_con.release()
        return one_rtp

    def put_one_rtp(self, rtp):
        self.rtp_con.acquire()
        self.rtp_buffer.append(rtp)
        self.rtp_con.notify()
        self.rtp_con.release()

    def end_rtp(self):
        self.rtp_end = True

    def get_rtp_type(self, rtp_payload):
        fb = struct.unpack('!B', rtp_payload[0:1])[0]
        rtp_type = fb & 31
        return rtp_type

    def extract_nal_from_nor_rtp(self, rtp_payload):
        return rtp_payload

    def extract_nal_from_fu_a_rtp(self, rtp_payloads, rtps):
        nal = ''
        if not check_rtp_fu_as(rtps):
            self.unpacketLog.LogStr('fu check error')
            return nal
        self.unpacketLog.LogStr('fu check succeed')
        for i in range(len(rtp_payloads)):
            nal += rtp_payloads[i][2:]
        return nal

    def extract_nal_from_stap_a_rtp(self, rtp_payload):
        rtp_payload = rtp_payload[1:]
        nals = []
        while len(rtp_payload) > 0:
            now_nal_size = struct.unpack('!H', rtp_payload[0:2])[0]
            nals.append(rtp_payload[2:now_nal_size + 2])
            rtp_payload = rtp_payload[now_nal_size + 2:]
        self.unpacketLog.LogStr('extract nal from stap, nal number: ' +
                                str(len(nals)))
        return nals

    def get_one_nal(self):
        #pdb.set_trace()
        if len(self.nals) > 0:
            res = self.nals[0]
            self.nals = self.nals[1:]
            return res
        else:
            if self.next_rtp == None:
                now_rtp = self.get_one_rtp()
                if now_rtp == None:
                    return None
            else:
                now_rtp = self.next_rtp
                self.next_rtp = None
            header_len = get_rtp_header_len(now_rtp)
            now_payload = now_rtp[header_len:]
            rtp_type = self.get_rtp_type(now_payload)
            if rtp_type <= 23:
                self.unpacketLog.LogStr("receive one nor rtp")
                res = self.extract_nal_from_nor_rtp(now_payload)
                return res
            elif rtp_type == 24:
                self.unpacketLog.LogStr('receive one stap_a rtp')
                self.nals = self.extract_nal_from_stap_a_rtp(now_payload)
                res = self.nals[0]
                self.nals = self.nals[1:]
                return res
            elif rtp_type == 28:
                #pdb.set_trace()
                self.unpacketLog.LogStr('receive one fu_a rtp')
                rtp_payloads = []
                rtps = []
                now_seq_num = get_seq_num(now_rtp)
                self.unpacketLog.LogStr('fu_a start seq num ' +
                                        str(now_seq_num))
                fu_a_end = False
                while now_rtp != None and (not fu_a_end):
                    header_len = get_rtp_header_len(now_rtp)
                    now_payload = now_rtp[header_len:]
                    rtp_type = self.get_rtp_type(now_payload)
                    if rtp_type != 28:
                        self.next_rtp = now_rtp
                        fu_a_end = True
                    else:
                        fu_header = get_fu_a_header(now_payload)
                        if len(rtps) > 0:
                            if fu_header & (1 << 7) > 0:
                                self.next_rtp = now_rtp
                                fu_a_end = True
                            else:
                                rtps.append(now_rtp)
                                rtp_payloads.append(now_payload)
                                if fu_header & (1 << 6) > 0:
                                    fu_a_end = True
                                else:
                                    now_rtp = self.get_one_rtp()
                        else:
                            rtps.append(now_rtp)
                            rtp_payloads.append(now_payload)
                            now_rtp = self.get_one_rtp()
                now_seq_num = get_seq_num(rtps[-1])
                self.unpacketLog.LogStr('fu_a end seq num ' + str(now_seq_num))
                res = self.extract_nal_from_fu_a_rtp(rtp_payloads, rtps)
                return res
            else:
                print "error rtp_type"
                pass
예제 #4
0
class packet:
    def __init__(self, file_name, mtu_size, ssrc, dqID):
        read_video.file_name = file_name
        read_video.init_file(read_video.file_name)
        self.mtu_size = mtu_size
        self.seq_num = 1
        self.ssrc = ssrc
        self.timestamp = 0
        self.nals = []
        self.left_nal = ""
        self.first_byte = 0
        self.nal_num = 0
        self.accessUnitID = 0
        self.dqID = dqID
        self.packetLog = Log("packetLog.txt")
        self.packetNumber = 1

    def end(self):
        read_video.close_file()

    def extractNalsBydqID(self, nals):
        res = []
        for nal in nals:
            self.packetLog.LogStr('get one nal with dqID %d' % nal.nal_dqID)
            if nal.nal_dqID <= self.dqID:
                res.append(nal)
        return res

    def get_one_packet(self):

        self.packetLog.LogStr(
            '************* packet id %d **********************' %
            self.packetNumber)
        self.packetNumber += 1
        consume_nal_num = 0
        header = self.build_rtp_header()
        left_space = self.mtu_size - len(header)
        #deal with fu_a
        if len(self.left_nal) != 0:
            (consume_size,
             payload) = self.build_fu_a_payload(self.left_nal, left_space, 0)
            self.left_nal = self.left_nal[consume_size:]
            return header + payload
        #deal with new nal
        while len(self.nals) == 0:
            self.packetLog.LogStr('read one access unit access unit id ' +
                                  str(self.accessUnitID))
            self.accessUnitID += 1
            au = read_video.read_one_access_unit()
            if au == None:
                return None
            self.packetLog.LogStr('access unit id ' + str(self.accessUnitID) +
                                  ' nals number: ' + str(len(au.nals)))
            self.nals += self.extractNalsBydqID(au.nals)
            self.nal_num = len(self.nals)

        curr_nal = self.nals[0]
        if len(curr_nal.video_byte) > left_space:
            self.packetLog.LogStr('one large nal: nal size ' +
                                  str(len(curr_nal.video_byte)))
            self.left_nal = curr_nal.video_byte
            self.first_byte = struct.unpack('!B', self.left_nal[0:1])[0]
            (consume_size,
             payload) = self.build_fu_a_payload(self.left_nal, left_space, 1)
            self.left_nal = self.left_nal[consume_size:]
            consume_nal_num = 1
        else:
            num = self.cal_stap_a_nal_num(self.nals, left_space)
            if num <= 1:
                payload = self.build_nor_payload(curr_nal)
                consume_nal_num = 1
            else:
                consume_nal_num = num
                payload = self.build_stap_a_payload(self.nals[0:num])
        self.nals = self.nals[consume_nal_num:]
        return header + payload

    def cal_stap_a_nal_num(self, au_left_nals, left_space):
        num = 0
        left_space -= 1
        next_id = 0
        while left_space >= 0 and next_id < len(au_left_nals):
            left_space -= len(au_left_nals[next_id].video_byte) + 2
            next_id += 1
            num += 1
        if left_space < 0:
            num -= 1
        return num

    def build_stap_a_payload(self, nals):
        fb = 0
        for i in range(len(nals)):
            fb |= struct.unpack('!B', nals[i].video_byte[0:1])[0]
        fb &= 255 - 31
        fb |= 24
        payload = ""
        payload += struct.pack("!B", fb)
        for i in range(len(nals)):
            self.packetLog.LogStr('stap_a one nal size:' +
                                  str(len(nals[i].video_byte)))
            payload += struct.pack("!H", len(nals[i].video_byte))
            payload += nals[i].video_byte
        return payload

    def build_fu_a_payload(self, left_nal, left_space, start):
        self.packetLog.LogStr('fu_a start ' + str(start))

        left_space -= 2
        payload = ''
        fb = self.first_byte
        fb = fb & (255 - 31)
        fb = fb | 28
        sb = start << 7
        if len(left_nal) <= left_space:
            left_space = len(left_nal)
            sb |= 1 << 6
        sb = sb | (self.first_byte & 31)
        self.packetLog.LogStr('fu_header ' + str(sb))
        payload = struct.pack('!BB', fb, sb)
        payload += left_nal[0:left_space]
        self.packetLog.LogStr('fu_a consume size ' + str(left_space))
        return (left_space, payload)

    def build_nor_payload(self, nal):
        self.packetLog.LogStr('nor consume size ' + str(len(nal.video_byte)))
        return nal.video_byte

    def build_rtp_header(self):
        fb = 0
        v = 2
        p = 0
        x = 0
        cc = 0
        fb += cc + (x << 4) + (p << 5) + (v << 6)
        sb = 0
        M = 0
        pt = 0
        sb += pt + (M << 7)

        header = ""
        self.packetLog.LogStr('seq num ' + str(self.seq_num))
        header += struct.pack('!BBHII', fb, sb, self.seq_num, self.timestamp,
                              self.ssrc)
        self.seq_num += 1
        return header