原始视频只要按照RTMP协议发送给RTMP,当需要处理

作者: 编程  发布:2019-09-21

1.

HTML5 3D衣服摇摆动画特效,

这又是一款基于HTML5 Canvas的3D动画杰作,它是一个可以随风飘动的3D衣服摇摆动画特效,非常逼真。当我们将鼠标滑过衣服时,衣服将会出现摇摆的动画,点击鼠标时,衣服将会更加剧烈地摆动。

9159.com 1

在线演示  源码下载

HTML代码

XML/HTML Code复制内容到剪贴板

  1. <div style="width:500px;margin:10px auto">  
  2.  <canvas id="cv" width="480" height="300"></canvas>  
  3.  <p>"3D on 2D Canvas" demo</p>  
  4.  <p>move cursor to pan / click to swing</p>  
  5. </div>  

P3D库JS代码,主要用来处理3D效果的

JavaScript Code复制内容到剪贴板

  1. window.P3D = {   
  2.  texture: null,   
  3.  g: null  
  4. };   
  5.   
  6. P3D.clear = function(f, w, h) {   
  7.  var g = this.g;   
  8.  g.beginPath();   
  9.  g.fillStyle = f;   
  10.  g.fillRect(0, 0, w, h);   
  11.   
  12. }   
  13.   
  14. P3D.num_cmp = function(a,b){return a-b;}   
  15.   
  16. P3D.drawTriangle = function(poss, uvs, shade_clr) {   
  17.  var w = this.texture.width;   
  18.  var h = this.texture.height;   
  19.   
  20.  var g = this.g;   
  21.   
  22.  var vAd = [ poss[1].x - poss[0].x , poss[1].y - poss[0].y ];   
  23.  var vBd = [ poss[2].x - poss[0].x , poss[2].y - poss[0].y ];   
  24.   
  25.  var vA = [ uvs[1].u - uvs[0].u , uvs[1].v - uvs[0].v ];   
  26.  var vB = [ uvs[2].u - uvs[0].u , uvs[2].v - uvs[0].v ];   
  27.   
  28.  vA[0] *= w;   
  29.  vA[1] *= h;   
  30.   
  31.  vB[0] *= w;   
  32.  vB[1] *= h;   
  33.   
  34.  var m = new M22();   
  35.  m._11 = vA[0];   
  36.  m._12 = vA[1];   
  37.  m._21 = vB[0];   
  38.  m._22 = vB[1];   
  39.   
  40.  var im = m.getInvert();   
  41.  if (!im) return false;   
  42.   
  43.  var a = im._11 * vAd[0] + im._12 * vBd[0];   
  44.  var b = im._21 * vAd[0] + im._22 * vBd[0];   
  45.   
  46.  var c = im._11 * vAd[1] + im._12 * vBd[1];   
  47.  var d = im._21 * vAd[1] + im._22 * vBd[1];   
  48.   
  49.  var wu = uvs[0].u * w;   
  50.  var hv = uvs[0].v * h;   
  51.  var du = wu * a + hv * b;   
  52.  var dv = wu * c + hv * d;   
  53.   
  54.  g.save();   
  55.   
  56.  g.beginPath();   
  57.  g.moveTo(poss[0].x, poss[0].y);   
  58.  g.lineTo(poss[1].x, poss[1].y);   
  59.  g.lineTo(poss[2].x, poss[2].y);   
  60.  g.clip();   
  61.   
  62.  g.transform(a, c, b, d, poss[0].x - du, poss[0].y - dv);   
  63.   
  64.  // bounds   
  65.  var bx = [wu, wu+vA[0], wu+vB[0]];   
  66.  var by = [hv, hv+vA[1], hv+vB[1]];   
  67.   
  68.  bx.sort(P3D.num_cmp);   
  69.  by.sort(P3D.num_cmp);   
  70.   
  71.  var bw = bx[2] - bx[0];   
  72.  var bh = by[2] - by[0];   
  73.   
  74.  if ((bx[0]+bw) <= (w-1)) bw++;   
  75.  if ((by[0]+bh) <= (h-1)) bh++;   
  76.  if (bx[0] >= 1) {bx[0]--; bw++;}   
  77.  if (by[0] >= 1) {by[0]--; bh++;}   
  78.   
  79.  g.drawImage(this.texture, bx[0], by[0], bw, bh, bx[0], by[0], bw, bh);   
  80.   
  81.  if (shade_clr) {   
  82.   g.fillStyle = shade_clr;   
  83.   g.fillRect(bx[0], by[0], bw, bh);   
  84.  }   
  85.   
  86.  g.restore();   
  87.   
  88.  return true;   
  89. }   
  90.   
  91. P3D.drawTestByIndexBuffer = function(pos_buf, ix_buf, culling) {   
  92.  var g = this.g;   
  93.   
  94.  if ((ix_buf.length%3) != 0)   
  95.   throw "invalid index buffer length!";   
  96.   
  97.  var len = ix_buf.length/3;   
  98.   
  99.  var i, ibase, vbase;   
  100.  var poss = [{},{},{}];   
  101.  g.strokeWidth = 1;   
  102.  for (i = 0, ibase = 0;i < len;++i)   
  103.  {   
  104.   vbase = ix_buf[ibase++] << 2;   
  105.   poss[0].x = pos_buf[vbase++];   
  106.   poss[0].y = pos_buf[vbase  ];   
  107.   
  108.   vbase = ix_buf[ibase++] << 2;   
  109.   poss[1].x = pos_buf[vbase++];   
  110.   poss[1].y = pos_buf[vbase  ];   
  111.   
  112.   vbase = ix_buf[ibase++] << 2;   
  113.   poss[2].x = pos_buf[vbase++];   
  114.   poss[2].y = pos_buf[vbase  ];   
  115.   
  116.   // z component of cross product < 0 ?   
  117.   
  118.   var Ax = poss[1].x - poss[0].x;   
  119.   var Ay = poss[1].y - poss[0].y;   
  120.   var Cx = poss[2].x - poss[1].x;   
  121.   var Cy = poss[2].y - poss[1].y;   
  122.   
  123.   var cull = ( (((Ax * Cy) - (Ay * Cx))*culling) < 0);   
  124.   
  125.   g.beginPath();   
  126.   g.strokeStyle = cull ? "#592" : "#0f0";   
  127.   g.moveTo(poss[0].x, poss[0].y);   
  128.   g.lineTo(poss[1].x, poss[1].y);   
  129.   g.lineTo(poss[2].x, poss[2].y);   
  130.   g.lineTo(poss[0].x, poss[0].y);   
  131.   g.stroke();   
  132.  }   
  133. }   
  134.   
  135. P3D.drawByIndexBuffer = function(pos_buf, ix_buf, tx_buf, culling, z_clip) {   
  136.  var w, h;   
  137.  var color_polygon = !this.texture;   
  138.  if (this.texture) {   
  139.   w = this.texture.width;   
  140.   h = this.texture.height;   
  141.  }   
  142.   
  143.  var g = this.g;   
  144.  var m = new M22();   
  145.   
  146.  if (!culling) culling = 0;   
  147.   
  148.  if ((ix_buf.length%3) != 0)   
  149.   throw "invalid index buffer length!";   
  150.   
  151.  var i, ibase, vbase, tbase, poss = [{},{},{}];   
  152.  var len = ix_buf.length/3;   
  153.  var uv_0u, uv_0v, uv_1u, uv_1v, uv_2u, uv_2v;   
  154.   
  155.  for (i = 0, ibase = 0;i < len;++i)   
  156.  {   
  157.   tbase = ix_buf[ibase++] << 1   
  158.   vbase = tbase << 1;   
  159.   poss[0].x = pos_buf[vbase++]; uv_0u = tx_buf[tbase++];   
  160.   poss[0].y = pos_buf[vbase++]; uv_0v = tx_buf[tbase];   
  161.   if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {ibase += 2; continue;}   
  162.   
  163.   tbase = ix_buf[ibase++] << 1   
  164.   vbase = tbase << 1;   
  165.   poss[1].x = pos_buf[vbase++]; uv_1u = tx_buf[tbase++];   
  166.   poss[1].y = pos_buf[vbase++]; uv_1v = tx_buf[tbase];   
  167.   if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {++ibase; continue;}   
  168.   
  169.   tbase = ix_buf[ibase++] << 1   
  170.   vbase = tbase << 1;   
  171.   poss[2].x = pos_buf[vbase++]; uv_2u = tx_buf[tbase++];   
  172.   poss[2].y = pos_buf[vbase++]; uv_2v = tx_buf[tbase];   
  173.   if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {continue;}   
  174.   
  175.   var vAd = [ poss[1].x - poss[0].x , poss[1].y - poss[0].y ];   
  176.   var vBd = [ poss[2].x - poss[0].x , poss[2].y - poss[0].y ];   
  177.   
  178.   var vCd = [ poss[2].x - poss[1].x , poss[2].y - poss[1].y ];   
  179.   
  180.   // z component of cross product < 0 ?   
  181.   if( (((vAd[0] * vCd[1]) - (vAd[1] * vCd[0]))*culling) < 0)   
  182.    continue;   
  183.   
  184.   if (color_polygon) {   
  185.    g.fillStyle = uv_0u;   
  186.   
  187.    g.beginPath();   
  188.    g.moveTo(poss[0].x, poss[0].y);   
  189.    g.lineTo(poss[1].x, poss[1].y);   
  190.    g.lineTo(poss[2].x, poss[2].y);   
  191.    g.fill();   
  192.    continue;   
  193.   }   
  194.   
  195.   var vA = [ uv_1u - uv_0u , uv_1v - uv_0v ];   
  196.   var vB = [ uv_2u - uv_0u , uv_2v - uv_0v ];   
  197.   
  198.   vA[0] *= w;   
  199.   vA[1] *= h;   
  200.   
  201.   vB[0] *= w;   
  202.   vB[1] *= h;   
  203.   
  204.   m._11 = vA[0];   
  205.   m._12 = vA[1];   
  206.   m._21 = vB[0];   
  207.   m._22 = vB[1];   
  208.   
  209.   var im = m.getInvert();   
  210.   if (!im) { continue;}   
  211.   
  212.   var a = im._11 * vAd[0] + im._12 * vBd[0];   
  213.   var b = im._21 * vAd[0] + im._22 * vBd[0];   
  214.   
  215.   var c = im._11 * vAd[1] + im._12 * vBd[1];   
  216.   var d = im._21 * vAd[1] + im._22 * vBd[1];   
  217.   
  218.   var wu = uv_0u * w;   
  219.   var hv = uv_0v * h;   
  220.   var du = wu * a + hv * b;   
  221.   var dv = wu * c + hv * d;   
  222.   
  223.   g.save();   
  224.   
  225.   g.beginPath();   
  226.   g.moveTo(poss[0].x, poss[0].y);   
  227.   g.lineTo(poss[1].x, poss[1].y);   
  228.   g.lineTo(poss[2].x, poss[2].y);   
  229.   g.clip();   
  230.   g.transform(a, c, b, d, poss[0].x - du, poss[0].y - dv);   
  231.   
  232.   // bounds   
  233.   var bx = [wu, wu+vA[0], wu+vB[0]];   
  234.   var by = [hv, hv+vA[1], hv+vB[1]];   
  235.   
  236.   bx.sort(P3D.num_cmp);   
  237.   by.sort(P3D.num_cmp);   
  238.   
  239.   var bw = bx[2] - bx[0];   
  240.   var bh = by[2] - by[0];   
  241.   
  242.   if ((bx[0]+bw) <= (w-1)) bw++;   
  243.   if ((by[0]+bh) <= (h-1)) bh++;   
  244.   if (bx[0] >= 1) {bx[0]--; bw++;}   
  245.   if (by[0] >= 1) {by[0]--; bh++;}   
  246.   
  247.   g.drawImage(this.texture, bx[0], by[0], bw, bh, bx[0], by[0], bw, bh);   
  248. /*  
  249.   if (shade_clr) {  
  250.    g.fillStyle = shade_clr;  
  251.    g.fillRect(bx[0], by[0], bw, bh);  
  252.   }  
  253. */  
  254.   g.restore();   
  255.   
  256.  }   
  257.   
  258. }   
  259.   
  260. function Vec3(_x, _y, _z)   
  261. {   
  262.  this.x = _x || 0;   
  263.  this.y = _y || 0;   
  264.  this.z = _z || 0;   
  265. }   
  266.   
  267. Vec3.prototype = {   
  268.  zero: function() {   
  269.   this.x = this.y = this.z = 0;   
  270.  },   
  271.   
  272.  sub: function(v) {   
  273.   this.x -= v.x;   
  274.   this.y -= v.y;   
  275.   this.z -= v.z;   
  276.   
  277.   return this;   
  278.  },   
  279.   
  280.  add: function(v) {   
  281.   this.x += v.x;   
  282.   this.y += v.y;   
  283.   this.z += v.z;   
  284.   
  285.   return this;   
  286.  },   
  287.   
  288.  copyFrom: function(v) {   
  289.   this.x = v.x;   
  290.   this.y = v.y;   
  291.   this.z = v.z;   
  292.   
  293.   return this;   
  294.  },   
  295.   
  296.  norm:function() {   
  297.   return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);   
  298.  },   
  299.   
  300.  normalize: function() {   
  301.   var nrm = Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);   
  302.   if (nrm != 0)   
  303.   {   
  304.    this.x /= nrm;   
  305.    this.y /= nrm;   
  306.    this.z /= nrm;   
  307.   }   
  308.   return this;   
  309.  },   
  310.   
  311.  smul: function(k) {   
  312.   this.x *= k;   
  313.   this.y *= k;   
  314.   this.z *= k;   
  315.   
  316.   return this;   
  317.  },   
  318.   
  319.  dpWith: function(v) {   
  320.   return this.x*v.x + this.y*v.y + this.z*v.z;   
  321.  },   
  322.   
  323.  cp: function(v, w) {   
  324.   this.x = (w.y * v.z) - (w.z * v.y);   
  325.   this.y = (w.z * v.x) - (w.x * v.z);   
  326.   this.z = (w.x * v.y) - (w.y * v.x);   
  327.   
  328.   return this;   
  329.  },   
  330.   
  331.  toString: function() {   
  332.   return this.x + ", " + this.y + "," + this.z;   
  333.  }   
  334. }   
  335.   
  336. function M44(cpy)   
  337. {   
  338.  if (cpy)   
  339.   this.copyFrom(cpy);   
  340.  else {   
  341.   this.ident();   
  342.  }   
  343. }   
  344.   
  345. M44.prototype = {   
  346.  ident: function() {   
  347.      this._12 = this._13 = this._14 = 0;   
  348.   this._21 =       this._23 = this._24 = 0;   
  349.   this._31 = this._32 =       this._34 = 0;   
  350.   this._41 = this._42 = this._43 =       0;   
  351.   
  352.   this._11 = this._22 = this._33 = this._44 = 1;   
  353.   
  354.   return this;   
  355.  },   
  356.   
  357.  copyFrom: function(m) {   
  358.   this._11 = m._11;   
  359.   this._12 = m._12;   
  360.   this._13 = m._13;   
  361.   this._14 = m._14;   
  362.   
  363.   this._21 = m._21;   
  364.   this._22 = m._22;   
  365.   this._23 = m._23;   
  366.   this._24 = m._24;   
  367.   
  368.   this._31 = m._31;   
  369.   this._32 = m._32;   
  370.   this._33 = m._33;   
  371.   this._34 = m._34;   
  372.   
  373.   this._41 = m._41;   
  374.   this._42 = m._42;   
  375.   this._43 = m._43;   
  376.   this._44 = m._44;   
  377.   
  378.   return this;   
  379.  },   
  380.   
  381.  transVec3: function(out, x, y, z) {   
  382.   out[0] = x * this._11 + y * this._21 + z * this._31 + this._41;   
  383.   out[1] = x * this._12 + y * this._22 + z * this._32 + this._42;   
  384.   out[2] = x * this._13 + y * this._23 + z * this._33 + this._43;   
  385.   out[3] = x * this._14 + y * this._24 + z * this._34 + this._44;   
  386.  },   
  387.   
  388.  transVec3Rot: function(out, x, y, z) {   
  389.   out[0] = x * this._11 + y * this._21 + z * this._31;   
  390.   out[1] = x * this._12 + y * this._22 + z * this._32;   
  391.   out[2] = x * this._13 + y * this._23 + z * this._33;   
  392.  },   
  393.   
  394.  perspectiveLH: function(vw, vh, z_near, z_far) {   
  395.   this._11 = 2.0*z_near/vw;   
  396.   this._12 = 0;   
  397.   this._13 = 0;   
  398.   this._14 = 0;   
  399.   
  400.   this._21 = 0;   
  401.   this._22 = 2*z_near/vh;   
  402.   this._23 = 0;   
  403.   this._24 = 0;   
  404.   
  405.   this._31 = 0;   
  406.   this._32 = 0;   
  407.   this._33 = z_far/(z_far-z_near);   
  408.   this._34 = 1;   
  409.   
  410.   this._41 = 0;   
  411.   this._42 = 0;   
  412.   this._43 = z_near*z_far/(z_near-z_far);   
  413.   this._44 = 0;   
  414.   
  415.   return this;   
  416.  },   
  417.   
  418.  lookAtLH: function(aUp, aFrom, aAt) {   
  419.   var aX = new Vec3();   
  420.   var aY = new Vec3();   
  421.   
  422.   var aZ = new Vec3(aAt.x, aAt.y, aAt.z);   
  423.   aZ.sub(aFrom).normalize();   
  424.   
  425.   aX.cp(aUp, aZ).normalize();   
  426.   aY.cp(aZ, aX);   
  427.   
  428.   this._11 = aX.x;  this._12 = aY.x;  this._13 = aZ.x;  this._14 = 0;   
  429.   this._21 = aX.y;  this._22 = aY.y;  this._23 = aZ.y;  this._24 = 0;   
  430.   this._31 = aX.z;  this._32 = aY.z;  this._33 = aZ.z;  this._34 = 0;   
  431.   
  432.   this._41 = -aFrom.dpWith(aX);   
  433.   this._42 = -aFrom.dpWith(aY);   
  434.   this._43 = -aFrom.dpWith(aZ);   
  435.   this._44 = 1;   
  436.   
  437.      return this;   
  438.  },   
  439.   
  440.  mul: function(A, B) {   
  441.   this._11 = A._11*B._11  +  A._12*B._21  +  A._13*B._31  +  A._14*B._41;   
  442.   this._12 = A._11*B._12  +  A._12*B._22  +  A._13*B._32  +  A._14*B._42;   
  443.   this._13 = A._11*B._13  +  A._12*B._23  +  A._13*B._33  +  A._14*B._43;   
  444.   this._14 = A._11*B._14  +  A._12*B._24  +  A._13*B._34  +  A._14*B._44;   
  445.   
  446.   this._21 = A._21*B._11  +  A._22*B._21  +  A._23*B._31  +  A._24*B._41;   
  447.   this._22 = A._21*B._12  +  A._22*B._22  +  A._23*B._32  +  A._24*B._42;   
  448.   this._23 = A._21*B._13  +  A._22*B._23  +  A._23*B._33  +  A._24*B._43;   
  449.   this._24 = A._21*B._14  +  A._22*B._24  +  A._23*B._34  +  A._24*B._44;   
  450.   
  451.   this._31 = A._31*B._11  +  A._32*B._21  +  A._33*B._31  +  A._34*B._41;   
  452.   this._32 = A._31*B._12  +  A._32*B._22  +  A._33*B._32  +  A._34*B._42;   
  453.   this._33 = A._31*B._13  +  A._32*B._23  +  A._33*B._33  +  A._34*B._43;   
  454.   this._34 = A._31*B._14  +  A._32*B._24  +  A._33*B._34  +  A._34*B._44;   
  455.   
  456.   this._41 = A._41*B._11  +  A._42*B._21  +  A._43*B._31  +  A._44*B._41;   
  457.   this._42 = A._41*B._12  +  A._42*B._22  +  A._43*B._32  +  A._44*B._42;   
  458.   this._43 = A._41*B._13  +  A._42*B._23  +  A._43*B._33  +  A._44*B._43;   
  459.   this._44 = A._41*B._14  +  A._42*B._24  +  A._43*B._34  +  A._44*B._44;   
  460.   
  461.   return this;   
  462.  },   
  463.   
  464.  translate: function(x, y, z) {   
  465.   this._11 = 1;  this._12 = 0;  this._13 = 0;  this._14 = 0;   
  466.   this._21 = 0;  this._22 = 1;  this._23 = 0;  this._24 = 0;   
  467.   this._31 = 0;  this._32 = 0;  this._33 = 1;  this._34 = 0;   
  468.   
  469.   this._41 = x;  this._42 = y;  this._43 = z;  this._44 = 1;   
  470.   return this;   
  471.  },   
  472.   
  473.  transpose33: function() {   
  474.   var t;   
  475.   
  476.   t = this._12;   
  477.   this._12 = this._21;   
  478.   this._21 = t;   
  479.   
  480.   t = this._13;   
  481.   this._13 = this._31;   
  482.   this._31 = t;   
  483.   
  484.   t = this._23;   
  485.   this._23 = this._32;   
  486.   this._32 = t;   
  487.   
  488.   return this;   
  489.  },   
  490.   
  491.  // OpenGL style rotation   
  492.  glRotate: function(angle, x, y, z) {   
  493.   var s = Math.sin( angle );   
  494.   var c = Math.cos( angle );   
  495.   
  496.   var xx = x * x;   
  497.   var yy = y * y;   
  498.   var zz = z * z;   
  499.   var xy = x * y;   
  500.   var yz = y * z;   
  501.   var zx = z * x;   
  502.   var xs = x * s;   
  503.   var ys = y * s;   
  504.   var zs = z * s;   
  505.   var one_c = 1.0 - c;   
  506. /*  
  507.   this._11 = (one_c * xx) + c;  
  508.   this._21 = (one_c * xy) - zs;  
  509.   this._31 = (one_c * zx) + ys;  
  510.   this._41 = 0;  
  511.  
  512.   this._12 = (one_c * xy) + zs;  
  513.   this._22 = (one_c * yy) + c;  
  514.   this._32 = (one_c * yz) - xs;  
  515.   this._42 = 0;  
  516.  
  517.   this._13 = (one_c * zx) - ys;  
  518.   this._23 = (one_c * yz) + xs;  
  519.   this._33 = (one_c * zz) + c;  
  520.   this._43 = 0;  
  521.  
  522.   this._14 = 0;  
  523.   this._24 = 0;  
  524.   this._34 = 0;  
  525.   this._44 = 1;  
  526. */  
  527.   
  528.   this._11 = (one_c * xx) + c;   
  529.   this._12 = (one_c * xy) - zs;   
  530.   this._13 = (one_c * zx) + ys;   
  531.   this._14 = 0;   
  532.   
  533.   this._21 = (one_c * xy) + zs;   
  534.   this._22 = (one_c * yy) + c;   
  535.   this._23 = (one_c * yz) - xs;   
  536.   this._24 = 0;   
  537.   
  538.   this._31 = (one_c * zx) - ys;   
  539.   this._32 = (one_c * yz) + xs;   
  540.   this._33 = (one_c * zz) + c;   
  541.   this._34 = 0;   
  542.   
  543.   this._41 = 0;   
  544.   this._42 = 0;   
  545.   this._43 = 0;   
  546.   this._44 = 1;   
  547.   
  548.   return this;   
  549.  }   
  550.   
  551. }   
  552.   
  553. // matrix 2x2   
  554. function M22()   
  555. {   
  556.  this._11 = 1;   
  557.  this._12 = 0;   
  558.  this._21 = 0;   
  559.  this._22 = 1;   
  560. }   
  561.   
  562. M22.prototype.getInvert = function()   
  563. {   
  564.  var out = new M22();   
  565.  var det = this._11 * this._22 - this._12 * this._21;   
  566.  if (det > -0.0001 && det < 0.0001)   
  567.   return null;   
  568.   
  569.  out._11 = this._22 / det;   
  570.  out._22 = this._11 / det;   
  571.   
  572.  out._12 = -this._12 / det;   
  573.  out._21 = -this._21 / det;   
  574.   
  575.  return out;   
  576. }   

