Reverse engineering Lenkeng HDMI over IP extender

014456_show1

Short time ago, I was searching for a way how to get HDMI output from camera to PC (and then stream on the Internet). There are PCI-x HDMI input cards on the market, but they cost 100$+. Suddenly, I have found a device, which transmitted HDMI signals over IP network for half of the above price so I took the chance. Specification said something about MJPEG so I thought it might be possible.

Beginning

When the package arrived, first thing was to test if it really works as described and it really did – audio and video output from DVD player transmitted through common ethernet switch to my TV. Second thing I did was of course starting wireshark and sniffing the data.

Screenshot from 2014-01-24 07:46:25

I found out, that it uses multicast to two UDP ports (2068 and 2066) and time to time broadcast some control packets.

Extracting video frames

Highest bitrate was on port 2068 what indicated it is video stream. After a while I found a packet with JFIF header (on picture above) – great! data is not encrypted, nor compressed and contains JPEGs. After investigating packets in sequence, I found out following structure in UDP payload:

| 2B – frame number | 2B – frame chunk number | data |
* frame number – (unsigned int, big endian) all chunks within  one JPEG have same frame number, increments by 0x01
* frame chunk number – (unsigned int, big endian) first image chunk is 0x0000, increments by 0x01, last chunk has MSB set to 1

So I searched google for python multicast listener and modified it to save data to .jpeg files according rules above. After running, I was able to see some images with correct size but they were somehow damaged. First few pixels were OK but then there was a mess, like something was missing. Few hours I elaborated with capturing script what could be wrong but then I’ve got an idea: why does wireshark shows malformed packets? After looking on wireshark packets again, I found out, there are some bytes in the end of packet not part of UDP payload.

Screenshot from 2014-01-24 08:19:15

So I googled raw socket listener (thanks Silver Moon) and manually parsed IP and UDP headers to match correct packets and extract UDP payload with trailing bytes any voila! it worked, I’ve got correct JPEG frames.

#!/usr/bin/python

#Packet sniffer in python
#For Linux - Sniffs all incoming and outgoing packets :)
#Silver Moon (m00n.silv3r@gmail.com)
#modified by danman

import socket, sys
from struct import *
import struct

#Convert a string of 6 characters of ethernet address into a dash separated hex string
def eth_addr (a) :
  b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]), ord(a[4]) , ord(a[5]))
  return b

#create a AF_PACKET type raw socket (thats basically packet level)
#define ETH_P_ALL    0x0003          /* Every packet (be careful!!!) */
try:
    s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0x0003))
except socket.error , msg:
    print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#sock.bind(('', 2068))
# wrong: mreq = struct.pack("sl", socket.inet_aton("224.51.105.104"), socket.INADDR_ANY)
#mreq = struct.pack("=4sl", socket.inet_aton("226.2.2.2"), socket.INADDR_ANY)
#sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

sender="000b78006001".decode("hex")
notopen=1
# = open('/tmp/fifo', 'w')

# receive a packet
while True:
    packet = s.recvfrom(65565)

    #packet string from tuple
    packet = packet[0]

    #parse ethernet header
    eth_length = 14

    eth_header = packet[:eth_length]
    eth = unpack('!6s6sH' , eth_header)
    eth_protocol = socket.ntohs(eth[2])

    if (packet[6:12]==sender) & (eth_protocol == 8) :

        #Parse IP header
        #take first 20 characters for the ip header
        ip_header = packet[eth_length:20+eth_length]

        #now unpack them :)
        iph = unpack('!BBHHHBBH4s4s' , ip_header)

        version_ihl = iph[0]
        version = version_ihl >> 4
        ihl = version_ihl & 0xF

        iph_length = ihl * 4

        ttl = iph[5]
        protocol = iph[6]
        s_addr = socket.inet_ntoa(iph[8]);
        d_addr = socket.inet_ntoa(iph[9]);

        #UDP packets
        if protocol == 17 :
            u = iph_length + eth_length
            udph_length = 8
            udp_header = packet[u:u+8]

            #now unpack them :)
            udph = unpack('!HHHH' , udp_header)

            source_port = udph[0]
            dest_port = udph[1]
            length = udph[2]
            checksum = udph[3]

            #get data from the packet
            h_size = eth_length + iph_length + udph_length
            data = packet[h_size:]

            if (dest_port==2068):
              frame_n=ord(data[0])*256+ord(data[1])
              part=ord(data[3])
              print "frame",frame_n,"part",part, "len",len(data),"end?",end
              if (part==0) & notopen:
                 f = open('files/'+str(frame_n)+"_"+str(part).zfill(3)+'.jpg', 'w')
                 notopen=0
              if notopen==0:
                  f.write(data[4:])

Thank you chinese engineers! Because of wrong length in IP header (1044) I have to listen on raw socket!

Initiating stream

All this was done, when both sender and receiver were plugged into network. I also wanted to be able to use only sender and PC. When I plugged in sender only, no stream was broadcasted so I plugged in also the receiver a captured control frames. Each one control packet from receiver was unique so I took payload from the first one and sent it from PC to IP address of sender and I was successful. The sender started to send stream for a few seconds and then stopped. So I started to send control packets one per second and the stream was playing continuously. Then I experimented with length of payload – I started to send shorter frames and I finally found out, that it only needs a few specific bytes. So the final packet is as follows:
Screenshot from 2014-01-25 12:38:41
unicast to 48689/UDP with payload 0x5446367A600200000000000303010026000000000234C2

Extracting audio

