rfc3984 
Standards Track [Page 2] RFC 3984 RTP Payload Format for H.264 Video February 2005 1. 
按照RFC3984协议实现H264视频流媒体

nalu单元 包起始 0x 00 00 00 01

H.264 NAL格式及分析器
http://hi.baidu.com/zsw%5Fdavy/b ... c409cc7cd92ace.html
http://hi.baidu.com/zsw_davy/blo ... 081312c8fc7acc.html

----------------------------------比特流信息----------------------------------------------

①NALU(Network Abstract Layer Unit):两标准中的比特流都是以NAL为单位,每个NAL单元包含一个RBSP,NALU的头信息定义了RBSP所属类型。类型一般包括序列参数集(SPS)、图像参数集(PPS)、增强信息(SEI)、条带(Slice)等,其中,SPS和PPS属于参数集,两标准采用参数集机制是为了将一些主要的序列、图像参数(解码图像尺寸、片组数、参考帧数、量化和滤波参数标记等)与其他参数分离,通过解码器先解码出来。此外,为了增强图像的清晰度,AVS-M添加了图像头(Picture head)信息。读取NALU流程中,每个NALU前有一个起始码0x000001,为防止 内部0x000001序列竞争,H.264编码器在最后一字节前插入一个新的字节——0x03,所以解码器检测到该序列时,需将0x03删掉,而AVS-M只需识别出起始码0x000001。

②读取宏块类型(mb type)和宏块编码模板(cbp):编解码图像以宏块划分,一个宏块由一个16*16亮度块和相应的一个8*8cb和一个8*8cr色度块组成。

(a) 两标准的帧内、帧间预测时宏块的划分是有区别的。H.264中,I_slice亮度块有Intra_4*4和Intra_16*16两种模式,色度块只有8*8模式;P_slice宏块分为16*16、16*8、8*16、8*8、8*4、4*8、4*4共7种模式。而AVS-M中,I_slice亮度块有I_4*4和I_Direct两模式,P_slice时宏块的划分和H.264中的划分一致。

(b) 两标准的宏块cbp值计算也不相同。H.264中,Intra_16*16宏块的亮度(色度)cbp直接通过读mb type得到;非Intra_16*16宏块的亮度cbp=coded_block_pattern%16,色度cbp=coded_block_pattern/16 。其中,亮度cbp最低4位有效,每位决定对应宏块的残差系数能不能为0;色度cbp为0时,对应残差系数为0,cbp为1时,DC残差系数不为0,AC系数为0,cbp为2时,DC、AC残差系数都不为0。AVS-M中,当宏块类型不是P_skip时,直接从码流中得到cbp的索引值,并以此索引值查表得到codenum值,再以codenum查表分别得到帧内/帧间cbp。此cbp为6位,每位代表宏块按8*8划分时能不能包含非零系数,当变换系数不为0时,需进一步读cbp_4*4中每位值来判断一个8*8块中4个4*4块的系数能不能为0。
---------------------------------------------------------------------------------------------
总的来说H264的码流的打包方式有两种,一种为 annex-b byte stream format 的格式,这个是绝大部分编码器的默认输出格式,就是每个帧的开头的3~4个字节是H264的start_code,0x00000001或者0x000001。
另一种是原始的NAL打包格式,就是开始的若干字节(1,2,4字节)是NAL的长度,而不是start_code,此时必须借助某个全局的数据来获得编码器的profile,level,PPS,SPS等信息才可以解码。
----------------------------------------------------------------------------
AVC vs. H.264
AVC and H.264 are synonymous. The standard is known by the full names "ISO/IEC 14496-10" and "ITU-T Recommendation H.264". In addition, a number of alternate names are used (or have been) in reference to this standard. These include:

  • MPEG-4 part 10
  • MPEG-4 AVC
  • AVC
  • MPEG-4 (in the broadcasting world MPEG4 part 2 is ignored)
  • H.264
  • JVT (Joint Video Team, nowadays rarely used referring to actual spec)
  • H.26L (early drafts went by this name)