3D衣服动画JS代码

JavaScript Code复制内容到剪贴板

  1. function ClothApp()   
  2. {   
  3.  this.canvas = document.getElementById("cv");   
  4.   
  5.  P3D.g = this.canvas.getContext("2d");   
  6.   
  7.  var tex = new Image();   
  8.  this.texture1 = tex;   
  9.  tex.onload = function(){ _this.start(); };   
  10.  tex.src = "20090226032826.gif";   
  11.   
  12.  tex = new Image();   
  13.  this.texture2 = tex;   
  14.  tex.onload = function(){ _this.start(); };   
  15.  tex.src = "20090226032825.png";   
  16.   
  17.  this.mLoadCount = 2;   
  18.  this.mTickCount = 0;   
  19.   
  20.  this.G = 0.53;   
  21.  this.G1 = 0.45;   
  22.  this.mProjMat  = null;   
  23.  this.mViewMat  = null;   
  24.  this.mViewFrom = new Vec3();   
  25.  this.mViewFrom.y = -150;   
  26.  this.mViewFrom.z = 1000;   
  27.  this.mViewFromA = (new Vec3()).copyFrom(this.mViewFrom);   
  28.   
  29.  this.mViewAngle = 0;   
  30.   
  31.  this.mNLen = 0;   
  32.  this.mNodes = [];   
  33.  this.mRenderTris = null;   
  34.   
  35.  this.mLTNode = null;   
  36.  this.mRTNode = null;   
  37.   
  38.  this.mLTNodeV = new Vec3();   
  39.  this.mRTNodeV = new Vec3();   
  40.   
  41.  this.mWForce = new Vec3();   
  42.  this.frate = 15;   
  43.   
  44.  var _this = this;   
  45. }   
  46.   
  47. ClothApp.zsortCmp = function(t1, t2) {   
  48.  return t2.sortKey - t1.sortKey;   
  49. }   
  50.   
  51. ClothApp.prototype = {   
  52.  start: function() {   
  53.   if (--this.mLoadCount != 0) return;   
  54.   
  55.   this.vUP = new Vec3(0,  1, 0);   
  56.   this.vAT = new Vec3(0, 80, 0);   
  57.   
  58.   this.mViewport = {};   
  59.   this.mViewport.w = 480;   
  60.   this.mViewport.h = 300;   
  61.   this.mViewport.ow = 240;   
  62.   this.mViewport.oh = 150;   
  63.   this.setupTransforms();   
  64.   
  65.   this.generateCloth(180);   
  66.   this.generateRenderTriangles();   
  67.   
  68.   var _this = this;   
  69.   this.canvas.addEventListener("mousemove", function(e){_this.onMouseMove(e);}, false);   
  70.   this.canvas.addEventListener("mousedown", function(e){_this.onClick(e);}, false);   
  71.   
  72.   window.setTimeout(function(){_this.onInterval();}, this.frate);   
  73.  },   
  74.   
  75.  onInterval: function() {   
  76.   this.mTickCount++;   
  77.   
  78.   // this.mLTNodeV.z = Math.cos(this.mTickCount*0.1) * 2;   
  79.   
  80.   this.tick();   
  81.   this.updatePosition();   
  82.   this.draw();   
  83.   
  84.   var _this = this;   
  85.   window.setTimeout(function(){_this.onInterval();}, this.frate);   
  86.  },   
  87.   
  88.  onMouseMove: function(e) {   
  89.   if (e.clientX || e.clientX == 0)   
  90.    this.mViewAngle = (e.clientX - 240) * 0.004;   
  91.   
  92.   if (e.clientY || e.clientY == 0)   
  93.    this.mViewFromA.y = 90 - (e.clientY - 0) * 0.8;   
  94.  },   
  95.   
  96.  onClick: function(e) {   
  97.   if (e.clientX || e.clientX == 0)   
  98.   {   
  99.    this.mWForce.z = -4;   
  100.    this.mWForce.x = (e.clientX - 240) * -0.03;   
  101.   }   
  102.  },   
  103.   
  104.  tick: function() {   
  105.   this.updateViewTrans(this.mViewAngle);   
  106.   
  107.   var nlen = this.mNodes.length;   
  108.   var i, nd;   
  109.   for(i = 0;i < nlen;i++)   
  110.   {   
  111.    nd = this.mNodes[i];   
  112.    nd.F.x = 0;   
  113.    nd.F.z = 0;   
  114.    if (nd.flags & 4)   
  115.     nd.F.y = -this.G1;   
  116.    else  
  117.     nd.F.y = -this.G;   
  118.   
  119.    nd.F.add(this.mWForce);   
  120.   }   
  121.   
  122.   this.mWForce.zero();   
  123.   this.applyTension();   
  124.   
  125.   for(i = 0;i < nlen;i++)   
  126.   {   
  127.    nd = this.mNodes[i];   
  128.   
  129.    if ((nd.flags&1) != 0) {   
  130.     nd.F.sub(nd.F);   
  131.    }   
  132.   
  133.    nd.velo.add(nd.F);   
  134.   }   
  135.   
  136.   this.mLTNode.velo.copyFrom(this.mLTNodeV);   
  137.   this.mRTNode.velo.copyFrom(this.mRTNodeV);   
  138.  },   
  139.   
  140.  updatePosition: function() {   
  141.   var nlen = this.mNodes.length;   
  142.   var i, nd;   
  143.   for(i = 0;i < nlen;i++)   
  144.   {   
  145.    nd = this.mNodes[i];   
  146.   
  147.    if ((nd.flags&1) != 0) {   
  148.     nd.cv.x = 0;   
  149.     nd.cv.y = 0;   
  150.     nd.cv.z = 0;   
  151.    }   
  152.   
  153.    nd.pos.add(nd.velo);   
  154.    nd.velo.sub(nd.cv);   
  155.    nd.cv.x = 0;   
  156.    nd.cv.y = 0;   
  157.    nd.cv.z = 0;   
  158.   
  159.    nd.velo.smul(0.95);   
  160.   }   
  161.  },   
  162.   
  163.  draw: function() {   
  164.   P3D.clear("#000", this.mViewport.w, this.mViewport.h);   
  165.   this.transformPolygons();   
  166.   
  167.   this.mRenderTris.sort(ClothApp.zsortCmp);   
  168.   var len = this.mRenderTris.length;   
  169.   var t, sh;   
  170.   for (var i = 0;i < len;i++) {   
  171.    t = this.mRenderTris[i];   
  172.   
  173.    if (P3D.texture != t.texture)   
  174.     P3D.texture = t.texture;   
  175.   
  176.    sh = undefined;   
  177.    if (t.lighting && t.shade > 0.01)   
  178.     sh = "rgba(0,0,0,"+t.shade+")";   
  179.    P3D.drawTriangle(t.tposs, t.uvs, sh);   
  180.   }   
  181.  },   
  182.   
  183.  applyTension: function() {   
  184.   var i, k, nd;   
  185.   var v = new Vec3();   
  186.   var nlen = this.mNodes.length;   
  187.   var naturalLen = this.mNLen;   
  188.   
  189.   for (k = 0;k < nlen;k++)   
  190.   {   
  191.    nd = this.mNodes[k];   
  192.    var F = nd.F;   
  193.   
  194.    for (i = 0;i < 4;i++)   
  195.    {   
  196.     var nbr = nd.links[i];   
  197.     if (!nbr) continue;   
  198.   
  199.     var len = v.copyFrom(nbr.pos).sub(nd.pos).norm();   
  200.     var dlen = len - naturalLen;   
  201.     if (dlen > 0) {   
  202.      v.smul(dlen * 0.5 / len);   
  203.   
  204.      F.x += v.x;   
  205.      F.y += v.y;   
  206.      F.z += v.z;   
  207.      nd.cv.add(v.smul(0.8));   
  208.     }   
  209.    }   
  210.   }    
  211.  },   
  212.   
  213.  setupTransforms: function() {   
  214.   this.mProjMat = new M44();   
  215.   this.mProjMat.perspectiveLH(24, 15, 10, 9000);   
  216.   
  217.   this.mViewMat = new M44();   
  218.   this.updateViewTrans(0);   
  219.  },   
  220.   
  221.  updateViewTrans: function(ry) {   
  222.   this.mViewFromA.z = Math.cos(ry) * 380;   
  223.   this.mViewFromA.x = Math.sin(ry) * 380;   
  224.   
  225.   this.mViewFrom.smul(0.7);   
  226.   this.mViewFrom.x += this.mViewFromA.x * 0.3;   
  227.   this.mViewFrom.y += this.mViewFromA.y * 0.3;   
  228.   this.mViewFrom.z += this.mViewFromA.z * 0.3;   
  229.   
  230.   this.mViewMat.lookAtLH(this.vUP, this.mViewFrom, this.vAT);   
  231.  },   
  232.   
  233.  generateCloth: function(base_y) {   
  234.   var cols = 9;   
  235.   var rows = 8;   
  236.   
  237.   var step   = 22;   
  238.   this.mNLen = step*0.9;   
  239.   var w = (cols-1) * step;   
  240.   
  241.   var i, k;   
  242.   for (k = 0;k < rows;k++)   
  243.   {   
  244.    for (i = 0;i < cols;i++)   
  245.    {   
  246.     var nd = new ClothNode();   
  247.     nd.pos.x = -(w/2) + i*step;   
  248.     nd.pos.y = base_y -k*step/2;   
  249.     nd.pos.z = k*16;   
  250.   
  251.     nd.uv.u = i / (cols-1);   
  252.     nd.uv.v = k / (rows-1);   
  253.   
  254.     if (i > 0) {   
  255.      var prv_nd = this.mNodes[this.mNodes.length-1];   
  256.      prv_nd.links[1] = nd;   
  257.      nd.links[0] = prv_nd;   
  258.     }   
  259.   
  260.     if (k > 0) {   
  261.      var up_nd = this.mNodes[this.mNodes.length-cols];   
  262.      up_nd.links[4] = nd;   
  263.      nd.links[3] = up_nd;   
  264.     }   
  265.   
  266.     if (i != 0 && i != 4 && i != (cols-1))   
  267.      nd.flags |= 4;   
  268.   
  269.     this.mNodes.push(nd);   
  270.    }   
  271.   }   
  272.   
  273.   // fix left-top and right-top   
  274.   this.mNodes[0     ].flags |= 1;   
  275.   this.mNodes[4     ].flags |= 1;   
  276.   this.mNodes[cols-1].flags |= 1;   
  277.   
  278.   this.mLTNode = this.mNodes[0     ];   
  279.   this.mRTNode = this.mNodes[cols-1];   
  280.  },   
  281.   
  282.  generateRenderTriangles: function()   
  283.  {   
  284.   if (!this.mRenderTris) this.mRenderTris = [];   
  285.   
  286.   var i;   
  287.   var nd;   
  288.   var nlen = this.mNodes.length;   
  289.   
  290.   for(i = 0;i < nlen;i++)   
  291.   {   
  292.    nd = this.mNodes[i];   
  293.    if (nd.links[1] && nd.links[1].links[4]) {   
  294.     var t = new RenderTriangle();   
  295.     t.texture = this.texture1;   
  296.   
  297.     t.poss[0] = nd.pos;   
  298.     t.poss[1] = nd.links[1].pos;   
  299.     t.poss[2] = nd.links[1].links[4].pos;   
  300.   
  301.     t.uvs[0]  = nd.uv;   
  302.     t.uvs[1]  = nd.links[1].uv;   
  303.     t.uvs[2]  = nd.links[1].links[4].uv;   
  304.   
  305.     this.mRenderTris.push(t);   
  306.   
  307.     t = new RenderTriangle();   
  308.     t.texture = this.texture1;   
  309.   
  310.     t.poss[0] = nd.pos;   
  311.     t.poss[1] = nd.links[1].links[4].pos;   
  312.     t.poss[2] = nd.links[4].pos;   
  313.   
  314.     t.uvs[0]  = nd.uv;   
  315.     t.uvs[1]  = nd.links[1].links[4].uv;   
  316.     t.uvs[2]  = nd.links[4].uv;   
  317.   
  318.     this.mRenderTris.push(t);   
  319.    }   
  320.   }   
  321.   
  322.   this.addBGTriangles(this.mNodes[0].pos.y);   
  323.  },   
  324.   
  325.  addBGTriangles: function(by) {   
  326.   var cols = 4;   
  327.   var t, x, y, sz = 110;   
  328.   var ox = -(cols*sz)/2;   
  329.   var oz = -(cols*sz)/2;   
  330.   
  331.   for (y = 0;y < cols;y++) {   
  332.    for (x = 0;x < cols;x++) {   
  333.     var bv = ((x+y)&1) * 0.5;   
  334.     t = new RenderTriangle();   
  335.     t.texture = this.texture2;   
  336.   
  337.     t.poss[0] = new Vec3(ox + x*sz     , by, oz + y*sz     );   
  338.     t.poss[1] = new Vec3(ox + x*sz + sz, by, oz + y*sz     );   
  339.     t.poss[2] = new Vec3(ox + x*sz     , by, oz + y*sz + sz);   
  340.   
  341.     t.uvs[0]  = {u:0  , v:bv    };   
  342.     t.uvs[1]  = {u:0.5, v:bv    };   
  343.     t.uvs[2]  = {u:0  , v:bv+0.5};   
  344.   
  345.     if ((x==1 || x==2) && (y==1 || y==2))   
  346.      this.modifyRoofUV(t, x == 2, bv);   
  347.   
  348.     t.lighting = false;   
  349.     t.zBias = 0.5;   
  350.     this.mRenderTris.push(t);   
  351.   
  352.     t = new RenderTriangle();   
  353.     t.texture = this.texture2;   
  354.   
  355.     t.poss[0] = new Vec3(ox + x*sz     , by, oz + y*sz + sz);   
  356.     t.poss[1] = new Vec3(ox + x*sz + sz, by, oz + y*sz    );   
  357.     t.poss[2] = new Vec3(ox + x*sz + sz, by, oz + y*sz + sz);   
  358.   
  359.     t.uvs[0]  = {u:0  , v:bv+0.5};   
  360.     t.uvs[1]  = {u:0.5, v:bv    };   
  361.     t.uvs[2]  = {u:0.5, v:bv+0.5};   
  362.   
  363.     if ((x==1 || x==2) && (y==1 || y==2))   
  364.      this.modifyRoofUV(t, x == 2, bv);   
  365.   
  366.     t.lighting = false;   
  367.     t.zBias = 0.5;   
  368.     this.mRenderTris.push(t);   
  369.   
  370.    }   
  371.   }   
  372.  },   
  373.   
  374.  modifyRoofUV: function(t, rv, bv) {   
  375.   if (rv) {   
  376.    t.uvs[0].u = 0.5 - t.uvs[0].u;   
  377.    t.uvs[1].u = 0.5 - t.uvs[1].u;   
  378.    t.uvs[2].u = 0.5 - t.uvs[2].u;   
  379.   }   
  380.   
  381.   t.uvs[0].u += 0.5;   
  382.   t.uvs[1].u += 0.5;   
  383.   t.uvs[2].u += 0.5;   
  384.   
  385.   if (rv) {   
  386.    t.uvs[0].v = 0.5 - t.uvs[0].v + bv + bv;   
  387.    t.uvs[1].v = 0.5 - t.uvs[1].v + bv + bv;   
  388.    t.uvs[2].v = 0.5 - t.uvs[2].v + bv + bv;   
  389.   }   
  390.   
  391.  },   
  392.   
  393.  transformPolygons: function() {   
  394.   var trans = new M44();   
  395.   trans.mul(this.mViewMat, this.mProjMat);   
  396.   
  397.   var hw = this.mViewport.ow;   
  398.   var hh = this.mViewport.oh;   
  399.   
  400.   var len = this.mRenderTris.length;   
  401.   var t;   
  402.   var spos = [0, 0, 0, 0];   
  403.   for (var i = 0;i < len;i++) {   
  404.    t = this.mRenderTris[i];   
  405.    for (var k = 0;k < 3;k++) {   
  406.     trans.transVec3(spos, t.poss[k].x, t.poss[k].y, t.poss[k].z);   
  407.   
  408.     var W = spos[3];   
  409.     spos[0] /= W;   
  410.     spos[1] /= W;   
  411.     spos[2] /= W;   
  412.   
  413.     spos[0] *= this.mViewport.w;   
  414.     spos[1] *= -this.mViewport.h;   
  415.     spos[0] += hw;   
  416.     spos[1] += hh;   
  417.   
  418.     t.tposs[k].x = spos[0];   
  419.     t.tposs[k].y = spos[1];   
  420.     t.tposs[k].z = spos[2];   
  421.    }   
  422.   
  423.    var v1 = (new Vec3()).copyFrom(t.poss[1]).sub(t.poss[0]).normalize();   
  424.    var v2 = (new Vec3()).copyFrom(t.poss[2]).sub(t.poss[1]).normalize();   
  425.    var N = (new Vec3()).cp(v1, v2);   
  426.   
  427.    trans.transVec3Rot(spos, N.x, N.y, N.z);   
  428.   
  429.    if (t.lighting) {   
  430.     if (spos[2] > 0)   
  431.      t.shade = 0.8   
  432.     else {   
  433.      t.shade = 0.1 - N.y * 0.6;   
  434.      if (t.shade < 0) t.shade = 0;   
  435.     }   
  436.    }   
  437.   
  438.    t.sortKey = Math.floor( (t.tposs[0].z + t.tposs[1].z + t.tposs[2].z + t.zBias) *1000 );   
  439.   }   
  440.  }   
  441. }   
  442.   
  443. function ClothNode()   
  444. {   
  445.  this.flags = 0;   
  446.  this.pos  = new Vec3();   
  447.  this.velo = new Vec3();   
  448.  this.cv   = new Vec3();   
  449.  this.F    = new Vec3();   
  450.  this.links = [null, null, null, null];   
  451.  this.uv = {u:0, v:0};   
  452. }   
  453.   
  454. function RenderTriangle()   
  455. {   
  456.  this.texture = null;   
  457.  this.poss  = new Array(3);   
  458.  this.tposs = [new Vec3(), new Vec3(), new Vec3()];   
  459.  this.uvs = [{u:0, v:0}, {u:0, v:0}, {u:0, v:0}];   
  460.  this.shade = 0;   
  461.  this.lighting = true;   
  462.  this.zBias = 0;   
  463.   
  464.  this.sortKey = 0;   
  465. }   

