winlin

for #133, rtsp parse the announce packet, parse the sps/pps and audio sequence header by base64.

@@ -92,7 +92,14 @@ int SrsRtspConn::do_cycle() @@ -92,7 +92,14 @@ int SrsRtspConn::do_cycle()
92 if (req->is_options()) { 92 if (req->is_options()) {
93 if ((ret = rtsp->send_message(new SrsRtspOptionsResponse(req->seq))) != ERROR_SUCCESS) { 93 if ((ret = rtsp->send_message(new SrsRtspOptionsResponse(req->seq))) != ERROR_SUCCESS) {
94 if (!srs_is_client_gracefully_close(ret)) { 94 if (!srs_is_client_gracefully_close(ret)) {
95 - srs_error("rtsp: send response failed. ret=%d", ret); 95 + srs_error("rtsp: send OPTIONS response failed. ret=%d", ret);
  96 + }
  97 + return ret;
  98 + }
  99 + } else if (req->is_announce()) {
  100 + if ((ret = rtsp->send_message(new SrsRtspResponse(req->seq))) != ERROR_SUCCESS) {
  101 + if (!srs_is_client_gracefully_close(ret)) {
  102 + srs_error("rtsp: send ANNOUNCE response failed. ret=%d", ret);
96 } 103 }
97 return ret; 104 return ret;
98 } 105 }
@@ -407,3 +407,217 @@ u_int32_t srs_crc32(const void* buf, int size) @@ -407,3 +407,217 @@ u_int32_t srs_crc32(const void* buf, int size)
407 return mpegts_crc32((const u_int8_t*)buf, size); 407 return mpegts_crc32((const u_int8_t*)buf, size);
408 } 408 }
409 409
  410 +/*
  411 + * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
  412 + *
  413 + * This file is part of FFmpeg.
  414 + *
  415 + * FFmpeg is free software; you can redistribute it and/or
  416 + * modify it under the terms of the GNU Lesser General Public
  417 + * License as published by the Free Software Foundation; either
  418 + * version 2.1 of the License, or (at your option) any later version.
  419 + *
  420 + * FFmpeg is distributed in the hope that it will be useful,
  421 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  422 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  423 + * Lesser General Public License for more details.
  424 + *
  425 + * You should have received a copy of the GNU Lesser General Public
  426 + * License along with FFmpeg; if not, write to the Free Software
  427 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  428 + */
  429 +
  430 +#define UINT_MAX 0xffffffff
  431 +
  432 +#ifndef AV_RB32
  433 +# define AV_RB32(x) \
  434 + (((uint32_t)((const u_int8_t*)(x))[0] << 24) | \
  435 + (((const u_int8_t*)(x))[1] << 16) | \
  436 + (((const u_int8_t*)(x))[2] << 8) | \
  437 + ((const u_int8_t*)(x))[3])
  438 +#endif
  439 +
  440 +#ifndef AV_WL32
  441 +# define AV_WL32(p, darg) do { \
  442 + unsigned d = (darg); \
  443 + ((u_int8_t*)(p))[0] = (d); \
  444 + ((u_int8_t*)(p))[1] = (d)>>8; \
  445 + ((u_int8_t*)(p))[2] = (d)>>16; \
  446 + ((u_int8_t*)(p))[3] = (d)>>24; \
  447 + } while(0)
  448 +#endif
  449 +
  450 +# define AV_WN(s, p, v) AV_WL##s(p, v)
  451 +
  452 +# if defined(AV_WN32) && !defined(AV_WL32)
  453 +# define AV_WL32(p, v) AV_WN32(p, v)
  454 +# elif !defined(AV_WN32) && defined(AV_WL32)
  455 +# define AV_WN32(p, v) AV_WL32(p, v)
  456 +# endif
  457 +
  458 +#ifndef AV_WN32
  459 +# define AV_WN32(p, v) AV_WN(32, p, v)
  460 +#endif
  461 +
  462 +#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff))
  463 +#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))
  464 +
  465 +#ifndef av_bswap32
  466 +static const u_int32_t av_bswap32(u_int32_t x)
  467 +{
  468 + return AV_BSWAP32C(x);
  469 +}
  470 +#endif
  471 +
  472 +#define av_be2ne32(x) av_bswap32(x)
  473 +
  474 +/**
  475 + * @file
  476 + * @brief Base64 encode/decode
  477 + * @author Ryan Martell <rdm4@martellventures.com> (with lots of Michael)
  478 + */
  479 +
  480 +/* ---------------- private code */
  481 +static const u_int8_t map2[256] =
  482 +{
  483 + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  484 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  485 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  486 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  487 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  488 + 0xff, 0xff, 0xff,
  489 +
  490 + 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
  491 + 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
  492 + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x01,
  493 + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
  494 + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
  495 + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
  496 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
  497 + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
  498 + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
  499 + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
  500 +
  501 + 0xff, 0xff, 0xff, 0xff, 0xff,
  502 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  503 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  504 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  505 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  506 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  507 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  508 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  509 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  510 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  511 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  512 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  513 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  514 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  515 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  516 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  517 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  518 +};
  519 +
  520 +#define BASE64_DEC_STEP(i) do { \
  521 + bits = map2[in[i]]; \
  522 + if (bits & 0x80) \
  523 + goto out ## i; \
  524 + v = i ? (v << 6) + bits : bits; \
  525 +} while(0)
  526 +
  527 +int srs_av_base64_decode(u_int8_t* out, const char* in_str, int out_size)
  528 +{
  529 + u_int8_t *dst = out;
  530 + u_int8_t *end = out + out_size;
  531 + // no sign extension
  532 + const u_int8_t *in = (const u_int8_t*)in_str;
  533 + unsigned bits = 0xff;
  534 + unsigned v;
  535 +
  536 + while (end - dst > 3) {
  537 + BASE64_DEC_STEP(0);
  538 + BASE64_DEC_STEP(1);
  539 + BASE64_DEC_STEP(2);
  540 + BASE64_DEC_STEP(3);
  541 + // Using AV_WB32 directly confuses compiler
  542 + v = av_be2ne32(v << 8);
  543 + AV_WN32(dst, v);
  544 + dst += 3;
  545 + in += 4;
  546 + }
  547 + if (end - dst) {
  548 + BASE64_DEC_STEP(0);
  549 + BASE64_DEC_STEP(1);
  550 + BASE64_DEC_STEP(2);
  551 + BASE64_DEC_STEP(3);
  552 + *dst++ = v >> 16;
  553 + if (end - dst)
  554 + *dst++ = v >> 8;
  555 + if (end - dst)
  556 + *dst++ = v;
  557 + in += 4;
  558 + }
  559 + while (1) {
  560 + BASE64_DEC_STEP(0);
  561 + in++;
  562 + BASE64_DEC_STEP(0);
  563 + in++;
  564 + BASE64_DEC_STEP(0);
  565 + in++;
  566 + BASE64_DEC_STEP(0);
  567 + in++;
  568 + }
  569 +
  570 +out3:
  571 + *dst++ = v >> 10;
  572 + v <<= 2;
  573 +out2:
  574 + *dst++ = v >> 4;
  575 +out1:
  576 +out0:
  577 + return bits & 1 ? -1 : dst - out;
  578 +}
  579 +
  580 +/*****************************************************************************
  581 +* b64_encode: Stolen from VLC's http.c.
  582 +* Simplified by Michael.
  583 +* Fixed edge cases and made it work from data (vs. strings) by Ryan.
  584 +*****************************************************************************/
  585 +
  586 +char* srs_av_base64_encode(char* out, int out_size, const u_int8_t* in, int in_size)
  587 +{
  588 + static const char b64[] =
  589 + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  590 + char *ret, *dst;
  591 + unsigned i_bits = 0;
  592 + int i_shift = 0;
  593 + int bytes_remaining = in_size;
  594 +
  595 + if (in_size >= (int)(UINT_MAX / 4) ||
  596 + out_size < SRS_AV_BASE64_SIZE(in_size))
  597 + return NULL;
  598 + ret = dst = out;
  599 + while (bytes_remaining > 3) {
  600 + i_bits = AV_RB32(in);
  601 + in += 3; bytes_remaining -= 3;
  602 + *dst++ = b64[ i_bits>>26 ];
  603 + *dst++ = b64[(i_bits>>20) & 0x3F];
  604 + *dst++ = b64[(i_bits>>14) & 0x3F];
  605 + *dst++ = b64[(i_bits>>8 ) & 0x3F];
  606 + }
  607 + i_bits = 0;
  608 + while (bytes_remaining) {
  609 + i_bits = (i_bits << 8) + *in++;
  610 + bytes_remaining--;
  611 + i_shift += 8;
  612 + }
  613 + while (i_shift > 0) {
  614 + *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
  615 + i_shift -= 6;
  616 + }
  617 + while ((dst - ret) & 3)
  618 + *dst++ = '=';
  619 + *dst = '\0';
  620 +
  621 + return ret;
  622 +}
  623 +