All of the above (and those I've missed) include the Annex B byte-stream format. Unlike earlier MPEG1/2/4 and H.26x codecs, the H.264 specification proper does not define a full bit-stream syntax. It describes a number of NAL (Network Abstraction Layer) units, a sequence of which can be decoded into video frames. These NAL units have no boundary markers, and rely on some unspecified format to provide framing.

Annex B of of the document specifies one such format, which wraps NAL units in a format resembling a traditional MPEG video elementary stream, thus making it suitable for use with containers like MPEG PS/TS unable to provide the required framing. Other formats, such as ISO base media based formats, are able to properly separate the NAL units and do not need the Annex B wrapping.

The H.264 spec suffers from a deficiency. It defines several header-type NAL units (SPS and PPS) without specifying how to pack them into the single codec data field available in most containers. Fortunately, most containers seem to have adopted the packing used by the ISO format known as MP4.

1. H.264起始码
  在网络传输h264数据时,一个UDP包就是一个NALU,解码器可以很方便的检测出NAL分界和解码。但是如果编码数据存储为一个文件,原来的解码器将无法从数据流中分别出每个NAL的起始位置和终止位置,为此h.264用起始码来解决这一问题。

H.264编码时,在每个NAL前添加起始码 0x000001,解码器在码流中检测到起始码,当前NAL结束。为了防止NAL内部出现0x000001的数据,h.264又提出'防止竞争 emulation prevention"机制,在编码完一个NAL时,如果检测出有连续两个0x00字节,就在后面插入一个0x03。当解码器在NAL内部检测到0x000003的数据,就把0x03抛弃,恢复原始数据。
   0x000000  >>>>>>  0x00000300
   0x000001  >>>>>>  0x00000301
   0x000002  >>>>>>  0x00000302
   0x000003  >>>>>>  0x00000303

附上h.264解码nalu中检测起始码的算法流程  
for(;;) 
{
    if next 24 bits are 0x000001 
    { 
        startCodeFound = true 
        break; 
    } 
    else 
    { 
        flush 8 bits  
    } 
}// for(;;) 
if(true == startCodeFound) 

     //startcode found 
     // Flush the start code found 
     flush 24 bits  
     //Now navigate up to next start code and put the in between stuff 
     // in the nal structure. 
     for(;;)
     { 
         get next 24 bits & check if it equals to 0x000001 
         if(false == (next 24 bits == 000001)) 
         { 
             // search for pattern 0x000000 
             check if next 24 bits are 0x000000 
             if(false == result) 
             { 
                 // copy the byte into the buffer 
                 copy one byte to the Nal unit              
             } 
             else 
             { 
                 break; 
             } 
          } 
          else 
          { 
              break; 
          } 
       }//for(;;)
   }

2. MPEG4起始码
        MPEG4的特色是VOP,没有NALU的概念,仍使用startcode对每帧进行分界。MPEG4的起始码是0x000001. 另外MPEG4中很多起始码也很有用,比如video_object_sequence_start_code 0x000001B0 表示一个视频对象序列的开始,VO_start_code 0x000001B6 表示一个VOP的开始. 0x000001B6之后的两位,是00表示 I frame, 01 表示 P frame, 10 表示 B frame.

H.264 NAL格式及分析器程序源代码
          email:zsw_davy@hotmail.com

NAL分析器程序源代码
/*! 
**************************************************************************************
* \file
*   nalchek.c
* \brief
*    NALU handling common to encoder and decoder
l Zsw_davy@hotmail.com
l Aug.18.2006 ***************************************************************************************
*/

#include "stdio.h"
#include "stdlib.h"

#include "nalucommon.h"

//#####################################
//#本程序检查一个缓冲区里面有几个NALU #
//#输出每个NALU的类型到输出文件    # 
//#输入为一个带有标记/NALU+标记/的文件#
//#####################################