以上就是HTML5 3D衣服摇摆动画特效的源码介绍,需要更为深入学习的下载源代码来研究。

3D衣服摇摆动画特效, 这又是一款基于HTML5 Canvas的3D动画杰作,它是一个可以随风飘动的3D衣服摇摆动画特效,非常逼真。当我们将鼠标...

 

前面的文章中提到了通过RTSP(Real Time Streaming Protocol)的方式来实现视频的直播,但RTSP方式的一个弊端是如果需要支持客户端通过网页来访问,就需要在在页面中嵌入一个ActiveX控件,而ActiveX一般都需要签名才能正常使用,否则用户在使用时还需要更改浏览器设置,并且ActiveX还只支持IE内核的浏览器,Chrome、FireFox需要IE插件才能运行,因此会特别影响用户体验。而RTMP(Real Time Messaging Protocol)很好的解决了这一个问题。由于RTMP是针对FLASH的流媒体协议,视频通过RTMP直播后,只需要在WEB上嵌入一个Web Player(如Jwplayer)即可观看,而且对平台也没什么限制,还可以方便的通过手机观看。

u16 g_summ = 0;

    本文是对nodejs0.8.9版本的api开发手册解读.nodejs网址

       视频通过RTMP方式发布需要一个RTMP Server(常见的有FMS、Wowza Media Server, 开源的有CRtmpServer、Red5等),原始视频只要按照RTMP协议发送给RTMP Server就可以RTMP视频流的发布了。为了便于视频的打包发布,封装了一个RTMPStream,目前只支持发送H264的视频文件。可以直接发送H264数据帧或H264文件,RTMPStream提供的接口如下。

