liveMedia/MP3FileSource.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2008 Live Networks, Inc.  All rights reserved.
00018 // MP3 File Sources
00019 // Implementation
00020 
00021 #include "MP3FileSource.hh"
00022 #include "MP3StreamState.hh"
00023 #include "InputFile.hh"
00024 
00026 
00027 MP3FileSource::MP3FileSource(UsageEnvironment& env, FILE* fid)
00028   : FramedFileSource(env, fid),
00029     fStreamState(new MP3StreamState(env)) {
00030 }
00031 
00032 MP3FileSource::~MP3FileSource() {
00033   delete fStreamState;
00034 }
00035 
00036 char const* MP3FileSource::MIMEtype() const {
00037   return "audio/MPEG";
00038 }
00039 
00040 MP3FileSource* MP3FileSource::createNew(UsageEnvironment& env, char const* fileName) {
00041   MP3FileSource* newSource = NULL;
00042 
00043   do {
00044     FILE* fid;
00045 
00046     fid = OpenInputFile(env, fileName);
00047     if (fid == NULL) break;
00048 
00049     newSource = new MP3FileSource(env, fid);
00050     if (newSource == NULL) break;
00051 
00052     unsigned fileSize = (unsigned)GetFileSize(fileName, fid);
00053     newSource->assignStream(fid, fileSize);
00054     if (!newSource->initializeStream()) break;
00055 
00056     return newSource;
00057   } while (0);
00058 
00059   Medium::close(newSource);
00060   return NULL;
00061 }
00062 
00063 float MP3FileSource::filePlayTime() const {
00064   return fStreamState->filePlayTime();
00065 }
00066 
00067 void MP3FileSource::setPresentationTimeScale(unsigned scale) {
00068   fStreamState->setPresentationTimeScale(scale);
00069 }
00070 
00071 void MP3FileSource::seekWithinFile(float seekNPT) {
00072   fStreamState->seekWithinFile(seekNPT);
00073 }
00074 
00075 void MP3FileSource::getAttributes() const {
00076   char buffer[200];
00077   fStreamState->getAttributes(buffer, sizeof buffer);
00078   envir().setResultMsg(buffer);
00079 }
00080 
00081 void MP3FileSource::doGetNextFrame() {
00082   if (!doGetNextFrame1()) {
00083     handleClosure(this);
00084     return;
00085   }
00086 
00087   // Switch to another task:
00088 #if defined(__WIN32__) || defined(_WIN32)
00089   // HACK: liveCaster/lc uses an implementation of scheduleDelayedTask()
00090   // that performs very badly (chewing up lots of CPU time, apparently polling)
00091   // on Windows.  Until this is fixed, we just call our "afterGetting()"
00092   // function directly.  This avoids infinite recursion, as long as our sink
00093   // is discontinuous, which is the case for the RTP sink that liveCaster/lc
00094   // uses. #####
00095   afterGetting(this);
00096 #else
00097   nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
00098                                 (TaskFunc*)afterGetting, this);
00099 #endif
00100 }
00101 
00102 Boolean MP3FileSource::doGetNextFrame1() {
00103   if (!fHaveJustInitialized) {
00104     if (fStreamState->findNextHeader(fPresentationTime) == 0) return False;
00105   } else {
00106     fPresentationTime = fFirstFramePresentationTime;
00107     fHaveJustInitialized = False;
00108   }
00109   
00110   if (!fStreamState->readFrame(fTo, fMaxSize, fFrameSize, fDurationInMicroseconds)) {
00111     char tmp[200];
00112     sprintf(tmp,
00113             "Insufficient buffer size %d for reading MPEG audio frame (needed %d)\n",
00114             fMaxSize, fFrameSize);
00115     envir().setResultMsg(tmp);
00116     fFrameSize = fMaxSize;
00117     return False;
00118   }
00119 
00120   return True;
00121 }
00122 
00123 void MP3FileSource::assignStream(FILE* fid, unsigned fileSize) {
00124   fStreamState->assignStream(fid, fileSize);
00125 }
00126 
00127 
00128 Boolean MP3FileSource::initializeStream() {
00129   // Make sure the file has an appropriate header near the start:
00130   if (fStreamState->findNextHeader(fFirstFramePresentationTime) == 0) {
00131       envir().setResultMsg("not an MPEG audio file");
00132       return False;
00133   }
00134 
00135   fStreamState->checkForXingHeader(); // in case this is a VBR file
00136 
00137   fHaveJustInitialized = True;
00138   // Hack: It's possible that our environment's 'result message' has been
00139   // reset within this function, so set it again to our name now:
00140   envir().setResultMsg(name());
00141   return True;
00142 }

Generated on Tue Jul 22 06:39:06 2008 for live by  doxygen 1.5.2