OLD | NEW |
---|---|
(Empty) | |
1 /** | |
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 | |
4 * found in the LICENSE file. | |
5 */ | |
6 | |
7 /** | |
8 * See |setSdpDefaultCodec|. | |
9 */ | |
10 function setSdpDefaultAudioCodec(sdp, codec) { | |
11 return setSdpDefaultCodec(sdp, 'audio', codec); | |
12 } | |
13 | |
14 /** | |
15 * See |setSdpDefaultCodec|. | |
16 */ | |
17 function setSdpDefaultVideoCodec(sdp, codec) { | |
18 return setSdpDefaultCodec(sdp, 'video', codec); | |
19 } | |
20 | |
21 /** | |
22 * Returns a modified version of |sdp| where the |codec| has been promoted to be | |
23 * the default codec, i.e. the codec whose ID is first in the list of codecs on | |
24 * the 'm=|type|' line, where |type| is 'audio' or 'video'. | |
25 * @private | |
26 */ | |
27 function setSdpDefaultCodec(sdp, type, codec) { | |
28 var sdpLines = splitSdpLines(sdp); | |
29 | |
30 // Find codec ID, e.g. 100 for 'VP8' if 'a=rtpmap:100 VP8/9000'. | |
31 var codecId = findRtpmapId(sdpLines, codec); | |
32 if (codecId === null) { | |
33 failure_('sdpPreferCodec', 'Unknown ID for |codec| = \'' + codec + '\'.'); | |
phoglund_chromium
2016/02/01 14:20:44
This function is undefined. use failTest defined h
hbos_chromium
2016/02/02 14:07:19
Moved success_ and failure_ to test_functions.js a
| |
34 } | |
35 | |
36 // Find 'm=|type|' line, e.g. 'm=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116'. | |
37 var mLineNo = findLine(sdpLines, 'm=' + type); | |
38 if (mLineNo === null) { | |
39 failure_('setSdpDefaultCodec', | |
40 '\'m=' + type + '\' line missing from |sdp|.'); | |
41 } | |
42 | |
43 // Modify video line to use the desired codec as the default. | |
44 sdpLines[mLineNo] = setMLineDefaultCodec(sdpLines[mLineNo], codecId); | |
45 return mergeSdpLines(sdpLines); | |
46 } | |
47 | |
48 /** | |
49 * See |getSdpDefaultCodec|. | |
50 */ | |
51 function getSdpDefaultAudioCodec(sdp) { | |
52 return getSdpDefaultCodec(sdp, 'audio'); | |
53 } | |
54 | |
55 /** | |
56 * See |getSdpDefaultCodec|. | |
57 */ | |
58 function getSdpDefaultVideoCodec(sdp) { | |
59 return getSdpDefaultCodec(sdp, 'video'); | |
60 } | |
61 | |
62 /** | |
63 * Gets the default codec according to the |sdp|, i.e. the name of the codec | |
64 * whose ID is first in the list of codecs on the 'm=|type|' line, where |type| | |
65 * is 'audio' or 'video'. | |
66 * @private | |
67 */ | |
68 function getSdpDefaultCodec(sdp, type) { | |
69 var sdpLines = splitSdpLines(sdp); | |
70 | |
71 // Find 'm=|type|' line, e.g. 'm=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116'. | |
72 var mLineNo = findLine(sdpLines, 'm=' + type); | |
73 if (mLineNo === null) { | |
74 failure_('getSdpDefaultCodec', | |
75 '\'m=' + type + '\' line missing from |sdp|.'); | |
76 } | |
77 | |
78 // The default codec's ID. | |
79 var defaultCodecId = getMLineDefaultCodec(sdpLines[mLineNo]); | |
80 if (defaultCodecId === null) { | |
81 failure_('getSdpDefaultCodec', | |
82 '\'m=' + type + '\' line contains no codecs.'); | |
83 } | |
84 | |
85 // Find codec name, e.g. 'VP8' for 100 if 'a=rtpmap:100 VP8/9000'. | |
86 var defaultCodec = findRtpmapCodec(sdpLines, defaultCodecId); | |
87 if (defaultCodec === null) { | |
88 failure_('getSdpDefaultCodec', | |
89 'Unknown codec name for default codec ' + defaultCodecId + '.'); | |
90 } | |
91 return defaultCodec; | |
92 } | |
93 | |
94 /** | |
95 * Searches through all |sdpLines| for the 'a=rtpmap:' line for the codec of | |
96 * the specified name, returning its ID as an int if found, or null otherwise. | |
97 * |codec| is the case-sensitive name of the codec. | |
98 * For example, if |sdpLines| contains 'a=rtpmap:100 VP8/9000' and |codec| is | |
99 * 'VP8', this function returns 100. | |
100 * @private | |
101 */ | |
102 function findRtpmapId(sdpLines, codec) { | |
103 var lineNo = findRtpmapLine(sdpLines, codec); | |
104 if (lineNo === null) | |
105 return null; | |
106 // Parse <id> from 'a=rtpmap:<id> <codec>/<rate>'. | |
107 var id = sdpLines[lineNo].substring(9, sdpLines[lineNo].indexOf(' ')); | |
108 return parseInt(id); | |
109 } | |
110 | |
111 /** | |
112 * Searches through all |sdpLines| for the 'a=rtpmap:' line for the codec of | |
113 * the specified codec ID, returning its name if found, or null otherwise. | |
114 * For example, if |sdpLines| contains 'a=rtpmap:100 VP8/9000' and |id| is 100, | |
115 * this function returns 'VP8'. | |
116 * @private | |
117 */ | |
118 function findRtpmapCodec(sdpLines, id) { | |
119 var lineNo = findRtpmapLine(sdpLines, id); | |
120 if (lineNo === null) | |
121 return null; | |
122 // Parse <codec> from 'a=rtpmap:<id> <codec>/<rate>'. | |
123 var from = sdpLines[lineNo].indexOf(' '); | |
124 var to = sdpLines[lineNo].indexOf('/', from); | |
125 if (from === null || to === null || from + 1 >= to) | |
126 failure_('findRtpmapCodec', ''); | |
127 return sdpLines[lineNo].substring(from + 1, to); | |
128 } | |
129 | |
130 /** | |
131 * Finds the first 'a=rtpmap:' line from |sdpLines| that contains |contains| and | |
132 * returns its line index, or null if no such line was found. |contains| may be | |
133 * the codec ID, codec name or bitrate. An 'a=rtpmap:' line looks like this: | |
134 * 'a=rtpmap:<id> <codec>/<rate>'. | |
135 */ | |
136 function findRtpmapLine(sdpLines, contains) { | |
137 for (var i = 0; i < sdpLines.length; i++) { | |
138 // Is 'a=rtpmap:' line containing |contains| string? | |
139 if (sdpLines[i].startsWith('a=rtpmap:') && | |
140 sdpLines[i].indexOf(contains) != -1) { | |
141 // Expecting pattern 'a=rtpmap:<id> <codec>/<rate>'. | |
142 var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+'); | |
143 if (!sdpLines[i].match(pattern)) | |
144 failure_('findRtpmapLine', 'Unexpected "a=rtpmap:" pattern.'); | |
145 // Return line index. | |
146 return i; | |
147 } | |
148 } | |
149 return null; | |
150 } | |
151 | |
152 /** | |
153 * Returns a modified version of |mLine| that has |codecId| first in the list of | |
154 * codec IDs. For example, setMLineDefaultCodec( | |
155 * 'm=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96', 107) | |
156 * Returns: | |
157 * 'm=video 9 UDP/TLS/RTP/SAVPF 107 100 101 116 117 96' | |
158 * @private | |
159 */ | |
160 function setMLineDefaultCodec(mLine, codecId) { | |
161 var elements = mLine.split(' '); | |
162 | |
163 // Copy first three elements, codec order starts on fourth. | |
164 var newLine = elements.slice(0, 3); | |
165 | |
166 // Put target |codecId| first and copy the rest. | |
167 newLine.push(codecId); | |
168 for (var i = 3; i < elements.length; i++) { | |
169 if (elements[i] != codecId) | |
170 newLine.push(elements[i]); | |
171 } | |
172 | |
173 return newLine.join(' '); | |
174 } | |
175 | |
176 /** | |
177 * Returns the default codec's ID from the |mLine|, or null if the codec list is | |
178 * empty. The default codec is the codec whose ID is first in the list of codec | |
179 * IDs on the |mLine|. For example, getMLineDefaultCodec( | |
180 * 'm=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96') | |
181 * Returns: | |
182 * 100 | |
183 * @private | |
184 */ | |
185 function getMLineDefaultCodec(mLine) { | |
186 var elements = mLine.split(' '); | |
187 if (elements.length < 4) | |
188 return null; | |
189 return parseInt(elements[3]); | |
190 } | |
191 | |
192 /** @private */ | |
193 function splitSdpLines(sdp) { | |
194 return sdp.split('\r\n'); | |
195 } | |
196 | |
197 /** @private */ | |
198 function mergeSdpLines(sdpLines) { | |
199 return sdpLines.join('\r\n'); | |
200 } | |
201 | |
202 /** @private */ | |
203 function findLine(lines, startsWith) { | |
204 for (var i = 0; i < lines.length; i++) { | |
205 if (lines[i].startsWith(startsWith)) | |
206 return i; | |
207 } | |
208 return null; | |
209 } | |
OLD | NEW |