├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package.json └── test ├── fixtures ├── dynamic.js ├── h264.js ├── pcma.js └── pcmu.js ├── packets.js ├── parseRtpPacket.js └── payloadType.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | *.log -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - 0.10 5 | - 0.12 6 | - 4 7 | - 5 8 | 9 | script: 10 | - npm run coverage 11 | 12 | after_script: 13 | - cat ./coverage/lcov.info | coveralls -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Aleksey Timchenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rtp-parser 2 | [![Build Status](https://travis-ci.org/fleg/rtp-parser.svg?branch=master)](https://travis-ci.org/fleg/rtp-parser) 3 | [![Coverage Status](https://coveralls.io/repos/fleg/rtp-parser/badge.svg?branch=master&service=github)](https://coveralls.io/github/fleg/rtp-parser?branch=master) 4 | [![NPM Version](https://img.shields.io/npm/v/rtp-parser.svg)](https://www.npmjs.com/package/rtp-parser) 5 | 6 | RTP packets parser 7 | 8 | ## TODO 9 | - add csrc test 10 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var FIXED_HEADER_LENGTH = 12; 4 | 5 | exports.FIXED_HEADER_LENGTH = FIXED_HEADER_LENGTH; 6 | 7 | exports.parseRtpPacket = function parseRtpPacket(buf) { 8 | if (!Buffer.isBuffer(buf)) { 9 | throw new Error('buffer required'); 10 | } 11 | 12 | if (buf.length < FIXED_HEADER_LENGTH) { 13 | throw new Error('can not parse buffer smaller than fixed header'); 14 | } 15 | 16 | var firstByte = buf.readUInt8(0), 17 | secondByte = buf.readUInt8(1); 18 | 19 | var parsed = { 20 | version: firstByte >> 6, 21 | padding: (firstByte >> 5) & 1, 22 | extension: (firstByte >> 4) & 1, 23 | csrcCount: firstByte & 0x0f, 24 | marker: secondByte >> 7, 25 | payloadType: secondByte & 0x7f, 26 | sequenceNumber: buf.readUInt16BE(2), 27 | timestamp: buf.readUInt32BE(4), 28 | ssrc: buf.readUInt32BE(8), 29 | csrc: [] 30 | }; 31 | 32 | for (var i = 0; i < parsed.csrcCount; i++) { 33 | parsed.csrc.push(buf.readUInt32BE(9 + 4 * i)); 34 | } 35 | 36 | parsed.payload = buf.slice(FIXED_HEADER_LENGTH + 4 * parsed.csrcCount); 37 | 38 | return parsed; 39 | }; 40 | 41 | var payloadTypesHash = { 42 | 0: {name: 'PCMU', mediaType: 'A', clockRate: 8000, channels: 1}, 43 | 1: {name: 'reserved', mediaType: 'A'}, 44 | 2: {name: 'reserved', mediaType: 'A'}, 45 | 3: {name: 'GSM' , mediaType: 'A', clockRate: 8000, channels: 1}, 46 | 4: {name: 'G723', mediaType: 'A', clockRate: 8000, channels: 1}, 47 | 5: {name: 'DVI4', mediaType: 'A', clockRate: 8000, channels: 1}, 48 | 6: {name: 'DVI4', mediaType: 'A', clockRate: 16000, channels: 1}, 49 | 7: {name: 'LPC', mediaType: 'A', clockRate: 8000, channels: 1}, 50 | 8: {name: 'PCMA', mediaType: 'A', clockRate: 8000, channels: 1}, 51 | 9: {name: 'G722', mediaType: 'A', clockRate: 8000, channels: 1}, 52 | 10: {name: 'L16', mediaType: 'A', clockRate: 44100, channels: 2}, 53 | 11: {name: 'L16', mediaType: 'A', clockRate: 44100, channels: 1}, 54 | 12: {name: 'QCELP', mediaType: 'A', clockRate: 8000, channels: 1}, 55 | 13: {name: 'CN', mediaType: 'A', clockRate: 8000, channels: 1}, 56 | 14: {name: 'MPA', mediaType: 'A', clockRate: 90000}, 57 | 15: {name: 'G728', mediaType: 'A', clockRate: 8000, channels: 1}, 58 | 16: {name: 'DVI4', mediaType: 'A', clockRate: 11025, channels: 1}, 59 | 17: {name: 'DVI4', mediaType: 'A', clockRate: 22050, channels: 1}, 60 | 18: {name: 'G729', mediaType: 'A', clockRate: 8000, channels: 1}, 61 | 19: {name: 'reserved', mediaType: 'A'}, 62 | 20: {name: 'unassigned', mediaType: 'A'}, 63 | 21: {name: 'unassigned', mediaType: 'A'}, 64 | 22: {name: 'unassigned', mediaType: 'A'}, 65 | 23: {name: 'unassigned', mediaType: 'A'}, 66 | 24: {name: 'unassigned', mediaType: 'V'}, 67 | 25: {name: 'CelB', mediaType: 'V', clockRate: 90000}, 68 | 26: {name: 'JPEG', mediaType: 'V', clockRate: 90000}, 69 | 27: {name: 'unassigned', mediaType: 'V'}, 70 | 28: {name: 'nv', mediaType: 'V', clockRate: 90000}, 71 | 29: {name: 'unassigned', mediaType: 'V'}, 72 | 30: {name: 'unassigned', mediaType: 'V'}, 73 | 31: {name: 'H261', mediaType: 'V', clockRate: 90000}, 74 | 32: {name: 'MPV', mediaType: 'V', clockRate: 90000}, 75 | 33: {name: 'MP2T', mediaType: 'AV', clockRate: 90000}, 76 | 34: {name: 'H263', mediaType: 'V', clockRate: 90000}, 77 | 35: {name: 'unassigned'}, 78 | 36: {name: 'unassigned'}, 79 | 37: {name: 'unassigned'}, 80 | 38: {name: 'unassigned'}, 81 | 39: {name: 'unassigned'}, 82 | 40: {name: 'unassigned'}, 83 | 41: {name: 'unassigned'}, 84 | 42: {name: 'unassigned'}, 85 | 43: {name: 'unassigned'}, 86 | 44: {name: 'unassigned'}, 87 | 45: {name: 'unassigned'}, 88 | 46: {name: 'unassigned'}, 89 | 47: {name: 'unassigned'}, 90 | 48: {name: 'unassigned'}, 91 | 49: {name: 'unassigned'}, 92 | 50: {name: 'unassigned'}, 93 | 51: {name: 'unassigned'}, 94 | 52: {name: 'unassigned'}, 95 | 53: {name: 'unassigned'}, 96 | 54: {name: 'unassigned'}, 97 | 55: {name: 'unassigned'}, 98 | 56: {name: 'unassigned'}, 99 | 57: {name: 'unassigned'}, 100 | 58: {name: 'unassigned'}, 101 | 59: {name: 'unassigned'}, 102 | 60: {name: 'unassigned'}, 103 | 61: {name: 'unassigned'}, 104 | 62: {name: 'unassigned'}, 105 | 63: {name: 'unassigned'}, 106 | 64: {name: 'unassigned'}, 107 | 65: {name: 'unassigned'}, 108 | 66: {name: 'unassigned'}, 109 | 67: {name: 'unassigned'}, 110 | 68: {name: 'unassigned'}, 111 | 69: {name: 'unassigned'}, 112 | 70: {name: 'unassigned'}, 113 | 71: {name: 'unassigned'}, 114 | 72: {name: 'reserved'}, 115 | 73: {name: 'reserved'}, 116 | 74: {name: 'reserved'}, 117 | 75: {name: 'reserved'}, 118 | 76: {name: 'reserved'}, 119 | 77: {name: 'unassigned'}, 120 | 78: {name: 'unassigned'}, 121 | 79: {name: 'unassigned'}, 122 | 80: {name: 'unassigned'}, 123 | 81: {name: 'unassigned'}, 124 | 82: {name: 'unassigned'}, 125 | 83: {name: 'unassigned'}, 126 | 84: {name: 'unassigned'}, 127 | 85: {name: 'unassigned'}, 128 | 86: {name: 'unassigned'}, 129 | 87: {name: 'unassigned'}, 130 | 88: {name: 'unassigned'}, 131 | 89: {name: 'unassigned'}, 132 | 90: {name: 'unassigned'}, 133 | 91: {name: 'unassigned'}, 134 | 92: {name: 'unassigned'}, 135 | 93: {name: 'unassigned'}, 136 | 94: {name: 'unassigned'}, 137 | 95: {name: 'unassigned'}, 138 | 96: {name: 'dynamic'}, 139 | 97: {name: 'dynamic'}, 140 | 98: {name: 'dynamic'}, 141 | 99: {name: 'dynamic'}, 142 | 100: {name: 'dynamic'}, 143 | 101: {name: 'dynamic'}, 144 | 102: {name: 'dynamic'}, 145 | 103: {name: 'dynamic'}, 146 | 104: {name: 'dynamic'}, 147 | 105: {name: 'dynamic'}, 148 | 106: {name: 'dynamic'}, 149 | 107: {name: 'dynamic'}, 150 | 108: {name: 'dynamic'}, 151 | 109: {name: 'dynamic'}, 152 | 110: {name: 'dynamic'}, 153 | 111: {name: 'dynamic'}, 154 | 112: {name: 'dynamic'}, 155 | 113: {name: 'dynamic'}, 156 | 114: {name: 'dynamic'}, 157 | 115: {name: 'dynamic'}, 158 | 116: {name: 'dynamic'}, 159 | 117: {name: 'dynamic'}, 160 | 118: {name: 'dynamic'}, 161 | 119: {name: 'dynamic'}, 162 | 120: {name: 'dynamic'}, 163 | 121: {name: 'dynamic'}, 164 | 122: {name: 'dynamic'}, 165 | 123: {name: 'dynamic'}, 166 | 124: {name: 'dynamic'}, 167 | 125: {name: 'dynamic'}, 168 | 126: {name: 'dynamic'}, 169 | 127: {name: 'dynamic'} 170 | }; 171 | 172 | exports.payloadTypesHash = payloadTypesHash; 173 | 174 | exports.parseRtpPayloadType = function parseRtpPayloadType(payloadType) { 175 | if (payloadType < 0 || payloadType > 127) { 176 | throw new Error('payload type range error'); 177 | } 178 | 179 | return payloadTypesHash[payloadType]; 180 | }; 181 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rtp-parser", 3 | "version": "1.0.0", 4 | "description": "RTP packets parser", 5 | "author": "Aleksey Timchenko ", 6 | "license": "MIT", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/fleg/rtp-parser.git" 10 | }, 11 | "main": "index.js", 12 | "files": [ 13 | "index.js" 14 | ], 15 | "scripts": { 16 | "test": "mocha test/ --reporter spec", 17 | "coverage": "istanbul cover _mocha -- --reporter spec --timeout 10000" 18 | }, 19 | "keywords": [ 20 | "rtp", 21 | "parser" 22 | ], 23 | "devDependencies": { 24 | "coveralls": "2.11.6", 25 | "expect.js": "0.3.1", 26 | "istanbul": "0.4.2", 27 | "mocha": "2.4.5", 28 | "underscore": "1.8.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/fixtures/dynamic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.packet = new Buffer( 4 | '80639408482795a973ed01010087b200000087b2020337ef8073f4784d000000' + 5 | '87b200000087b200000087b200000087b200000087b200000087b200000087b2' + 6 | '00000087b200000087b200000087b200000087b200000087b200000087b20000' + 7 | '0087b200000087b200000087b200000087b200000087b200000087b200000087' + 8 | 'b200000087b200000087b200000087b200000087b200000087b200000087b200' + 9 | '000087b200000087b2000000', 'hex' 10 | ); 11 | 12 | exports.parsed = { 13 | version: 2, 14 | padding: 0, 15 | extension: 0, 16 | csrcCount: 0, 17 | marker: 0, 18 | payloadType: 99, 19 | sequenceNumber: 37896, 20 | timestamp: 1210553769, 21 | ssrc: 0x73ed0101, 22 | csrc: [], 23 | payload: new Buffer( 24 | '0087b200000087b2020337ef8073f4784d00000087b200000087b200000087b2' + 25 | '00000087b200000087b200000087b200000087b200000087b200000087b20000' + 26 | '0087b200000087b200000087b200000087b200000087b200000087b200000087' + 27 | 'b200000087b200000087b200000087b200000087b200000087b200000087b200' + 28 | '000087b200000087b200000087b200000087b200000087b200000087b2000000', 'hex' 29 | ) 30 | }; 31 | -------------------------------------------------------------------------------- /test/fixtures/h264.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.packet = new Buffer( 4 | '806000010e3ba23214d5629d5c819a6c04f5ca4e35109ee53f1ef2e24fbfaf8a' + 5 | '6c4dec5fdad7e6b16be2132fbfc4352745d17f22b71fc788761e796ff09340fd' + 6 | '7f2ebf84958bd85f23d7e2c99182021d7e46d316b89ca5503ec5f9ba1d713497' + 7 | '7eb9bb75c9dfefafc9a07be5bff26c5f97ddf22b17edebf2d03eb929b0bf691f' + 8 | 'f2b5ef973bb5c846dbfc7f4f8ec4fe9f882d9745f89d8fafe6ebf7d7e2347ca9' + 9 | 'fe2965634ff7475ae20bd23e7d72117d2e085a90dfddcc12d9c9cddaf97b57cc' + 10 | 'fb5e2d3fbb7f2f41fcde835cde9f8bc7717ada1d07e202287f65f044dff7cdd6' + 11 | 'b88097ab7fdf0f38d9fa09bc294e5dc29589e4090e0413fe6b3eb93a5f0cc7a3' + 12 | '7eaffd7264fae33a7912735fd7cbbfe4a17f7d85f11e823a483fe3a3272b871b' + 13 | '8003cf09f0226d6f24cebb0ac32cb77b9c2db529b94e7ff867ad46859ffffd05' + 14 | '1185e208117cff4bab8b19cc21cccfc267a02f958f130976eef8e26c0ebbe2fb' + 15 | '03d7f1d1f4cff5a3a7f18fb56be58f1d8d1bb98f395a0c92b57c833255bf12ac' + 16 | '0c60bfbca63f897190ca6fef7cca3a5fff18edfc6875f8cce37ff13d05fcf9b1' + 17 | 'd3d29a9c70a8d995ac2fd2e8debd15cc318bf841df65ec354bca4d07f31583eb' + 18 | '954f1c5ead422b122a3d439c48ce9f6c31c51287629d9c9caf41c26168f2ef41' + 19 | '6c7ff0f08a686f5e9153c7730ccd0862b0e76ed6757517d0ba93ad49d6b54bf6' + 20 | '337ae86f45eecf70caae24473f4b511cde196585f5a858f626c025ebd7c708d1' + 21 | '50f96b45f136bf4616bcc2a25b12f40ee097a552f29ba7e2496e81dac67376a6' + 22 | 'e85d42fb87f986770cf436a0a0570634e0bb98631f11d0da8553b525286ab30a' + 23 | 'da0aa3afeb511d7abad575aabc575aaebd2561086c3d62b567b50f74ba1aaca1' + 24 | '3b22463efd8ffa7a738ae24fa105bb19db1d4e256f116af51478d51b08640b39' + 25 | '16d97ffc37d2efad7d7bb34dd7abaf42caae080458c5412e519d21bd0be89dd6' + 26 | 'e0efaf47f5e85b70b0ab8438a1883f7d709a65dbe13dc1cf436a066dc140ab9e' + 27 | '946f28c2d38de448f8f09c7973417f7f85a332ee17dc31cc4842f47094cf09cb' + 28 | 'fd3ff8beb14255838dcbb90554e2ad2308c98b9446ff47e93b36d5a11b836a70' + 29 | 'bf64b7876dc1485a2fff299fcbc2666fc91c2bd1fa5b71816cb9ff417e1ae9f4' + 30 | '7f098c6fec77d0ba93ad41a422e3c299944a77fff559390569c2fc59e441543a' + 31 | '7371eeefafac6720c0899ffdfc5ee17151ec0cbcc2a9e4e86d45a6f939871a3d' + 32 | '72fa619e1074be527bd70913aeaa4e2fb6966b85c547cbcc2bb84b956767e4d3' + 33 | 'fc8997f093d6874387bb7bbae62b697e5375bc90992dfbfcb3a1eb97297d7368' + 34 | 'e81ae53eb13d0be9055364e611b7f0917210ede2ef3f089b4ba7b05f9740bf09' + 35 | 'aedd8ac5e56d70bf2bde4ef6bf11e37d1b747f88f5324d8ab8f2e81eded35f8b' + 36 | '3173a5fdb7fe44cbfb7d25c5dbf3ffcbd05f124e522cff5324bf95b3eb935fda' + 37 | 'b0bf27b1ae6543fcb4bbe67b5f2f4917845efdaf60fc589cb1292b58db513c21' + 38 | '5fc6444fb37c2622fbff6d8bb7b5f1c27540dbf96e44d70b72885e5e5d3d71d6' + 39 | '5f4fb77ca4d055c59fb0a868fe39641ff2958177dd7f841bf415af62b7fec9b2' + 40 | 'f897d1e9572aedf89f5a2fc43b1e97f698481fe552cff2edfe13f7d8525b8ee1' + 41 | '32dbe81a1f5c87b0f11c85c3b4cfcc4e832f47aba526ef8a3317a078fe1026be' + 42 | 'f9ffc4f5a076be65605ae44c5fc8ebf887a74e8ab9937fdfb12e6561535c73e8' + 43 | '2af6b2f136b411d6fd7e54ffc4b3cfd0e92e123b7fb9b848cfd3e5111e5185b7' + 44 | 'eb844457dbd2d72d03e4e3debb74f49256efb5d1bac5ee14e209647fd9e2f916' + 45 | 'd4bcda5f939d07cd43eb94fdb1fcc66b955bfc609b5d2e521fa47e8b517d5e2f' + 46 | '90db149c244d977f892ec51e121f5c51b9d276304bd0da8ae315931f311a1f69' + 47 | 'bc3dc264b1fd87e3b96f6b277e3b896653d54e638ae1036bd16653853715c61f' + 48 | '796e8abcea386799141056618433c84b7ae28a41890bf7c7747e97a751faeb09' + 49 | '720ceab89afe7545e65b', 'hex' 50 | ); 51 | 52 | exports.parsed = { 53 | version: 2, 54 | padding: 0, 55 | extension: 0, 56 | csrcCount: 0, 57 | marker: 0, 58 | payloadType: 96, 59 | sequenceNumber: 1, 60 | timestamp: 238789170, 61 | ssrc: 0x14d5629d, 62 | csrc: [], 63 | payload: new Buffer( 64 | '5c819a6c04f5ca4e35109ee53f1ef2e24fbfaf8a6c4dec5fdad7e6b16be2132f' + 65 | 'bfc4352745d17f22b71fc788761e796ff09340fd7f2ebf84958bd85f23d7e2c9' + 66 | '9182021d7e46d316b89ca5503ec5f9ba1d7134977eb9bb75c9dfefafc9a07be5' + 67 | 'bff26c5f97ddf22b17edebf2d03eb929b0bf691ff2b5ef973bb5c846dbfc7f4f' + 68 | '8ec4fe9f882d9745f89d8fafe6ebf7d7e2347ca9fe2965634ff7475ae20bd23e' + 69 | '7d72117d2e085a90dfddcc12d9c9cddaf97b57ccfb5e2d3fbb7f2f41fcde835c' + 70 | 'de9f8bc7717ada1d07e202287f65f044dff7cdd6b88097ab7fdf0f38d9fa09bc' + 71 | '294e5dc29589e4090e0413fe6b3eb93a5f0cc7a37eaffd7264fae33a7912735f' + 72 | 'd7cbbfe4a17f7d85f11e823a483fe3a3272b871b8003cf09f0226d6f24cebb0a' + 73 | 'c32cb77b9c2db529b94e7ff867ad46859ffffd051185e208117cff4bab8b19cc' + 74 | '21cccfc267a02f958f130976eef8e26c0ebbe2fb03d7f1d1f4cff5a3a7f18fb5' + 75 | '6be58f1d8d1bb98f395a0c92b57c833255bf12ac0c60bfbca63f897190ca6fef' + 76 | '7cca3a5fff18edfc6875f8cce37ff13d05fcf9b1d3d29a9c70a8d995ac2fd2e8' + 77 | 'debd15cc318bf841df65ec354bca4d07f31583eb954f1c5ead422b122a3d439c' + 78 | '48ce9f6c31c51287629d9c9caf41c26168f2ef416c7ff0f08a686f5e9153c773' + 79 | '0ccd0862b0e76ed6757517d0ba93ad49d6b54bf6337ae86f45eecf70caae2447' + 80 | '3f4b511cde196585f5a858f626c025ebd7c708d150f96b45f136bf4616bcc2a2' + 81 | '5b12f40ee097a552f29ba7e2496e81dac67376a6e85d42fb87f986770cf436a0' + 82 | 'a0570634e0bb98631f11d0da8553b525286ab30ada0aa3afeb511d7abad575aa' + 83 | 'bc575aaebd2561086c3d62b567b50f74ba1aaca13b22463efd8ffa7a738ae24f' + 84 | 'a105bb19db1d4e256f116af51478d51b08640b3916d97ffc37d2efad7d7bb34d' + 85 | 'd7abaf42caae080458c5412e519d21bd0be89dd6e0efaf47f5e85b70b0ab8438' + 86 | 'a1883f7d709a65dbe13dc1cf436a066dc140ab9e946f28c2d38de448f8f09c79' + 87 | '73417f7f85a332ee17dc31cc4842f47094cf09cbfd3ff8beb14255838dcbb905' + 88 | '54e2ad2308c98b9446ff47e93b36d5a11b836a70bf64b7876dc1485a2fff299f' + 89 | 'cbc2666fc91c2bd1fa5b71816cb9ff417e1ae9f47f098c6fec77d0ba93ad41a4' + 90 | '22e3c299944a77fff559390569c2fc59e441543a7371eeefafac6720c0899ffd' + 91 | 'fc5ee17151ec0cbcc2a9e4e86d45a6f939871a3d72fa619e1074be527bd70913' + 92 | 'aeaa4e2fb6966b85c547cbcc2bb84b956767e4d3fc8997f093d6874387bb7bba' + 93 | 'e62b697e5375bc90992dfbfcb3a1eb97297d7368e81ae53eb13d0be9055364e6' + 94 | '11b7f0917210ede2ef3f089b4ba7b05f9740bf09aedd8ac5e56d70bf2bde4ef6' + 95 | 'bf11e37d1b747f88f5324d8ab8f2e81eded35f8b3173a5fdb7fe44cbfb7d25c5' + 96 | 'dbf3ffcbd05f124e522cff5324bf95b3eb935fdab0bf27b1ae6543fcb4bbe67b' + 97 | '5f2f4917845efdaf60fc589cb1292b58db513c215fc6444fb37c2622fbff6d8b' + 98 | 'b7b5f1c27540dbf96e44d70b72885e5e5d3d71d65f4fb77ca4d055c59fb0a868' + 99 | 'fe39641ff2958177dd7f841bf415af62b7fec9b2f897d1e9572aedf89f5a2fc4' + 100 | '3b1e97f698481fe552cff2edfe13f7d8525b8ee132dbe81a1f5c87b0f11c85c3' + 101 | 'b4cfcc4e832f47aba526ef8a3317a078fe1026bef9ffc4f5a076be65605ae44c' + 102 | '5fc8ebf887a74e8ab9937fdfb12e6561535c73e82af6b2f136b411d6fd7e54ff' + 103 | 'c4b3cfd0e92e123b7fb9b848cfd3e5111e5185b7eb844457dbd2d72d03e4e3de' + 104 | 'bb74f49256efb5d1bac5ee14e209647fd9e2f916d4bcda5f939d07cd43eb94fd' + 105 | 'b1fcc66b955bfc609b5d2e521fa47e8b517d5e2f90db149c244d977f892ec51e' + 106 | '121f5c51b9d276304bd0da8ae315931f311a1f69bc3dc264b1fd87e3b96f6b27' + 107 | '7e3b896653d54e638ae1036bd16653853715c61f796e8abcea38679914105661' + 108 | '8433c84b7ae28a41890bf7c7747e97a751faeb09720ceab89afe7545e65b', 'hex' 109 | ) 110 | }; 111 | -------------------------------------------------------------------------------- /test/fixtures/pcma.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.packet = new Buffer( 4 | '8008e70d00000ff0dee0ee8fd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 5 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 6 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 7 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 8 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 9 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 10 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 11 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5', 'hex' 12 | ); 13 | 14 | exports.parsed = { 15 | version: 2, 16 | padding: 0, 17 | extension: 0, 18 | csrcCount: 0, 19 | marker: 0, 20 | payloadType: 8, 21 | sequenceNumber: 59149, 22 | timestamp: 4080, 23 | ssrc: 0xdee0ee8f, 24 | csrc: [], 25 | payload: new Buffer( 26 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 27 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 28 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 29 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 30 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 31 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 32 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5' + 33 | 'd5d5d5d5d5d5d5d5d5d5d5d5d5d5d5d5', 'hex' 34 | ) 35 | }; 36 | -------------------------------------------------------------------------------- /test/fixtures/pcmu.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.packet = new Buffer( 4 | '80802fc0019e81841736bd54fffefefefe7e7e7e7d7effff7e7e7e7e7efefeff' + 5 | 'ff7e7eff7e7eff7dfffeff7e7e7efffefeff7e7e7e7eff7effff7e7e7efeffff' + 6 | 'feffff7eff7e7e7e7e7eff7efffeffffff7e7e7eff7efffe7e7e7eff7e7efe7e' + 7 | 'fffe7e7e7e7efffeff7effff7e7effff7e7d7e7e7efefefefe7e7e7e7eff7e7e' + 8 | '7e7e7e7e7eff7e7effff7e7effffffff7eff7effff7efffefefffffeff7e7e7e' + 9 | '7e7e7e7efefeff7e7d7e7e7efe7e7e7e7d7efffefffefffefeff7e7efffefe7e' + 10 | '7e7e7efeff7eff7e7eff7efefefe7e7d7e7e7e7e7effff7eff7effff7dffffff' + 11 | 'ffff7e7eff7e7efffffefeff7eff7e7e7eff7eff7e7e7e7d7efeffff', 'hex' 12 | ); 13 | 14 | exports.parsed = { 15 | version: 2, 16 | padding: 0, 17 | extension: 0, 18 | csrcCount: 0, 19 | marker: 1, 20 | payloadType: 0, 21 | sequenceNumber: 12224, 22 | timestamp: 27165060, 23 | ssrc: 0x1736bd54, 24 | csrc: [], 25 | payload: new Buffer( 26 | 'fffefefefe7e7e7e7d7effff7e7e7e7e7efefeffff7e7eff7e7eff7dfffeff7e' + 27 | '7e7efffefeff7e7e7e7eff7effff7e7e7efefffffeffff7eff7e7e7e7e7eff7e' + 28 | 'fffeffffff7e7e7eff7efffe7e7e7eff7e7efe7efffe7e7e7e7efffeff7effff' + 29 | '7e7effff7e7d7e7e7efefefefe7e7e7e7eff7e7e7e7e7e7e7eff7e7effff7e7e' + 30 | 'ffffffff7eff7effff7efffefefffffeff7e7e7e7e7e7e7efefeff7e7d7e7e7e' + 31 | 'fe7e7e7e7d7efffefffefffefeff7e7efffefe7e7e7e7efeff7eff7e7eff7efe' + 32 | 'fefe7e7d7e7e7e7e7effff7eff7effff7dffffffffff7e7eff7e7efffffefeff' + 33 | '7eff7e7e7eff7eff7e7e7e7d7efeffff', 'hex' 34 | ) 35 | }; 36 | -------------------------------------------------------------------------------- /test/packets.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('underscore'), 4 | expect = require('expect.js'), 5 | parseRtpPacket = require('../index').parseRtpPacket; 6 | 7 | describe('packets test', function() { 8 | _(['h264', 'pcma', 'pcmu', 'dynamic']).each(function(name) { 9 | it('parse `' + name + '` packet', function() { 10 | var fixture = require('./fixtures/' + name), 11 | expected = fixture.parsed, 12 | parsed = parseRtpPacket(fixture.packet); 13 | 14 | expect(expected.version).to.equal(parsed.version); 15 | expect(expected.padding).to.equal(parsed.padding); 16 | expect(expected.extension).to.equal(parsed.extension); 17 | expect(expected.csrcCount).to.equal(parsed.csrcCount); 18 | expect(expected.marker).to.equal(parsed.marker); 19 | expect(expected.payloadType).to.equal(parsed.payloadType); 20 | expect(expected.sequenceNumber).to.equal(parsed.sequenceNumber); 21 | expect(expected.timestamp).to.equal(parsed.timestamp); 22 | expect(expected.ssrc).to.equal(parsed.ssrc); 23 | expect(expected.payload.toString('hex')) 24 | .to.equal(parsed.payload.toString('hex')); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/parseRtpPacket.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var expect = require('expect.js'), 4 | parseRtpPacket = require('../index').parseRtpPacket; 5 | 6 | describe('parser test', function() { 7 | it('should throw error on non-buffer', function() { 8 | expect(function() { 9 | parseRtpPacket('i am not buffer'); 10 | }).to.throwException(/buffer required/); 11 | }); 12 | 13 | it('should throw error on buffer smaller than fixed header', function() { 14 | expect(function() { 15 | parseRtpPacket(new Buffer('deadbeef', 'hex')); 16 | }).to.throwException(/can not parse buffer smaller than fixed header/); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /test/payloadType.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _ = require('underscore'), 4 | expect = require('expect.js'), 5 | payloadTypesHash = require('../index').payloadTypesHash, 6 | parseRtpPayloadType = require('../index').parseRtpPayloadType; 7 | 8 | var PAYLOAD_TYPES = 128; 9 | 10 | describe('payload type test', function() { 11 | it('should have ' + PAYLOAD_TYPES + ' types', function() { 12 | expect(_(payloadTypesHash).keys()).to.have.length(PAYLOAD_TYPES); 13 | expect(payloadTypesHash).to.only.have.keys( 14 | _(PAYLOAD_TYPES).chain().range().map(String).value() 15 | ); 16 | }); 17 | 18 | it('should throw error on bad types', function() { 19 | var error = /payload type range error/; 20 | 21 | expect(function() { 22 | parseRtpPayloadType(-1); 23 | }).to.throwException(error); 24 | 25 | expect(function() { 26 | parseRtpPayloadType(128); 27 | }).to.throwException(error); 28 | }); 29 | 30 | it('check random types', function() { 31 | expect(parseRtpPayloadType(26)).to.have.property('name', 'JPEG'); 32 | expect(parseRtpPayloadType(8)).to.have.property('name', 'PCMA'); 33 | expect(parseRtpPayloadType(0)).to.have.property('name', 'PCMU'); 34 | }); 35 | }); 36 | --------------------------------------------------------------------------------