Last part of my research was to extract audio from stream. Again, I used wireshark to sniff and analyse packets.
Screenshot from 2014-01-25 12:44:22
I saved the stream to file as raw data and imported into audacity. After trying few formats for importing I found out, that there is some audio playing when set for Signed 32bit PCM, big-endian, stereo, 48Khz.
Screenshot from 2014-01-25 12:48:49
As you can see on the picture, sound was interfered by regular peaks. After investigating packets, I found that the data is well structured except the beginning of payload starting with some 0x00 and 0x55 (as on picture from wireshark). So I took python multicast listener again and truncated first 16bytes from each packet and streamed to stdout:

#!/usr/bin/python

import socket
import struct
import sys

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 2066))
# wrong: mreq = struct.pack("sl", socket.inet_aton("224.51.105.104"), socket.INADDR_ANY)
mreq = struct.pack("=4sl", socket.inet_aton("226.2.2.2"), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
counter=0

while True:
  packet=sock.recv(10240)
  sys.stdout.write(packet[16:])

I started vlc to listen to streamed audio with following command:

./listen-audio.py | vlc --demux=rawaud --rawaud-channels 2 --rawaud-samplerate 48000 --rawaud-fourcc s32b -

and I’ve got audio playing from VLC.

Hardware

Great magic box! As a curious engineer, I definitely had to know what’s inside this gadget. Here are some photos:

IMG_20131123_123422

  • LK-3080-ACL – main processor from Lenkeng
  • IT6604E – HDMI input interface doing HDCP decoding

IMG_20131130_123031

  • LK-3080-ACL – main processor from Lenkeng
  • CAT6612CQ – HDMI out interface

Conclusion

I was searching for solution for live video mixing from cameras with HDMI output. They can be far from mixing computer connected via switches and cheap ethernet technology. With this knowledge I have build a prototype for mixing software in Qt separating input video streams by source IP and mixing/switching them. It’s still in beta phase, but you can see it on my github. If you have any questions or suggestions, feel free to let me know in comment.

Quality test (updated 26/01/2014)

As requested by readers, today I did a speed/quality test. I took jpeg 1080×1920 image and let it play on DVD player. You can compare original and transmitted image here:

new-york-new-york-city-manhattan-manhattan-hotel-millennium filename

Transmitter was streaming 1080p@18fps with 90Mbps bitrate. Unfortunately I have no blue-ray player on hand to test original HD content.

Update 2. Feb 2014

Today I have quickly tested 1080 again and it showed up, that quality is not that bad as on pictures above. Please see following picture. The source was computer showing the same picture in fullscreen mode.

filename

Update 23. May 2014

Together with Tom Warren we modified the script in a way that now it plays correctly in VLC via pipe using this command and code:

./scriptname.py | vlc –

#!/usr/bin/python2

#Packet sniffer in python
#For Linux - Sniffs all incoming and outgoing packets :)
#Silver Moon (m00n.silv3r@gmail.com)
#modified by danman


import socket, sys
from struct import *
import struct
import binascii


#Convert a string of 6 characters of ethernet address into a dash separated hex string

def eth_addr (a) :
  b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (ord(a[0]) , ord(a[1]) , ord(a[2]), ord(a[3]), ord(a[4]) , ord(a[5]))
  return b


#create a AF_PACKET type raw socket (thats basically packet level)
#define ETH_P_ALL    0x0003          /* Every packet (be careful!!!) */
try:
    s = socket.socket( socket.AF_PACKET , socket.SOCK_RAW , socket.ntohs(0x0003))
except socket.error , msg:
    print 'Socket could not be created. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
    sys.exit()


sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#sock.bind(('', 2068))
# wrong: mreq = struct.pack("sl", socket.inet_aton("224.51.105.104"), socket.INADDR_ANY)
mreq = struct.pack("=4sl", socket.inet_aton("226.2.2.2"), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)


sender="000b78006001".decode("hex")
#sender = binascii.a2b_hex("000b78006001")  bc5ff4730e6f
#sender = binascii.a2b_hex("bc5ff4730e6f")
#print binascii.b2a_hex(sender)
notopen=1
# = open('/tmp/fifo', 'w')
print "--myboundary\nContent-Type: image/jpeg\n"

# receive a packet
while True:
    packet = s.recvfrom(65565)

    #packet string from tuple
    packet = packet[0]

    #parse ethernet header
    eth_length = 14

    eth_header = packet[:eth_length]
    eth = unpack('!6s6sH' , eth_header)
    eth_protocol = socket.ntohs(eth[2])


    if (packet[6:12] == sender) & (eth_protocol == 8) :

        #Parse IP header
        #take first 20 characters for the ip header
        ip_header = packet[eth_length:20+eth_length]

        #now unpack them :)
        iph = unpack('!BBHHHBBH4s4s' , ip_header)

        version_ihl = iph[0]
        version = version_ihl >> 4
        ihl = version_ihl & 0xF

        iph_length = ihl * 4

        ttl = iph[5]
        protocol = iph[6]
        s_addr = socket.inet_ntoa(iph[8]);
        d_addr = socket.inet_ntoa(iph[9]);

        #UDP packets
        if protocol == 17 :
            u = iph_length + eth_length
            udph_length = 8
            udp_header = packet[u:u+8]

            #now unpack them :)
            udph = unpack('!HHHH' , udp_header)

            source_port = udph[0]
            dest_port = udph[1]
            length = udph[2]
            checksum = udph[3]

            #get data from the packet
            h_size = eth_length + iph_length + udph_length
            data = packet[h_size:]

            if (dest_port==2068):
              frame_n=ord(data[0])*256+ord(data[1])
              part=ord(data[2])*256+ord(data[3])
              if (part==0) : # & (notopen==1) :
                 #f = open('files/'+str(frame_n)+"_"+str(part).zfill(3)+'.jpg', 'w')
		 #fname = str(frame_n)+"_"+str(part).zfill(3)+'.jpg'
		 #fname = 'file.jpg'
		 print "\n--myboundary\nContent-Type: image/jpeg\n"
                 notopen=0
		 #print 'File ' + str(frame_n) + ' created.'
              if notopen==0:
                 #f.write(data[4:])
		 #print data[4:]
		 sys.stdout.write(data[4:])
		 #with open(fname, 'wb') as fin:
		    #sys.stdout.write(fin.write(data[4:]))
		    #print fin.write(data[4:])

Update 13. Dec 2014

For those who are interested in Windows version, Brian has written .NET version of similar capturer from scratch with a nicely documented project page here.
Brian, thank you for your work.

143 thoughts on “Reverse engineering Lenkeng HDMI over IP extender”

  1. Congratulations! Amazing project and some nice hackery right there. I was thinking for a long time about disk recorder for HDV camcorders. They use firewire for data transfer. It would be easy if you can find small device with FW port and linux OS but it looks like it’s almost impossible – there are no compact devices, small enough to mount in on the camera.

    Your article inspired me to think differently – why use Firewire if we have HDMI present on almost every camcorder? HDMI recorders are also expensive, even HDMI capture cards are out of my price range (not to mention you can’t build small device around it).

    But what if we use one of those HDMI extenders, hook it up to the Raspberry Pi and capture all data to the SD card? It would be simple, small and battery powered – perferct for my application.

    From my understanding you get continous audio stream and every video frame as a separate JPEG file, right? It might be possible to use ffmpeg to compress it with h.264 and write video and data together as a single file (h.264 or maybe less lossy format).

    1. Yes, you are right. Of course, you can take this stream and push it to ffmpeg but this was not my original intention.

      1. For my application image quality is on the first place. I see there is huge quality loss but it might be caused by DVD player (note moire patterns and serration on “teeth” on the edges, typical to scaling down by line skipping). Do you have other device with HDMI port? Some camcorder so you can record footage by the camcorder itself and via HDMI extender then compare.

    1. Thank you, I haven’t tried continuous streaming for such a long time but when I left it conected and powered on for a week, it retained fully functional.

    1. I have used usb to ttl serial converter but I was not able to cummunicate without errors so I gave up. I’ve got some output but the communication was somehow crippled. Maybe I’ll try again later with some other converter. So far I have found it is some sort of debug console.

      1. Show me such communication. Or try again usign a proper shield and SHORT cables. Usual speed is 57600 8n1 or 115200 8n1 but there can be variations.

        1. I have received the device as well and hooked up my jtagulator to the device.
          It’s
          1 = +
          2 = Rx
          3 = Tx
          4 = Gnd
          using 3.3v

          When I send an enter \r\n it sends back
          Unknown Command!!
          TFCMD>

          So I am looking into that currently.

        2. Typing help gave me an item.

          reg : Read/Write reg. of taifa device

          sys : Do some system set

          spi : Read/Write SPI device

          osd : Read/Write SPI device

          gpio : GPIO port Read/Write

          mdio : Read/Write mdio device

          i2c : Read/Write i2c device

          hdmi : Read/Write HdmiTx device

          hdmi : Read/Write HdmiRX device

          dbg : Debug message level

          ch : Audio buffer control

          i2cm : Read/Write i2c device with multi register address

          edid : EDID Read/Write

          3 : Do EP9x53 controller Task

          i2s : T/R audio by I2S mode

          l2 : Set L2 routing table.

          l4 : Set L4 routing table.

          sdram : External SDRAM Test

          cap : Capturer fskp, CRC, bypassSD, shsize, svsize

          ver : Debug Console Version Information

          av : select Tx/Rx format

          q : video quality toggle

          q : show stack status

          fps : show/off fps for test

          inband : inband packet test

          TFCMD>

          1. the “av” command is very important.

            what options does it have?

            probably changing the format is the easier route to follow.

        3. Boot sequence:0123456
          *************************************************
          * Initializeing MM *
          *************************************************
          Start:0x00100000 End:0x00280000, Size:0x00180000(1536K), Pages:384

          TF680 FW Verion: Tx_v1.07_C904 ITE 152MHz IR LAN_MODULE
          FW Release Date: Nov 2 2012, 11:04:55
          TF680 MAC: 00:0B:78:
          TF680 IP: 192.168.168.55
          All of Tasks Created
          [taifa Debug Console]
          (c)2010 taifatech inc. All rights reserved.
          **Type ‘help’ for more details; ‘exit’ to quit**
          TFCMD>
          OtoM TFVEP is disconnected !!!

        4. So here are some commands and their results.
          TFCMD>reg
          WARNING: too few parameters…
          USAGE:
          reg r 90907000 10: read sequentially from reg 0x90907000 len.0x10
          reg w 90907000 aa55aa55 55aa55aa: write 0xaa55aa55, 0x55aa55aa to reg 0x90907000.
          reg f 90907000 aa55aa55 20: write 0xaa55aa55 from reg 0x90907000 to reg 0x9090701f
          reg e : enable/disable message output of wirte operation
          TFCMD>edid
          WARNING: too few parameters…
          USAGE:
          edid r 2 : Read EDID content of HDMI Port 2
          edid w 2 5 : Write EDID 5th content to EPROM for HDMI Port 2
          HDMI EDID : PortI – 5th; PortII – 6th
          TFCMD>sdram
          WARNING: Unknown Option…
          USAGE:
          sdram d startAddr endAddr: SDRAM Data Bus Test
          sdram v baseAddr byteLen: SDRAM Device Test
          sdram s startAddr endAddr: Scan All SDRAM Test
          TFCMD>ver
          Debug Console Version Information
          version:0.2
          TFCMD>av
          WARNING: too few parameters…
          USAGE:
          (for demo only)
          av [video mode=>1:1080p, 2:720p]
          3:960×600
          4:960×544
          5:960×536(1/2 scale down)
          6:1267×728(2/3 scale down)
          7:1440×1080(source 1080p 3/4 scale down)
          8:960×544(source 720p 3/4 scale down)
          9:JPEG Encoder 420 format
          TFCMD>q
          q p [n]: paper quality)
          q d [n]: default quality)
          n: 0 ~ 24(18h), 0 is best, and 24 is worse
          TFCMD>fps
          WARNING: Unknown Option…
          USAGE:
          fps show : show fps
          fps off : off fps
          TFCMD>inband
          WARNING: Unknown Option…
          USAGE:
          send : send test data
          TFCMD>

          1. I have see this. I’d be great if they send us technical datasheet. I asked them but it looks like they don’t won’t to release such documents.

          1. Command “q” is what we should modify. Did you tried to set it for the best quality? Can you post some sample footage?

          2. I took some time to find some sort of service manual for these devices. It looks like SoC is Taifatech TF-680. I couldn’t find any helpful files tho. It looks like these devices have Web control panel so type its IP address to the web browser.

          3. Not yet, I haven’t even connected an hdmi cable or network cable.

            I will not have time today to do so, but I could do that tomorrow evening and post some results.

          4. I’d be thankful for checking what real quality looks like and see if “q” command actually does something. I’m about to order this device myself but I must be sure the quality meets standards for my application.

          5. I have see this. I’d be great if they send us technical datasheet. I asked them but it looks like they don’t won’t to release such documents.

  2. To complete your work you should create 2 stand-alone programs: one to receive (i.e. record) and one to send (i.e. playback) video streams with optional conversion to mpeg 😀

    1. Good suggestion but I’m too lazy to do things I do not need 😀 . I can sell you the reciever and you can continue with the second part 🙂

      1. LOL! I’m lazier than you 🙂
        After inspecting the device I think it’s even expensive for the low quality of the streams it outputs.

  3. There’s an open question being debated on Hackaday about bandwidth vs. quality of these devices. Given that it’s only a 100Mbps port and using MJPEG, there is going to be a definite limit on quality.

    Are you able to provide some bandwidth-usage number (i.e. how close to the max 100Mbps does it get?) as well as some 1080 screenshots of “clean” content, e.g. from a Blu-ray player. That would also answer the HDCP question too 😉

    Thanks!

      1. There does seem to be some fairly significant loss of quality in your pictures.

        Those who want high quality will probably do better when a high quality HDMI capture card.

        That said, this does a very good job considering it’s 1/2 the price and gives you a free receiver to view the content as well.

        1. I’d hold on expressing opinions on image quality. Look carefully on the picture. It looks like the image was scaled down and than scaled up. Maybe his DVD player is doing that conversion. Let’s wait for sample footage from other video source.

          My advice is to use camcorder with HDMI out to see what quality camcorder records and what quality can be achieved via HDMI capture. Another good device to test would be a PC with HDMI on the GPU: record computer screen via HDMI extender and do a print screen and then compare.

  4. Where can i buy one of this?
    Does it have the model / manufacturer?
    Is it available in something with easy international shipping like dx.com aliexpress other than ebay?

  5. Interested in knowing if the unit streams a constant framerate regardless of the input resolution or does it use the input resolution to determine the framerate?

    I am involved with running conferences and these would be perfect if we could feed the MJPEG stream into something like GStreamer so we can feed it into our mixing software.

    1. There is an option to overlay the FPS with the serial console, I will overlay this Wednesday and see if it is constant or fluctuating too much.

      My goal is to record it and replay it over an blackmagic device.

      What I also saw was that it de-interlaces it, so 1080i 5994 in, will result in 1080p60 probably.

      1. Huuf: Can you contact me at hdxx@o2.pl? I have some questions to ask. I could ask you here but e-mail is more convenient since you don’t have to visit the website.

    1. The best HDMI capture device I have ever used was made by Blackmagic, I used the H.264 pro (which is £325) for my work but their other kit is also good. If you can use PCIe then their capture cards are well priced. The problem is that HDCP doesn’t work on these cards.

      I’ve bought one of these kits to see how they perform for myself.

  6. Great! The quality loss is not that significant, exactly as I predicted 🙂 I’m curious if it can be even better if we play a little bit with the console.

    Manufacturer replied to my first message but then they stopped. I asked them about SDK which would allow us to write new firmware, possibly with USB support (TF-680 has USB host!) for WiFi dongles which would give us better transfer and maybe better quality. It has many more cool features but without SDK we aren’t going to make anything…

    Do you have ideas how we can obtain one?

  7. Great beat ! I wish to apprentice while you amend your site, how could i subscribe for a blog website? The account aided me a acceptable deal. I had been tiny bit acquainted of this your broadcast offered bright clear concept

  8. Thinking further on this, why don’t you convert your HDMI receiver into a gstreamer source? Then you can just build your switcher/matrix/mixer around gstreamer and then you have flexibility for your sources? It seems building in the hardware to your design would limit it?

    1. I could, but I want to have complete controll on all parts so I can do some optimizations. Next thing is, that I wanted to avoid any external utilities which can introduce unwanted buffering/latency.

  9. So, I did some research on the unit this week during the evenings and this morning.
    In short: Don’t buy it. Not that reliable.

    In long:
    I used the following equipment:
    -Sony BDPBX39 Blu-ray player outputting at 1080p60
    -Philips 22pfl4505d/f7 – TV – Maximum input 1080i60

    Audio quality:
    -Audio is in good quality, as stated before, most people won’t hear the difference, but it is 2 channels only, so if you have this extender in between and do want to do multi channel 5.1 surround sound you will unable to do this.

    Video quality:
    -It is OK for JPG, encoding quality seems OK, when in high detail shots you see the degradation but meh.
    -It does do de-interlacing on chip, so if you have an interlaced signal, you will get an de-interlaced signal into the receiver instead of just sending top or bottom field
    -It appears to always downgrade to a maximum of 30 FPS (See Network for more details about FPS)
    -The Rx end downgraded to 720p to make an progressive resolution to not deal with interlacing.

    Audio/Video synchronization:
    -BAD, it is easy visible that the audio is out of synchronization and never appears to be corrected. In the capture program you would need the ability to sync up audio / video.

    Network quality with NetGear GS105
    -Test environment where it goes just from Tx –> Netgear –> Rx, no other network devices attached to the NetGear using 3 feet Cat6 cable
    -There are a lot of dropped frames, it rarely gets to 30 fps, but is mainly arround 13-17fps, often it drops to 0 fps and only audio passes through where it stopped completely twice.

    Network with direct Cat6 cable (3 feet)
    -Mainly remains at 30FPS, sometimes there is a drop, where it says 1 has failed, but actually 2 frames are missing.

    Extra research
    -Packet at port 48689 (all values are hex, unless otherwise specified)
    –Receiver sends one when it receives one from the sender.\
    –Endianness is different in the packet counter than in the rest of the packets
    –[0..4] 5 byte header [54:46:36:7a:63]
    –[5] 1 byte define what you are
    —01 = Sender
    —02 = Receiver
    –[6…7] always 00 00
    –[8…9] 2 bytes of an internal counter of how many 48689 packages have been send. Overflows at ff ff back to 00 00 to 01 00
    –[10..18] two different sequences for sender / receiver
    —[00:03:03:03:00:24:00:00:00] = Sender
    —[00:03:03:01:00:26:00:00:00] = Receiver
    –[19…22] Uptime receiver in ms (0 for sender)
    All bytes are 0 for the receiver from now on to make a length of 512 bytes
    –[23…26] [00:00:00:00]
    –[27] Some flag byte to indicate the signal
    —03 for signal
    —10 for no signal
    –[28..29] Width of signal (probably input or encoded width)
    –[30..31] Height of signal (probably input or encoded height)
    –[32..33] FPS of signal
    –[34..35] Width of signal (probably input or encoded width)
    –[36..37] Height of signal (probably input or encoded height)
    –[38..39] [00:78]
    –[40..43] Uptime in ms for the sender
    –[44..49] [00:01:00:00:00:00]
    –[50] Some indicater of number of receivers connected but doesn’t change when one disconnects
    —00 when none is connected
    —02 when one is connected
    –[51] [0a]
    For the rest it’s filled with 00’s to pad up to 520 bytes.
    -Packet on port 2067
    –This is a frame count packet.

    The rest of the details are already covered in this blogpost.

  10. Can anyone help me?
    Since I plugged the sender and receiver in the network the Wi-Fi connection of my laptop will not connect to the router anymore.
    Any suggestion?
    Thanks in advance.
    Eric

    1. Yes, this is normal if you are using non-multicast capable switches. They distribute multicast as broadcast and overload your wifi. You should use/test these convertors on separate subnet or somehow filter multicast on you wifi AP.

  11. Hi Huuf

    I want to use this device just to connect a PC to a long distance monitor (about 40 metres) at 1920x1080p resolution, mainly for powerpoint pesentations, means resolution is important.

    You said that receiver downscales to 720p. Is it true for 1080p input content or just for interlaced ?

    Thanks

  12. Danman,

    The jpeg file you captured at receiver is 737.460 bytes, means 5.9 Mbits

    Then at 30fps will be 177 Mbits/s stream

    So, How can this device broadcast 1080p at 30fps with a 100Mbit lan interface ?
    I’m missing something ?

      1. But Huuf said this:

        “Network with direct Cat6 cable (3 feet)
        -Mainly remains at 30FPS, sometimes there is a drop, where it says 1 has failed, but actually 2 frames are missing.”

        ¿?

  13. I’m not able to get the configuration packet (or any other packed but ‘who is’) from the receiver, nor its possible to send config packages to the receiver. Also, i’m not able to get an image with the mixer software. My devices have a label called “V 2.0”. I’m able to get the Jpeg pictures with the python script and both devices (sender & receiver).

    Has something changed with a new hardware revision?

  14. hey. I’ve updated your python script to work with gstreamer. It works quite well, but unfortunately depending on the content, the stream is broken. You also should have noticed that. Does somebody know a fix for that?

    Heres the code:
    http://codepad.org/Bb6K4Kxe

    you can start it with this command as root (check the fps):
    python udphdmi.py | gst-launch-1.0 -v fdsrc do-timestamp=truet ! ‘image/jpeg,framerate=30/1’ ! jpegdec ! autovideosink &

    As you can see, I played a little bit with single file jpeg output and audio output. I’m searching for a way to easily multiplex video and audio to gstreamer. One idea is to split both into multipart messages, but that doesn’t work (gestreamer is able to find the header with multipartdemux, but it crashes). Maybe I’m too nooby ^^.

    PS: you need a NIC that “likes” defective packages.

    1. there’s one more bug in that script I fixed later, this line:
      part=ord(data[3])
      should be:
      part=ord(data[2])*256+ord(data[3])
      but it shows up only with bigger frames, maybe that’s your case.

  15. I’ve solved 1 Bug: first the part has to be calculated: part = data [2]*256 + data [3].

    But the real problem seems to be lost packets. Wireshark is able to receive them, so they are not lost. Is it possible that the python script is to slow to receive all Packets?

    1. You might need to put the NIC into promiscous mode, or set the NIC-driver to pass on packets with checksum errors:
      eg.
      ———–
      import os
      NIC=’eth0′
      ret = os.system(“ifconfig ” + NIC + ” promisc”)
      if ret != 0:
      print ‘NIC could not be put in promiscous mode. Error.’
      sys.exit()
      else:
      print ‘NIC (‘ + NIC + ‘) put in promiscous mode’
      ———-
      as root…

  16. Confirmed. I’m able to receive a real smooth stream with this update (on my smallest 1.4 Ghz core2duo machine):

    http://codepad.org/L0v4hIJe

    I’ve started it with that gstreamer command:

    python bufferudp.py | gst-launch-1.0 -v fdsrc ! queue ! jpegdec ! autovideosink &

    so, if someone has an idea, i would be very interested in audio and an even faster python skript.

    (The Problem was, that gstreamer canceled the decoding. It was a simple timing problem. Removing the fixed framerate, cleaning up the skript and adding a buffer is all the magic)

  17. OK, here it is:

    socket.py:
    http://codepad.org/VThPnCR5

    and here the magic:
    sudo python socket.py

    and some gstreamer magic:
    gst-launch-1.0 -v udpsrc port=5007 buffer-size=100000 ! queue ! audio/x-raw,rate=48000,channels=2,format=S32BE ! autoaudiosink \ udpsrc buffer-size=1000000 port=5006 ! queue ! jpegdec ! queue ! autovideosink

    take care that there are no foreign packets @port 5006 or 5007

    I still have some problems with some broken frames. If somebody has an idea, i would be very interested.

    1. I have tested your python script.
      Thanks for that.
      But get this error.
      ‘module’ object has no attribute ‘AF_INET’
      Ubuntu

  18. Looking at the TF-680 datasheet, it suggests that upto 7.1 audio is supported in the chipset (presumably PCM only?), yet Huuf said (in comment 67) that it only outputs 2-channel. Can anyone else confirm whether the audio is downsampled to 2-channel?

    I’m looking at using one of these to get an HDMI “input” into a dedicated server (i5-based) that can then transcode into H264, and stream to a set of Raspberry Pi units that I have behind all the TVs in my house (7 Pi in all) – is this achievable?

    My source outputs 1080i50 or 720p50 – am I right in thinking that this device will deinterlace the 1080i50 to 1080p25, but then only deliver ~18fps of that?

  19. Have ordered one, to see if I can make it work for what I need.

    It occurs to me that it might be possible to use a Raspberry Pi to handle the transcoding from MJPEG to H264 in hardware using an up-to-date version of gstreamer. The only problem is that it’ll require a separate USB-ethernet device (because the built-in 10/100 will be busy with the stream from the Lenkeng).

    Should be fun trying, anyway!

  20. hi and thanks for the actual blog post ive recently been searching regarding this specific advice online for sum hours these days as a result thanks bgcdgacddccd

  21. Hi many thanks for your work.
    It’s first time I use python.
    Could you let me know if can I transmit HDMI signals over IP network to mac os x PC?

  22. I’m trying to use the brillant work already done here to take the output (video and audio) and serve it up via RTP or similar for a software mixer (ie vidblaster or wirecast).

    Best I’ve got so far is video in linux. Can’t get the mixer to work (it loads, but blank display for hdmi source) and no luck with TheRealTentacles scripts either…

    Any ideas? Anyone keen to help ?

  23. Didn’t get the sender to transmitt.
    If I log with wireshark,
    I got messages from Transmitter-device on port 48689.
    But didn’t see the “activation” message from receiver.
    any one a hint.
    Have the most things done in C.
    But this is not clear for me.

  24. After sniffing the networktraffic, I think, they changed something in there FW.

    Here what I found:
    Transmitter is polling on port 48689 (UDP Packet).
    When receiver is switched on, it seem’s that the receiver is sending a Broadcast
    message. I saw the source IP was 192.168.168.56 (receiver), and target IP was 192.168.168.55 (transmitter).
    I thought, this message (broadcast) will activate the streaming. But didn’t work.

    Next message after this is a valid UDP message, on port 2067 as a “sync” Packet. Byte 5+6 is the count of the frame.

    And then the already known UDP packets.
    I never seen any other packet from receiver!

    Any one how has also played arround with this extenders?
    Did you see any different packets fom receiver?

    Thanks

    1. I’m seeing the same with newer-model transmitters – IP of 192.168.168.56, and polling over port 48689. If I add another transmitter to the same network, it lays claim to the exact same IP address and also starts sending UDP packets over port 48689.

      My receiver must be faulty – do you mind posting the broadcast or sync message sent to the transmitter?

  25. I saw this and bought a pair on eBay with an extra receiver. The units themselves are great, no longer having crappy video sender picture. I hope to also view the feed on the pc, there is lot of information here to absorb, maybe better suited to a GitHub project to bring it all together.
    Great effort on all concerned with the reverse engineering ! ( just need to get WinLirc working with the STB for full remote viewing )

  26. Great project, how can I run the python script within OSX? Has anyone tried to replay the video/audio stream in OSX.

  27. I also have one of the new firmware revisions, and do not see a message sent from the receiver to the transmitter. All is see is the transmitter polling. Does anyone know of a way to get the transmitter to start transmitting without having the receiver on the network?

    1. Nevermind, I found it. I just had to have my computer be directly in between the transmitter and receiver. I used two ethernet cards on my computer and bridged them together. Then i just plugged the transmitter into one and the receiver into the other. Hope this helps anyone else having problems not seeing all the communication in wireshark.

  28. Hi,

    Nice work ! Do you know if that’s really CPU consuming on the Raspberry Pi to capture through this device ?

    Would there be CPU power enough to send this to the RPI GPU video encoder and to send this encoded stream to twitch ?

    I need to so a “twitch box” that can allow me to encode whatever I’m doing (gaming mostly) on my comp and/or gaming console and twitch that in “real time”.

    I was hoping my Raspberry Pi would be able to do that but apparently the GPU can only encode through the camera interface…

    Any help would be welcome.

    Regards

  29. Any port for Windows or Android VLC?

    I’ve just got my sender and two recievers (version 2). Had to change all my switches from “normal” switches to smartswitches (HP) to get it to work in my network. It now works with both recievers simultaneously (also rest of the network, Internet, wifi etc works in parallell).

    But, I would like to get it to work on my Windows computers and if possible also on my Android devices.

    /Roger

  30. Just got a tx/rx pair from eBay last Friday. Here’s what I found:

    1) There is a webserver running on each unit. It allows setting of IP address (no DHCP), so if you can set them on the same subnet as your computer. The default IP addresses are 192.168.168.55 (for Tx) and 192.168.168.56 (for Rx).

    2) The units that I received work as advertised if I connect an IP cable between them with no switch or if I have one switch in the path. But if I try to send video through 3 switches (one next to the HDMI source, one in my central switch, and one in my office), I get maybe one still picture every few seconds. I’m using Netgear ProSafe switches.

    3) The devices don’t do any IGMP messaging. When the Tx unit handshakes with the Rx unit, it just sends out data to the multicast MAC address 01:00:5e:02:02:02. This essentially becomes a broadcast as far as my Layer 2 switches are concerned.

    4) If I try to run video through my whole network, the packets tend to flood all of the ports on all my switches and make it difficult to do anything else on the network. I saw a comment from Eric that his WiFi failed. That happened to me as well. But, if I confine the Tx/Rx units to one switch, I can use a switch setting on my central switch to “Block Unknown Multicast Address” packets. This keeps the multicast from leaking out of the one switch.

    5) I see numerous “ETHERNET FRAME CHECK SEQUENCE INCORRECT” messages on Wireshark. This was with the 3 switches in the path. But it seems to match the above screenshot of Wireshark. I’ll be checking this with the 1-switch configuration later this week.

  31. Hi everyone. I got a set of these in a few days ago and after the python program failed to run on my Windows machine, I just wrote my own app in C#. It is in a pretty rough state (you’ll need to build it with VS 2013 community edition, more than likely, after changing some hard-coded settings), but it does work. It manages the control packets to keep the Sender activated and it sniffs the video and audio streams, making them available by http so you can send them to VLC or FFMPEG or whatever.

    https://hdmiextender.codeplex.com/

    1. Ok buddy but if you want your link to stay here you will need to link back from your project page. I’ll check in a week.

      1. My apologies! I was in a hurry to get it online and neglected to give you credit for your excellent blog post. That has been remedied.

        Have you by chance found a way to keep the audio and video in sync when recording, transcoding, or even just viewing locally? That is the main problem I’ve been having; audio regularly loses sync and I have no idea how to prevent it.

        1. I’m not sure but I’d probably blame ffmpeg and some its internal buffers. The best solution would probably be to write muxer/encoder using libav and not using ffmpeg binary. But that’s my guess only…

  32. I’ve been using these devices for a long time and this is a fascinating read. I’m not a softie, but understand most of what being discussed.

    Picture quality is good/bad depending on the source material. Full 1080p DTS source, they really struggle to keep up and as pointed out go out of lip sync.

    I orginaly used them here at home on a pair of netgear bluebox gigabit ethernet switches, and the poor things just died with the amount of multicast flying around, it also saturated a couple of other devices on the network, I now have cisco switches and have limited where those perticular multicast groups go which has solved the problem. One could also gre tunnel the multicast to keep it under the control if going across a co-operate LAN.

    I mainly bought them for audio, and to be honest they do not sound to bad on compressed pop material, considering they are not lossless, They present themselves to the HDMI port on the PC as just stereo, and even fiddling around with info file to force multichannel sound it’s probable to conclude that multichannel sound will never work even though one chipset is 7.1 capable, even though it’s claimed on the website.

    Has anyone else proven diffrent with more modern firmware with multichannel sound being possible ?

  33. hi, have you ever tried to open the stream directly (so without preprocessing) in vlc? Any chance that could work? Thanks in andvance.

      1. is there any kind of hdmi extender who will just play in vlc without tampering? I already googled it but the closest thing i found is you post. Thanks in advance.

        1. Good news for you, I did find some chinese devices that take HDMI input and produce an h264 video stream (with audio) that you can simply open in VLC without all this hacking around.

          Go to aliexpress.com and search for “HDMI encoder”. You should find a couple models that look like clones of each other for around $200 USD plus shipping. I personally bought 2 of them from the seller “Unisheen Tech Store” because they had the best rating. Though I did have to negotiate for a better shipping price.

          The main problem with those chinese encoders was poor contrast and color accuracy. Luckily you can improve it a lot in the web interface by setting Brightness to 35, Contrast to 60, and Saturation to 45. Hue stays at 50. In your graphics card driver, enable “Full dynamic range” for video (if you have such an option), which lets VLC display the full 0-255 range for each color. Otherwise you get a limited contrast range.

          1. Oh I also did not mention that those chinese HDMI encoders add a fair amount of latency (1-3 seconds). This is a bit annoying even if you are just watching TV or something with it, but if low latency is a concern you’d be better off with a capture card or even the LKV373 extender plus hacky software 🙂

  34. Hi, i have been capturing tv for a while and for some reason the transmitter changed the destination ip from the control packages from 226.2.2.2 to 255.255.255.255? Has anybody run in this issue before how to set it back?

  35. Hi – I’ve tried creating the .py file and loading with VLC on a Raspberry Pi however I get the error message “es demux error: cannot peek” – can anyone help me with this?

    Thanks in advance,

  36. hi
    good job, I want image compression (sender).
    Then I send it to receiver(broadcast).
    And show output them.
    please give a source code and help me, How do I send an image.

  37. Hi,

    has anyone checked if other hdmi extender using the same chipsets?

    I was searching for informations about Axing Hoe 1-00 when i found this page. The Axing devices look quite similar.

  38. Any thoughts on those $70 android boxes with HDMI input (Tronsmart Pavo M9 4K, UGOOS UT3+ TV, etc).. is there any reason an open source server (like tvheadend) couldn’t be ported to do the same thing (stream hdmi video over ethernet)?

    1. I’ve just ordered Tronsmart Pavo M9. Will definitely look into it. It should be possible to stream directly to network in H264 an AAC. Expect my review in about a month. Thanks for the tip.

  39. I’m trying to get the hdmi extender kit to work trough a Zyxel adsl router with firewall nat and so on. Ho do i have to set the internal firewall of the router to get it work?

  40. Can somebody extract a dump of the SPI chip (winbond) 25q32 from the TX unit?
    I manage to “kill” one and I don’t even have serial console anymore.
    The firmware I had before was TF680 FW Verion: Tx_v1.07_C904 ITE 152MHz IR LAN_MODULE. Thanks.

  41. Hello friend, I would like to replace a transmitter for a raspberry pi or even a PC using a python script? If you have for how you sell me this eScript and how long it would be ready?

      1. Okay, thanks for your reply. There’s this one too (can’t find the one with English description): http://i.marktplaats.com/00/s/NTU2WDkwMA==/z/r9IAAOSwNyFWfBcl/$_84.JPG
        There isn’t mention of it being LKV373, but it looks very similar to the original one. It looks like it only supports Cat6 (?).
        One worry I have with the one I first posted, is that it has support for IR, which presumably is sent in the TCP packets. I’m trying to avoid messing around a lot with packet analysis before I have at least one working version (to compare with for example).

  42. Another question: sound can get out of sync, however is this an issue when using the original hardware transmitter and hardware receiver too? Thanks for the hard work, I look forward to playing around with this.

  43. I’ve got a version 3 here the packets seems different. Everything is on port 5004. It doesn’t seem that it is actual JPEG data. I do not have a receiver here so maybe the receiver needs to tell the transmitter that it is ready?

    Did somebody had any luck with the version 3 transmitter?

    1. Yes, v3 aka lkv373a uses h264 and different protocol. I’m allready in process of obtaining it. Will post details when it comes.

      1. I’m also waiting your analysis to V3 inverse engeenring, to go this way or try something similar to http://www.qintexworld.com/showgoods/889.html . The goal is to build an open source and hardware video net architecture, something similar to NewTek NDI, but with source code published in GITHub…

        If you need help, touch me.

          1. I think so…

            I buyed today a pair of LKV373A, when it arrives (by the final of Juny), I would try to follow your experiences.

  44. Hi friends. I´m working on a project to pass HDMI video by wireless links and I need to know how much bitrate is needed for 480i. An good fellow can say this for me?
    Thanks in advace.
    Greatings from Brazil.

  45. Power outage kill the TX after 48 hours of usage now it is dead. It did the same thing for all my tx. Anyone know how to bring the tx back to life? can’t get into the interface through ip.

    1. I plugged my TX at least 50 times on and off without any problem. I guess there was a power surge in your case so your device will be probably broken.

  46. I had a V2 and it died within 6 months. We had a power outage as well, so perhaps related (nothing else died in the house). It had worked flawlessly with audio on amp prior to extender and then run through extender to video on projector, no latency. I then just bought another one to replace it, came as a V3. This one works, but the video delay, latency, is really bad, about half a second, unusable!
    What happened between V2 and V3??? Did they change something?
    Cheers
    D

Leave a Reply

Your email address will not be published. Required fields are marked *