liveMedia/MatroskaFileServerDemux.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 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2012 Live Networks, Inc.  All rights reserved.
00018 // A server demultiplexor for a Matroska file
00019 // Implementation
00020 
00021 #include "MatroskaFileServerDemux.hh"
00022 #include "MP3AudioMatroskaFileServerMediaSubsession.hh"
00023 #include "AACAudioMatroskaFileServerMediaSubsession.hh"
00024 #include "AC3AudioMatroskaFileServerMediaSubsession.hh"
00025 #include "VorbisAudioMatroskaFileServerMediaSubsession.hh"
00026 #include "H264VideoMatroskaFileServerMediaSubsession.hh"
00027 #include "VP8VideoMatroskaFileServerMediaSubsession.hh"
00028 #include "T140TextMatroskaFileServerMediaSubsession.hh"
00029 
00030 void MatroskaFileServerDemux
00031 ::createNew(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData) {
00032   (void)new MatroskaFileServerDemux(env, fileName, onCreation, onCreationClientData);
00033 }
00034 
00035 ServerMediaSubsession* MatroskaFileServerDemux::newServerMediaSubsession() {
00036   ServerMediaSubsession* result;
00037 
00038   for (result = NULL; result == NULL && fNextTrackTypeToCheck != MATROSKA_TRACK_TYPE_OTHER; fNextTrackTypeToCheck <<= 1) {
00039     unsigned trackNumber = 0;
00040     if (fNextTrackTypeToCheck == MATROSKA_TRACK_TYPE_VIDEO) trackNumber = fOurMatroskaFile->chosenVideoTrackNumber();
00041     else if (fNextTrackTypeToCheck == MATROSKA_TRACK_TYPE_AUDIO) trackNumber = fOurMatroskaFile->chosenAudioTrackNumber();
00042     else if (fNextTrackTypeToCheck == MATROSKA_TRACK_TYPE_SUBTITLE) trackNumber = fOurMatroskaFile->chosenSubtitleTrackNumber();
00043 
00044     result = newServerMediaSubsession(trackNumber);
00045   }
00046 
00047   return result;
00048 }
00049 
00050 ServerMediaSubsession* MatroskaFileServerDemux::newServerMediaSubsession(unsigned trackNumber) {
00051   MatroskaTrack* track = fOurMatroskaFile->lookup(trackNumber);
00052   if (track == NULL) return NULL;
00053 
00054   // Use the track's "codecID" string to figure out which "ServerMediaSubsession" subclass to use:
00055   ServerMediaSubsession* result = NULL;
00056   if (strncmp(track->codecID, "A_MPEG", 6) == 0) {
00057     track->mimeType = "audio/MPEG";
00058     result = MP3AudioMatroskaFileServerMediaSubsession::createNew(*this, track->trackNumber, False, NULL);
00059   } else if (strncmp(track->codecID, "A_AAC", 5) == 0) {
00060     track->mimeType = "audio/AAC";
00061     result = AACAudioMatroskaFileServerMediaSubsession::createNew(*this, track->trackNumber);
00062   } else if (strncmp(track->codecID, "A_AC3", 5) == 0) {
00063     track->mimeType = "audio/AC3";
00064     result = AC3AudioMatroskaFileServerMediaSubsession::createNew(*this, track->trackNumber);
00065   } else if (strncmp(track->codecID, "A_VORBIS", 8) == 0) {
00066     track->mimeType = "audio/VORBIS";
00067     result = VorbisAudioMatroskaFileServerMediaSubsession::createNew(*this, track->trackNumber);
00068   } else if (strcmp(track->codecID, "V_MPEG4/ISO/AVC") == 0) {
00069     track->mimeType = "video/H264";
00070     result = H264VideoMatroskaFileServerMediaSubsession::createNew(*this, track->trackNumber);
00071   } else if (strncmp(track->codecID, "V_VP8", 5) == 0) {
00072     track->mimeType = "video/VP8";
00073     result = VP8VideoMatroskaFileServerMediaSubsession::createNew(*this, track->trackNumber);
00074   } else if (strncmp(track->codecID, "S_TEXT", 6) == 0) {
00075     track->mimeType = "text/T140";
00076     result = T140TextMatroskaFileServerMediaSubsession::createNew(*this, track->trackNumber);
00077   }
00078 
00079   if (result != NULL) {
00080 #ifdef DEBUG
00081     fprintf(stderr, "Created 'ServerMediaSubsession' object for track #%d: %s (%s)\n", track->trackNumber, track->codecID, track->mimeType);
00082 #endif
00083   }
00084 
00085   return result;
00086 }
00087 
00088 FramedSource* MatroskaFileServerDemux::newDemuxedTrack(unsigned clientSessionId, unsigned trackNumber) {
00089   MatroskaDemux* demuxToUse = NULL;
00090 
00091   if (clientSessionId != 0 && clientSessionId == fLastClientSessionId) {
00092     demuxToUse = fLastCreatedDemux; // use the same demultiplexor as before
00093       // Note: This code relies upon the fact that the creation of streams for different
00094       // client sessions do not overlap - so all demuxed tracks are created for one "MatroskaDemux" at a time.
00095       // Also, the "clientSessionId != 0" test is a hack, because 'session 0' is special; its audio and video streams
00096       // are created and destroyed one-at-a-time, rather than both streams being
00097       // created, and then (later) both streams being destroyed (as is the case
00098       // for other ('real') session ids).  Because of this, a separate demultiplexor is used for each 'session 0' track.
00099   }
00100 
00101   if (demuxToUse == NULL) demuxToUse = fOurMatroskaFile->newDemux();
00102 
00103   fLastClientSessionId = clientSessionId;
00104   fLastCreatedDemux = demuxToUse;
00105 
00106   return demuxToUse->newDemuxedTrack(trackNumber);
00107 }
00108 
00109 MatroskaFileServerDemux
00110 ::MatroskaFileServerDemux(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData)
00111   : Medium(env),
00112     fFileName(fileName), fOnCreation(onCreation), fOnCreationClientData(onCreationClientData),
00113     fNextTrackTypeToCheck(0x1), fLastClientSessionId(0), fLastCreatedDemux(NULL) {
00114   MatroskaFile::createNew(env, fileName, onMatroskaFileCreation, this);
00115 }
00116 
00117 MatroskaFileServerDemux::~MatroskaFileServerDemux() {
00118   Medium::close(fOurMatroskaFile);
00119 }
00120 
00121 void MatroskaFileServerDemux::onMatroskaFileCreation(MatroskaFile* newFile, void* clientData) {
00122   ((MatroskaFileServerDemux*)clientData)->onMatroskaFileCreation(newFile);
00123 }
00124 
00125 void MatroskaFileServerDemux::onMatroskaFileCreation(MatroskaFile* newFile) {
00126   fOurMatroskaFile = newFile;
00127 
00128   // Now, call our own creation notification function:
00129   if (fOnCreation != NULL) (*fOnCreation)(this, fOnCreationClientData);
00130 }

Generated on Thu May 17 07:11:46 2012 for live by  doxygen 1.5.2