Skip to content
This repository was archived by the owner on Feb 22, 2020. It is now read-only.

Commit 0ac92e4

Browse files
authored
Merge pull request #325 from gnes-ai/webp_encoder
feat(webp-encoder): add webp encoder
2 parents 5583462 + 5121d65 commit 0ac92e4

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed

gnes/client/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ def __init__(self, args):
7878
self.logger = set_logger(self.__class__.__name__, self.args.verbose)
7979
self.ctx = zmq.Context()
8080
self.ctx.setsockopt(zmq.LINGER, 0)
81+
self.logger.info('current libzmq version is %s, pyzmq version is %s' % (zmq.zmq_version(), zmq.__version__))
82+
8183
self.receiver, recv_addr = build_socket(
8284
self.ctx, self.args.host_in, self.args.port_in,
8385
self.args.socket_in, self.args.identity)

gnes/preprocessor/io_utils/webp.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Tencent is pleased to support the open source community by making GNES available.
2+
#
3+
# Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
4+
# Licensed under the Apache License, Version 2.0 (the 'License');
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an 'AS IS' BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
from typing import List
17+
18+
def encode_video(images: List['np.ndarray'], frame_rate: int, pix_fmt: str = 'rgb24'):
19+
import webp
20+
from PIL import Image
21+
22+
height, width, _ = images[0].shape
23+
if pix_fmt == 'rgb24':
24+
pix_fmt = 'RGB'
25+
# Save an animation
26+
enc = webp.WebPAnimEncoder.new(width, height)
27+
timestamp_ms = 0
28+
duration = 1000 // frame_rate
29+
for x in images:
30+
img = Image.fromarray(x.copy(), pix_fmt)
31+
pic = webp.WebPPicture.from_pil(img)
32+
enc.encode_frame(pic, timestamp_ms)
33+
timestamp_ms += duration
34+
anim_data = enc.assemble(timestamp_ms)
35+
return bytes(anim_data.buffer())

gnes/preprocessor/video/video_encoder.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
from ...proto import gnes_pb2, blob2array
1717
from ..base import BaseVideoPreprocessor
18-
from ..io_utils import video, gif
18+
from ..io_utils import video, gif, webp
1919

2020

2121
class VideoEncoderPreprocessor(BaseVideoPreprocessor):
@@ -25,16 +25,17 @@ def __init__(self, frame_rate: int = 10, pix_fmt: str = 'rgb24', video_format: s
2525
self.frame_rate = frame_rate
2626
self.video_format = video_format
2727

28-
if self.video_format not in ['mp4', 'gif']:
28+
if self.video_format not in ['mp4', 'gif', 'webp']:
2929
raise ValueError("%s encoder has not been supported!" % (self.video_format))
3030

31-
3231
def _encode(self, images: 'np.ndarray'):
3332
encoder = None
3433
if self.video_format == 'mp4':
3534
encoder = video
3635
elif self.video_format == 'gif':
3736
encoder = gif
37+
elif self.video_format == 'webp':
38+
encoder = webp
3839

3940
return encoder.encode_video(images, pix_fmt=self.pix_fmt, frame_rate=self.frame_rate)
4041

gnes/service/frontend.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ def StreamCall(self, request_iterator, context):
120120
self.pending_request = 0
121121

122122
def get_response(num_recv, blocked=False):
123+
if blocked:
124+
self.logger.info('waiting for %d responses ...' % (num_recv))
123125
for _ in range(num_recv):
124126
if blocked or zmq_client.receiver.poll(1):
125127
msg = zmq_client.recv_message(**self.send_recv_kwargs)
@@ -129,12 +131,14 @@ def get_response(num_recv, blocked=False):
129131
with self.zmq_context as zmq_client:
130132

131133
for request in request_iterator:
134+
self.logger.info('receive request: %s' % request.request_id)
132135
num_recv = max(self.pending_request - self.args.max_pending_request, 1)
133136
yield from get_response(num_recv, num_recv > 1)
134-
137+
self.logger.info('send new request into %d appending tasks' % (self.pending_request))
135138
zmq_client.send_message(self.add_envelope(request, zmq_client), **self.send_recv_kwargs)
136139
self.pending_request += 1
137140

141+
self.logger.info('all requests are sent, waiting for the responses...')
138142
yield from get_response(self.pending_request, blocked=True)
139143

140144
class ZmqContext:

0 commit comments

Comments
 (0)