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

流媒体/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 "media_flow.h"
  24. #include "audio_oss_source.h"
  25. #include "video_v4l_source.h"
  26. #include "video_sdl_preview.h"
  27. #include "file_mp4_recorder.h"
  28. #include "rtp_transmitter.h"
  29. #include "file_raw_sink.h"
  30. // Generic Flow
  31. bool CMediaFlow::GetStatus(u_int32_t valueName, void* pValue) 
  32. {
  33. switch (valueName) {
  34. default:
  35. return false;
  36. }
  37. return true;
  38. }
  39. void CAVMediaFlow::Start(void)
  40. {
  41. if (m_started || m_pConfig == NULL) {
  42. return;
  43. }
  44. if (m_pConfig->GetBoolValue(CONFIG_VIDEO_ENABLE) 
  45.   && m_videoSource == NULL) {
  46. const char* sourceType = 
  47. m_pConfig->GetStringValue(CONFIG_VIDEO_SOURCE_TYPE);
  48. if (!strcasecmp(sourceType, VIDEO_SOURCE_V4L)) {
  49. m_videoSource = new CV4LVideoSource();
  50. } else {
  51. error_message("unknown video source type %s", sourceType);
  52. return;
  53. }
  54. m_videoSource->SetConfig(m_pConfig);
  55. m_videoSource->StartThread();
  56. }
  57. if (m_pConfig->GetBoolValue(CONFIG_AUDIO_ENABLE)) {
  58. if (m_pConfig->IsOneSource() && m_videoSource) {
  59. m_audioSource = m_videoSource;
  60. } else {
  61. const char* sourceType = 
  62. m_pConfig->GetStringValue(CONFIG_AUDIO_SOURCE_TYPE);
  63. if (!strcasecmp(sourceType, AUDIO_SOURCE_OSS)) {
  64. SetAudioInput();
  65. m_audioSource = new COSSAudioSource();
  66. } else {
  67. error_message("unknown audio source type %s", sourceType);
  68. return;
  69. }
  70. m_audioSource->SetConfig(m_pConfig);
  71. m_audioSource->StartThread();
  72. }
  73. m_audioSource->SetVideoSource(m_videoSource);
  74. }
  75. if (m_pConfig->GetBoolValue(CONFIG_RECORD_ENABLE)) {
  76. m_mp4Recorder = new CMp4Recorder();
  77. m_mp4Recorder->SetConfig(m_pConfig);
  78. m_mp4Recorder->StartThread();
  79. AddSink(m_mp4Recorder);
  80. }
  81. if (m_pConfig->GetBoolValue(CONFIG_RTP_ENABLE)) {
  82. m_rtpTransmitter = new CRtpTransmitter();
  83. m_rtpTransmitter->SetConfig(m_pConfig);
  84. m_rtpTransmitter->StartThread();
  85. AddSink(m_rtpTransmitter);
  86. }
  87. if (m_pConfig->GetBoolValue(CONFIG_RAW_ENABLE)) {
  88. m_rawSink = new CRawFileSink();
  89. m_rawSink->SetConfig(m_pConfig);
  90. m_rawSink->StartThread();
  91. AddSink(m_rawSink);
  92. }
  93. #ifndef NOGUI
  94. if (m_videoPreview == NULL) {
  95. m_videoPreview = new CSDLVideoPreview();
  96. m_videoPreview->SetConfig(m_pConfig);
  97. m_videoPreview->StartThread();
  98. m_videoPreview->Start();
  99. if (m_videoSource) {
  100. m_videoSource->AddSink(m_videoPreview);
  101. }
  102. }
  103. #endif
  104. if (m_videoSource && m_videoSource == m_audioSource) {
  105. m_videoSource->Start();
  106. } else {
  107. if (m_videoSource) {
  108. m_videoSource->StartVideo();
  109. }
  110. if (m_audioSource) {
  111. m_audioSource->StartAudio();
  112. }
  113. }
  114. if (m_mp4Recorder) {
  115. m_mp4Recorder->Start();
  116. }
  117. if (m_rtpTransmitter) {
  118. m_rtpTransmitter->Start();
  119. }
  120. if (m_rawSink) {
  121. m_rawSink->Start();
  122. }
  123. if (m_videoSource) {
  124. // force video source to generate a key frame
  125. // so that sinks can quickly sync up
  126. m_videoSource->GenerateKeyFrame();
  127. }
  128. m_started = true;
  129. }
  130. void CAVMediaFlow::Stop(void)
  131. {
  132. if (!m_started) {
  133. return;
  134. }
  135. if (m_mp4Recorder) {
  136. RemoveSink(m_mp4Recorder);
  137. m_mp4Recorder->StopThread();
  138. delete m_mp4Recorder;
  139. m_mp4Recorder = NULL;
  140. }
  141. if (m_rtpTransmitter) {
  142. RemoveSink(m_rtpTransmitter);
  143. m_rtpTransmitter->StopThread();
  144. delete m_rtpTransmitter;
  145. m_rtpTransmitter = NULL;
  146. }
  147. if (m_rawSink) {
  148. RemoveSink(m_rawSink);
  149. m_rawSink->StopThread();
  150. delete m_rawSink;
  151. m_rawSink = NULL;
  152. }
  153. bool oneSource = (m_audioSource == m_videoSource);
  154. if (m_audioSource) {
  155. m_audioSource->StopThread();
  156. delete m_audioSource;
  157. m_audioSource = NULL;
  158. }
  159. if (!m_pConfig->IsCaptureVideoSource()) {
  160. if (m_videoSource && !oneSource) {
  161. m_videoSource->StopThread();
  162. delete m_videoSource;
  163. }
  164. m_videoSource = NULL;
  165. #ifndef NOGUI
  166. if (m_videoPreview) {
  167. m_videoPreview->StopThread();
  168. delete m_videoPreview;
  169. m_videoPreview = NULL;
  170. }
  171. #endif
  172. }
  173. m_started = false;
  174. }
  175. void CAVMediaFlow::AddSink(CMediaSink* pSink)
  176. {
  177. if (m_videoSource) {
  178. m_videoSource->AddSink(pSink);
  179. }
  180. if (m_audioSource && m_audioSource != m_videoSource) {
  181. m_audioSource->AddSink(pSink);
  182. }
  183. }
  184. void CAVMediaFlow::RemoveSink(CMediaSink* pSink)
  185. {
  186. if (m_videoSource) {
  187. m_videoSource->RemoveSink(pSink);
  188. }
  189. if (m_audioSource && m_audioSource != m_videoSource) {
  190. m_audioSource->RemoveSink(pSink);
  191. }
  192. }
  193. void CAVMediaFlow::StartVideoPreview(void)
  194. {
  195. if (m_pConfig == NULL) {
  196. return;
  197. }
  198. if (!m_pConfig->IsCaptureVideoSource()) {
  199. return;
  200. }
  201. if (m_videoSource == NULL) {
  202. m_videoSource = new CV4LVideoSource();
  203. m_videoSource->SetConfig(m_pConfig);
  204. m_videoSource->StartThread();
  205. }
  206. if (m_videoPreview == NULL) {
  207. m_videoPreview = new CSDLVideoPreview();
  208. m_videoPreview->SetConfig(m_pConfig);
  209. m_videoPreview->StartThread();
  210. m_videoSource->AddSink(m_videoPreview);
  211. }
  212. m_videoSource->StartVideo();
  213. m_videoPreview->Start();
  214. }
  215. void CAVMediaFlow::StopVideoPreview(void)
  216. {
  217. if (!m_pConfig->IsCaptureVideoSource()) {
  218. return;
  219. }
  220. if (m_videoSource) {
  221. if (!m_started) {
  222. m_videoSource->StopThread();
  223. delete m_videoSource;
  224. m_videoSource = NULL;
  225. } else {
  226. m_videoSource->Stop();
  227. }
  228. }
  229. if (m_videoPreview) {
  230. if (!m_started) {
  231. m_videoPreview->StopThread();
  232. delete m_videoPreview;
  233. m_videoPreview = NULL;
  234. } else {
  235. m_videoPreview->Stop();
  236. }
  237. }
  238. }
  239. void CAVMediaFlow::SetAudioInput(void)
  240. {
  241. // if mixer is specified, then user takes responsibility for
  242. // configuring mixer to set the appropriate input sources
  243. // this allows multiple inputs to be used, for example
  244. if (!strcasecmp(m_pConfig->GetStringValue(CONFIG_AUDIO_INPUT_NAME),
  245.   "mix")) {
  246. return;
  247. }
  248. // else set the mixer input source to the one specified
  249. static char* inputNames[] = SOUND_DEVICE_NAMES;
  250. char* mixerName = 
  251. m_pConfig->GetStringValue(CONFIG_AUDIO_MIXER_NAME);
  252. int mixer = open(mixerName, O_RDONLY);
  253. if (mixer < 0) {
  254. error_message("Couldn't open mixer %s", mixerName);
  255. return;
  256. }
  257. u_int8_t i;
  258. int recmask = 0;
  259. for (i = 0; i < sizeof(inputNames) / sizeof(char*); i++) {
  260. if (!strcasecmp(m_pConfig->GetStringValue(CONFIG_AUDIO_INPUT_NAME),
  261.   inputNames[i])) {
  262. recmask |= (1 << i);
  263. ioctl(mixer, SOUND_MIXER_WRITE_RECSRC, &recmask);
  264. break;
  265. }
  266. }
  267. close(mixer);
  268. }
  269. void CAVMediaFlow::SetAudioOutput(bool mute)
  270. {
  271. static int muted = 0;
  272. static int lastVolume;
  273. char* mixerName = 
  274. m_pConfig->GetStringValue(CONFIG_AUDIO_MIXER_NAME);
  275. int mixer = open(mixerName, O_RDONLY);
  276. if (mixer < 0) {
  277. error_message("Couldn't open mixer %s", mixerName);
  278. return;
  279. }
  280. if (mute) {
  281. ioctl(mixer, SOUND_MIXER_READ_LINE, &lastVolume);
  282. ioctl(mixer, SOUND_MIXER_WRITE_LINE, &muted);
  283. } else {
  284. int newVolume;
  285. ioctl(mixer, SOUND_MIXER_READ_LINE, &newVolume);
  286. if (newVolume == 0) {
  287. ioctl(mixer, SOUND_MIXER_WRITE_LINE, &lastVolume);
  288. }
  289. }
  290. close(mixer);
  291. }
  292. bool CAVMediaFlow::GetStatus(u_int32_t valueName, void* pValue) 
  293. {
  294. CMediaSource* source = NULL;
  295. if (m_videoSource) {
  296. source = m_videoSource;
  297. } else if (m_audioSource) {
  298. source = m_audioSource;
  299. }
  300. switch (valueName) {
  301. case FLOW_STATUS_DONE: 
  302. {
  303. bool done = true;
  304. if (m_videoSource) {
  305. done = m_videoSource->IsDone();
  306. }
  307. if (m_audioSource) {
  308. done = (done && m_audioSource->IsDone());
  309. }
  310. *(bool*)pValue = done;
  311. }
  312. break;
  313. case FLOW_STATUS_DURATION:
  314. if (source) {
  315. *(Duration*)pValue = source->GetElapsedDuration();
  316. } else {
  317. *(Duration*)pValue = 0;
  318. }
  319. break;
  320. case FLOW_STATUS_PROGRESS:
  321. if (source) {
  322. *(float*)pValue = source->GetProgress();
  323. } else {
  324. *(float*)pValue = 0.0;
  325. }
  326. break;
  327. case FLOW_STATUS_VIDEO_ENCODED_FRAMES:
  328. if (m_videoSource) {
  329. *(u_int32_t*)pValue = m_videoSource->GetNumEncodedVideoFrames();
  330. } else {
  331. *(u_int32_t*)pValue = 0;
  332. }
  333. break;
  334. default:
  335. return CMediaFlow::GetStatus(valueName, pValue);
  336. }
  337. return true;
  338. }