@@ -85,5 +85,35 @@ extern bool srs_aac_startswith_adts(SrsStream* stream); @@ -85,5 +85,35 @@ extern bool srs_aac_startswith_adts(SrsStream* stream);
85 */ 85 */
86 extern u_int32_t srs_crc32(const void* buf, int size); 86 extern u_int32_t srs_crc32(const void* buf, int size);
87 87
  88 +/**
  89 +* Decode a base64-encoded string.
  90 +*
  91 +* @param out buffer for decoded data
  92 +* @param in null-terminated input string
  93 +* @param out_size size in bytes of the out buffer, must be at
  94 +* least 3/4 of the length of in
  95 +* @return number of bytes written, or a negative value in case of
  96 +* invalid input
  97 +*/
  98 +extern int srs_av_base64_decode(u_int8_t* out, const char* in, int out_size);
  99 +
  100 +/**
  101 +* Encode data to base64 and null-terminate.
  102 +*
  103 +* @param out buffer for encoded data
  104 +* @param out_size size in bytes of the out buffer (including the
  105 +* null terminator), must be at least AV_BASE64_SIZE(in_size)
  106 +* @param in input buffer containing the data to encode
  107 +* @param in_size size in bytes of the in buffer
  108 +* @return out or NULL in case of error
  109 +*/
  110 +extern char* srs_av_base64_encode(char* out, int out_size, const u_int8_t* in, int in_size);
  111 +
  112 +/**
  113 + * Calculate the output size needed to base64-encode x bytes to a
  114 + * null-terminated string.
  115 + */
  116 +#define SRS_AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
  117 +
