PageRenderTime 29ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/liveMedia/MP3StreamState.cpp

https://github.com/jimjh/liveMedia-for-Android
C++ | 457 lines | 340 code | 64 blank | 53 comment | 96 complexity | 9da717a549724f6a73c961b11f9609f9 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**********
  2. This library is free software; you can redistribute it and/or modify it under
  3. the terms of the GNU Lesser General Public License as published by the
  4. Free Software Foundation; either version 2.1 of the License, or (at your
  5. option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
  6. This library is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
  9. more details.
  10. You should have received a copy of the GNU Lesser General Public License
  11. along with this library; if not, write to the Free Software Foundation, Inc.,
  12. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  13. **********/
  14. // "liveMedia"
  15. // Copyright (c) 1996-2011 Live Networks, Inc. All rights reserved.
  16. // A class encapsulating the state of a MP3 stream
  17. // Implementation
  18. #include "MP3StreamState.hh"
  19. #include "InputFile.hh"
  20. #include "GroupsockHelper.hh"
  21. #if defined(__WIN32__) || defined(_WIN32)
  22. #define snprintf _snprintf
  23. #endif
  24. #define MILLION 1000000
  25. MP3StreamState::MP3StreamState(UsageEnvironment& env)
  26. : fEnv(env), fFid(NULL), fPresentationTimeScale(1) {
  27. }
  28. MP3StreamState::~MP3StreamState() {
  29. // Close our open file or socket:
  30. if (fFid != NULL && fFid != stdin) {
  31. if (fFidIsReallyASocket) {
  32. long fid_long = (long)fFid;
  33. closeSocket((int)fid_long);
  34. } else {
  35. CloseInputFile(fFid);
  36. }
  37. }
  38. }
  39. void MP3StreamState::assignStream(FILE* fid, unsigned fileSize) {
  40. fFid = fid;
  41. if (fileSize == (unsigned)(-1)) { /*HACK#####*/
  42. fFidIsReallyASocket = 1;
  43. fFileSize = 0;
  44. } else {
  45. fFidIsReallyASocket = 0;
  46. fFileSize = fileSize;
  47. }
  48. fNumFramesInFile = 0; // until we know otherwise
  49. fIsVBR = fHasXingTOC = False; // ditto
  50. // Set the first frame's 'presentation time' to the current wall time:
  51. gettimeofday(&fNextFramePresentationTime, NULL);
  52. }
  53. struct timeval MP3StreamState::currentFramePlayTime() const {
  54. unsigned const numSamples = 1152;
  55. unsigned const freq = fr().samplingFreq*(1 + fr().isMPEG2);
  56. // result is numSamples/freq
  57. unsigned const uSeconds
  58. = ((numSamples*2*MILLION)/freq + 1)/2; // rounds to nearest integer
  59. struct timeval result;
  60. result.tv_sec = uSeconds/MILLION;
  61. result.tv_usec = uSeconds%MILLION;
  62. return result;
  63. }
  64. float MP3StreamState::filePlayTime() const {
  65. unsigned numFramesInFile = fNumFramesInFile;
  66. if (numFramesInFile == 0) {
  67. // Estimate the number of frames from the file size, and the
  68. // size of the current frame:
  69. numFramesInFile = fFileSize/(4 + fCurrentFrame.frameSize);
  70. }
  71. struct timeval const pt = currentFramePlayTime();
  72. return numFramesInFile*(pt.tv_sec + pt.tv_usec/(float)MILLION);
  73. }
  74. unsigned MP3StreamState::getByteNumberFromPositionFraction(float fraction) {
  75. if (fHasXingTOC) {
  76. // The file is VBR, with a Xing TOC; use it to determine which byte to seek to:
  77. float percent = fraction*100.0f;
  78. unsigned a = (unsigned)percent;
  79. if (a > 99) a = 99;
  80. unsigned fa = fXingTOC[a];
  81. unsigned fb;
  82. if (a < 99) {
  83. fb = fXingTOC[a+1];
  84. } else {
  85. fb = 256;
  86. }
  87. fraction = (fa + (fb-fa)*(percent-a))/256.0f;
  88. }
  89. return (unsigned)(fraction*fFileSize);
  90. }
  91. void MP3StreamState::seekWithinFile(unsigned seekByteNumber) {
  92. if (fFidIsReallyASocket) return; // it's not seekable
  93. SeekFile64(fFid, seekByteNumber, SEEK_SET);
  94. }
  95. unsigned MP3StreamState::findNextHeader(struct timeval& presentationTime) {
  96. presentationTime = fNextFramePresentationTime;
  97. if (!findNextFrame()) return 0;
  98. // From this frame, figure out the *next* frame's presentation time:
  99. struct timeval framePlayTime = currentFramePlayTime();
  100. if (fPresentationTimeScale > 1) {
  101. // Scale this value
  102. unsigned secondsRem = framePlayTime.tv_sec % fPresentationTimeScale;
  103. framePlayTime.tv_sec -= secondsRem;
  104. framePlayTime.tv_usec += secondsRem*MILLION;
  105. framePlayTime.tv_sec /= fPresentationTimeScale;
  106. framePlayTime.tv_usec /= fPresentationTimeScale;
  107. }
  108. fNextFramePresentationTime.tv_usec += framePlayTime.tv_usec;
  109. fNextFramePresentationTime.tv_sec
  110. += framePlayTime.tv_sec + fNextFramePresentationTime.tv_usec/MILLION;
  111. fNextFramePresentationTime.tv_usec %= MILLION;
  112. return fr().hdr;
  113. }
  114. Boolean MP3StreamState::readFrame(unsigned char* outBuf, unsigned outBufSize,
  115. unsigned& resultFrameSize,
  116. unsigned& resultDurationInMicroseconds) {
  117. /* We assume that "mp3FindNextHeader()" has already been called */
  118. resultFrameSize = 4 + fr().frameSize;
  119. if (outBufSize < resultFrameSize) {
  120. #ifdef DEBUG_ERRORS
  121. fprintf(stderr, "Insufficient buffer size for reading input frame (%d, need %d)\n",
  122. outBufSize, resultFrameSize);
  123. #endif
  124. if (outBufSize < 4) outBufSize = 0;
  125. resultFrameSize = outBufSize;
  126. return False;
  127. }
  128. if (resultFrameSize >= 4) {
  129. unsigned& hdr = fr().hdr;
  130. *outBuf++ = (unsigned char)(hdr>>24);
  131. *outBuf++ = (unsigned char)(hdr>>16);
  132. *outBuf++ = (unsigned char)(hdr>>8);
  133. *outBuf++ = (unsigned char)(hdr);
  134. memmove(outBuf, fr().frameBytes, resultFrameSize-4);
  135. }
  136. struct timeval const pt = currentFramePlayTime();
  137. resultDurationInMicroseconds = pt.tv_sec*MILLION + pt.tv_usec;
  138. return True;
  139. }
  140. void MP3StreamState::getAttributes(char* buffer, unsigned bufferSize) const {
  141. char const* formatStr
  142. = "bandwidth %d MPEGnumber %d MPEGlayer %d samplingFrequency %d isStereo %d playTime %d isVBR %d";
  143. unsigned fpt = (unsigned)(filePlayTime() + 0.5); // rounds to nearest integer
  144. #if defined(IRIX) || defined(ALPHA) || defined(_QNX4) || defined(IMN_PIM) || defined(CRIS)
  145. /* snprintf() isn't defined, so just use sprintf() - ugh! */
  146. sprintf(buffer, formatStr,
  147. fr().bitrate, fr().isMPEG2 ? 2 : 1, fr().layer, fr().samplingFreq, fr().isStereo,
  148. fpt, fIsVBR);
  149. #else
  150. snprintf(buffer, bufferSize, formatStr,
  151. fr().bitrate, fr().isMPEG2 ? 2 : 1, fr().layer, fr().samplingFreq, fr().isStereo,
  152. fpt, fIsVBR);
  153. #endif
  154. }
  155. void MP3StreamState::writeGetCmd(char const* hostName,
  156. unsigned short portNum,
  157. char const* fileName) {
  158. char const* const getCmdFmt = "GET %s HTTP/1.1\r\nHost: %s:%d\r\n\r\n";
  159. if (fFidIsReallyASocket) {
  160. long fid_long = (long)fFid;
  161. int sock = (int)fid_long;
  162. char writeBuf[100];
  163. #if defined(IRIX) || defined(ALPHA) || defined(_QNX4) || defined(IMN_PIM) || defined(CRIS)
  164. /* snprintf() isn't defined, so just use sprintf() */
  165. /* This is a security risk if filename can come from an external user */
  166. sprintf(writeBuf, getCmdFmt, fileName, hostName, portNum);
  167. #else
  168. snprintf(writeBuf, sizeof writeBuf, getCmdFmt,
  169. fileName, hostName, portNum);
  170. #endif
  171. send(sock, writeBuf, strlen(writeBuf), 0);
  172. } else {
  173. fprintf(fFid, getCmdFmt, fileName, hostName, portNum);
  174. fflush(fFid);
  175. }
  176. }
  177. // This is crufty old code that needs to be cleaned up #####
  178. #define HDRCMPMASK 0xfffffd00
  179. Boolean MP3StreamState::findNextFrame() {
  180. unsigned char hbuf[8];
  181. unsigned l; int i;
  182. int attempt = 0;
  183. read_again:
  184. if (readFromStream(hbuf, 4) != 4) return False;
  185. fr().hdr = ((unsigned long) hbuf[0] << 24)
  186. | ((unsigned long) hbuf[1] << 16)
  187. | ((unsigned long) hbuf[2] << 8)
  188. | (unsigned long) hbuf[3];
  189. #ifdef DEBUG_PARSE
  190. fprintf(stderr, "fr().hdr: 0x%08x\n", fr().hdr);
  191. #endif
  192. if (fr().oldHdr != fr().hdr || !fr().oldHdr) {
  193. i = 0;
  194. init_resync:
  195. #ifdef DEBUG_PARSE
  196. fprintf(stderr, "init_resync: fr().hdr: 0x%08x\n", fr().hdr);
  197. #endif
  198. if ( (fr().hdr & 0xffe00000) != 0xffe00000
  199. || (fr().hdr & 0x00060000) == 0 // undefined 'layer' field
  200. || (fr().hdr & 0x0000F000) == 0 // 'free format' bitrate index
  201. || (fr().hdr & 0x0000F000) == 0x0000F000 // undefined bitrate index
  202. || (fr().hdr & 0x00000C00) == 0x00000C00 // undefined frequency index
  203. || (fr().hdr & 0x00000003) != 0x00000000 // 'emphasis' field unexpectedly set
  204. ) {
  205. /* RSF: Do the following test even if we're not at the
  206. start of the file, in case we have two or more
  207. separate MP3 files cat'ed together:
  208. */
  209. /* Check for RIFF hdr */
  210. if (fr().hdr == ('R'<<24)+('I'<<16)+('F'<<8)+'F') {
  211. unsigned char buf[70 /*was: 40*/];
  212. #ifdef DEBUG_ERRORS
  213. fprintf(stderr,"Skipped RIFF header\n");
  214. #endif
  215. readFromStream(buf, 66); /* already read 4 */
  216. goto read_again;
  217. }
  218. /* Check for ID3 hdr */
  219. if ((fr().hdr&0xFFFFFF00) == ('I'<<24)+('D'<<16)+('3'<<8)) {
  220. unsigned tagSize, bytesToSkip;
  221. unsigned char buf[1000];
  222. readFromStream(buf, 6); /* already read 4 */
  223. tagSize = ((buf[2]&0x7F)<<21) + ((buf[3]&0x7F)<<14) + ((buf[4]&0x7F)<<7) + (buf[5]&0x7F);
  224. bytesToSkip = tagSize;
  225. while (bytesToSkip > 0) {
  226. unsigned bytesToRead = sizeof buf;
  227. if (bytesToRead > bytesToSkip) {
  228. bytesToRead = bytesToSkip;
  229. }
  230. readFromStream(buf, bytesToRead);
  231. bytesToSkip -= bytesToRead;
  232. }
  233. #ifdef DEBUG_ERRORS
  234. fprintf(stderr,"Skipped %d-byte ID3 header\n", tagSize);
  235. #endif
  236. goto read_again;
  237. }
  238. /* give up after 20,000 bytes */
  239. if (i++ < 20000/*4096*//*1024*/) {
  240. memmove (&hbuf[0], &hbuf[1], 3);
  241. if (readFromStream(hbuf+3,1) != 1) {
  242. return False;
  243. }
  244. fr().hdr <<= 8;
  245. fr().hdr |= hbuf[3];
  246. fr().hdr &= 0xffffffff;
  247. #ifdef DEBUG_PARSE
  248. fprintf(stderr, "calling init_resync %d\n", i);
  249. #endif
  250. goto init_resync;
  251. }
  252. #ifdef DEBUG_ERRORS
  253. fprintf(stderr,"Giving up searching valid MPEG header\n");
  254. #endif
  255. return False;
  256. #ifdef DEBUG_ERRORS
  257. fprintf(stderr,"Illegal Audio-MPEG-Header 0x%08lx at offset 0x%lx.\n",
  258. fr().hdr,tell_stream(str)-4);
  259. #endif
  260. /* Read more bytes until we find something that looks
  261. reasonably like a valid header. This is not a
  262. perfect strategy, but it should get us back on the
  263. track within a short time (and hopefully without
  264. too much distortion in the audio output). */
  265. do {
  266. attempt++;
  267. memmove (&hbuf[0], &hbuf[1], 7);
  268. if (readFromStream(&hbuf[3],1) != 1) {
  269. return False;
  270. }
  271. /* This is faster than combining fr().hdr from scratch */
  272. fr().hdr = ((fr().hdr << 8) | hbuf[3]) & 0xffffffff;
  273. if (!fr().oldHdr)
  274. goto init_resync; /* "considered harmful", eh? */
  275. } while ((fr().hdr & HDRCMPMASK) != (fr().oldHdr & HDRCMPMASK)
  276. && (fr().hdr & HDRCMPMASK) != (fr().firstHdr & HDRCMPMASK));
  277. #ifdef DEBUG_ERRORS
  278. fprintf (stderr, "Skipped %d bytes in input.\n", attempt);
  279. #endif
  280. }
  281. if (!fr().firstHdr) {
  282. fr().firstHdr = fr().hdr;
  283. }
  284. fr().setParamsFromHeader();
  285. fr().setBytePointer(fr().frameBytes, fr().frameSize);
  286. fr().oldHdr = fr().hdr;
  287. if (fr().isFreeFormat) {
  288. #ifdef DEBUG_ERRORS
  289. fprintf(stderr,"Free format not supported.\n");
  290. #endif
  291. return False;
  292. }
  293. #ifdef MP3_ONLY
  294. if (fr().layer != 3) {
  295. #ifdef DEBUG_ERRORS
  296. fprintf(stderr, "MPEG layer %d is not supported!\n", fr().layer);
  297. #endif
  298. return False;
  299. }
  300. #endif
  301. }
  302. if ((l = readFromStream(fr().frameBytes, fr().frameSize))
  303. != fr().frameSize) {
  304. if (l == 0) return False;
  305. memset(fr().frameBytes+1, 0, fr().frameSize-1);
  306. }
  307. return True;
  308. }
  309. static Boolean socketIsReadable(int socket) {
  310. const unsigned numFds = socket+1;
  311. fd_set rd_set;
  312. FD_ZERO(&rd_set);
  313. FD_SET((unsigned)socket, &rd_set);
  314. struct timeval timeout;
  315. timeout.tv_sec = timeout.tv_usec = 0;
  316. int result = select(numFds, &rd_set, NULL, NULL, &timeout);
  317. return result != 0; // not > 0, because windows can return -1 for file sockets
  318. }
  319. static char watchVariable;
  320. static void checkFunc(void* /*clientData*/) {
  321. watchVariable = ~0;
  322. }
  323. static void waitUntilSocketIsReadable(UsageEnvironment& env, int socket) {
  324. while (!socketIsReadable(socket)) {
  325. // Delay a short period of time before checking again.
  326. unsigned usecsToDelay = 1000; // 1 ms
  327. env.taskScheduler().scheduleDelayedTask(usecsToDelay,
  328. (TaskFunc*)checkFunc, (void*)NULL);
  329. watchVariable = 0;
  330. env.taskScheduler().doEventLoop(&watchVariable);
  331. // This allows other tasks to run while we're waiting:
  332. }
  333. }
  334. unsigned MP3StreamState::readFromStream(unsigned char* buf,
  335. unsigned numChars) {
  336. // Hack for doing socket I/O instead of file I/O (e.g., on Windows)
  337. if (fFidIsReallyASocket) {
  338. long fid_long = (long)fFid;
  339. int sock = (int)fid_long;
  340. unsigned totBytesRead = 0;
  341. do {
  342. waitUntilSocketIsReadable(fEnv, sock);
  343. int bytesRead
  344. = recv(sock, &((char*)buf)[totBytesRead], numChars-totBytesRead, 0);
  345. if (bytesRead < 0) return 0;
  346. totBytesRead += (unsigned)bytesRead;
  347. } while (totBytesRead < numChars);
  348. return totBytesRead;
  349. } else {
  350. waitUntilSocketIsReadable(fEnv, (int)fileno(fFid));
  351. return fread(buf, 1, numChars, fFid);
  352. }
  353. }
  354. #define XING_FRAMES_FLAG 0x0001
  355. #define XING_BYTES_FLAG 0x0002
  356. #define XING_TOC_FLAG 0x0004
  357. #define XING_VBR_SCALE_FLAG 0x0008
  358. void MP3StreamState::checkForXingHeader() {
  359. // Look for 'Xing' in the first 4 bytes after the 'side info':
  360. if (fr().frameSize < fr().sideInfoSize) return;
  361. unsigned bytesAvailable = fr().frameSize - fr().sideInfoSize;
  362. unsigned char* p = &(fr().frameBytes[fr().sideInfoSize]);
  363. if (bytesAvailable < 8) return;
  364. if (p[0] != 'X' || p[1] != 'i' || p[2] != 'n' || p[3] != 'g') return;
  365. // We found it.
  366. fIsVBR = True;
  367. u_int32_t flags = (p[4]<<24) | (p[5]<<16) | (p[6]<<8) | p[7];
  368. unsigned i = 8;
  369. bytesAvailable -= 8;
  370. if (flags&XING_FRAMES_FLAG) {
  371. // The next 4 bytes are the number of frames:
  372. if (bytesAvailable < 4) return;
  373. fNumFramesInFile = (p[i]<<24)|(p[i+1]<<16)|(p[i+2]<<8)|(p[i+3]);
  374. i += 4; bytesAvailable -= 4;
  375. }
  376. if (flags&XING_BYTES_FLAG) {
  377. // The next 4 bytes is the file size:
  378. if (bytesAvailable < 4) return;
  379. fFileSize = (p[i]<<24)|(p[i+1]<<16)|(p[i+2]<<8)|(p[i+3]);
  380. i += 4; bytesAvailable -= 4;
  381. }
  382. if (flags&XING_TOC_FLAG) {
  383. // Fill in the Xing 'table of contents':
  384. if (bytesAvailable < XING_TOC_LENGTH) return;
  385. fHasXingTOC = True;
  386. for (unsigned j = 0; j < XING_TOC_LENGTH; ++j) {
  387. fXingTOC[j] = p[i+j];
  388. }
  389. i += XING_TOC_FLAG; bytesAvailable -= XING_TOC_FLAG;
  390. }
  391. }