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 |