88 #endif 118 #endif
89 119
@@ -32,6 +32,8 @@ using namespace std; @@ -32,6 +32,8 @@ using namespace std;
32 #include <srs_kernel_error.hpp> 32 #include <srs_kernel_error.hpp>
33 #include <srs_kernel_log.hpp> 33 #include <srs_kernel_log.hpp>
34 #include <srs_kernel_consts.hpp> 34 #include <srs_kernel_consts.hpp>
  35 +#include <srs_core_autofree.hpp>
  36 +#include <srs_kernel_utility.hpp>
35 37
36 #ifdef SRS_AUTO_STREAM_CASTER 38 #ifdef SRS_AUTO_STREAM_CASTER
37 39
@@ -116,13 +118,290 @@ std::string srs_generate_rtsp_method_str(SrsRtspMethod method) @@ -116,13 +118,290 @@ std::string srs_generate_rtsp_method_str(SrsRtspMethod method)
116 } 118 }
117 } 119 }
118 120
  121 +SrsRtspSdp::SrsRtspSdp()
  122 +{
  123 + state = SrsRtspSdpStateOthers;
  124 +}
  125 +
  126 +SrsRtspSdp::~SrsRtspSdp()
  127 +{
  128 +}
  129 +
  130 +int SrsRtspSdp::parse(string token)
  131 +{
  132 + int ret = ERROR_SUCCESS;
  133 +
  134 + if (token.empty()) {
  135 + srs_info("rtsp: ignore empty token.");
  136 + return ret;
  137 + }
  138 +
  139 + size_t pos = string::npos;
  140 +
  141 + char* start = (char*)token.data();
  142 + char* end = start + (int)token.length();
  143 + char* p = start;
  144 +
  145 + // key, first 2bytes.
  146 + // v=0
  147 + // o=- 0 0 IN IP4 127.0.0.1
  148 + // s=No Name
  149 + // c=IN IP4 192.168.43.23
  150 + // t=0 0
  151 + // a=tool:libavformat 53.9.0
  152 + // m=video 0 RTP/AVP 96
  153 + // b=AS:850
  154 + // a=rtpmap:96 H264/90000
  155 + // a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAKKzRwFAFu/8ALQAiEAAAAwAQAAADAwjxgxHg,aOmrLIs=
  156 + // a=control:streamid=0
  157 + // m=audio 0 RTP/AVP 97
  158 + // b=AS:49
  159 + // a=rtpmap:97 MPEG4-GENERIC/44100/2
  160 + // a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=139056E5A0
  161 + // a=control:streamid=1
  162 + char key = p[0];
  163 + p += 2;
  164 +
  165 + // left bytes as attr string.
  166 + std::string attr_str;
  167 + if (end - p) {
  168 + attr_str.append(p, end - p);
  169 + }
  170 +
  171 + // parse the attributes from left bytes.
  172 + std::vector<std::string> attrs;
  173 + while (p < end) {
  174 + // parse an attribute, split by SP.
  175 + char* pa = p;
  176 + for (; p < end && p[0] != __SRS_RTSP_SP; p++) {
  177 + }
  178 + std::string attr;
  179 + if (p > pa) {
  180 + attr.append(pa, p - pa);
  181 + attrs.push_back(attr);
  182 + }
  183 + p++;
  184 + }
  185 +
  186 + // parse the first attr as desc, update the first elem for desc.
  187 + // for example, the value can be "tool", "AS", "rtpmap", "fmtp", "control"
  188 + std::string desc_key;
  189 + if (attrs.size() > 0) {
  190 + std::string attr = attrs.at(0);
  191 + if ((pos = attr.find(":")) != string::npos) {
  192 + desc_key = attr.substr(0, pos);
  193 + attr = attr.substr(pos + 1);
  194 + attr_str = attr_str.substr(pos + 1);
  195 + attrs[0] = attr;
  196 + } else {
  197 + desc_key = attr;
  198 + }
  199 + }
  200 +
  201 + // interpret the attribute according by key.
  202 + switch (key) {
  203 + case 'v': version = attr_str; break;
  204 + case 'o':
  205 + owner_username = (attrs.size() > 0)? attrs[0]:"";
  206 + owner_session_id = (attrs.size() > 1)? attrs[1]:"";
  207 + owner_session_version = (attrs.size() > 2)? attrs[2]:"";
  208 + owner_network_type = (attrs.size() > 3)? attrs[3]:"";
  209 + owner_address_type = (attrs.size() > 4)? attrs[4]:"";
  210 + owner_address = (attrs.size() > 5)? attrs[5]:"";
  211 + break;
  212 + case 's': session_name = attr_str; break;
  213 + case 'c':
  214 + connection_network_type = (attrs.size() > 0)? attrs[0]:"";
  215 + connection_address_type = (attrs.size() > 0)? attrs[0]:"";
  216 + connection_address = (attrs.size() > 0)? attrs[0]:"";
  217 + break;
  218 + case 'a':
  219 + if (desc_key == "tool") {
  220 + tool = attr_str;
  221 + } else if (desc_key == "rtpmap") {
  222 + if (state == SrsRtspSdpStateVideo) {
  223 + video_codec = (attrs.size() > 1)? attrs[1]:"";
  224 + if ((pos = video_codec.find("/")) != string::npos) {
  225 + video_sample_rate = video_codec.substr(pos + 1);
  226 + video_codec = video_codec.substr(0, pos);
  227 + }
  228 + } else if (state == SrsRtspSdpStateAudio) {
  229 + audio_codec = (attrs.size() > 1)? attrs[1]:"";
  230 + if ((pos = audio_codec.find("/")) != string::npos) {
  231 + audio_sample_rate = audio_codec.substr(pos + 1);
  232 + audio_codec = audio_codec.substr(0, pos);
  233 + }
  234 + if ((pos = audio_codec.find("/")) != string::npos) {
  235 + audio_channel = audio_codec.substr(pos + 1);
  236 + audio_codec = audio_codec.substr(0, pos);
  237 + }
  238 + }
  239 + } else if (desc_key == "fmtp") {
  240 + for (int i = 1; i < (int)attrs.size(); i++) {
  241 + std::string attr = attrs.at(i);
  242 + if ((ret = parse_fmtp_attribute(attr)) != ERROR_SUCCESS) {
  243 + srs_error("rtsp: parse fmtp failed, attr=%s. ret=%d", attr.c_str(), ret);
  244 + return ret;
  245 + }
  246 + }
  247 + } else if (desc_key == "control") {
  248 + for (int i = 0; i < (int)attrs.size(); i++) {
  249 + std::string attr = attrs.at(i);
  250 + if ((ret = parse_control_attribute(attr)) != ERROR_SUCCESS) {
  251 + srs_error("rtsp: parse control failed, attr=%s. ret=%d", attr.c_str(), ret);
  252 + return ret;
  253 + }
  254 + }
  255 + }
  256 + break;
  257 + case 'm':
  258 + if (desc_key == "video") {
  259 + state = SrsRtspSdpStateVideo;
  260 + video_port = (attrs.size() > 1)? attrs[1]:"";
  261 + video_protocol = (attrs.size() > 2)? attrs[2]:"";
  262 + video_transport_format = (attrs.size() > 3)? attrs[3]:"";
  263 + } else if (desc_key == "audio") {
  264 + state = SrsRtspSdpStateAudio;
  265 + audio_port = (attrs.size() > 1)? attrs[1]:"";
  266 + audio_protocol = (attrs.size() > 2)? attrs[2]:"";
  267 + audio_transport_format = (attrs.size() > 3)? attrs[3]:"";
  268 + }
  269 + break;
  270 + case 'b':
  271 + if (desc_key == "AS") {
  272 + if (state == SrsRtspSdpStateVideo) {
  273 + video_bandwidth_kbps = (attrs.size() > 0)? attrs[0]:"";
  274 + } else if (state == SrsRtspSdpStateAudio) {
  275 + audio_bandwidth_kbps = (attrs.size() > 0)? attrs[0]:"";
  276 + }
  277 + }
  278 + break;
  279 + case 't':
  280 + default: break;
  281 + }
  282 +
  283 + return ret;
  284 +}
  285 +
  286 +int SrsRtspSdp::parse_fmtp_attribute(string& attr)
  287 +{
  288 + int ret = ERROR_SUCCESS;
  289 +
  290 + size_t pos = string::npos;
  291 +
  292 + while (!attr.empty()) {
  293 + std::string item = attr;
  294 + if ((pos = item.find(";")) != string::npos) {
  295 + item = attr.substr(0, pos);
  296 + attr = attr.substr(pos + 1);
  297 + } else {
  298 + attr = "";
  299 + }
  300 +
  301 + std::string item_key = item, item_value;
  302 + if ((pos = item.find("=")) != string::npos) {
  303 + item_key = item.substr(0, pos);
  304 + item_value = item.substr(pos + 1);
  305 + }
  306 +
  307 + if (state == SrsRtspSdpStateVideo) {
  308 + if (item_key == "packetization-mode") {
  309 + video_packetization_mode = item_value;
  310 + } else if (item_key == "sprop-parameter-sets") {
  311 + video_sps = item_value;
  312 + if ((pos = video_sps.find(",")) != string::npos) {
  313 + video_pps = video_sps.substr(pos + 1);
  314 + video_sps = video_sps.substr(0, pos);
  315 + }
  316 + // decode the sps/pps by base64
  317 + video_sps = base64_decode(video_sps);
  318 + video_pps = base64_decode(video_pps);
  319 + }
  320 + } else if (state == SrsRtspSdpStateAudio) {
  321 + if (item_key == "profile-level-id") {
  322 + audio_profile_level_id = item_value;
  323 + } else if (item_key == "mode") {
  324 + audio_mode = item_value;
  325 + } else if (item_key == "sizelength") {
  326 + audio_size_length = item_value;
  327 + } else if (item_key == "indexlength") {
  328 + audio_index_length = item_value;
  329 + } else if (item_key == "indexdeltalength") {
  330 + audio_index_delta_length = item_value;
  331 + } else if (item_key == "config") {
  332 + audio_sh = base64_decode(item_value);
  333 + }
  334 + }
  335 + }
  336 +
  337 + return ret;
  338 +}
  339 +
  340 +int SrsRtspSdp::parse_control_attribute(string& attr)
  341 +{
  342 + int ret = ERROR_SUCCESS;
  343 +
  344 + size_t pos = string::npos;
  345 +
  346 + while (!attr.empty()) {
  347 + std::string item = attr;
  348 + if ((pos = item.find(";")) != string::npos) {
  349 + item = attr.substr(0, pos);
  350 + attr = attr.substr(pos + 1);
  351 + } else {
  352 + attr = "";
  353 + }
  354 +
  355 + std::string item_key = item, item_value;
  356 + if ((pos = item.find("=")) != string::npos) {
  357 + item_key = item.substr(0, pos);
  358 + item_value = item.substr(pos + 1);
  359 + }
  360 +
  361 + if (state == SrsRtspSdpStateVideo) {
  362 + if (item_key == "streamid") {
  363 + video_stream_id = item_value;
  364 + }
  365 + } else if (state == SrsRtspSdpStateAudio) {
  366 + if (item_key == "streamid") {
  367 + audio_stream_id = item_value;
  368 + }
  369 + }
  370 + }
  371 +
  372 + return ret;
  373 +}
  374 +
  375 +string SrsRtspSdp::base64_decode(string value)
  376 +{
  377 + if (value.empty()) {
  378 + return "";
  379 + }
  380 +
  381 + int nb_output = (int)(value.length() * 2);
  382 + u_int8_t* output = new u_int8_t[nb_output];
  383 + SrsAutoFree(u_int8_t, output);
  384 +
  385 + int ret = srs_av_base64_decode(output, (char*)value.c_str(), nb_output);
  386 + if (ret <= 0) {
  387 + return "";
  388 + }
  389 +
  390 + std::string plaintext;
  391 + plaintext.append((char*)output, ret);
  392 + return plaintext;
  393 +}
  394 +