u8 buf[2] = {0x10, 0x05};

   

 

g_summ = (buf[1] << 8) | buf[0]; // g_summ = 0x0510

    缓存类(Buffer)

[cpp] view plaincopy

2.

    stability:3 - Stable

 

u16 g_summ = 0x0510;

    纯javascript对Unicode支持不叫不错,但是对二进制数据的支持就不怎么样了,当需要处理TCP流或者文件系统时,是必须要处理八进制流(octet streams).Node有几种策略来操作,创建,销毁八进制值流.

 

buf[0] = g_summ; // buf[0] = 0x10

 

  1. class CRTMPStream    
  2. {    
  3. public:    
  4.     CRTMPStream(void);    
  5.     ~CRTMPStream(void);    
  6. public:    
  7.     // 连接到RTMP Server    
  8.     bool Connect(const char* url);    
  9.     // 断开连接    
  10.     void Close();    
  11.     // 发送MetaData    
  12.     bool SendMetadata(LPRTMPMetadata lpMetaData);    
  13.     // 发送H264数据帧    
  14.     bool SendH264Packet(unsigned char *data,unsigned int size,bool bIsKeyFrame,unsigned int nTimeStamp);    
  15.     // 发送H264文件    
  16.     bool SendH264File(const char *pFileName);    
  17. //...    
  18. }    

buf[1] = (g_summ >> 8);// buf[1] = 0x05

    原始数据被储存在buffer类的实例中,一个buffer很想一个integer的数组,但是符合一个在v8堆栈外的原始内存分配.一个buffer是不能被改变大小的.

调用示例:

 

[cpp] view plaincopy

    buffer类是全局的,尽量不要一有需要就使用require('buffer')加载.

 

 

 

    在buffers和javascript string对象之间转换需要显示的调用一个编码函数.下面是string类型不懂的编码格式:

  1. #include <stdio.h>    
  2. #include "RTMPStreamRTMPStream.h"    
  3.     
  4. int main(int argc,char* argv[])    
  5. {    
  6.     CRTMPStream rtmpSender;    
  7.     
  8.     bool bRet = rtmpSender.Connect("rtmp://192.168.1.104/live/test");    
  9.     
  10.     rtmpSender.SendH264File("E:\video\test.264");    
  11.     
  12.     rtmpSender.Close();    
  13. }    

