存档

‘网络转载’ 分类的存档

值得推荐的C/C++框架和库

2016年3月2日
值得推荐的C/C++框架和库已关闭评论

【本文系外部转贴,原文地址:http://coolshell.info/c/c++/2014/12/13/c-open-project.htm】留作存档

值得学习的C语言开源项目

– 1. Webbench

Webbench 是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以 模拟3万个并发连接去测试网站的负载能力。Webbench使用C语言编写, 代码实在太简洁,源码加起来不到600行。

下载链接:http://home.tiscali.cz/~cz210552/webbench.html

– 2. Tinyhttpd

tinyhttpd是一个超轻量型Http Server,使用C语言开发,全部代码只有502行(包括注释),附带一个简单的Client,可以通过阅读这段代码理解一个 Http Server 的本质。

下载链接:http://sourceforge.net/projects/tinyhttpd/

– 3. cJSON

cJSON是C语言中的一个JSON编解码器,非常轻量级,C文件只有500多行,速度也非常理想。

cJSON也存在几个弱点,虽然功能不是非常强大,但cJSON的小身板和速度是最值得赞赏的。其代码被非常好地维护着,结构也简单易懂,可以作为一个非常好的C语言项目进行学习。

项目主页:http://sourceforge.net/projects/cjson/

– 4. CMockery

cmockery是google发布的用于C单元测试的一个轻量级的框架。它很小巧,对其他开源包没有依赖,对被测试代码侵入性小。cmockery的源代码行数不到3K,你阅读一下will_return和mock的源代码就一目了然了。

主要特点:

  • 免费且开源,google提供技术支持;
  • 轻量级的框架,使测试更加快速简单;
  • 避免使用复杂的编译器特性,对老版本的编译器来讲,兼容性好;
  • 并不强制要求待测代码必须依赖C99标准,这一特性对许多嵌入式系统的开发很有用

下载链接:http://code.google.com/p/cmockery/downloads/list

– 5. Libev

libev 是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施。其以高效出名,它可以将IO事件,定时器,和信号统一起来,统一放在事件处 理这一套框架下处理。基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很好的资源。

下载链接:http://software.schmorp.de/pkg/libev.html

– 6. Memcached

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态数据库 驱动网站的速度。Memcached 基于一个存储键/值对的 hashmap。Memcached-1.4.7的代码量还是可以接受的,只有10K行左右。

下载地址:http://memcached.org/

– 7. Lua

Lua很棒,Lua是巴西人发明的,这些都令我不爽,但是还不至于脸红,最多眼红。

让我脸红的是Lua的源代码,百分之一百的ANSI C,一点都不掺杂。在任何支持ANSI C编译器的平台上都可以轻松编译通过。我试过,真是一点废话都没有。Lua的代码数量足够小,5.1.4仅仅1.5W行,去掉空白行和注释估计能到1W行。

下载地址:http://www.lua.org/

– 8. SQLite

SQLite是一个开源的嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。 其特点是高度便携、使用方便、结构紧凑、高效、可靠。足够小,大致3万行C代码,250K。

下载地址:http://www.sqlite.org/ 。

– 9. UNIX v6

UNIX V6 的内核源代码包括设备驱动程序在内 约有1 万行,这个数量的源代码,初学者是能够充分理解的。有一种说法是一个人所能理解的代码量上限为1 万行,UNIX V6的内核源代码从数量上看正好在这个范围之内。看到这里,大家是不是也有“如果只有1万行的话没准儿我也能学会”的想法呢?

另一方面,最近的操作系统,例如Linux 最新版的内核源代码据说超过了1000 万行。就算不是初学者,想完全理解全部代码基本上也是不可能的。

下载地址:http://minnie.tuhs.org/cgi-bin/utree.pl?file=V6

– 10. NETBSD

NetBSD 是一个免费的,具有高度移植性的 UNIX-like 操作系统,是现行可移植平台最多的操作系统,可以在许多平台上执行,从 64bit alpha 服务器到手持设备和嵌入式设备。NetBSD计划的口号是:”Of course it runs NetBSD”。它设计简洁,代码规范,拥有众多先进特性,使得它在业界和学术界广受好评。由于简洁的设计和先进的特征,使得它在生产和研究方面,都有卓 越的表现,而且它也有受使用者支持的完整的源代码。许多程序都可以很容易地通过NetBSD Packages Collection获得。

下载地址:http://www.netbsd.org/

C++ 资源大全

关于 C++ 框架、库和资源的一些汇总列表,内容包括:标准库、Web应用框架、人工智能、数据库、图片处理、机器学习、日志、代码分析等。

 

标准库

C++标准库,包括了STL容器,算法和函数等。

 

框架

C++通用框架和库

  • Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件的集合
  • ASL :Adobe源代码库提供了同行的评审和可移植的C++源代码库。
  • Boost :大量通用C++库的集合。
  • BDE :来自于彭博资讯实验室的开发环境。
  • Cinder:提供专业品质创造性编码的开源开发社区。
  • Cxxomfort:轻量级的,只包含头文件的库,将C++ 11的一些新特性移植到C++03中。
  • Dlib:使用契约式编程和现代C++科技设计的通用的跨平台的C++库。
  • EASTL :EA-STL公共部分
  • ffead-cpp :企业应用程序开发框架
  • Folly:由Facebook开发和使用的开源C++库
  • JUCE :包罗万象的C++类库,用于开发跨平台软件
  • libPhenom:用于构建高性能和高度可扩展性系统的事件框架。
  • LibSourcey :用于实时的视频流和高性能网络应用程序的C++11 evented IO
  • LibU : C语言写的多平台工具库
  • Loki :C++库的设计,包括常见的设计模式和习语的实现。
  • MiLi :只含头文件的小型C++库
  • openFrameworks :开发C++工具包,用于创意性编码。
  • Qt :跨平台的应用程序和用户界面框架
  • Reason :跨平台的框架,使开发者能够更容易地使用Java,.Net和Python,同时也满足了他们对C++性能和优势的需求。
  • ROOT :具备所有功能的一系列面向对象的框架,能够非常高效地处理和分析大量的数据,为欧洲原子能研究机构所用。
  • STLport:是STL具有代表性的版本
  • STXXL:用于额外的大型数据集的标准模板库。
  • Ultimate++ :C++跨平台快速应用程序开发框架
  • Windows Template Library:用于开发Windows应用程序和UI组件的C++库
  • Yomm11 :C++11的开放multi-methods.

 

人工智能

  • btsk :游戏行为树启动器工具
  • Evolving Objects:基于模板的,ANSI C++演化计算库,能够帮助你非常快速地编写出自己的随机优化算法。
  • Neu:C++11框架,编程语言集,用于创建人工智能应用程序的多用途软件系统。

 

异步事件循环

  • Boost.Asio:用于网络和底层I/O编程的跨平台的C++库。
  • libev :功能齐全,高性能的时间循环,轻微地仿效libevent,但是不再像libevent一样有局限性,也修复了它的一些bug。
  • libevent :事件通知库
  • libuv :跨平台异步I/O。

 

音频

音频,声音,音乐,数字化音乐库

  • FMOD :易于使用的跨平台的音频引擎和音频内容的游戏创作工具。
  • Maximilian :C++音频和音乐数字信号处理库
  • OpenAL :开源音频库—跨平台的音频API
  • Opus:一个完全开放的,免版税的,高度通用的音频编解码器
  • Speex:免费编解码器,为Opus所废弃
  • Tonic: C++易用和高效的音频合成
  • Vorbis: Ogg Vorbis是一种完全开放的,非专有的,免版税的通用压缩音频格式。

 

生态学

生物信息,基因组学和生物技术

  • libsequence:用于表示和分析群体遗传学数据的C++库。
  • SeqAn:专注于生物数据序列分析的算法和数据结构。
  • Vcflib :用于解析和处理VCF文件的C++库
  • Wham:直接把联想测试应用到BAM文件的基因结构变异。

 

压缩

压缩和归档库

  • bzip2:一个完全免费,免费专利和高质量的数据压缩
  • doboz:能够快速解压缩的压缩库
  • PhysicsFS:对各种归档提供抽象访问的库,主要用于视频游戏,设计灵感部分来自于Quake3的文件子系统。
  • KArchive:用于创建,读写和操作文件档案(例如zip和 tar)的库,它通过QIODevice的一系列子类,使用gzip格式,提供了透明的压缩和解压缩的数据。
  • LZ4 :非常快速的压缩算法
  • LZHAM :无损压缩数据库,压缩比率跟LZMA接近,但是解压缩速度却要快得多。
  • LZMA :7z格式默认和通用的压缩方法。
  • LZMAT :及其快速的实时无损数据压缩库
  • miniz:单一的C源文件,紧缩/膨胀压缩库,使用zlib兼容API,ZIP归档读写,PNG写方式。
  • Minizip:Zlib最新bug修复,支持PKWARE磁盘跨越,AES加密和IO缓冲。
  • Snappy :快速压缩和解压缩
  • ZLib :非常紧凑的数据流压缩库
  • ZZIPlib:提供ZIP归档的读权限。

 

并发性

并发执行和多线程

  • Boost.Compute :用于OpenCL的C++GPU计算库
  • Bolt :针对GPU进行优化的C++模板库
  • C++React :用于C++11的反应性编程库
  • Intel TBB :Intel线程构件块
  • Libclsph:基于OpenCL的GPU加速SPH流体仿真库
  • OpenCL :并行编程的异构系统的开放标准
  • OpenMP:OpenMP API
  • Thrust :类似于C++标准模板库的并行算法库
  • HPX :用于任何规模的并行和分布式应用程序的通用C++运行时系统
  • VexCL :用于OpenCL/CUDA 的C++向量表达式模板库。

 

容器

  • C++ B-tree :基于B树数据结构,实现命令内存容器的模板库
  • Hashmaps: C++中开放寻址哈希表算法的实现

 

密码学

  • Bcrypt :一个跨平台的文件加密工具,加密文件可以移植到所有可支持的操作系统和处理器中。
  • BeeCrypt
  • Botan: C++加密库
  • Crypto++:一个有关加密方案的免费的C++库
  • GnuPG: OpenPGP标准的完整实现
  • GnuTLS :实现了SSL,TLS和DTLS协议的安全通信库
  • Libgcrypt
  • libmcrypt
  • LibreSSL:免费的SSL/TLS协议,属于2014 OpenSSL的一个分支
  • LibTomCrypt:一个非常全面的,模块化的,可移植的加密工具
  • libsodium:基于NaCI的加密库,固执己见,容易使用
  • Nettle 底层的加密库
  • OpenSSL : 一个强大的,商用的,功能齐全的,开放源代码的加密库。
  • Tiny AES128 in C :用C实现的一个小巧,可移植的实现了AES128ESB的加密算法

 

数据库

数据库,SQL服务器,ODBC驱动程序和工具

  • hiberlite :用于Sqlite3的C++对象关系映射
  • Hiredis: 用于Redis数据库的很简单的C客户端库
  • LevelDB: 快速键值存储库
  • LMDB:符合数据库四大基本元素的嵌入键值存储
  • MySQL++:封装了MySql的C API的C++ 包装器
  • RocksDB:来自Facebook的嵌入键值的快速存储
  • SQLite:一个完全嵌入式的,功能齐全的关系数据库,只有几百KB,可以正确包含到你的项目中。

 

调试

调试库, 内存和资源泄露检测,单元测试

  • Boost.Test:Boost测试库
  • Catch:一个很时尚的,C++原生的框架,只包含头文件,用于单元测试,测试驱动开发和行为驱动开发。
  • CppUnit:由JUnit移植过来的C++测试框架
  • CTest:CMake测试驱动程序
  • googletest:谷歌C++测试框架
  • ig-debugheap:用于跟踪内存错误的多平台调试堆
  • libtap:用C语言编写测试
  • MemTrack —用于C++跟踪内存分配
  • microprofile– 跨平台的网络试图分析器
  • minUnit :使用C写的迷你单元测试框架,只使用了两个宏
  • Remotery:用于web视图的单一C文件分析器
  • UnitTest++:轻量级的C++单元测试框架

 

游戏引擎

  • Cocos2d-x :一个跨平台框架,用于构建2D游戏,互动图书,演示和其他图形应用程序。
  • Grit :社区项目,用于构建一个免费的游戏引擎,实现开放的世界3D游戏。
  • Irrlicht :C++语言编写的开源高性能的实时#D引擎
  • Polycode:C++实现的用于创建游戏的开源框架(与Lua绑定)。

 

图形用户界面

  • CEGUI : 很灵活的跨平台GUI库
  • FLTK :快速,轻量级的跨平台的C++GUI工具包。
  • GTK+: 用于创建图形用户界面的跨平台工具包
  • gtkmm :用于受欢迎的GUI库GTK+的官方C++接口。
  • imgui:拥有最小依赖关系的立即模式图形用户界面
  • libRocket :libRocket 是一个C++ HTML/CSS 游戏接口中间件
  • MyGUI :快速,灵活,简单的GUI
  • Ncurses:终端用户界面
  • QCustomPlot :没有更多依赖关系的Qt绘图控件
  • Qwt :用户与技术应用的Qt 控件
  • QwtPlot3D :功能丰富的基于Qt/OpenGL的C++编程库,本质上提供了一群3D控件
  • OtterUI :OtterUI 是用于嵌入式系统和互动娱乐软件的用户界面开发解决方案
  • PDCurses 包含源代码和预编译库的公共图形函数库
  • wxWidgets C++库,允许开发人员使用一个代码库可以为widows, Mac OS X,Linux和其他平台创建应用程序

 

图形

  • bgfx:跨平台的渲染库
  • Cairo:支持多种输出设备的2D图形库
  • Horde3D 一个小型的3D渲染和动画引擎
  • magnum C++11和OpenGL 2D/3D 图形引擎
  • Ogre 3D 用C++编写的一个面向场景,实时,灵活的3D渲染引擎(并非游戏引擎)
  • OpenSceneGraph 具有高性能的开源3D图形工具包
  • Panda3D 用于3D渲染和游戏开发的框架,用Python和C++编写。
  • Skia 用于绘制文字,图形和图像的完整的2D图形库
  • urho3d 跨平台的渲染和游戏引擎。

 

图像处理

  • Boost.GIL:通用图像库
  • CImg :用于图像处理的小型开源C++工具包
  • CxImage :用于加载,保存,显示和转换的图像处理和转换库,可以处理的图片格式包括 BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K。
  • FreeImage :开源库,支持现在多媒体应用所需的通用图片格式和其他格式。
  • GDCM:Grassroots DICOM 库
  • ITK:跨平台的开源图像分析系统
  • Magick++:ImageMagick程序的C++接口
  • MagickWnd:ImageMagick程序的C++接口
  • OpenCV : 开源计算机视觉类库
  • tesseract-ocr:OCR引擎
  • VIGRA :用于图像分析通用C++计算机视觉库
  • VTK :用于3D计算机图形学,图像处理和可视化的开源免费软件系统。

 

