资讯详情

有损传输实例

下周终于可以去公司了,感觉假期有点快。阳台吹晚风,用Java以柔性有损传输为例:

  • 发送端发送的任何数据包都可以丢弃,不影响接收端的解码。
  • 不做发送端编码FEC,不做冗余。
  • 发送端不检测丢包不重传,接收端能在很短的时间内收到多少。

这绝对具有超低延迟效果,但结合良好的编解码算法。它背后的想法是:

  • 信息(尤其是像素或帧差)具有连续性特征,不会突变的概率很大。
  • 预测网络拥塞和帧差比RTT更容易,更准确。

一个简单的实现UDP柔性有损传输,以下是运行代码后的实际效果,本地lo口传输,tc netem模拟丢包。文件名 dst-x.jpg,x表示丢包率,第一个是原图,分别是1%、5%、10%、40%和80%。 在这里插入图片描述

时间关系,例子很简单,只传输一个jpeg但可想而知,图片可以做得更好。

看效果,丢包造成的损失是有规律的损失,因为我懒惰,我使用固定步长的像素间隔集成packet,例如,将1、101、201、301、401整合成一个packet,2、202、302、402整合成下一个packet,正确的做法应该是随机集成,或者根据图像像素的意义集成,如编码不均匀,尽量集中背景等类似像素,反之亦然,尽量分散以换取更大的冗余。

即使是80%的丢包率,也能显示出良好的轮廓。

结合好的编码解码,效果肯定更好。如果深挖,结合像素的意义,编码纠错效果可以弥补丢包带来的很多损失,比如黑色皮鞋面。像素丢失后,很容易猜出是黑色的。预测比预测网络拥塞容易得多,不是吗?

总之,主要是编解码算法,至于传输效果,交给香农定律。

在上述10%的丢包率场景中,损坏传输的分辨率效果良好。皮鞋清晰可见,无重传。最短延迟只包括传输延迟和编解码延迟,但如果使用TCP呢?为了换取原图效果,延迟增加了多少? 当丢包率分别为1%和80%时,以下是损坏传输的时间tcpdump -ttttt: 下面是TCP15%丢包率时无损传输时间: 重传引入这么大的延迟无损清晰度值得吗?相信香农定律,有噪音信道编码定理。 附上代码,我不知道怎么编程,但也不是一点也不知道。我编得不好。代码是用搜索的一些片段拼凑起来的,我自己写了一些,不多:

import java.util.Random; import java.awt.image.*; import java.io.*; import java.net.*; import javax.imageio.ImageIO;  public class ImgTrans { 
          public static int [] dst_array = null;  public static int DELTA = 500;   public static int[] getPixels(String path) throws Exception { 
          BufferedImage img = null;   int w, h;   int data[] = null;   img = ImageIO.read(new File(path));
		w = img.getWidth(); h = img.getHeight();
		data = new int[2 + w * h];
		data[0] = w; data[1] = h;
		for (int i = 0; i < h; i ++) { 
       
			for (int j = 0; j < w; j ++) { 
       
				data[2 + w * i + j] = img.getRGB(j, i);
			}
		}
		return data;
	}

	public static void setPixels(int [] data, String path) throws Exception { 
       
		BufferedImage img = null;
		File outfile = new File(path);
		int w, h, k = 0;
		w = data[0]; h = data[1];
		img = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
		for (int i = 0; i < h; i ++) { 
       
			for (int j = 0; j < w; j ++) { 
       
				img.setRGB(j, i, data[2 + w * i + j]);
			}
		}
		ImageIO.write(img, "jpg", outfile);
	}

	public static void receiveImg(int [] sub) { 
       
		int delta = ImgTrans.DELTA;
		int len = sub[3];
		int offset = sub[4];
		int count  = len/delta;

		if (dst_array == null) { 
       
			dst_array = new int[len + 2];
			for (int i = 0; i < len + 2; i ++) { 
       
				dst_array[i] = 0;
			}
			dst_array[0] = sub[0]; dst_array[1] = sub[1];
		}

		for (int j = 0; j < count; j ++) { 
       
			dst_array[2 + offset + j*ImgTrans.DELTA] = sub[j + 5];
		}
		if (offset < len%ImgTrans.DELTA) { 
       
			dst_array[2 + offset + count*ImgTrans.DELTA] = sub[count + 5];
		}
	}

	public static void sendImg(int [] data) throws Exception { 
       
		int delta = ImgTrans.DELTA;
		int count;
		int len = data.length - 2;
		int k = 0;
		int[] sub;
		DatagramSocket socket = new DatagramSocket();
		count = len/delta;

		for (int i = 0; i < ImgTrans.DELTA; i ++) { 
       
			if (i < len%ImgTrans.DELTA) { 
       
				sub = new int[count + 6];
				sub[2] = count + 6;
			} else { 
       
				sub = new int[count + 5];
				sub[2] = count + 5;
			}
			sub[0] = data[0];
			sub[1] = data[1];
			sub[3] = len;
			sub[4] = i;
			for (int j = 0; j < count; j ++) { 
       
				sub[5 + j] = data[i + j*ImgTrans.DELTA + 2];
			}
			if (i < len % ImgTrans.DELTA) { 
       
				sub[count] = data[count*ImgTrans.DELTA + i + 2];
			}
			byte[] bs = ImgTrans.iatoba(sub);
			DatagramPacket subpkt = new DatagramPacket(bs, bs.length, InetAddress.getLocalHost(), 1234);
			socket.send(subpkt);
			/* for test Random rand = new Random(); int r = rand.nextInt(200); if (r < 190) { System.out.println(sub.length + " len count " + count); receiveImg(sub); } */
		}
	}

	public static byte[] iatoba(int[] intarr) { 
       
		int blen = intarr.length * 4;
		byte[] bt = new byte[blen];
		int curint = 0;
		for (int j = 0, k = 0; j < intarr.length; j ++, k += 4) { 
       
			curint = intarr[j];
			bt[k] = (byte)((curint>>24) & 0xFF);
			bt[k+1] = (byte)((curint>>16) & 0xFF);
			bt[k+2] = (byte)((curint>>8) & 0xFF);
			bt[k+3] = (byte)((curint>>0 )& 0xFF);
		}
		return bt;
	}

	public static int[] batoia(byte[] btarr) { 
       
		int i1,i2,i3,i4;
		int[] intarr = new int[btarr.length/4];
		for (int j = 0, k = 0; j < intarr.length; j ++, k += 4) { 
       
			i1 = btarr[k];
			i2 = btarr[k+1];
			i3 = btarr[k+2];
			i4 = btarr[k+3];

			if (i1 < 0)
				i1 += 256;
			if (i2 < 0)
				i2 += 256;
			if(i3 < 0)
				i3+=256;
			if(i4 < 0)
				i4+=256;
			intarr[j] = (i1<<24) + (i2<<16) + (i3<<8) + (i4<<0);
		}
		return intarr;
	}

	static class RecvThread extends Thread { 
       
		private DatagramSocket mSocket;
		public void run() { 
       
			try { 
       
				mSocket = new DatagramSocket(1234);
				while(true) { 
       
					byte[] bs = new byte[5000];
					DatagramPacket subpkt = new DatagramPacket(bs, bs.length);
					mSocket.receive(subpkt);
					ImgTrans.receiveImg(ImgTrans.batoia(bs));
				}
			} catch (Exception e) { 
        }
		}
	}
        // tc qdisc add dev lo root netem loss 1%
        // tc qdisc add dev lo root netem loss 5%
        // tc qdisc add dev lo root netem loss 10%
        // tc qdisc add dev lo root netem loss 40%
        // tc qdisc add dev lo root netem loss 80%
	public static void main(String []args) throws Exception { 
       
		int data[] = null;
		RecvThread thread = new RecvThread();
		thread.start();
		Thread.sleep(100);
		data = getPixels(args[0]);
		sendImg(data);
		Thread.sleep(1000);
		setPixels(dst_array, args[1]);
		System.exit(0);
    	}
}

傍晚凉风体感不错,我不是一直说什么有损柔性传输吗,写个有损传输的demo,看下效果。

浙江温州皮鞋湿,下雨进水不会胖。

标签: 超低频振动传感器m35工作原理

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台