'ascii' - for 7 bit ASCII data only. This encoding method is very fast, and will strip the high bit if set. Note that this encoding converts a null character ('' or 'u0026#39;) into 0x20 (character code of a space). If you want to convert a null character into 0x00, you should use 'utf8'.

通过JwPlayer播放效果如下:

 

 

'utf8' - Multibyte encoded Unicode characters. Many web pages and other document formats use UTF-8.多字节编码的Unicode字符.很多web页面和其他文档都使用UTF-8格式.

9159.com 2

 

最后附上RTMPStream完整的代码:

'utf16le' - 2 or 4 bytes, little endian encoded Unicode characters. Surrogate pairs (U+10000 to U+10FFFF) are supported.2个或者4个字节,小字节编码的Unicode字符.代理对的支持范围是10000~10FFFF.

 

 

[cpp] view plaincopy

'ucs2' - Alias of 'utf16le'.utf16le的别名

 

 

 

'base64' - Base64 string encoding.基于64的字符串编码.

  1. /********************************************************************  
  2. filename:   RTMPStream.h 
  3. created:    2013-04-3 
  4. author:     firehood  
  5. purpose:    发送H264视频到RTMP Server,使用libRtmp库 
  6. *********************************************************************/   
  7. #pragma once  
  8. #include "rtmp.h"  
  9. #include "rtmp_sys.h"  
  10. #include "amf.h"  
  11. #include <stdio.h>  
  12.   
  13. #define FILEBUFSIZE (1024 * 1024 * 10)       //  10M  
  14.   
  15. // NALU单元  
  16. typedef struct _NaluUnit  
  17. {  
  18.     int type;  
  19.     int size;  
  20.     unsigned char *data;  
  21. }NaluUnit;  
  22.   
  23. typedef struct _RTMPMetadata  
  24. {  
  25.     // video, must be h264 type  
  26.     unsigned int    nWidth;  
  27.     unsigned int    nHeight;  
  28.     unsigned int    nFrameRate;     // fps  
  29.     unsigned int    nVideoDataRate; // bps  
  30.     unsigned int    nSpsLen;  
  31.     unsigned char   Sps[1024];  
  32.     unsigned int    nPpsLen;  
  33.     unsigned char   Pps[9159.com ,1024];  
  34.   
  35.     // audio, must be aac type  
  36.     bool            bHasAudio;  
  37.     unsigned int    nAudioSampleRate;  
  38.     unsigned int    nAudioSampleSize;  
  39.     unsigned int    nAudioChannels;  
  40.     char            pAudioSpecCfg;  
  41.     unsigned int    nAudioSpecCfgLen;  
  42.   
  43. } RTMPMetadata,*LPRTMPMetadata;  
  44.   
  45.   
  46. class CRTMPStream  
  47. {  
  48. public:  
  49.     CRTMPStream(void);  
  50.     ~CRTMPStream(void);  
  51. public:  
  52.     // 连接到RTMP Server  
  53.     bool Connect(const char* url);  
  54.     // 断开连接  
  55.     void Close();  
  56.     // 发送MetaData  
  57.     bool SendMetadata(LPRTMPMetadata lpMetaData);  
  58.     // 发送H264数据帧  
  59.     bool SendH264Packet(unsigned char *data,unsigned int size,bool bIsKeyFrame,unsigned int nTimeStamp);  
  60.     // 发送H264文件  
  61.     bool SendH264File(const char *pFileName);  
  62. private:  
  63.     // 送缓存中读取一个NALU包  
  64.     bool ReadOneNaluFromBuf(NaluUnit &nalu);  
  65.     // 发送数据  
  66.     int SendPacket(unsigned int nPacketType,unsigned char *data,unsigned int size,unsigned int nTimestamp);  
  67. private:  
  68.     RTMP* m_pRtmp;  
  69.     unsigned char* m_pFileBuf;  
  70.     unsigned int  m_nFileBufSize;  
  71.     unsigned int  m_nCurPos;  
  72. };  

 

[cpp] view plaincopy

'binary' - A way of encoding raw binary data into strings by using only the first 8 bits of each character. This encoding method is deprecated and should be avoided in favor of Buffer objects where possible. This encoding will be removed in future versions of Node.一种仅使用每个字符的前8个字节把原始二进制数据编码成strings.这个方法已经过时,应该避免在使用buffer对象时使用,这种编码将会来未来的node版本中被移除.

 

 

 

'hex' - Encode each byte as two hexadecimal characters.将每一个字节编码称两个16进制字符.

  1. /********************************************************************  
  2. filename:   RTMPStream.cpp 
  3. created:    2013-04-3 
  4. author:     firehood  
  5. purpose:    发送H264视频到RTMP Server,使用libRtmp库 
  6. *********************************************************************/   
  7. #include "RTMPStream.h"  
  8. #include "SpsDecode.h"  
  9. #ifdef WIN32    
  10. #include <windows.h>  
  11. #endif  
  12.   
  13. #ifdef WIN32  
  14. #pragma comment(lib,"WS2_32.lib")  
  15. #pragma comment(lib,"winmm.lib")  
  16. #endif  
  17.   
  18. enum  
  19. {  
  20.     FLV_CODECID_H264 = 7,  
  21. };  
  22.   
  23. int InitSockets()    
  24. {    
  25. #ifdef WIN32    
  26.     WORD version;    
  27.     WSADATA wsaData;    
  28.     version = MAKEWORD(1, 1);    
  29.     return (WSAStartup(version, &wsaData) == 0);    
  30. #else    
  31.     return TRUE;    
  32. #endif    
  33. }    
  34.   
  35. inline void CleanupSockets()    
  36. {    
  37. #ifdef WIN32    
  38.     WSACleanup();    
  39. #endif    
  40. }    
  41.   
  42. char * put_byte( char *output, uint8_t nVal )    
  43. {    
  44.     output[0] = nVal;    
  45.     return output+1;    
  46. }    
  47. char * put_be16(char *output, uint16_t nVal )    
  48. {    
  49.     output[1] = nVal & 0xff;    
  50.     output[0] = nVal >> 8;    
  51.     return output+2;    
  52. }    
  53. char * put_be24(char *output,uint32_t nVal )    
  54. {    
  55.     output[2] = nVal & 0xff;    
  56.     output[1] = nVal >> 8;    
  57.     output[0] = nVal >> 16;    
  58.     return output+3;    
  59. }    
  60. char * put_be32(char *output, uint32_t nVal )    
  61. {    
  62.     output[3] = nVal & 0xff;    
  63.     output[2] = nVal >> 8;    
  64.     output[1] = nVal >> 16;    
  65.     output[0] = nVal >> 24;    
  66.     return output+4;    
  67. }    
  68. char *  put_be64( char *output, uint64_t nVal )    
  69. {    
  70.     output=put_be32( output, nVal >> 32 );    
  71.     output=put_be32( output, nVal );    
  72.     return output;    
  73. }    
  74. char * put_amf_string( char *c, const char *str )    
  75. {    
  76.     uint16_t len = strlen( str );    
  77.     c=put_be16( c, len );    
  78.     memcpy(c,str,len);    
  79.     return c+len;    
  80. }    
  81. char * put_amf_double( char *c, double d )    
  82. {    
  83.     *c++ = AMF_NUMBER;  /* type: Number */    
  84.     {    
  85.         unsigned char *ci, *co;    
  86.         ci = (unsigned char *)&d;    
  87.         co = (unsigned char *)c;    
  88.         co[0] = ci[7];    
  89.         co[1] = ci[6];    
  90.         co[2] = ci[5];    
  91.         co[3] = ci[4];    
  92.         co[4] = ci[3];    
  93.         co[5] = ci[2];    
  94.         co[6] = ci[1];    
  95.         co[7] = ci[0];    
  96.     }    
  97.     return c+8;    
  98. }  
  99.   
  100. CRTMPStream::CRTMPStream(void):  
  101. m_pRtmp(NULL),  
  102. m_nFileBufSize(0),  
  103. m_nCurPos(0)  
  104. {  
  105.     m_pFileBuf = new unsigned char[FILEBUFSIZE];  
  106.     memset(m_pFileBuf,0,FILEBUFSIZE);  
  107.     InitSockets();  
  108.     m_pRtmp = RTMP_Alloc();    
  109.     RTMP_Init(m_pRtmp);    
  110. }  
  111.   
  112. CRTMPStream::~CRTMPStream(void)  
  113. {  
  114.     Close();  
  115.     WSACleanup();    
  116.     delete[] m_pFileBuf;  
  117. }  
  118.   
  119. bool CRTMPStream::Connect(const char* url)  
  120. {  
  121.     if(RTMP_SetupURL(m_pRtmp, (char*)url)<0)  
  122.     {  
  123.         return FALSE;  
  124.     }  
  125.     RTMP_EnableWrite(m_pRtmp);  
  126.     if(RTMP_Connect(m_pRtmp, NULL)<0)  
  127.     {  
  128.         return FALSE;  
  129.     }  
  130.     if(RTMP_ConnectStream(m_pRtmp,0)<0)  
  131.     {  
  132.         return FALSE;  
  133.     }  
  134.     return TRUE;  
  135. }  
  136.   
  137. void CRTMPStream::Close()  
  138. {  
  139.     if(m_pRtmp)  
  140.     {  
  141.         RTMP_Close(m_pRtmp);  
  142.         RTMP_Free(m_pRtmp);  
  143.         m_pRtmp = NULL;  
  144.     }  
  145. }  
  146.   
  147. int CRTMPStream::SendPacket(unsigned int nPacketType,unsigned char *data,unsigned int size,unsigned int nTimestamp)  
  148. {  
  149.     if(m_pRtmp == NULL)  
  150.     {  
  151.         return FALSE;  
  152.     }  
  153.   
  154.     RTMPPacket packet;  
  155.     RTMPPacket_Reset(&packet);  
  156.     RTMPPacket_Alloc(&packet,size);  
  157.   
  158.     packet.m_packetType = nPacketType;  
  159.     packet.m_nChannel = 0x04;    
  160.     packet.m_headerType = RTMP_PACKET_SIZE_LARGE;    
  161.     packet.m_nTimeStamp = nTimestamp;    
  162.     packet.m_nInfoField2 = m_pRtmp->m_stream_id;  
  163.     packet.m_nBodySize = size;  
  164.     memcpy(packet.m_body,data,size);  
  165.   
  166.     int nRet = RTMP_SendPacket(m_pRtmp,&packet,0);  
  167.   
  168.     RTMPPacket_Free(&packet);  
  169.   
  170.     return nRet;  
  171. }  
  172.   
  173. bool CRTMPStream::SendMetadata(LPRTMPMetadata lpMetaData)  
  174. {  
  175.     if(lpMetaData == NULL)  
  176.     {  
  177.         return false;  
  178.     }  
  179.     char body[1024] = {0};;  
  180.       
  181.     char * p = (char *)body;    
  182.     p = put_byte(p, AMF_STRING );  
  183.     p = put_amf_string(p , "@setDataFrame" );  
  184.   
  185.     p = put_byte( p, AMF_STRING );  
  186.     p = put_amf_string( p, "onMetaData" );  
  187.   
  188.     p = put_byte(p, AMF_OBJECT );    
  189.     p = put_amf_string( p, "copyright" );    
  190.     p = put_byte(p, AMF_STRING );    
  191.     p = put_amf_string( p, "firehood" );    
  192.   
  193.     p =put_amf_string( p, "width");  
  194.     p =put_amf_double( p, lpMetaData->nWidth);  
  195.   
  196.     p =put_amf_string( p, "height");  
  197.     p =put_amf_double( p, lpMetaData->nHeight);  
  198.   
  199.     p =put_amf_string( p, "framerate" );  
  200.     p =put_amf_double( p, lpMetaData->nFrameRate);   
  201.   
  202.     p =put_amf_string( p, "videocodecid" );  
  203.     p =put_amf_double( p, FLV_CODECID_H264 );  
  204.   
  205.     p =put_amf_string( p, "" );  
  206.     p =put_byte( p, AMF_OBJECT_END  );  
  207.   
  208.     int index = p-body;  
  209.   
  210.     SendPacket(RTMP_PACKET_TYPE_INFO,(unsigned char*)body,p-body,0);  
  211.   
  212.     int i = 0;  
  213.     body[i++] = 0x17; // 1:keyframe  7:AVC  
  214.     body[i++] = 0x00; // AVC sequence header  
  215.   
  216.     body[i++] = 0x00;  
  217.     body[i++] = 0x00;  
  218.     body[i++] = 0x00; // fill in 0;  
  219.   
  220.     // AVCDecoderConfigurationRecord.  
  221.     body[i++] = 0x01; // configurationVersion  
  222.     body[i++] = lpMetaData->Sps[1]; // AVCProfileIndication  
  223.     body[i++] = lpMetaData->Sps[2]; // profile_compatibility  
  224.     body[i++] = lpMetaData->Sps[3]; // AVCLevelIndication   
  225.     body[i++] = 0xff; // lengthSizeMinusOne    
  226.   
  227.     // sps nums  
  228.     body[i++] = 0xE1; //&0x1f  
  229.     // sps data length  
  230.     body[i++] = lpMetaData->nSpsLen>>8;  
  231.     body[i++] = lpMetaData->nSpsLen&0xff;  
  232.     // sps data  
  233.     memcpy(&body[i],lpMetaData->Sps,lpMetaData->nSpsLen);  
  234.     i= i+lpMetaData->nSpsLen;  
  235.   
  236.     // pps nums  
  237.     body[i++] = 0x01; //&0x1f  
  238.     // pps data length   
  239.     body[i++] = lpMetaData->nPpsLen>>8;  
  240.     body[i++] = lpMetaData->nPpsLen&0xff;  
  241.     // sps data  
  242.     memcpy(&body[i],lpMetaData->Pps,lpMetaData->nPpsLen);  
  243.     i= i+lpMetaData->nPpsLen;  
  244.   
  245.     return SendPacket(RTMP_PACKET_TYPE_VIDEO,(unsigned char*)body,i,0);  
  246.   
  247. }  
  248.   
  249. bool CRTMPStream::SendH264Packet(unsigned char *data,unsigned int size,bool bIsKeyFrame,unsigned int nTimeStamp)  
  250. {  
  251.     if(data == NULL && size<11)  
  252.     {  
  253.         return false;  
  254.     }  
  255.   
  256.     unsigned char *body = new unsigned char[size+9];  
  257.   
  258.     int i = 0;  
  259.     if(bIsKeyFrame)  
  260.     {  
  261.         body[i++] = 0x17;// 1:Iframe  7:AVC  
  262.     }  
  263.     else  
  264.     {  
  265.         body[i++] = 0x27;// 2:Pframe  7:AVC  
  266.     }  
  267.     body[i++] = 0x01;// AVC NALU  
  268.     body[i++] = 0x00;  
  269.     body[i++] = 0x00;  
  270.     body[i++] = 0x00;  
  271.   
  272.     // NALU size  
  273.     body[i++] = size>>24;  
  274.     body[i++] = size>>16;  
  275.     body[i++] = size>>8;  
  276.     body[i++] = size&0xff;;  
  277.   
  278.     // NALU data  
  279.     memcpy(&body[i],data,size);  
  280.   
  281.     bool bRet = SendPacket(RTMP_PACKET_TYPE_VIDEO,body,i+size,nTimeStamp);  
  282.   
  283.     delete[] body;  
  284.   
  285.     return bRet;  
  286. }  
  287.   
  288. bool CRTMPStream::SendH264File(const char *pFileName)  
  289. {  
  290.     if(pFileName == NULL)  
  291.     {  
  292.         return FALSE;  
  293.     }  
  294.     FILE *fp = fopen(pFileName, "rb");    
  295.     if(!fp)    
  296.     {    
  297.         printf("ERROR:open file %s failed!",pFileName);  
  298.     }    
  299.     fseek(fp, 0, SEEK_SET);  
  300.     m_nFileBufSize = fread(m_pFileBuf, sizeof(unsigned char), FILEBUFSIZE, fp);  
  301.     if(m_nFileBufSize >= FILEBUFSIZE)  
  302.     {  
  303.         printf("warning : File size is larger than BUFSIZEn");  
  304.     }  
  305.     fclose(fp);    
  306.   
  307.     RTMPMetadata metaData;  
  308.     memset(&metaData,0,sizeof(RTMPMetadata));  
  309.   
  310.     NaluUnit naluUnit;  
  311.     // 读取SPS帧  
  312.     ReadOneNaluFromBuf(naluUnit);  
  313.     metaData.nSpsLen = naluUnit.size;  
  314.     memcpy(metaData.Sps,naluUnit.data,naluUnit.size);  
  315.   
  316.     // 读取PPS帧  
  317.     ReadOneNaluFromBuf(naluUnit);  
  318.     metaData.nPpsLen = naluUnit.size;  
  319.     memcpy(metaData.Pps,naluUnit.data,naluUnit.size);  
  320.   
  321.     // 解码SPS,获取视频图像宽、高信息  
  322.     int width = 0,height = 0;  
  323.     h264_decode_sps(metaData.Sps,metaData.nSpsLen,width,height);  
  324.     metaData.nWidth = width;  
  325.     metaData.nHeight = height;  
  326.     metaData.nFrameRate = 25;  
  327.      
  328.     // 发送MetaData  
  329.     SendMetadata(&metaData);  
  330.   
  331.     unsigned int tick = 0;  
  332.     while(ReadOneNaluFromBuf(naluUnit))  
  333.     {  
  334.         bool bKeyframe  = (naluUnit.type == 0x05) ? TRUE : FALSE;  
  335.         // 发送H264数据帧  
  336.         SendH264Packet(naluUnit.data,naluUnit.size,bKeyframe,tick);  
  337.         msleep(40);  
  338.         tick +=40;  
  339.     }  
  340.   
  341.     return TRUE;  
  342. }  
  343.   
  344. bool CRTMPStream::ReadOneNaluFromBuf(NaluUnit &nalu)  
  345. {  
  346.     int i = m_nCurPos;  
  347.     while(i<m_nFileBufSize)  
  348.     {  
  349.         if(m_pFileBuf[i++] == 0x00 &&  
  350.             m_pFileBuf[i++] == 0x00 &&  
  351.             m_pFileBuf[i++] == 0x00 &&  
  352.             m_pFileBuf[i++] == 0x01  
  353.             )  
  354.         {  
  355.             int pos = i;  
  356.             while (pos<m_nFileBufSize)  
  357.             {  
  358.                 if(m_pFileBuf[pos++] == 0x00 &&  
  359.                     m_pFileBuf[pos++] == 0x00 &&  
  360.                     m_pFileBuf[pos++] == 0x00 &&  
  361.                     m_pFileBuf[pos++] == 0x01  
  362.                     )  
  363.                 {  
  364.                     break;  
  365.                 }  
  366.             }  
  367.             if(pos == nBufferSize)  
  368.             {  
  369.                 nalu.size = pos-i;    
  370.             }  
  371.             else  
  372.             {  
  373.                 nalu.size = (pos-4)-i;  
  374.             }  
  375.             nalu.type = m_pFileBuf[i]&0x1f;  
  376.             nalu.data = &m_pFileBuf[i];  
  377.   
  378.             m_nCurPos = pos-4;  
  379.             return TRUE;  
  380.         }  
  381.     }  
  382.     return FALSE;  
  383. }  

 

附上SpsDecode.h文件:

    Class:Buffer
    Buffer类是一个直接处理二进制数据的全局类型.它可以通过多重方法被构造.

 

    new Buffer(size)   
size number,一个表示大小的数字.
    分配一个新的buffer,size个八位字节(octets).

[cpp] view plaincopy

    new Buffer(array)   
array Array,一个数组.
    使用一个octets的array数组来分配一个新的buffer.

 

    new Buffer(str,[encoding])   
str String,需要编码的字符串.
encoding String,需要使用的编码格式,可选.
    分配一个新的buffer,包含给定的str,encoding默认为"utf8".

 

    buf.write(string,[offset],[length],[encoding])   
str String,被写入buffer的数据.
offet number,可选,默认0.数据写入到buffer的位置.
length Number,可选,默认:buffer.length - offset,要写入数据的长度
encoding String,需要使用的编码格式,可选,默认为"utf8".
    将string使用指定的encoding写入到buffer的offset处.offset默认是0,encomding默认是'utf8',length是将要写入的字节长度.返回写入了多少个八进制字节.如果Buffer没有足够的空间来适应整个string,那么将只有string的部分被写入.length默认是buffer.length

  1. #include <stdio.h>  
  2. #include <math.h>  
  3.   
  4. UINT Ue(BYTE *pBuff, UINT nLen, UINT &nStartBit)  
  5. {  
  6.     //计算0bit的个数  
  7.     UINT nZeroNum = 0;  
  8.     while (nStartBit < nLen * 8)  
  9.     {  
  10.         if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8))) //&:按位与,%取余  
  11.         {  
  12.             break;  
  13.         }  
  14.         nZeroNum++;  
  15.         nStartBit++;  
  16.     }  
  17.     nStartBit ++;  
  18.   
  19.   
  20.     //计算结果  
  21.     DWORD dwRet = 0;  
  22.     for (UINT i=0; i<nZeroNum; i++)  
  23.     {  
  24.         dwRet <<= 1;  
  25.         if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8)))  
  26.         {  
  27.             dwRet += 1;  
  28.         }  
  29.         nStartBit++;  
  30.     }  
  31.     return (1 << nZeroNum) - 1 + dwRet;  
  32. }  
  33.   
  34.   
  35. int Se(BYTE *pBuff, UINT nLen, UINT &nStartBit)  
  36. {  
  37.     int UeVal=Ue(pBuff,nLen,nStartBit);  
  38.     double k=UeVal;  
  39.     int nValue=ceil(k/2);//ceil函数:ceil函数的作用是求不小于给定实数的最小整数。ceil(2)=ceil(1.2)=cei(1.5)=2.00  
  40.     if (UeVal % 2==0)  
  41.         nValue=-nValue;  
  42.     return nValue;  
  43. }  
  44.   
  45.   
  46. DWORD u(UINT BitCount,BYTE * buf,UINT &nStartBit)  
  47. {  
  48.     DWORD dwRet = 0;  
  49.     for (UINT i=0; i<BitCount; i++)  
  50.     {  
  51.         dwRet <<= 1;  
  52.         if (buf[nStartBit / 8] & (0x80 >> (nStartBit % 8)))  
  53.         {  
  54.             dwRet += 1;  
  55.         }  
  56.         nStartBit++;  
  57.     }  
  58.     return dwRet;  
  59. }  
  60.   
  61.   
  62. bool h264_decode_sps(BYTE * buf,unsigned int nLen,int &width,int &height)  
  63. {  
  64.     UINT StartBit=0;   
  65.     int forbidden_zero_bit=u(1,buf,StartBit);  
  66.     int nal_ref_idc=u(2,buf,StartBit);  
  67.     int nal_unit_type=u(5,buf,StartBit);  
  68.     if(nal_unit_type==7)  
  69.     {  
  70.         int profile_idc=u(8,buf,StartBit);  
  71.         int constraint_set0_flag=u(1,buf,StartBit);//(buf[1] & 0x80)>>7;  
  72.         int constraint_set1_flag=u(1,buf,StartBit);//(buf[1] & 0x40)>>6;  
  73.         int constraint_set2_flag=u(1,buf,StartBit);//(buf[1] & 0x20)>>5;  
  74.         int constraint_set3_flag=u(1,buf,StartBit);//(buf[1] & 0x10)>>4;  
  75.         int reserved_zero_4bits=u(4,buf,StartBit);  
  76.         int level_idc=u(8,buf,StartBit);  
  77.   
  78.         int seq_parameter_set_id=Ue(buf,nLen,StartBit);  
  79.   
  80.         if( profile_idc == 100 || profile_idc == 110 ||  
  81.             profile_idc == 122 || profile_idc == 144 )  
  82.         {  
  83.             int chroma_format_idc=Ue(buf,nLen,StartBit);  
  84.             if( chroma_format_idc == 3 )  
  85.                 int residual_colour_transform_flag=u(1,buf,StartBit);  
  86.             int bit_depth_luma_minus8=Ue(buf,nLen,StartBit);  
  87.             int bit_depth_chroma_minus8=Ue(buf,nLen,StartBit);  
  88.             int qpprime_y_zero_transform_bypass_flag=u(1,buf,StartBit);  
  89.             int seq_scaling_matrix_present_flag=u(1,buf,StartBit);  
  90.   
  91.             int seq_scaling_list_present_flag[8];  
  92.             if( seq_scaling_matrix_present_flag )  
  93.             {  
  94.                 for( int i = 0; i < 8; i++ ) {  
  95.                     seq_scaling_list_present_flag[i]=u(1,buf,StartBit);  
  96.                 }  
  97.             }  
  98.         }  
  99.         int log2_max_frame_num_minus4=Ue(buf,nLen,StartBit);  
  100.         int pic_order_cnt_type=Ue(buf,nLen,StartBit);  
  101.         if( pic_order_cnt_type == 0 )  
  102.             int log2_max_pic_order_cnt_lsb_minus4=Ue(buf,nLen,StartBit);  
  103.         else if( pic_order_cnt_type == 1 )  
  104.         {  
  105.             int delta_pic_order_always_zero_flag=u(1,buf,StartBit);  
  106.             int offset_for_non_ref_pic=Se(buf,nLen,StartBit);  
  107.             int offset_for_top_to_bottom_field=Se(buf,nLen,StartBit);  
  108.             int num_ref_frames_in_pic_order_cnt_cycle=Ue(buf,nLen,StartBit);  
  109.   
  110.             int *offset_for_ref_frame=new int[num_ref_frames_in_pic_order_cnt_cycle];  
  111.             for( int i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )  
  112.                 offset_for_ref_frame[i]=Se(buf,nLen,StartBit);  
  113.             delete [] offset_for_ref_frame;  
  114.         }  
  115.         int num_ref_frames=Ue(buf,nLen,StartBit);  
  116.         int gaps_in_frame_num_value_allowed_flag=u(1,buf,StartBit);  
  117.         int pic_width_in_mbs_minus1=Ue(buf,nLen,StartBit);  
  118.         int pic_height_in_map_units_minus1=Ue(buf,nLen,StartBit);  
  119.   
  120.         width=(pic_width_in_mbs_minus1+1)*16;  
  121.         height=(pic_height_in_map_units_minus1+1)*16;  
  122.   
  123.         return true;  
  124.     }  
  125.     else  
  126.         return false;  
  127. }  
  128.   
  • offset.这个方法不会写入不完整的字符.[javascript] view plaincopyprint?
    <SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">buf = new Buffer(256); 
    len = buf.write('u00bd + u00bc = u00be', 0); 
    console.log(len + " bytes: " + buf.toString('utf8', 0, len));</SPAN> 

