Skip to contentSkip to conversation

Improve latency of IR decoding

PATCH New Sean Young 2 participants 7 messages Mar 24, 2018 – Apr 4, 2018

Subsystems (5)
lore
Share & tools
lore

Sean Young

author maintainer
#0 lore raw

cover Improve latency of IR decoding

The current IR decoding is much too slow. Many IR protocols rely on a trailing space for decoding (e.g. rc-6 needs to know when the bits end). The trailing space is generated by the IR timeout, and if this is longer than required, keys can be perceived as sticky and slugish.

The other issue the keyup timer. IR has no concept of a keyup message, this is implied by the absence of IR. So, minimising the timeout for this further improves the handling.

With these patches in place, using IR with the builtin decoders is much improved and feels very snappy.

Sean Young (3):
media: rc: set timeout to smallest value required by enabled protocols
media: rc: add ioctl to get the current timeout
media: rc: per-protocol repeat period and minimum keyup timer

 Documentation/media/uapi/rc/lirc-func.rst          |  1 +
 .../media/uapi/rc/lirc-set-rec-timeout.rst         | 14 +++--
 drivers/media/cec/cec-core.c                       |  2 +-
 drivers/media/rc/ir-imon-decoder.c                 |  1 +
 drivers/media/rc/ir-jvc-decoder.c                  |  1 +
 drivers/media/rc/ir-mce_kbd-decoder.c              |  1 +
 drivers/media/rc/ir-nec-decoder.c                  |  1 +
 drivers/media/rc/ir-rc5-decoder.c                  |  1 +
 drivers/media/rc/ir-rc6-decoder.c                  |  1 +
 drivers/media/rc/ir-sanyo-decoder.c                |  1 +
 drivers/media/rc/ir-sharp-decoder.c                |  1 +
 drivers/media/rc/ir-sony-decoder.c                 |  1 +
 drivers/media/rc/ir-xmp-decoder.c                  |  1 +
 drivers/media/rc/lirc_dev.c                        |  9 ++-
 drivers/media/rc/rc-core-priv.h                    |  1 +
 drivers/media/rc/rc-ir-raw.c                       | 31 +++++++++-
 drivers/media/rc/rc-main.c                         | 68 +++++++++++-----------
 include/uapi/linux/lirc.h                          |  6 ++
 18 files changed, 101 insertions(+), 41 deletions(-)
Signature · 1 line
2.14.3
author maintainer
#1 lore raw

PATCH 1/3 media: rc: set timeout to smallest value required by enabled protocols

The longer the IR timeout, the longer we wait until delivering each scancode. By reducing this timeout, we reduce the time it take for the last scancode to be delivered.

Note that the lirc daemon disables all protocols, in case we revert back to the default value.

---
 drivers/media/rc/ir-imon-decoder.c    |  1 +
 drivers/media/rc/ir-jvc-decoder.c     |  1 +
 drivers/media/rc/ir-mce_kbd-decoder.c |  1 +
 drivers/media/rc/ir-nec-decoder.c     |  1 +
 drivers/media/rc/ir-rc5-decoder.c     |  1 +
 drivers/media/rc/ir-rc6-decoder.c     |  1 +
 drivers/media/rc/ir-sanyo-decoder.c   |  1 +
 drivers/media/rc/ir-sharp-decoder.c   |  1 +
 drivers/media/rc/ir-sony-decoder.c    |  1 +
 drivers/media/rc/ir-xmp-decoder.c     |  1 +
 drivers/media/rc/rc-core-priv.h       |  1 +
 drivers/media/rc/rc-ir-raw.c          | 31 ++++++++++++++++++++++++++++++-
 drivers/media/rc/rc-main.c            | 12 ++++++------
 13 files changed, 47 insertions(+), 7 deletions(-)
drivers/media/rc/ir-imon-decoder.c +1 -0
index a1ff06a26542..9024b359e5ee 100644
@@ -170,6 +170,7 @@ static struct ir_raw_handler imon_handler = {
 	.decode		= ir_imon_decode,
 	.encode		= ir_imon_encode,
 	.carrier	= 38000,
+	.max_space	= IMON_UNIT * IMON_BITS * 2,
 };
 
 static int __init ir_imon_decode_init(void)