119 SrsRtspRequest::SrsRtspRequest() 395 SrsRtspRequest::SrsRtspRequest()
120 { 396 {
121 seq = 0; 397 seq = 0;
  398 + content_length = 0;
  399 + sdp = NULL;
122 } 400 }
123 401
124 SrsRtspRequest::~SrsRtspRequest() 402 SrsRtspRequest::~SrsRtspRequest()
125 { 403 {
  404 + srs_freep(sdp);
126 } 405 }
127 406
128 bool SrsRtspRequest::is_options() 407 bool SrsRtspRequest::is_options()
@@ -130,6 +409,11 @@ bool SrsRtspRequest::is_options() @@ -130,6 +409,11 @@ bool SrsRtspRequest::is_options()
130 return method == __SRS_METHOD_OPTIONS; 409 return method == __SRS_METHOD_OPTIONS;
131 } 410 }
132 411
  412 +bool SrsRtspRequest::is_announce()
  413 +{
  414 + return method == __SRS_METHOD_ANNOUNCE;
  415 +}
  416 +
133 SrsRtspResponse::SrsRtspResponse(int cseq) 417 SrsRtspResponse::SrsRtspResponse(int cseq)
134 { 418 {
135 seq = cseq; 419 seq = cseq;
@@ -306,11 +590,29 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req) @@ -306,11 +590,29 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
306 std::string seq; 590 std::string seq;
307 if ((ret = recv_token_eof(seq)) != ERROR_SUCCESS) { 591 if ((ret = recv_token_eof(seq)) != ERROR_SUCCESS) {
308 if (!srs_is_client_gracefully_close(ret)) { 592 if (!srs_is_client_gracefully_close(ret)) {
309 - srs_error("rtsp: parse seq failed. ret=%d", ret); 593 + srs_error("rtsp: parse %s failed. ret=%d", __SRS_TOKEN_CSEQ, ret);
310 } 594 }
311 return ret; 595 return ret;
312 } 596 }
313 - req->seq = ::atoi(seq.c_str()); 597 + req->seq = ::atol(seq.c_str());
  598 + } else if (token == __SRS_TOKEN_CONTENT_TYPE) {
  599 + std::string ct;
  600 + if ((ret = recv_token_eof(ct)) != ERROR_SUCCESS) {
  601 + if (!srs_is_client_gracefully_close(ret)) {
  602 + srs_error("rtsp: parse %s failed. ret=%d", __SRS_TOKEN_CONTENT_TYPE, ret);
  603 + }
  604 + return ret;
  605 + }
  606 + req->content_type = ct;
  607 + } else if (token == __SRS_TOKEN_CONTENT_LENGTH) {
  608 + std::string cl;
  609 + if ((ret = recv_token_eof(cl)) != ERROR_SUCCESS) {
  610 + if (!srs_is_client_gracefully_close(ret)) {
  611 + srs_error("rtsp: parse %s failed. ret=%d", __SRS_TOKEN_CONTENT_LENGTH, ret);
  612 + }
  613 + return ret;
  614 + }
  615 + req->content_length = ::atol(cl.c_str());
314 } else { 616 } else {
315 // unknown header name, parse util EOF. 617 // unknown header name, parse util EOF.
316 SrsRtspTokenState state = SrsRtspTokenStateNormal; 618 SrsRtspTokenState state = SrsRtspTokenStateNormal;
@@ -327,7 +629,30 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req) @@ -327,7 +629,30 @@ int SrsRtspStack::do_recv_message(SrsRtspRequest* req)
327 } 629 }
328 } 630 }
329 631
330 - // parse body. 632 + // parse rdp body.
  633 + long consumed = 0;
  634 + while (consumed < req->content_length) {
  635 + if (!req->sdp) {
  636 + req->sdp = new SrsRtspSdp();
  637 + }
  638 +
  639 + int nb_token = 0;
  640 + std::string token;
  641 + if ((ret = recv_token_util_eof(token, &nb_token)) != ERROR_SUCCESS) {
  642 + if (!srs_is_client_gracefully_close(ret)) {
  643 + srs_error("rtsp: parse sdp token failed. ret=%d", ret);
  644 + }
  645 + return ret;
  646 + }
  647 + consumed += nb_token;
  648 +
  649 + if ((ret = req->sdp->parse(token)) != ERROR_SUCCESS) {
  650 + srs_error("rtsp: sdp parse token failed, token=%s. ret=%d", token.c_str(), ret);
  651 + return ret;
  652 + }
  653 + srs_info("rtsp: %s", token.c_str());
  654 + }
  655 + srs_info("rtsp: sdp parsed, size=%d", consumed);
