liveMedia/include/MatroskaFile.hh

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 class that encapsulates a Matroska file.
00019 // C++ header
00020 
00021 #ifndef _MATROSKA_FILE_HH
00022 #define _MATROSKA_FILE_HH
00023 
00024 #ifndef _MEDIA_HH
00025 #include "Media.hh"
00026 #endif
00027 #ifndef _HASH_TABLE_HH
00028 #include "HashTable.hh"
00029 #endif
00030 
00031 class MatroskaTrack; // forward
00032 class MatroskaDemux; // forward
00033 
00034 class MatroskaFile: public Medium {
00035 public:
00036   typedef void (onCreationFunc)(MatroskaFile* newFile, void* clientData);
00037   static void createNew(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData,
00038                         char const* preferredLanguage = "eng");
00039     // Note: Unlike most "createNew()" functions, this one doesn't return a new object immediately.  Instead, because this class
00040     // requires file reading (to parse the Matroska 'Track' headers) before a new object can be initialized, the creation of a new
00041     // object is signalled by calling - from the event loop - an 'onCreationFunc' that is passed as a parameter to "createNew()".
00042 
00043   // For looking up and iterating over the file's tracks:
00044   class TrackTable {
00045   public:
00046     TrackTable();
00047     virtual ~TrackTable();
00048 
00049     void add(MatroskaTrack* newTrack, unsigned trackNumber);
00050     MatroskaTrack* lookup(unsigned trackNumber);
00051 
00052     unsigned numTracks() const;
00053 
00054     class Iterator {
00055     public:
00056       Iterator(TrackTable& ourTable);
00057       virtual ~Iterator();
00058       MatroskaTrack* next();
00059     private:
00060       TrackTable& fOurTable;
00061       HashTable::Iterator* fIter;
00062     };
00063 
00064   private:
00065     friend class Iterator;
00066     HashTable* fTable;
00067   };
00068 
00069   MatroskaTrack* lookup(unsigned trackNumber) { return fTracks.lookup(trackNumber); } // shortcut
00070 
00071   // Create a demultiplexor for extracting tracks from this file.  (Separate clients will typically have separate demultiplexors.)
00072   MatroskaDemux* newDemux();
00073 
00074   // Parameters of the file ('Segment'); set when the file is parsed:
00075   unsigned timecodeScale() { return fTimecodeScale; } // in nanoseconds
00076   float segmentDuration() { return fSegmentDuration; } // in units of "timecodeScale()"
00077   float fileDuration(); // in seconds
00078   TrackTable& tracks() { return fTracks; }
00079   
00080   char const* fileName() const { return fFileName; }
00081 
00082   unsigned chosenVideoTrackNumber() { return fChosenVideoTrackNumber; }
00083   unsigned chosenAudioTrackNumber() { return fChosenAudioTrackNumber; }
00084   unsigned chosenSubtitleTrackNumber() { return fChosenSubtitleTrackNumber; }
00085 
00086 private:
00087   MatroskaFile(UsageEnvironment& env, char const* fileName, onCreationFunc* onCreation, void* onCreationClientData,
00088                char const* preferredLanguage);
00089       // called only by createNew()
00090   virtual ~MatroskaFile();
00091 
00092   static void handleEndOfTrackHeaderParsing(void* clientData);
00093   void handleEndOfTrackHeaderParsing();
00094 
00095   void addCuePoint(double cueTime, u_int64_t clusterOffsetInFile, unsigned blockNumWithinCluster);
00096   Boolean lookupCuePoint(double& cueTime, u_int64_t& resultClusterOffsetInFile, unsigned& resultBlockNumWithinCluster);
00097   void printCuePoints(FILE* fid);
00098 
00099   void removeDemux(MatroskaDemux* demux);
00100 
00101 private:
00102   friend class MatroskaFileParser;
00103   friend class MatroskaDemux;
00104   char const* fFileName;
00105   onCreationFunc* fOnCreation;
00106   void* fOnCreationClientData;
00107   char const* fPreferredLanguage;
00108 
00109   unsigned fTimecodeScale; // in nanoseconds
00110   float fSegmentDuration; // in units of "fTimecodeScale"
00111   u_int64_t fSegmentDataOffset, fClusterOffset, fCuesOffset;
00112 
00113   TrackTable fTracks;
00114   HashTable* fDemuxesTable;
00115   class CuePoint* fCuePoints;
00116   unsigned fChosenVideoTrackNumber, fChosenAudioTrackNumber, fChosenSubtitleTrackNumber;
00117   class MatroskaFileParser* fParserForInitialization;
00118 };
00119 
00120 // We define our own track type codes as bits (powers of 2), so we can use the set of track types as a bitmap, representing a set:
00121 // (Note that MATROSKA_TRACK_TYPE_OTHER must be last, and have the largest value.)
00122 #define MATROSKA_TRACK_TYPE_VIDEO 0x01
00123 #define MATROSKA_TRACK_TYPE_AUDIO 0x02
00124 #define MATROSKA_TRACK_TYPE_SUBTITLE 0x04
00125 #define MATROSKA_TRACK_TYPE_OTHER 0x08
00126 
00127 class MatroskaTrack {
00128 public:
00129   MatroskaTrack();
00130   virtual ~MatroskaTrack();
00131 
00132   // track parameters
00133   unsigned trackNumber;
00134   u_int8_t trackType;
00135   Boolean isEnabled, isDefault, isForced;
00136   unsigned defaultDuration;
00137   char* name;
00138   char* language;
00139   char* codecID;
00140   unsigned samplingFrequency;
00141   unsigned numChannels;
00142   char const* mimeType;
00143   unsigned codecPrivateSize;
00144   u_int8_t* codecPrivate;
00145   unsigned headerStrippedBytesSize;
00146   u_int8_t* headerStrippedBytes;
00147   unsigned subframeSizeSize; // 0 means: frames do not have subframes (the default behavior)
00148   Boolean haveSubframes() const { return subframeSizeSize > 0; }
00149 
00150   // The following are used when delivering frames from this track (if there's no "default duration"):
00151   struct timeval prevPresentationTime;
00152   int durationImbalance; // the difference between the presentation times that we've delivered, and frame durations (in useconds)
00153 };
00154 
00155 class MatroskaDemux: public Medium {
00156 public:
00157   FramedSource* newDemuxedTrack(unsigned trackNumber);
00158     // Note: We assume that:
00159     // - Every track created by "newDemuxedTrack()" is later read
00160     // - All calls to "newDemuxedTrack()" are made before any track is read
00161 
00162   class MatroskaDemuxedTrack* lookupDemuxedTrack(unsigned trackNumber);
00163 
00164 protected:
00165   friend class MatroskaFile;
00166   MatroskaDemux(MatroskaFile& ourFile); // we're created only by a "MatroskaFile" (a friend)
00167   virtual ~MatroskaDemux();
00168 
00169 private:
00170   friend class MatroskaDemuxedTrack;
00171   void removeTrack(unsigned trackNumber);
00172   void continueReading(); // called by a demuxed track to tell us that it has a pending read ("doGetNextFrame()")
00173   void seekToTime(double& seekNPT);
00174 
00175   static void handleEndOfFile(void* clientData);
00176   void handleEndOfFile();
00177 
00178 private:
00179   MatroskaFile& fOurFile;
00180   class MatroskaFileParser* fOurParser;
00181   HashTable* fDemuxedTracksTable;
00182 };
00183 
00184 #endif

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