drivers/media/rc/ir-jvc-decoder.c +1 -0
index 8cb68ae43282..190c690b14f8 100644
@@ -213,6 +213,7 @@ static struct ir_raw_handler jvc_handler = {
 	.decode		= ir_jvc_decode,
 	.encode		= ir_jvc_encode,
 	.carrier	= 38000,
+	.max_space	= JVC_TRAILER_SPACE,
 };
 
 static int __init ir_jvc_decode_init(void)
drivers/media/rc/ir-mce_kbd-decoder.c +1 -0
index c110984ca671..ae4b980c4a16 100644
@@ -475,6 +475,7 @@ static struct ir_raw_handler mce_kbd_handler = {
 	.raw_register	= ir_mce_kbd_register,
 	.raw_unregister	= ir_mce_kbd_unregister,
 	.carrier	= 36000,
+	.max_space	= MCIR2_MAX_LEN,
 };
 
 static int __init ir_mce_kbd_decode_init(void)
drivers/media/rc/ir-nec-decoder.c +1 -0
index 21647b809e6f..fac12f867a81 100644
@@ -253,6 +253,7 @@ static struct ir_raw_handler nec_handler = {
 	.decode		= ir_nec_decode,
 	.encode		= ir_nec_encode,
 	.carrier	= 38000,
+	.max_space	= NEC_TRAILER_SPACE,
 };
 
 static int __init ir_nec_decode_init(void)
drivers/media/rc/ir-rc5-decoder.c +1 -0
index 74d3b859c3a2..711068c8de90 100644
@@ -274,6 +274,7 @@ static struct ir_raw_handler rc5_handler = {
 	.decode		= ir_rc5_decode,
 	.encode		= ir_rc5_encode,
 	.carrier	= 36000,
+	.max_space	= RC5_TRAILER,
 };
 
 static int __init ir_rc5_decode_init(void)
drivers/media/rc/ir-rc6-decoder.c +1 -0
index 8314da32453f..9cc4820878c7 100644
@@ -394,6 +394,7 @@ static struct ir_raw_handler rc6_handler = {
 	.decode		= ir_rc6_decode,
 	.encode		= ir_rc6_encode,
 	.carrier	= 36000,
+	.max_space	= RC6_SUFFIX_SPACE,
 };
 
 static int __init ir_rc6_decode_init(void)
drivers/media/rc/ir-sanyo-decoder.c +1 -0
index 4efe6db5376a..e72787b446c9 100644
@@ -210,6 +210,7 @@ static struct ir_raw_handler sanyo_handler = {
 	.decode		= ir_sanyo_decode,
 	.encode		= ir_sanyo_encode,
 	.carrier	= 38000,
+	.max_space	= SANYO_TRAILER_SPACE,
 };
 
 static int __init ir_sanyo_decode_init(void)
drivers/media/rc/ir-sharp-decoder.c +1 -0
index 6a38c50566a4..ccbd4c12d1d7 100644
@@ -226,6 +226,7 @@ static struct ir_raw_handler sharp_handler = {
 	.decode		= ir_sharp_decode,
 	.encode		= ir_sharp_encode,
 	.carrier	= 38000,
+	.max_space	= SHARP_TRAILER_SPACE,
 };
 
 static int __init ir_sharp_decode_init(void)
drivers/media/rc/ir-sony-decoder.c +1 -0
index 6764ec9de646..598bae8d8ffb 100644
@@ -224,6 +224,7 @@ static struct ir_raw_handler sony_handler = {
 	.decode		= ir_sony_decode,
 	.encode		= ir_sony_encode,
 	.carrier	= 40000,
+	.max_space	= SONY_TRAILER_SPACE,
 };
 
 static int __init ir_sony_decode_init(void)
drivers/media/rc/ir-xmp-decoder.c +1 -0
index 58b47af1a763..e005a75a86fe 100644
@@ -199,6 +199,7 @@ static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev)
 static struct ir_raw_handler xmp_handler = {
 	.protocols	= RC_PROTO_BIT_XMP,
 	.decode		= ir_xmp_decode,
+	.max_space	= XMP_TRAILER_SPACE,
 };
 
 static int __init ir_xmp_decode_init(void)
