sdp_file.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:8k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  * Dave Mackie dmackie@cisco.com
  20.  * Bill May  wmay@cisco.com
  21.  */
  22. #include "mp4live.h"
  23. #include <sys/socket.h>
  24. #include <netinet/in.h>
  25. #include <arpa/inet.h>
  26. #include "sdp.h"
  27. #include "mp4.h"
  28. #include "mp4av.h"
  29. bool GenerateSdpFile(CLiveConfig* pConfig)
  30. {
  31. session_desc_t sdp;
  32. memset(&sdp, 0, sizeof(sdp));
  33. // o=
  34. sdp.session_id = GetTimestamp();
  35. sdp.session_version = GetTimestamp();
  36. sdp.create_addr_type = "IP4";
  37. char sHostName[256];
  38. char sIpAddress[16];
  39. if (gethostname(sHostName, sizeof(sHostName)) < 0) {
  40. debug_message("GenerateSdpFile: Couldn't gethostname"); 
  41. strcpy(sIpAddress, "0.0.0.0");
  42. } else {
  43. struct hostent* h = gethostbyname(sHostName);
  44. if (h == NULL) {
  45. debug_message("GenerateSdpFile: Couldn't gethostbyname"); 
  46. strcpy(sIpAddress, "0.0.0.0");
  47. } else {
  48. strcpy(sIpAddress, 
  49. inet_ntoa(*(struct in_addr*)(h->h_addr_list[0])));
  50. }
  51. }
  52. sdp.create_addr = sIpAddress;
  53. // s=
  54. sdp.session_name = pConfig->GetStringValue(CONFIG_SDP_FILE_NAME);
  55. bool destIsMcast = false; // Multicast
  56. bool destIsSSMcast = false; // Single Source Multicast
  57. struct in_addr in;
  58. struct in6_addr in6;
  59. char* sDestAddr = 
  60. pConfig->GetStringValue(CONFIG_RTP_DEST_ADDRESS);
  61. if (inet_aton(sDestAddr, &in)) {
  62. sdp.session_connect.conn_type = "IP4";
  63. destIsMcast = IN_MULTICAST(ntohl(in.s_addr));
  64. if ((ntohl(in.s_addr) >> 24) == 232) {
  65. destIsSSMcast = true;
  66. }
  67. } else if (inet_pton(AF_INET6, sDestAddr, &in6)) {
  68. sdp.session_connect.conn_type = "IP6";
  69. destIsMcast = IN6_IS_ADDR_MULTICAST(&in6);
  70. }
  71. // c=
  72. sdp.session_connect.conn_addr = sDestAddr;
  73. if (destIsMcast) {
  74. sdp.session_connect.ttl = 
  75. pConfig->GetIntegerValue(CONFIG_RTP_MCAST_TTL);
  76. }
  77. sdp.session_connect.used = 1;
  78. // Since we currently don't do anything with RTCP RR's
  79. // and they create unnecessary state in the routers
  80. // tell clients not to generate them
  81. struct bandwidth_t bandwidth;
  82. memset(&bandwidth, 0, sizeof(bandwidth));
  83. sdp.session_bandwidth = &bandwidth;
  84. bandwidth.modifier = BANDWIDTH_MODIFIER_USER; 
  85. bandwidth.bandwidth = 0;
  86. bandwidth.user_band = "RR";
  87. // if SSM, add source filter attribute
  88. if (destIsSSMcast) {
  89. char sIncl[64];
  90. sprintf(sIncl, "a=incl:IN IP4 %s %s",
  91. pConfig->GetStringValue(CONFIG_RTP_DEST_ADDRESS),
  92. sIpAddress);
  93. sdp_add_string_to_list(&sdp.unparsed_a_lines, sIncl);
  94. }
  95. bool audioIsAac =
  96. !strcasecmp(pConfig->GetStringValue(CONFIG_AUDIO_ENCODING),
  97. AUDIO_ENCODING_AAC);
  98. // if ISMA compliant (no audio or AAC audio), add that info
  99. if (!pConfig->GetBoolValue(CONFIG_AUDIO_ENABLE) || audioIsAac) {
  100. sdp_add_string_to_list(&sdp.unparsed_a_lines,
  101. "a=isma-compliance:1,1.0,1");
  102. }
  103. u_int8_t videoProfile = 0xFF;
  104. if (pConfig->GetBoolValue(CONFIG_VIDEO_ENABLE)) {
  105. videoProfile = 
  106. pConfig->GetIntegerValue(CONFIG_VIDEO_PROFILE_ID);
  107. }
  108. u_int8_t audioProfile = 0xFF;
  109. if (pConfig->GetBoolValue(CONFIG_AUDIO_ENABLE)) {
  110. if (audioIsAac) {
  111. audioProfile = 0x0F;
  112. } else {
  113. audioProfile = 0xFE;
  114. }
  115. }
  116. u_int8_t* pAudioConfig = NULL;
  117. u_int32_t audioConfigLength = 0;
  118. if (audioIsAac) {
  119. MP4AV_AacGetConfiguration(
  120. &pAudioConfig,
  121. &audioConfigLength,
  122. MP4AV_AAC_LC_PROFILE,
  123. pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE),
  124. pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS));
  125. }
  126. char* iod =
  127. MP4MakeIsmaSdpIod(
  128. videoProfile,
  129. pConfig->GetIntegerValue(CONFIG_VIDEO_BIT_RATE),
  130. pConfig->m_videoMpeg4Config,
  131. pConfig->m_videoMpeg4ConfigLength,
  132. audioProfile,
  133. pConfig->GetIntegerValue(CONFIG_AUDIO_BIT_RATE),
  134. pAudioConfig,
  135. audioConfigLength,
  136. 0 /* DEBUG MP4_DETAILS_ISMA */);
  137. if (iod) {
  138. sdp_add_string_to_list(&sdp.unparsed_a_lines, iod);
  139. free(iod);
  140. }
  141. // m=
  142. media_desc_t sdpMediaVideo;
  143. format_list_t sdpMediaVideoFormat;
  144. rtpmap_desc_t sdpVideoRtpMap;
  145. char videoFmtpBuf[512];
  146. bandwidth_t videoBandwidth;
  147. if (pConfig->GetBoolValue(CONFIG_VIDEO_ENABLE)) {
  148. memset(&sdpMediaVideo, 0, sizeof(sdpMediaVideo));
  149. sdp.media = &sdpMediaVideo;
  150. sdpMediaVideo.parent = &sdp;
  151. sdpMediaVideo.media = "video";
  152. sdpMediaVideo.port = 
  153. pConfig->GetIntegerValue(CONFIG_RTP_VIDEO_DEST_PORT);
  154. sdpMediaVideo.proto = "RTP/AVP";
  155. sdpMediaVideo.fmt = &sdpMediaVideoFormat;
  156. memset(&sdpMediaVideoFormat, 0, sizeof(sdpMediaVideoFormat));
  157. sdpMediaVideoFormat.media = &sdpMediaVideo;
  158. sdpMediaVideoFormat.fmt = "96";
  159. memset(&sdpVideoRtpMap, 0, sizeof(sdpVideoRtpMap));
  160. sdpVideoRtpMap.encode_name = "MP4V-ES";
  161. sdpVideoRtpMap.clock_rate = 90000;
  162. sdpMediaVideoFormat.rtpmap = &sdpVideoRtpMap;
  163. char* sConfig = MP4BinaryToBase16(
  164. pConfig->m_videoMpeg4Config, 
  165. pConfig->m_videoMpeg4ConfigLength); 
  166. sprintf(videoFmtpBuf, 
  167. "profile-level-id=%u; config=%s;",
  168. pConfig->GetIntegerValue(CONFIG_VIDEO_PROFILE_LEVEL_ID),
  169. sConfig); 
  170. free(sConfig);
  171. sdpMediaVideoFormat.fmt_param = videoFmtpBuf;
  172. memset(&videoBandwidth, 0, sizeof(videoBandwidth));
  173. sdpMediaVideo.media_bandwidth = &videoBandwidth;
  174. videoBandwidth.modifier = BANDWIDTH_MODIFIER_AS; 
  175. videoBandwidth.bandwidth =
  176. pConfig->GetIntegerValue(CONFIG_VIDEO_BIT_RATE);
  177. }
  178. media_desc_t sdpMediaAudio;
  179. format_list_t sdpMediaAudioFormat;
  180. rtpmap_desc_t sdpAudioRtpMap;
  181. bandwidth_t audioBandwidth;
  182. char audioFmtpBuf[512];
  183. if (pConfig->GetBoolValue(CONFIG_AUDIO_ENABLE)) {
  184. if (sdp.media) {
  185. sdp.media->next = &sdpMediaAudio;
  186. } else {
  187. sdp.media = &sdpMediaAudio;
  188. }
  189. memset(&sdpMediaAudio, 0, sizeof(sdpMediaAudio));
  190. sdpMediaAudio.parent = &sdp;
  191. sdpMediaAudio.media = "audio";
  192. sdpMediaAudio.port = 
  193. pConfig->GetIntegerValue(CONFIG_RTP_AUDIO_DEST_PORT);
  194. sdpMediaAudio.proto = "RTP/AVP";
  195. sdpMediaAudio.fmt = &sdpMediaAudioFormat;
  196. memset(&sdpMediaAudioFormat, 0, sizeof(sdpMediaAudioFormat));
  197. sdpMediaAudioFormat.media = &sdpMediaAudio;
  198. sdpMediaAudioFormat.fmt = "97";
  199. memset(&sdpAudioRtpMap, 0, sizeof(sdpAudioRtpMap));
  200. if (!strcasecmp(pConfig->GetStringValue(CONFIG_AUDIO_ENCODING),
  201.   AUDIO_ENCODING_MP3)) {
  202. sdpAudioRtpMap.encode_name = "MPA";
  203. } else if (audioIsAac) {
  204. sdpAudioRtpMap.encode_name = "mpeg4-generic";
  205. char* sConfig = 
  206. MP4BinaryToBase16(pAudioConfig, audioConfigLength);
  207. sprintf(audioFmtpBuf,
  208. "streamtype=5; profile-level-id=15; mode=AAC-hbr; config=%s; "
  209. "SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;",
  210. sConfig); 
  211. free(sConfig);
  212. sdpMediaAudioFormat.fmt_param = audioFmtpBuf;
  213. }
  214. sdpAudioRtpMap.clock_rate = 
  215. pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE);
  216. sdpMediaAudioFormat.rtpmap = &sdpAudioRtpMap;
  217. memset(&audioBandwidth, 0, sizeof(audioBandwidth));
  218. sdpMediaAudio.media_bandwidth = &audioBandwidth;
  219. audioBandwidth.modifier = BANDWIDTH_MODIFIER_AS; 
  220. audioBandwidth.bandwidth =
  221. pConfig->GetIntegerValue(CONFIG_AUDIO_BIT_RATE);
  222. }
  223. free(pAudioConfig);
  224. // finally call sdp library 
  225. // to write the entire sdp description
  226. // to the given sdp file name
  227. bool rc = (sdp_encode_one_to_file(&sdp, 
  228. pConfig->GetStringValue(CONFIG_SDP_FILE_NAME), 0) == 0);
  229. // free malloced memory inside sdp structure
  230. sdp_free_string_list(&sdp.unparsed_a_lines);
  231. return rc;
  232. }