最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打包、解包的文档和代码。功夫不负有心人,找到不少有价值的文档和代码。参考这些资料,写了H264 RTP打包类、解包类,实现了单个NAL单元包和FU_A分片单元包。对于丢包处理,采用简单的策略:丢弃随后的所有数据包,直到收到关键帧。测试效果还不错,代码贴上来,若能为同道中人借鉴一二,足矣。两个类的使用说明如下(省略了错误处理过程):

DWORD H264SSRC ;
 CH264_RTP_PACK pack ( H264SSRC ) ;
 BYTE *pVideoData ;
 DWORD Size, ts ;
 bool IsEndOfFrame ;
 WORD wLen ;
 pack.Set ( pVideoData, Size, ts, IsEndOfFrame ) ;
 BYTE *pPacket ;
 while ( pPacket = pack.Get ( &wLen ) )
 {
  // rtp packet process
  // ...
 }

HRESULT hr ;
 CH264_RTP_UNPACK unpack ( hr ) ;
 BYTE *pRtpData ;
 WORD inSize;
 int outSize ;
 BYTE *pFrame = unpack.Parse_RTP_Packet ( pRtpData, inSize, &outSize ) ;
 if ( pFrame != NULL )
 {
  // frame process
  // ...
 }

  1. //////////////////////////////////////////////////////////////////////////////////////////
  2. // class CH264_RTP_PACK start
  3.  
  4. class CH264_RTP_PACK
  5. {
  6. #define RTP_VERSION 2
  7.  
  8. typedef struct NAL_msg_s
  9. {
  10. bool eoFrame ;
  11. unsigned char type; // NAL type
  12. unsigned char *start; // pointer to first location in the send buffer
  13. unsigned char *end; // pointer to last location in send buffer
  14. unsigned long size ;
  15. } NAL_MSG_t;
  16.  
  17. typedef struct
  18. {
  19. //LITTLE_ENDIAN
  20. unsigned short cc:; /* CSRC count */
  21. unsigned short x:; /* header extension flag */
  22. unsigned short p:; /* padding flag */
  23. unsigned short v:; /* packet type */
  24. unsigned short pt:; /* payload type */
  25. unsigned short m:; /* marker bit */
  26.  
  27. unsigned short seq; /* sequence number */
  28. unsigned long ts; /* timestamp */
  29. unsigned long ssrc; /* synchronization source */
  30. } rtp_hdr_t;
  31.  
  32. typedef struct tagRTP_INFO
  33. {
  34. NAL_MSG_t nal; // NAL information
  35. rtp_hdr_t rtp_hdr; // RTP header is assembled here
  36. int hdr_len; // length of RTP header
  37.  
  38. unsigned char *pRTP; // pointer to where RTP packet has beem assembled
  39. unsigned char *start; // pointer to start of payload
  40. unsigned char *end; // pointer to end of payload
  41.  
  42. unsigned int s_bit; // bit in the FU header
  43. unsigned int e_bit; // bit in the FU header
  44. bool FU_flag; // fragmented NAL Unit flag
  45. } RTP_INFO;
  46.  
  47. public:
  48. CH264_RTP_PACK(unsigned long H264SSRC, unsigned char H264PAYLOADTYPE=, unsigned short MAXRTPPACKSIZE= )
  49. {
  50. m_MAXRTPPACKSIZE = MAXRTPPACKSIZE ;
  51. if ( m_MAXRTPPACKSIZE > )
  52. {
  53. m_MAXRTPPACKSIZE = ;
  54. }
  55. if ( m_MAXRTPPACKSIZE < )
  56. {
  57. m_MAXRTPPACKSIZE = ;
  58. }
  59.  
  60. memset ( &m_RTP_Info, , sizeof(m_RTP_Info) ) ;
  61.  
  62. m_RTP_Info.rtp_hdr.pt = H264PAYLOADTYPE ;
  63. m_RTP_Info.rtp_hdr.ssrc = H264SSRC ;
  64. m_RTP_Info.rtp_hdr.v = RTP_VERSION ;
  65.  
  66. m_RTP_Info.rtp_hdr.seq = ;
  67. }
  68.  
  69. ~CH264_RTP_PACK(void)
  70. {
  71. }
  72.  
  73. //传入Set的数据必须是一个完整的NAL,起始码为0x00000001。
  74. //起始码之前至少预留10个字节,以避免内存COPY操作。
  75. //打包完成后,原缓冲区内的数据被破坏。
  76. bool Set ( unsigned char *NAL_Buf, unsigned long NAL_Size, unsigned long Time_Stamp, bool End_Of_Frame )
  77. {
  78. unsigned long startcode = StartCode(NAL_Buf) ;
  79.  
  80. if ( startcode != 0x01000000 )
  81. {
  82. return false ;
  83. }
  84.  
  85. int type = NAL_Buf[] & 0x1f ;
  86. if ( type < || type > )
  87. {
  88. return false ;
  89. }
  90.  
  91. m_RTP_Info.nal.start = NAL_Buf ;
  92. m_RTP_Info.nal.size = NAL_Size ;
  93. m_RTP_Info.nal.eoFrame = End_Of_Frame ;
  94. m_RTP_Info.nal.type = m_RTP_Info.nal.start[] ;
  95. m_RTP_Info.nal.end = m_RTP_Info.nal.start + m_RTP_Info.nal.size ;
  96.  
  97. m_RTP_Info.rtp_hdr.ts = Time_Stamp ;
  98.  
  99. m_RTP_Info.nal.start += ; // skip the syncword
  100.  
  101. if ( (m_RTP_Info.nal.size + ) > m_MAXRTPPACKSIZE )
  102. {
  103. m_RTP_Info.FU_flag = true ;
  104. m_RTP_Info.s_bit = ;
  105. m_RTP_Info.e_bit = ;
  106.  
  107. m_RTP_Info.nal.start += ; // skip NAL header
  108. }
  109. else
  110. {
  111. m_RTP_Info.FU_flag = false ;
  112. m_RTP_Info.s_bit = m_RTP_Info.e_bit = ;
  113. }
  114.  
  115. m_RTP_Info.start = m_RTP_Info.end = m_RTP_Info.nal.start ;
  116. m_bBeginNAL = true ;
  117.  
  118. return true ;
  119. }
  120.  
  121. //循环调用Get获取RTP包,直到返回值为NULL
  122. unsigned char* Get ( unsigned short *pPacketSize )
  123. {
  124. if ( m_RTP_Info.end == m_RTP_Info.nal.end )
  125. {
  126. *pPacketSize = ;
  127. return NULL ;
  128. }
  129.  
  130. if ( m_bBeginNAL )
  131. {
  132. m_bBeginNAL = false ;
  133. }
  134. else
  135. {
  136. m_RTP_Info.start = m_RTP_Info.end; // continue with the next RTP-FU packet
  137. }
  138.  
  139. int bytesLeft = m_RTP_Info.nal.end - m_RTP_Info.start ;
  140. int maxSize = m_MAXRTPPACKSIZE - ; // sizeof(basic rtp header) == 12 bytes
  141. if ( m_RTP_Info.FU_flag )
  142. maxSize -= ;
  143.  
  144. if ( bytesLeft > maxSize )
  145. {
  146. m_RTP_Info.end = m_RTP_Info.start + maxSize ; // limit RTP packetsize to 1472 bytes
  147. }
  148. else
  149. {
  150. m_RTP_Info.end = m_RTP_Info.start + bytesLeft ;
  151. }
  152.  
  153. if ( m_RTP_Info.FU_flag )
  154. { // multiple packet NAL slice
  155. if ( m_RTP_Info.end == m_RTP_Info.nal.end )
  156. {
  157. m_RTP_Info.e_bit = ;
  158. }
  159. }
  160.  
  161. m_RTP_Info.rtp_hdr.m = m_RTP_Info.nal.eoFrame ? : ; // should be set at EofFrame
  162. if ( m_RTP_Info.FU_flag && !m_RTP_Info.e_bit )
  163. {
  164. m_RTP_Info.rtp_hdr.m = ;
  165. }
  166.  
  167. m_RTP_Info.rtp_hdr.seq++ ;
  168.  
  169. unsigned char *cp = m_RTP_Info.start ;
  170. cp -= ( m_RTP_Info.FU_flag ? : ) ;
  171. m_RTP_Info.pRTP = cp ;
  172.  
  173. unsigned char *cp2 = (unsigned char *)&m_RTP_Info.rtp_hdr ;
  174. cp[] = cp2[] ;
  175. cp[] = cp2[] ;
  176.  
  177. cp[] = ( m_RTP_Info.rtp_hdr.seq >> ) & 0xff ;
  178. cp[] = m_RTP_Info.rtp_hdr.seq & 0xff ;
  179.  
  180. cp[] = ( m_RTP_Info.rtp_hdr.ts >> ) & 0xff ;
  181. cp[] = ( m_RTP_Info.rtp_hdr.ts >> ) & 0xff ;
  182. cp[] = ( m_RTP_Info.rtp_hdr.ts >> ) & 0xff ;
  183. cp[] = m_RTP_Info.rtp_hdr.ts & 0xff ;
  184.  
  185. cp[] = ( m_RTP_Info.rtp_hdr.ssrc >> ) & 0xff ;
  186. cp[] = ( m_RTP_Info.rtp_hdr.ssrc >> ) & 0xff ;
  187. cp[] = ( m_RTP_Info.rtp_hdr.ssrc >> ) & 0xff ;
  188. cp[] = m_RTP_Info.rtp_hdr.ssrc & 0xff ;
  189. m_RTP_Info.hdr_len = ;
  190. /*!
  191. * /n The FU indicator octet has the following format:
  192. * /n
  193. * /n +---------------+
  194. * /n MSB |0|1|2|3|4|5|6|7| LSB
  195. * /n +-+-+-+-+-+-+-+-+
  196. * /n |F|NRI| Type |
  197. * /n +---------------+
  198. * /n
  199. * /n The FU header has the following format:
  200. * /n
  201. * /n +---------------+
  202. * /n |0|1|2|3|4|5|6|7|
  203. * /n +-+-+-+-+-+-+-+-+
  204. * /n |S|E|R| Type |
  205. * /n +---------------+
  206. */
  207. if ( m_RTP_Info.FU_flag )
  208. {
  209. // FU indicator F|NRI|Type
  210. cp[] = ( m_RTP_Info.nal.type & 0xe0 ) | ; //Type is 28 for FU_A
  211. //FU header S|E|R|Type
  212. cp[] = ( m_RTP_Info.s_bit << ) | ( m_RTP_Info.e_bit << ) | ( m_RTP_Info.nal.type & 0x1f ) ; //R = 0, must be ignored by receiver
  213.  
  214. m_RTP_Info.s_bit = m_RTP_Info.e_bit= ;
  215. m_RTP_Info.hdr_len = ;
  216. }
  217. m_RTP_Info.start = &cp[m_RTP_Info.hdr_len] ; // new start of payload
  218.  
  219. *pPacketSize = m_RTP_Info.hdr_len + ( m_RTP_Info.end - m_RTP_Info.start ) ;
  220. return m_RTP_Info.pRTP ;
  221. }
  222.  
  223. private:
  224. unsigned int StartCode( unsigned char *cp )
  225. {
  226. unsigned int d32 ;
  227. d32 = cp[] ;
  228. d32 <<= ;
  229. d32 |= cp[] ;
  230. d32 <<= ;
  231. d32 |= cp[] ;
  232. d32 <<= ;
  233. d32 |= cp[] ;
  234. return d32 ;
  235. }
  236.  
  237. private:
  238. RTP_INFO m_RTP_Info ;
  239. bool m_bBeginNAL ;
  240. unsigned short m_MAXRTPPACKSIZE ;
  241. };
  242.  
  243. // class CH264_RTP_PACK end
  244. //////////////////////////////////////////////////////////////////////////////////////////
  245.  
  246. //////////////////////////////////////////////////////////////////////////////////////////
  247. // class CH264_RTP_UNPACK start
  248.  
  249. class CH264_RTP_UNPACK
  250. {
  251.  
  252. #define RTP_VERSION 2
  253. #define BUF_SIZE (1024 * 500)
  254.  
  255. typedef struct
  256. {
  257. //LITTLE_ENDIAN
  258. unsigned short cc:; /* CSRC count */
  259. unsigned short x:; /* header extension flag */
  260. unsigned short p:; /* padding flag */
  261. unsigned short v:; /* packet type */
  262. unsigned short pt:; /* payload type */
  263. unsigned short m:; /* marker bit */
  264.  
  265. unsigned short seq; /* sequence number */
  266. unsigned long ts; /* timestamp */
  267. unsigned long ssrc; /* synchronization source */
  268. } rtp_hdr_t;
  269. public:
  270.  
  271. CH264_RTP_UNPACK ( HRESULT &hr, unsigned char H264PAYLOADTYPE = )
  272. : m_bSPSFound(false)
  273. , m_bWaitKeyFrame(true)
  274. , m_bPrevFrameEnd(false)
  275. , m_bAssemblingFrame(false)
  276. , m_wSeq()
  277. , m_ssrc()
  278. {
  279. m_pBuf = new BYTE[BUF_SIZE] ;
  280. if ( m_pBuf == NULL )
  281. {
  282. hr = E_OUTOFMEMORY ;
  283. return ;
  284. }
  285.  
  286. m_H264PAYLOADTYPE = H264PAYLOADTYPE ;
  287. m_pEnd = m_pBuf + BUF_SIZE ;
  288. m_pStart = m_pBuf ;
  289. m_dwSize = ;
  290. hr = S_OK ;
  291. }
  292.  
  293. ~CH264_RTP_UNPACK(void)
  294. {
  295. delete [] m_pBuf ;
  296. }
  297.  
  298. //pBuf为H264 RTP视频数据包,nSize为RTP视频数据包字节长度,outSize为输出视频数据帧字节长度。
  299. //返回值为指向视频数据帧的指针。输入数据可能被破坏。
  300. BYTE* Parse_RTP_Packet ( BYTE *pBuf, unsigned short nSize, int *outSize )
  301. {
  302. if ( nSize <= )
  303. {
  304. return NULL ;
  305. }
  306.  
  307. BYTE *cp = (BYTE*)&m_RTP_Header ;
  308. cp[] = pBuf[] ;
  309. cp[] = pBuf[] ;
  310.  
  311. m_RTP_Header.seq = pBuf[] ;
  312. m_RTP_Header.seq <<= ;
  313. m_RTP_Header.seq |= pBuf[] ;
  314.  
  315. m_RTP_Header.ts = pBuf[] ;
  316. m_RTP_Header.ts <<= ;
  317. m_RTP_Header.ts |= pBuf[] ;
  318. m_RTP_Header.ts <<= ;
  319. m_RTP_Header.ts |= pBuf[] ;
  320. m_RTP_Header.ts <<= ;
  321. m_RTP_Header.ts |= pBuf[] ;
  322.  
  323. m_RTP_Header.ssrc = pBuf[] ;
  324. m_RTP_Header.ssrc <<= ;
  325. m_RTP_Header.ssrc |= pBuf[] ;
  326. m_RTP_Header.ssrc <<= ;
  327. m_RTP_Header.ssrc |= pBuf[] ;
  328. m_RTP_Header.ssrc <<= ;
  329. m_RTP_Header.ssrc |= pBuf[] ;
  330.  
  331. BYTE *pPayload = pBuf + ;
  332. DWORD PayloadSize = nSize - ;
  333.  
  334. // Check the RTP version number (it should be 2):
  335. if ( m_RTP_Header.v != RTP_VERSION )
  336. {
  337. return NULL ;
  338. }
  339.  
  340. /*
  341. // Skip over any CSRC identifiers in the header:
  342. if ( m_RTP_Header.cc )
  343. {
  344. long cc = m_RTP_Header.cc * 4 ;
  345. if ( Size < cc )
  346. {
  347. return NULL ;
  348. }
  349.  
  350. Size -= cc ;
  351. p += cc ;
  352. }
  353.  
  354. // Check for (& ignore) any RTP header extension
  355. if ( m_RTP_Header.x )
  356. {
  357. if ( Size < 4 )
  358. {
  359. return NULL ;
  360. }
  361.  
  362. Size -= 4 ;
  363. p += 2 ;
  364. long l = p[0] ;
  365. l <<= 8 ;
  366. l |= p[1] ;
  367. p += 2 ;
  368. l *= 4 ;
  369. if ( Size < l ) ;
  370. {
  371. return NULL ;
  372. }
  373. Size -= l ;
  374. p += l ;
  375. }
  376.  
  377. // Discard any padding bytes:
  378. if ( m_RTP_Header.p )
  379. {
  380. if ( Size == 0 )
  381. {
  382. return NULL ;
  383. }
  384. long Padding = p[Size-1] ;
  385. if ( Size < Padding )
  386. {
  387. return NULL ;
  388. }
  389. Size -= Padding ;
  390. }*/
  391.  
  392. // Check the Payload Type.
  393. if ( m_RTP_Header.pt != m_H264PAYLOADTYPE )
  394. {
  395. return NULL ;
  396. }
  397.  
  398. int PayloadType = pPayload[] & 0x1f ;
  399. int NALType = PayloadType ;
  400. if ( NALType == ) // FU_A
  401. {
  402. if ( PayloadSize < )
  403. {
  404. return NULL ;
  405. }
  406.  
  407. NALType = pPayload[] & 0x1f ;
  408. }
  409.  
  410. if ( m_ssrc != m_RTP_Header.ssrc )
  411. {
  412. m_ssrc = m_RTP_Header.ssrc ;
  413. SetLostPacket () ;
  414. }
  415.  
  416. if ( NALType == 0x07 ) // SPS
  417. {
  418. m_bSPSFound = true ;
  419. }
  420.  
  421. if ( !m_bSPSFound )
  422. {
  423. return NULL ;
  424. }
  425.  
  426. if ( NALType == 0x07 || NALType == 0x08 ) // SPS PPS
  427. {
  428. m_wSeq = m_RTP_Header.seq ;
  429. m_bPrevFrameEnd = true ;
  430.  
  431. pPayload -= ;
  432. *((DWORD*)(pPayload)) = 0x01000000 ;
  433. *outSize = PayloadSize + ;
  434. return pPayload ;
  435. }
  436.  
  437. if ( m_bWaitKeyFrame )
  438. {
  439. if ( m_RTP_Header.m ) // frame end
  440. {
  441. m_bPrevFrameEnd = true ;
  442. if ( !m_bAssemblingFrame )
  443. {
  444. m_wSeq = m_RTP_Header.seq ;
  445. return NULL ;
  446. }
  447. }
  448.  
  449. if ( !m_bPrevFrameEnd )
  450. {
  451. m_wSeq = m_RTP_Header.seq ;
  452. return NULL ;
  453. }
  454. else
  455. {
  456. if ( NALType != 0x05 ) // KEY FRAME
  457. {
  458. m_wSeq = m_RTP_Header.seq ;
  459. m_bPrevFrameEnd = false ;
  460. return NULL ;
  461. }
  462. }
  463. }
  464.  
  465. ///////////////////////////////////////////////////////////////
  466.  
  467. if ( m_RTP_Header.seq != (WORD)( m_wSeq + ) ) // lost packet
  468. {
  469. m_wSeq = m_RTP_Header.seq ;
  470. SetLostPacket () ;
  471. return NULL ;
  472. }
  473. else
  474. {
  475. // 码流正常
  476.  
  477. m_wSeq = m_RTP_Header.seq ;
  478. m_bAssemblingFrame = true ;
  479.  
  480. if ( PayloadType != ) // whole NAL
  481. {
  482. *((DWORD*)(m_pStart)) = 0x01000000 ;
  483. m_pStart += ;
  484. m_dwSize += ;
  485. }
  486. else // FU_A
  487. {
  488. if ( pPayload[] & 0x80 ) // FU_A start
  489. {
  490. *((DWORD*)(m_pStart)) = 0x01000000 ;
  491. m_pStart += ;
  492. m_dwSize += ;
  493.  
  494. pPayload[] = ( pPayload[] & 0xE0 ) | NALType ;
  495.  
  496. pPayload += ;
  497. PayloadSize -= ;
  498. }
  499. else
  500. {
  501. pPayload += ;
  502. PayloadSize -= ;
  503. }
  504. }
  505.  
  506. if ( m_pStart + PayloadSize < m_pEnd )
  507. {
  508. CopyMemory ( m_pStart, pPayload, PayloadSize ) ;
  509. m_dwSize += PayloadSize ;
  510. m_pStart += PayloadSize ;
  511. }
  512. else // memory overflow
  513. {
  514. SetLostPacket () ;
  515. return NULL ;
  516. }
  517.  
  518. if ( m_RTP_Header.m ) // frame end
  519. {
  520. *outSize = m_dwSize ;
  521.  
  522. m_pStart = m_pBuf ;
  523. m_dwSize = ;
  524.  
  525. if ( NALType == 0x05 ) // KEY FRAME
  526. {
  527. m_bWaitKeyFrame = false ;
  528. }
  529. return m_pBuf ;
  530. }
  531. else
  532. {
  533. return NULL ;
  534. }
  535. }
  536. }
  537.  
  538. void SetLostPacket()
  539. {
  540. m_bSPSFound = false ;
  541. m_bWaitKeyFrame = true ;
  542. m_bPrevFrameEnd = false ;
  543. m_bAssemblingFrame = false ;
  544. m_pStart = m_pBuf ;
  545. m_dwSize = ;
  546. }
  547.  
  548. private:
  549. rtp_hdr_t m_RTP_Header ;
  550.  
  551. BYTE *m_pBuf ;
  552.  
  553. bool m_bSPSFound ;
  554. bool m_bWaitKeyFrame ;
  555. bool m_bAssemblingFrame ;
  556. bool m_bPrevFrameEnd ;
  557. BYTE *m_pStart ;
  558. BYTE *m_pEnd ;
  559. DWORD m_dwSize ;
  560.  
  561. WORD m_wSeq ;
  562.  
  563. BYTE m_H264PAYLOADTYPE ;
  564. DWORD m_ssrc ;
  565. };
  566.  
  567. // class CH264_RTP_UNPACK end
  568. //////////////////////////////////////////////////////////////////////////////////////////