drivers/media/rc/rc-core-priv.h +1 -0
index e0e6a17460f6..8c38941295b8 100644
@@ -37,6 +37,7 @@ struct ir_raw_handler {
 	int (*encode)(enum rc_proto protocol, u32 scancode,
 		      struct ir_raw_event *events, unsigned int max);
 	u32 carrier;
+	u32 max_space;
 
 	/* These two should only be used by the mce kbd decoder */
 	int (*raw_register)(struct rc_dev *dev);
drivers/media/rc/rc-ir-raw.c +30 -1
index 374f83105a23..f4e1fd95f839 100644
@@ -233,7 +233,36 @@ ir_raw_get_allowed_protocols(void)
 
 static int change_protocol(struct rc_dev *dev, u64 *rc_proto)
 {
-	/* the caller will update dev->enabled_protocols */
+	struct ir_raw_handler *handler;
+	u32 timeout = 0;
+
+	if (!dev->max_timeout)
+		return 0;
+
+	mutex_lock(&ir_raw_handler_lock);
+	list_for_each_entry(handler, &ir_raw_handler_list, list) {
+		if (handler->protocols & *rc_proto) {
+			if (timeout < handler->max_space)
+				timeout = handler->max_space;
+		}
+	}
+	mutex_unlock(&ir_raw_handler_lock);
+
+	if (timeout == 0)
+		timeout = IR_DEFAULT_TIMEOUT;
+	else
+		timeout += MS_TO_NS(10);
+
+	if (timeout < dev->min_timeout)
+		timeout = dev->min_timeout;
+	else if (timeout > dev->max_timeout)
+		timeout = dev->max_timeout;
+
+	if (dev->s_timeout)
+		dev->s_timeout(dev, timeout);
+	else
+		dev->timeout = timeout;
+
 	return 0;
 }
 
drivers/media/rc/rc-main.c +6 -6
index b67be33bd62f..6a720e9c7aa8 100644
@@ -1241,6 +1241,9 @@ static ssize_t store_protocols(struct device *device,
 	if (rc < 0)
 		goto out;
 
+	if (dev->driver_type == RC_DRIVER_IR_RAW)
+		ir_raw_load_modules(&new_protocols);
+
 	rc = dev->change_protocol(dev, &new_protocols);
 	if (rc < 0) {
 		dev_dbg(&dev->dev, "Error setting protocols to 0x%llx\n",
@@ -1248,9 +1251,6 @@ static ssize_t store_protocols(struct device *device,
 		goto out;
 	}
 
-	if (dev->driver_type == RC_DRIVER_IR_RAW)
-		ir_raw_load_modules(&new_protocols);
-
 	if (new_protocols != old_protocols) {
 		*current_protocols = new_protocols;
 		dev_dbg(&dev->dev, "Protocols changed to 0x%llx\n",
@@ -1735,6 +1735,9 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
 	if (dev->driver_type == RC_DRIVER_SCANCODE && !dev->change_protocol)
 		dev->enabled_protocols = dev->allowed_protocols;
 
+	if (dev->driver_type == RC_DRIVER_IR_RAW)
+		ir_raw_load_modules(&rc_proto);
+
 	if (dev->change_protocol) {
 		rc = dev->change_protocol(dev, &rc_proto);
 		if (rc < 0)
@@ -1742,9 +1745,6 @@ static int rc_prepare_rx_device(struct rc_dev *dev)
 		dev->enabled_protocols = rc_proto;
 	}
 
-	if (dev->driver_type == RC_DRIVER_IR_RAW)
-		ir_raw_load_modules(&rc_proto);
-
 	set_bit(EV_KEY, dev->input_dev->evbit);
 	set_bit(EV_REP, dev->input_dev->evbit);
 	set_bit(EV_MSC, dev->input_dev->evbit);
Signature · 1 line
2.14.3
author maintainer
#2 lore raw

PATCH 2/3 media: rc: add ioctl to get the current timeout

In reply to Sean Young

Since the kernel now modifies the timeout, make it possible to retrieve the current value.

---
 Documentation/media/uapi/rc/lirc-func.rst            |  1 +
 Documentation/media/uapi/rc/lirc-set-rec-timeout.rst | 14 +++++++++-----
 drivers/media/rc/lirc_dev.c                          |  7 +++++++
 include/uapi/linux/lirc.h                            |  6 ++++++
 4 files changed, 23 insertions(+), 5 deletions(-)
Documentation/media/uapi/rc/lirc-func.rst +1 -0
index ddb4620de294..9656423a3f28 100644
@@ -17,6 +17,7 @@ LIRC Function Reference
     lirc-get-rec-resolution
     lirc-set-send-duty-cycle
     lirc-get-timeout
+    lirc-get-rec-timeout
     lirc-set-rec-timeout
     lirc-set-rec-carrier
     lirc-set-rec-carrier-range
Documentation/media/uapi/rc/lirc-set-rec-timeout.rst +9 -5
index b3e16bbdbc90..a833a6a4c25a 100644
@@ -1,19 +1,23 @@
 .. -*- coding: utf-8; mode: rst -*-
 
 .. _lirc_set_rec_timeout:
+.. _lirc_get_rec_timeout:
 
-**************************
-ioctl LIRC_SET_REC_TIMEOUT
-**************************
+***************************************************
+ioctl LIRC_GET_REC_TIMEOUT and LIRC_SET_REC_TIMEOUT
+***************************************************
 
 Name
 ====
 
-LIRC_SET_REC_TIMEOUT - sets the integer value for IR inactivity timeout.
+LIRC_GET_REC_TIMEOUT/LIRC_SET_REC_TIMEOUT - Get/set the integer value for IR inactivity timeout.
 
 Synopsis
 ========
 
+.. c:function:: int ioctl( int fd, LIRC_GET_REC_TIMEOUT, __u32 *timeout )
+    :name: LIRC_GET_REC_TIMEOUT
+
 .. c:function:: int ioctl( int fd, LIRC_SET_REC_TIMEOUT, __u32 *timeout )
     :name: LIRC_SET_REC_TIMEOUT
 
@@ -30,7 +34,7 @@ Arguments
 Description
 ===========
 
-Sets the integer value for IR inactivity timeout.
+Get and set the integer value for IR inactivity timeout.
 
 If supported by the hardware, setting it to 0  disables all hardware timeouts
 and data should be reported as soon as possible. If the exact value
drivers/media/rc/lirc_dev.c +7 -0
index 24e9fbb80e81..17f40c8e939f 100644
@@ -575,6 +575,13 @@ static long ir_lirc_ioctl(struct file *file, unsigned int cmd,
 		}
 		break;
 
+	case LIRC_GET_REC_TIMEOUT:
+		if (!dev->timeout)
+			ret = -ENOTTY;
+		else
+			val = DIV_ROUND_UP(dev->timeout, 1000);
+		break;
+
 	case LIRC_SET_REC_TIMEOUT_REPORTS:
 		if (!dev->timeout)
 			ret = -ENOTTY;
include/uapi/linux/lirc.h +6 -0
index 948d9a491083..7db6063fa6a2 100644
@@ -134,6 +134,12 @@
 
 #define LIRC_SET_WIDEBAND_RECEIVER     _IOW('i', 0x00000023, __u32)
 
+/*
+ * Return the recording timeout, which is either set by
+ * the ioctl LIRC_SET_REC_TIMEOUT or by the kernel after setting the protocols.
+ */
+#define LIRC_GET_REC_TIMEOUT	       _IOR('i', 0x00000024, __u32)
+
 /*
  * struct lirc_scancode - decoded scancode with protocol for use with
  *	LIRC_MODE_SCANCODE
Signature · 1 line
2.14.3
author maintainer
#3 lore raw

PATCH 3/3 media: rc: per-protocol repeat period and minimum keyup timer

In reply to Sean Young

Each IR protocol has its own repeat period. We can minimise the keyup timer to be the protocol period + IR timeout. This makes keys less "sticky" and makes IR more reactive and nicer to use.

This feature was previously attempted in commit d57ea877af38 ("media: rc:
per-protocol repeat period"), but that did not take the IR timeout into account, and had to be reverted.

---
 drivers/media/cec/cec-core.c |  2 +-
 drivers/media/rc/lirc_dev.c  |  2 +-
 drivers/media/rc/rc-main.c   | 56 +++++++++++++++++++++++---------------------
 3 files changed, 31 insertions(+), 29 deletions(-)
drivers/media/cec/cec-core.c +1 -1
index b0c87f9ea08f..b278ab90b387 100644
@@ -322,7 +322,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
 	adap->rc->allowed_protocols = RC_PROTO_BIT_CEC;
 	adap->rc->priv = adap;
 	adap->rc->map_name = RC_MAP_CEC;
-	adap->rc->timeout = MS_TO_NS(100);
+	adap->rc->timeout = MS_TO_NS(550);
 #endif
 	return adap;
 }
drivers/media/rc/lirc_dev.c +1 -1
index 17f40c8e939f..19660f9757e1 100644
@@ -583,7 +583,7 @@ static long ir_lirc_ioctl(struct file *file, unsigned int cmd,
 		break;
 
 	case LIRC_SET_REC_TIMEOUT_REPORTS:
-		if (!dev->timeout)
+		if (dev->driver_type != RC_DRIVER_IR_RAW)
 			ret = -ENOTTY;
 		else
 			fh->send_timeout_reports = !!val;
drivers/media/rc/rc-main.c +29 -27

106 lines not on this page · raw message

Signature · 1 line
2.14.3
#4 lore raw

cover Improve latency of IR decoding

In reply to Sean Young

Hi Sean,

Quoted 11 lines · Sean Young

The current IR decoding is much too slow. Many IR protocols rely on a trailing space for decoding (e.g. rc-6 needs to know when the bits end). The trailing space is generated by the IR timeout, and if this is longer than required, keys can be perceived as sticky and slugish.

The other issue the keyup timer. IR has no concept of a keyup message, this is implied by the absence of IR. So, minimising the timeout for this further improves the handling.

With these patches in place, using IR with the builtin decoders is much improved and feels very snappy.

thanks a lot for the patches!

I didn't have much time to test yet, but quick checks on Amlogic/meson-ir (kernel 4.16-rc7 + media tree + your patches) and Raspberry Pi (RPi foundation kernel 4.14 + my backport of your patches) look really promising.

I found one issue, though, in ir-sharp-decoder.c max_space must be set to SHARP_ECHO_SPACE - otherwise we get a timeout between the normal and inverted message part and decoding fails.

One thing I'm wondering is if the keyup timer marging might be too tight now. Basically we have just the fixed 10ms marging from idle timeout. The repeat periods of the protocols are rather accurate/strict, so (programmable) remotes not sticking to the official timing might cause repeated keyup/down events if they are repeating a tad to slow.

I'm not sure if this could be an issue, but maybe we should add a safety margin to the repeat periods as well? For example 10 or 20 percent of the specced repeat periods. What do you think?

To get some more test coverage I've asked my colleague to include my backport patch in the LibreELEC testbuilds for x86 and RPi. We've got some 500 regular users of these so if something's not working we should find out soon. I just hope I didn't mess up the backport... Here's the link to my 4.14 patch:

https://github.com/HiassofT/LibreELEC.tv/blob/le9-ir-latency/packages/linux/patches/default/linux-999-improve-ir-timeout-handling.patch

so long & thanks,

Hias

Quoted 29 lines

Sean Young (3):
media: rc: set timeout to smallest value required by enabled protocols
media: rc: add ioctl to get the current timeout
media: rc: per-protocol repeat period and minimum keyup timer

 Documentation/media/uapi/rc/lirc-func.rst          |  1 +
 .../media/uapi/rc/lirc-set-rec-timeout.rst         | 14 +++--
 drivers/media/cec/cec-core.c                       |  2 +-
 drivers/media/rc/ir-imon-decoder.c                 |  1 +
 drivers/media/rc/ir-jvc-decoder.c                  |  1 +
 drivers/media/rc/ir-mce_kbd-decoder.c              |  1 +
 drivers/media/rc/ir-nec-decoder.c                  |  1 +
 drivers/media/rc/ir-rc5-decoder.c                  |  1 +
 drivers/media/rc/ir-rc6-decoder.c                  |  1 +
 drivers/media/rc/ir-sanyo-decoder.c                |  1 +
 drivers/media/rc/ir-sharp-decoder.c                |  1 +
 drivers/media/rc/ir-sony-decoder.c                 |  1 +
 drivers/media/rc/ir-xmp-decoder.c                  |  1 +
 drivers/media/rc/lirc_dev.c                        |  9 ++-
 drivers/media/rc/rc-core-priv.h                    |  1 +
 drivers/media/rc/rc-ir-raw.c                       | 31 +++++++++-
 drivers/media/rc/rc-main.c                         | 68 +++++++++++-----------
 include/uapi/linux/lirc.h                          |  6 ++
 18 files changed, 101 insertions(+), 41 deletions(-)
Signature · 1 line
2.14.3
#5 lore raw

cover Improve latency of IR decoding

Hi Sean,

Quoted 33 lines · Matthias Reichl

Hi Sean,

Quoted 11 lines · Sean Young

The current IR decoding is much too slow. Many IR protocols rely on a trailing space for decoding (e.g. rc-6 needs to know when the bits end). The trailing space is generated by the IR timeout, and if this is longer than required, keys can be perceived as sticky and slugish.

The other issue the keyup timer. IR has no concept of a keyup message, this is implied by the absence of IR. So, minimising the timeout for this further improves the handling.

With these patches in place, using IR with the builtin decoders is much improved and feels very snappy.

thanks a lot for the patches!

I didn't have much time to test yet, but quick checks on Amlogic/meson-ir (kernel 4.16-rc7 + media tree + your patches) and Raspberry Pi (RPi foundation kernel 4.14 + my backport of your patches) look really promising.

I found one issue, though, in ir-sharp-decoder.c max_space must be set to SHARP_ECHO_SPACE - otherwise we get a timeout between the normal and inverted message part and decoding fails.

One thing I'm wondering is if the keyup timer marging might be too tight now. Basically we have just the fixed 10ms marging from idle timeout. The repeat periods of the protocols are rather accurate/strict, so (programmable) remotes not sticking to the official timing might cause repeated keyup/down events if they are repeating a tad to slow.

Quoted 8 lines

I'm not sure if this could be an issue, but maybe we should add a safety margin to the repeat periods as well? For example 10 or 20 percent of the specced repeat periods. What do you think?

To get some more test coverage I've asked my colleague to include my backport patch in the LibreELEC testbuilds for x86 and RPi. We've got some 500 regular users of these so if something's not working we should find out soon.

Quick update: testing so far went really smooth, no issues reported since we included the backport patch in LibreELEC testbuilds.

Quote from https://github.com/LibreELEC/LibreELEC.tv/pull/2623#issuecomment-377897518

Quoted 3 lines

This is in my nightly test builds since 28 March, and no problems reported so far.

On my NUC with Harmony One/RC6 remote these commits are working just fine.

I've been using LibreELEC on RPi with the patch (using a gpio ir receiver and a Hauppauge RC-5 remote) since then and everything was fine as well.

so long,

Hias

Quoted 38 lines

I just hope I
didn't mess up the backport... Here's the link to my 4.14 patch:

https://github.com/HiassofT/LibreELEC.tv/blob/le9-ir-latency/packages/linux/patches/default/linux-999-improve-ir-timeout-handling.patch

so long & thanks,

Hias

Quoted 29 lines

Sean Young (3):
media: rc: set timeout to smallest value required by enabled protocols
media: rc: add ioctl to get the current timeout
media: rc: per-protocol repeat period and minimum keyup timer

 Documentation/media/uapi/rc/lirc-func.rst          |  1 +
 .../media/uapi/rc/lirc-set-rec-timeout.rst         | 14 +++--
 drivers/media/cec/cec-core.c                       |  2 +-
 drivers/media/rc/ir-imon-decoder.c                 |  1 +
 drivers/media/rc/ir-jvc-decoder.c                  |  1 +
 drivers/media/rc/ir-mce_kbd-decoder.c              |  1 +
 drivers/media/rc/ir-nec-decoder.c                  |  1 +
 drivers/media/rc/ir-rc5-decoder.c                  |  1 +
 drivers/media/rc/ir-rc6-decoder.c                  |  1 +
 drivers/media/rc/ir-sanyo-decoder.c                |  1 +
 drivers/media/rc/ir-sharp-decoder.c                |  1 +
 drivers/media/rc/ir-sony-decoder.c                 |  1 +
 drivers/media/rc/ir-xmp-decoder.c                  |  1 +
 drivers/media/rc/lirc_dev.c                        |  9 ++-
 drivers/media/rc/rc-core-priv.h                    |  1 +
 drivers/media/rc/rc-ir-raw.c                       | 31 +++++++++-
 drivers/media/rc/rc-main.c                         | 68 +++++++++++-----------
 include/uapi/linux/lirc.h                          |  6 ++
 18 files changed, 101 insertions(+), 41 deletions(-)
Signature · 1 line
2.14.3
author maintainer
#6 lore raw

cover Improve latency of IR decoding

Hi Matthias,

Quoted 18 lines · Matthias Reichl
Quoted 17 lines · Matthias Reichl

Hi Sean,

Quoted 11 lines · Sean Young

The current IR decoding is much too slow. Many IR protocols rely on a trailing space for decoding (e.g. rc-6 needs to know when the bits end). The trailing space is generated by the IR timeout, and if this is longer than required, keys can be perceived as sticky and slugish.

The other issue the keyup timer. IR has no concept of a keyup message, this is implied by the absence of IR. So, minimising the timeout for this further improves the handling.

With these patches in place, using IR with the builtin decoders is much improved and feels very snappy.

thanks a lot for the patches!

Quoted 8 lines
Quoted 8 lines

I didn't have much time to test yet, but quick checks on Amlogic/meson-ir (kernel 4.16-rc7 + media tree + your patches) and Raspberry Pi (RPi foundation kernel 4.14 + my backport of your patches) look really promising.

I found one issue, though, in ir-sharp-decoder.c max_space must be set to SHARP_ECHO_SPACE - otherwise we get a timeout between the normal and inverted message part and decoding fails.

Thanks for spotting that -- you're right!

Quoted 6 lines
Quoted 6 lines

One thing I'm wondering is if the keyup timer marging might be too tight now. Basically we have just the fixed 10ms marging from idle timeout. The repeat periods of the protocols are rather accurate/strict, so (programmable) remotes not sticking to the official timing might cause repeated keyup/down events if they are repeating a tad to slow.

This does need some further thought. There might be delays in the scheduling of the rc decoding thread or the IR hardware might be slow delivering new IR pulse data (e.g. fifo like hardware, e.g. winbond-cir).

Quoted 9 lines
Quoted 8 lines

I'm not sure if this could be an issue, but maybe we should add a safety margin to the repeat periods as well? For example 10 or 20 percent of the specced repeat periods. What do you think?

To get some more test coverage I've asked my colleague to include my backport patch in the LibreELEC testbuilds for x86 and RPi. We've got some 500 regular users of these so if something's not working we should find out soon.

Quoted 4 lines

Quick update: testing so far went really smooth, no issues reported since we included the backport patch in LibreELEC testbuilds.

Quote from https://github.com/LibreELEC/LibreELEC.tv/pull/2623#issuecomment-377897518

Thank you so much for including the patches in the LibreELEC test builds, that really is a great test!

Quoted 7 lines
Quoted 3 lines

This is in my nightly test builds since 28 March, and no problems reported so far.

On my NUC with Harmony One/RC6 remote these commits are working just fine.

I've been using LibreELEC on RPi with the patch (using a gpio ir receiver and a Hauppauge RC-5 remote) since then and everything was fine as well.

That's great. I'd like to do some more testing with various bits of hardware and test all the protocols.

Thanks,

Sean