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

流媒体/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-2002.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  * Dave Mackie dmackie@cisco.com
  20.  */
  21. #include "mp4live.h"
  22. #include "media_source.h"
  23. #include "audio_encoder.h"
  24. #include "video_encoder.h"
  25. #include "video_util_rgb.h"
  26. #include <mp4av.h>
  27. CMediaSource::CMediaSource() 
  28. {
  29. m_pSinksMutex = SDL_CreateMutex();
  30. if (m_pSinksMutex == NULL) {
  31. debug_message("CreateMutex error");
  32. }
  33. for (int i = 0; i < MAX_SINKS; i++) {
  34. m_sinks[i] = NULL;
  35. }
  36. m_source = false;
  37. m_sourceVideo = false;
  38. m_sourceAudio = false;
  39. m_maxAheadDuration = TimestampTicks / 2 ; // 500 msec
  40. m_videoSource = this;
  41. m_videoSrcYImage = NULL;
  42. m_videoDstYImage = NULL;
  43. m_videoYResizer = NULL;
  44. m_videoSrcUVImage = NULL;
  45. m_videoDstUVImage = NULL;
  46. m_videoUVResizer = NULL;
  47. m_videoEncoder = NULL;
  48. m_videoDstPrevImage = NULL;
  49. m_videoDstPrevReconstructImage = NULL;
  50. m_videoDstPrevFrame = NULL;
  51. m_audioResampleInputBuffer = NULL;
  52. m_audioPreEncodingBuffer = NULL;
  53. m_audioEncoder = NULL;
  54. }
  55. CMediaSource::~CMediaSource() 
  56. {
  57. SDL_DestroyMutex(m_pSinksMutex);
  58. m_pSinksMutex = NULL;
  59. }
  60. bool CMediaSource::AddSink(CMediaSink* pSink) 
  61. {
  62. bool rc = false;
  63. if (SDL_LockMutex(m_pSinksMutex) == -1) {
  64. debug_message("AddSink LockMutex error");
  65. return rc;
  66. }
  67. for (int i = 0; i < MAX_SINKS; i++) {
  68. if (m_sinks[i] == NULL) {
  69. m_sinks[i] = pSink;
  70. rc = true;
  71. break;
  72. }
  73. }
  74. if (SDL_UnlockMutex(m_pSinksMutex) == -1) {
  75. debug_message("UnlockMutex error");
  76. }
  77. return rc;
  78. }
  79. void CMediaSource::RemoveSink(CMediaSink* pSink) 
  80. {
  81. if (SDL_LockMutex(m_pSinksMutex) == -1) {
  82. debug_message("RemoveSink LockMutex error");
  83. return;
  84. }
  85. for (int i = 0; i < MAX_SINKS; i++) {
  86. if (m_sinks[i] == pSink) {
  87. int j;
  88. for (j = i; j < MAX_SINKS - 1; j++) {
  89. m_sinks[j] = m_sinks[j+1];
  90. }
  91. m_sinks[j] = NULL;
  92. break;
  93. }
  94. }
  95. if (SDL_UnlockMutex(m_pSinksMutex) == -1) {
  96. debug_message("UnlockMutex error");
  97. }
  98. }
  99. void CMediaSource::RemoveAllSinks(void) 
  100. {
  101. if (SDL_LockMutex(m_pSinksMutex) == -1) {
  102. debug_message("RemoveAllSinks LockMutex error");
  103. return;
  104. }
  105. for (int i = 0; i < MAX_SINKS; i++) {
  106. if (m_sinks[i] == NULL) {
  107. break;
  108. }
  109. m_sinks[i] = NULL;
  110. }
  111. if (SDL_UnlockMutex(m_pSinksMutex) == -1) {
  112. debug_message("UnlockMutex error");
  113. }
  114. }
  115. void CMediaSource::ProcessMedia()
  116. {
  117. Duration start = GetElapsedDuration();
  118. // process ~1 second before returning to check for commands
  119. while (GetElapsedDuration() - start < (Duration)TimestampTicks) {
  120. if (m_sourceVideo && m_sourceAudio) {
  121. bool endOfVideo = IsEndOfVideo();
  122. bool endOfAudio = IsEndOfAudio();
  123. if (!endOfVideo && !endOfAudio) {
  124. if (m_videoSrcElapsedDuration <= m_audioSrcElapsedDuration) {
  125. ProcessVideo();
  126. } else {
  127. ProcessAudio();
  128. }
  129. } else if (endOfVideo && endOfAudio) {
  130. DoStopSource();
  131. break;
  132. } else if (endOfVideo) {
  133. ProcessAudio();
  134. } else { // endOfAudio
  135. ProcessVideo();
  136. }
  137. } else if (m_sourceVideo) {
  138. if (IsEndOfVideo()) {
  139. DoStopSource();
  140. break;
  141. }
  142. ProcessVideo();
  143. } else if (m_sourceAudio) {
  144. if (IsEndOfAudio()) {
  145. DoStopSource();
  146. break;
  147. }
  148. ProcessAudio();
  149. }
  150. }
  151. }
  152. Duration CMediaSource::GetElapsedDuration()
  153. {
  154. if (m_sourceVideo && m_sourceAudio) {
  155. return MIN(m_videoSrcElapsedDuration, m_audioSrcElapsedDuration);
  156. } else if (m_sourceVideo) {
  157. return m_videoSrcElapsedDuration;
  158. } else if (m_sourceAudio) {
  159. return m_audioSrcElapsedDuration;
  160. }
  161. return 0;
  162. }
  163. // slow down non-realtime sources, i.e. files
  164. // if any of the sinks require real-time semantics, i.e. RTP/UDP
  165. void CMediaSource::PaceSource()
  166. {
  167. if (m_sourceRealTime || !m_sinkRealTime) {
  168. return;
  169. }
  170. Duration realDuration =
  171. GetTimestamp() - m_startTimestamp;
  172. Duration aheadDuration =
  173. GetElapsedDuration() - realDuration;
  174. if (aheadDuration >= m_maxAheadDuration) {
  175. SDL_Delay((aheadDuration - (m_maxAheadDuration / 2)) / 1000);
  176. }
  177. }
  178. void CMediaSource::ForwardFrame(CMediaFrame* pFrame)
  179. {
  180. if (SDL_LockMutex(m_pSinksMutex) == -1) {
  181. debug_message("ForwardFrame LockMutex error");
  182. return;
  183. }
  184. for (int i = 0; i < MAX_SINKS; i++) {
  185. if (m_sinks[i] == NULL) {
  186. break;
  187. }
  188. m_sinks[i]->EnqueueFrame(pFrame);
  189. }
  190. if (SDL_UnlockMutex(m_pSinksMutex) == -1) {
  191. debug_message("UnlockMutex error");
  192. }
  193. return;
  194. }
  195. void CMediaSource::DoStopSource()
  196. {
  197. if (!m_source) {
  198. return;
  199. }
  200. DoStopVideo();
  201. DoStopAudio();
  202. m_source = false;
  203. }
  204. bool CMediaSource::InitVideo(
  205. MediaType srcType,
  206. bool realTime)
  207. {
  208. m_sourceRealTime = realTime;
  209. m_sinkRealTime = m_pConfig->GetBoolValue(CONFIG_RTP_ENABLE);
  210. m_videoSrcType = srcType;
  211. m_videoSrcFrameNumber = 0;
  212. m_audioSrcFrameNumber = 0; // ensure audio is also at zero
  213. m_videoDstType = CMediaFrame::Mpeg4VideoFrame;
  214. m_videoDstFrameRate =
  215. m_pConfig->GetFloatValue(CONFIG_VIDEO_FRAME_RATE);
  216. m_videoDstFrameDuration = 
  217. (Duration)(((float)TimestampTicks / m_videoDstFrameRate) + 0.5);
  218. m_videoDstFrameNumber = 0;
  219. m_videoDstWidth =
  220. m_pConfig->m_videoWidth;
  221. m_videoDstHeight =
  222. m_pConfig->m_videoHeight;
  223. m_videoDstAspectRatio = 
  224. (float)m_pConfig->m_videoWidth / (float)m_pConfig->m_videoHeight;
  225. m_videoDstYSize = m_videoDstWidth * m_videoDstHeight;
  226. m_videoDstUVSize = m_videoDstYSize / 4;
  227. m_videoDstYUVSize = (m_videoDstYSize * 3) / 2;
  228. // intialize encoder
  229. m_videoEncoder = VideoEncoderCreate(
  230. m_pConfig->GetStringValue(CONFIG_VIDEO_ENCODER));
  231. if (!m_videoEncoder) {
  232. return false;
  233. }
  234. if (!m_videoEncoder->Init(m_pConfig, realTime)) {
  235. delete m_videoEncoder;
  236. m_videoEncoder = NULL;
  237. return false;
  238. }
  239. m_videoWantKeyFrame = true;
  240. m_videoSkippedFrames = 0;
  241. m_videoEncodingDrift = 0;
  242. m_videoEncodingMaxDrift = m_videoDstFrameDuration;
  243. m_videoSrcElapsedDuration = 0;
  244. m_videoDstElapsedDuration = 0;
  245. m_otherTotalDrift = 0;
  246. m_otherLastTotalDrift = 0;
  247. m_videoDstPrevImage = NULL;
  248. m_videoDstPrevReconstructImage = NULL;
  249. m_videoDstPrevFrame = NULL;
  250. m_videoDstPrevFrameLength = 0;
  251. return true;
  252. }
  253. void CMediaSource::SetVideoSrcSize(
  254. u_int16_t srcWidth,
  255. u_int16_t srcHeight,
  256. u_int16_t srcStride,
  257. bool matchAspectRatios)
  258. {
  259. // N.B. InitVideo() must be called first
  260. m_videoSrcWidth = srcWidth;
  261. m_videoSrcHeight = srcHeight;
  262. m_videoSrcAspectRatio = (float)srcWidth / (float)srcHeight;
  263. m_videoMatchAspectRatios = matchAspectRatios;
  264. SetVideoSrcStride(srcStride);
  265. }
  266. void CMediaSource::SetVideoSrcStride(
  267. u_int16_t srcStride)
  268. {
  269. // N.B. SetVideoSrcSize() should be called once before 
  270. m_videoSrcYStride = srcStride;
  271. m_videoSrcUVStride = srcStride / 2;
  272. // these next three may change below
  273. m_videoSrcAdjustedHeight = m_videoSrcHeight;
  274. m_videoSrcYCrop = 0;
  275. m_videoSrcUVCrop = 0;
  276. // match aspect ratios
  277. if (m_videoMatchAspectRatios 
  278.   && fabs(m_videoSrcAspectRatio - m_videoDstAspectRatio) > 0.01) {
  279. m_videoSrcAdjustedHeight =
  280. (u_int16_t)(m_videoSrcWidth / m_videoDstAspectRatio);
  281. if ((m_videoSrcAdjustedHeight % 16) != 0) {
  282. m_videoSrcAdjustedHeight += 16 - (m_videoSrcAdjustedHeight % 16);
  283. }
  284. if (m_videoSrcAspectRatio < m_videoDstAspectRatio) {
  285. // crop src
  286. m_videoSrcYCrop = m_videoSrcYStride * 
  287. ((m_videoSrcHeight - m_videoSrcAdjustedHeight) / 2);
  288. m_videoSrcUVCrop = m_videoSrcYCrop / 4;
  289. }
  290. }
  291. m_videoSrcYSize = m_videoSrcYStride 
  292. * MAX(m_videoSrcHeight, m_videoSrcAdjustedHeight);
  293. m_videoSrcUVSize = m_videoSrcYSize / 4;
  294. m_videoSrcYUVSize = (m_videoSrcYSize * 3) / 2;
  295. // resizing
  296. DestroyVideoResizer();
  297. if (m_videoSrcWidth != m_videoDstWidth 
  298.   || m_videoSrcAdjustedHeight != m_videoDstHeight) {
  299. m_videoSrcYImage = 
  300. scale_new_image(m_videoSrcWidth, 
  301. m_videoSrcAdjustedHeight, 1);
  302. m_videoSrcYImage->span = m_videoSrcYStride;
  303. m_videoDstYImage = 
  304. scale_new_image(m_videoDstWidth, 
  305. m_videoDstHeight, 1);
  306. m_videoYResizer = 
  307. scale_image_init(m_videoDstYImage, m_videoSrcYImage, 
  308. Bell_filter, Bell_support);
  309. m_videoSrcUVImage = 
  310. scale_new_image(m_videoSrcWidth / 2, 
  311. m_videoSrcAdjustedHeight / 2, 1);
  312. m_videoSrcUVImage->span = m_videoSrcUVStride;
  313. m_videoDstUVImage = 
  314. scale_new_image(m_videoDstWidth / 2, 
  315. m_videoDstHeight / 2, 1);
  316. m_videoUVResizer = 
  317. scale_image_init(m_videoDstUVImage, m_videoSrcUVImage, 
  318. Bell_filter, Bell_support);
  319. }
  320. }
  321. void CMediaSource::ProcessVideoYUVFrame(
  322. u_int8_t* pY,
  323. u_int8_t* pU,
  324. u_int8_t* pV,
  325. u_int16_t yStride,
  326. u_int16_t uvStride,
  327. Timestamp srcFrameTimestamp)
  328. {
  329. if (m_videoSrcFrameNumber == 0 && m_audioSrcFrameNumber == 0) {
  330. m_startTimestamp = srcFrameTimestamp;
  331. }
  332. m_videoSrcFrameNumber++;
  333. m_videoSrcElapsedDuration = srcFrameTimestamp - m_startTimestamp;
  334. // drop src frames as needed to match target frame rate
  335. if (m_videoDstElapsedDuration > m_videoSrcElapsedDuration) {
  336. return;
  337. }
  338. // if we're running in real-time mode
  339. if (m_sourceRealTime) {
  340. // add any external drift (i.e. audio encoding drift)
  341. // to our drift measurement
  342. m_videoEncodingDrift += 
  343. m_otherTotalDrift - m_otherLastTotalDrift;
  344. m_otherLastTotalDrift = m_otherTotalDrift;
  345. // check if we are falling behind
  346. if (m_videoEncodingDrift >= m_videoEncodingMaxDrift) {
  347. m_videoEncodingDrift -= m_videoDstFrameDuration;
  348. if (m_videoEncodingDrift < 0) {
  349. m_videoEncodingDrift = 0;
  350. }
  351. // skip this frame
  352. m_videoSkippedFrames++;
  353. return;
  354. }
  355. }
  356. Timestamp encodingStartTimestamp = GetTimestamp();
  357. // this will either never happen (live capture)
  358. // or just happen once at startup when we discover
  359. // the stride used by the video decoder
  360. if (yStride != m_videoSrcYStride) {
  361. SetVideoSrcSize(m_videoSrcWidth, m_videoSrcHeight, 
  362. yStride, m_videoMatchAspectRatios);
  363. }
  364. u_int8_t* mallocedYuvImage = NULL;
  365. // crop to desired aspect ratio (may be a no-op)
  366. u_int8_t* yImage = pY + m_videoSrcYCrop;
  367. u_int8_t* uImage = pU + m_videoSrcUVCrop;
  368. u_int8_t* vImage = pV + m_videoSrcUVCrop;
  369. // Note: caller is responsible for adding any padding that is needed
  370. // resize image if necessary
  371. if (m_videoYResizer) {
  372. u_int8_t* resizedYUV = 
  373. (u_int8_t*)Malloc(m_videoDstYUVSize);
  374. u_int8_t* resizedY = 
  375. resizedYUV;
  376. u_int8_t* resizedU = 
  377. resizedYUV + m_videoDstYSize;
  378. u_int8_t* resizedV = 
  379. resizedYUV + m_videoDstYSize + m_videoDstUVSize;
  380. m_videoSrcYImage->data = yImage;
  381. m_videoDstYImage->data = resizedY;
  382. scale_image_process(m_videoYResizer);
  383. m_videoSrcUVImage->data = uImage;
  384. m_videoDstUVImage->data = resizedU;
  385. scale_image_process(m_videoUVResizer);
  386. m_videoSrcUVImage->data = vImage;
  387. m_videoDstUVImage->data = resizedV;
  388. scale_image_process(m_videoUVResizer);
  389. // done with the original source image
  390. // this may be NULL
  391. free(mallocedYuvImage);
  392. // switch over to resized version
  393. mallocedYuvImage = resizedYUV;
  394. yImage = resizedY;
  395. uImage = resizedU;
  396. vImage = resizedV;
  397. yStride = m_videoDstWidth;
  398. uvStride = yStride / 2;
  399. }
  400. // if we want encoded video frames
  401. if (m_pConfig->m_videoEncode) {
  402. // call video encoder
  403. bool rc = m_videoEncoder->EncodeImage(
  404. yImage, uImage, vImage, 
  405. yStride, uvStride,
  406. m_videoWantKeyFrame);
  407. if (!rc) {
  408. debug_message("Can't encode image!");
  409. free(mallocedYuvImage);
  410. return;
  411. }
  412. // clear want key frame flag
  413. m_videoWantKeyFrame = false;
  414. }
  415. Timestamp dstPrevFrameTimestamp =
  416. m_startTimestamp + m_videoDstElapsedDuration;
  417. // calculate previous frame duration
  418. Duration dstPrevFrameDuration = m_videoDstFrameDuration;
  419. m_videoDstElapsedDuration += m_videoDstFrameDuration;
  420. if (m_sourceRealTime && m_videoSrcFrameNumber > 0) {
  421. // first adjust due to skipped frames
  422. Duration dstPrevFrameAdjustment = 
  423. m_videoSkippedFrames * m_videoDstFrameDuration;
  424. dstPrevFrameDuration += dstPrevFrameAdjustment;
  425. m_videoDstElapsedDuration += dstPrevFrameAdjustment;
  426. // next check our duration against real elasped time
  427. Duration lag = m_videoSrcElapsedDuration - m_videoDstElapsedDuration;
  428. if (lag > 0) {
  429. // adjust by integral number of target duration units
  430. dstPrevFrameAdjustment = 
  431. (lag / m_videoDstFrameDuration) * m_videoDstFrameDuration;
  432. dstPrevFrameDuration += dstPrevFrameAdjustment;
  433. m_videoDstElapsedDuration += dstPrevFrameAdjustment;
  434. }
  435. }
  436. // forward encoded video to sinks
  437. if (m_pConfig->m_videoEncode) {
  438. if (m_videoDstPrevFrame) {
  439. CMediaFrame* pFrame = new CMediaFrame(
  440. CMediaFrame::Mpeg4VideoFrame, 
  441. m_videoDstPrevFrame, 
  442. m_videoDstPrevFrameLength,
  443. dstPrevFrameTimestamp, 
  444. dstPrevFrameDuration);
  445. ForwardFrame(pFrame);
  446. delete pFrame;
  447. }
  448. // hold onto this encoded vop until next one is ready
  449. m_videoEncoder->GetEncodedImage(
  450. &m_videoDstPrevFrame, &m_videoDstPrevFrameLength);
  451. }
  452. // forward raw video to sinks
  453. if (m_pConfig->SourceRawVideo()) {
  454. if (m_videoDstPrevImage) {
  455. CMediaFrame* pFrame =
  456. new CMediaFrame(
  457. CMediaFrame::YuvVideoFrame, 
  458. m_videoDstPrevImage, 
  459. m_videoDstYUVSize,
  460. dstPrevFrameTimestamp, 
  461. dstPrevFrameDuration);
  462. ForwardFrame(pFrame);
  463. delete pFrame;
  464. }
  465. m_videoDstPrevImage = (u_int8_t*)Malloc(m_videoDstYUVSize);
  466. imgcpy(m_videoDstPrevImage, 
  467. yImage, 
  468. m_videoDstWidth,
  469. m_videoDstHeight,
  470. yStride);
  471. imgcpy(m_videoDstPrevImage + m_videoDstYSize,
  472. uImage, 
  473. m_videoDstWidth / 2,
  474. m_videoDstHeight / 2,
  475. uvStride);
  476. imgcpy(m_videoDstPrevImage + m_videoDstYSize + m_videoDstUVSize,
  477. vImage, 
  478. m_videoDstWidth / 2,
  479. m_videoDstHeight / 2,
  480. uvStride);
  481. }
  482. // forward reconstructed video to sinks
  483. if (m_pConfig->m_videoEncode
  484.   && m_pConfig->GetBoolValue(CONFIG_VIDEO_ENCODED_PREVIEW)) {
  485. if (m_videoDstPrevReconstructImage) {
  486. CMediaFrame* pFrame =
  487. new CMediaFrame(CMediaFrame::ReconstructYuvVideoFrame, 
  488. m_videoDstPrevReconstructImage, 
  489. m_videoDstYUVSize,
  490. dstPrevFrameTimestamp, 
  491. dstPrevFrameDuration);
  492. ForwardFrame(pFrame);
  493. delete pFrame;
  494. }
  495. m_videoDstPrevReconstructImage = 
  496. (u_int8_t*)Malloc(m_videoDstYUVSize);
  497. m_videoEncoder->GetReconstructedImage(
  498. m_videoDstPrevReconstructImage,
  499. m_videoDstPrevReconstructImage 
  500. + m_videoDstYSize,
  501. m_videoDstPrevReconstructImage
  502. + m_videoDstYSize + m_videoDstUVSize);
  503. }
  504. m_videoDstFrameNumber++;
  505. // calculate how we're doing versus target frame rate
  506. // this is used to decide if we need to drop frames
  507. if (m_sourceRealTime) {
  508. // reset skipped frames
  509. m_videoSkippedFrames = 0;
  510. Duration drift =
  511. (GetTimestamp() - encodingStartTimestamp) 
  512. - m_videoDstFrameDuration;
  513. if (drift > 0) {
  514. m_videoEncodingDrift += drift;
  515. }
  516. }
  517. free(mallocedYuvImage);
  518. return;
  519. }
  520. void CMediaSource::DoStopVideo()
  521. {
  522. DestroyVideoResizer();
  523. if (m_videoEncoder) {
  524. m_videoEncoder->Stop();
  525. delete m_videoEncoder;
  526. m_videoEncoder = NULL;
  527. }
  528. m_sourceVideo = false;
  529. }
  530. void CMediaSource::DestroyVideoResizer()
  531. {
  532. if (m_videoSrcYImage) {
  533. scale_free_image(m_videoSrcYImage);
  534. m_videoSrcYImage = NULL;
  535. }
  536. if (m_videoDstYImage) {
  537. scale_free_image(m_videoDstYImage);
  538. m_videoDstYImage = NULL;
  539. }
  540. if (m_videoYResizer) {
  541. scale_image_done(m_videoYResizer);
  542. m_videoYResizer = NULL;
  543. }
  544. if (m_videoSrcUVImage) {
  545. scale_free_image(m_videoSrcUVImage);
  546. m_videoSrcUVImage = NULL;
  547. }
  548. if (m_videoDstUVImage) {
  549. scale_free_image(m_videoDstUVImage);
  550. m_videoDstUVImage = NULL;
  551. }
  552. if (m_videoUVResizer) {
  553. scale_image_done(m_videoUVResizer);
  554. m_videoUVResizer = NULL;
  555. }
  556. }
  557. bool CMediaSource::InitAudio(
  558. bool realTime)
  559. {
  560. m_sourceRealTime = realTime;
  561. m_sinkRealTime = m_pConfig->GetBoolValue(CONFIG_RTP_ENABLE);
  562. m_audioSrcSampleNumber = 0;
  563. m_audioSrcFrameNumber = 0;
  564. m_videoSrcFrameNumber = 0; // ensure video is also at zero
  565. // audio destination info
  566. char* dstEncoding =
  567. m_pConfig->GetStringValue(CONFIG_AUDIO_ENCODING);
  568. if (!strcasecmp(dstEncoding, AUDIO_ENCODING_MP3)) {
  569. m_audioDstType = CMediaFrame::Mp3AudioFrame;
  570. } else if (!strcasecmp(dstEncoding, AUDIO_ENCODING_AAC)) {
  571. m_audioDstType = CMediaFrame::AacAudioFrame;
  572. } else {
  573. debug_message("unknown dest audio encoding");
  574. return false;
  575. }
  576. m_audioDstChannels =
  577. m_pConfig->GetIntegerValue(CONFIG_AUDIO_CHANNELS);
  578. m_audioDstSampleRate =
  579. m_pConfig->GetIntegerValue(CONFIG_AUDIO_SAMPLE_RATE);
  580. m_audioDstSampleNumber = 0;
  581. m_audioDstFrameNumber = 0;
  582. m_audioDstRawSampleNumber = 0;
  583. m_audioDstRawFrameNumber = 0;
  584. m_audioSrcElapsedDuration = 0;
  585. m_audioDstElapsedDuration = 0;
  586. return true;
  587. }
  588. bool CMediaSource::SetAudioSrc(
  589. MediaType srcType,
  590. u_int8_t srcChannels,
  591. u_int32_t srcSampleRate)
  592. {
  593. // audio source info 
  594. m_audioSrcType = srcType;
  595. m_audioSrcChannels = srcChannels;
  596. m_audioSrcSampleRate = srcSampleRate;
  597. m_audioSrcSamplesPerFrame = 0; // unknown, presumed variable
  598. // init audio encoder
  599. delete m_audioEncoder;
  600. m_audioEncoder = AudioEncoderCreate(
  601. m_pConfig->GetStringValue(CONFIG_AUDIO_ENCODER));
  602. if (m_audioEncoder == NULL) {
  603. return false;
  604. }
  605. if (!m_audioEncoder->Init(m_pConfig, m_sourceRealTime)) {
  606. delete m_audioEncoder;
  607. m_audioEncoder = NULL;
  608. return false;
  609. }
  610. m_audioDstSamplesPerFrame = 
  611. m_audioEncoder->GetSamplesPerFrame();
  612. // if we need to resample
  613. if (m_audioDstSampleRate != m_audioSrcSampleRate) {
  614. // if sampling rates are integral multiples
  615. // we can use simpler, faster linear interpolation
  616. // else we use quadratic interpolation
  617. if (m_audioDstSampleRate < m_audioSrcSampleRate) {
  618. m_audioResampleUseLinear =
  619. ((m_audioSrcSampleRate % m_audioDstSampleRate) == 0);
  620. } else if (m_audioDstSampleRate >= m_audioSrcSampleRate) {
  621. m_audioResampleUseLinear =
  622. ((m_audioDstSampleRate % m_audioSrcSampleRate) == 0);
  623. }
  624. m_audioResampleInputNumber = 0;
  625. free(m_audioResampleInputBuffer);
  626. m_audioResampleInputBuffer =
  627. (int16_t*)calloc(16 * m_audioSrcChannels, 2);
  628. }
  629. m_audioPreEncodingBufferLength = 0;
  630. m_audioPreEncodingBufferMaxLength =
  631. 4 * DstSamplesToBytes(m_audioDstSamplesPerFrame);
  632. m_audioPreEncodingBuffer = (u_int8_t*)realloc(
  633. m_audioPreEncodingBuffer,
  634. m_audioPreEncodingBufferMaxLength);
  635. if (m_audioPreEncodingBuffer == NULL) {
  636. delete m_audioEncoder;
  637. m_audioEncoder = NULL;
  638. return false;
  639. }
  640. return true;
  641. }
  642. void CMediaSource::ProcessAudioFrame(
  643. u_int8_t* frameData,
  644. u_int32_t frameDataLength,
  645. Timestamp srcFrameTimestamp,
  646. bool resync)
  647. {
  648. if (m_videoSrcFrameNumber == 0 && m_audioSrcFrameNumber == 0) {
  649. m_startTimestamp = srcFrameTimestamp;
  650. }
  651. m_audioSrcFrameNumber++;
  652. m_audioSrcElapsedDuration = srcFrameTimestamp - m_startTimestamp;
  653. if (resync) {
  654. // flush preEncodingBuffer
  655. m_audioPreEncodingBufferLength = 0;
  656. // change dst sample numbers to account for gap
  657. m_audioDstSampleNumber =
  658. m_audioDstRawSampleNumber =
  659. DstTicksToSamples(m_audioSrcElapsedDuration);
  660. }
  661. bool pcmMalloced = false;
  662. bool pcmBuffered;
  663. u_int8_t* pcmData = frameData;
  664. u_int32_t pcmDataLength = frameDataLength;
  665. // resample audio, if necessary
  666. if (m_audioSrcSampleRate != m_audioDstSampleRate) {
  667. ResampleAudio(pcmData, pcmDataLength);
  668. // resampled data is now available in m_audioPreEncodingBuffer
  669. pcmBuffered = true;
  670. } else if (m_audioSrcSamplesPerFrame != m_audioDstSamplesPerFrame) {
  671. // reframe audio, if necessary
  672. // e.g. MP3 is 1152 samples/frame, AAC is 1024 samples/frame
  673. // add samples to end of m_audioBuffer
  674. // InitAudio() ensures that buffer is large enough
  675. memcpy(
  676. &m_audioPreEncodingBuffer[m_audioPreEncodingBufferLength],
  677. pcmData,
  678. pcmDataLength);
  679. m_audioPreEncodingBufferLength += pcmDataLength;
  680. pcmBuffered = true;
  681. } else {
  682. pcmBuffered = false;
  683. }
  684. // LATER restructure so as get rid of this label, and goto below
  685. pcmBufferCheck:
  686. if (pcmBuffered) {
  687. u_int32_t samplesAvailable =
  688. DstBytesToSamples(m_audioPreEncodingBufferLength);
  689. // not enough samples collected yet to call encode or forward
  690. if (samplesAvailable < m_audioDstSamplesPerFrame) {
  691. return;
  692. }
  693. // setup for encode/forward
  694. pcmData = 
  695. &m_audioPreEncodingBuffer[0];
  696. pcmDataLength = 
  697. DstSamplesToBytes(m_audioDstSamplesPerFrame);
  698. }
  699. // encode audio frame
  700. if (m_pConfig->m_audioEncode) {
  701. Timestamp encodingStartTimestamp = GetTimestamp();
  702. bool rc = m_audioEncoder->EncodeSamples(
  703. (u_int16_t*)pcmData, pcmDataLength);
  704. if (!rc) {
  705. debug_message("failed to encode audio");
  706. return;
  707. }
  708. Duration encodingTime =
  709. (GetTimestamp() - encodingStartTimestamp);
  710. if (m_sourceRealTime) {
  711. Duration drift = encodingTime 
  712. - DstSamplesToTicks(DstBytesToSamples(pcmDataLength));
  713. if (drift > 0) {
  714. m_videoSource->AddEncodingDrift(drift);
  715. }
  716. }
  717. u_int32_t forwardedSamples;
  718. u_int32_t forwardedFrames;
  719. ForwardEncodedAudioFrames(
  720. m_startTimestamp 
  721. + DstSamplesToTicks(m_audioDstSampleNumber),
  722. &forwardedSamples,
  723. &forwardedFrames);
  724. m_audioDstSampleNumber += forwardedSamples;
  725. m_audioDstFrameNumber += forwardedFrames;
  726. }
  727. // if desired, forward raw audio to sinks
  728. if (m_pConfig->SourceRawAudio()) {
  729. // make a copy of the pcm data if needed
  730. u_int8_t* pcmForwardedData;
  731. if (!pcmMalloced) {
  732. pcmForwardedData = (u_int8_t*)Malloc(pcmDataLength);
  733. memcpy(pcmForwardedData, pcmData, pcmDataLength);
  734. } else {
  735. pcmForwardedData = pcmData;
  736. pcmMalloced = false;
  737. }
  738. CMediaFrame* pFrame =
  739. new CMediaFrame(
  740. CMediaFrame::PcmAudioFrame, 
  741. pcmForwardedData, 
  742. pcmDataLength,
  743. m_startTimestamp 
  744. + DstSamplesToTicks(m_audioDstRawSampleNumber),
  745. DstBytesToSamples(pcmDataLength),
  746. m_audioDstSampleRate);
  747. ForwardFrame(pFrame);
  748. delete pFrame;
  749. m_audioDstRawSampleNumber += DstBytesToSamples(pcmDataLength);
  750. m_audioDstRawFrameNumber++;
  751. }
  752. if (pcmMalloced) {
  753. free(pcmData);
  754. }
  755. if (pcmBuffered) {
  756. m_audioPreEncodingBufferLength -= pcmDataLength;
  757. memcpy(
  758. &m_audioPreEncodingBuffer[0],
  759. &m_audioPreEncodingBuffer[pcmDataLength],
  760. m_audioPreEncodingBufferLength);
  761. goto pcmBufferCheck;
  762. }
  763. }
  764. void CMediaSource::ResampleAudio(
  765. u_int8_t* frameData,
  766. u_int32_t frameDataLength)
  767. {
  768. int16_t* pIn =
  769. (int16_t*)frameData;
  770. int16_t* pOut = 
  771. (int16_t*)&m_audioPreEncodingBuffer[m_audioPreEncodingBufferLength];
  772. // compute how many input samples are available
  773. u_int32_t numIn =
  774. m_audioResampleInputNumber + SrcBytesToSamples(frameDataLength);
  775. // compute how many output samples 
  776. // can be generated from the available input samples
  777. u_int32_t numOut =
  778. (numIn * m_audioDstSampleRate) / m_audioSrcSampleRate;
  779. float inTime0 = 
  780. (float)(m_audioResampleInputNumber * m_audioSrcSampleRate)
  781. / (float)m_audioDstSampleRate;
  782. int32_t inIndex;
  783. u_int32_t outIndex;
  784. // for all output samples
  785. for (outIndex = 0; true; outIndex++) {
  786. float outTime0 = 
  787. (outIndex * m_audioSrcSampleRate) / (float)m_audioDstSampleRate;
  788. inIndex = (int32_t)(outTime0 - inTime0 + 0.5);
  789. // DEBUG printf("resample out %d %f in %d %fn",
  790. // DEBUG outIndex, outTime0, inIndex, inTime0);
  791. // the unusual location of the loop exit condition
  792. // is because we need the initial inIndex for the next call
  793. // see the end of this function for how this is used
  794. if (outIndex >= numOut) {
  795. break;
  796. }
  797. float x1 = outTime0 - (inTime0 + inIndex);
  798. float x0 = x1 + 1;
  799. float x2 = x1 - 1;
  800. float x3 = x1 - 2;
  801. for (u_int8_t ch = 0; ch < m_audioSrcChannels; ch++) {
  802. int16_t y0, y1, y2, y3;
  803. if (inIndex < 0) {
  804. y1 = m_audioResampleInputBuffer
  805. [(-(inIndex) - 1) * m_audioSrcChannels + ch];
  806. } else {
  807. y1 = pIn[inIndex * m_audioSrcChannels + ch];
  808. }
  809. if (inIndex + 1 < 0) {
  810. y2 = m_audioResampleInputBuffer
  811. [(-(inIndex + 1) - 1) * m_audioSrcChannels + ch];
  812. } else {
  813. y2 = pIn[(inIndex + 1) * m_audioSrcChannels + ch];
  814. }
  815. if (m_audioResampleUseLinear) {
  816. *pOut++ = (int16_t)
  817. (((y2 * x1) - (y1 * x2)) + 0.5);
  818. } else { // use quadratic resampling
  819. if (inIndex - 1 < 0) {
  820. y0 = m_audioResampleInputBuffer
  821. [(-(inIndex - 1) - 1) * m_audioSrcChannels + ch];
  822. } else {
  823. y0 = pIn[(inIndex - 1) * m_audioSrcChannels + ch];
  824. }
  825. if (inIndex + 2 < 0) {
  826. y3 = m_audioResampleInputBuffer
  827. [(-(inIndex + 2) - 1) * m_audioSrcChannels + ch];
  828. } else {
  829. y3 = pIn[(inIndex + 2) * m_audioSrcChannels + ch];
  830. }
  831. int32_t outValue = (int32_t)(
  832. - (y0 * x1 * x2 * x3 / 6) 
  833. + (y1 * x0 * x2 * x3 / 2) 
  834. - (y2 * x0 * x1 * x3 / 2) 
  835. + (y3 * x0 * x1 * x2 / 6)
  836. + 0.5);
  837. // DEBUG printf("x0 %f y %d %d %d %d -> %d (delta %d)n",
  838. // DEBUG x0, y0, y1, y2, y3, 
  839. // DEBUG outValue, outValue - ((y0 + y1) / 2));
  840. if (outValue > 32767) {
  841. outValue = 32767;
  842. } else if (outValue < -32767) {
  843. outValue = -32767;
  844. }
  845. *pOut++ = (int16_t)outValue;
  846. }
  847. }
  848. }
  849. // since resampling inputs can span input frame boundaries
  850. // we may need to save up to 3 samples for the next call
  851. m_audioResampleInputNumber = 0;
  852. for (int32_t i = SrcBytesToSamples(frameDataLength) - 1; 
  853.   i >= inIndex; i--) {
  854. // DEBUG printf("resample save [%d] <- [%d]n",
  855. // DEBUG m_audioResampleInputNumber, i);
  856. memcpy(
  857. &m_audioResampleInputBuffer[m_audioResampleInputNumber],
  858. &pIn[i * m_audioSrcChannels],
  859. m_audioSrcChannels * sizeof(int16_t));
  860. m_audioResampleInputNumber++;
  861. }
  862. m_audioPreEncodingBufferLength += 
  863. numOut * m_audioSrcChannels * sizeof(int16_t);
  864. return;
  865. }
  866. void CMediaSource::ForwardEncodedAudioFrames(
  867. Timestamp baseTimestamp,
  868. u_int32_t* pNumSamples,
  869. u_int32_t* pNumFrames)
  870. {
  871. u_int8_t* pFrame;
  872. u_int32_t frameLength;
  873. u_int32_t frameNumSamples;
  874. (*pNumSamples) = 0;
  875. (*pNumFrames) = 0;
  876. while (m_audioEncoder->GetEncodedSamples(
  877.   &pFrame, &frameLength, &frameNumSamples)) {
  878. // sanity check
  879. if (pFrame == NULL || frameLength == 0) {
  880. break;
  881. }
  882. (*pNumSamples) += frameNumSamples;
  883. (*pNumFrames)++;
  884. // forward the encoded frame to sinks
  885. CMediaFrame* pMediaFrame =
  886. new CMediaFrame(
  887. m_audioEncoder->GetFrameType(),
  888. pFrame, 
  889. frameLength,
  890. baseTimestamp 
  891. + DstSamplesToTicks((*pNumSamples)),
  892. frameNumSamples,
  893. m_audioDstSampleRate);
  894. ForwardFrame(pMediaFrame);
  895. delete pMediaFrame;
  896. }
  897. }
  898. void CMediaSource::DoStopAudio()
  899. {
  900. if (m_audioEncoder) {
  901. // flush remaining output from audio encoder
  902. // and forward it to sinks
  903. m_audioEncoder->EncodeSamples(NULL, 0);
  904. u_int32_t forwardedSamples;
  905. u_int32_t forwardedFrames;
  906. ForwardEncodedAudioFrames(
  907. m_startTimestamp
  908. + DstSamplesToTicks(m_audioDstSampleNumber),
  909. &forwardedSamples,
  910. &forwardedFrames);
  911. m_audioDstSampleNumber += forwardedSamples;
  912. m_audioDstFrameNumber += forwardedFrames;
  913. m_audioEncoder->Stop();
  914. delete m_audioEncoder;
  915. m_audioEncoder = NULL;
  916. }
  917. free(m_audioResampleInputBuffer);
  918. m_audioResampleInputBuffer = NULL;
  919. free(m_audioPreEncodingBuffer);
  920. m_audioPreEncodingBuffer = NULL;
  921. m_sourceAudio = false;
  922. }