10a7ce71fSopenharmony_ci#!/usr/bin/env python3
20a7ce71fSopenharmony_ci# Copyright (c) 2021 Huawei Device Co., Ltd.
30a7ce71fSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
40a7ce71fSopenharmony_ci# you may not use this file except in compliance with the License.
50a7ce71fSopenharmony_ci# You may obtain a copy of the License at
60a7ce71fSopenharmony_ci#
70a7ce71fSopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
80a7ce71fSopenharmony_ci#
90a7ce71fSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
100a7ce71fSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
110a7ce71fSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120a7ce71fSopenharmony_ci# See the License for the specific language governing permissions and
130a7ce71fSopenharmony_ci# limitations under the License.
140a7ce71fSopenharmony_ci
150a7ce71fSopenharmony_ciimport sys
160a7ce71fSopenharmony_ciimport struct
170a7ce71fSopenharmony_ciimport signal
180a7ce71fSopenharmony_cifrom threading import Thread
190a7ce71fSopenharmony_cifrom datetime import datetime
200a7ce71fSopenharmony_cifrom socketserver import ThreadingTCPServer, StreamRequestHandler
210a7ce71fSopenharmony_ci
220a7ce71fSopenharmony_ciTARGET_WIDTH = 128
230a7ce71fSopenharmony_ciTARGET_HEIGHT = 64
240a7ce71fSopenharmony_ciPIXEL_PER_BYTE = 8
250a7ce71fSopenharmony_ci
260a7ce71fSopenharmony_ciBIN_FRAME_SIZE = int(TARGET_WIDTH * TARGET_HEIGHT / PIXEL_PER_BYTE)
270a7ce71fSopenharmony_ci
280a7ce71fSopenharmony_ciDEFAULT_PORT = 5678
290a7ce71fSopenharmony_ci
300a7ce71fSopenharmony_ciREQUEST_SIZE = 4
310a7ce71fSopenharmony_ciSTATUS_SUCCESS = 0
320a7ce71fSopenharmony_ciSTATUS_FAILURE = 255
330a7ce71fSopenharmony_ci
340a7ce71fSopenharmony_ciclass EncodeHandler(StreamRequestHandler):
350a7ce71fSopenharmony_ci    bitmapList = []
360a7ce71fSopenharmony_ci
370a7ce71fSopenharmony_ci    def handle(self):
380a7ce71fSopenharmony_ci        addr = self.request.getpeername()
390a7ce71fSopenharmony_ci        print('Got connection from', addr)
400a7ce71fSopenharmony_ci
410a7ce71fSopenharmony_ci        while True:
420a7ce71fSopenharmony_ci            startTime = datetime.now()
430a7ce71fSopenharmony_ci            req = self.rfile.read(REQUEST_SIZE)
440a7ce71fSopenharmony_ci            if not req:
450a7ce71fSopenharmony_ci                break
460a7ce71fSopenharmony_ci            # recv request from client
470a7ce71fSopenharmony_ci            frameId = int.from_bytes(req, 'big') # bytes request
480a7ce71fSopenharmony_ci
490a7ce71fSopenharmony_ci            # prepare response
500a7ce71fSopenharmony_ci            status, body = None, bytes()
510a7ce71fSopenharmony_ci            if frameId < len(EncodeHandler.bitmapList):
520a7ce71fSopenharmony_ci                status = STATUS_SUCCESS
530a7ce71fSopenharmony_ci                body = EncodeHandler.bitmapList[frameId]
540a7ce71fSopenharmony_ci            else:
550a7ce71fSopenharmony_ci                status = STATUS_FAILURE
560a7ce71fSopenharmony_ci                print('frameId out of range!')
570a7ce71fSopenharmony_ci                break
580a7ce71fSopenharmony_ci            # response header is: status(4B) + body length(4B)
590a7ce71fSopenharmony_ci            head = struct.pack('>II', status, len(body))
600a7ce71fSopenharmony_ci
610a7ce71fSopenharmony_ci            # send response(header + body) to client
620a7ce71fSopenharmony_ci            self.wfile.write(head + body)
630a7ce71fSopenharmony_ci
640a7ce71fSopenharmony_ci            currentTime = datetime.now()
650a7ce71fSopenharmony_ci            timeCost = currentTime - startTime
660a7ce71fSopenharmony_ci            print('frameId:', frameId, 'timeCost: %.3f' % timeCost.total_seconds())
670a7ce71fSopenharmony_ci        print('handle request from', addr, 'done!')
680a7ce71fSopenharmony_ci        self.wfile.close()
690a7ce71fSopenharmony_ci
700a7ce71fSopenharmony_cidef load_video_bin(binFile):
710a7ce71fSopenharmony_ci    binFrames = []
720a7ce71fSopenharmony_ci    print('loading', binFile, '...')
730a7ce71fSopenharmony_ci    with open(binFile, 'rb') as f:
740a7ce71fSopenharmony_ci        while True:
750a7ce71fSopenharmony_ci            blob = f.read(BIN_FRAME_SIZE)
760a7ce71fSopenharmony_ci            if len(blob) == 0:
770a7ce71fSopenharmony_ci                break
780a7ce71fSopenharmony_ci            binFrames.append(blob)
790a7ce71fSopenharmony_ci    print('load', binFile, 'done!')
800a7ce71fSopenharmony_ci    return binFrames
810a7ce71fSopenharmony_ci
820a7ce71fSopenharmony_cidef main():
830a7ce71fSopenharmony_ci    if len(sys.argv) < 2:
840a7ce71fSopenharmony_ci        print("Usage: {} binFile [port]\n\t".format(sys.argv[0]))
850a7ce71fSopenharmony_ci        exit(-1)
860a7ce71fSopenharmony_ci
870a7ce71fSopenharmony_ci    binFile = sys.argv[1]
880a7ce71fSopenharmony_ci    port = DEFAULT_PORT if len(sys.argv) < 3 else int(sys.argv[2])
890a7ce71fSopenharmony_ci
900a7ce71fSopenharmony_ci    print('binFile:', binFile, 'port:', port)
910a7ce71fSopenharmony_ci    server = ThreadingTCPServer(('', port), EncodeHandler)
920a7ce71fSopenharmony_ci
930a7ce71fSopenharmony_ci    def sigint_handler(signum, frame):
940a7ce71fSopenharmony_ci        print('sig {} raised: {}'.format(signum, frame))
950a7ce71fSopenharmony_ci        server.socket.close()
960a7ce71fSopenharmony_ci        server.shutdown()
970a7ce71fSopenharmony_ci        sys.exit(0)
980a7ce71fSopenharmony_ci    signal.signal(signal.SIGINT, sigint_handler) # main thread will handle signals
990a7ce71fSopenharmony_ci
1000a7ce71fSopenharmony_ci    try:
1010a7ce71fSopenharmony_ci        EncodeHandler.bitmapList = load_video_bin(binFile)
1020a7ce71fSopenharmony_ci        waiterThread = Thread(target=server.serve_forever, args=())
1030a7ce71fSopenharmony_ci        waiterThread.start()
1040a7ce71fSopenharmony_ci        waiterThread.join()
1050a7ce71fSopenharmony_ci    except Exception as e:
1060a7ce71fSopenharmony_ci        print('exception raised:', e)
1070a7ce71fSopenharmony_ci    finally:
1080a7ce71fSopenharmony_ci        server.socket.close()
1090a7ce71fSopenharmony_ci        server.shutdown()
1100a7ce71fSopenharmony_ci
1110a7ce71fSopenharmony_ciif __name__ == "__main__":
1120a7ce71fSopenharmony_ci    main()
113