{"id":18251582,"url":"https://github.com/ariesdevil/graduation-project","last_synced_at":"2025-09-13T22:08:18.918Z","repository":{"id":108861644,"uuid":"91432183","full_name":"ariesdevil/graduation-project","owner":"ariesdevil","description":"基于喷泉码的视频传输demo","archived":false,"fork":false,"pushed_at":"2016-06-03T15:20:55.000Z","size":995,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-08T20:48:41.017Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ariesdevil.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-16T08:05:10.000Z","updated_at":"2025-01-07T06:44:29.000Z","dependencies_parsed_at":"2023-05-10T11:47:20.563Z","dependency_job_id":null,"html_url":"https://github.com/ariesdevil/graduation-project","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ariesdevil/graduation-project","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariesdevil%2Fgraduation-project","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariesdevil%2Fgraduation-project/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariesdevil%2Fgraduation-project/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariesdevil%2Fgraduation-project/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ariesdevil","download_url":"https://codeload.github.com/ariesdevil/graduation-project/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ariesdevil%2Fgraduation-project/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275033292,"owners_count":25393845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-13T02:00:10.085Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-05T09:47:59.499Z","updated_at":"2025-09-13T22:08:18.747Z","avatar_url":"https://github.com/ariesdevil.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 毕业设计——基于数字喷泉码和UDP协议的视频传输Demo\n\n![image](https://github.com/28hua/graduation-project/raw/master/compare.png)\n\n左图：没有经过编码；右图：经过LT码编码。\n\n这篇README是继一篇发表在我的微信公众号上的文章写的，那篇文章介绍了喷泉码的背景，喷泉码的一个分支Raptor码被写入3GPP，Raptor码的一个实现方法RaptorQ也被高通公司写入RFC6330。\n\n我的毕设实现的是最原始的喷泉码LT码，把树梅派摄像头采集的视频数据经过LT码编码后再发送。研究的结果嘛，呵呵，喷泉码这么用是不合适的。首先，主流的视频都是经过H.264压缩的，这种压缩方法的优势是压缩率高，缺点是帧之间的相关性强，关键帧的错误导致后续一连串的马赛克。喷泉码，尤其LT码的译码存在一定的译码失败概率，根据实现质量的高低这个概率很可能比信道的丢包率还要高。第二，喷泉码要求发送的数据包比原始的数据包稍微多一些，采用这种方案并不比采用TCP协议的重传产生的开销小。徒手实现LT码的编译码费了很大劲儿，编译码又带来时延，真不见得比用TCP协议实现得干净利索。第三，出于译码的需要，编码包需要携带它与原始包的邻接关系，由于视频是实时的，编码包需要携带一个ID标识它是用来译第几块视频的。这两点又带来了开销。第四，是UDP协议的问题。UDP不带反馈，它不像TCP协议或者管道那样带有同步的功能，发端不会因为收端忙得处理不过来就等它一下，白花花的编码包说丢就丢。我用的笨方法是一边两端都加上阻塞队列和专门的编译码线程，一边让发端发完一个包就usleep(100)微秒。毕设也给了我启示，如果有一个网络应用你想要用UDP做，那么十有八九你错了。\n\n我的上一篇文章讲到这个项目最初是用C语言写的，用C语言的问题是这是一门面向过程的语言，写程序的过程中关注点一直是数组、指针、内存管理，造成进度一直比较慢，模块间耦合严重，难以调整编码器的参数，所以我用C++重写了。当时我预计需要设计度分布、编码器、补零数据包、编码包四个类，并且犹豫编解码算法是放到编码器的编解码函数里还是放到编码包、补零数据包的构造函数里。现在C++版本定型，就喷泉码模块而言，我设计了四个类：编码器、补零数据包、编码包、序列化器。对于度分布，那其实是一个离散型随机变量的累积分步，它是纯数据，用一个节点元素为pair的vector表示足以。编解码算法最后放到了编码器的编译码函数里，我觉得概念上这样更合理，而且算法需要获取编码器的配置信息。编码算法需要一个随机数和一个随机序列的发生器，问题抽象出来是：(1)如何产生服从某一分布的随机数，(2)如何从n个数中随机且均匀地选出m个数。这两个问题网上有很多答案，概率论的基础。\n\n方才提到阻塞队列和专门的译码线程。毕设的仓库里有一个阻塞队列的简单实现——BlockQueue.h。原理其实非常简单，使用了最基础的同步原语互斥量和条件变量：生产者线程push(element)时锁住队列，push完成后通知消费者线程，然后解锁；消费者线程pop()element时锁住队列，等待push通知队列非空，然后pop，完成后通知生产者队列不满，解锁。阻塞队列就像shell中的管道，网络协议里的TCP，是居家旅行杀人越货的必备的小东东。\n\n这套小程序原本想要放在无人机上试一下，但是昨天上午起飞前无人机侧翻，一个螺旋浆扎进了草里，电机烧了，怕是飞不成了。\n\n扫码关注xiaoyang-said：\n![image](https://github.com/28hua/graduation-project/raw/master/weixin.jpg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fariesdevil%2Fgraduation-project","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fariesdevil%2Fgraduation-project","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fariesdevil%2Fgraduation-project/lists"}