Gnash
0.8.10
|
00001 // MediaParser.h: Base class for media parsers 00002 // 00003 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 00004 // Free Software Foundation, Inc. 00005 // 00006 // This program is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU General Public License as published by 00008 // the Free Software Foundation; either version 3 of the License, or 00009 // (at your option) any later version. 00010 // 00011 // This program is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with this program; if not, write to the Free Software 00018 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00019 00020 #ifndef GNASH_MEDIAPARSER_H 00021 #define GNASH_MEDIAPARSER_H 00022 00023 #include <boost/scoped_array.hpp> 00024 #include <boost/shared_ptr.hpp> 00025 #include <boost/thread/thread.hpp> 00026 #include <boost/thread/condition.hpp> 00027 #include <boost/thread/barrier.hpp> 00028 #include <memory> 00029 #include <deque> 00030 #include <map> 00031 #include <vector> 00032 #include <iosfwd> // for output operator forward declarations 00033 #include <boost/optional.hpp> 00034 00035 #include "IOChannel.h" // for inlines 00036 #include "dsodefs.h" // DSOEXPORT 00037 00038 // Undefine this to load/parse media files in main thread 00039 #define LOAD_MEDIA_IN_A_SEPARATE_THREAD 1 00040 00041 namespace gnash { 00042 class SimpleBuffer; 00043 namespace media { 00044 struct Id3Info; 00045 } 00046 } 00047 00048 namespace gnash { 00049 namespace media { 00050 00051 00053 enum videoFrameType 00054 { 00056 KEY_FRAME = 1, 00057 00059 INTER_FRAME = 2, 00060 00062 DIS_INTER_FRAME = 3 00063 }; 00064 00066 enum codecType 00067 { 00069 CODEC_TYPE_FLASH, 00070 00072 CODEC_TYPE_CUSTOM 00073 }; 00074 00076 enum videoCodecType 00077 { 00079 VIDEO_CODEC_H263 = 2, 00080 00082 VIDEO_CODEC_SCREENVIDEO = 3, 00083 00085 VIDEO_CODEC_VP6 = 4, 00086 00088 VIDEO_CODEC_VP6A = 5, 00089 00091 VIDEO_CODEC_SCREENVIDEO2 = 6, 00092 00094 VIDEO_CODEC_H264 = 7 00095 00096 // NOTE: if you add more elements here remember to 00097 // also add them to the output operator! 00098 }; 00099 00100 DSOEXPORT std::ostream& operator<< (std::ostream& os, const videoCodecType& t); 00101 00103 // 00120 enum audioCodecType 00121 { 00123 // 00133 AUDIO_CODEC_RAW = 0, 00134 00136 // 00146 AUDIO_CODEC_ADPCM = 1, 00147 00149 // 00162 AUDIO_CODEC_MP3 = 2, 00163 00165 AUDIO_CODEC_UNCOMPRESSED = 3, 00166 00168 // 00172 AUDIO_CODEC_NELLYMOSER_8HZ_MONO = 5, 00173 00175 // 00179 AUDIO_CODEC_NELLYMOSER = 6, 00180 00182 AUDIO_CODEC_AAC = 10, 00183 00185 AUDIO_CODEC_SPEEX = 11 00186 00187 // NOTE: if you add more elements here remember to 00188 // also add them to the output operator! 00189 }; 00190 00191 DSOEXPORT std::ostream& operator<< (std::ostream& os, const audioCodecType& t); 00192 00194 // 00200 class AudioInfo 00201 { 00202 00203 public: 00204 00206 // 00231 AudioInfo(int codeci, boost::uint16_t sampleRatei, 00232 boost::uint16_t sampleSizei, bool stereoi, 00233 boost::uint64_t durationi, codecType typei) 00234 : 00235 codec(codeci), 00236 sampleRate(sampleRatei), 00237 sampleSize(sampleSizei), 00238 stereo(stereoi), 00239 duration(durationi), 00240 type(typei) 00241 { 00242 } 00243 00245 // 00250 int codec; 00251 00252 boost::uint16_t sampleRate; 00253 00255 boost::uint16_t sampleSize; 00256 00257 bool stereo; 00258 00259 boost::uint64_t duration; 00260 00261 codecType type; 00262 00264 // 00268 class ExtraInfo { 00269 public: 00270 virtual ~ExtraInfo() {} 00271 }; 00272 00274 // 00277 std::auto_ptr<ExtraInfo> extra; 00278 }; 00279 00281 // 00286 class VideoInfo 00287 { 00288 public: 00289 00291 // 00318 VideoInfo(int codeci, boost::uint16_t widthi, boost::uint16_t heighti, 00319 boost::uint16_t frameRatei, boost::uint64_t durationi, 00320 codecType typei) 00321 : 00322 codec(codeci), 00323 width(widthi), 00324 height(heighti), 00325 frameRate(frameRatei), 00326 duration(durationi), 00327 type(typei) 00328 { 00329 } 00330 00331 int codec; 00332 boost::uint16_t width; 00333 boost::uint16_t height; 00334 boost::uint16_t frameRate; 00335 boost::uint64_t duration; 00336 codecType type; 00337 00339 // 00343 class ExtraInfo { 00344 public: 00345 virtual ~ExtraInfo() {} 00346 }; 00347 00349 // 00352 std::auto_ptr<ExtraInfo> extra; 00353 }; 00354 00355 DSOEXPORT std::ostream& operator << (std::ostream& os, const VideoInfo& vi); 00356 00357 00358 class EncodedExtraData { 00359 00360 public: 00361 virtual ~EncodedExtraData() {} 00362 00363 }; 00364 00366 class EncodedVideoFrame 00367 { 00368 public: 00369 00371 // 00384 EncodedVideoFrame(boost::uint8_t* data, boost::uint32_t size, 00385 unsigned int frameNum, 00386 boost::uint64_t timestamp=0) 00387 : 00388 _size(size), 00389 _data(data), 00390 _frameNum(frameNum), 00391 _timestamp(timestamp) 00392 {} 00393 00395 const boost::uint8_t* data() const { return _data.get(); } 00396 00398 boost::uint32_t dataSize() const { return _size; } 00399 00401 boost::uint64_t timestamp() const { return _timestamp; } 00402 00404 unsigned frameNum() const { return _frameNum; } 00405 00406 // FIXME: should have better encapsulation for this sort of stuff. 00407 std::auto_ptr<EncodedExtraData> extradata; 00408 private: 00409 00410 boost::uint32_t _size; 00411 boost::scoped_array<boost::uint8_t> _data; 00412 unsigned int _frameNum; 00413 boost::uint64_t _timestamp; 00414 }; 00415 00417 class EncodedAudioFrame 00418 { 00419 public: 00420 boost::uint32_t dataSize; 00421 boost::scoped_array<boost::uint8_t> data; 00422 boost::uint64_t timestamp; 00423 00424 // FIXME: should have better encapsulation for this sort of stuff. 00425 std::auto_ptr<EncodedExtraData> extradata; 00426 }; 00427 00429 // 00436 class MediaParser 00437 { 00438 public: 00439 00441 // 00443 typedef std::multimap<boost::uint64_t, boost::shared_ptr<SimpleBuffer> > 00444 MetaTags; 00445 00446 typedef std::vector<MetaTags::mapped_type> OrderedMetaTags; 00447 MediaParser(std::auto_ptr<IOChannel> stream); 00448 00449 // Classes with virtual methods (virtual classes) 00450 // must have a virtual destructor, or the destructors 00451 // of subclasses will never be invoked, tipically resulting 00452 // in memory leaks.. 00453 // 00454 virtual ~MediaParser(); 00455 00459 // 00466 virtual bool seek(boost::uint32_t& time)=0; 00467 00469 // 00477 DSOEXPORT boost::uint64_t getBufferLength() const; 00478 00480 // 00482 DSOEXPORT bool isBufferEmpty() const; 00483 00485 DSOEXPORT boost::uint64_t getBufferTime() const 00486 { 00487 boost::mutex::scoped_lock lock(_bufferTimeMutex); 00488 return _bufferTime; 00489 } 00490 00492 // 00496 DSOEXPORT void setBufferTime(boost::uint64_t t) 00497 { 00498 boost::mutex::scoped_lock lock(_bufferTimeMutex); 00499 _bufferTime=t; 00500 } 00501 00503 // 00509 DSOEXPORT bool nextFrameTimestamp(boost::uint64_t& ts) const; 00510 00512 // 00518 DSOEXPORT bool nextVideoFrameTimestamp(boost::uint64_t& ts) const; 00519 00521 // 00527 DSOEXPORT std::auto_ptr<EncodedVideoFrame> nextVideoFrame(); 00528 00530 // 00536 DSOEXPORT bool nextAudioFrameTimestamp(boost::uint64_t& ts) const; 00537 00539 // 00545 DSOEXPORT std::auto_ptr<EncodedAudioFrame> nextAudioFrame(); 00546 00548 // 00552 VideoInfo* getVideoInfo() { return _videoInfo.get(); } 00553 00555 // 00559 AudioInfo* getAudioInfo() { return _audioInfo.get(); } 00560 00562 // 00568 bool parsingCompleted() const { return _parsingComplete; } 00569 00571 // 00578 virtual bool indexingCompleted() const { return true; } 00579 00581 virtual boost::uint64_t getBytesLoaded() const { return 0; } 00582 00584 boost::uint64_t getBytesTotal() const 00585 { 00586 return _stream->size(); 00587 } 00588 00590 // 00598 virtual bool parseNextChunk()=0; 00599 00601 // 00606 // 00609 virtual void fetchMetaTags(OrderedMetaTags& tags, boost::uint64_t ts); 00610 00612 // 00614 virtual boost::optional<Id3Info> getId3Info() const; 00615 00616 protected: 00617 00619 00621 std::auto_ptr<VideoInfo> _videoInfo; 00622 00624 std::auto_ptr<AudioInfo> _audioInfo; 00625 00627 bool _parsingComplete; 00628 00630 boost::uint64_t _bytesLoaded; 00631 00633 00635 void startParserThread(); 00636 00638 // 00644 void stopParserThread(); 00645 00647 void clearBuffers(); 00648 00650 // 00653 void pushEncodedAudioFrame(std::auto_ptr<EncodedAudioFrame> frame); 00654 00656 // 00659 void pushEncodedVideoFrame(std::auto_ptr<EncodedVideoFrame> frame); 00660 00662 std::auto_ptr<IOChannel> _stream; 00663 mutable boost::mutex _streamMutex; 00664 00665 static void parserLoopStarter(MediaParser* mp) 00666 { 00667 mp->parserLoop(); 00668 } 00669 00678 void parserLoop(); 00679 00680 bool parserThreadKillRequested() const 00681 { 00682 boost::mutex::scoped_lock lock(_parserThreadKillRequestMutex); 00683 return _parserThreadKillRequested; 00684 } 00685 00686 boost::uint64_t _bufferTime; 00687 mutable boost::mutex _bufferTimeMutex; 00688 00689 std::auto_ptr<boost::thread> _parserThread; 00690 boost::barrier _parserThreadStartBarrier; 00691 mutable boost::mutex _parserThreadKillRequestMutex; 00692 bool _parserThreadKillRequested; 00693 boost::condition _parserThreadWakeup; 00694 00700 void waitIfNeeded(boost::mutex::scoped_lock& qMutexLock); 00701 00702 void wakeupParserThread(); 00703 00705 mutable boost::mutex _qMutex; 00706 00708 mutable boost::mutex _bytesLoadedMutex; 00709 00711 // 00717 bool bufferFull() const; 00718 00722 bool _seekRequest; 00723 00724 private: 00725 00726 typedef std::deque<EncodedVideoFrame*> VideoFrames; 00727 typedef std::deque<EncodedAudioFrame*> AudioFrames; 00728 00730 // 00735 const EncodedVideoFrame* peekNextVideoFrame() const; 00736 00738 // 00743 const EncodedAudioFrame* peekNextAudioFrame() const; 00744 00745 00747 // 00750 VideoFrames _videoFrames; 00751 00753 // 00756 AudioFrames _audioFrames; 00757 00758 void requestParserThreadKill() 00759 { 00760 boost::mutex::scoped_lock lock(_parserThreadKillRequestMutex); 00761 _parserThreadKillRequested=true; 00762 _parserThreadWakeup.notify_all(); 00763 } 00764 00766 boost::uint64_t audioBufferLength() const; 00767 00769 boost::uint64_t videoBufferLength() const; 00770 00772 boost::uint64_t getBufferLengthNoLock() const; 00773 00774 }; 00775 00776 00777 } // gnash.media namespace 00778 } // namespace gnash 00779 00780 #endif // __MEDIAPARSER_H__