void main(void)
{
FILE *pSrc;
FILE *pRep;

if((pSrc=fopen("H264.rec","r+b"))==NULL) 
  exit(-1);
else printf("open src file succeed\n");
if((pRep=fopen("H264.rep","w+t"))==NULL)
  exit(-1);
else printf("open report file succeed\n");
ReportNalu(pSrc,pRep); 
fclose(pSrc);
fclose(pRep);
}

/*! **************************************************************************************
* \file
*    nalucommon.h.h
* \brief
*    NALU handling common to encoder and decoder
*  zsw_davy@hotmail.com
*   Aug.18.2006 ***************************************************************************************
*/
#include

#ifndef _NALUCOMMON_H_
#define _NALUCOMMON_H_

typedef struct 
{
int startcodeprefix_len;      //! 4 for parameter sets and first slice in picture, 3 for everything else

(suggested)
unsigned len;                 //! Length of the NAL unit (Excluding the start code, which does not belong

to the NALU)
unsigned max_size;            //! Nal Unit Buffer size
int nal_unit_type;            //! NALU_TYPE_xxxx
int nal_reference_idc;        //! NALU_PRIORITY_xxxx
int forbidden_bit;            //! should be always FALSE
unsigned char *buf;        //! conjtains the first byte followed by the EBSP
} NALU_t;

#define MAXRBSPSIZE 64000

#define NALU_TYPE_SLICE    1
#define NALU_TYPE_DPA      2
#define NALU_TYPE_DPB      3
#define NALU_TYPE_DPC      4
#define NALU_TYPE_IDR      5
#define NALU_TYPE_SEI      6
#define NALU_TYPE_SPS      7
#define NALU_TYPE_PPS      8
#define NALU_TYPE_AUD      9
#define NALU_TYPE_EOSEQ    10
#define NALU_TYPE_EOSTREAM 11
#define NALU_TYPE_FILL     12

#define NALU_PRIORITY_HIGHEST     3
#define NALU_PRIORITY_HIGH        2
#define NALU_PRIRITY_LOW          1
#define NALU_PRIORITY_DISPOSABLE  0

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

#ifndef BOOL
#define BOOL unsigned int
#endif

void ReportNalu(FILE* src,FILE* rep);
void ParseRecBuf(unsigned char *p,int bufsize,FILE* pReport);
int ShowBits (unsigned char buffer[],int totbitoffset,int bytecount, int numbits);
BOOL next_bits(unsigned char *p,int bufpos,int bs,int id );
static int FindStartCode (unsigned char *Buf, int bufpos,  int bufsize, int next_start_pos, BOOL fIRFD);
BOOL gETNALandPROC(unsigned char *p,int bufpos,int bufsize, BOOL fisrtfd,NALU_t *mNal,int inc_SIZE,FILE

*pReport);
#endif

//############################################################
//#       src 文件格式如下   
//#        #-#-#-#-#-B-INT32LEN-T264DST  - #-#-#-#-B-INT32LEN #
//#    1 1 1 1 1 1     4   INT32LEN                           #
//############################################################

void ReportNalu(FILE* src,FILE* rep)
{
unsigned char tempbuf[1];
unsigned char *pBuf;
int *dstlen;
    int fpos=0; 
int fstart=0;
int FileSize=0;
int BufSize; 
int dstpacketid=0;
unsigned int  SymState=0;
fseek(src,0,SEEK_END); 
FileSize=ftell(src);
printf("the src file size is %d \n",FileSize);
fseek(src,0,SEEK_SET);
do {
  
  while (fread(tempbuf,sizeof(unsigned char),1,src))
  {
   if(tempbuf=="#") SymState++;
   else
   { 
    fpos=fstart+1;
    SymState=0;
    fseek(src,fpos,SEEK_SET);
   }
   if(SymState==4)
   {fpos+=4;break;}
  }
  
  fread(tempbuf,sizeof(unsigned char),1,src);
  
  if(tempbuf=="B")
  {
   SymState++;
   fpos+=1;
  }
  else
  { 
   fpos=fstart+1;
   fseek(src,fpos,SEEK_SET);
  }
  
  if(SymState==5)   
  {   
   dstpacketid++;
   fprintf(rep,"the %d dstpacket\n",dstpacketid);
   dstlen=(int*)malloc(sizeof(int));
   fread(dstlen,sizeof(unsigned char),4,src);
   BufSize=(int*)dstlen;
   pBuf=(unsigned char*)malloc(sizeof(unsigned char)*BufSize);
   fpos+=4;
   fread(pBuf,sizeof(unsigned char),BufSize,src);
   ParseRecBuf(pBuf,BufSize,rep);
   fstart=fpos;
   free(dstlen);
   free(pBuf);
  } 
  
} while(fpos!=FileSize);//

}

