| OLD | NEW |
| 1 /** | 1 /** |
| 2 * Copyright 2016 The Chromium Authors. All rights reserved. | 2 * Copyright 2016 The Chromium Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * See |setSdpDefaultCodec|. | 8 * See |setSdpDefaultCodec|. |
| 9 */ | 9 */ |
| 10 function setSdpDefaultAudioCodec(sdp, codec) { | 10 function setSdpDefaultAudioCodec(sdp, codec) { |
| 11 return setSdpDefaultCodec(sdp, 'audio', codec); | 11 return setSdpDefaultCodec(sdp, 'audio', codec, false /* preferHwCodec */); |
| 12 } | 12 } |
| 13 | 13 |
| 14 /** | 14 /** |
| 15 * See |setSdpDefaultCodec|. | 15 * See |setSdpDefaultCodec|. |
| 16 */ | 16 */ |
| 17 function setSdpDefaultVideoCodec(sdp, codec) { | 17 function setSdpDefaultVideoCodec(sdp, codec, preferHwCodec) { |
| 18 return setSdpDefaultCodec(sdp, 'video', codec); | 18 return setSdpDefaultCodec(sdp, 'video', codec, preferHwCodec); |
| 19 } | 19 } |
| 20 | 20 |
| 21 /** | 21 /** |
| 22 * Returns a modified version of |sdp| where the opus DTX flag has been | 22 * Returns a modified version of |sdp| where the opus DTX flag has been |
| 23 * enabled. | 23 * enabled. |
| 24 */ | 24 */ |
| 25 function setOpusDtxEnabled(sdp) { | 25 function setOpusDtxEnabled(sdp) { |
| 26 var sdpLines = splitSdpLines(sdp); | 26 var sdpLines = splitSdpLines(sdp); |
| 27 | 27 |
| 28 // Get default audio codec | 28 // Get default audio codec |
| (...skipping 19 matching lines...) Expand all Loading... |
| 48 } else { | 48 } else { |
| 49 // Modify the line to enable Opus Dtx. | 49 // Modify the line to enable Opus Dtx. |
| 50 sdpLines[fmtLineNo] += ';usedtx=1' | 50 sdpLines[fmtLineNo] += ';usedtx=1' |
| 51 } | 51 } |
| 52 return mergeSdpLines(sdpLines); | 52 return mergeSdpLines(sdpLines); |
| 53 } | 53 } |
| 54 | 54 |
| 55 /** | 55 /** |
| 56 * Returns a modified version of |sdp| where the |codec| has been promoted to be | 56 * Returns a modified version of |sdp| where the |codec| has been promoted to be |
| 57 * the default codec, i.e. the codec whose ID is first in the list of codecs on | 57 * the default codec, i.e. the codec whose ID is first in the list of codecs on |
| 58 * the 'm=|type|' line, where |type| is 'audio' or 'video'. | 58 * the 'm=|type|' line, where |type| is 'audio' or 'video'. If |preferHwCodec| |
| 59 * is true, it will select the last codec with the given name, and if false, it |
| 60 * will select the first codec with the given name, because HW codecs are listed |
| 61 * after SW codecs in the SDP list. |
| 59 * @private | 62 * @private |
| 60 */ | 63 */ |
| 61 function setSdpDefaultCodec(sdp, type, codec) { | 64 function setSdpDefaultCodec(sdp, type, codec, preferHwCodec) { |
| 62 var sdpLines = splitSdpLines(sdp); | 65 var sdpLines = splitSdpLines(sdp); |
| 63 | 66 |
| 64 // Find codec ID, e.g. 100 for 'VP8' if 'a=rtpmap:100 VP8/9000'. | 67 // Find codec ID, e.g. 100 for 'VP8' if 'a=rtpmap:100 VP8/9000'. |
| 65 var codecId = findRtpmapId(sdpLines, codec); | 68 var codecId = findRtpmapId(sdpLines, codec, preferHwCodec); |
| 66 if (codecId === null) { | 69 if (codecId === null) { |
| 67 failure('setSdpDefaultCodec', | 70 failure('setSdpDefaultCodec', |
| 68 'Unknown ID for |codec| = \'' + codec + '\'.'); | 71 'Unknown ID for |codec| = \'' + codec + '\'.'); |
| 69 } | 72 } |
| 70 | 73 |
| 71 // Find 'm=|type|' line, e.g. 'm=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116'. | 74 // Find 'm=|type|' line, e.g. 'm=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116'. |
| 72 var mLineNo = findLine(sdpLines, 'm=' + type); | 75 var mLineNo = findLine(sdpLines, 'm=' + type); |
| 73 if (mLineNo === null) { | 76 if (mLineNo === null) { |
| 74 failure('setSdpDefaultCodec', | 77 failure('setSdpDefaultCodec', |
| 75 '\'m=' + type + '\' line missing from |sdp|.'); | 78 '\'m=' + type + '\' line missing from |sdp|.'); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 if (defaultCodec === null) { | 125 if (defaultCodec === null) { |
| 123 failure('getSdpDefaultCodec', | 126 failure('getSdpDefaultCodec', |
| 124 'Unknown codec name for default codec ' + defaultCodecId + '.'); | 127 'Unknown codec name for default codec ' + defaultCodecId + '.'); |
| 125 } | 128 } |
| 126 return defaultCodec; | 129 return defaultCodec; |
| 127 } | 130 } |
| 128 | 131 |
| 129 /** | 132 /** |
| 130 * Searches through all |sdpLines| for the 'a=rtpmap:' line for the codec of | 133 * Searches through all |sdpLines| for the 'a=rtpmap:' line for the codec of |
| 131 * the specified name, returning its ID as an int if found, or null otherwise. | 134 * the specified name, returning its ID as an int if found, or null otherwise. |
| 132 * |codec| is the case-sensitive name of the codec. | 135 * |codec| is the case-sensitive name of the codec. If |lastInstance| |
| 136 * is true, it will return the last such ID, and if false, it will return the |
| 137 * first such ID. |
| 133 * For example, if |sdpLines| contains 'a=rtpmap:100 VP8/9000' and |codec| is | 138 * For example, if |sdpLines| contains 'a=rtpmap:100 VP8/9000' and |codec| is |
| 134 * 'VP8', this function returns 100. | 139 * 'VP8', this function returns 100. |
| 135 * @private | 140 * @private |
| 136 */ | 141 */ |
| 137 function findRtpmapId(sdpLines, codec) { | 142 function findRtpmapId(sdpLines, codec, lastInstance) { |
| 138 var lineNo = findRtpmapLine(sdpLines, codec); | 143 var lineNo = findRtpmapLine(sdpLines, codec, lastInstance); |
| 139 if (lineNo === null) | 144 if (lineNo === null) |
| 140 return null; | 145 return null; |
| 141 // Parse <id> from 'a=rtpmap:<id> <codec>/<rate>'. | 146 // Parse <id> from 'a=rtpmap:<id> <codec>/<rate>'. |
| 142 var id = sdpLines[lineNo].substring(9, sdpLines[lineNo].indexOf(' ')); | 147 var id = sdpLines[lineNo].substring(9, sdpLines[lineNo].indexOf(' ')); |
| 143 return parseInt(id); | 148 return parseInt(id); |
| 144 } | 149 } |
| 145 | 150 |
| 146 /** | 151 /** |
| 147 * Searches through all |sdpLines| for the 'a=rtpmap:' line for the codec of | 152 * Searches through all |sdpLines| for the 'a=rtpmap:' line for the codec of |
| 148 * the specified codec ID, returning its name if found, or null otherwise. | 153 * the specified codec ID, returning its name if found, or null otherwise. |
| 149 * For example, if |sdpLines| contains 'a=rtpmap:100 VP8/9000' and |id| is 100, | 154 * For example, if |sdpLines| contains 'a=rtpmap:100 VP8/9000' and |id| is 100, |
| 150 * this function returns 'VP8'. | 155 * this function returns 'VP8'. |
| 151 * @private | 156 * @private |
| 152 */ | 157 */ |
| 153 function findRtpmapCodec(sdpLines, id) { | 158 function findRtpmapCodec(sdpLines, id) { |
| 154 var lineNo = findRtpmapLine(sdpLines, id); | 159 var lineNo = findRtpmapLine(sdpLines, id); |
| 155 if (lineNo === null) | 160 if (lineNo === null) |
| 156 return null; | 161 return null; |
| 157 // Parse <codec> from 'a=rtpmap:<id> <codec>/<rate>'. | 162 // Parse <codec> from 'a=rtpmap:<id> <codec>/<rate>'. |
| 158 var from = sdpLines[lineNo].indexOf(' '); | 163 var from = sdpLines[lineNo].indexOf(' '); |
| 159 var to = sdpLines[lineNo].indexOf('/', from); | 164 var to = sdpLines[lineNo].indexOf('/', from); |
| 160 if (from === null || to === null || from + 1 >= to) | 165 if (from === null || to === null || from + 1 >= to) |
| 161 failure('findRtpmapCodec', ''); | 166 failure('findRtpmapCodec', ''); |
| 162 return sdpLines[lineNo].substring(from + 1, to); | 167 return sdpLines[lineNo].substring(from + 1, to); |
| 163 } | 168 } |
| 164 | 169 |
| 165 /** | 170 /** |
| 166 * Finds the first 'a=rtpmap:' line from |sdpLines| that contains |contains| and | 171 * Finds a 'a=rtpmap:' line from |sdpLines| that contains |contains| and returns |
| 167 * returns its line index, or null if no such line was found. |contains| may be | 172 * its line index, or null if no such line was found. |contains| may be the |
| 168 * the codec ID, codec name or bitrate. An 'a=rtpmap:' line looks like this: | 173 * codec ID, codec name or bitrate. If |lastInstance| is true, it will return |
| 169 * 'a=rtpmap:<id> <codec>/<rate>'. | 174 * the last such line index, and if false, it will return the first such line |
| 175 * index. |
| 176 * An 'a=rtpmap:' line looks like this: 'a=rtpmap:<id> <codec>/<rate>'. |
| 170 */ | 177 */ |
| 171 function findRtpmapLine(sdpLines, contains) { | 178 function findRtpmapLine(sdpLines, contains, lastInstance) { |
| 172 for (var i = 0; i < sdpLines.length; i++) { | 179 if (lastInstance === true) { |
| 173 // Is 'a=rtpmap:' line containing |contains| string? | 180 for (var i = sdpLines.length - 1; i >= 0 ; i--) { |
| 174 if (sdpLines[i].startsWith('a=rtpmap:') && | 181 if (isRtpmapLine(sdpLines[i], contains)) |
| 175 sdpLines[i].indexOf(contains) != -1) { | 182 return i; |
| 176 // Expecting pattern 'a=rtpmap:<id> <codec>/<rate>'. | 183 } |
| 177 var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+'); | 184 } else { |
| 178 if (!sdpLines[i].match(pattern)) | 185 for (var i = 0; i < sdpLines.length; i++) { |
| 179 failure('findRtpmapLine', 'Unexpected "a=rtpmap:" pattern.'); | 186 if (isRtpmapLine(sdpLines[i], contains)) |
| 180 // Return line index. | 187 return i; |
| 181 return i; | |
| 182 } | 188 } |
| 183 } | 189 } |
| 184 return null; | 190 return null; |
| 185 } | 191 } |
| 186 | 192 |
| 187 /** | 193 /** |
| 194 * Returns true if |sdpLine| contains |contains| and is of pattern |
| 195 * 'a=rtpmap:<id> <codec>/<rate>'. |
| 196 */ |
| 197 function isRtpmapLine(sdpLine, contains) { |
| 198 // Is 'a=rtpmap:' line containing |contains| string? |
| 199 if (sdpLine.startsWith('a=rtpmap:') && |
| 200 sdpLine.indexOf(contains) != -1) { |
| 201 // Expecting pattern 'a=rtpmap:<id> <codec>/<rate>'. |
| 202 var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+'); |
| 203 if (!sdpLine.match(pattern)) |
| 204 failure('isRtpmapLine', 'Unexpected "a=rtpmap:" pattern.'); |
| 205 return true; |
| 206 } |
| 207 return false; |
| 208 } |
| 209 |
| 210 /** |
| 188 * Finds the fmtp line in |sdpLines| for the given |codecId|, and returns its | 211 * Finds the fmtp line in |sdpLines| for the given |codecId|, and returns its |
| 189 * line number. The line starts with 'a=fmtp:<codecId>'. | 212 * line number. The line starts with 'a=fmtp:<codecId>'. |
| 190 * @private | 213 * @private |
| 191 */ | 214 */ |
| 192 function findFmtpLine(sdpLines, codecId) { | 215 function findFmtpLine(sdpLines, codecId) { |
| 193 return findLine(sdpLines, 'a=fmtp:' + codecId); | 216 return findLine(sdpLines, 'a=fmtp:' + codecId); |
| 194 | 217 |
| 195 } | 218 } |
| 196 | 219 |
| 197 /** | 220 /** |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 } | 268 } |
| 246 | 269 |
| 247 /** @private */ | 270 /** @private */ |
| 248 function findLine(lines, lineStartsWith, startingLine = 0) { | 271 function findLine(lines, lineStartsWith, startingLine = 0) { |
| 249 for (var i = startingLine; i < lines.length; i++) { | 272 for (var i = startingLine; i < lines.length; i++) { |
| 250 if (lines[i].startsWith(lineStartsWith)) | 273 if (lines[i].startsWith(lineStartsWith)) |
| 251 return i; | 274 return i; |
| 252 } | 275 } |
| 253 return null; | 276 return null; |
| 254 } | 277 } |
| OLD | NEW |