参考:

1,基于RTP的H264视频数据打包解包类

http://blog.csdn.net/dengzikun/article/details/5807694

(转)基于RTP的H264视频数据打包解包类的更多相关文章

  1. 基于RTP的H264视频数据打包解包类

    from:http://blog.csdn.net/dengzikun/article/details/5807694 最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打 ...

  2. 【FFMPEG】基于RTP的H264视频数据打包解包类

    最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打包.解包的文档和代码.功夫不负有心人,找到不少有价值的文档和代码.参考这些资料,写了H264 RTP打包类.解包类,实现 ...

  3. h264_rtp打包解包类及实现demo

    打包头文件: class CH2642Rtp { public: CH2642Rtp(uint32_t ssrc, uint8_t payloadType = 96, uint8_t fps = 25 ...

  4. Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口

    Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...

  5. 07.进程管理+作业控制+文件查找与压缩+文件压缩与打包+tar打包解包+NFS

    进程管理 程序放在磁盘上叫文件,把它复制到内存,并在cpu运行,就叫进程, 进程多少也反映当前运行程序的多少 进程在系统中会为每个进程生成一个进程号,在所有的进程中有一个特殊进程即init进程, 它是 ...

  6. Mtk Android 打包解包*.img

    打包/解包 boot.img, system.img, userdata.img, or recovery.img [DESCRIPTION] MTK codebase编译出来的image必须使用MT ...

  7. 【Unity】AssetBundle的使用——打包/解包

    最近参考了各位大神的资源,初步学习了Unity的资源管理模式,包括在编辑器管理(使用AssetDatabase)和在运行时管理(使用Resources和AssetBundle).在此简单总结运行时用A ...

  8. xpack文件打包解包代码库

    Github ###概述 xpack是一个文件资源打包工具及类库,可以对多文件进行打包解包. 其使用文件名的hash作为索引,建立hash索引表以加速文件查找. ###特性 支持hashid自动解冲突 ...

  9. Ruby中星号打包解包操作

    Ruby中可以使用一个星号*和两个星号**完成一些打包.解包操作,它们称为splat操作符: 一个星号:以数组为依据进行打包解包(参考文章) 两个星号:以hash为依据进行打包解包(参考文章) 两个星 ...

随机推荐

  1. hdu 1181(Floyed)

    变形课 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submis ...

  2. codevs——1008 选数

    1008 选数 2002年NOIP全国联赛普及组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 已知 n ...

  3. Maven引入本地Jar包并打包进War包中

    1.概述 在平时的开发中,有一些Jar包因为种种原因,在Maven的中央仓库中没有收录,所以就要使用本地引入的方式加入进来. 2. 拷贝至项目根目录 项目根目录即pom.xml文件所在的同级目录,可以 ...

  4. 在windows下安装gulp[转]

    一.准备工作 1.什么是 npm? npm 是 nodejs 的包管理工具,主要功能就是管理.更新.搜索.发布node的包.Gulp 就是通过 NPM 安装的.关于 NPM 中文介绍,这里有一篇非常不 ...

  5. Hibernate调试——定位查询源头

    本文是我在importNew翻译的文章,首发在importNew,这里会定期更新链接. 为什么有时Hibernate会在程序某一部分生成一条指定sql查询?这个问题让人非常难立马理解.当处理不是我们本 ...

  6. yarn 基本用法

    1.初始化一个新的项目 yarn init 2.添加一个依赖包 yarn add [package] yarn add [package]@[version] yarn add [package]@[ ...

  7. Odoo HRMS应用简介

    Odoo HRMS包含行政管理的大部分功能,包含 部门组织架构 员工清册 岗位规划以及招聘管理 用工合同 考勤管理 休假和加班 费用报销 员工考核 绩效.激励.培训成绩 薪资清册     个角色 角色 ...

  8. BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第11章节--为Office和SP解决方式开发集成Apps Office的JavaScript对象模型

    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第11章节--为Office和SP解决方式开发集成Apps  Office的JavaScript对象模型         ...

  9. 常见Struts、Hibernate、Spring、J2EE、ibatis、Oracle等开发框架架构图及其简介

    各种系统架构图及其简介 转载请保留出处,不胜人生一场醉汇总. 以下文字和架构图均在本人相关系统设计和架构方案中有所应用. 原文出处:http://space.itpub.net/6517/viewsp ...

  10. linux之return和exit引发的大问题(vfork和fork)

    在coolshell.cn上看到的一个问题.为此拿来研究一下. 首先 看看return和exit的差别 在linux上分别跑一下这个代码 int main() { return 0; //exit(0 ...