国际化

  • gettext :GNU `gettext’
  • IBM ICU:提供Unicode 和全球化支持的C、C++ 和Java库
  • libiconv :用于不同字符编码之间的编码转换库

 

Jason

  • frozen : C/C++的Jason解析生成器
  • Jansson :进行编解码和处理Jason数据的C语言库
  • jbson :C++14中构建和迭代BSON data,和Json 文档的库
  • JeayeSON:非常健全的C++ JSON库,只包含头文件
  • JSON++ : C++ JSON 解析器
  • json-parser:用可移植的ANSI C编写的JSON解析器,占用内存非常少
  • json11 :一个迷你的C++11 JSON库
  • jute :非常简单的C++ JSON解析器
  • ibjson:C语言中的JSON解析和打印库,很容易和任何模型集成。
  • libjson:轻量级的JSON库
  • PicoJSON:C++中JSON解析序列化,只包含头文件
  • qt-json :用于JSON数据和 QVariant层次间的相互解析的简单类
  • QJson:将JSON数据映射到QVariant对象的基于Qt的库
  • RapidJSON: 用于C++的快速JSON 解析生成器,包含SAX和DOM两种风格的API
  • YAJL :C语言中快速流JSON解析库

 

日志

  • Boost.Log :设计非常模块化,并且具有扩展性
  • easyloggingpp:C++日志库,只包含单一的头文件。
  • Log4cpp :一系列C++类库,灵活添加日志到文件,系统日志,IDSA和其他地方。
  • templog:轻量级C++库,可以添加日志到你的C++应用程序中

 

机器学习

  • Caffe :快速的神经网络框架
  • CCV :以C语言为核心的现代计算机视觉库
  • mlpack :可扩展的C++机器学习库
  • OpenCV:开源计算机视觉库
  • Recommender:使用协同过滤进行产品推荐/建议的C语言库。
  • SHOGUN:Shogun 机器学习工具
  • sofia-ml :用于机器学习的快速增量算法套件

 

数学

  • Armadillo :高质量的C++线性代数库,速度和易用性做到了很好的平衡。语法和MatlAB很相似
  • blaze:高性能的C++数学库,用于密集和稀疏算法。
  • ceres-solver :来自谷歌的C++库,用于建模和解决大型复杂非线性最小平方问题。
  • CGal: 高效,可靠的集合算法集合
  • cml :用于游戏和图形的免费C++数学库
  • Eigen :高级C++模板头文件库,包括线性代数,矩阵,向量操作,数值解决和其他相关的算法。
  • GMTL:数学图形模板库是一组广泛实现基本图形的工具。
  • GMP:用于个高精度计算的C/C++库,处理有符号整数,有理数和浮点数。

 

多媒体

  • GStreamer :构建媒体处理组件图形的库
  • LIVE555 Streaming Media :使用开放标准协议(RTP/RTCP, RTSP, SIP) 的多媒体流库
  • libVLC :libVLC (VLC SDK)媒体框架
  • QtAv:基于Qt和FFmpeg的多媒体播放框架,能够帮助你轻而易举地编写出一个播放器
  • SDL :简单直控媒体层
  • SFML :快速,简单的多媒体库

 

网络

  • ACE:C++面向对象网络变成工具包
  • Boost.Asio:用于网络和底层I/O编程的跨平台的C++库
  • Casablanca:C++ REST SDK
  • cpp-netlib:高级网络编程的开源库集合
  • Dyad.c:C语言的异步网络
  • libcurl :多协议文件传输库
  • Mongoose:非常轻量级的网络服务器
  • Muduo :用于Linux多线程服务器的C++非阻塞网络库
  • net_skeleton :C/C++的TCP 客户端/服务器库
  • nope.c :基于C语言的超轻型软件平台,用于可扩展的服务器端和网络应用。 对于C编程人员,可以考虑node.js
  • Onion :C语言HTTP服务器库,其设计为轻量级,易使用。
  • POCO:用于构建网络和基于互联网应用程序的C++类库,可以运行在桌面,服务器,移动和嵌入式系统。
  • RakNet:为游戏开发人员提供的跨平台的开源C++网络引擎。
  • Tuf o :用于Qt之上的C++构建的异步Web框架。
  • WebSocket++ :基于C++/Boost Aiso的websocket 客户端/服务器库
  • ZeroMQ :高速,模块化的异步通信库

 

物理学

动力学仿真引擎

  • Box2D:2D的游戏物理引擎。
  • Bullet :3D的游戏物理引擎。
  • Chipmunk :快速,轻量级的2D游戏物理库
  • LiquidFun:2D的游戏物理引擎
  • ODE :开放动力学引擎-开源,高性能库,模拟刚体动力学。
  • ofxBox2d:Box2D开源框架包装器。
  • Simbody :高性能C++多体动力学/物理库,模拟关节生物力学和机械系统,像车辆,机器人和人体骨骼。

 

机器人学

  • MOOS-IvP :一组开源C++模块,提供机器人平台的自主权,尤其是自主的海洋车辆。
  • MRPT:移动机器人编程工具包
  • PCL :点云库是一个独立的,大规模的开放项目,用于2D/3D图像和点云处理。
  • Robotics Library (RL): 一个独立的C++库,包括机器人动力学,运动规划和控制。
  • RobWork:一组C++库的集合,用于机器人系统的仿真和控制。
  • ROS :机器人操作系统,提供了一些库和工具帮助软件开发人员创建机器人应用程序。

 

科学计算

  • FFTW :用一维或者多维计算DFT的C语言库。
  • GSL:GNU科学库。

 

脚本

  • ChaiScript :用于C++的易于使用的嵌入式脚本语言。
  • Lua :用于配置文件和基本应用程序脚本的小型快速脚本引擎。
  • luacxx:用于创建Lua绑定的C++ 11 API
  • SWIG :一个可以让你的C++代码链接到JavaScript,Perl,PHP,Python,Tcl和Ruby的包装器/接口生成器
  • V7:嵌入式的JavaScript 引擎。
  • V8 :谷歌的快速JavaScript引擎,可以被嵌入到任何C++应用程序中。

 

序列化

  • Cap’n Proto :快速数据交换格式和RPC系统。
  • cereal :C++11 序列化库
  • FlatBuffers :内存高效的序列化库
  • MessagePack :C/C++的高效二进制序列化库,例如 JSON
  • protobuf :协议缓冲,谷歌的数据交换格式。
  • protobuf-c :C语言的协议缓冲实现
  • SimpleBinaryEncoding:用于低延迟应用程序的对二进制格式的应用程序信息的编码和解码。
  • Thrift :高效的跨语言IPC/RPC,用于C++,Java,Python,PHP,C#和其它多种语言中,最初由Twitter开发。注:原文有误,应该是 facebook 在2007年开发的,现在是 Apache 在维护

 

视频

  • libvpx :VP8/VP9编码解码SDK
  • FFmpeg :一个完整的,跨平台的解决方案,用于记录,转换视频和音频流。
  • libde265 :开放的h.265视频编解码器的实现。
  • OpenH264:开源H.364 编解码器。
  • Theora :免费开源的视频压缩格式。

 

虚拟机

  • CarpVM:C中有趣的VM,让我们一起来看看这个。
  • MicroPython :旨在实现单片机上Python3.x的实现
  • TinyVM:用纯粹的ANSI C编写的小型,快速,轻量级的虚拟机。

 

Web应用框架

  • Civetweb :提供易于使用,强大的,C/C++嵌入式Web服务器,带有可选的CGI,SSL和Lua支持。
  • CppCMS :免费高性能的Web开发框架(不是 CMS).
  • Crow :一个C++微型web框架(灵感来自于Python Flask)
  • Kore :使用C语言开发的用于web应用程序的超快速和灵活的web服务器/框架。
  • libOnion:轻量级的库,帮助你使用C编程语言创建web服务器。
  • QDjango:使用C++编写的,基于Qt库的web框架,试图效仿Django API,因此得此名。
  • Wt :开发Web应用的C++库。

 

XML

XML就是个垃圾,xml的解析很烦人,对于计算机它也是个灾难。这种糟糕的东西完全没有存在的理由了。-Linus Torvalds

  • Expat :用C语言编写的xml解析库
  • Libxml2 :Gnome的xml C解析器和工具包
  • libxml++ :C++的xml解析器
  • PugiXML :用于C++的,支持XPath的轻量级,简单快速的XML解析器。
  • RapidXml :试图创建最快速的XML解析器,同时保持易用性,可移植性和合理的W3C兼容性。
  • TinyXML :简单小型的C++XML解析器,可以很容易地集成到其它项目中。
  • TinyXML2:简单快速的C++CML解析器,可以很容易集成到其它项目中。
  • TinyXML++:TinyXML的一个全新的接口,使用了C++的许多许多优势,模板,异常和更好的异常处理。
  • Xerces-C++ :用可移植的C++的子集编写的XML验证解析器。

 

多项混杂

一些有用的库或者工具,但是不适合上面的分类,或者还没有分类。

  • C++ Format :C++的小型,安全和快速格式化库
  • casacore :从aips++ 派生的一系列C++核心库
  • cxx-prettyprint:用于C++容器的打印库
  • DynaPDF :易于使用的PDF生成库
  • gcc-poison :帮助开发人员禁止应用程序中的不安全的C/C++函数的简单的头文件。
  • googlemock:编写和使用C++模拟类的库
  • HTTP Parser :C的http请求/响应解析器
  • libcpuid :用于x86 CPU检测盒特征提取的小型C库
  • libevil :许可证管理器
  • libusb:允许移动访问USB设备的通用USB库
  • PCRE:正则表达式C库,灵感来自于Perl中正则表达式的功能。
  • Remote Call Framework :C++的进程间通信框架。
  • Scintilla :开源的代码编辑控件
  • Serial Communication Library :C++语言编写的跨平台,串口库。
  • SDS:C的简单动态字符串库
  • SLDR :超轻的DNS解析器
  • SLRE: 超轻的正则表达式库
  • Stage :移动机器人模拟器
  • VarTypes:C++/Qt4功能丰富,面向对象的管理变量的框架。
  • ZBar:‘条形码扫描器’库,可以扫描照片,图片和视频流中的条形码,并返回结果。
  • CppVerbalExpressions :易于使用的C++正则表达式
  • QtVerbalExpressions:基于C++ VerbalExpressions 库的Qt库
  • PHP-CPP:使用C++来构建PHP扩展的库
  • Better String :C的另一个字符串库,功能更丰富,但是没有缓冲溢出问题,还包含了一个C++包装器。

 

软件

用于创建开发环境的软件

编译器

C/C++编译器列表

  • Clang :由苹果公司开发的
  • GCC:GNU编译器集合
  • Intel C++ Compiler :由英特尔公司开发
  • LLVM :模块化和可重用编译器和工具链技术的集合
  • Microsoft Visual C++ :MSVC,由微软公司开发
  • Open WatCom :Watcom,C,C++和Fortran交叉编译器和工具
  • TCC :轻量级的C语言编译器

 

在线编译器

在线C/C++编译器列表

  • codepad :在线编译器/解释器,一个简单的协作工具
  • CodeTwist:一个简单的在线编译器/解释器,你可以粘贴的C,C++或者Java代码,在线执行并查看结果
  • coliru :在线编译器/shell, 支持各种C++编译器
  • Compiler Explorer:交互式编译器,可以进行汇编输出
  • CompileOnline:Linux上在线编译和执行C++程序
  • Ideone :一个在线编译器和调试工具,允许你在线编译源代码并执行,支持60多种编程语言。

 

调试器

C/C++调试器列表

 

集成开发环境(IDE)

C/C++集成开发环境列表

  • AppCode :构建与JetBrains’ IntelliJ IDEA 平台上的用于Objective-C,C,C++,Java和Java开发的集成开发环境
  • CLion:来自JetBrains的跨平台的C/C++的集成开发环境
  • Code::Blocks :免费C,C++和Fortran的集成开发环境
  • CodeLite :另一个跨平台的免费的C/C++集成开发环境
  • Dev-C++:可移植的C/C++/C++11集成开发环境
  • Eclipse CDT:基于Eclipse平台的功能齐全的C和C++集成开发环境
  • Geany :轻量级的快速,跨平台的集成开发环境。
  • IBM VisualAge :来自IBM的家庭计算机集成开发环境。
  • Irony-mode:由libclang驱动的用于Emacs的C/C++微模式
  • KDevelop:免费开源集成开发环境
  • Microsoft Visual Studio :来自微软的集成开发环境
  • NetBeans :主要用于Java开发的的集成开发环境,也支持其他语言,尤其是PHP,C/C++和HTML5。
  • Qt Creator:跨平台的C++,Javascript和QML集成开发环境,也是Qt SDK的一部分。
  • rtags:C/C++的客户端服务器索引,用于 跟基于clang的emacs的集成
  • Xcode :由苹果公司开发
  • YouCompleteMe:一个用于Vim的根据你敲的代码快速模糊搜索并进行代码补全的引擎。

 

构建系统

  • Bear :用于为clang工具生成编译数据库的工具
  • Biicode:基于文件的简单依赖管理器。
  • CMake :跨平台的免费开源软件用于管理软件使用独立编译的方法进行构建的过程。
  • CPM:基于CMake和Git的C++包管理器
  • FASTBuild:高性能,开源的构建系统,支持高度可扩展性的编译,缓冲和网络分布。
  • Ninja :专注于速度的小型构建系统
  • Scons :使用Python scipt 配置的软件构建工具
  • tundra :高性能的代码构建系统,甚至对于非常大型的软件项目,也能提供最好的增量构建次数。
  • tup:基于文件的构建系统,用于后台监控变化的文件。

 

静态代码分析

提高质量,减少瑕疵的代码分析工具列表

感谢平凡之路和fffaraz 的整理,转载请注明出处。

IT技术

构建嵌入式Linux + web+sqlite +php5.0 平台

2014年1月16日
构建嵌入式Linux + web+sqlite +php5.0 平台已关闭评论

Web和数据库技术在嵌入式技术中得到越来越广泛的应用,本专题我们来研究如何构建一个嵌入式Linux +web +php+sqlite 平台。

一、 工作软件平台配置

桌面Linux版本: Ubuntu10.04 – LTS

交叉编译器版本: arm-linux-gcc 4.4.3

设置好系统移植编译相关的环境变量,后面编译时用的到,设置方法如下:

#gedit /root/.bashrc  , 在.bashrc 增加如下内容:

export CC=arm-linux-gcc

export AR=arm-linux-ar

export LD=arm-linux-ld

export RANLIB=arm-linux-ranlib

export STRIP=arm-linux-strip

export CC_FOR_BUILD=gcc

保存关闭,gedit ,重新打开命令行终端。

二、移植PHP5

1. 移植zlib库和libxml2库

由于php5需要zlib库和libxml2库的支持,我们首先交叉编译编译zlib库和libxml2库。

1.1    移植zlib库

  • 解压软件包 zlib-1.2.3.tar.bz2 到 zlib-1.2.3目录;

  • 进入到zlib-1.2.3目录,执行 ./configure –shared –prefix=/home/zlibarm 配置 zlib 库;

  • 执行make命令编译 zlib库

  • 执行make install 安装编译好的库

make install 执行完成后, 在/home/zlibarm目录下可以看到我们编译好的 zlib库和相关头文件;

1.2    移植libxml2库

  • 解压软件包libxml2-2.7.8.tar.gz 到libxml2-2.7.8目录

  • 进入到libxml2-2.7.8目录,执行 ./configure –-prefix=/home/libxmlarm –host=arm-linux 配置libxml2库;

  • 执行make命令编译 libxml2库

  • 执行make install 安装编译好的库

make install 执行完成后, 在/home/libxmlarm目录下可以看到我们编译好的 libxml库和相关头文件;

2. 移植PHP5.0软件包

要让我们的WEB服务器支持PHP语言,我们需要移植PHP软件包,PHP软件包我们选择php-5.2.17.tar.gz, PHP移植步骤如下:

  • 解压软件包php-5.2.17.tar.gz到目录php-5.2.17

  • 编写PHP配置脚本文件 elphpcfg.sh, 配置脚本文件内容如下:

—————————————————————————

#! /bin/sh

./configure –prefix=/mnt/disk/eappweb/phparm

–host=arm-linux

–with-sqlite=shared

–with-pdo-sqlite=shared

–with-libxml-dir=/home/libxmlarm

–with-zlib-dir=/home/zlibarm

–disable-all

–enable-pdo=shared

–enable-embed=shared

–with-config-file-path=/mnt/disk/eappweb –with-config-file-scan-dir=/mnt/disk/eappweb

————————————————————————–

  • 编辑完PHP配置脚本文件elphpcfg.sh ,把elphpcfg.sh复制到php-5.2.17目录;

  • 进入php-5.2.17目录,执行 ./elphpcfg.sh配置PHP软件包;

  • 执行make命令编译 PHP5软件包

  • 执行make install 安装编译好的PHP5软件包

make install 执行完成后,在/mnt/disk/eappweb/phparm 目录下可以看到我们交叉编译好的PHP5 库文件及相关可执行文件;

注意: 编译过程中如果出现某些库文件找不到的错误信息,则把刚才编译好的一些库文件复制到编译器库文件所在路径。

三、 移植嵌入式数据库sqlite

Sqlite是嵌入式linux系统中常用的数据库,我们选择的sqlite软件包版本为sqlite-autoconf-3070701[1].tar.gz,Sqlite移植步骤如下:

  • 解压软件包sqlite-autoconf-3070701[1].tar.gz到目录sqlite-autoconf-3070701

  • 进入到sqlite-autoconf-3070701目录,执行./configure –host=arm-linux –prefix=/home/sqlitearm  –disable-tcl 配置sqlite数据库;

  • 执行make命令编译 sqlite软件包

  • 执行make install 安装编译好的sqlite软件包

make install 执行完成后,在/home/sqlitearm 目录下可以看到我们交叉编译好的sqlite 库文件及相关可执行文件;

四 、 移植web服务器appweb

Appweb是在嵌入式linux系统中常用的开源web服务器软件,我们选用的appweb 服务器软件版本为appweb-src-2.4.2-2.zip, appweb 移植步骤如下:

  • 解压软件包appweb-src-2.4.2-2.zip到目录appweb-src-2.4.2;

  • 创建appweb 配置脚本文件 appwebcfg.sh, 配置脚本文件内容如下:

——————————————————————————

#! /bin/sh

./configure –prefix=/home/appwebarm –host=arm-linux –build=i686-pc-linux –disable-shared –disable-shared-libc –enable-static –port=80 –disable-multi-thread –type=RELEASE –disable-test –disable-samples –with-php5=builtin –with-php5-libs=php5 –with-php5-dir=/home/zgdz/php-5.2.17 –with-php5-libpath=/home/zgdz/php-5.2.17/libs –with-php5-iflags="-I/home/zgdz/php-5.2.17  -I/home/zgdz/php-5.2.17/main -I/home/zgdz/php-5.2.17/Zend  -I/home/zgdz/php-5.2.17/TSRM"

——————————————————————————

  • 保存appweb配置脚本文件appwebcfg.sh,并复制到appweb-src-2.4.2目录下;

  • 进入appweb-src-2.4.2目录,执./appwebcfg.sh 配置appweb服务器;

  • 执行make 编译appweb软件包;

  • 执行make install 安装编译好的 appweb软件包;

Make install执行完成后,在/home/appwebarm 目录下可以看到我们交叉编译好的appweb应用软件及相关配置文档。

这样构建嵌入式web服务器 + PHP5 + Sqlite所需用的库文件和软件包都交叉编译完成了,接下来我们开始在嵌入式ARM11开发板 飞凌OK6410上部署嵌入式web服务器 + PHP5 + Sqlite平台。

五、部署嵌入式web PHP5.0 数据库平台

目标平台为飞凌OK6410开发板,在飞凌OK6410开发板上部署嵌入式Linux + appweb + PHP5.0 + sqlite数据库平台步骤如下:

  • 建立 /mnt/disk/eappweb 目录

  • 将appweb、PHP、sqlite相关库文件和配置文件复制到/mnt/disk/eappweb目录下,如下图所示:

构建嵌入式Linux + web+sqlite +php5.0 平台 - lihom_1987@126 - 王老板的博客

其中appweb.conf 是appweb的配置文件,根据实际情况进行配置,这里我们用默认配置即可。Php.ini为 PHP配置文件,修改php.ini文件,设置如下配置参数:

————————————————————————–

short_open_tag = On,

extension_dir = "/mnt/disk/eappweb/"

extension=pdo.so

extension=pdo_sqlite.so

extension=sqlite.so

enable_dl = On

—————————————————————————

  •    设置环境变量LD_LIBRARY_PATH= /mnt/disk/eappweb

  •    运行appweb服务器,执行appweb服务器命令如下:
    ./appweb –f appweb.conf –r /mnt/disk/eappweb

    这样开发板上就运行了appweb服务器。将电脑和开发板用网线连接起来,打开电脑浏览器输入:http://192.168.2.232/test.php 就可以看到PHP测试网页,说明PHP功能测试成功。

六、验证数据 sqlite支持功能

1. 测试数据库加载功能:

编写PHP脚本文件,phptest2.php,内容如下所示:

——————————————————————————-

<?php

if (extension_loaded(‘sqlite’)) {

echo ‘ok’;

}else{

if(!dl(‘sqlite’))

{

echo ‘sorry’;

}

else

{

    echo ‘ok’;

}

}

?>

—————————————————————————–

在浏览器地址栏输入:http://192.168.2.232/phptest2.php,显示OK,说明sqlite库加载成功。

2. 测试sqlite数据库操作功能:

编写脚本文件phptest.php, 内容如下:

————————————————————————–

<?php

$dbname="1.db";

if (!file_exists($dbname))

{

$fp = fopen($dbname, "w+") or die("创建数据库失败!");

fclose($fp);

$db = sqlite_open($dbname) or die("打开数据库失败");

sqlite_query($db, "CREATE TABLE liuyan (id integer primary key,name varchar(10),content text )") or die("建表失败!");;

}

$db = sqlite_open($dbname) or die("打开数据库失败");

if($_POST[‘postdata’])

{

$name=$_POST[‘name’];

$content=$_POST[‘content’];

sqlite_query($db, "INSERT INTO liuyan VALUES (NULL,’".$name."’,’".$content."’)") or die("插入数据失败");

}

$result = sqlite_query($db, ‘select name,content from liuyan’);

while($data=sqlite_fetch_array($result))

$list[]=$data;

?>

<div>

<?php

if(is_array($list))

foreach($list as $key=>$listdata)

echo $listdata[‘name’]. "说:".$listdata[‘content’]."<br />";

?>

</div>

<form action="" method="post">

姓名:<input name="name" type="text" id="name" size="27" /><br />

俺说: <textarea name="content" cols="25" rows="4" id="content"></textarea><br />

<input name="postdata" type="submit" id="postdata" value="提交" />

</form>

——————————————————————————

在浏览器地址栏输入:http://192.168.2.232/phptest.php,显示一个简单的留言板功能。留言后,在开发板的/mnt/disk/eappweb/web目录下可以看到生成的1.db数据库文件。

到这里,我们的嵌入式Linux + web+sqlite +php5.0 平台就构建并且验证完成了。

希望这篇文章对大家移植嵌入式WEB服务器有所帮助。

IT技术, php , , ,

MOV及MP4文件格式中几个重要的Table

2013年12月17日
MOV及MP4文件格式中几个重要的Table已关闭评论

MP4,全称是MPEG4 Part 14,是一种使用MPEG-4的多媒体文件格式,扩展名为.mp4。

MOV,是QuickTime影片格式,它是Apple公司开发的一种音频、视频文件格式,用于存储常用数字媒体类型。其扩展名为.mov。

在MOV和MP4文件格式中包括几个重要的Table,对应的atoms分别为:stts、ctts、stss、stsc、stsz以及stco/co64。

1、Sample时间表stts

stts:Time-To-Sample Atoms,存储了媒体sample的时常信息,提供了时间和相关sample之间的映射关系。该atom包含了一个表,关于time和sample号之间的索引关系。表的每个entry给出了具有相同时间间隔的连续的sample的个数和这些sample的时间间隔值。将这些时间间隔相加在一起,就可以得到一个完整的time与sample之间的映射。将所有的时间间隔相加在一起,就可以得到该track的时间总长。

每个sample的显示时间可以通过如下的公式得到:

D(n+1) = D(n) + STTS(n)

其中,STTS(n)是sample n的时间间隔,包含在表格中;D(n)是sample n的显示时间。

Time-To-Sample的table entry布局如图1-1所示:

图1-1 Time-To-Sample的table entry布局

Table entries根据每个sample在媒体流中的顺序和时长对他们进行描述。如果连续的samples有相同的时长,他们会被放在同一个table entry中。特别的,如果所有的sample具有相同的时长,那么table中就只有一个entry。

一个简单的例子如图1-2所示。这个媒体流包括9个samples,通过3个entries来描述。需要说明的一点是,这里的entry和 chunk不是对应的。比如,sample 4、5和6在同一个chunk中,但是,由于他们的时长不一样,sample 4的时长为3,而sample 5和6的时长为1,因此,通过不同的entry来描述。

图1-2 关于Time-To-Sample的一个简单例子

2、时间合成偏移表ctts

ctts:Composition Offset Atom。每一个视频sample都有一个解码顺序和一个显示顺序。对于一个sample来说,解码顺序和显示顺序可能不一致,比如H.264格式,因此,Composition Offset Atom就是在这种情况下被使用的。

(1)如果解码顺序和显示顺序是一致的,Composition Offset Atom就不会出现。Time-To-Sample Atoms既提供了解码顺序也提供了显示顺序,并能够计算出每个sample的开始时间和结束时间。

(2)如果解码顺序和显示顺序不一致,那么Time-To-Sample Atoms既提供解码顺序,Composition Offset Atom则通过差值的形式来提供显示时间。

Composition Offset Atom提供了一个从解码时间到显示时间的sample一对一的映射,具有如下的映射关系:

CT(n) = DT(n) + CTTS(n)

其中,CTTS(n)是sample n在table中的entry(这里假设一个entry只对应一个sample)可以是正值也可是负值;DT(n)是sample n的解码时间,通过Time-To-Sample Atoms计算获得;CT(n)便是sample n的显示时间。

Composition Offset Atom的table entry的布局和Time-To-Sample Atoms的一样,如图2-1所示:

图2-1 Composition Offset Atom的table entry布局

3、同步Sample表stss

stss:Sync Sample Atom,标识了媒体流中的关键帧,提供了随机访问点标记。Sync Sample Atom包含了一个table,table的每个entry标识了一个sample,该sample是媒体流的关键帧。Table中的sample号是严格按照增长的顺序排列的,如果该table不存在,那么每一个sample都可以作为随机访问点。换句话说,如果Sync Sample Atom不存在,那么所有的sample都是关键帧。

Sync Sample Table的布局如图3-1所示:

图3-1 Sync Sample Table的布局

4、Chunk中的Sample信息表stsc

stsc:Sample-To-Chunk Atom。为了优化数据访问,通常把sample封装到chunk中,一个chunk可能会包含一个或者几个sample。每个chunk会有不同的 size,每个chunk中的sample也会有不同的size。在Sample-To-Chunk Atom中包含了个table,这个table提供了从sample到chunk的一个映射,每个table entry可能包含一个或者多个chunk。Table entry包含的内容包括第一个chunk号、每个chunk包含的sample的个数以及sample的描述ID。Sample-To-Chunk Atom的table entry布局如图4-1所示。

图4-1 Sample-To-Chunk Atom的table entry布局

每个table entry包含一组chunk,enrty中的每个chunk包含相同数目的sample。而且,这些chunk中的每个sample都必须使用相同的 sample description。任何时候,如果chunk中的sample数目或者sample description改变,必须创建一个新的table entry。如果所有的chunk包含的sample数目相同,那么该table只有一个entry。

一个简单的例子,如图4-2所示。图中看不出来总共有多少个chunk,因为entry中只包含第一个chunk号,因此,对于最后一个entry,在某些情况下需要特殊的处理,因为无法判断什么时候结束。

图4-2 一个关于Sample-To-Chunk table的例子

5、Sample大小表stsz

stsz:Sample Size Atom,指定了每个sample的size。Sample Size Atom给出了sample的总数和一张表,这个表包含了每个sample的size。如果指定了默认的sampe size,那么这个table就不存在了。即每个sample使用这个默认的sample size。sample size table的布局如图5-1所示。

图5-1 sample size table的布局

6、Chunk的偏移量表stco/co64

stco/co64:Chunk Offset Atom,指定了每个chunk在文件中的位置。Chunk Offset Atom包含了一个table,表中的每个entry给出了每个chunk在文件中的位置。有两种形式来表示每个entry的值,即chunk的偏移量,32位和64位。如果Chunk Offset Atom的类型为stco,则使用的是32位的,如果是co64,那么使用的就是64位的。chunk offset table的布局如图6-1所示。

图6-1 chunk offset table的布局

需要注意的是,table中只是给出了每个chunk的偏移量,并没有给出每个sample的偏移量。因此,如果要获得每个sample的偏移量,还需要用到Sample Size Table和Sample-To-Chunk Table。

本文来自:http://blog.csdn.net/yu_yuan_1314/article/details/9078287

IT技术 , , , ,

mp4 格式 解析

2013年12月17日
mp4 格式 解析已关闭评论

感谢新浪播客可下人间!

转载地址:http://blog.sina.com.cn/s/blog_48f93b530100jz4b.html

目前MP4的概念被炒得很火,也很乱。最开始MP4指的是音频(MP3的升级版),即MPEG-2 AAC标准。随后MP4概念被转移到视频上,对应的是MPEG-4标准。而现在我们流行的叫法,多半是指能播放MPEG-4标准编码格式视频的播放器。但是这篇文章介绍的内容跟上面这些都无关,我们要讨论的是MP4文件封装格式,对应的标准为ISO/IEC 14496-12,即信息技术 视听对象编码的第12部分:ISO 基本媒体文件格式(Information technology Coding of audio-visual objects Part 12: ISO base media file format)。ISO/IEC组织指定的标准一般用数字表示,ISO/IEC 14496即MPEG-4标准。

MP4视频文件封装格式是基于QuickTime容器格式定义的,因此参考QuickTime的格式定义对理解MP4文件格式很有帮助。MP4文件格式是一个十分开放的容器,几乎可以用来描述所有的媒体结构,MP4文件中的媒体描述与媒体数据是分开的,并且媒体数据的组织也很自由,不一定要按照时间顺序排列,甚至媒体数据可以直接引用其他文件。同时,MP4也支持流媒体。MP4目前被广泛用于封装h.264视频和AAC音频,是高清视频的代表。

现在我们就来看看MP4文件格式到底是什么样的。

1、概述

MP4文件中的所有数据都装在box(QuickTime中为atom)中,也就是说MP4文件由若干个box组成,每个box有类型和长度,可以将 box理解为一个数据对象块。box中可以包含另一个box,这种box称为container box。一个MP4文件首先会有且只有一个“ftyp”类型的box,作为MP4格式的标志并包含关于文件的一些信息;之后会有且只有一个“moov”类型的box(Movie Box),它是一种container box,子box包含了媒体的metadata信息;MP4文件的媒体数据包含在“mdat”类型的box(Midia Data Box)中,该类型的box也是container box,可以有多个,也可以没有(当媒体数据全部引用其他文件时),媒体数据的结构由metadata进行描述。

下面是一些概念:

track  表示一些sample的集合,对于媒体数据来说,track表示一个视频或音频序列。

hint track  这个特殊的track并不包含媒体数据,而是包含了一些将其他数据track打包成流媒体的指示信息。

sample  对于非hint track来说,video sample即为一帧视频,或一组连续视频帧,audio sample即为一段连续的压缩音频,它们统称sample。对于hint track,sample定义一个或多个流媒体包的格式。

sample table  指明sampe时序和物理布局的表。

chunk 一个track的几个sample组成的单元。

在本文中,我们不讨论涉及hint的内容,只关注包含媒体数据的本地MP4文件。下图为一个典型的MP4文件的结构树。

mp4 格式 解析(1) - mu_huilin - 坐看云起

2、Box

首先需要说明的是,box中的字节序为网络字节序,也就是大端字节序(Big-Endian),简单的说,就是一个32位的4字节整数存储方式为高位字节在内存的低端。Box由header和body组成,其中header统一指明box的大小和类型,body根据类型有不同的意义和格式。

标准的box开头的4个字节(32位)为box size,该大小包括box header和box body整个box的大小,这样我们就可以在文件中定位各个box。如果size为1,则表示这个box的大小为large size,真正的size值要在largesize域上得到。(实际上只有“mdat”类型的box才有可能用到large size。)如果size为0,表示该box为文件的最后一个box,文件结尾即为该box结尾。(同样只存在于“mdat”类型的box中。)

size后面紧跟的32位为box type,一般是4个字符,如“ftyp”、“moov”等,这些box type都是已经预定义好的,分别表示固定的意义。如果是“uuid”,表示该box为用户扩展类型。如果box type是未定义的,应该将其忽略。

3、File Type Box(ftyp)

该box有且只有1个,并且只能被包含在文件层,而不能被其他box包含。该box应该被放在文件的最开始,指示该MP4文件应用的相关信息。

“ftyp” body依次包括1个32位的major brand(4个字符),1个32位的minor version(整数)和1个以32位(4个字符)为单位元素的数组compatible brands。这些都是用来指示文件应用级别的信息。该box的字节实例如下:

mp4 格式 解析(1) - mu_huilin - 坐看云起

4、Movie Box(moov)

该box包含了文件媒体的metadata信息,“moov”是一个container box,具体内容信息由子box诠释。同File Type Box一样,该box有且只有一个,且只被包含在文件层。一般情况下,“moov”会紧随“ftyp”出现。

一般情况下(限于篇幅,本文只讲解常见的MP4文件结构),“moov”中会包含1个“mvhd”和若干个“trak”。其中“mvhd”为header box,一般作为“moov”的第一个子box出现(对于其他container box来说,header box都应作为首个子box出现)。“trak”包含了一个track的相关信息,是一个container box。下图为部分“moov”的字节实例,其中红色部分为box header,绿色为“mvhd”,黄色为一部分“trak”。

mp4 格式 解析(1) - mu_huilin - 坐看云起

4.1 Movie Header Box(mvhd)

“mvhd”结构如下表。

字段

字节数

意义

box size

4

box大小

box type

4

box类型

version

1

box版本,0或1,一般为0。(以下字节数均按version=0)

flags

3

creation time

4

创建时间(相对于UTC时间1904-01-01零点的秒数)

modification time

4

修改时间

time scale

4

文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数

duration

4

该 track的时间长度,用duration和time scale值可以计算track时长,比如audio track的time scale = 8000, duration = 560128,时长为70.016,video track的time scale = 600, duration = 42000,时长为70

rate

4

推荐播放速率,高16位和低16位分别为小数点整数部分和小数部分,即[16.16] 格式,该值为1.0(0x00010000)表示正常前向播放

volume

2

与rate类似,[8.8] 格式,1.0(0x0100)表示最大音量

reserved

10

保留位

matrix

36

视频变换矩阵

pre-defined

24

next track id

4

下一个track使用的id号

“mvhd”的字节实例如下图,各字段已经用颜色区分开:

mp4 格式 解析(1) - mu_huilin - 坐看云起

4.2 Track Box(trak)

“trak”也是一个container box,其子box包含了该track的媒体数据引用和描述(hint track除外)。一个MP4文件中的媒体可以包含多个track,且至少有一个track,这些track之间彼此独立,有自己的时间和空间信息。 “trak”必须包含一个“tkhd”和一个“mdia”,此外还有很多可选的box(略)。其中“tkhd”为track header box,“mdia”为media box,该box是一个包含一些track媒体数据信息box的container box。

“trak”的部分字节实例如下图,其中黄色为“trak”box的头,绿色为“tkhd”,蓝色为“edts”(一个可选box),红色为一部分“mdia”。

mp4 格式 解析(1) - mu_huilin - 坐看云起

4.2.1 Track Header Box(tkhd)

“tkhd”结构如下表。

字段

字节数

意义

box size

4

box大小

box type

4

box类型

version

1

box版本,0或1,一般为0。(以下字节数均按version=0)

flags

3

按位或操作结果值,预定义如下:

0x000001 track_enabled,否则该track不被播放;

0x000002 track_in_movie,表示该track在播放中被引用;

0x000004 track_in_preview,表示该track在预览时被引用。

一般该值为7,如果一个媒体所有track均未设置track_in_movie和track_in_preview,将被理解为所有track均设置了这两项;对于hint track,该值为0

creation time

4

创建时间(相对于UTC时间1904-01-01零点的秒数)

modification time

4

修改时间

track id

4

id号,不能重复且不能为0

reserved

4

保留位

duration

4

track的时间长度

reserved

8

保留位

layer

2

视频层,默认为0,值小的在上层

alternate group

2

track分组信息,默认为0表示该track未与其他track有群组关系

volume

2

[8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0

reserved

2

保留位

matrix

36

视频变换矩阵

width

4

height

4

高,均为 [16.16] 格式值,与sample描述中的实际画面大小比值,用于播放时的展示宽高

“tkhd”的字节实例如下图,各字段已经用颜色区分开:

mp4 格式 解析(1) - mu_huilin - 坐看云起

4.2.2 Media Box(mdia)

“mdia”也是个container box,其子box的结构和种类还是比较复杂的。先来看一个“mdia”的实例结构树图

mp4 格式 解析(1) - mu_huilin - 坐看云起

总体来说,“mdia”定义了track媒体类型以及sample数据,描述sample信息。一般“mdia”包含一个“mdhd”,一个“hdlr”和一个“minf”,其中“mdhd”为media header box,“hdlr”为handler reference box,“minf”为media information box。下面依次看一下这几个box的结构。

4.2.2.1 Media Header Box(mdhd)

“mdhd”结构如下表。

字段

字节数

意义

box size

4

box大小

box type

4

box类型

version

1

box版本,0或1,一般为0。(以下字节数均按version=0)

flags

3

creation time

4

创建时间(相对于UTC时间1904-01-01零点的秒数)

modification time

4

修改时间

time scale

4

同前表

duration

4

track的时间长度

language

2

媒体语言码。最高位为0,后面15位为3个字符(见ISO 639-2/T标准中定义)

pre-defined

2

“mdhd”的字节实例如下图,各字段已经用颜色区分开:

mp4 格式 解析(1) - mu_huilin - 坐看云起

4.2.2.2 Handler Reference Box(hdlr)

“hdlr”解释了媒体的播放过程信息,该box也可以被包含在meta box(meta)中。“hdlr”结构如下表。

字段

字节数

意义

box size

4

box大小

box type

4

box类型

version

1

box版本,0或1,一般为0。(以下字节数均按version=0)

flags

3

pre-defined

4

handler type

4

在media box中,该值为4个字符:

“vide”— video track

“soun”— audio track

“hint”— hint track

reserved

12

name

不定

track type name,以‘\0’结尾的字符串

“hdlr”的字节实例如下图,各字段已经用颜色区分开:

mp4 格式 解析(1) - mu_huilin - 坐看云起

4.2.2.3 Media Information Box(minf)

“minf”存储了解释track媒体数据的handler-specific信息,media handler用这些信息将媒体时间映射到媒体数据并进行处理。“minf”中的信息格式和内容与媒体类型以及解释媒体数据的media handler密切相关,其他media handler不知道如何解释这些信息。“minf”是一个container box,其实际内容由子box说明。

一般情况下,“minf”包含一个header box,一个“dinf”和一个“stbl”,其中,header box根据track type(即media handler type)分为“vmhd”、“smhd”、“hmhd”和“nmhd”,“dinf”为data information box,“stbl”为sample table box。下面分别介绍。

下图为“minf”部分字节实例,其中红色为box header,蓝色为“smhd”,绿色为“dinf”,黄色为一部分“stbl”。

mp4 格式 解析(1) - mu_huilin - 坐看云起

4.2.2.3.1 Media Information Header Box(vmhd、smhd、hmhd、nmhd)

Video Media Header Box(vmhd)

字段

字节数

意义

box size

4

box大小

box type

4

box类型

version

1

box版本,0或1,一般为0。(以下字节数均按version=0)

flags

3

graphics mode

4

视频合成模式,为0时拷贝原始图像,否则与opcolor进行合成

opcolor

2×3

{red,green,blue}

Sound Media Header Box(smhd)

字段

字节数

意义

box size

4

box大小

box type

4

box类型

version

1

box版本,0或1,一般为0。(以下字节数均按version=0)

flags

3

balance

2

立体声平衡,[8.8] 格式值,一般为0,-1.0表示全部左声道,1.0表示全部右声道

reserved

2

Hint Media Header Box(hmhd)

Null Media Header Box(nmhd)

非视音频媒体使用该box,略。

4.2.2.3.2 Data Information Box(dinf)

“dinf”解释如何定位媒体信息,是一个container box。“dinf”一般包含一个“dref”,即data reference box;“dref”下会包含若干个“url”或“urn”,这些box组成一个表,用来定位track数据。简单的说,track可以被分成若干段,每一段都可以根据“url”或“urn”指向的地址来获取数据,sample描述中会用这些片段的序号将这些片段组成一个完整的track。一般情况下,当数据被完全包含在文件中时,“url”或“urn”中的定位字符串是空的。

“dref”的字节结构如下表。

字段

字节数

意义

box size

4

box大小

box type

4

box类型

version

1

box版本,0或1,一般为0。(以下字节数均按version=0)

flags

3

entry count

4

“url”或“urn”表的元素个数

“url”或“urn”列表

不定

“url”或“urn”都是box,“url”的内容为字符串(location string),“urn”的内容为一对字符串(name string and location string)。当“url”或“urn”的box flag为1时,字符串均为空。

下面是一个“dinf”的字节实例图。其中黄色为“dinf”的box header,由红色部分我们知道包含的“url”或“urn”个数为1,红色后面为“url”box的内容。紫色为“url”的box header(根据box type我们知道是个“url”),绿色为box flag,值为1,说明“url”中的字符串为空,表示track数据已包含在文件中。

mp4 格式 解析(1) - mu_huilin - 坐看云起

4.2.2.3.3 Sample Table Box(stbl)

“stbl”几乎是普通的MP4文件中最复杂的一个box了,首先需要回忆一下sample的概念。sample是媒体数据存储的单位,存储在media的chunk中,chunk和sample的长度均可互不相同,如下图所示。

mp4文件格式解析(三)

“stbl”包含了关于track中sample所有时间和位置的信息,以及sample的编解码等信息。利用这个表,可以解释sample的时序、类型、大小以及在各自存储容器中的位置。“stbl”是一个container box,其子box包括:sample description box(stsd)、time to sample box(stts)、sample size box(stsz或stz2)、sample to chunk box(stsc)、chunk offset box(stco或co64)、composition time to sample box(ctts)、sync sample box(stss)等。

“stsd”必不可少,且至少包含一个条目,该box包含了data reference box进行sample数据检索的信息。没有“stsd”就无法计算media sample的存储位置。“stsd”包含了编码的信息,其存储的信息随媒体类型不同而不同。

Sample Description Box(stsd)

box header和version字段后会有一个entry count字段,根据entry的个数,每个entry会有type信息,如“vide”、“sund”等,根据type不同sample description会提供不同的信息,例如对于video track,会有“VisualSampleEntry”类型信息,对于audio track会有“AudioSampleEntry”类型信息。

视频的编码类型、宽高、长度,音频的声道、采样等信息都会出现在这个box中。

Time To Sample Box(stts)

“stts” 存储了sample的duration,描述了sample时序的映射方法,我们通过它可以找到任何时间的sample。“stts”可以包含一个压缩的表来映射时间和sample序号,用其他的表来提供每个sample的长度和指针。表中每个条目提供了在同一个时间偏移量里面连续的sample序号,以及samples的偏移量。递增这些偏移量,就可以建立一个完整的time to sample表。

Sample Size Box(stsz)

“stsz” 定义了每个sample的大小,包含了媒体中全部sample的数目和一张给出每个sample大小的表。这个box相对来说体积是比较大的。

Sample To Chunk Box(stsc)

用chunk组织sample可以方便优化数据获取,一个thunk包含一个或多个sample。“stsc”中用一个表描述了sample与chunk的映射关系,查看这张表就可以找到包含指定sample的thunk,从而找到这个sample。

Sync Sample Box(stss)

“stss” 确定media中的关键帧。对于压缩媒体数据,关键帧是一系列压缩序列的开始帧,其解压缩时不依赖以前的帧,而后续帧的解压缩将依赖于这个关键帧。 “stss”可以非常紧凑的标记媒体内的随机存取点,它包含一个sample序号表,表内的每一项严格按照sample的序号排列,说明了媒体中的哪一个 sample是关键帧。如果此表不存在,说明每一个sample都是一个关键帧,是一个随机存取点。

Chunk Offset Box(stco)

“stco” 定义了每个thunk在媒体流中的位置。位置有两种可能,32位的和64位的,后者对非常大的电影很有用。在一个表中只会有一种可能,这个位置是在整个文件中的,而不是在任何box中的,这样做就可以直接在文件中找到媒体数据,而不用解释box。需要注意的是一旦前面的box有了任何改变,这张表都要重新建立,因为位置信息已经改变了。

5、Free Space Box(free或skip)

“free”中的内容是无关紧要的,可以被忽略。该box被删除后,不会对播放产生任何影响。

6、Meida Data Box(mdat)

该box包含于文件层,可以有多个,也可以没有(当媒体数据全部为外部文件引用时),用来存储媒体数据。数据直接跟在box type字段后面,具体数据结构的意义需要参考metadata(主要在sample table中描述)。

普通MP4文件的结构就讲完了,可能会比较乱,下面这张图是常见的box的树结构图,可以用来大致了解MP4文件的构造。

mp4 格式 解析(1) - mu_huilin - 坐看云起

本文完。

再次感谢可下人间。

IT技术 , ,

使用mp4v2将H264+AAC合成mp4文件

2013年8月14日
使用mp4v2将H264+AAC合成mp4文件已关闭评论

摘自:http://www.cnblogs.com/chutianyao/archive/2012/04/13/2446140.html

录制程序要添加新功能:录制CMMB电视节目,我们的板卡发送出来的是RTP流(H264视频和AAC音频),录制程序要做的工作是:

(1)接收并解析RTP包,分离出H264和AAC数据流;

(2)将H264视频和AAC音频以某种格式封装,最后存成文件,供用户查看。

第一步已经有部分代码可供参考,因此很快就完成了。

第二步,我们决定封装成mp4,查找了一些资料后,决定使用开源库mp4v2来合成mp4文件。

技术路线已确定,就开工干活。

(一)mp4格式的基础知识。

关于mp4格式,网上介绍的不少,有以下内容可供参考:

(1)两个ISO标准:

[ISO/IEC 14496-12]:ISO base media file format –”is a general format forming the basis for a number of other more specific file formats. This format contains the timing, structure, and media information for timed sequences of media data, such as audio-visual presentations ”

[ISO/IEC 14496-14]:MP4 file format –”This specification defines MP4 as an instance of the ISO Media File format [ISO/IEC 14496-12 and ISO/IEC
15444-12]. ”

定义了mp4文件格式标准。

(2)http://wenku.baidu.com/view/673482284b73f242336c5f4c.html

是上面两个标准的解释,建议先看这个,了解大概,具体细节再看ISO标准文件。

(二)技术验证。主要就是写验证代码,验证技术可行性。

去官网下载mp4v2源码、编译、安装过程略过不提。所有资料可以在http://code.google.com/p/mp4v2/找到。

先写部分验证代码,很快完成了,但封装出来的文件有问题,无法播放。

合成部分,代码如下:

复制代码

 1 static void* writeThread(void* arg)
 2 {
 3     rtp_s* p_rtp = (rtp_s*) arg;
 4     if (p_rtp == NULL)
 5     {
 6         printf("ERROR!\n");
 7         return;
 8     }
 9 
10     MP4FileHandle file = MP4CreateEx("test.mp4", MP4_DETAILS_ALL, 0, 1, 1, 0, 0, 0, 0);//创建mp4文件
11     if (file == MP4_INVALID_FILE_HANDLE)
12     {
13         printf("open file fialed.\n");
14         return;
15     }
16 
17     MP4SetTimeScale(file, 90000);
18 
19     //添加h264 track    
20     MP4TrackId video = MP4AddH264VideoTrack(file, 90000, 90000 / 25, 320, 240,
21                                             0x64, //sps[1] AVCProfileIndication
22                                             0x00, //sps[2] profile_compat
23                                             0x1f, //sps[3] AVCLevelIndication
24                                             3); // 4 bytes length before each NAL unit
25     if (video == MP4_INVALID_TRACK_ID)
26     {
27         printf("add video track failed.\n");
28         return;
29     }
30     MP4SetVideoProfileLevel(file, 0x7F);
31 
32     //添加aac音频
33     MP4TrackId audio = MP4AddAudioTrack(file, 48000, 1024, MP4_MPEG4_AUDIO_TYPE);
34     if (video == MP4_INVALID_TRACK_ID)
35     {
36         printf("add audio track failed.\n");
37         return;
38     }
39     MP4SetAudioProfileLevel(file, 0x2);
40 
41 
42     int ncount = 0;
43     while (1)
44     {
45         frame_t* pf = NULL; //frame
46         pthread_mutex_lock(&p_rtp->mutex);
47         pf = p_rtp->p_frame_header;
48         if (pf != NULL)
49         {
50             if (pf->i_type == 1)//video
51             {
52                MP4WriteSample(file, video, pf->p_frame, pf->i_frame_size, MP4_INVALID_DURATION, 0, 1);
53              }
54             else if (pf->i_type == 2)//audio
55             {
56                 MP4WriteSample(file, audio, pf->p_frame, pf->i_frame_size , MP4_INVALID_DURATION, 0, 1);
57             }
58 
59             ncount++;
60 
61             //clear frame.
62             p_rtp->i_buf_num--;
63             p_rtp->p_frame_header = pf->p_next;
64             if (p_rtp->i_buf_num <= 0)
65             {
66                 p_rtp->p_frame_buf = p_rtp->p_frame_header;
67             }
68             free_frame(&pf);
69             pf = NULL;
70 
71             if (ncount >= 1000)
72             {
73                 break;
74             }
75         }
76         else
77         {
78             //printf("BUFF EMPTY, p_rtp->i_buf_num:%d\n", p_rtp->i_buf_num);
79         }
80         pthread_mutex_unlock(&p_rtp->mutex);
81         usleep(10000);
82     }
83 
84     MP4Close(file);
85 }

复制代码

现象:没有图像,也没有声音,根本无法播放。

于是,艰苦的工作开始了:跟踪查找原因。

(1)使用 vlc播放合成的mp4文件,查看详细输出:

复制代码

1 vlc -vvv test.mp4
2 [0x8e9357c] mp4 stream debug: found Box: ftyp size 24 
3 [0x8e9357c] mp4 stream debug: found Box: free size 136 
4 [0x8e9357c] mp4 stream debug: skip box: "free" 
5 [0x8e9357c] mp4 stream debug: found Box: mdat size 985725 
6 [0x8e9357c] mp4 stream debug: skip box: "mdat" 
7 [0x8e9357c] mp4 stream debug: found Box: moov size 5187 
8 [0x8e9357c] mp4 stream debug: found Box: mvhd size 108 
9 [0x8e9357c] mp4 stream debug: read box: "mvhd" creation 734515d-06h:22m:03s modification 734515d-06h:22m:23s time scale 90000 duration 694977d-48h:00m:29s rate 1.000000 volume 1.000000 next track id 3 

复制代码

可以看到vlc(实际上是调用libmp4库)解析box都正确的,mdat的大小也是正确的。

但接下来一行:

skip box: "mdat"

就比较奇怪了,明明解析正确了,为什么要将mdat忽略掉呢?要知道,mdat里存放的可是真正的音视频数据阿?如果skip掉了,后面解码时没有数据,当然播放不了了?

(2)既然找到疑点,继续跟踪。

查看vlc的源代码,在文件modules/demux/mp4/libmp4.c中发现:skip信息是由MP4_ReadBoxSkip()函数打印的,而调用的地方在libmp4.c中2641行:

复制代码

 1 /* Nothing to do with this box */
 2 { FOURCC_mdat,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
 3 { FOURCC_skip,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },{ FOURCC_free,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
 4 { FOURCC_wide,  MP4_ReadBoxSkip,        MP4_FreeBox_Common },
 5 
 6 而在libmp4.h中:
 7 #define FOURCC_mdat VLC_FOURCC( 'm', 'd', 'a', 't' )
 8 #define FOURCC_skip VLC_FOURCC( 's', 'k', 'i', 'p' )
 9 #define FOURCC_free VLC_FOURCC( 'f', 'r', 'e', 'e' )
10 #define FOURCC_wide VLC_FOURCC( 'w', 'i', 'd', 'e' )

复制代码

从代码看,vlc调用libmp4解析文件时,主动忽略了mdat,skip,free,wide这四种类型的box。

为什么呢?

(3)继续查看modules/demux/mp4/mp4.c中的Open()函数(解析模块的入口函数),可以看到本模块的主要工作是初始化一个demux_sys_t结构体,该结构体定义如下:

复制代码

 1 struct demux_sys_t
 2 {
 3     MP4_Box_t    *p_root;      /* container for the whole file */
 4     mtime_t      i_pcr;
 5     uint64_t     i_time;         /* time position of the presentation * in movie timescale */
 6     uint64_t     i_timescale;    /* movie time scale */
 7     uint64_t     i_duration;     /* movie duration */
 8     unsigned int i_tracks;       /* number of tracks */
 9     mp4_track_t  *track;         /* array of track */
10     float        f_fps;          /* number of frame per seconds */
11 
12     /* */
13     MP4_Box_t    *p_tref_chap;
14 
15     /* */
16     input_title_t *p_title;
17 };

复制代码

似乎只是为了获取mp4的tracks,moov,duration, timescale等基本信息,实际上并不解码数据,因此就不需要关注mdat这个box了。

综上:vlc的输出是正常的,libmp4忽略了mdat这个box也不是造成mp4文件无法播放的原因,只是因为libmp4这个模块并不真正解码数据,所以不需要关注这个box。

既然问题不在这,那在哪里呢?

(4)继续看vlc的输出:

AVC: nal size -1710483062

no frame!

[0x8e93eb4] avcodec decoder warning: cannot decode one frame (3595 bytes)

可以看到,vlc实际上是调用avcodec(ffmpeg)来解码数据的,我们的视频是AVC(H264)格式的。

从错误信息可以确定,是H264的NAL大小错误,似乎跟mp4文件本身关系不大。

不管那么多,先看看代码再说。

vlc是以lib的形式使用ffmpeg的,所以我们必须看ffmpeg的代码:

复制代码

libavcodec/h264.c:
static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size){

    ….

    for(;;){
        if(buf_index >= next_avc) {
            if(buf_index >= buf_size) break;
            nalsize = 0;
            for(i = 0; i < h->nal_length_size; i++)
                nalsize = (nalsize << 8) | buf[buf_index++];
            if(nalsize <= 0 || nalsize > buf_size - buf_index){
                av_log(h->s.avctx, AV_LOG_ERROR, "AVC: nal size %d\n", nalsize);
                break;
            }
            next_avc= buf_index + nalsize;
        } 

…

}

复制代码

可以看到,正是这里报错的。

但是,为什么报错呢?根据ffmpeg的信息,知道取出来的 nalsize为负数。

怀疑是h264流本身有问题,于是用Elecard查看了生成的mp4文件,视频播放又非常正常。似乎h264流是正常的?

愁呀愁。。。。

(5)在mp4v2的论坛上找到一个帖子,与我的情况非常类似:

http://groups.google.com/group/mp4v2/browse_thread/thread/a4ac6824e585f003/0169c48511f5827a?lnk=gst&q=avc#0169c48511f5827a

内容如下:

Ottavio Campana

“question about MP4AddH264VideoTrack。

What’s the meaning of the profile_compat and

sampleLenFieldSizeMinusOne fields?”

Jeremy Noring

"Usually an NALU is prefixed by the start code 0x00000001. To write it

as a sample in MP4 file format, just replace the start code with size

of the NALU(without 4-byte start code) in big endian. You also need to

specify how many bytes of the size value requires. Take libmp4v2 for

example, the last parameter in MP4AddH264VideoTrack(.., uint8_t

sampleLenFieldSizeMinusOne) indicate the number of byes minus one."

…so each sample you and to mp4v2 should be prefixed with a size code

(in big-endian, of course). I use a 4 byte size code, so

sampleLenFieldSizeMinusOne gets set to 3. This seems to work; my

files playback on just about everything. Perhaps one of the project

maintainers can clarify this, and it’d also be good to update the

documentation of that call to make this clear.”

Ottavio Campana

that’s the code I used as reference to write my program 🙁

but my doubt is that there must be something wrong somewhere, because

boxes seem to be correctly written, but when I try to decode them I

get errors like

[h264 @ 0xb40fa0]AVC: nal size -502662121

have you ever seen an error like this?

Ottavio Campana

> Not sure, but it looks you’re not converting it to big-endian before

> prefixing it to your sample.

well, eventually using ffmpeg to dump the read frames, I discovered

that I had to strip che NALU start code, i.e. the 0x00000001, and to

put the NALU size at its place.

It works perfectly now, but I still wonder why I had to put the size

at the begin of the data, since it is a parameter which is passed to

MP4WriteSample, so I expected the function to add it.

从中得到如下关键信息:

(1)h264流中的NAL,头四个字节是0x00000001;

(2)mp4中的h264track,头四个字节要求是NAL的长度,并且是大端顺序;

(3)mp4v2很可能针对此种情况并没有做处理,所以写到mp4文件中的每个NAL头四个字节还是0x00000001.

那好说,我将每个sample(也就是NAL)的头四个字节内容改成NAL的长度,且试试看:

复制代码

if(pf->i_frame_size >= 4)
{
    uint32_t* p = (&pf->p_frame[0]);
      *p = htonl(pf->i_frame_size -4);//大端,去掉头部四个字节
}
MP4WriteSample(file, video, pf->p_frame, pf->i_frame_size,     MP4_INVALID_DURATION, 0, 1);

复制代码

测试下来,果然OK了!

(6)视频已经解决了,音频还有问题:播放的声音太快。

尝试调整参数:

MP4TrackId audio = MP4AddAudioTrack(file, 48000, 1024, MP4_MPEG4_AUDIO_TYPE);

第三个参数sampleDuration,表示每个sample持续多少个duration,网上看到的都是1024。

我尝试了几个不同的值:128,256,512,4096都不行,最后发现设为2048就正常了。

(为什么是2048??????我不清楚,也许是因为我们的音频是双声道?有时间再研究。。。)

正确代码如下:

复制代码

MP4TrackId audio = MP4AddAudioTrack(file, 48000, 2048, MP4_MPEG4_AUDIO_TYPE);

复制代码

至此,已经成功的将rtp流合成了mp4文件,证明了技术上是可行的。

关于该demo,可以在这里 https://github.com/ZhengfengRao/rtp2mp4 看到。

注意:很多参数都是针对我们的具体应用写死的,仅供参考。

(三)将功能合并到录制程序中。

略。

IT技术 , , ,

AAC ADTS格式分析

2013年8月14日
AAC ADTS格式分析已关闭评论

摘自http://blog.csdn.net/bsplover/article/details/7426476

1.ADTS是个啥

ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式。

记得第一次做demux的时候,把AAC音频的ES流从FLV封装格式中抽出来送给硬件解码器时,不能播;保存到本地用pc的播放器播时,我靠也不能播。当时崩溃了,后来通过查找资料才知道。一般的AAC解码器都需要把AAC的ES流打包成ADTS的格式,一般是在AAC ES流前添加7个字节的ADTS header。也就是说你可以吧ADTS这个头看作是AAC的frameheader。

ADTS AAC

ADTS_header
AAC ES
ADTS_header
AAC ES

ADTS_header
AAC ES

2.ADTS内容及结构

ADTS 头中相对有用的信息 采样率、声道数、帧长度。想想也是,我要是解码器的话,你给我一堆得AAC音频ES流我也解不出来。每一个带ADTS头信息的AAC流会清晰的告送解码器他需要的这些信息。

一般情况下ADTS的头信息都是7个字节,分为2部分:

adts_fixed_header();

adts_variable_header();



syncword :同步头 总是0xFFF, all bits must be 1,代表着一个ADTS帧的开始

ID:MPEG Version: 0 for MPEG-4, 1 for MPEG-2

Layer:always: ’00’

profile:表示使用哪个级别的AAC,有些芯片只支持AAC LC 。在MPEG-2 AAC中定义了3种:

sampling_frequency_index:表示使用的采样率下标,通过这个下标在 Sampling Frequencies[ ]数组中查找得知采样率的值。

There are 13 supported frequencies:

  • 0: 96000 Hz
  • 1: 88200 Hz
  • 2: 64000 Hz
  • 3: 48000 Hz
  • 4: 44100 Hz
  • 5: 32000 Hz
  • 6: 24000 Hz
  • 7: 22050 Hz
  • 8: 16000 Hz
  • 9: 12000 Hz
  • 10: 11025 Hz
  • 11: 8000 Hz
  • 12: 7350 Hz
  • 13: Reserved
  • 14: Reserved
  • 15: frequency is written explictly

channel_configuration: 表示声道数 

  • 0: Defined in AOT Specifc Config
  • 1: 1 channel: front-center
  • 2: 2 channels: front-left, front-right
  • 3: 3 channels: front-center, front-left, front-right
  • 4: 4 channels: front-center, front-left, front-right, back-center
  • 5: 5 channels: front-center, front-left, front-right, back-left, back-right
  • 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
  • 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
  • 8-15: Reserved

frame_length : 一个ADTS帧的长度包括ADTS头和AAC原始流.

adts_buffer_fullness:0x7FF 说明是码率可变的码流

3.将AAC打包成ADTS格式

如果是通过嵌入式高清解码芯片做产品的话,一般情况的解码工作都是由硬件来完成的。所以大部分的工作是把AAC原始流打包成ADTS的格式,然后丢给硬件就行了。

通过对ADTS格式的了解,很容易就能把AAC打包成ADTS。我们只需得到封装格式里面关于音频采样率、声道数、元数据长度、aac格式类型等信息。然后在每个AAC原始流前面加上个ADTS头就OK了。

贴上ffmpeg中添加ADTS头的代码,就可以很清晰的了解ADTS头的结构:

[html] view plaincopy

  1. int ff_adts_write_frame_header(ADTSContext *ctx, 
  2.                                uint8_t *buf, int size, int pce_size) 
  3.     PutBitContext pb; 
  4.     init_put_bits(&pb, buf, ADTS_HEADER_SIZE); 
  5.     /* adts_fixed_header */ 
  6.     put_bits(&pb, 12, 0xfff);   /* syncword */ 
  7.     put_bits(&pb, 1, 0);        /* ID */ 
  8.     put_bits(&pb, 2, 0);        /* layer */ 
  9.     put_bits(&pb, 1, 1);        /* protection_absent */ 
  10.     put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */ 
  11.     put_bits(&pb, 4, ctx->sample_rate_index); 
  12.     put_bits(&pb, 1, 0);        /* private_bit */ 
  13.     put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */ 
  14.     put_bits(&pb, 1, 0);        /* original_copy */ 
  15.     put_bits(&pb, 1, 0);        /* home */ 
  16.     /* adts_variable_header */ 
  17.     put_bits(&pb, 1, 0);        /* copyright_identification_bit */ 
  18.     put_bits(&pb, 1, 0);        /* copyright_identification_start */ 
  19.     put_bits(&pb, 13, ADTS_HEADER_SIZE + size + pce_size); /* aac_frame_length */ 
  20.     put_bits(&pb, 11, 0x7ff);   /* adts_buffer_fullness */ 
  21.     put_bits(&pb, 2, 0);        /* number_of_raw_data_blocks_in_frame */ 
  22.     flush_put_bits(&pb); 
  23.     return 0; 

IT技术 , ,

基于liveMedia的RTSP/RTP编程

2012年4月23日
基于liveMedia的RTSP/RTP编程已关闭评论

 

liveMedia项目的源代码包括四个基本的库,各种测试代码以及IVE555 Media Server。
四个基本的库分别是UsageEnvironment&TaskScheduler,groupsock,liveMedia,BasicUsageEnvironment。
UsageEnvironment 和TaskScheduler类用于事件的调度,实现异步读取事件的句柄的设置以及错误信息的输出。另外,还有一个HashTable类定义了一个通用的 hash表,其它代码要用到这个表。这些都是抽象类,在应用程序中基于这些类实现自己的子类。
groupsock类是对网络接口的封装,用于收发数据包。正如名字本身,Groupsock主要是面向多播数据的收发的,它也同时支持单播数据的收发。Groupsock定义了两个构造函数
    Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr,
              Port port, u_int8_t ttl);
    Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr,
              struct in_addr const& sourceFilterAddr,
              Port port);
前 者是用于SIM(source-independent multicast)组,后者用于SSM(source-specific multicast)组。groupsock库中的Helper例程提供了读写socket等函数,并且屏蔽了不同的操作系统之间的区别,这是在 GroupsockHelper.cpp文件中实现的。
liveMedia库中有一系列类,基类是Medium,这些类针对不同的流媒体类型和编码。
各种测试代码在testProgram目录下,比如openRTSP等,这些代码有助于理解liveMedia的应用。
LIVE555 Media Server是一个纯粹的RTSP服务器。支持多种格式的媒体文件:
      * TS流文件,扩展名ts。
      * PS流文件,扩展名mpg。
      * MPEG-4视频基本流文件,扩展名m4e。
      * MP3文件,扩展名mp3。
      * WAV文件(PCM),扩展名wav。
      * AMR音频文件,扩展名.amr。
      * AAC文件,ADTS格式,扩展名aac。 
用live555开发应用程序
基 于liveMedia的程序,需要通过继承UsageEnvironment抽象类和TaskScheduler抽象类,定义相应的类来处理事件调度,数 据读写以及错误处理。live项目的源代码里有这些类的一个实现,这就是“BasicUsageEnvironment”库。 BasicUsageEnvironment主要是针对简单的控制台应用程序,利用select实现事件获取和处理。这个库利用Unix或者 Windows的控制台作为输入输出,处于应用程序原形或者调试的目的,可以用这个库用户可以开发传统的运行与控制台的应用。 
通过使 用自定义的“UsageEnvironment”和“TaskScheduler”抽象类的子类,这些应用程序就可以在特定的环境中运行,不需要做过多的 修改。需要指出的是在图形环境(GUI toolkit)下,抽象类 TaskScheduler 的子类在实现 doEventLoop()的时候应该与图形环境自己的事件处理框架集成。
先来熟悉在liveMedia库中Source,Sink以及 Filter等概念。Sink就是消费数据的对象,比如把接收到的数据存储到文件,这个文件就是一个Sink。Source就是生产数据的对象,比如通过 RTP读取数据。数据流经过多个’source’和’sink’s,下面是一个示例:
      ‘source1’ -> ‘source2’ (a filter) -> ‘source3’ (a filter) -> ‘sink’
从其它Source接收数据的source也叫做"filters"。Module是一个sink或者一个filter。
数据接收的终点是Sink类,MediaSink是所有Sink类的基类。MediaSink的定义如下:
class MediaSink: public Medium {
public:
    static Boolean lookupByName(UsageEnvironment& env, char const* sinkName,
                                MediaSink*& resultSink);
    typedef void (afterPlayingFunc)(void* clientData);
    Boolean startPlaying(MediaSource& source,
                         afterPlayingFunc* afterFunc,
                         void* afterClientData);
    virtual void stopPlaying();
    // Test for specific types of sink:
    virtual Boolean isRTPSink() const;
    FramedSource* source() const {return fSource;}
protected:
    MediaSink(UsageEnvironment& env); // abstract base class
    virtual ~MediaSink();
    virtual Boolean sourceIsCompatibleWithUs(MediaSource& source);
        // called by startPlaying()
    virtual Boolean continuePlaying() = 0;
        // called by startPlaying()
    static void onSourceClosure(void* clientData);
        // should be called (on ourselves) by continuePlaying() when it
        // discovers that the source we’re playing from has closed.
    FramedSource* fSource;
private:
    // redefined virtual functions:
    virtual Boolean isSink() const;
private:
    // The following fields are used when we’re being played:
    afterPlayingFunc* fAfterFunc;
    void* fAfterClientData;
};
Sink 类实现对数据的处理是通过实现纯虚函数continuePlaying(),通常情况下continuePlaying调用 fSource->getNextFrame来为Source设置数据缓冲区,处理数据的回调函数等,fSource是MediaSink的类型为 FramedSource*的类成员;
基于liveMedia的应用程序的控制流程如下:
应用程序是事件驱动的,使用如下方式的循环
      while (1) {
          通过查找读网络句柄的列表和延迟队列(delay queue)来发现需要完成的任务
          完成这个任务
      }
对于每个sink,在进入这个循环之前,应用程序通常调用下面的方法来启动需要做的生成任务:
      someSinkObject->startPlaying();
任何时候,一个Module需要获取数据都通过调用刚好在它之前的那个Module的FramedSource::getNextFrame()方法。这是通过纯虚函数FramedSource:doGetNextFrame()实现的,每一个Source module都有相应的实现。
Each ‘source’ module’s implementation of "doGetNextFrame()" works by arranging for an ‘after getting’ function to be called (from an event handler) when new data becomes available for the caller.
注意,任何应用程序都要处理从’sources’到’sinks’的数据流,但是并非每个这样的数据流都与从网络接口收发数据相对应。
比 如,一个服务器应用程序发送RTP数据包的时候用到一个或多个"RTPSink" modules。这些"RTPSink" modules以别的方式接收数据,通常是文件 "*Source" modules (e.g., to read data from a file), and, as a side effect, transmit RTP packets. 
一个简单的RTSP客户端程序
在另一个文章里,给出了这个简单的客户端的程序的代码,可以通过修改Makefile来裁剪liveMedia,使得这个客户端最小化。此客户端已经正常运行。
首先是OPTION
然后是DESCRIBE
      建立Media Session,调用的函数是 MediaSession::createNew,在文件liveMedia/MediaSession.cpp中实现。
      为这个Media Session建立RTPSource,这是通过调用 MediaSubsession::initiate来实现的的,这个方法在liveMedia/MediaSession.cpp中实现。
在然后是SETUP
最后是PLAY
rtp数据的句柄:MultiFramedRTPSource::networkReadHandler 在liveMedia/MultiFramedRTPSource.cpp中
rtcp数据处理的句柄:RTCPInstance::incomingReportHandler 在liveMedia/RTCP.cpp中
rtp 数据处理的句柄的设置:MultiFramedRTPSource:doGetNextFrame 在liveMedia/MultiFramedRTPSource.cpp中, 被FileSink::continuePlaying调用在FileSink.cpp中.
rtcp数据处理的句柄设置fRTCPInstance = RTCPInstance::createNew 在/liveMedia/MediaSession.cpp中调用,
createNew调用了构造函数RTCPInstance::RTCPInstance,这个构造函数有如下调用
TaskScheduler::BackgroundHandlerProc* handler = (TaskScheduler::BackgroundHandlerProc*)&incomingReportHandler; 

*********************************************************************************************************************
通过分析live库提供的例子程序OpenRTSP,可以清晰地了解客户端接收来自网络上媒体数据的过程。注意,RTP协议和RTCP协议接收的数据分别是 视音频数据和发送/接收状况的相关信息,其中,RTP协议只负责接收数据,而RTCP协议除了接收服务器的消息之外,还要向服务器反馈。
A.        main函数流程
main(int argc,char *argv[])
{
1.            创建BasicTaskScheduler对象
2.            创建BisicUsageEnvironment对象
3.            分析argv参数,(最简单的用法是:openRTSP rtsp://172.16.24.240/mpeg4video.mp4)以便在下面设置一些相关参数
4.            创建RTSPClient对象
5.            由RTSPClient对象向服务器发送OPTION消息并接受回应
6.            产生SDPDescription字符串(由RTSPClient对象向服务器发送DESCRIBE消息并接受回应,根据回应的信息产生SDPDescription字符串,其中包括视音频数据的协议和解码器类型)
7.            创建MediaSession对象(根据SDPDescription在MediaSession中创建和初始化MediaSubSession子会话对象)
8.            while循环中配置所有子会话对象(为每个子会话创建RTPSource和RTCPInstance对象,并创建两个GroupSock对象,分别对应 RTPSource和RTCPInstance对象,把在每个GroupSock对象中创建的socket描述符置入 BasicTaskScheduler::fReadSet中,RTPSource对象的创建的依据是SDPDescription,例如对于MPEG4 文件来说,视音频RTPSource分别对应MPEG4ESVideoRTPSource和MPEG4GenericRTPSource对象。 RTCPInstance对象在构造函数中完成将Socket描述符、处理接收RTCP数据的函数 (RTCPInstance::incomingReportHandler)以及RTCPInstance本身三者绑定在一个 HandlerDescriptor对象中,并置入BasicTaskScheduler::fReadHandler中。完成绑定后会向服务器发送一条 消息。)
9.            由RTSPClient对象向服务器发送SETUP消息并接受回应。
10.        while循环中为每个子会话创建接收器(FileSink对象),在FileSink对象中根据子会话的codec等属性缺省产生记录视音频数据的文件 名,视音频文件名分别为:video-MP4V-ES-1和audio-MPEG4-GENERIC-2,无后缀名
11.        while循环中为每个子会话的视音频数据装配相应的接收函数,将每个子会话中的RTPSource中的GroupSock对象中的SOCKET描述符, 置入BasicTaskScheduler::fReadSet中,并将描述符、处理接收RTP数据的函数 (MultiFramedRTPSource::networkReadHandler)以及RTPSource本身三者绑定在一个 HandlerDescriptor对象中,并置入BasicTaskScheduler::fReadHandler中,并将FileSink的缓冲区 和包含写入文件操作的一个函数指针配置给RTPSource对象,这个缓冲区将会在networkReadHandler中接收来自网络的视音频数据(分 析和去掉RTP包头的工作由RTPSource完成),而这个函数指针在networkReadHandler中被调用以完成将缓冲区中的数据写入文件。
12.        由RTSPClient对象向服务器发送PLAY消息并接受回应。
13.        进入while循环,调用BasicTaskScheduler::SingleStep()函数接受数据,直到服务器发送TREADOWN消息给客户端,客户端接收到该消息后释放资源,程序退出。

}

IT技术 , , , ,

cc、gcc、g++、CC的区别概括

2012年4月10日
cc、gcc、g++、CC的区别概括已关闭评论
      gcc是C编译器;g++是C++编译器;linux下cc一般是一个符号连接,指向gcc;gcc和g++都是GUN(组织)的编译器。而CC则一般是makefile里面的一个名字,即宏定义,嘿,因为Linux/Unix都是大小写敏感的系统,这点一定要注意。

cc是Unix系统的C Compiler,而gcc则是GNU Compiler Collection,GNU编译器套装。gcc原名为Gun C语言编译器,因为它原本只能处理C语言,但gcc很快地扩展,包含很多编译器(C、C++、Objective-C、Ada、Fortran、Java)。因此,它们是不一样的,一个是古老的C编译器,一个是GNU编译器集合,gcc里面的C编译器比cc强大多了,因此没必要用cc。

下载不到cc的原因在于:cc来自于昂贵的Unix系统,cc是商业软件。

Linux下的cc是gcc符号连接,可以通过$ls –l /usr/bin/cc来简单察看,该变量是make程序的内建变量,默认指向gcc。cc符号链接和变量存在的意义在于源码的移植性,可以方便的用gcc来编译老的用cc编译的Unix软件,甚至连makefile都不用改在,而且也便于Linux程序在Unix下编译。

 

误区一:gcc只能编译C代码,g++只能编译C++代码。

两者都可以,但请注意:

(1)后缀为.c的,gcc把它当作是C程序,而g++当作是c++程序;后缀为.cpp的,两者都会认为是C++程序,注意,虽然C++是C的超集,但是两者对语法的要求是有区别的。C++的语法规则更加严谨一些。

(2)编译阶段,g++会调用gcc,对于C++代码,两者是等价的,但是因为gcc命令不能自动和C++程序使用的库联接,所以通常用g++来完成链接,为了统一起见,干脆编译/链接统统用g++了,这就给人一种错觉,好像cpp程序只能用g++似的。

 

误区二:gcc不会定义__cplusplus宏,而g++会

实际上,这个宏只是标志着编译器将会把代码按C还是C++语法来解释,如上所述,如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则,就是已定义。

 

误区三:编译只能用gcc,链接只能用g++

严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g++,而链接可以用g++或者gcc -lstdc++。因为gcc命令不能自动和C++程序使用的库联接,所以通常使用g++来完成联接。但在编译阶段,g++会自动调用gcc,二者等价。

 

C++的编译器肯定可以编译C的代码,注意除了C++对C的语法扩充之外,编译和链接C和C++的标准库通常也不一样呢,用gcc而非g++也编译了C++的程序就证明了这一点。

 

注:符号链接是一种特殊类型的文件,它的内容只是一个字符串。它可能指向一个存在的文件也可能什么都不指向。当您在命令行或程序里提到符号链接的时候,您实际上进入了它指向的文件,前提是这个文件是存在的。

IT技术 , , ,

IP实时传输协议RTP/RTCP详解

2012年3月20日
IP实时传输协议RTP/RTCP详解已关闭评论

IP实时传输协议RTP/RTCP详解

1、简介

目前,在IP网络中实现实时语音、视频通信和应用已经成为网络应用的一个主流技术和发展方向,本文详细介绍IP协议族中用于实时语音、视频数据传输的标准协议RTP( Real-time Transport Protocol)和RTCP(RTP Control Ptotocol)的主要功能。

2、RTP/RTCP协议简介

      RTP 由 IETF(www.ietf.org)定义在 RFC 3550和3551中。

      RTP被定义为传输音频、视频、模拟数据等实时数据的传输协议,与传统的注重的高可靠的数据传输的运输层协议相比,它更加侧重的数据传输的实时性,此协议提供的服务包括数据顺序号、时间标记、传输控制等。

      RTP通常与辅助控制协议RTCP一起工作,RTP只负责实时数据的传输,RTCP负责对RTP的通信和会话进行带外管理(如流量控制、拥塞控制、会话源管理等)。

3、RTP/RTCP协议层次和封装

      RTP位于传输层(通常是UDP)之上,应用程序之下,实时语音、视频数据经过模数转换和压缩编码处理后,先送给RTP封装成为RTP数据单元,RTP数据单元被封装为UDP数据报,然后再向下递交给IP封装为IP数据包。

      RTP分组只包含RTP数据,而控制是由另一个配套协议RTCP提供。RTP在端口号1025到65535之间选择一个未使用的偶数UDP端口号,而在同一次会话中的RTCP则使用下一个奇数UDP端口号。

      RTP通常和RTCP一起工作,在RTP会话期间,各参与者周期的发送RTCP消息。RTCP消息含有已发送数据的丢包统计和网络拥塞等信息,服务器可以利用这些信息动态的改变传输速率,甚至改变净荷的类型。RTCP消息也被封装为UDP数据报进行传输。

4、RTP/RTCP协议头信息

      version (V): 2 bits    
标明RTP版本号。协议初始版本为0,RFC3550中规定的版本号为2。

       padding (P): 1 bit    
如果该位被设置,则在该packet末尾包含了额外的附加信息,附加信息的最后一个字节表示额外附加信息的长度(包含该字节本身)。该字段之所以存在是因为一些加密机制需要固定长度的数据块,或者为了在一个底层协议数据单元中传输多个RTP packets。

      extension (X): 1 bit
如果该位被设置,则在固定的头部后存在一个扩展头部,格式定义在RFC3550 5.3.1节。

      CSRC count (CC): 4 bits
在固定头部后存在多少个CSRC标记。

      marker (M): 1 bit
该位的功能依赖于profile的定义。profile可以改变该位的长度,但是要保持marker和payload type总长度不变(一共是8 bit)。

      payload type (PT): 7 bits
标记着RTP packet所携带信息的类型,标准类型列出在RFC3551中。如果接收方不能识别该类型,必须忽略该packet。

      sequence number: 16 bits
序列号,每个RTP packet发送后该序列号加1,接收方可以根据该序列号重新排列数据包顺序。

      timestamp: 32 bits
时间戳。反映RTP packet所携带信息包中第一个字节的采样时间。

      SSRC: 32 bits
数据源标识。在一个RTP Session其间每个数据流都应该有一个不同的SSRC。

      CSRC list: 0 to 15 items, 每个源标识32 bits
贡献数据源标识。只有存在Mixer的时候才有效。如一个将多声道的语音流合并成一个单声道的语音流,在这里就列出原来每个声道的SSRC。

5、RTCP协议

      RTCP协议处理机根据定义了五种类型的报文:
      RR: receiver report
      SR: sender report
      SDES: source description items.
      BYE: indicates end of participation.
      APP: application specific functions
它们完成接收、分析、产生和发送控制报文的功能。

      RTCP可以说是控制交通的协议,它提供了:

      1)SR发送者报告分组:用来使发送端周期的向所有接收端用多播方式进行报告。内容包括:

该RTP流的SSRC;该RTP流中最新产生的RTP分组的时间戳和绝对时钟时间(或称墙上时间:wall clock time);该RTP流包含的分组数;该RTP流包含的字节数。

绝对时钟时间是必要的。因为RTP要求每一种媒体使用一个流。有了绝对时钟时间就可以进行图形和声音的同步。

      2)RR接收者报告分组:用来使接收端周期性的向所有的点用多播方式进行报告。内容包括

所接收到的RTP流的SSRC;该RTP流的分组丢失率;在该RTP流中的最后一个RTP分组的序号;分组到达时间间隔的抖动等。

发送RR分组有两个目的。第一,可以使所有的接收端和发送端了解当前网络的状态。

第二,可以使所有发送RTCP分组的站点自适应的调整自己发送RTCP分组的速率,RTCP分组的通信量不超过网络中的数据分组的通信量的5%,而接收端分组报告分组的通信量又应小于所有RTCP分组的通信量的75%。

      3)SDES源描述分组:给出会话中参加者的描述,包括参加者的规范名(CNAME)

      4)BYE分组:关闭一个数据流。

      5)APP分组:应用程序能够定义新的分组类型。

6、实时流协议RTSP协议

      1) RTSP协议

          RTSP(Real Time Streaming Protocol)协议定义了如何有效地通过IP网络传送多媒体数据,是一种客户端到服务器端的多媒体描述协议,详见RFC2326。
          RTSP是一个非常类似于HTTP的应用层协议。每个发布和媒体文件也被定义为RTSP UPL。而媒体文件的发布信息被书写进一个被称为媒体发布文件里,这个文件在后面会说明。在这个文件说明的包括编码器,语言,RTSP ULS,地址,端口号以几其它参数。这个发布文件可以在客户端通过EMAIL形式或者HTTP形式获得。

      2) RTSP协议的特点:

      RTSP是应用层协议,与RTP、RSVP一起设计来完全流式服务。
      RTSP有很大的灵活性,可被用在多种操作系统上,它允许客户端和不同厂商的服务平台交互。
      RTSP在体系结构上位于RTP和RTCP之上,它使用RTP完成数据传输。它将流式媒体数据可控制的通过网络传输到客户端。
      RTSP可以保持用户计算机与传输流业务服务器之间的固定连接,用于观看者与单播(Unicast)服务器通信并且还允许双向通信,观看者可以同流媒体服务器通信.
提供类似“VCR”形式的例如暂停、快进、倒转、跳转等操作。操作的资源对象可以是直播流也可以是存储片段。
      RTSP是设还提供了选择传输通道,如使用UDP还是多点UDP或是TCP。

7、资源预留协议RSVP

      1) RSVP协议:
      RSVP (Resorce reSerVation Protocol) 资源预留协议并不是一个路由协议,而是一种IP网络中的信令协议,它与路由协议相结合来实现对网络传输服务质量(QoS)的控制。RSVP是为支持因特网综合业务而提出的。这是解决IP通信中QoS(服务质量)问题的一种技术,用来保证点端到端的传输带宽。

      2) RSVP协议是如何工作:
      RSVP使用控制数据报,这些数据报在向特定地址传输时包括了需要由路由器检查(有些时候需要更新)的信息,如果路由器需要决定是不是要检查数据报的内容的时候对上层数据内容进行语法分析。这种分析的代价可不小。现在的情况是,网络终端利用它向网络申请资源,在这种表明“申请” 的信号中,包含着如下的信息:业务的种类? 使用者类型? 什么时间?需要多大带宽? 其他参考信息? 网络在接收到上类信息后,会根据实际情况为此次连接分配一个优先代码,用户利用优先代码进行信息传递时,网络不需重新对业务进行分析与判别,从另外一个角度来说,利用RSVP 能从一定程度上减少网络对信息处理的时延,提高网络节点的工作效率,改善信息传输的服务质量(QoS)。实时应用用RSVP是为了在传输路径中保持必要的资源以保证请求能确保到达。
      RSVP是IP路由器为提供更好的服务质量向前迈进的具有深刻意义的一步。传统上IP路由器只负责分组转发,通过路由协议知道邻近路由器的地址。而RSVP则类似于电路交换系统的信令协议一样,为一个数据流通知其所经过的每个节点(IP路由器),与端点协商为此数据流提供质量保证。

8、结束语

在前面我们讨论了一些与实时数据传输相关的四个协议:

      1)RTP是实时数据传输协议。它提供时间标志,序列号以及其它能够保证在实时数据传输时处理时间的方法;它是依靠RVSP保证服务质量标准的。
      2)RTCP是RTP的控制部分,是用来保证服务质量和成员管理的。
      3)RTSP是开始和指引流媒体数据从流媒体服务器。它又可叫做"网上录像机控制协议".它是提供远程的控制,具体的数据传输是交给RTP的。
      4)RSVP是Internet上的资源预订协议,使用RSVP预留一部分网络资源(即带宽),能在一定程度上为流媒体的传输提供QoS。就像TCP的重发和滑动窗口等都是

IT技术 , , , ,

RTMP 协议研究(转载)

2012年2月22日
RTMP 协议研究(转载)已关闭评论

原文地址:http://blog.csdn.net/chenyanxu/archive/2009/09/02/4511087.aspx
正文开始:

RTMP 协议研究

1 协议研究概述
   协议设计和分析一直都是在工作遇到,正好在这里总结一下,说到协议,在这个网络的时代,没有人可以离开它了。他存在我们生活中的任何角落,只不过我们平时,并没有注意到它的存在,可以这么说如果没有协议,我们生活和日常的工作生产都不能进行。如果仔细想想你生活中用到的所有东西,协议已经包含其中。那到底什么是协议呢?说的简单一点就是双方达成的共识,以便更好的交流,理论上协议是什么呢?如果学过《信号与系统》的人都知道有个简单的道理,就是信息在经过一个管道的符号集,到另一个符号集时信息不会丢失。

    任何复杂的事物都有个最简单的本质,网络上的协议也是这样,有个最基本的本质。除去上下层的概念,协议就只剩下通信双方实体的规则。

   一般的协议都包含最基本的协议头,不管是物理层、链路层、还是网络层,这个头就构成了协议的本质东西。通常协议头要包含以下最基本的三项信息:

双方实体的唯一标示,用来标示通信双方的实体。
类型描述或者是净核描述,标志净核的内容。
协议净核的长度,用来在萃取净核的内容应用。
   其中,前两项是必须要有的,没有他们,通信双方的交互根本得不到保证,第三项在不太灵活的通信中可以去掉,而有第二项的类型推出。

    协议的丰富性,有净核的多样性体现。

   协议头除了以上的三项,还可以增加更多的信息(比如控制信息、时间信息等),取决于具体的应用。找到这些基本的东西,再去看协议的时候,能够更好的抓住协议的主体进行分析和设计了。

2 RTMP 协议概述
   RTMP 协议是被 Flash 用于对象、视频、音频的传输。该协议建立在 TCP 协议或者轮询 HTTP 协议之上, RTMP 协议就像一个用来装数据包的容器,这些数据可以是 AMF 格式的数据,也可以是 FLV 中的视 / 音频数据。一个单一的连接可以通过不同的通道传输多路网络流,这些通道中的包都是按照固定大小的包传输的 .

3 RTMP 协议部分

3.1 协议头
struct RTMP_HEAD

{

      char cChannelid : 6;// 第一个字节的后 6 位

      char cCheadsize ; // 第一个字节的头两位

      char cTimer[3];  // 三个字节表示的时间信息

      char cLength[3]; // 三个字节表示的长度

      char cDatatype; // 数据类型

      char sStreamid[4]; // 流标识

};

这里有三个最基本的元素(唯一标示 )、(类型 )和(净核的长度 )分别是: cChannelid 、 cDatatype 和 cLength 。

3.2 数据类型
数据类型 决定了协议上层可以做的具体的事情,和使用协议的人必须遵循的规则。

同时数据类型 说明了净核 的基本内容。

RTMP 数据类型:

0×01,  Chunk Size,  changes the chunk size for packets 
0×02,  Unknown,   anyone know this one? 
0×03,  Bytes Read,  send every x bytes read by both sides 
0×04,  Ping,  ping is a stream control message, has subtypes 
0×05,  Server BW,  the servers downstream bw 
0×06,  Client BW,  the clients upstream bw 
0×07,  Unknown,  anyone know this one? 
0×08,  Audio Data,  packet containing audio 
0×09,  Video Data,  packet containing video data 
0×0A-0×11, Unknown,  anyone know? 
0×12,  Notify,  an invoke which does not expect a reply 
0×13,  Shared Object,  has subtypes 
0×14,  Invoke,  like remoting call, used for stream actions too. 

3.3 协议的净核
   RTMP 的协议净核是用 AMF 格式来描述, AMF 格式本身的产生就是为了 RTMP 协议服务的,最初的 RTMP 采用 XML 的形式传输数据,但 XML 只是字符形式的值对的格式传输数据,而随着应用的普及这完全不能满足要求了,比如对象、结构、数组,甚至可以是数据集,配合 DataGrid 组件可以很方便地显示数据。
为了处理复杂数据类型,采用一种独有的方式使 Flash 与应用服务器间可以来回传送数据势在必行。于是 AMF 应运而生。

AMF 是 Adobe 独家开发出来的通信协议,它采用二进制压缩,序列化、反序列化、传输数据,从而为 Flash 播放器与 Flash Remoting 网关通信提供了一种轻量级的、高效能的通信方式。 
AMF 最大的特色在于可直接将 Flash 内置对象,例如 Object, Array, Date, XML ,传回服务器端,并且在服务器端自动进行解析成适当的对象,这就减轻了开发人员繁复工作,同时也更省了开发时间。由于 AMF 采用二进制编码,这种方式可以高度压缩数据,因此非常适合用 来传递大量的资料。数据量越大, Flash Remoting 的传输效能就越高,远远超过 Web Service 。至于 XML, LoadVars 和 loadVariables() ,它们使用纯文本的传输方式,效能就更不能与 Flash Remoting 相提并论了。

注意: Flash Remoting 需要浏览器支持 Binary POST , Flash 播放器在 Netscape 6.x. 环境下运行 Flash Remoting 会不起作用( Flash Remoting 调用没有效果也不返回错误), Netscape 7 已经纠正了这个 bug 。对于早期 Safari 和 Chimera 版的苹果机也有这个问题。
同样是轻量级数据交换协议,同样是通过调用远程服务,同样是基于标准的 HTTP 和 HTTPS 协议, Flash Remoting 为什么选择了使用 AMF 而放弃了 SOAP 与 Flash 播放器通信呢  有如下原因:
SOAP 将数据处理成 XML 格式,相对于二进制的 AFM 太冗长了; 
AMF 能更有效序列化数据;因为 AMF 的初衷只是为了支持 Flash ActionScript 的数据类型,而 SOAP 却致力于提供更广泛的用途; 
AMF 支持 Flash 播放器 6 只需要浏览器增加 4 KB 左右(压缩后)的大小,而 SOAP 就大多了; 

SOAP 的一些头部文件请求在 Flash 播放器 6 不支持。那 Flash 播放器 6 为什么能访问基于 SOAP 的 Web 服务呢?原来 Flash Remoting 网关将 SOAP 请求在服务器端与转换成 AFM 格式,然后利用 AFM 与 Flash 播放器通信。

另外, AMF 包中包含 onResult 事件(比如说 response 事件)和 onStatus 事件(比如说 error 事件),这些事件对象在 Flash 中可以直接使用。 
AMF 从 Flash MX 时代的 AMF0 发展到现在的 AMF3 。 AMF3 用作 Flash Playe 9 的 ActionScript 3.0 的默认序列化格式,而 AMF0 则用作旧版的 ActionScript 1.0 和 2.0 的序列化格式。 在网络传输数据方面, AMF3 比 AMF0 更有效率。 AMF3 能将 int 和 uint 对象作为整数( integer )传输,并且能序列化 ActionScript 3.0 才支持的数据类型 , 比如 ByteArray , XML 和 Iexternalizable 。

AMF 很好的解决了内容的丰富性。(具体 AMF 格式参考附件格式文档)

3.3.1 AMF中的数据类型Data Types

AMF0 supports the following data types (with their type field values):

NUMBER = 0x00
BOOLEAN = 0x01
STRING = 0x02
OBJECT = 0x03
MOVIECLIP = 0x04
NULL_VALUE = 0x05
UNDEFINED = 0x06
REFERENCE = 0x07
ECMA_ARRAY = 0x08
OBJECT_END = 0x09
STRICT_ARRAY = 0x0a
DATE = 0x0b
LONG_STRING = 0x0c
UNSUPPORTED = 0x0d
RECORD_SET = 0x0e
XML_OBJECT = 0x0f
TYPED_OBJECT = 0x10

Binary Format
AMF format for a value/object consists of a type byte (see above) followed by zero or more bytes. This section describes the bytes following the type byte for various types.

NUMBER (type byte: 0x00)
Numbers are stored as 8 byte (big endian) float double. On x86 you can just byteswap a double to encode it correctly.

BOOLEAN (type byte: 0x01)
A boolean is encoded in one byte. FIXME: is true sent as 0xff? 0x01?

STRING (type byte: 0x02)
A string is encoded as a 2 byte (big endian) count (number of bytes) followed by that many bytes of text. Note: there is no null terminator.

I think the text is assumed to be UTF-8. Can someone double check me on this?

NULL_VALUE (type byte: 0x05)
A null has zero bytes following the type byte

UNDEFINED (type byte: 0x06)
A undefined has zero bytes following the type byte

OBJECT (type byte: 0x08)
An object is encoded as a series of key/value pairs. The key is encoded as a STRING (above) WITH NO TYPE BYTE, and the value is any AMF value.

The object encoding is terminated by 0x000009 (that is a zero length string key, followed by the OBJECT_END type byte described below.

OBJECT_END (type byte: 0x09)
This is not really a value, but a marker for the end of an OBJECT. See above.

STRICT_ARRAY (type byte: 0x0a)
This is the encoding for arrays such as ["foo", "bar", 1, 2, 3]. For a hash (a set of key/value pairs) you’ll need to use OBJECT above.

An array is encoded as 4 byte (big endian) integer which is the number of elements in the array, followed by that many AMF values.

That’s it. There’s no terminator of any kind.

Use in shared object files
While most AMF objects are just a value, there is a special variation used by shared object files for properties. Rather than start with the type field, followed by the length, it starts with a byte count, then the name, and then the regular AMF type field, the length, and then the data.

3.4 客户端和服务器的连接过程

3.4.1客户和服务器的握手

   Flash Player 以系统时间作为种子通过某种算法生成的数字签名,大小是 1537 字节向服务器发起第一次握手,服务器根据客户端的数字签名产生一个 3073 字节的验证包,给客户端,客户端在接受到服务器的回应以后会发送一个 1536 字节的回复。

具体的流程:

发送第一次握手包 handshark1
接收第二次握手包 handshark2
发送的三次握手包 handshark3
第一个握手包 handshark1 和服务器的回复握手包 handshark2 都是以 0X03 开头。这三次握手不是 RTMP 协议本身的内容,所以在这并没有包含 RTMP  的协议头。是服务器的厂家自己产品做验证用的,严格的说就是你必须用  Adobe 的客户端和服务器才能使用我的协议。

3.4.2客户和服务器通信
   具体连接和请求视频的过程

发送 rtmp_connect 命令
发送本地带宽消息 . 默认是 125000
服务器返回服务器带宽信息
服务器返回本地带宽信息
服务器返回连接成功消息 "NetConnection.Connect.Success"
客户端发送创建流请求 encodeCreateStreamPacket
服务器返回创建流成功消息
客户端发送播放文件消息 Rtmp_Play
服务器返回 TYPE_CHUNK_SIZE 消息
服务器返回开始播放消息 "NetStream.Play.Start"
服务器返回视频信息 (TYPE_STREAM_METADATA) ,包括大小,宽高,速率等等信息--文件长度可以在这里推算出来
RTMP 的净核决定了内容服务, adobe 的服务器采用的 AMF 格式的字串命令来控制视频的传输和播放,具体的字串命令信息如下:

(注:字串的定义有厂家( adobe )自己定义,只要满足 AMF 的格式就可以) 
NetConnection.Call.Failed
NetConnection.Call.BadVersion 
NetConnection.Connect.AppShutdown
NetConnection.Connect.Closed
NetConnection.Connect.Rejected
NetConnection.Connect.Success
NetStream.Clear.Success
NetStream.Clear.Failed
NetStream.Publish.Start
NetStream.Publish.BadName
NetStream.Failed
NetStream.Unpublish.Success
NetStream.Record.Start
NetStream.Record.NoAccess
NetStream.Record.Stop
NetStream.Record.Failed
NetStream.Play.InsufficientBW
NetStream.Play.Start
NetStream.Play.StreamNotFound
NetStream.Play.Stop
NetStream.Play.Failed
NetStream.Play.Reset
NetStream.Play.PublishNotify
NetStream.Play.UnpublishNotify
NetStream.Data.Start
Application.Script.Error
Application.Script.Warning
Application.Resource.LowMemory
Application.Shutdown
Application.GC
Play
Pause
demoService.getListOfAvailableFLVs
getStreamLength
connect
app
flashVer
swfUrl
tcUrl
fpad
capabilities
audioCodecs
audioCodecs
videoCodecs
videoFunction
pageUrl
createStream
deleteStream
duration
framerate
audiocodecid
audiodatarate
videocodecid
videodatarate
height
width

3.4.2数据的萃取
      在服务器返回开始播放消息 "NetStream.Play.Start" 之后,服务器就会开始给客户端传输数据了,一般数据的萃取都是先解析协议的头,然后根据协议头中数据类型和净核长度就可以把数据部分取出, RTMP 协议也是这样。

struct RTMP_HEAD

{

      char cChannelid : 6;// 第一个字节的后 6 位

      char cCheadsize ; // 第一个字节的头两位

      char cTimer[3];  // 三个字节表示的时间信息

      char cLength[3]; // 三个字节表示的长度

      char cDatatype; // 数据类型

      char sStreamid[4]; // 流标识

}

      首先判断 cDatatype 是那种类型,然后根据不同的类型进行萃取数据部分,进行不同的处理,获取视频的数据的方式先看是否是一下的类型:

0×08  Audio Data  packet containing audio 
0×09  Video Data  packet containing video data 

根据净核的长度读取出内存中的音视频数据,这里的音视频数据是有一定编码格式的数据,这个取决于应用的具体配置, Flash play 使用的是 FLV 的格式。要对这部分数据进行存取,还有做一部分工作,对 FLV 的视频数据进行去壳,取出数据保存文件就可以了。

————————————————————————————

以下是百度百科上转载过来的,方便与上文对照理解:

rtmp

Real Time Messaging Protocol(实时消息传送协议协议)概述

实时消息传送协议是Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的私有协议。它有三种变种:

1)工作在TCP之上的明文协议,使用端口1935;

2)RTMPT封装在HTTP请求之中,可穿越防火墙;

3)RTMPS类似RTMPT,但使用的是HTTPS连接;

介绍:

RTMP协议是被Flash用于对象,视频,音频的传输.该协议建立在TCP协议或者轮询HTTP协议之上.

RTMP协议就像一个用来装数据包的容器,这些数据可以是AMF格式的数据,也可以是FLV中的视/音频数据.

一个单一的连接可以通过不同的通道传输多路网络流.这些通道中的包都是按照固定大小的包传输的.

网络连接(Connection)

一个Actionscript连接并播放一个流的简单代码:

复制内容到剪贴板代码:

var videoInstance:Video = your_video_instance;

var nc:NetConnection = new NetConnection();

var connected:Boolean = nc.connect("rtmp:/localhost/myapp");

var ns:NetStream = new NetStream(nc);

videoInstance.attachVideo(ns);

ns.play("flvName");

默认端口为1935

握手

Client → Server :向服务器发出握手请求.这不属于协议包一部分,该握手请求第一个字节为(0×03),其后跟着1536个字节.经管看上去这部分的内容对于RTMP协议来说并不是至关重要的,但也不可随意对待.

Server → Client :服务器向客户端回应握手请求.这部分的数据仍然不属于RTMP协议的部分.该回应的其实字节仍然为(0x03),但是后边跟着个长度为1536个字节 (一共为3072 )的包块.第一个1536块看上去似乎可以是任意内容,甚至好像可以是Null都没有关系.第二个1536的代码块,是上一步客户端向服务器端发送的握手请求的内容.

Client→Server:把上一步服务器向客户端回应的第二块1536个字节的数据块.

至此客户端与服务器端的握手结束,下面将发送RTMP协议的包内容.

Client → Server :向服务器发送连接包.

Server → Client :服务器回应.

… …. 等等… …

RTMP 数据类型

0×01 Chunk Size changes the chunk size for packets

0×02 Unknown anyone know this one?

0×03 Bytes Read send every x bytes read by both sides

0×04 Ping ping is a stream control message, has subtypes

0×05 Server BW the servers downstream bw

0×06 Client BW the clients upstream bw

0×07 Unknown anyone know this one?

0×08 Audio Data packet containing audio

0×09 Video Data packet containing video data

0x0A – 0×11 Unknown anyone know?

0×12 Notify an invoke which does not expect a reply

0×13 Shared Object has subtypes

0×14 Invoke like remoting call, used for stream actions too.

Shared Object 数据类型

0×01 Connect

0×02 Disconnect

0×03 Set Attribute

0×04 Update Data

0×05 Update Attribute

0×06 Send Message

0×07 Status

0×08 Clear Data

0×09 Delete Data

0x0A Delete Attribute

0x0B

Initial Data

RTMP包结构

RTMP包 包含一个固定长度的包头和一个最长为128字节的包体.包头可以是下面4种长度的任意一种:12, 8, 4, or 1 byte(s).

第一个字节的前两个Bit很重要,它决定了包头的长度.它可以用掩码0xC0进行"与"计算.下面的表格罗列了可能的包头长度:Bits Header Length

00 12 bytes

01 8 bytes

10 4 bytes

11 1 byte

我们在这里讨论关RTMP包结构的问题并不是非常的详细.我们在以后有时间会讨论关于AMF的问题(敬请期待…:loveliness:),其实RTMP包结构就是使用了AMF格式.

关于流的操作我们需要进一步研究,在论坛中的http://www.openred5.com/bbs /viewthread.php?tid=175&extra=page%3D1这篇文章研究的还是不错的,大家可以参考.不过下面可以列一个关于客户端向服务器端发送流的流程:

Client→Server :发送一个创建流的请求.

Server→Client :返回一个表示流的索引号.

Client→Server :开始发送.

Client→Server :发送视音频数据包(这些包在同一个频道(channel)并用流的索引号来唯一标识).

IT技术 ,

windows下编译librtmp、rtmpdump(转载)

2012年2月22日
windows下编译librtmp、rtmpdump(转载)已关闭评论

原文网站:http://zhaostudy2.blog.163.com/blog/static/1353502052011182538414/

    这段时间做实时视频的网页直播遇到了很多困难。

    开始时,迫于项目时间的压力,觉得没有足够的时间学习和分析如何将实时视频发送到RTMP流媒体服务器作为实时流,只好使用最粗糙的做法是:先把获取到的实时视频以RTP包的形式 发送给本机,然后本机程序中调用ffmpeg将接收到的RTP包 以RTMP的形式转发到Red5,最后,从网页上获取播放列表,播放实时视频。

    这种做法中存在很多问题:(1)多了一层rtp包到rtmp服务器的转发,浪费很多处理器的时间。(2)多了一层转发,系统稳定性很有问题。在视频流转发了一定时间后,ffmpeg会奇怪地停止转发,原因不明。(3)ffmpeg的视频流播放控制难以实现。在网页上停止播放和继续播放视频时,既要控制发送 RTP包,又要控制RTMP包,很麻烦。

    后来,分析了一下ffmpeg的源代码,发现FFmpeg中对RTMP的支持部分就是使用了RTMPDump中的librtmp。于是,我就打算直接使用librtmp与Red5建立rtmp连接,将实时视频直接发到Red5。

    最近过年,在家里闲着,就认真研究一下如何使用librtmp直接将实时视频发送到Red5。我们首先要做的就是编译出librtmp的动态库和静态库。

    RTMPDump项目官方网站在:http://rtmpdump.mplayerhq.hu/ 。对RTMP协议的实现在其中librtmp中。这是一个匈牙利人在2009年,Adobe公司还没有公开RTMP协议的情况下对RTMP协议的实现得。 官方网站中只提供了程序源代码和动态链接库(dll),要在开发中方便地使用RTMPDump,还需要自己编译它的静态库(lib)。

==> 编译librtmp静态库

    从官方网站http://rtmpdump.mplayerhq.hu/ 下载RTMPDump源代码。

    要编译librtmp,还需要另外3个库:zlib、OpenSSL、PolarSSL。

    zlib是用于数据压缩的函数库,数据压缩效果比较好,早在1995年就发布了第一版,目前仅支持LZ77变种算法、DEFLATE算法。(http://www.zlib.net/)。

    OpenSSL和PolarSSL 是对SSL(Security Socket Layer,加密套接字协议层)的实现。(http://www.openssl.org/ http://polarssl.org/)。

    (1)使用VC++6.0新建一个静态库工程,命名为librtmp,如下图所示:

[原创] 实时视频在网页直播--windows下编译librtmp、rtmpdump - 小小研究院 - 小小研究院

     (2)把RTMPDump源代码目录下的librtmp目录下的所有文件 复制到工程目录librtmp\下,并在VC++6.0中的Source Files和Header Files文件夹中添加librtmp相应的文件,如下图所示:

[原创] 实时视频在网页直播--windows下编译librtmp、rtmpdump - 小小研究院 - 小小研究院

     (3)下载zlib开发包 http://download.csdn.net/source/3013660。把其中的zdll.lib、zlib.def、zlib.h、zconf.h放到新建的工程目录librtmp\下。

     (4)下载openssl开发包 http://download.csdn.net/source/3013684。把其中的libeay32.lib、ssleay32.lib 及openssl文件夹 复制到工程目录librtmp\下,并在VC++6.0的“工具”->“选项”->“目录”-> “ Include files ”中添加当前的工程目录librtmp\。如下图所示:

[原创] 实时视频在网页直播--windows下编译librtmp、rtmpdump - 小小研究院 - 小小研究院

    (5) 下载PolarSSL源代码 http://download.csdn.net/source/3013696。解压出来,用VC++6.0打开\visualc\polarssl.dsw ,可以编译出静态库(polarssl.lib)。然后将头文件所在的文件夹polarssl\ 和polarssl.lib复制到工程目录librtmp\下。

    (6)编译静态库工程,这时会在多个文件中出现这样一个错误: error C2065: ‘__FUNCTION__’ : undeclared identifier 。解决办法是,在存在这个错误的.c文件的中添加一个宏定义:#define __FUNCTION__ "" 。问题就解决了。再编译工程即可得到librtmp.lib,如下图所示:

[原创] 实时视频在网页直播--windows下编译librtmp、rtmpdump - 小小研究院 - 小小研究院

[原创] 实时视频在网页直播--windows下编译librtmp、rtmpdump - 小小研究院 - 小小研究院

     (7)但是,这样编译出来的librtmp.lib在使用的时候会出现很多个外部符号未定义的错误。如下图所示:

[原创] 实时视频在网页直播--windows下编译librtmp、rtmpdump - 小小研究院 - 小小研究院

    这是librtmp的条件编译导致的问题,解决方法是:在rtmp_sys.h中把代码:

#ifdef _XBOX
#include <xtl.h>
#include <winsockx.h>
#define snprintf _snprintf
#define strcasecmp stricmp
#define strncasecmp strnicmp
#define vsnprintf _vsnprintf

#else /* !_XBOX */
#include <winsock2.h>
#include <ws2tcpip.h>
#endif

    改为

#include <winsock2.h>
#include <ws2tcpip.h>

#define snprintf _snprintf
#define strcasecmp stricmp
#define strncasecmp strnicmp
#define vsnprintf _vsnprintf

    然后,删除rtmp.c中的如下代码:

#ifdef _DEBUG
  fwrite(buf, 1, len, netstackdump);
#endif

#ifdef _DEBUG
extern FILE *netstackdump;
extern FILE *netstackdump_read;
#endif

#ifdef _DEBUG
      fwrite(ptr, 1, nBytes, netstackdump_read);
#endif

(8)编译rtmp.c即可得到librtmp.lib

    我已经将rtmpdump编译好的静态库、动态库以及源代码打成一个包,放到 http://download.csdn.net/source/3014336。如果不想自己编译,可以从这里下载,也可以直接下载下面的附件:http://dl.iteye.com/topics/download/3d9886b0-7e7a-3264-ba43-c23d207f719c

———————————-

林祥杰点评:

openssl和PolarSSL只需要用到一个,若不使用ssl都可以不添加,源代码里有宏CRYPTO可以关闭

IT技术 , ,

RTMP协议详解(转)

2012年2月22日
RTMP协议详解(转)已关闭评论

Real Time Messaging Protocol(实时消息传送协议协议)是Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的私有协议。

具体使用RTMP的AS代码大概如下:

var videoInstance:Video = your_video_instance;

var nc:NetConnection = new NetConnection();

var connected:Boolean = nc.connect("rtmp://localhost/myapp");

var ns:NetStream = new NetStream(nc);

videoInstance.attachVideo(ns);

ns.play("flvName");

Adobe也在官方网站已经提供了RTMP协议的官方文档说明,为什么要写这个系列文章最大的原因只是对前一段工作的一个总结和回顾,最近两个月,实现了一个RTMP Server的c++版本,把公司的流媒体服务和flash无缝对接起来。希望我的文字能给后来研究这个协议的同学有一定的帮助。

RTMP协议是一个基于TCP的高层协议族,当然这个玩意据说还有UDP协议版本的,不过现在还没有出来,好像Adobe下一版本的FMS会提供支持。下文将要描述的是TCP协议版本的协议。

RTMP协议的概要理解:

RTMP协议是为了和flash之间交换信令以及媒体数据。为了提高使用效率信令和媒体数据都是使用相同的机制。因为是相同的机制Adobe就整出来了一些比较搞人的概念,当然每个协议第一次接触都是比较难理解的。

在RTMP协议中信令和媒体数据都称之为Message,在网络中传输这些Message,为了区分它们肯定是要加一个Message head的,所以RTMP协议也有一个Message head,还有一个问题因为RTMP协议是基于TCP的,由于TCP的包长度是有限制的(一般来说不超过1500个字节),而RTMP的Message长度是有可能很大的,像一个视频帧的包可能会有几十甚至几千K,这个问题就必然有一个分片的问题,在RTMP协议中对应的说法就是chunk,每一个Message + head都是由一个和多个chunk组成的。到这里对RTMP协议的概要理解就算完了。

RTMP的字节序:
       RTMP的字节序和大多数网络协议一样是大端序,也有一些字段是小端序的,不过都有特殊的说明。
RTMP的head组成

         RTMP的head在协议中的表现形式是chunk head,前面已经说到一个Message + head可以分成一个和多个chunk,为了区分这些chunk,肯定是需要一个chunk head的,具体的实现就把Message head的信息和chunk head的信息合并在一起以chunk head的形式表现。

一个完整的chunk的组成如下图所示

Chunk basic header:

该字段包含chunk的stream ID和 type 。chunk的Type决定了消息头的编码方式。该字段的长度完全依赖于stream ID,该字段是一个可变长的字段。

Chunk Msg Header:0, 3 ,7, 11

该字段包含了将要发送的消息的信息(或者是一部分,一个消息拆成多个chunk的情况下是一部分)该字段的长度由chunk basic header中的type决定。

Extend Timestamp: 0 ,4 bytes

该字段发送的时候必须是正常的时间戳设置成0xffffff时,当正常时间戳不为0xffffff时,该字段不发送。当时间戳比0xffffff小该字段不发送,当时间戳比0xffffff大时该字段必须发送,且正常时间戳设置成0xffffff。

Chunk Data
        实际数据(Payload),可以是信令,也可以是媒体数据。
Chunk basic header:
   chunk basic head的长度为1~3个字节,具体长度主要是依赖chunk stream ID的长度,所谓chunk stream ID是flash server用来管理连接的客户端的信令交互的标识,在red5的文档中称之为channel ID,协议最大支持65597个streamID 从3~65599。ID 0,1,2为协议保留,0代表ID是64~319(第二个byte + 64);1代表chunk stream ID为64~65599((第三个byte)* 256 + 第二个byte + 64)(小端表示);2代表该消息为低层的协议(在RTMP协议中控制信令的chunk stream ID都是2)。3~63的chunk stream ID就是该byte的值。没有附加的字段来标识chunk stream streamID。在这里要指出的是虽然RTMP的chunk stream ID理论是可以达到65599,但是目前使用的chunk stream ID很少,2~7都是约定的,8是用来传输publish play等命令,其他的chunk stream ID目前好像没有使用,至少我不知道用来干嘛的。
      所以目前chunk basic head的长度一般为1个字节。这一个字节由两部分组成
                           +++++++++++++++++++
                            +fmt    + cs id               +
                            +++++++++++++++++++
      fmt占两个bit用来标识紧跟其后的chunk Msg Header的长度,cs id占六个bit。
      两位的fmt取值为 0~3,分别代表的意义如下:
      case 0:chunk Msg Header长度为11;
      case 1:chunk Msg Header长度为7;
      case 2:chunk Msg Header长度为3;
      case 3:chunk Msg Header长度为0;
      所以 只有一个字节的chunk basic header取值为 chunk basic header = (fmt << 6) | (cs id).

Chunk Msg Header:

Chunk Msg Header的长度是可变的,Chunk Msg Header可变的原因是为了压缩传输的字节数,把一些相同类型的chunk的head去掉一些字节,换句话说就是四种类型的包头都可以通过一定的规则还原成11个字节,这个压缩和还原在RTMP协议中称之为复用/解复用。

那我们以11个字节的完整包头来解释Chunk Msg Header,如图所示

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

+ timestamp + message length + message type id + message stream id +

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Timestamp:3bytes

对于type 0的chunk,绝对时间戳在这里表示,如果时间戳值大于等于0xffffff(16777215),该值必须是0xffffff,且时间戳扩展字段必须发送,其他情况没有要求。

message length:3bytes

Message的长度,注意这里的长度并不是跟随chunk head其后的chunk data(Payload)的长度,而是前文提到的一条信令或者一帧视频数据或音频数据的长度。前文提到过信令或者媒体数据都称之为Message,一条 Message可以分为一条或者多条chunk。

message type id:1byte

Message的类型ID,具体的值将在后文专门来讨论。

message stream id:4bytes

message stream id的字节序是小端序,这个字段是为了解复用而设计的,RTMP文档上说的相当的模糊,

message stream ID可以使任意值,不同的消息流复用成相同的chunk stream,基于它们的ID能够解复用。于chunk stream 是相关的,这个字段是一个不透明的值没有整明白什么意思,我的理解就是用来标识和服务器连接的flash端的序号。

长度是7 bytes 的chunk head,该类型不包含stream ID,该chunk的streamID和前一个chunk的stream ID是相同的,变长的消息,例如视频流格式,在第一个新的chunk以后使用这种类型,注意其中时间戳部分是相对时间,为何上一个绝对时间之间的差值 如图所示:

++++++++++++++++++++++++++++++++++++++++++++++++++++++

+ timestamp    delta + message length + message type id +

++++++++++++++++++++++++++++++++++++++++++++++++++++++

        3 bytes的chunk head,该类型既不包含stream ID 也不包含消息长度,这种类型用于stream ID和前一个chunk相同,且有固定长度的信息,例如音频流格式,在第一个新的chunk以后使用该类型。如图所示:

                           ++++++++++++++++++++

                           + timestamp    delta +

                           ++++++++++++++++++++

        0 bytes的chunk head,这种类型的chunk从前一个chunk得到值信息,当一个单个消息拆成多个chunk时,这些chunk除了第一个以外,其他的都应该使用这种类型,

chunk的长度:

chunk的长度初始长度固定为 128个字节,但是这个值并不是不可变的,在客户端和服务端建立连接以后,客户端和服务端都可以通过发送信令的方式来通知对端修改chunk的长度,理论上来说可以修改chunk的最长长度为65536。这里chunk的长度是指chunk的数据部分的长度,即chunk data(payload)的长度,如果一条Message的数据长度超过了chunk的长度,就必须把Message分割成多条chunk,即如果一条视频类型Message长度为2000个byte,chunk长度为1500,则该Message将会分割成两条chunk,第一条的chunk data长度为1500,第二条的chunk data长度为500。当然这两条chunk的chunk head肯定是不同的,其中第二条chunk的chunk head就是0字节的。

转自《RTMP协议详解(一) (二) (三)

IT技术 , , ,

差分与单端(转载)

2012年2月21日
差分与单端(转载)已关闭评论

一、基本区别

不说理论上的定义,说实际的

单端信号指的是用一个线传输的信号,一根线没参考点怎么会有信号呢?

easy,参考点就是地啊。也就是说,单端信号是在一跟导线上传输的与地之间的电平差

那么当你把信号从A点传递到B点的时候,有一个前提就是A点和B点的地电势应该

差不多是一样的,为啥说差不多呢,后面再详细说。

差分信号指的是用两根线传输的信号,传输的是两根信号之间的电平差。

当你把信号从A点传递到B点的时候,A点和B点的地电势可以一样也可以不一样

但是A点和B点的地电势差有一个范围,超过这个范围就会出问题了。

二、传输上的差别

单端信号的优点是,省钱~方便~

大部分的低频电平信号都是使用单端信号进行传输的。一个信号一根线,最后

把两边的地用一根线一连,完事。

缺点在不同应用领域暴露的不一样

归结起来,最主要的一个方面就是,抗干扰能力差。

首先说最大的一个问题,地电势差以及地一致性。

大家都认为地是0V,实际上,真正的应用中地是千奇百怪变化莫测的一个东西

我想我会专门写一些地方面的趣事。

比如A点到B点之间,有那么一根线,用来连接两个系统之间的地

那么如果这根线上的电流很大时,两点间的地电势可能就不可忽略了,这样一个信号

从A的角度看起来是1V,从B的角度看起来可能只有0.8V了,这可不是一个什么好事情

这就是地电势差对单端信号的影响。

接着说地一致性。实际上很多时候这个地上由于电流忽大忽小,布局结构远远近近

地上会产生一定的电压波动,这也会影响单端信号的质量。

差分信号在这一点有优势,由于两个信号都是相对于地的

当地电势发生变化时,两个信号同时上下浮动(当然是理想状态下)

差分两根线之间的电压差却很少发生变化,这样信号质量不久高了吗?

其次就是传输过程中的干扰,当一根导线穿过某个线圈时,且这根线圈上通着交流电

时,这根导线上会产生感应电动势~~好简单的道理,实际上工业现场遇到的大部分

问题就是这么简单,可是你无法抗拒~

如果是单端信号,产生多少,就是多少,这就是噪声你毫无办法。

但是如果是差分信号,你就可以考虑拉,为啥呢,两根导线是平行传输的

每根导线上产生的感应电动势不是一样吗,两个一减,他不久没了吗~

确实,同样的情况下,传输距离较长时,差分信号具有更强的驱动能力、更强的

抗干扰能力,同样的,当你传输的信号会对其他设备有干扰时,差分信号也比

单端信号产生的信号相对小,也就是常说的EMI特性(存疑,是这么说把?)

三、使用时需要注意di

由于差分比单端有不少好处,在模拟信号传输中很多人愿意使用差分信号

比如桥式应变片式力传感器,其输出信号满量程时有的也只有2mV

如果使用单端信号传输,那么这个信号只要电源的纹波就能把他吃光。

所以实际上,都是用仪表运方进行放大后,再进行处理。

而仪表运方正是处理差分信号最有力的几个工具之一。

但是,使用差分信号时,一定要注意一个问题,共模电压范围。

也就是说,这两根线上的电压,相对于系统的地,还是不能太大。

你传输0.1V的信号没问题,但是如果一根是 1000.0 另外一根是 1000.1,那就不好玩了

问题在于,在很多场合下使用差分信号都是为了不让两个系统的地简单的共在一起

更不能把差分信号中的一根直接接在本地系统的地上,那不白费尽吗–又成单端了

那么如何抑制共模电压呢?

其实也挺简单的,将两根线都通过一个足够大的电阻,连接到系统的地上。

这就像一根拴在风筝上的线,我在地上跑跑跳跳,不会影响风筝的高度

但是你永远逃不出我的视线,而我的视线,在电子行业,叫共模电压范围~~嘿嘿

最后,回答板上一个网友的问题

单端转差分怎么转。

单单将单端信号用反向跟随器跟随并不是不行

但是差分信号被平白的放大了2倍~~

常见的用仪表运方+普通运方搭建的单端转差分是个很好的例子。

另外有一篇也是说明单端与差分输入的差别,摘录了一段,供参考。

差分信号和普通的单端信号走线相比,最明显的优势体现在以下三个方面:

a.抗干扰能力强,因为两根差分走线之间的耦合很好,当外界存在噪声干扰时,几乎是同时被耦合到两条线上,而接收端关心的只是两信号的差值,所以外界的共模噪声可以被完全抵消。

b.能有效抑制EMI,同样的道理,由于两根信号的极性相反,他们对外辐射的电磁场可以相互抵消,耦合的越紧密,泄放到外界的电磁能量越少。

c.时序定位精确,由于差分信号的开关变化是位于两个信号的交点,而不像普通单端信号依靠高低两个阈值电压判断,因而受工艺,温度的影响小,能降低时序上的误差,同时也更适合于低幅度信号的电路。目前流行的LVDS(low voltage differential signaling)就是指这种小振幅差分信号技术。

IT技术 , ,

数字逻辑标准及接口技术

2012年2月21日
数字逻辑标准及接口技术已关闭评论

我们知道,0和1是数字世界的两个基本元素,在数字电路中它们由特定范围的高低电平来表示。数字电路发展的早期,绝大多数数字器件都采用TTL和CMOS数字逻辑标准。近几年,产生了许多针对不同应用的低压、高速的数字逻辑标准,例如LVTTL、LVCMOS、LVDS、HSTL、SSTL、LVPECL等。

实际应用中共有二三十种数字逻辑信号标准,根据其物理连接特性不同,可以划分为单端逻辑信号、单端差分逻辑信号和差分逻辑信号三大类。在对它们详细介绍之前,我们首先了解一下数字逻辑信号的几个重要专业术语。

     a. 门限电压(VTH ) 
–      -顾名思义,VTH为逻辑状态高或低转换的门限电压,在逻辑器件中,当信号电压高于VTH 为逻辑高,反之则为逻辑低,通常VTH为电源电压的1/2。 
—  b. 输出高电平(VOH)和输出低电平(VOL) 
—     确切地说VOH应该为逻辑器件输出高电平的下限,VOL为输出低电平的上限。通常在VOH和VOL之间有一个电压缓冲区,这样在实际电路中输出逻辑信号迭加噪声后,就不会导致对逻辑状态的错误判断。 
—  c. 输入高电平(VIH)和输入低电平(VIL) 
—     VIH为输入高电平的下限,VIL为输入低电平的上限。

在许多数字系统中,前一个逻辑器件的输出就是后一个逻辑器件的输入,所以必须满足VOH>VIH、VOL< VIL,否则就会出现逻辑状态判断错误。另外,它们之间的差值称为噪声容限,外部叠加的噪声应小于噪声容限,否则也会出现逻辑状态判断错误。

单端数字逻辑信号
—单端信号是两个逻辑器件互连最基本的方法,它只需要一条连线来实现逻辑信号传输。另外,它也可以实现单端发送、差分接收的连接方式,这时差分接收器的另外一个输入端提供参考接地电平,即图4中的VREF接地。-单端信号连接的数字逻辑标准主要有TTL、CMOS、LVTTL、LVCMOS、PCI等,它们的主要性能参数如表1所示。 
—(1) 注意:信号的传输带宽是一个粗略的估算值,因为器件工艺、连线长度、PCB走线方式和应用环境都会对实际传输带宽造成影响。

单端差分逻辑信号
—单端差分信号指的是信号单端发送、差分接收的一种信号传输方式。差分接收器的两个输入端,一个接收信号,另一个提供参考电平VREF。VREF是用来设置接收器的门限电压,其大小通常为单端驱动器输出电压VDDO的1/2。相对单端信号,单端差分信号是通过降低传输信号的电平幅度,来加快晶体管的转换速度,从而提高传输带宽。 
—图6为HSTL-I单端差分信号的实际参数和信号波形图,其中单端驱动器输出电压VDDO=1.5V;门限电压VTH = VREF=1/2 VDDO=0.75V;VIL= VREF – 0.1V 、VIH= VREF + 0.1V。 
—除了HSTL-I单端差分逻辑标准外,另外一个常见的标准是美国Cypress的1.8V HSTL,也称eHSTL,其性能参数如表2所示。

差分逻辑信号
—如图7所示,差分信号是通过一对单端信号线进行传输,两条线上的信号相同,但相位相差为180°。 
—从信号传输原理看,差分信号的电平幅度比单端差分信号更低;此外,如图8,差分信号接收端VDIFF=VOH-VOL,这样可以抵消实际传输过程中迭加在两个单端信号上的共模噪声,更好地保持了信号的完整性,降低了信号整体噪声, 从而实现更高的带宽。 
—常见的差分逻辑信号标准有LVDS、SSTL、ECL、PECL等,它们的具体性能参数如表3所示。

Table3

应用
—可以说,任何一种新的数字逻辑信号标准的产生,都是实际应用需要驱动的结果,每一种标准都有各自的特点及应用环境。 
—a. TTL、CMOS系列是应用最广泛的数字逻辑标准,被数字逻辑器件厂商普遍采用; 
—b. 时钟驱动器件、SRAM、DDR SRAM 等存储器件基本都采用HSTL标准; 
—d. SSTL系列是由IBM、Hitachi等公司发起的,主要用于PC内存模快上; 
—e. PECL系列是Motorola 公司发明的,广泛应用于精度较高的时钟器件; 
—f. LVDS广泛应用于中距离传输的一些高速串行或平行接口器件。

接口技术
—在数字系统的设计和调试中,会经常遇到不同数字逻辑标准的接口问题。只要深入理解各种逻辑标准的接口电平特性;遵循VOH>VIH 、 VOL< VIL,实际噪声小于容限噪声等原则;同时注意一些影响信号完整性的参数,例如驱动电流、匹配阻抗、转换速率等,许多问题都能迎刃而解。 
—另外,也可以选用专用逻辑电平转换器件、接口转换器件、可编程逻辑器件来解决数字逻辑标准的接口问题,提高传输的稳定性。例如,IDT、TI公司都推出了多款逻辑电平转换和接口转换器件;Xilinx公司的 CoolRunnerII系列CPLD可以支持LVTTL、LVCOMS、SSTL2-I、HSTL-I等多种接口标准,Spartan-3系列FPGA 支持的标准多达23种。

TTL:Transistor-Transistor Logic 三极管结构。

Vcc:5V
输出 VOL: <0.8V ; VOH:>2.4V。 
输入 VIL:   <1.2V ; VIH: >2.0V 
TTL器件输出低电平要小于0.8V,高电平要大于2.4V。输入,低于1.2V就认为是0,高于2.0就认为是1。

因为2.4V与5V之间还有很大空闲,对改善噪声容限并没什么好处,又会白白增大系统功耗,还会影响速度。所以后来就把一部分“砍”掉了。也就是后面的LVTTL。
LVTTL又分3.3V、2.5V以及更低电压的LVTTL(Low Voltage TTL)。

3.3V LVTTL:
Vcc:3.3V;VOH>=2.4V;VOL<=0.4V;VIH>=2V;VIL<=0.8V。
2.5V LVTTL:
Vcc:2.5V;VOH>=2.0V;VOL<=0.2V;VIH>=1.7V;VIL<=0.7V。

TTL使用注意:TTL电平一般过冲都会比较严重,可能在始端串22欧或33欧电阻;TTL电平输入脚悬空时是内部认为是高电平。要下拉的话应用1k以下电阻下拉。TTL输出不能驱动CMOS输入。

CMOS电平:Complementary Metal Oxide Semiconductor  PMOS+NMOS。

Vcc:5V
输出 VOL: <0.1*Vcc ; VOH:>0.9*Vcc。 
输入 VIL:  <0.3*Vcc ; VIH: >0.7*Vcc.

CMOS电平Vcc可达到12V 
CMOS电路输出高电平约为0.9Vcc,而输出低电平约为 0.1Vcc。

相对TTL有了更大的噪声容限,输入阻抗远大于TTL输入阻抗。对应3.3V LVTTL,出现了LVCMOS,可以与3.3V的LVTTL直接相互驱动。

3.3V LVCMOS:
Vcc:3.3V;VOH>=3.2V;VOL<=0.1V;VIH>=2.0V;VIL<=0.7V。
2.5V LVCMOS:
Vcc:2.5V;VOH>=2V;VOL<=0.1V;VIH>=1.7V;VIL<=0.7V。
CMOS使用注意:CMOS结构内部寄生有可控硅结构,当输入或输入管脚高于VCC一定值(比如一些芯片是0.7V)时,电流足够大的话,可能引起闩锁效应,导致芯片的烧毁。
CMOS电路不使用的输入端不能悬空,会造成逻辑混乱,不用的输入端必须连到高电平或低电平, 这是因为 CMOS 是高输入阻抗器件, 理想状态是没有输入电流的. 如果不用的输入引脚悬空, 很容易感应到干扰信号, 影响芯片的逻辑运行, 甚至静电积累永久性的击穿这个输入端, 造成芯片失效. 
另外,CMOS集成电路电源电压Vcc可以在较大范围内变化,因而对电源的要求不像TTL集成电路那样严格。 
用TTL电平他们就可以兼容。

TTL和CMOS区别:

1.电平的上限和下限定义不一样,CMOS具有更大的抗噪区域。同是5伏供电的话,ttl一般是1.7V和3.5V的样子,CMOS一般是2.2V,2.9V的样子,不准确,仅供参考。

2。电流驱动能力不一样,ttl一般提供25毫安的驱动能力,而CMOS一般在10毫安左右。
3。需要的电流输入大小也不一样,一般ttl需要2.5毫安左右,CMOS 几乎不需要电流输入。 
4。TTL电路是电流控制器件,而coms电路是电压控制器件。 
5。TTL电路的速度快,传输延迟时间短(5-10ns),但是功耗大。COMS电路的速度慢,传输延迟时间长(25-50ns),但功耗低。COMS电路本身的功耗与输入信号的脉冲频率有关,频率越高,芯片集越热,这是正常现象。
COMS电路的锁定效应:
COMS电路由于输入太大的电流,内部的电流急剧增大,除非切断电源,电流一直在增大。这种效应就是锁定效应。当产生锁定效应时,COMS的内部电流能达到40mA以上,很容易烧毁芯片。 
防御措施: 1)在输入端和输出端加钳位电路,使输入和输出不超过不超过规定电压。 
2)芯片的电源输入端加去耦电路,防止VDD端出现瞬间的高压。 
3)在VDD和外电源之间加线流电阻,即使有大的电流也不让它进去。 
4)当系统由几个电源分别供电时,开关要按下列顺序:开启时,先开启COMS电路得电源,再开启输入信号和负载的电源;关闭时,先关闭输入信号和负载的电源,再关闭COMS电路的电源。

COMS电路的使用注意事项 
1)COMS电路时电压控制器件,它的输入总抗很大,对干扰信号的捕捉能力很强。所以,不用的管脚不要悬空,要接上拉电阻或者下拉电阻,给它一个恒定的电平。 
2)输入端接低内组的信号源时,要在输入端和信号源之间要串联限流电阻,使输入的电流限制在1mA之内。 
3)当接长信号传输线时,在COMS电路端接匹配电阻。 
4)当输入端接大电容时,应该在输入端和电容间接保护电阻。电阻值为R=V0/1mA.V0是外界电容上的电压。 
5)COMS的输入电流超过1mA,就有可能烧坏COMS。 
TTL门电路中输入端负载特性(输入端带电阻特殊情况的处理): 
1)悬空时相当于输入端接高电平。因为这时可以看作是输入端接一个无穷大的电阻。 
2)在门电路输入端串联10K电阻后再输入低电平,输入端出呈现的是高电平而不是低电平。因为由TTL门电路的输入端负载特性可知,只有在输入端接的串联电阻小于910欧时,它输入来的低电平信号才能被门电路识别出来,串联电阻再大的话输入端就一直呈现高电平。这个一定要注意。COMS门电路就不用考虑这些了。 
TTL电路有集电极开路OC门,MOS管也有和集电极对应的漏极开路的OD门,它的输出就叫做开漏输出。OC门在截止时有漏电流输出,那就是漏电流,为什么有漏电流呢?那是因为当三机管截止的时候,它的基极电流约等于0,但是并不是真正的为0,经过三极管的集电极的电流也就不是真正的 0,而是约0。而这个就是漏电流。开漏输出:OC门的输出就是开漏输出;OD门的输出也是开漏输出。它可以吸收很大的电流,但是不能向外输出的电流。所以,为了能输入和输出电流,它使用的时候要跟电源和上拉电阻一齐用。OD门一般作为输出缓冲/驱动器、电平转换器以及满足吸收大负载电流的需要。 
TTL集成电路中,输出有接上拉三极管的输出叫做图腾柱输出,没有的叫做OC门。因为TTL就是一个三级关,图腾柱也就是两个三级管推挽相连。所以推挽就是图腾。一般图腾式输出,高电平400UA,低电平8MA

3.3V和5.0V电平信号的转换
在混合电压系统中,不同电源电压的逻辑器件互相接口时存在以下几个问题:

第一,加到输入和输出引脚上允许的最大电压限制问题。器件对加到输入或者输出脚上的电压通常是有限制的。这些引脚有二极管或者分离元件接到Vcc。如果接入的电压过高,则电流将会通过二极管或者分离元件流向电源。例如在3.3V器件的输入端加上5V的信号,则5V电源会向3.3V电源充电。持续的电流将会损坏二极管和其它电路元件。

第二,两个电源间电流的互串问题。在等待或者掉电方式时,3.3V电源降落到0V,大电流将流通到地,这使得总线上的高电压被下拉到地,这些情况将引起数据丢失和元件损坏。必须注意的是:不管在3.3V的工作状态还是在0V的等待状态都不允许电流流向Vcc。

第三,接口输入转换门限问题。5V器件和3.3V器件的接口有很多情况,同样TTL和CMOS间的电平转换也存在着不同情况。驱动器必须满足接收器的输入转换电平,并且要有足够的容限以保证不损坏电路元件。

      基于上述情况,5V器件和3.3V器件是不能直接接口的。有些半导体器件制造厂家就推出了具有5V输入容限的3.3V器件,这种器件输入端具有ESD保护电路。实际上数字电路的所有输入端都有一个ESD保护电路,传统的CMOS电路通过接地二极管对负向高电压限幅,正向高电压则由二极管钳位。这种电路的缺点是最大的输入电压被限制在3.3V+0.5V(二极管压降)以内(否则电流将流向3.3V电源)。而大多数5V系统输出端的电压可达3.6V以上,因此采用了这种电路结构的3.3V器件是不能与5V器件输出端直接接口的。如果采用相当于快速齐纳二极管的MOS场效应管代替上述钳位二极管,实现对高电压限幅,并且去掉接到Vcc(3.3V)的二极管,那么最大输入电压不受Vcc(3.3V)的限制。典型情况下,这种电路的击穿电压在7V~10V之间。因此,这种改进后具有ESD保护电路的3.3V系统的输入端可以承受5V的输入电压。为了防止在3.3V器件的输出端可能存在电流倒灌问题,还需要在输出端加保护电路,当加到输出端电压高于Vcc(3.3V)时,保护电路的比较器会断开电流倒灌通路,这样在三态方式时就能与5V器件相连。
按此在新窗口浏览图片
    分析各种逻辑电平信号的电特性,会发现有以下五种接口情况:
第一,相同供电电压的TTL器件驱动CMOS器件时,TTL器件的输出高电平可能达不到CMOS器件的输入高电平的最小值。3.3V TTL器件的VOH是2.4V,3.3V CMOS器件的VIH是0.8VCC(3.3V×0.8=2.64V);5.0V TTL器件的VOH是2.4V,5.0V CMOS器件的VIH是0.7VCC(3.5V)。为了可靠地传输数据,可以将TTL器件的输出端上拉。有些CMOS工艺制造的器件兼容 TTL电平,这样就可以与相同供电电压的TTL器件直接接口,不需要上拉。

第二,相同供电电压的CMOS器件驱动TTL器件,电平匹配,数据能可靠地传输。

第三,不同供电电压的TTL器件驱动CMOS器件时,TTL器件的输出高电平也可能达不到CMOS器件的输入高电平的最小值。3.3V TTL器件的VOH是2.4V,5.0V CMOS器件的VIH是0.7VCC(3.5V),电平不匹配;5.0V TTL器件的VOH是2.4V,3.3V CMOS器件的VIH是0.8VCC(2.64V),可以将5.0V TTL器件的输出端上拉,达到电平匹配的目的。

第四,不同供电电压的CMOS器件驱动TTL器件时,在输入端具有5V容限的情况下,电平匹配,数据能可靠地传输。

第五,不同供电电压的TTL器件在输入端具有5V容限的情况下可以直接接口;不同供电电压的CMOS器件由于电平不匹配不能直接接口。

      由以上分析可知,不同逻辑标准的电平信号一般是不能直接接口的。在只有少量信号需要电平转换的情况下,可以考虑上拉电阻或选择具有5V输入容限的器件,甚至可以考虑电阻分压降低输入电压的办法。对于大量信号需要电平转换的情况,为了可靠传输数据,可以采用双电压(一边是3.3V,另一边是5V)供电的双向驱动器来实现电平转换。如仙童半导体公司的74LVX4245、TI公司的SN74ALVC164245、SN74ALVC4245
等芯片,可以较好地解决3.3V与5V电平的转换问题。

ECL:Emitter Coupled Logic 发射极耦合逻辑电路(差分结构)
Vcc=0V;Vee:-5.2V;VOH=-0.88V;VOL=-1.72V;VIH=-1.24V;VIL=-1.36V。
速度快,驱动能力强,噪声小,很容易达到几百M的应用。但是功耗大,需要负电源。为简化电源,出现了PECL(ECL结构,改用正电压供电)和LVPECL。
PECL:Pseudo/Positive ECL
Vcc=5V;VOH=4.12V;VOL=3.28V;VIH=3.78V;VIL=3.64V
LVPELC:Low Voltage PECL
Vcc=3.3V;VOH=2.42V;VOL=1.58V;VIH=2.06V;VIL=1.94V
ECL、 PECL、LVPECL使用注意:不同电平不能直接驱动。中间可用交流耦合、电阻网络或专用芯片进行转换。以上三种均为射随输出结构,必须有电阻拉到一个直流偏置电压。(如多用于时钟的LVPECL:直流匹配时用130欧上拉,同时用82欧下拉;交流匹配时用82欧上拉,同时用130欧下拉。但两种方式工作后直流电平都在1.95V左右。)
前面的电平标准摆幅都比较大,为降低电磁辐射,同时提高开关速度又推出LVDS电平标准。
LVDS:Low Voltage Differential Signaling 
差分对输入输出,内部有一个恒流源3.5-4mA,在差分线上改变方向来表示0和1。通过外部的100欧匹配电阻(并在差分线上靠近接收端)转换为±350mV的差分电平。
LVDS使用注意:可以达到600M以上,PCB要求较高,差分线要求严格等长,差最好不超过10mil(0.25mm)。100欧电阻离接收端距离不能超过500mil,最好控制在300mil以内。
下面的电平用的可能不是很多,篇幅关系,只简单做一下介绍。如果感兴趣的话可以联系我。
CML:是内部做好匹配的一种电路,不需再进行匹配。三极管结构,也是差分线,速度能达到3G以上。只能点对点传输。
GTL:类似CMOS的一种结构,输入为比较器结构,比较器一端接参考电平,另一端接输入信号。1.2V电源供电。
Vcc=1.2V;VOH>=1.1V;VOL<=0.4V;VIH>=0.85V;VIL<=0.75V
PGTL/GTL+:
Vcc=1.5V;VOH>=1.4V;VOL<=0.46V;VIH>=1.2V;VIL<=0.8V
HSTL是主要用于QDR存储器的一种电平标准:一般有V&not;CCIO=1.8V和V&not;&not;CCIO= 1.5V。和上面的GTL相似,输入为输入为比较器结构,比较器一端接参考电平(VCCIO/2),另一端接输入信号。对参考电平要求比较高(1%精度)。
SSTL主要用于DDR存储器。和HSTL基本相同。V&not;&not;CCIO=2.5V,输入为输入为比较器结构,比较器一端接参考电平1.25V,另一端接输入信号。对参考电平要求比较高(1%精度)。
HSTL和SSTL大多用在300M以下。
RS232和RS485基本和大家比较熟了,只简单提一下:
RS232采用±12-15V供电,我们电脑后面的串口即为RS232标准。+12V表示0,-12V表示1。可以用MAX3232等专用芯片转换,也可以用两个三极管加一些外围电路进行反相和电压匹配。
RS485是一种差分结构,相对RS232有更高的抗干扰能力。传输距离可以达到上千米

IT技术 , , , , , , , ,

Cadence Allegro PCB Design 16.3破解安装

2012年2月14日
Cadence Allegro PCB Design 16.3破解安装已关闭评论

在高速数字电路设计中,Cadence Allegro无疑是最常用的工具之一,但是如果要买正版,费用不是你我等能够承受得起的。作为个人或者学校学习用,安装一个破解版也是可行的。

一、下载安装包。

从网上搜做关键字“Cadence OrCad v16.3 SHooTERS”找到下载的网站并下载,文件大小为1.7GB左右,比如我是从这里http://www.verycd.com/topics/2795352/下载的,我的带宽是6兆,下载了4个小时,下载后的文件名是:
[PCB设计].Cadence.OrCad.v16.3-SHooTERS.iso

二、破解安装。

主意:安装前先关闭防火墙和杀毒软件

1、安装虚拟光驱工具

把下载的ISO文件刻录到DVD光碟上,如果没有刻录机怎么办,那就从网上下载一个虚拟光驱软件Daemon Tools 3.47.0,比如我是从这里http://www.newhua.com/soft/3617.htm下载这个工具的,下载后的文件名daemon_tools_347cn.zip,双击它解压并安装,安装完后需要重启电脑。然后:

这样就在我的电脑里多了一个名叫Cadence的虚拟光盘。

2、开始安装。

进入我的电脑,双击Cadence光驱(我的虚拟光驱盘符是P)进入,再双击里面的setup.exe启动安装程序:

在上图中点击“License Manager”安装许可证管理工具,每一步都选择默认值即可,直到出现下面的画面:

这是点击取消(Cancel)按钮,然后出现下面的画面:

接下来点击Finish,完成License Manager的安装。

把安装光盘中的目录\SHooTERS\license_manager下的两个文件cdslmd.exe和orcad_163.lic拷贝到 License Manager的安装目录下(默认安装目录是C:\Cadence\LicenseManager)。拷贝时如果提示目标文件名已经存在,直接点击“是” (即覆盖)即可。

用记事本打开刚刚复制到LicenseManager目录中的orcad_163.lic文件,将第一行的“this_host”修改成自己的计算机名称(比如我的计算机名称是moodisk-home):

修改完后保存退出,然后把文件orcad_163.lic改名为license.lic。

主意:如果不知道自己电脑的计算机名称,那么进入命令窗口,输入命令hostname即可查看,如下图所示:

回到Cadence Allegro 安装界面,点击Product Installation,开始安装各种产品:

接下来的安装画面选择默认值即可,直到出现如下的安装画面,直接点击“Next”进入下一步:

本破解方法成功破解了所有的产品,所以到了选择安装什么产品的时候建议安装全部产品:

需要消耗磁盘空间3.47GB。什么?报磁盘空间不够,那我也救不了您了,反正我的电脑有两块500GB的硬盘,做成RAID 1,绰绰有余。

接下来的安装步骤没有什么特别的,一直Next下去,最后点击“Finish”按钮完成安装。

……等等。

下面开始破解了。不过先别急,尽管您在上面的安装结尾点击了“Finsh”,但是实际上安装程序还要花很长的时间在后台做设置,直到安装程序退出了,才可开始破解。

复制安装光盘上的目录\SHooTERS下的文件orcad_163.exe到Cadence Allegro产品的安装根目录下(默认安装根目录是c:\Candence),如果您改变了安装目录,那么久拷贝到那个目录(安装根目录下一定存在子目录SPB_16.3)。拷贝完了双击orcad_163.exe文件运行它:

主意:最后出现的那个黑白窗口会停留数秒钟,如果机器速度慢,可能要几十秒钟,如果一出现马上就消失了,很可能不是您的机器速度太快,而且破解失败!!

完成上一步后,按照下图启动许可证服务器配置程序:

弹出如下画面:

点击“Browse…”按钮定位许可证文件license.lic(位于LicenseManager安装目录下,我们在前面的步骤中已经拷贝到那里,默认目录是C:\Cadence\LicenseManager):

此后一路“Next”,最后点击“Finish”完成破解。

主意:在后续步骤中可能会出现错误:
Unable to start Cadence License Server with the new license file
或者报内存错误,不用理会,我验证了全部的产品都可用。

还有如果您点击HELP中版本信息时,看到的序列号仍然是UNLICENSED,不过不影响任何功能使用。

就这样了,没花钱,能用就不错了! ^_^

附录:

1、配套的学习视频建议看看与博士的(从www.sig007.com下载),不过版本是15.7,与16.3版本在界面上有一定的差别。
2、另外配套软件LPViewer是不可少的,这个工具是免费的,用来查阅ipc 7351国标元件尺寸,从这里http://www.mentor.com/products/pcb-system-design/library- tools/lp-wizard/lp-viewer-download可以下载这个工具。

IT技术 , , ,

纽扣电池型号对照表

2012年2月13日
纽扣电池型号对照表已关闭评论

纽扣电池的型号通常是在纽扣电池的背面由字母和阿拉伯数字组成。瑞士的氧化银纽扣电池型号为3##,日本的型号通常是SR###SW,或 SR###W(#代表一个阿拉伯数字)。纽扣锂电池的型号通常为CR####。不同材料的纽扣电池,其型号规格也就不同。

各地的标准型号列举如下:

香港 国际 瑞士 日本 其他 电压 直径Ф*厚度(mm) 用途
AG0 LR69 379 SR521   1.5V 5.8*2.1  
AG1 LR621 364 SR621 164 1.5V 6.8*2.1  
AG2 LR726 396 SR726 196 1.5V 7.9*2.6  
AG3 LR41 392 SR41 192 1.5V 7.9*3.6 迷你手电、体温计
AG4 LR626 377 SR626 177 1.5V 6.8*2.6  
AG5 LR754 393 SR754 193 1.5V 7.9*5.4  
AG6 LR920 371 SR927 171 1.5V 9.5*2.1  
AG7 LR927 395 SR927 195 1.5V 9.5*2.6  
AG8 LR55 391 SR1120 191 1.5V 11.6*2.1  
AG9 LR936 394 SR936 194 1.5V 9.5*3.6  
AG10 LR54 389 SR1130 189 1.5V 11.6*3.1 计算器
AG11 LR721 362 SR721 162 1.5V 7.9*2.1  
AG12 LR43 386 SR1142 186 1.5V 11.6*4.2 计算器、计步器
AG13 LR44 357 SR1154 A76 1.5V 11.6*5.4 手表、计算机
      CR2032   3V 20*3.2 体重秤、主板
      CR2025   3V 20*2.6 电子词典
      CR2016   3V 20*1.6 手表,计算机、电子记事簿

下面例举两种材料的纽扣电池的型号对照表。

氧化银纽扣电池型号对照表——AG系列

锂-二氧化锰纽扣电池型号对照表——CR系列

IT技术 ,

USB 2.0 A型、B型、Mini和Micro接口定义及封装

2012年2月3日
USB 2.0 A型、B型、Mini和Micro接口定义及封装已关闭评论

USB全称Universal Serial Bus(通用串行总线),目前USB 2.0接口分为四种类型A型、B型、Mini型还有后来补充的Micro型接口,每种接口都分插头和插座两个部分,Micro还有比较特殊的AB兼容型,本文简要介绍这四类插头和插座的实物及结构尺寸图,如果是做设计用途,还需要参考官方最新补充或修正说明,尽管USB 3.0性能非常卓越,但由于USB 3.0规范变化较大,真正应用起来还需假以时日,不管怎样,都已经把火线逼到末路,苹果公司极其郁闷但也爱莫能助。

注意:

1、本文封装尺寸来源,USB 2.0 Specification Engineering Change Notice(Date:10/20/2000)

2、本文图片来源USB官方协议文档,由于USB 3.0在接口和线缆规范上变化较大,后面专门介绍。

3、本文未带插头封装尺寸,插头尺寸请参加官方文档ecn1-usb20-miniB-revd.pdf,下个版本USB 3.0在接口和封装上都有很大变化,本文属于USB 2.0协议内容,如果是USB 3.0设备,似乎只有A型头才能插到2.0插座中Receptacle。

1、A型USB插头(plug)和A型USB插座(receptacle)

引脚顺序(左侧为Plug,右侧为Receptacle):

引脚定义:

编号 定义 颜色识别
1 VBUS Red(红色)
2 D- White(白色)
3 D+ Green(绿色)
4 GND Black(黑色)

封装尺寸(单PIN Receptacle):

2、B型USB插头(plug)和B型USB插座(receptacle)

引脚顺序(左侧为Plug,右侧为Receptacle,注意箭头所指斜口向上,USB端口朝向自己):

引脚定义、封装尺寸均与A型USB引脚说明相同。

封装尺寸(单PIN Receptacle):

3、Mini B型USB插头(plug)和Mini B型USB插座(receptacle)

引脚顺序(左侧为Plug,右侧为Receptacle,注意宽边在上,USB端口朝向自己):

引脚定义:

编号 定义 颜色识别
1 VBUS Red(红色)
2 D- White(白色)
3 D+ Green(绿色)
4 ID Not connected(未连接)
5 GND Black(黑色)

封装尺寸(Receptacle):

以上部分为USB 2.0规范内容,下面的Micro USB实际上是在2006年才发布的补充规范,由于该接口定义无法后向支持USB 3.0协议,故仍然归于USB 2.0协议包。

4、Micro USB插头和插座

Micro USB补充定义用于蜂窝电话和便携设备的Micro USB接口,比Mini USB接口更小。其中标准A型和标准B型及Mini-B型都是在USB 2.0规范里定义,2006补充的Micro USB规范定义了,补充了以下定义:

Micro-B plug and receptacle

Micro-AB receptacle

Micro-A plug

由于该协议文档极不清晰,相关插图也是采用贴图形式,所以不再抓图介绍,只放两个实物照片上来看一下(图片来源:USB MOBILE):

A型与B型的比较如下图:从左往右依次为:miniUSB公口(A型插头)、miniUSB公口(B型插头)、USB公口(B型)、USB母口(A型插座)、USB公口(A型插头)
USB接口

详细了解,请参考官方USB 2.0规范文档,之Micro-USB_1_01.pdf一文,附USB官方网址:http://www.usb.org/

IT技术 , , , , , ,

HDMI之CEC

2012年1月10日
HDMI之CEC已关闭评论

The bus, known as the consumer electronics control (CEC) bus, is the basis for a new level of automatic control in HDMI-interfaced systems. With the recent release of a CEC compliance test specification and commercial CEC test equipment, consumer electronic companies are now poised to implement CEC in their products. In fact, new CECenabled products are expected to begin shipping in April 2006.

The basic technology of the CEC bus originated in Europe, on the SCART interface, where it’s been used with great success for many years. HDMI borrows and improves on the basic SCART technology, allowing AV products to discover and communicate with one another across a system. CEC makes possible global controls, which build on existing point-topoint E-DDC-based "plug & play" automation to minimize the number of IR remotes and key-presses required for basic operation of a system.

CEC assumes that all AV source products in a system are directly or indirectly connected to a “root” display. HDMI connections form an upside-down tree, with a display as the “root”, switches as “branches”, and various source products as “leaf” nodes. For example, CEC allows users to connect a mix of AV products, place a DVD into the player, press PLAY, and let CEC handle the rest.

CEC will automatically power-on the appropriate products, route the DVDplayer’s audio output through the AVR to attached speakers, and route the player’s motion picture to the Digital TV. Likewise, selecting a channel on the set-top-box will cause television audio to replace movie audio on the speakers and a TV picture to replace the motion picture on the Digital TV. Further, pressing the RECORD button on the recording device will cause the television program on the "root" to be automatically routed to and recorded on that device. In short, CEC enables automatic equipment discovery and simple "one touch" operation in HDMI-interfaced systems.

The CEC bus is a one-wire, “party line” that connects up to ten (10) AV devices through standard HDMI cabling. The CEC protocol includes automatic mechanisms for physical address (topology) discovery, (product type based) logical addressing, arbitration, retransmission, broadcasting, and routing control. Message opcodes support both device specific (e.g. set-top-box, DTV, and player) and general features (e.g. for power, signal routing, remote control pass-through, and on-screen display).

IT技术 ,

HDMI之EDID

2012年1月10日
HDMI之EDID已关闭评论

      EDID(Extended Display Identification DATA,即扩展显示识别数据), 最初是为PC显示器设置的优化显示格式而设计的规范,存储在显示器中专用的1Kb的EEROM存储器中(即EDID数据结构是128Bytes),数字电视HDMI接口,遵从并且扩展了此规范。

     同PC主机和显示器通过DDC数据线访问存储器中数据,以确定显示器的显示属性(如分辨率、纵横比等)信息一样,在数字电视上,也沿用HDMI接口的DDC数据线访问EDID存储器,以确定数字电视的相关显示属性,关键是128Byte是PC显示器的标准,已不能满足数字电视视频标准的要求,因此需要对数据结构进行扩展,由于EDID标准并没有相应的规范,按照EIA/CEA-861-B标准规范对EDID数据进行编程。(VESA已经有相关的规范出台, 新的标准也是配合了EIA/CEA-861-B标准规范而已, 且需付费才能获取)

HDMI接口在数字电视中的EDID数据结构,与PC显示器的最大区别是编程数据可以是128Byte的倍数,它不仅规定数字电视显示的格式,也规定数字视频信号和数字音频信号,基本的128Byte以外的数据都是附加数据,在基本数据的第127个字节定义EDID的附加数据块数量。在EDID数据编程中,根据数字电视的显示属性要求,有两个关键环节必须注意:

  第一,如果数字电视的显示是固定格式,则在首选Timing Mode字节中必须选择相应的定义;

  第二,数字电视的标准显示属性应在第一段详细Timing Mode字节中完成数据编程。
数字电视HDMI的EDID读取,因为有CEA的数据在附加数据块里,信号源必须满足E-DDC标准,才能读取EDID数据。

IT技术 ,

HDMI之HPD

2012年1月10日
HDMI之HPD已关闭评论

    HPD(Hot Plug Detection),在HDMI的一对联接中,为热插拔的实现而设计的。简单地说,当发送端接入接受端时,接受端会回应HPD信号给发送端,进而发送端会启动DDC通道,而读取接受端EDID的信息,然后进行HDCP的交互,如果双方认证成功,则视频、音频正常工作,否则联接失败,不同系统会有不同的处理。

    例如,如果EDID信息不支持HDMI,则发送端只发送视频信息,而没有音频信息,这时候的HDMI就只相当于DVI了;如果HDCP认证不成功,有的系统会出现雪花屏幕和噪音,有的系统会由高分辨率(1080I、720P)降低为低分辨率(480I、480P)而输出,这样一来,HDTV就不再是HD 了,而变成了普通的SD。

    An Important element to proper interpretation of EDID is "Hot Plugging". The following presents a recommendation for achieving consistent results during a Hot Plugging event.

    DVI 1.0 define a HPD signal function that indicates to the host whether a  monitor is connected. HPD is designed to be powered by the DDC +5V coming from the host, and to be independaent of whether the monitor is powered or not. In this way, a host device can detect the monitor and read its characteristics from EDID without the monitor being powered. On a PC, this feature allows the system to load the correct display configuration without delaying the boot process.

    In short, in this context, HPD serves as an indication that the EDID is available to be read, however HPD may also have alternative uses. It does no imply any other state of readiness. The relevant definitions from the DVI 1.0 specification are:

    a. HPD – Signal is driven by monitor to enable the system to identify the presence of a monitor;

    b. The monitor is required to provide a voltage of greater than +2.4V on the HPD pin of the connector only when the EDID data structure is available to be read by the host.

    Implementation Notes: As an example for hot plug support, a simple monitor implementation of HPD support could be a pull up resistor to the EDID power supply. After HPD goes active, the host is only expected to read EDID and determine that a valid display mode is available and supported.

    Note — Whenever the EDID information in a device changes for any reason(e.g. if the EDID was updated, or is capable of dynamically changing its information content), the receiving device pulses HPD low for at least 100ms. This recommendation follows from the HDCP repeater implementation requirement that HDCP repeater pulse HPD low for at least 100ms to indicate the connection of new device or disconnection of an existing one.

    这里只是概要的谈谈,后续将会对其联系EDID和HDCP详述。

IT技术 ,