有损传输实例
Posted dog250
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有损传输实例相关的知识,希望对你有一定的参考价值。
下周终于可去公司了,有点快放假的感觉。阳台吹着晚风,用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:
下面是TCP无损传输在15%丢包率时传输时间:
重传引入这么大的延时换无损清晰度,值得吗?还是相信香农定律吧,有噪信道编码定理。
附上代码,我不怎么会编程,但也不是一点也不会,稍微会一点,编的不好,代码是搜来的一些片段拼凑的,自己也写了点,不多:
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,看下效果。
浙江温州皮鞋湿,下雨进水不会胖。
以上是关于有损传输实例的主要内容,如果未能解决你的问题,请参考以下文章
计算机网络 王道考研2021 第二章:物理层 -- 奈氏准则 香农定理
计算机网络学习笔记——物理层奈奎斯特/香农定理物理接口传输介质交换电信网络无线网络
计算机网络学习笔记——物理层奈奎斯特/香农定理物理接口传输介质交换电信网络无线网络