buf = new Buffer(256);
len = buf.write('u00bd + u00bc = u00be', 0);
console.log(len + " bytes: " + buf.toString('utf8', 0, len));    写入的字符个数(可能和写入的字节数不一样)被保存在Buffer._charWritten变量中,并且将会在下次调用buf.writer()时被覆盖.

    buf.toString([encoding],[start],[end])
encoding String,optional,default:'uft8' .字符串,可选,默认:'utf8'
start Number ,optional,default:0.数字,可选,默认:0.
end Number,optional,default:buffer.length.数字,可选,默认:buffer.length
    解码buffer中的数据,并且返回一个字符串,使用encoding(默认:'utf8')编码,在start开始,在end结束.
    见上面的buffer.write()例子.

    buf[index]

    设置和获取在index位置的八进制字节.这个值索引了一个实体bytes,所以这个合法的范围是)0x00到0xff或者0到255.
    例子:copy一个ASCII字符串到buffer中,一次一个字节:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">str = "node.js"; 
buf = new Buffer(str.length); 
 
for (var i = 0; i < str.length ; i++) { 
  buf[i] = str.charCodeAt(i); 

 
console.log(buf); 
 
// node.js</SPAN> 

str = "node.js";
buf = new Buffer(str.length);

for (var i = 0; i < str.length ; i++) {
  buf[i] = str.charCodeAt(i);
}

console.log(buf);

// node.js

    Class Method:Buffer.isBuffer(obj)
obj Object 一个对象
Return: Boolean 返回布尔值
    测试obj是否是一个Buffer类.

    Class Method:Buffer.isBuffer(obj)
string String 一个字符串
encoding String, Optional, Default: 'utf8' 编码,可选,默认'utf8'
Return: Number 返回一个数字
    给出一个字符串的实际的字节长度.encoding默认:'utf8'.这个方法和string.prototype.length不同,后者返回一个字符串中字符的个数.
    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">str = 'u00bd + u00bc = u00be'; 
 
console.log(str + ": " + str.length + " characters, " + 
  Buffer.byteLength(str, 'utf8') + " bytes"); 
 
// ½ + ¼ = ¾: 9 characters, 12 bytes</SPAN> 

str = 'u00bd + u00bc = u00be';

console.log(str + ": " + str.length + " characters, " +
  Buffer.byteLength(str, 'utf8') + " bytes");

// ½ + ¼ = ¾: 9 characters, 12 bytes

    Class Method:Buffer.concat(list,[totalLength])

list Array List of Buffer objects to concat 一个数组,需要连接的buffer对象的一个数组.
totalLength Number Total length of the buffers when concatenated 这个连接后的beffer对象的总长度.
    返回一个连接了整个list的buffer对象.
    如果list中没有条目,或者totallength是0,那么将返回一个0长度的buffer.
    如果List中只有一个条目,那么list中的这个条目将被直接返回.
    如果list中多于一个条目,那么一个衅新的Buffer将会被创建.
    如果totalLength没有被提供,将会从list中的buffer对象中读取.然而这将会增加一个额外的循环到这个方法,所以明确的提供长度有更高的效率.

   buf.length
Number数字
    这个buf的字节大小.注意:这不一定是buf中保存的内容的大小.length索引的是buffer对象的分配内存的总大小.当buf的content改变时length不会变.[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">buf = new Buffer(1234); 
 
console.log(buf.length); 
buf.write("some string", 0, "ascii"); 
console.log(buf.length); 
 
// 1234  
// 1234</SPAN> 

buf = new Buffer(1234);

console.log(buf.length);
buf.write("some string", 0, "ascii");
console.log(buf.length);

// 1234
// 1234

   buf.copy(targetBuffer,[targetStart],[sourceStart],[sourceEnd])
targetBuffer Buffer object - Buffer to copy into 复制的目标buffer对象
targetStart Number, Optional, Default: 0 在目标buffer的哪个位置开始写入
sourceStart Number, Optional, Default: 0在原buffer的哪个位置开始读取
sourceEnd Number, Optional, Default: buffer.length原buffer读取到哪里结束.
    在两个buffer对象之间做copy工作.原区域和目标区域可以重叠.targetStart和sourceStart默认是0,sourceEnd默认是原buffer的大小.
    例子:创建两个buffer,然后copy buf1中的字节16到字节19的区域到buf2,buf2从第八个字节开始写入.[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">buf1 = new Buffer(26); 
buf2 = new Buffer(26); 
 
for (var i = 0 ; i < 26 ; i++) { 
  buf1[i] = i + 97; // 97 is ASCII a  
  buf2[i] = 33; // ASCII !  

 
buf1.copy(buf2, 8, 16, 20); 
console.log(buf2.toString('ascii', 0, 25)); 
 
// !!!!!!!!qrst!!!!!!!!!!!!!</SPAN> 

buf1 = new Buffer(26);
buf2 = new Buffer(26);

for (var i = 0 ; i < 26 ; i++) {
  buf1[i] = i + 97; // 97 is ASCII a
  buf2[i] = 33; // ASCII !
}

buf1.copy(buf2, 8, 16, 20);
console.log(buf2.toString('ascii', 0, 25));

// !!!!!!!!qrst!!!!!!!!!!!!!

   buf.slice([start],[end])

start Number, Optional, Default: 0 开始位置,默认0
end Number, Optional, Default: buffer.length 结束位置,默认buffer大小.
    返回一个新的buffer对象,这个新buffer和老buffer公用一个内存.但是被start和end索引偏移缩减了.(比如,一个buffer里有1到10个字节,我们只想要4-8个字节,就可以用这个函数buf.slice(4,8),因为他们共用一个内存,所以不会消耗内存,)
    修改新的buffer,老buffer的内容同样也会被修改,(因为共用内存嘛).
    例子:用ASCII码字母表创建一个buffer,用一下slice函数,然后修改原buffer中的一个字节.[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf1 = new Buffer(26); 
 
for (var i = 0 ; i < 26 ; i++) { 
  buf1[i] = i + 97; // 97 is ASCII a  

 
var buf2 = buf1.slice(0, 3); 
console.log(buf2.toString('ascii', 0, buf2.length)); 
buf1[0] = 33; 
console.log(buf2.toString('ascii', 0, buf2.length)); 
 
// abc  
// !bc</SPAN> 

var buf1 = new Buffer(26);

for (var i = 0 ; i < 26 ; i++) {
  buf1[i] = i + 97; // 97 is ASCII a
}

var buf2 = buf1.slice(0, 3);
console.log(buf2.toString('ascii', 0, buf2.length));
buf1[0] = 33;
console.log(buf2.toString('ascii', 0, buf2.length));

// abc
// !bc

   buf.rendUInt8(offset,[noAssert])

offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
Return: Number 返回数字
    在buffer的指定offset处返回一个无符号的8bit integer类型.
    设置noAssert为true,来忽略对offset的验证.这意味着offset可以超过buffer的边界.默认为false.
    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(4); 
 
buf[0] = 0x3; 
buf[1] = 0x4; 
buf[2] = 0x23; 
buf[3] = 0x42; 
 
for (ii = 0; ii < buf.length; ii++) { 
  console.log(buf.readUInt8(ii)); 

 
// 0x3  
// 0x4  
// 0x23  
// 0x42</SPAN> 

var buf = new Buffer(4);

buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;

for (ii = 0; ii < buf.length; ii++) {
  console.log(buf.readUInt8(ii));
}

// 0x3
// 0x4
// 0x23
// 0x42

   buf.rendUInt16LE(offset,[noAssert])

   buf.rendUInt16BE(offset,[noAssert])

offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
Return: Number 返回数字
    在buffer的offset处使用指定的字节序列(le和be)返回一个无符号16bit的integer.
    设置noAssert为true,来忽略对offset的验证.这意味着offset可以超过buffer的边界.默认为false.

    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(4); 
 
buf[0] = 0x3; 
buf[1] = 0x4; 
buf[2] = 0x23; 
buf[3] = 0x42; 
 
console.log(buf.readUInt16BE(0)); 
console.log(buf.readUInt16LE(0)); 
console.log(buf.readUInt16BE(1)); 
console.log(buf.readUInt16LE(1)); 
console.log(buf.readUInt16BE(2)); 
console.log(buf.readUInt16LE(2)); 
 
// 0x0304  
// 0x0403  
// 0x0423  
// 0x2304  
// 0x2342  
// 0x4223</SPAN> 

var buf = new Buffer(4);

buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;

console.log(buf.readUInt16BE(0));
console.log(buf.readUInt16LE(0));
console.log(buf.readUInt16BE(1));
console.log(buf.readUInt16LE(1));
console.log(buf.readUInt16BE(2));
console.log(buf.readUInt16LE(2));

// 0x0304
// 0x0403
// 0x0423
// 0x2304
// 0x2342
// 0x4223

   buf.rendUInt32LE(offset,[noAssert])

   buf.rendUInt32BE(offset,[noAssert])

offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
Return: Number 返回数字
    在buffer的offset处使用指定的字节序列(le和be)返回一个无符号32bit的integer.
    设置noAssert为true,来忽略对offset的验证.这意味着offset可以超过buffer的边界.默认为false.

    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(4); 
 
buf[0] = 0x3; 
buf[1] = 0x4; 
buf[2] = 0x23; 
buf[3] = 0x42; 
 
console.log(buf.readUInt32BE(0)); 
console.log(buf.readUInt32LE(0)); 
 
// 0x03042342  
// 0x42230403</SPAN> 

var buf = new Buffer(4);

buf[0] = 0x3;
buf[1] = 0x4;
buf[2] = 0x23;
buf[3] = 0x42;

console.log(buf.readUInt32BE(0));
console.log(buf.readUInt32LE(0));

// 0x03042342
// 0x42230403

   buf.rendInt8(offset,[noAssert])
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
Return: Number 返回数字
    在buffer的offset处返回一个有符号8bit的integer.
    设置noAssert为true,来忽略对offset的验证.这意味着offset可以超过buffer的边界.默认为false.

    除了buffer的内容被看作是有正负符号的值之外,和buffer.readUInt8一样的功能.

   buf.rendInt16LE(offset,[noAssert])

   buf.rendInt16BE(offset,[noAssert])

offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
Return: Number 返回数字
    在buffer的offset处使用指定的字节序列(le和be)返回一个有符号16bit的integer.
    设置noAssert为true,来忽略对offset的验证.这意味着offset可以超过buffer的边界.默认为false.

    除了buffer的内容被看作是有正负符号的值之外,和buffer.readUInt16*一样的功能.

   buf.rendInt32LE(offset,[noAssert])

   buf.rendInt32BE(offset,[noAssert])

offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
Return: Number 返回数字
    在buffer的offset处使用指定的字节序列(le和be)返回一个有符号32bit的integer.
    设置noAssert为true,来忽略对offset的验证.这意味着offset可以超过buffer的边界.默认为false.

    除了buffer的内容被看作是有正负符号的值之外,和buffer.readUInt32*一样的功能.

   buf.rendFloatLE(offset,[noAssert])

   buf.rendFloatBE(offset,[noAssert])

offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
Return: Number 返回数字
    在buffer的offset处使用指定的字节序列(le和be)返回一个有符号32bit的float.
    设置noAssert为true,来忽略对offset的验证.这意味着offset可以超过buffer的边界.默认为false.

    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(4); 
 
buf[0] = 0x00; 
buf[1] = 0x00; 
buf[2] = 0x80; 
buf[3] = 0x3f; 
 
console.log(buf.readFloatLE(0)); 
 
// 0x01</SPAN> 

var buf = new Buffer(4);

buf[0] = 0x00;
buf[1] = 0x00;
buf[2] = 0x80;
buf[3] = 0x3f;

console.log(buf.readFloatLE(0));

// 0x01

   buf.rendDoubleLE(offset,[noAssert])

   buf.rendDoubleBE(offset,[noAssert])

offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
Return: Number 返回数字
    在buffer的offset处使用指定的字节序列(le和be)返回一个有符号64bit的double.
    设置noAssert为true,来忽略对offset的验证.这意味着offset可以超过buffer的边界.默认为false.

    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(8); 
 
buf[0] = 0x55; 
buf[1] = 0x55; 
buf[2] = 0x55; 
buf[3] = 0x55; 
buf[4] = 0x55; 
buf[5] = 0x55; 
buf[6] = 0xd5; 
buf[7] = 0x3f; 
 
console.log(buf.readDoubleLE(0)); 
 
// 0.3333333333333333</SPAN> 

var buf = new Buffer(8);

buf[0] = 0x55;
buf[1] = 0x55;
buf[2] = 0x55;
buf[3] = 0x55;
buf[4] = 0x55;
buf[5] = 0x55;
buf[6] = 0xd5;
buf[7] = 0x3f;

console.log(buf.readDoubleLE(0));

// 0.3333333333333333

   buf.writerUInt8(value,offset,[noAssert])

value Number 数字
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
    在buffer的offset处写入value.注意vlaue必须是一个有效无符号的8bit integer.
    设置noAssert为true来忽略value和offset的验证.这意味着,value可能太大,offset可能越界,而导致value值的丢失.
    除非你确定正确,否则不要使用它.默认为false.
    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(4); 
buf.writeUInt8(0x3, 0); 
buf.writeUInt8(0x4, 1); 
buf.writeUInt8(0x23, 2); 
buf.writeUInt8(0x42, 3); 
 
console.log(buf); 
 
// <Buffer 03 04 23 42></SPAN> 

var buf = new Buffer(4);
buf.writeUInt8(0x3, 0);
buf.writeUInt8(0x4, 1);
buf.writeUInt8(0x23, 2);
buf.writeUInt8(0x42, 3);

console.log(buf);

// <Buffer 03 04 23 42>

   buf.writerUInt16LE(value,offset,[noAssert])

   buf.writerUInt16BE(value,offset,[noAssert])

value Number 数字
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
    在buffer的offset处使用指定的字节序列(le和be)写入value.注意vlaue必须是一个有效无符号的16bit integer.
    设置noAssert为true来忽略value和offset的验证.这意味着,value可能太大,offset可能越界,而导致value值的丢失.
    除非你确定正确,否则不要使用它.默认为false.
    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(4); 
buf.writeUInt16BE(0xdead, 0); 
buf.writeUInt16BE(0xbeef, 2); 
 
console.log(buf); 
 
buf.writeUInt16LE(0xdead, 0); 
buf.writeUInt16LE(0xbeef, 2); 
 
console.log(buf); 
 
// <Buffer de ad be ef>  
// <Buffer ad de ef be></SPAN> 

var buf = new Buffer(4);
buf.writeUInt16BE(0xdead, 0);
buf.writeUInt16BE(0xbeef, 2);

console.log(buf);

buf.writeUInt16LE(0xdead, 0);
buf.writeUInt16LE(0xbeef, 2);

console.log(buf);

// <Buffer de ad be ef>
// <Buffer ad de ef be>

   buf.writerUInt32LE(value,offset,[noAssert])

   buf.writerUInt32BE(value,offset,[noAssert])

value Number 数字
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
    在buffer的offset处使用指定的字节序列(le和be)写入value.注意vlaue必须是一个有效无符号的32bit integer.
    设置noAssert为true来忽略value和offset的验证.这意味着,value可能太大,offset可能越界,而导致value值的丢失.
    除非你确定正确,否则不要使用它.默认为false.
    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(4); 
buf.writeUInt32BE(0xfeedface, 0); 
 
console.log(buf); 
 
buf.writeUInt32LE(0xfeedface, 0); 
 
console.log(buf); 
 
// <Buffer fe ed fa ce>  
// <Buffer ce fa ed fe></SPAN> 

var buf = new Buffer(4);
buf.writeUInt32BE(0xfeedface, 0);

console.log(buf);

buf.writeUInt32LE(0xfeedface, 0);

console.log(buf);

// <Buffer fe ed fa ce>
// <Buffer ce fa ed fe>

   buf.writerInt8(value,offset,[noAssert])

value Number 数字
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
    在buffer的offset处写入value.注意vlaue必须是一个有效有符号的8bit integer.
    设置noAssert为true来忽略value和offset的验证.这意味着,value可能太大,offset可能越界,而导致value值的丢失.
    除非你确定正确,否则不要使用它.默认为false.
    除了buffer中被写入的内容被看作是有正负符号的值之外,和buffer.writeUInt8一样的功能.

   buf.writerInt16LE(value,offset,[noAssert])

   buf.writerInt16BE(value,offset,[noAssert])

value Number 数字
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
    在buffer的offset处写入value.注意vlaue必须是一个有效有符号的16bit integer.
    设置noAssert为true来忽略value和offset的验证.这意味着,value可能太大,offset可能越界,而导致value值的丢失.
    除非你确定正确,否则不要使用它.默认为false.
    除了buffer中被写入的内容被看作是有正负符号的值之外,和buffer.writeUInt16*一样的功能.

 

   buf.writerInt32LE(value,offset,[noAssert])

   buf.writerInt32BE(value,offset,[noAssert])

value Number 数字
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
    在buffer的offset处写入value.注意vlaue必须是一个有效有符号的32bit integer.
    设置noAssert为true来忽略value和offset的验证.这意味着,value可能太大,offset可能越界,而导致value值的丢失.
    除非你确定正确,否则不要使用它.默认为false.
    除了buffer中被写入的内容被看作是有正负符号的值之外,和buffer.writeUInt32*一样的功能.

 

   buf.writerFloatLE(value,offset,[noAssert])

   buf.writerFloatBE(value,offset,[noAssert])

value Number 数字
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
    在buffer的offset处写入value.注意vlaue必须是一个有效有符号的32bit float.
    设置noAssert为true来忽略value和offset的验证.这意味着,value可能太大,offset可能越界,而导致value值的丢失.
    除非你确定正确,否则不要使用它.默认为false.
    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(4); 
buf.writeFloatBE(0xcafebabe, 0); 
 
console.log(buf); 
 
buf.writeFloatLE(0xcafebabe, 0); 
 
console.log(buf); 
 
// <Buffer 4f 4a fe bb>  
// <Buffer bb fe 4a 4f></SPAN> 

var buf = new Buffer(4);
buf.writeFloatBE(0xcafebabe, 0);

console.log(buf);

buf.writeFloatLE(0xcafebabe, 0);

console.log(buf);

// <Buffer 4f 4a fe bb>
// <Buffer bb fe 4a 4f>

   buf.writerDoubleLE(value,offset,[noAssert])

   buf.writerDoubleBE(value,offset,[noAssert])

value Number 数字
offset Number 偏移量
noAssert Boolean, Optional, Default: false 是否忽略offset验证,offset可能超出范围.
    在buffer的offset处写入value.注意vlaue必须是一个有效有符号的64bit double.
    设置noAssert为true来忽略value和offset的验证.这意味着,value可能太大,offset可能越界,而导致value值的丢失.
    除非你确定正确,否则不要使用它.默认为false.
    例子:[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var buf = new Buffer(8); 
buf.writeDoubleBE(0xdeadbeefcafebabe, 0); 
 
console.log(buf); 
 
buf.writeDoubleLE(0xdeadbeefcafebabe, 0); 
 
console.log(buf); 
 
// <Buffer 43 eb d5 b7 dd f9 5f d7>  
// <Buffer d7 5f f9 dd b7 d5 eb 43></SPAN> 

var buf = new Buffer(8);
buf.writeDoubleBE(0xdeadbeefcafebabe, 0);

console.log(buf);

buf.writeDoubleLE(0xdeadbeefcafebabe, 0);

console.log(buf);

// <Buffer 43 eb d5 b7 dd f9 5f d7>
// <Buffer d7 5f f9 dd b7 d5 eb 43>
   buf.fill(value,[offset],[end])

value 要填充的值
offset Number, Optional 偏移量,可选 默认0
end Number, Optional 结束位置 可选.默认buffer大小
   使用指定的value来填充buffer.如果offset和end没有指定,将会默认填充整个buffer.[javascript] view plaincopyprint?
<SPAN style="FONT-SIZE: 18px; FONT-FAMILY: FangSong_GB2312">var b = new Buffer(50); 
b.fill("h");</SPAN> 

var b = new Buffer(50);
b.fill("h");  
    buf.INSPECT_MAX_BYTES

Number, Default: 50,数字,默认50.
    当buffer.inspect()被调用时返回的字节数.这个可以被用户模块重写.
    注意,这是一个通过require('buffer')获得的buffer模块的一个属性,不是全局的Buffer的一个属性,也不是一个buffer实例的属性.

   Class:SlowBuffer

    这个类主要是内部使用.javascript程序应该使用buffer来代替SlowBuffer.
    为了避免在一个服务器中分配小模块内存的c++buffer对象的数量瓶颈.node分配的内存块一个8kb,如果一个buffer小于这个8kb,那么他将会是一个SlowBuffer的子类.如果大于8kb,node将会直接分配一个slowBuffer大小的块返回.

      

缓存类(Buffer) stability:3 - Stable 纯javascript对Unicode支持不叫不错,但是对二进制数据的支持就...

本文由9159.com发布于编程,转载请注明出处:原始视频只要按照RTMP协议发送给RTMP,当需要处理

关键词:

上一篇:没有了
下一篇:没有了