331 656
332 return ret; 657 return ret;
333 } 658 }
@@ -382,14 +707,14 @@ int SrsRtspStack::recv_token_eof(std::string& token) @@ -382,14 +707,14 @@ int SrsRtspStack::recv_token_eof(std::string& token)
382 return ret; 707 return ret;
383 } 708 }
384 709
385 -int SrsRtspStack::recv_token_util_eof(std::string& token) 710 +int SrsRtspStack::recv_token_util_eof(std::string& token, int* pconsumed)
386 { 711 {
387 int ret = ERROR_SUCCESS; 712 int ret = ERROR_SUCCESS;
388 713
389 SrsRtspTokenState state; 714 SrsRtspTokenState state;
390 715
391 // use 0x00 as ignore the normal token flag. 716 // use 0x00 as ignore the normal token flag.
392 - if ((ret = recv_token(token, state, 0x00)) != ERROR_SUCCESS) { 717 + if ((ret = recv_token(token, state, 0x00, pconsumed)) != ERROR_SUCCESS) {
393 if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) { 718 if (ret == ERROR_RTSP_REQUEST_HEADER_EOF) {
394 return ret; 719 return ret;
395 } 720 }
@@ -408,7 +733,7 @@ int SrsRtspStack::recv_token_util_eof(std::string& token) @@ -408,7 +733,7 @@ int SrsRtspStack::recv_token_util_eof(std::string& token)
408 return ret; 733 return ret;
409 } 734 }
410 735
411 -int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch) 736 +int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch, int* pconsumed)
412 { 737 {
413 int ret = ERROR_SUCCESS; 738 int ret = ERROR_SUCCESS;
414 739
@@ -474,6 +799,9 @@ int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char @@ -474,6 +799,9 @@ int SrsRtspStack::recv_token(std::string& token, SrsRtspTokenState& state, char
474 // consume the token bytes. 799 // consume the token bytes.
475 srs_assert(p - start); 800 srs_assert(p - start);
476 buf->erase(p - start); 801 buf->erase(p - start);
  802 + if (pconsumed) {
  803 + *pconsumed = p - start;
  804 + }
477 break; 805 break;
478 } 806 }
479 807
@@ -58,6 +58,8 @@ class ISrsProtocolReaderWriter; @@ -58,6 +58,8 @@ class ISrsProtocolReaderWriter;
58 // RTSP token 58 // RTSP token
59 #define __SRS_TOKEN_CSEQ "CSeq" 59 #define __SRS_TOKEN_CSEQ "CSeq"
60 #define __SRS_TOKEN_PUBLIC "Public" 60 #define __SRS_TOKEN_PUBLIC "Public"
  61 +#define __SRS_TOKEN_CONTENT_TYPE "Content-Type"
  62 +#define __SRS_TOKEN_CONTENT_LENGTH "Content-Length"
61 63
62 // RTSP methods 64 // RTSP methods
63 #define __SRS_METHOD_OPTIONS "OPTIONS" 65 #define __SRS_METHOD_OPTIONS "OPTIONS"
@@ -77,6 +79,118 @@ class ISrsProtocolReaderWriter; @@ -77,6 +79,118 @@ class ISrsProtocolReaderWriter;
77 #define __SRS_VERSION "RTSP/1.0" 79 #define __SRS_VERSION "RTSP/1.0"
78 80
79 /** 81 /**
  82 +* the rtsp sdp parse state.
  83 +*/
  84 +enum SrsRtspSdpState
  85 +{
  86 + /**
  87 + * other sdp properties.
  88 + */
  89 + SrsRtspSdpStateOthers,
  90 + /**
  91 + * parse sdp audio state.
  92 + */
  93 + SrsRtspSdpStateAudio,
  94 + /**
  95 + * parse sdp video state.
  96 + */
  97 + SrsRtspSdpStateVideo,
  98 +};
  99 +
  100 +/**
  101 +* the sdp in announce.
  102 +* Appendix C: Use of SDP for RTSP Session Descriptions
  103 +* The Session Description Protocol (SDP, RFC 2327 [6]) may be used to
  104 +* describe streams or presentations in RTSP.
  105 +*/
  106 +class SrsRtspSdp
  107 +{
  108 +private:
  109 + SrsRtspSdpState state;
  110 +public:
  111 + /**
  112 + * the version of sdp.
  113 + */
  114 + std::string version;
  115 + /**
  116 + * the owner/creator of sdp.
  117 + */
  118 + std::string owner_username;
  119 + std::string owner_session_id;
  120 + std::string owner_session_version;
  121 + std::string owner_network_type;
  122 + std::string owner_address_type;
  123 + std::string owner_address;
  124 + /**
  125 + * the session name of sdp.
  126 + */
  127 + std::string session_name;
  128 + /**
  129 + * the connection info of sdp.
  130 + */
  131 + std::string connection_network_type;
  132 + std::string connection_address_type;
  133 + std::string connection_address;
  134 + /**
  135 + * the tool attribute of sdp.
  136 + */
  137 + std::string tool;
  138 + /**
  139 + * the video attribute of sdp.
  140 + */
  141 + std::string video_port;
  142 + std::string video_protocol;
  143 + std::string video_transport_format;
  144 + std::string video_bandwidth_kbps;
  145 + std::string video_codec;
  146 + std::string video_sample_rate;
  147 + std::string video_stream_id;
  148 + // fmtp
  149 + std::string video_packetization_mode;
  150 + std::string video_sps; // sequence header: sps.
  151 + std::string video_pps; // sequence header: pps.
  152 + /**
  153 + * the audio attribute of sdp.
  154 + */
  155 + std::string audio_port;
  156 + std::string audio_protocol;
  157 + std::string audio_transport_format;
  158 + std::string audio_bandwidth_kbps;
  159 + std::string audio_codec;
  160 + std::string audio_sample_rate;
  161 + std::string audio_channel;
  162 + std::string audio_stream_id;
  163 + // fmtp
  164 + std::string audio_profile_level_id;
  165 + std::string audio_mode;
  166 + std::string audio_size_length;
  167 + std::string audio_index_length;
  168 + std::string audio_index_delta_length;
  169 + std::string audio_sh; // sequence header.
  170 +public:
  171 + SrsRtspSdp();
  172 + virtual ~SrsRtspSdp();
  173 +public:
  174 + /**
  175 + * parse a line of token for sdp.
  176 + */
  177 + virtual int parse(std::string token);
  178 +private:
  179 + /**
  180 + * generally, the fmtp is the sequence header for video or audio.
  181 + */
  182 + virtual int parse_fmtp_attribute(std::string& attr);
  183 + /**
  184 + * generally, the control is the stream info for video or audio.
  185 + */
  186 + virtual int parse_control_attribute(std::string& attr);
  187 + /**
  188 + * decode the string by base64.
  189 + */
  190 + virtual std::string base64_decode(std::string value);
  191 +};
  192 +
  193 +/**
80 * the rtsp request message. 194 * the rtsp request message.
81 * 6 Request 195 * 6 Request
82 * A request message from a client to a server or vice versa includes, 196 * A request message from a client to a server or vice versa includes,
@@ -110,12 +224,33 @@ public: @@ -110,12 +224,33 @@ public:
110 * number as the original (i.e. the sequence number is not incremented 224 * number as the original (i.e. the sequence number is not incremented
111 * for retransmissions of the same request). 225 * for retransmissions of the same request).
112 */ 226 */
113 - int seq; 227 + long seq;
  228 + /**
  229 + * 12.16 Content-Type
  230 + * See [H14.18]. Note that the content types suitable for RTSP are
  231 + * likely to be restricted in practice to presentation descriptions and
  232 + * parameter-value types.
  233 + */
  234 + std::string content_type;
  235 + /**
  236 + * 12.14 Content-Length
  237 + * This field contains the length of the content of the method (i.e.
  238 + * after the double CRLF following the last header). Unlike HTTP, it
  239 + * MUST be included in all messages that carry content beyond the header
  240 + * portion of the message. If it is missing, a default value of zero is
  241 + * assumed. It is interpreted according to [H14.14].
  242 + */
  243 + long content_length;
  244 + /**
  245 + * the sdp in announce, NULL for no sdp.
  246 + */
  247 + SrsRtspSdp* sdp;
114 public: 248 public:
115 SrsRtspRequest(); 249 SrsRtspRequest();
116 virtual ~SrsRtspRequest(); 250 virtual ~SrsRtspRequest();
117 public: 251 public:
118 virtual bool is_options(); 252 virtual bool is_options();
  253 + virtual bool is_announce();
119 }; 254 };
120 255
121 /** 256 /**
@@ -159,7 +294,7 @@ public: @@ -159,7 +294,7 @@ public:
159 * number as the original (i.e. the sequence number is not incremented 294 * number as the original (i.e. the sequence number is not incremented
160 * for retransmissions of the same request). 295 * for retransmissions of the same request).
161 */ 296 */
162 - int seq; 297 + long seq;
163 public: 298 public:
164 SrsRtspResponse(int cseq); 299 SrsRtspResponse(int cseq);
165 virtual ~SrsRtspResponse(); 300 virtual ~SrsRtspResponse();
@@ -283,18 +418,20 @@ private: @@ -283,18 +418,20 @@ private:
283 virtual int recv_token_eof(std::string& token); 418 virtual int recv_token_eof(std::string& token);
284 /** 419 /**
285 * read the token util got eof, for example, to read the response status Reason-Phrase 420 * read the token util got eof, for example, to read the response status Reason-Phrase
  421 + * @param pconsumed, output the token parsed length. NULL to ignore.
286 */ 422 */
287 - virtual int recv_token_util_eof(std::string& token); 423 + virtual int recv_token_util_eof(std::string& token, int* pconsumed = NULL);
288 /** 424 /**
289 * read a token from io, split by SP, endswith CRLF: 425 * read a token from io, split by SP, endswith CRLF:
290 * token1 SP token2 SP ... tokenN CRLF 426 * token1 SP token2 SP ... tokenN CRLF
  427 + * @param token, output the read token.
  428 + * @param state, output the token parse state.
291 * @param normal_ch, the char to indicates the normal token. 429 * @param normal_ch, the char to indicates the normal token.
292 * the SP use to indicates the normal token, @see __SRS_RTSP_SP 430 * the SP use to indicates the normal token, @see __SRS_RTSP_SP
293 * the 0x00 use to ignore normal token flag. @see recv_token_util_eof 431 * the 0x00 use to ignore normal token flag. @see recv_token_util_eof
294 - * @param token, output the read token.  
295 - * @param state, output the token parse state. 432 + * @param pconsumed, output the token parsed length. NULL to ignore.
296 */ 433 */
297 - virtual int recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch = __SRS_RTSP_SP); 434 + virtual int recv_token(std::string& token, SrsRtspTokenState& state, char normal_ch = __SRS_RTSP_SP, int* pconsumed = NULL);
298 }; 435 };
299 436
300 #endif 437 #endif