//####################################################
//# unsigned char *p  --T264 encode的一个dst长度为len#
//# int bufsize   --buffer的大小     # 
//##FILE* pReport     --文件指针,存放NAL的分析结果  #
//####################################################

void ParseRecBuf(unsigned char *p,int bufsize,FILE* pReport)
{

int bufpos=0;
int bUFSTART=0;
    struct NALU_t *mNal;
BOOL isfirst; 
BOOL starcode_ex;
BOOL zero_ex;
BOOL trail_ex;
int nALSIZE=0;
int nal_id=0;
BOOL firstfd=FALSE;

while (bufpos<bufsize)
{
  if( !next_bits(p,bufpos,bufsize, 24 )  &&
   !next_bits(p,bufpos,bufsize,32 )  &&
   next_bits( p,bufpos,bufsize,8 ))
  {bufpos+=8;isfirst=TRUE;firstfd=TRUE;}// leading_zero_8bits /* equal to 0x00 */ //f(8)
  else{ isfirst=FALSE; }
  
  if(!next_bits( p,bufpos,bufsize,24 )  &&    
   next_bits( p,bufpos,bufsize,8 )
   )  
  {    
   bufpos+=8;//zero_byte /* equal to 0x00 */ f(8)
   zero_ex=TRUE;
   if( bufpos<bufsize &&
    next_bits(p,bufpos,bufsize, 24 ) )
   {      
    bufpos+=24; // start_code_prefix_one_3bytes /* equal to 0x000001 */ f(24)
    starcode_ex=TRUE;
    mNal=(struct NALU_t* )malloc(sizeof( NALU_t));
   if(gETNALandPROC(p,bufpos,bufsize,firstfd,mNal,nALSIZE,pReport))

{  
    
    nal_id++;
       fprintf(pReport," id of the nal packet above is %d\n",nal_id);
    bufpos+=(nALSIZE>>3);
    if(( bufpos<bufsize)  &&
     (!next_bits(p,bufpos,bufsize, 24 )) &&  
     (!next_bits(p,bufpos,bufsize, 32 ) ) &&
     (next_bits(p,bufpos, bufsize,8 )))
    {
     bufpos+=8; trail_ex=TRUE ;/*  trailing_zero_8bitsequal to 0x00 */
    }
    else trail_ex=FALSE;
    free(mNal);
   }
   else printf("cannot get any nal units\n");
   }
   else{starcode_ex=FALSE;}      
  }
  else
  { zero_ex=FALSE; }
  
  if (!zero_ex || !starcode_ex)
   bufpos=bUFSTART+1; 
  else bUFSTART=bufpos;

}

//############################################
//#unsigned char *p =--buffer containing NALU#
//#int bufpos--current buffer position   #
//#int bs---buffersize                   #
//#int id                                #
//#  id=24   ----0x000001----FALSE   #
//#     id=32   ----0x00000001---FALSE   #
//#     id=8 ----0x00------TRUE    # 
//############################################
BOOL next_bits(unsigned char *p,int bufpos,int bs,int id )
{
BOOL rERULT;
switch(id) {
case 8:   
  if(ShowBits(p,bufpos,bs,8)==0x00) rERULT=TRUE ;
  else rERULT=FALSE;
  break;
case 24: 
  if(ShowBits(p,bufpos,bs,24)!=0x000001) rERULT=FALSE;
  else rERULT=TRUE;
  break;
case 32 :
  if(ShowBits(p,bufpos,bs,32)!=0x00000001) rERULT=FALSE;
  else rERULT=TRUE;
  break;
default:
  break;
}
return rERULT;
}

//##############################################
// # \brief         #
// #  Reads bits from the bitstream buffer     #
// # \param buffer        #
// #    buffer containing VLC-coded data bits  #
// # \param totbitoffset      #
// #    bit offset from start of partition     #
// # \param bytecount                          #
// #    total bytes in bitstream               #
// # \param numbits                            #
// #    number of bits to read                 #
// #############################################
int ShowBits (unsigned char buffer[],int totbitoffset,int bytecount, int numbits)
{

register int inf;
long byteoffset;      // byte from start of buffer
int bitoffset;      // bit from start of byte

byteoffset= totbitoffset/8;
bitoffset= 7-(totbitoffset%8);

inf=0;
while (numbits)
{
  inf <<=1;
  inf |= (buffer[byteoffset] & (0x01<>bitoffset;
  numbits--;
  bitoffset--;
  if (bitoffset < 0)
  {
   byteoffset++;
   bitoffset += 8;
   if (byteoffset > bytecount)
   {
    return -1;
   }
  }
}

return inf;   // return absolute offset in bit from start of frame
}

//#########################################################################
// # \brief

#
// #    returns if new start code is found at byte aligned position buf.  #
// #    new-startcode is of form N 0x00 bytes, followed by a 0x01 byte.   #
// #  \return

#
// #     1 if start-code is found or                      \n              #
// #     0, indicating that there is no start code                        #
// #                                                                      #
// #  \param Buf                                                          #
// #     pointer to byte-stream                                           #
// #  \param   bufpos                                             #
// #     indicates current bufpos. 
//#     \bufsize
//  #   indicates   total buffer size                          #
//  #  \param      next_star_pos                                           #
//  #      indicates the next_start_code pos                               #
//  #  \param      fIRFD
//  #    is firs nal already found
// ########################################################################
static int FindStartCode (unsigned char *Buf, int bufpos,  int bufsize, int next_start_pos, BOOL fIRFD)
{
int info;
int tPOS;
int tSTART=bufpos;
BOOL sTARFOUND=FALSE;
info = 1;
while (!sTARFOUND && tSTART<bufsize) {
  for (tPOS = 0; tPOS < 3; tPOS++)
   if(Buf[tSTART+tPOS] != 0)
    info = 0;    
   if(Buf[tSTART+tPOS] != 1)
    info = 0;
   if (info==0)    tSTART++;    
   else sTARFOUND=TRUE; 
}
if (fIRFD && sTARFOUND)
{  
  if(Buf[tSTART-1]==0 &&
   Buf[tSTART-2]==0)
  { info=2;//trailing zero found
  next_start_pos=tSTART-2;}
  else {info=1;
  next_start_pos=tSTART;}   

return info;
}

//#####################################
//# unsigned char *p      #
//# int bufpos                    #
//# NALU_t *mNal          #
//# int n_SIZE       #
//#           #
//#           # 
//#####################################
BOOL gETNALandPROC(unsigned char *p,
       int bufpos,
       int bufsize,
       BOOL fisrtfd,
       NALU_t *mNal,
       int inc_SIZE,
       FILE *pReport)
{  
BOOL getNfailed=FALSE;
    int nal_BUFSIZE=0;
int next_start_point=0;
int mNal_size=0;
int b_bufpos=bufpos/8;
unsigned int finresult;
BOOL info=TRUE;
finresult=FindStartCode (p,b_bufpos,bufsize,next_start_point,fisrtfd);
if (finresult==1 || finresult==2) {   
  nal_BUFSIZE=next_start_point-b_bufpos-1;
  inc_SIZE=nal_BUFSIZE;
  mNal->buf=(unsigned char *)malloc(sizeof(unsigned char)*nal_BUFSIZE);
  mNal->len=nal_BUFSIZE;
  memcpy (mNal->buf, &p[b_bufpos+1], mNal->len);
  mNal->forbidden_bit = (mNal->buf[0]>>7) & 1;
  mNal->nal_reference_idc = (mNal->buf[0]>>5) & 3;
  mNal->nal_unit_type = (mNal->buf[0]) & 0x1f;
  fprintf(pReport,"#########################################################################\n");
  fprintf(pReport,"nal len is %d\n",mNal->len);
  fprintf(pReport,"fobidden bit is % d\n",mNal->forbidden_bit);
  fprintf(pReport,"nal_reference_idc is d%\n",mNal->nal_reference_idc);
  switch(mNal->nal_unit_type) {
  case NALU_TYPE_SLICE :
   fprintf(pReport," nal type is  * NALU_TYPE_SLICE\n");
   break;
  case NALU_TYPE_DPA:
   fprintf(pReport,"nal type is *  NALU_TYPE_DPA\n");
   break;
  case NALU_TYPE_DPB :
   fprintf(pReport,"nal type is  * NALU_TYPE_DPB\n");
   break;
  case NALU_TYPE_DPC:
   fprintf(pReport,"nal type is  * NALU_TYPE_DPC\n");
   break;
  case NALU_TYPE_IDR:
   fprintf(pReport,"nal type is  * NALU_TYPE_IDR\n");
   break;
  case NALU_TYPE_SEI:
   fprintf(pReport,"nal type is  * NALU_TYPE_SEI\n");
   break;
  case NALU_TYPE_SPS:
   fprintf(pReport,"nal type is  * NALU_TYPE_SPS\n");
   break;
  case NALU_TYPE_PPS:
   fprintf(pReport,"nal type is  * NALU_TYPE_PPS\n");
   break;
  case NALU_TYPE_AUD:
   fprintf(pReport,"nal type is  * NALU_TYPE_AUD\n");
   break;
  case NALU_TYPE_EOSEQ:
   fprintf(pReport,"nal type is  * NALU_TYPE_EOSEQ\n");
   break;
  case NALU_TYPE_EOSTREAM:
   fprintf(pReport,"nal type is  * NALU_TYPE_EOSTREAM\n");
   break;
  case NALU_TYPE_FILL  :
   fprintf(pReport,"nal type is  * NALU_TYPE_FILL\n");
   break;
  default:
   break;
  }
  fprintf(pReport,"nal start code len is %d\n",mNal->startcodeprefix_len);
  fprintf(pReport,"#########################################################################\n"); 
  free(mNal->buf);
  mNal->buf=NULL;
  }
else info=FALSE;
return info;
}

H264 视频文件 帧格式 传输封装等相关推荐

  1. H264 视频文件 帧格式 传输封装等 杂碎

    H264 视频文件 帧格式 传输封装等 杂碎 rfc3984 Standards Track [Page 2] RFC 3984 RTP Payload Format for H.264 Video ...

  2. FFmpeg 4.0.2编码YUV序列为H264视频文件

    /****************************** 功能:编码YUV序列为h264视频文件 FFmpeg:4.0.2 ******************************/ #in ...

  3. ffmpeg —— v4l2录制h264视频文件(边采集边转码)

    相关文章: v4l2采集图像并转换格式 视频编码(yuv编码h264) 目标:使用v4l2采集摄像头图像数据,并实时编码成h264视频文件. 代码: #include <stdio.h> ...

  4. H264 视频文件如何缩放分辨率?

    前几天在知识星球里面有位朋友请教问题:如何将 H264 视频缩放分辨率? 具体的问题详情如下: 将 800x600 的 H264 文件缩放成 400x300 的,大概的流程是先解码,得到 AVFram ...

  5. windows使用ffmpeg将mp4文件转变成h264视频文件

    我是直接使用ffmpeg的安装包,win10下 首先下载ffmpeg http://www.ffmpeg.org/download.htmlhttp://www.ffmpeg.org/download ...

  6. tornado+nginx上传视频文件

    [http://arloz.me/tornado/2014/06/27/uploadvideotornado.html] [NGINX REFRER: Nginx upload module] 由于t ...

  7. 图像/短视频文件的MD5码的定义、作用以及获取方式

    目录 一.图像/短视频文件的MD5码定义: 二.MD5码的作用: 三.如何获取一个图像/短视频文件的MD5码: 一.图像/短视频文件的MD5码定义: MD5(Message-Digest Algori ...

  8. FFmpeg进阶: 转码输出视频文件中的音频

    很多时候为了方便收听视频文件中的音频信息,我们会将视频文件中的音频流转码输出成音频文件,方便在对应的平台上进行播放.这里就介绍一下如何通过FFmpeg将视频文件中的音频流转码成特定编码格式的音频文件. ...

  9. h.264视频文件封装

    所谓封装格式就是将已经编码压缩好的视频轨和音频轨按照一定的格式放到一个文件中,也就是说仅仅是一个外壳,或者大家把它当成一个放视频轨和音频轨的文件夹也可以.说得通俗点,视频轨相当于饭,而音频轨相当于菜, ...

  10. mp4v2再学习 -- H264视频编码成MP4文件

    一.H264视频编码成MP4文件 参看:H264视频编码成MP4文件 参看:mp4v2在VS2010下的编译与在项目中的使用 最近做项目需要将H264文件封装为mp4文件,从网上找到了MP4V2库,下 ...

最新文章

  1. 对外星智能的搜索得到了重大的升级
  2. caliop 数据可视化_星载激光雷达CALIOP数据处理算法概述
  3. 今天晴朗,但是由于晚上睡眠不是很好就头昏眼花
  4. android 水平方向瀑布流,Android RecyclerView(瀑布流)水平/垂直方向分割线
  5. shell函数可接受不同参数
  6. Mono项目的新进展
  7. 移动应用开发专业简介(610212)
  8. 测试文档模板_基于模型的测试(贰)
  9. 服务器虚拟化税收编码,服务器主机税收分类
  10. DB9 串口母对母转接头是个坑
  11. Ubuntu16.04桌面版pxe启动实现自动安装
  12. Symbolic Math Toolbox——MuPAD
  13. php mysql 考勤系统_考勤问题思路和解决
  14. 计算机最大数最小数的函数,Excel函数教程: 求最大、最小、中间数、最多数-excel技巧-电脑技巧收藏家...
  15. SIM卡的PIN码(CHV)及对应的APDU命令
  16. php图书馆注册模板,php微信公众号开发之校园图书馆
  17. Python爬虫实战- 爬取整个网站112G-8000本pdf epub格式电子书下载
  18. php英文怎么读,100的英文怎么读_单词及读音
  19. 65页PPT|数字化转型中的大数据治理如何落地
  20. 汉字转换为二进制的原理

热门文章

  1. 电影说明里何谓枪版?何谓TS版?TC版?
  2. face++ 行驶证OCR识别
  3. 快学数据挖掘—数据探索—贡献度分析
  4. St. Luke’s University Health Network是世界首批试用远程患者管理解决方案Masimo SafetyNet™来协助COVID-19住院患者的机构之一
  5. C++输入大写字母转小写字母
  6. 应对个人信息保护法律合规,妥善管理个人隐私数据
  7. html怎么统计总访问量,如何实现对网站页面访问量的统计?
  8. eclipse使用maven新建类目录时,提示The folder is already a source folder
  9. Deepin 深度技术 Windows XP SP2 珍藏版
  10. 人工智能 机器学习 数据挖掘 数据分析 算法大全