From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-lf1-f44.google.com ([209.85.167.44]:36027 "EHLO mail-lf1-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727993AbeIJQm4 (ORCPT ); Mon, 10 Sep 2018 12:42:56 -0400 Received: by mail-lf1-f44.google.com with SMTP id x207-v6so17191808lff.3 for ; Mon, 10 Sep 2018 04:49:13 -0700 (PDT) Subject: Re: [Xen-devel][PATCH 1/1] cameraif: add ABI for para-virtual camera To: Hans Verkuil , "Oleksandr_Andrushchenko@epam.com" , xen-devel@lists.xenproject.org, konrad.wilk@oracle.com, jgross@suse.com, boris.ostrovsky@oracle.com, mchehab@kernel.org, linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, koji.matsuoka.xm@renesas.com References: <20180731093142.3828-1-andr2000@gmail.com> <20180731093142.3828-2-andr2000@gmail.com> <73b69e31-d36d-d89f-20d6-d59dbefe395e@xs4all.nl> <7134b3ad-9fcf-0139-41b3-67a3dbc8224d@xs4all.nl> <51f97715-454a-0242-b381-29944d77d5b5@gmail.com> <3c6bb5c8-eeb4-fd09-407a-5a77b29b56c3@xs4all.nl> <2a39c994-118f-a17e-c40a-f5fbbad1cb03@epam.com> <30d7c91a-4515-157b-fc29-90c2e6f0008b@xs4all.nl> From: Oleksandr Andrushchenko Message-ID: Date: Mon, 10 Sep 2018 14:49:10 +0300 MIME-Version: 1.0 In-Reply-To: <30d7c91a-4515-157b-fc29-90c2e6f0008b@xs4all.nl> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US Sender: linux-media-owner@vger.kernel.org List-ID: On 09/10/2018 02:09 PM, Hans Verkuil wrote: > On 09/10/2018 11:52 AM, Oleksandr Andrushchenko wrote: >> On 09/10/2018 12:04 PM, Hans Verkuil wrote: >>> On 09/10/2018 10:24 AM, Oleksandr Andrushchenko wrote: >>>> On 09/10/2018 10:53 AM, Hans Verkuil wrote: >>>>> Hi Oleksandr, >>>>> >>>>> On 09/10/2018 09:16 AM, Oleksandr Andrushchenko wrote: >>> >>> >>>>>>> I suspect that you likely will want to support such sources eventually, so >>>>>>> it pays to design this with that in mind. >>>>>> Again, I think that this is the backend to hide these >>>>>> use-cases from the frontend. >>>>> I'm not sure you can: say you are playing a bluray connected to the system >>>>> with HDMI, then if there is a resolution change, what do you do? You can tear >>>>> everything down and build it up again, or you can just tell frontends that >>>>> something changed and that they have to look at the new vcamera configuration. >>>>> >>>>> The latter seems to be more sensible to me. It is really not much that you >>>>> need to do: all you really need is an event signalling that something changed. >>>>> In V4L2 that's the V4L2_EVENT_SOURCE_CHANGE. >>>> well, this complicates things a lot as I'll have to >>>> re-allocate buffers - right? >>> Right. Different resolutions means different sized buffers and usually lots of >>> changes throughout the whole video pipeline, which in this case can even >>> go into multiple VMs. >>> >>> One additional thing to keep in mind for the future: V4L2_EVENT_SOURCE_CHANGE >>> has a flags field that tells userspace what changed. Right now that is just the >>> resolution, but in the future you can expect flags for cases where just the >>> colorspace information changes, but not the resolution. >>> >>> Which reminds me of two important missing pieces of information in your protocol: >>> >>> 1) You need to communicate the colorspace data: >>> >>> - colorspace >>> - xfer_func >>> - ycbcr_enc/hsv_enc (unlikely you ever want to support HSV pixelformats, so I >>> think you can ignore hsv_enc) >>> - quantization >>> >>> See https://hverkuil.home.xs4all.nl/spec/uapi/v4l/pixfmt-v4l2.html#c.v4l2_pix_format >>> and the links to the colorspace sections in the V4L2 spec for details). >>> >>> This information is part of the format, it is reported by the driver. >> I'll take a look and think what can be put and how into the protocol, >> do you think I'll have to implement all the above for >> this stage? > Yes. Without it VMs will have no way of knowing how to reproduce the right colors. > They don't *have* to use this information, but it should be there. For cameras > this isn't all that important, for SDTV/HDTV sources this becomes more relevant > (esp. the quantization and ycbcr_enc information) and for sources with BT.2020/HDR > formats this is critical. ok, then I'll add the following to the set_config request/response:     uint32_t colorspace;     uint32_t xfer_func;     uint32_t ycbcr_enc;     uint32_t quantization; With this respect, I will need to put some OS agnostic constants into the protocol, so if backend and frontend are not Linux/V4L2 based they can still talk to each other. I see that V4L2 already defines constants for the above: [1], [2], [3], [4]. Do you think I can define the same replacing V4L2_ prefix with XENCAMERA_, e.g. V4L2_XFER_FUNC_SRGB -> XENCAMERA_XFER_FUNC_SRGB? Do I need to define all those or there can be some subset of the above for my simpler use-case? > The vivid driver can actually reproduce all combinations, so that's a good driver > to test this with. You mean I can use it on backend side instead of real HW camera and test all the configurations possible/those of interest? >>> 2) If you support interlaced formats and V4L2_FIELD_ALTERNATE (i.e. >>> each buffer contains a single field), then you need to be able to tell >>> userspace whether the dequeued buffer contains a top or bottom field. >> I think at the first stage we can assume that interlaced >> formats are not supported and add such support later if need be. > Frankly I consider that a smart move :-) Interlaced formats are awful... > > You just have to keep this in mind if you ever have to add support for this. Agreed > >>> Also, what to do with dropped frames/fields: V4L2 has a sequence counter and >>> timestamp that can help detecting that. You probably need something similar. >> Ok, this can be reported as part of XENCAMERA_EVT_FRAME_AVAIL event >>>> But anyways, I can add >>>> #define XENCAMERA_EVT_CFG_CHANGE 0x01 >>>> in the protocol, so we can address this use-case >>> >>> >>>>>> 1. set format command: >>>>>> * pixel_format - uint32_t, pixel format to be used, FOURCC code. >>>>>> * width - uint32_t, width in pixels. >>>>>> * height - uint32_t, height in pixels. >>>>>> >>>>>> 2. Set frame rate command: >>>>>> + * frame_rate_numer - uint32_t, numerator of the frame rate. >>>>>> + * frame_rate_denom - uint32_t, denominator of the frame rate. >>>>>> >>>>>> 3. Set/request num bufs: >>>>>> * num_bufs - uint8_t, desired number of buffers to be used. >>>>> I like this much better. 1+2 could be combined, but 3 should definitely remain >>>>> separate. >>>> ok, then 1+2 combined + 3 separate. >>>> Do you think we can still name 1+2 as "set_format" or "set_config" >>>> will fit better? >>> set_format is closer to S_FMT as used in V4L2, so I have a slight preference >>> for that, but it is really up to you. >> I'll probably stick to SET_CONFIG here >>>>>>>> + * >>>>>>>> + * See response format for this request. >>>>>>>> + * >>>>>>>> + * Notes: >>>>>>>> + * - frontend must check the corresponding response in order to see >>>>>>>> + * if the values reported back by the backend do match the desired ones >>>>>>>> + * and can be accepted. >>>>>>>> + * - frontend may send multiple XENCAMERA_OP_SET_CONFIG requests before >>>>>>>> + * sending XENCAMERA_OP_STREAM_START request to update or tune the >>>>>>>> + * configuration. >>>>>>>> + */ >>>>>>>> +struct xencamera_config { >>>>>>>> + uint32_t pixel_format; >>>>>>>> + uint32_t width; >>>>>>>> + uint32_t height; >>>>>>>> + uint32_t frame_rate_nom; >>>>>>>> + uint32_t frame_rate_denom; >>>>>>>> + uint8_t num_bufs; >>>>>>>> +}; >>>>>>>> + >>>>>>>> +/* >>>>>>>> + * Request buffer details - request camera buffer's memory layout. >>>>>>>> + * detailed description: >>>>>>>> + * 0 1 2 3 octet >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | id |_GET_BUF_DETAILS| reserved | 4 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | reserved | 8 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/| >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | reserved | 64 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * >>>>>>>> + * See response format for this request. >>>>>>>> + * >>>>>>>> + * >>>>>>>> + * Request camera buffer creation: >>>>>>>> + * 0 1 2 3 octet >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | id | _OP_BUF_CREATE | reserved | 4 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | reserved | 8 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | index | reserved | 12 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | gref_directory | 16 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | reserved | 20 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/| >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * | reserved | 64 >>>>>>>> + * +----------------+----------------+----------------+----------------+ >>>>>>>> + * >>>>>>>> + * An attempt to create multiple buffers with the same index is an error. >>>>>>>> + * index can be re-used after destroying the corresponding camera buffer. >>>>>>>> + * >>>>>>>> + * index - uint8_t, index of the buffer to be created. >>>>>>>> + * gref_directory - grant_ref_t, a reference to the first shared page >>>>>>>> + * describing shared buffer references. The size of the buffer is equal to >>>>>>>> + * XENCAMERA_OP_GET_BUF_DETAILS.size response. At least one page exists. If >>>>>>>> + * shared buffer size exceeds what can be addressed by this single page, >>>>>>>> + * then reference to the next shared page must be supplied (see >>>>>>>> + * gref_dir_next_page below). >>>>>>> It might be better to allocate all buffers in one go, i.e. what VIDIOC_REQBUFS >>>>>>> does. >>>>>> Well, I still think it is better to have a per buffer interface >>>>>> in the protocol as it is done for other Xen virtual devices. >>>>>> So, I'll keep this as is for now: VIDIOC_REQBUFS can still do >>>>>> what it does internally in the frontend driver >>>>> I may have misunderstood the original API. The newly proposed XENCAMERA_OP_BUF_REQUEST >>>>> maps to REQBUFS, right? And then BUF_CREATE/DESTROY just set up the shared buffer >>>>> mappings for the buffers created by REQBUFS. If that's the sequence, then it makes >>>>> sense. I'm not sure about the naming. >>>>> >>>>> You might want to make it clear that XENCAMERA_OP_BUF_REQUEST allocates the buffers >>>>> on the backend, and so can fail. Also, the actual number of allocated buffers in >>>>> case of success can be more or less than what was requested. >>>> The buffers can be allocated and shared by either backend or frontend: see >>>> "be-alloc" configuration option telling which domain (VM) shares >>>> the Xen grant references to the pages of the buffer: either frontend >>>> or backend. >>> If you want to do zero-copy video capture, >> this is the goal >>> then you need to know which >>> device in your video pipeline (which now covers both actual hardware and >>> multiple VMs) has the strictest memory layout requirements. Often the >>> video HW requires contiguous physical memory for the buffers, which means >>> you can't just give it a piece of non-contig memory allocated elsewhere. >> We have already implemented zero copying use-cases for >> virtual display, please see [1] and [2] which are dma-buf >> based which can cope with real HW restrictions you mention. >> And in that case we can implement zero-copying both ways, >> e.g. when the Xen grant references are shared by either >> backend or frontend. This is different from camera use-cases: >> a single buffer needs to be shared with multiple frontends, >> so zero-copying is only possible when backend allocates the references >> and shares those with frontends. The way when frontend allocates >> the buffers and still we can implement zero-copying is when >> there is a single frontend in the system, otherwise we >> need to copy the images from backend's buffers into frontend's >> ones. > OK. The important thing is that you thought about this :-) Sure, copying kills performance... > >>> In practice you have two possible memory models you can use with V4L2 drivers: >>> MMAP (i.e. allocated by the driver and the buffers can, if needed, be exported >>> as dmabuf handles with VIDIOC_EXPBUF), or DMABUF where buffers are allocated >>> elsewhere and imported to V4L2, which may fail if it doesn't match the HW >>> requirements. >> For the frontend it is possible to work with both MMAP/DMABUF >> and the rest is on the backend's side - this was proven by >> virtual display implementation, so I see no problem here >> for virtual camera. >>>> So, I was more thinking that in case of V4L2 based frontend driver: >>>> 1. Frontend serves REQBUFS ioctl and asks the backend with >>>> XENCAMERA_OP_BUF_REQUEST >>>> if it can handle that many buffers and gets number of buffers to be used >>>> and buffer structure (number of planes, sizes, offsets etc.) as the reply >>>> to that request >>>> 2. Frontend creates n buffers with XENCAMERA_OP_BUF_CREATE >>>> 3. Frontend returns from REQBUFS ioctl with actual number of buffers >>>> allocated > Regards, > > Hans Thank you, Oleksandr [1] https://hverkuil.home.xs4all.nl/spec/uapi/v4l/colorspaces-defs.html#c.v4l2_colorspace [2] https://hverkuil.home.xs4all.nl/spec/uapi/v4l/colorspaces-defs.html#c.v4l2_ycbcr_encoding [3] https://hverkuil.home.xs4all.nl/spec/uapi/v4l/colorspaces-defs.html#c.v4l2_quantization [4] https://hverkuil.home.xs4all.nl/spec/uapi/v4l/colorspaces-defs.html#c.v4l2_xfer_func From mboxrd@z Thu Jan 1 00:00:00 1970 From: Oleksandr Andrushchenko Subject: Re: [PATCH 1/1] cameraif: add ABI for para-virtual camera Date: Mon, 10 Sep 2018 14:49:10 +0300 Message-ID: References: <20180731093142.3828-1-andr2000@gmail.com> <20180731093142.3828-2-andr2000@gmail.com> <73b69e31-d36d-d89f-20d6-d59dbefe395e@xs4all.nl> <7134b3ad-9fcf-0139-41b3-67a3dbc8224d@xs4all.nl> <51f97715-454a-0242-b381-29944d77d5b5@gmail.com> <3c6bb5c8-eeb4-fd09-407a-5a77b29b56c3@xs4all.nl> <2a39c994-118f-a17e-c40a-f5fbbad1cb03@epam.com> <30d7c91a-4515-157b-fc29-90c2e6f0008b@xs4all.nl> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8"; Format="flowed" Content-Transfer-Encoding: base64 Return-path: Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1fzKgu-0005nW-CT for xen-devel@lists.xenproject.org; Mon, 10 Sep 2018 11:49:16 +0000 Received: by mail-lf1-x12c.google.com with SMTP id l26-v6so17167287lfc.8 for ; Mon, 10 Sep 2018 04:49:14 -0700 (PDT) In-Reply-To: <30d7c91a-4515-157b-fc29-90c2e6f0008b@xs4all.nl> Content-Language: en-US List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" To: Hans Verkuil , "Oleksandr_Andrushchenko@epam.com" , xen-devel@lists.xenproject.org, konrad.wilk@oracle.com, jgross@suse.com, boris.ostrovsky@oracle.com, mchehab@kernel.org, linux-media@vger.kernel.org, sakari.ailus@linux.intel.com, koji.matsuoka.xm@renesas.com List-Id: xen-devel@lists.xenproject.org T24gMDkvMTAvMjAxOCAwMjowOSBQTSwgSGFucyBWZXJrdWlsIHdyb3RlOgo+IE9uIDA5LzEwLzIw MTggMTE6NTIgQU0sIE9sZWtzYW5kciBBbmRydXNoY2hlbmtvIHdyb3RlOgo+PiBPbiAwOS8xMC8y MDE4IDEyOjA0IFBNLCBIYW5zIFZlcmt1aWwgd3JvdGU6Cj4+PiBPbiAwOS8xMC8yMDE4IDEwOjI0 IEFNLCBPbGVrc2FuZHIgQW5kcnVzaGNoZW5rbyB3cm90ZToKPj4+PiBPbiAwOS8xMC8yMDE4IDEw OjUzIEFNLCBIYW5zIFZlcmt1aWwgd3JvdGU6Cj4+Pj4+IEhpIE9sZWtzYW5kciwKPj4+Pj4KPj4+ Pj4gT24gMDkvMTAvMjAxOCAwOToxNiBBTSwgT2xla3NhbmRyIEFuZHJ1c2hjaGVua28gd3JvdGU6 Cj4+PiA8c25pcD4KPj4+Cj4+Pj4+Pj4gSSBzdXNwZWN0IHRoYXQgeW91IGxpa2VseSB3aWxsIHdh bnQgdG8gc3VwcG9ydCBzdWNoIHNvdXJjZXMgZXZlbnR1YWxseSwgc28KPj4+Pj4+PiBpdCBwYXlz IHRvIGRlc2lnbiB0aGlzIHdpdGggdGhhdCBpbiBtaW5kLgo+Pj4+Pj4gQWdhaW4sIEkgdGhpbmsg dGhhdCB0aGlzIGlzIHRoZSBiYWNrZW5kIHRvIGhpZGUgdGhlc2UKPj4+Pj4+IHVzZS1jYXNlcyBm cm9tIHRoZSBmcm9udGVuZC4KPj4+Pj4gSSdtIG5vdCBzdXJlIHlvdSBjYW46IHNheSB5b3UgYXJl IHBsYXlpbmcgYSBibHVyYXkgY29ubmVjdGVkIHRvIHRoZSBzeXN0ZW0KPj4+Pj4gd2l0aCBIRE1J LCB0aGVuIGlmIHRoZXJlIGlzIGEgcmVzb2x1dGlvbiBjaGFuZ2UsIHdoYXQgZG8geW91IGRvPyBZ b3UgY2FuIHRlYXIKPj4+Pj4gZXZlcnl0aGluZyBkb3duIGFuZCBidWlsZCBpdCB1cCBhZ2Fpbiwg b3IgeW91IGNhbiBqdXN0IHRlbGwgZnJvbnRlbmRzIHRoYXQKPj4+Pj4gc29tZXRoaW5nIGNoYW5n ZWQgYW5kIHRoYXQgdGhleSBoYXZlIHRvIGxvb2sgYXQgdGhlIG5ldyB2Y2FtZXJhIGNvbmZpZ3Vy YXRpb24uCj4+Pj4+Cj4+Pj4+IFRoZSBsYXR0ZXIgc2VlbXMgdG8gYmUgbW9yZSBzZW5zaWJsZSB0 byBtZS4gSXQgaXMgcmVhbGx5IG5vdCBtdWNoIHRoYXQgeW91Cj4+Pj4+IG5lZWQgdG8gZG86IGFs bCB5b3UgcmVhbGx5IG5lZWQgaXMgYW4gZXZlbnQgc2lnbmFsbGluZyB0aGF0IHNvbWV0aGluZyBj aGFuZ2VkLgo+Pj4+PiBJbiBWNEwyIHRoYXQncyB0aGUgVjRMMl9FVkVOVF9TT1VSQ0VfQ0hBTkdF Lgo+Pj4+IHdlbGwsIHRoaXMgY29tcGxpY2F0ZXMgdGhpbmdzIGEgbG90IGFzIEknbGwgaGF2ZSB0 bwo+Pj4+IHJlLWFsbG9jYXRlIGJ1ZmZlcnMgLSByaWdodD8KPj4+IFJpZ2h0LiBEaWZmZXJlbnQg cmVzb2x1dGlvbnMgbWVhbnMgZGlmZmVyZW50IHNpemVkIGJ1ZmZlcnMgYW5kIHVzdWFsbHkgbG90 cyBvZgo+Pj4gY2hhbmdlcyB0aHJvdWdob3V0IHRoZSB3aG9sZSB2aWRlbyBwaXBlbGluZSwgd2hp Y2ggaW4gdGhpcyBjYXNlIGNhbiBldmVuCj4+PiBnbyBpbnRvIG11bHRpcGxlIFZNcy4KPj4+Cj4+ PiBPbmUgYWRkaXRpb25hbCB0aGluZyB0byBrZWVwIGluIG1pbmQgZm9yIHRoZSBmdXR1cmU6IFY0 TDJfRVZFTlRfU09VUkNFX0NIQU5HRQo+Pj4gaGFzIGEgZmxhZ3MgZmllbGQgdGhhdCB0ZWxscyB1 c2Vyc3BhY2Ugd2hhdCBjaGFuZ2VkLiBSaWdodCBub3cgdGhhdCBpcyBqdXN0IHRoZQo+Pj4gcmVz b2x1dGlvbiwgYnV0IGluIHRoZSBmdXR1cmUgeW91IGNhbiBleHBlY3QgZmxhZ3MgZm9yIGNhc2Vz IHdoZXJlIGp1c3QgdGhlCj4+PiBjb2xvcnNwYWNlIGluZm9ybWF0aW9uIGNoYW5nZXMsIGJ1dCBu b3QgdGhlIHJlc29sdXRpb24uCj4+Pgo+Pj4gV2hpY2ggcmVtaW5kcyBtZSBvZiB0d28gaW1wb3J0 YW50IG1pc3NpbmcgcGllY2VzIG9mIGluZm9ybWF0aW9uIGluIHlvdXIgcHJvdG9jb2w6Cj4+Pgo+ Pj4gMSkgWW91IG5lZWQgdG8gY29tbXVuaWNhdGUgdGhlIGNvbG9yc3BhY2UgZGF0YToKPj4+Cj4+ PiAtIGNvbG9yc3BhY2UKPj4+IC0geGZlcl9mdW5jCj4+PiAtIHljYmNyX2VuYy9oc3ZfZW5jICh1 bmxpa2VseSB5b3UgZXZlciB3YW50IHRvIHN1cHBvcnQgSFNWIHBpeGVsZm9ybWF0cywgc28gSQo+ Pj4gICAgIHRoaW5rIHlvdSBjYW4gaWdub3JlIGhzdl9lbmMpCj4+PiAtIHF1YW50aXphdGlvbgo+ Pj4KPj4+IFNlZSBodHRwczovL2h2ZXJrdWlsLmhvbWUueHM0YWxsLm5sL3NwZWMvdWFwaS92NGwv cGl4Zm10LXY0bDIuaHRtbCNjLnY0bDJfcGl4X2Zvcm1hdAo+Pj4gYW5kIHRoZSBsaW5rcyB0byB0 aGUgY29sb3JzcGFjZSBzZWN0aW9ucyBpbiB0aGUgVjRMMiBzcGVjIGZvciBkZXRhaWxzKS4KPj4+ Cj4+PiBUaGlzIGluZm9ybWF0aW9uIGlzIHBhcnQgb2YgdGhlIGZvcm1hdCwgaXQgaXMgcmVwb3J0 ZWQgYnkgdGhlIGRyaXZlci4KPj4gSSdsbCB0YWtlIGEgbG9vayBhbmQgdGhpbmsgd2hhdCBjYW4g YmUgcHV0IGFuZCBob3cgaW50byB0aGUgcHJvdG9jb2wsCj4+IGRvIHlvdSB0aGluayBJJ2xsIGhh dmUgdG8gaW1wbGVtZW50IGFsbCB0aGUgYWJvdmUgZm9yCj4+IHRoaXMgc3RhZ2U/Cj4gWWVzLiBX aXRob3V0IGl0IFZNcyB3aWxsIGhhdmUgbm8gd2F5IG9mIGtub3dpbmcgaG93IHRvIHJlcHJvZHVj ZSB0aGUgcmlnaHQgY29sb3JzLgo+IFRoZXkgZG9uJ3QgKmhhdmUqIHRvIHVzZSB0aGlzIGluZm9y bWF0aW9uLCBidXQgaXQgc2hvdWxkIGJlIHRoZXJlLiBGb3IgY2FtZXJhcwo+IHRoaXMgaXNuJ3Qg YWxsIHRoYXQgaW1wb3J0YW50LCBmb3IgU0RUVi9IRFRWIHNvdXJjZXMgdGhpcyBiZWNvbWVzIG1v cmUgcmVsZXZhbnQKPiAoZXNwLiB0aGUgcXVhbnRpemF0aW9uIGFuZCB5Y2Jjcl9lbmMgaW5mb3Jt YXRpb24pIGFuZCBmb3Igc291cmNlcyB3aXRoIEJULjIwMjAvSERSCj4gZm9ybWF0cyB0aGlzIGlz IGNyaXRpY2FsLgpvaywgdGhlbiBJJ2xsIGFkZCB0aGUgZm9sbG93aW5nIHRvIHRoZSBzZXRfY29u ZmlnIHJlcXVlc3QvcmVzcG9uc2U6CgogwqDCoMKgIHVpbnQzMl90IGNvbG9yc3BhY2U7CiDCoMKg wqAgdWludDMyX3QgeGZlcl9mdW5jOwogwqDCoMKgIHVpbnQzMl90IHljYmNyX2VuYzsKIMKgwqDC oCB1aW50MzJfdCBxdWFudGl6YXRpb247CgpXaXRoIHRoaXMgcmVzcGVjdCwgSSB3aWxsIG5lZWQg dG8gcHV0IHNvbWUgT1MgYWdub3N0aWMgY29uc3RhbnRzCmludG8gdGhlIHByb3RvY29sLCBzbyBp ZiBiYWNrZW5kIGFuZCBmcm9udGVuZCBhcmUgbm90IExpbnV4L1Y0TDIKYmFzZWQgdGhleSBjYW4g c3RpbGwgdGFsayB0byBlYWNoIG90aGVyLgpJIHNlZSB0aGF0IFY0TDIgYWxyZWFkeSBkZWZpbmVz IGNvbnN0YW50cyBmb3IgdGhlIGFib3ZlOiBbMV0sIFsyXSwgWzNdLCBbNF0uCgpEbyB5b3UgdGhp bmsgSSBjYW4gZGVmaW5lIHRoZSBzYW1lIHJlcGxhY2luZyBWNEwyXyBwcmVmaXgKd2l0aCBYRU5D QU1FUkFfLCBlLmcuIFY0TDJfWEZFUl9GVU5DX1NSR0IgLT4gWEVOQ0FNRVJBX1hGRVJfRlVOQ19T UkdCPwoKRG8gSSBuZWVkIHRvIGRlZmluZSBhbGwgdGhvc2Ugb3IgdGhlcmUgY2FuIGJlIHNvbWUg c3Vic2V0IG9mIHRoZQphYm92ZSBmb3IgbXkgc2ltcGxlciB1c2UtY2FzZT8KCj4gVGhlIHZpdmlk IGRyaXZlciBjYW4gYWN0dWFsbHkgcmVwcm9kdWNlIGFsbCBjb21iaW5hdGlvbnMsIHNvIHRoYXQn cyBhIGdvb2QgZHJpdmVyCj4gdG8gdGVzdCB0aGlzIHdpdGguCllvdSBtZWFuIEkgY2FuIHVzZSBp dCBvbiBiYWNrZW5kIHNpZGUgaW5zdGVhZCBvZiByZWFsIEhXIGNhbWVyYSBhbmQKdGVzdCBhbGwg dGhlIGNvbmZpZ3VyYXRpb25zIHBvc3NpYmxlL3Rob3NlIG9mIGludGVyZXN0Pwo+Pj4gMikgSWYg eW91IHN1cHBvcnQgaW50ZXJsYWNlZCBmb3JtYXRzIGFuZCBWNEwyX0ZJRUxEX0FMVEVSTkFURSAo aS5lLgo+Pj4gICAgICBlYWNoIGJ1ZmZlciBjb250YWlucyBhIHNpbmdsZSBmaWVsZCksIHRoZW4g eW91IG5lZWQgdG8gYmUgYWJsZSB0byB0ZWxsCj4+PiAgICAgIHVzZXJzcGFjZSB3aGV0aGVyIHRo ZSBkZXF1ZXVlZCBidWZmZXIgY29udGFpbnMgYSB0b3Agb3IgYm90dG9tIGZpZWxkLgo+PiBJIHRo aW5rIGF0IHRoZSBmaXJzdCBzdGFnZSB3ZSBjYW4gYXNzdW1lIHRoYXQgaW50ZXJsYWNlZAo+PiBm b3JtYXRzIGFyZSBub3Qgc3VwcG9ydGVkIGFuZCBhZGQgc3VjaCBzdXBwb3J0IGxhdGVyIGlmIG5l ZWQgYmUuCj4gRnJhbmtseSBJIGNvbnNpZGVyIHRoYXQgYSBzbWFydCBtb3ZlIDotKSBJbnRlcmxh Y2VkIGZvcm1hdHMgYXJlIGF3ZnVsLi4uCj4KPiBZb3UganVzdCBoYXZlIHRvIGtlZXAgdGhpcyBp biBtaW5kIGlmIHlvdSBldmVyIGhhdmUgdG8gYWRkIHN1cHBvcnQgZm9yIHRoaXMuCkFncmVlZAo+ Cj4+PiBBbHNvLCB3aGF0IHRvIGRvIHdpdGggZHJvcHBlZCBmcmFtZXMvZmllbGRzOiBWNEwyIGhh cyBhIHNlcXVlbmNlIGNvdW50ZXIgYW5kCj4+PiB0aW1lc3RhbXAgdGhhdCBjYW4gaGVscCBkZXRl Y3RpbmcgdGhhdC4gWW91IHByb2JhYmx5IG5lZWQgc29tZXRoaW5nIHNpbWlsYXIuCj4+IE9rLCB0 aGlzIGNhbiBiZSByZXBvcnRlZCBhcyBwYXJ0IG9mIFhFTkNBTUVSQV9FVlRfRlJBTUVfQVZBSUwg ZXZlbnQKPj4+PiBCdXQgYW55d2F5cywgSSBjYW4gYWRkCj4+Pj4gI2RlZmluZSBYRU5DQU1FUkFf RVZUX0NGR19DSEFOR0UgICAgICAgMHgwMQo+Pj4+IGluIHRoZSBwcm90b2NvbCwgc28gd2UgY2Fu IGFkZHJlc3MgdGhpcyB1c2UtY2FzZQo+Pj4gPHNuaXA+Cj4+Pgo+Pj4+Pj4gMS4gc2V0IGZvcm1h dCBjb21tYW5kOgo+Pj4+Pj4gICAgICAqIHBpeGVsX2Zvcm1hdCAtIHVpbnQzMl90LCBwaXhlbCBm b3JtYXQgdG8gYmUgdXNlZCwgRk9VUkNDIGNvZGUuCj4+Pj4+PiAgICAgICogd2lkdGggLSB1aW50 MzJfdCwgd2lkdGggaW4gcGl4ZWxzLgo+Pj4+Pj4gICAgICAqIGhlaWdodCAtIHVpbnQzMl90LCBo ZWlnaHQgaW4gcGl4ZWxzLgo+Pj4+Pj4KPj4+Pj4+IDIuIFNldCBmcmFtZSByYXRlIGNvbW1hbmQ6 Cj4+Pj4+PiAgICAgICsgKiBmcmFtZV9yYXRlX251bWVyIC0gdWludDMyX3QsIG51bWVyYXRvciBv ZiB0aGUgZnJhbWUgcmF0ZS4KPj4+Pj4+ICAgICAgKyAqIGZyYW1lX3JhdGVfZGVub20gLSB1aW50 MzJfdCwgZGVub21pbmF0b3Igb2YgdGhlIGZyYW1lIHJhdGUuCj4+Pj4+Pgo+Pj4+Pj4gMy4gU2V0 L3JlcXVlc3QgbnVtIGJ1ZnM6Cj4+Pj4+PiAgICAgICogbnVtX2J1ZnMgLSB1aW50OF90LCBkZXNp cmVkIG51bWJlciBvZiBidWZmZXJzIHRvIGJlIHVzZWQuCj4+Pj4+IEkgbGlrZSB0aGlzIG11Y2gg YmV0dGVyLiAxKzIgY291bGQgYmUgY29tYmluZWQsIGJ1dCAzIHNob3VsZCBkZWZpbml0ZWx5IHJl bWFpbgo+Pj4+PiBzZXBhcmF0ZS4KPj4+PiBvaywgdGhlbiAxKzIgY29tYmluZWQgKyAzIHNlcGFy YXRlLgo+Pj4+IERvIHlvdSB0aGluayB3ZSBjYW4gc3RpbGwgbmFtZSAxKzIgYXMgInNldF9mb3Jt YXQiIG9yICJzZXRfY29uZmlnIgo+Pj4+IHdpbGwgZml0IGJldHRlcj8KPj4+IHNldF9mb3JtYXQg aXMgY2xvc2VyIHRvIFNfRk1UIGFzIHVzZWQgaW4gVjRMMiwgc28gSSBoYXZlIGEgc2xpZ2h0IHBy ZWZlcmVuY2UKPj4+IGZvciB0aGF0LCBidXQgaXQgaXMgcmVhbGx5IHVwIHRvIHlvdS4KPj4gSSds bCBwcm9iYWJseSBzdGljayB0byBTRVRfQ09ORklHIGhlcmUKPj4+Pj4+Pj4gKyAqCj4+Pj4+Pj4+ ICsgKiBTZWUgcmVzcG9uc2UgZm9ybWF0IGZvciB0aGlzIHJlcXVlc3QuCj4+Pj4+Pj4+ICsgKgo+ Pj4+Pj4+PiArICogTm90ZXM6Cj4+Pj4+Pj4+ICsgKiAgLSBmcm9udGVuZCBtdXN0IGNoZWNrIHRo ZSBjb3JyZXNwb25kaW5nIHJlc3BvbnNlIGluIG9yZGVyIHRvIHNlZQo+Pj4+Pj4+PiArICogICAg aWYgdGhlIHZhbHVlcyByZXBvcnRlZCBiYWNrIGJ5IHRoZSBiYWNrZW5kIGRvIG1hdGNoIHRoZSBk ZXNpcmVkIG9uZXMKPj4+Pj4+Pj4gKyAqICAgIGFuZCBjYW4gYmUgYWNjZXB0ZWQuCj4+Pj4+Pj4+ ICsgKiAgLSBmcm9udGVuZCBtYXkgc2VuZCBtdWx0aXBsZSBYRU5DQU1FUkFfT1BfU0VUX0NPTkZJ RyByZXF1ZXN0cyBiZWZvcmUKPj4+Pj4+Pj4gKyAqICAgIHNlbmRpbmcgWEVOQ0FNRVJBX09QX1NU UkVBTV9TVEFSVCByZXF1ZXN0IHRvIHVwZGF0ZSBvciB0dW5lIHRoZQo+Pj4+Pj4+PiArICogICAg Y29uZmlndXJhdGlvbi4KPj4+Pj4+Pj4gKyAqLwo+Pj4+Pj4+PiArc3RydWN0IHhlbmNhbWVyYV9j b25maWcgewo+Pj4+Pj4+PiArICAgIHVpbnQzMl90IHBpeGVsX2Zvcm1hdDsKPj4+Pj4+Pj4gKyAg ICB1aW50MzJfdCB3aWR0aDsKPj4+Pj4+Pj4gKyAgICB1aW50MzJfdCBoZWlnaHQ7Cj4+Pj4+Pj4+ ICsgICAgdWludDMyX3QgZnJhbWVfcmF0ZV9ub207Cj4+Pj4+Pj4+ICsgICAgdWludDMyX3QgZnJh bWVfcmF0ZV9kZW5vbTsKPj4+Pj4+Pj4gKyAgICB1aW50OF90IG51bV9idWZzOwo+Pj4+Pj4+PiAr fTsKPj4+Pj4+Pj4gKwo+Pj4+Pj4+PiArLyoKPj4+Pj4+Pj4gKyAqIFJlcXVlc3QgYnVmZmVyIGRl dGFpbHMgLSByZXF1ZXN0IGNhbWVyYSBidWZmZXIncyBtZW1vcnkgbGF5b3V0Lgo+Pj4+Pj4+PiAr ICogZGV0YWlsZWQgZGVzY3JpcHRpb246Cj4+Pj4+Pj4+ICsgKiAgICAgICAgIDAgICAgICAgICAg ICAgICAgMSAgICAgICAgICAgICAgICAgMiAgICAgICAgICAgICAgIDMgICAgICAgIG9jdGV0Cj4+ Pj4+Pj4+ICsgKiArLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0t LS0tLS0rLS0tLS0tLS0tLS0tLS0tLSsKPj4+Pj4+Pj4gKyAqIHwgICAgICAgICAgICAgICBpZCAg ICAgICAgICAgICAgICB8X0dFVF9CVUZfREVUQUlMU3wgICByZXNlcnZlZCAgICAgfCA0Cj4+Pj4+ Pj4+ICsgKiArLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0t LS0rLS0tLS0tLS0tLS0tLS0tLSsKPj4+Pj4+Pj4gKyAqIHwgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICByZXNlcnZlZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCA4Cj4+Pj4+Pj4+ ICsgKiArLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0r LS0tLS0tLS0tLS0tLS0tLSsKPj4+Pj4+Pj4gKyAqIHwvXC9cL1wvXC9cL1wvXC9cL1wvXC9cL1wv XC9cL1wvXC9cL1wvXC9cL1wvXC9cL1wvXC9cL1wvXC9cL1wvXC9cL1wvfAo+Pj4+Pj4+PiArICog Ky0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKy0tLS0t LS0tLS0tLS0tLS0rCj4+Pj4+Pj4+ICsgKiB8ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg cmVzZXJ2ZWQgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgNjQKPj4+Pj4+Pj4gKyAqICst LS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0t LS0tLS0tLS0tKwo+Pj4+Pj4+PiArICoKPj4+Pj4+Pj4gKyAqIFNlZSByZXNwb25zZSBmb3JtYXQg Zm9yIHRoaXMgcmVxdWVzdC4KPj4+Pj4+Pj4gKyAqCj4+Pj4+Pj4+ICsgKgo+Pj4+Pj4+PiArICog UmVxdWVzdCBjYW1lcmEgYnVmZmVyIGNyZWF0aW9uOgo+Pj4+Pj4+PiArICogICAgICAgICAwICAg ICAgICAgICAgICAgIDEgICAgICAgICAgICAgICAgIDIgICAgICAgICAgICAgICAzICAgICAgICBv Y3RldAo+Pj4+Pj4+PiArICogKy0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLSstLS0t LS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rCj4+Pj4+Pj4+ICsgKiB8ICAgICAgICAgICAg ICAgaWQgICAgICAgICAgICAgICAgfCBfT1BfQlVGX0NSRUFURSB8ICAgcmVzZXJ2ZWQgICAgIHwg NAo+Pj4+Pj4+PiArICogKy0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0t LS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rCj4+Pj4+Pj4+ICsgKiB8ICAgICAgICAgICAgICAg ICAgICAgICAgICAgICByZXNlcnZlZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgOAo+ Pj4+Pj4+PiArICogKy0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0t LS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rCj4+Pj4+Pj4+ICsgKiB8ICAgICAgaW5kZXggICAgIHwg ICAgICAgICAgICAgICAgICAgICByZXNlcnZlZCAgICAgICAgICAgICAgICAgICAgIHwgMTIKPj4+ Pj4+Pj4gKyAqICstLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0t LS0tLSstLS0tLS0tLS0tLS0tLS0tKwo+Pj4+Pj4+PiArICogfCAgICAgICAgICAgICAgICAgICAg ICAgICAgIGdyZWZfZGlyZWN0b3J5ICAgICAgICAgICAgICAgICAgICAgICAgICB8IDE2Cj4+Pj4+ Pj4+ICsgKiArLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0t LS0rLS0tLS0tLS0tLS0tLS0tLSsKPj4+Pj4+Pj4gKyAqIHwgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIHJlc2VydmVkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAyMAo+Pj4+Pj4+ PiArICogKy0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0t Ky0tLS0tLS0tLS0tLS0tLS0rCj4+Pj4+Pj4+ICsgKiB8L1wvXC9cL1wvXC9cL1wvXC9cL1wvXC9c L1wvXC9cL1wvXC9cL1wvXC9cL1wvXC9cL1wvXC9cL1wvXC9cL1wvXC9cL3wKPj4+Pj4+Pj4gKyAq ICstLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLSstLS0t LS0tLS0tLS0tLS0tKwo+Pj4+Pj4+PiArICogfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAg cmVzZXJ2ZWQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IDY0Cj4+Pj4+Pj4+ICsgKiAr LS0tLS0tLS0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tKy0tLS0tLS0tLS0tLS0tLS0rLS0tLS0t LS0tLS0tLS0tLSsKPj4+Pj4+Pj4gKyAqCj4+Pj4+Pj4+ICsgKiBBbiBhdHRlbXB0IHRvIGNyZWF0 ZSBtdWx0aXBsZSBidWZmZXJzIHdpdGggdGhlIHNhbWUgaW5kZXggaXMgYW4gZXJyb3IuCj4+Pj4+ Pj4+ICsgKiBpbmRleCBjYW4gYmUgcmUtdXNlZCBhZnRlciBkZXN0cm95aW5nIHRoZSBjb3JyZXNw b25kaW5nIGNhbWVyYSBidWZmZXIuCj4+Pj4+Pj4+ICsgKgo+Pj4+Pj4+PiArICogaW5kZXggLSB1 aW50OF90LCBpbmRleCBvZiB0aGUgYnVmZmVyIHRvIGJlIGNyZWF0ZWQuCj4+Pj4+Pj4+ICsgKiBn cmVmX2RpcmVjdG9yeSAtIGdyYW50X3JlZl90LCBhIHJlZmVyZW5jZSB0byB0aGUgZmlyc3Qgc2hh cmVkIHBhZ2UKPj4+Pj4+Pj4gKyAqICAgZGVzY3JpYmluZyBzaGFyZWQgYnVmZmVyIHJlZmVyZW5j ZXMuIFRoZSBzaXplIG9mIHRoZSBidWZmZXIgaXMgZXF1YWwgdG8KPj4+Pj4+Pj4gKyAqICAgWEVO Q0FNRVJBX09QX0dFVF9CVUZfREVUQUlMUy5zaXplIHJlc3BvbnNlLiBBdCBsZWFzdCBvbmUgcGFn ZSBleGlzdHMuIElmCj4+Pj4+Pj4+ICsgKiAgIHNoYXJlZCBidWZmZXIgc2l6ZSBleGNlZWRzIHdo YXQgY2FuIGJlIGFkZHJlc3NlZCBieSB0aGlzIHNpbmdsZSBwYWdlLAo+Pj4+Pj4+PiArICogICB0 aGVuIHJlZmVyZW5jZSB0byB0aGUgbmV4dCBzaGFyZWQgcGFnZSBtdXN0IGJlIHN1cHBsaWVkIChz ZWUKPj4+Pj4+Pj4gKyAqICAgZ3JlZl9kaXJfbmV4dF9wYWdlIGJlbG93KS4KPj4+Pj4+PiBJdCBt aWdodCBiZSBiZXR0ZXIgdG8gYWxsb2NhdGUgYWxsIGJ1ZmZlcnMgaW4gb25lIGdvLCBpLmUuIHdo YXQgVklESU9DX1JFUUJVRlMKPj4+Pj4+PiBkb2VzLgo+Pj4+Pj4gV2VsbCwgSSBzdGlsbCB0aGlu ayBpdCBpcyBiZXR0ZXIgdG8gaGF2ZSBhIHBlciBidWZmZXIgaW50ZXJmYWNlCj4+Pj4+PiBpbiB0 aGUgcHJvdG9jb2wgYXMgaXQgaXMgZG9uZSBmb3Igb3RoZXIgWGVuIHZpcnR1YWwgZGV2aWNlcy4K Pj4+Pj4+IFNvLCBJJ2xsIGtlZXAgdGhpcyBhcyBpcyBmb3Igbm93OiBWSURJT0NfUkVRQlVGUyBj YW4gc3RpbGwgZG8KPj4+Pj4+IHdoYXQgaXQgZG9lcyBpbnRlcm5hbGx5IGluIHRoZSBmcm9udGVu ZCBkcml2ZXIKPj4+Pj4gSSBtYXkgaGF2ZSBtaXN1bmRlcnN0b29kIHRoZSBvcmlnaW5hbCBBUEku IFRoZSBuZXdseSBwcm9wb3NlZCBYRU5DQU1FUkFfT1BfQlVGX1JFUVVFU1QKPj4+Pj4gbWFwcyB0 byBSRVFCVUZTLCByaWdodD8gQW5kIHRoZW4gQlVGX0NSRUFURS9ERVNUUk9ZIGp1c3Qgc2V0IHVw IHRoZSBzaGFyZWQgYnVmZmVyCj4+Pj4+IG1hcHBpbmdzIGZvciB0aGUgYnVmZmVycyBjcmVhdGVk IGJ5IFJFUUJVRlMuIElmIHRoYXQncyB0aGUgc2VxdWVuY2UsIHRoZW4gaXQgbWFrZXMKPj4+Pj4g c2Vuc2UuIEknbSBub3Qgc3VyZSBhYm91dCB0aGUgbmFtaW5nLgo+Pj4+Pgo+Pj4+PiBZb3UgbWln aHQgd2FudCB0byBtYWtlIGl0IGNsZWFyIHRoYXQgWEVOQ0FNRVJBX09QX0JVRl9SRVFVRVNUIGFs bG9jYXRlcyB0aGUgYnVmZmVycwo+Pj4+PiBvbiB0aGUgYmFja2VuZCwgYW5kIHNvIGNhbiBmYWls LiBBbHNvLCB0aGUgYWN0dWFsIG51bWJlciBvZiBhbGxvY2F0ZWQgYnVmZmVycyBpbgo+Pj4+PiBj YXNlIG9mIHN1Y2Nlc3MgY2FuIGJlIG1vcmUgb3IgbGVzcyB0aGFuIHdoYXQgd2FzIHJlcXVlc3Rl ZC4KPj4+PiBUaGUgYnVmZmVycyBjYW4gYmUgYWxsb2NhdGVkIGFuZCBzaGFyZWQgYnkgZWl0aGVy IGJhY2tlbmQgb3IgZnJvbnRlbmQ6IHNlZQo+Pj4+ICJiZS1hbGxvYyIgY29uZmlndXJhdGlvbiBv cHRpb24gdGVsbGluZyB3aGljaCBkb21haW4gKFZNKSBzaGFyZXMKPj4+PiB0aGUgWGVuIGdyYW50 IHJlZmVyZW5jZXMgdG8gdGhlIHBhZ2VzIG9mIHRoZSBidWZmZXI6IGVpdGhlciBmcm9udGVuZAo+ Pj4+IG9yIGJhY2tlbmQuCj4+PiBJZiB5b3Ugd2FudCB0byBkbyB6ZXJvLWNvcHkgdmlkZW8gY2Fw dHVyZSwKPj4gdGhpcyBpcyB0aGUgZ29hbAo+Pj4gICAgdGhlbiB5b3UgbmVlZCB0byBrbm93IHdo aWNoCj4+PiBkZXZpY2UgaW4geW91ciB2aWRlbyBwaXBlbGluZSAod2hpY2ggbm93IGNvdmVycyBi b3RoIGFjdHVhbCBoYXJkd2FyZSBhbmQKPj4+IG11bHRpcGxlIFZNcykgaGFzIHRoZSBzdHJpY3Rl c3QgbWVtb3J5IGxheW91dCByZXF1aXJlbWVudHMuIE9mdGVuIHRoZQo+Pj4gdmlkZW8gSFcgcmVx dWlyZXMgY29udGlndW91cyBwaHlzaWNhbCBtZW1vcnkgZm9yIHRoZSBidWZmZXJzLCB3aGljaCBt ZWFucwo+Pj4geW91IGNhbid0IGp1c3QgZ2l2ZSBpdCBhIHBpZWNlIG9mIG5vbi1jb250aWcgbWVt b3J5IGFsbG9jYXRlZCBlbHNld2hlcmUuCj4+IFdlIGhhdmUgYWxyZWFkeSBpbXBsZW1lbnRlZCB6 ZXJvIGNvcHlpbmcgdXNlLWNhc2VzIGZvcgo+PiB2aXJ0dWFsIGRpc3BsYXksIHBsZWFzZSBzZWUg WzFdIGFuZCBbMl0gd2hpY2ggYXJlIGRtYS1idWYKPj4gYmFzZWQgd2hpY2ggY2FuIGNvcGUgd2l0 aCByZWFsIEhXIHJlc3RyaWN0aW9ucyB5b3UgbWVudGlvbi4KPj4gQW5kIGluIHRoYXQgY2FzZSB3 ZSBjYW4gaW1wbGVtZW50IHplcm8tY29weWluZyBib3RoIHdheXMsCj4+IGUuZy4gd2hlbiB0aGUg WGVuIGdyYW50IHJlZmVyZW5jZXMgYXJlIHNoYXJlZCBieSBlaXRoZXIKPj4gYmFja2VuZCBvciBm cm9udGVuZC4gVGhpcyBpcyBkaWZmZXJlbnQgZnJvbSBjYW1lcmEgdXNlLWNhc2VzOgo+PiBhIHNp bmdsZSBidWZmZXIgbmVlZHMgdG8gYmUgc2hhcmVkIHdpdGggbXVsdGlwbGUgZnJvbnRlbmRzLAo+ PiBzbyB6ZXJvLWNvcHlpbmcgaXMgb25seSBwb3NzaWJsZSB3aGVuIGJhY2tlbmQgYWxsb2NhdGVz IHRoZSByZWZlcmVuY2VzCj4+IGFuZCBzaGFyZXMgdGhvc2Ugd2l0aCBmcm9udGVuZHMuIFRoZSB3 YXkgd2hlbiBmcm9udGVuZCBhbGxvY2F0ZXMKPj4gdGhlIGJ1ZmZlcnMgYW5kIHN0aWxsIHdlIGNh biBpbXBsZW1lbnQgemVyby1jb3B5aW5nIGlzIHdoZW4KPj4gdGhlcmUgaXMgYSBzaW5nbGUgZnJv bnRlbmQgaW4gdGhlIHN5c3RlbSwgb3RoZXJ3aXNlIHdlCj4+IG5lZWQgdG8gY29weSB0aGUgaW1h Z2VzIGZyb20gYmFja2VuZCdzIGJ1ZmZlcnMgaW50byBmcm9udGVuZCdzCj4+IG9uZXMuCj4gT0su IFRoZSBpbXBvcnRhbnQgdGhpbmcgaXMgdGhhdCB5b3UgdGhvdWdodCBhYm91dCB0aGlzIDotKQpT dXJlLCBjb3B5aW5nIGtpbGxzIHBlcmZvcm1hbmNlLi4uCj4KPj4+IEluIHByYWN0aWNlIHlvdSBo YXZlIHR3byBwb3NzaWJsZSBtZW1vcnkgbW9kZWxzIHlvdSBjYW4gdXNlIHdpdGggVjRMMiBkcml2 ZXJzOgo+Pj4gTU1BUCAoaS5lLiBhbGxvY2F0ZWQgYnkgdGhlIGRyaXZlciBhbmQgdGhlIGJ1ZmZl cnMgY2FuLCBpZiBuZWVkZWQsIGJlIGV4cG9ydGVkCj4+PiBhcyBkbWFidWYgaGFuZGxlcyB3aXRo IFZJRElPQ19FWFBCVUYpLCBvciBETUFCVUYgd2hlcmUgYnVmZmVycyBhcmUgYWxsb2NhdGVkCj4+ PiBlbHNld2hlcmUgYW5kIGltcG9ydGVkIHRvIFY0TDIsIHdoaWNoIG1heSBmYWlsIGlmIGl0IGRv ZXNuJ3QgbWF0Y2ggdGhlIEhXCj4+PiByZXF1aXJlbWVudHMuCj4+IEZvciB0aGUgZnJvbnRlbmQg aXQgaXMgcG9zc2libGUgdG8gd29yayB3aXRoIGJvdGggTU1BUC9ETUFCVUYKPj4gYW5kIHRoZSBy ZXN0IGlzIG9uIHRoZSBiYWNrZW5kJ3Mgc2lkZSAtIHRoaXMgd2FzIHByb3ZlbiBieQo+PiB2aXJ0 dWFsIGRpc3BsYXkgaW1wbGVtZW50YXRpb24sIHNvIEkgc2VlIG5vIHByb2JsZW0gaGVyZQo+PiBm b3IgdmlydHVhbCBjYW1lcmEuCj4+Pj4gU28sIEkgd2FzIG1vcmUgdGhpbmtpbmcgdGhhdCBpbiBj YXNlIG9mIFY0TDIgYmFzZWQgZnJvbnRlbmQgZHJpdmVyOgo+Pj4+IDEuIEZyb250ZW5kIHNlcnZl cyBSRVFCVUZTIGlvY3RsIGFuZCBhc2tzIHRoZSBiYWNrZW5kIHdpdGgKPj4+PiBYRU5DQU1FUkFf T1BfQlVGX1JFUVVFU1QKPj4+PiBpZiBpdCBjYW4gaGFuZGxlIHRoYXQgbWFueSBidWZmZXJzIGFu ZCBnZXRzIG51bWJlciBvZiBidWZmZXJzIHRvIGJlIHVzZWQKPj4+PiBhbmQgYnVmZmVyIHN0cnVj dHVyZSAobnVtYmVyIG9mIHBsYW5lcywgc2l6ZXMsIG9mZnNldHMgZXRjLikgYXMgdGhlIHJlcGx5 Cj4+Pj4gdG8gdGhhdCByZXF1ZXN0Cj4+Pj4gMi4gRnJvbnRlbmQgY3JlYXRlcyBuIGJ1ZmZlcnMg d2l0aCBYRU5DQU1FUkFfT1BfQlVGX0NSRUFURQo+Pj4+IDMuIEZyb250ZW5kIHJldHVybnMgZnJv bSBSRVFCVUZTIGlvY3RsIHdpdGggYWN0dWFsIG51bWJlciBvZiBidWZmZXJzCj4+Pj4gYWxsb2Nh dGVkCj4gUmVnYXJkcywKPgo+IAlIYW5zClRoYW5rIHlvdSwKT2xla3NhbmRyCgpbMV0gCmh0dHBz Oi8vaHZlcmt1aWwuaG9tZS54czRhbGwubmwvc3BlYy91YXBpL3Y0bC9jb2xvcnNwYWNlcy1kZWZz Lmh0bWwjYy52NGwyX2NvbG9yc3BhY2UKWzJdIApodHRwczovL2h2ZXJrdWlsLmhvbWUueHM0YWxs Lm5sL3NwZWMvdWFwaS92NGwvY29sb3JzcGFjZXMtZGVmcy5odG1sI2MudjRsMl95Y2Jjcl9lbmNv ZGluZwpbM10gCmh0dHBzOi8vaHZlcmt1aWwuaG9tZS54czRhbGwubmwvc3BlYy91YXBpL3Y0bC9j b2xvcnNwYWNlcy1kZWZzLmh0bWwjYy52NGwyX3F1YW50aXphdGlvbgpbNF0gCmh0dHBzOi8vaHZl cmt1aWwuaG9tZS54czRhbGwubmwvc3BlYy91YXBpL3Y0bC9jb2xvcnNwYWNlcy1kZWZzLmh0bWwj Yy52NGwyX3hmZXJfZnVuYwoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX18KWGVuLWRldmVsIG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVucHJvamVj dC5vcmcKaHR0cHM6Ly9saXN0cy54ZW5wcm9qZWN0Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL3hlbi1k ZXZlbA==