Gnash 0.8.9
|
00001 // MediaParser.h: Base class for media parsers 00002 // 00003 // Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 #ifndef GNASH_MEDIAPARSER_H 00020 #define GNASH_MEDIAPARSER_H 00021 00022 #include "IOChannel.h" // for inlines 00023 #include "dsodefs.h" // DSOEXPORT 00024 00025 #include <boost/scoped_array.hpp> 00026 #include <boost/shared_ptr.hpp> 00027 #include <boost/thread/thread.hpp> 00028 #include <boost/thread/condition.hpp> 00029 #include <boost/thread/barrier.hpp> 00030 #include <memory> 00031 #include <deque> 00032 #include <map> 00033 #include <vector> 00034 #include <iosfwd> // for output operator forward declarations 00035 00036 // Undefine this to load/parse media files in main thread 00037 #define LOAD_MEDIA_IN_A_SEPARATE_THREAD 1 00038 00039 namespace gnash { 00040 class SimpleBuffer; 00041 } 00042 00043 namespace gnash { 00044 namespace media { 00045 00046 00048 enum videoFrameType 00049 { 00051 KEY_FRAME = 1, 00052 00054 INTER_FRAME = 2, 00055 00057 DIS_INTER_FRAME = 3 00058 }; 00059 00061 enum codecType 00062 { 00064 CODEC_TYPE_FLASH, 00065 00067 CODEC_TYPE_CUSTOM 00068 }; 00069 00071 enum videoCodecType 00072 { 00074 VIDEO_CODEC_H263 = 2, 00075 00077 VIDEO_CODEC_SCREENVIDEO = 3, 00078 00080 VIDEO_CODEC_VP6 = 4, 00081 00083 VIDEO_CODEC_VP6A = 5, 00084 00086 VIDEO_CODEC_SCREENVIDEO2 = 6, 00087 00089 VIDEO_CODEC_H264 = 7 00090 00091 // NOTE: if you add more elements here remember to 00092 // also add them to the output operator! 00093 }; 00094 00095 DSOEXPORT std::ostream& operator<< (std::ostream& os, const videoCodecType& t); 00096 00098 // 00115 enum audioCodecType 00116 { 00118 // 00128 AUDIO_CODEC_RAW = 0, 00129 00131 // 00141 AUDIO_CODEC_ADPCM = 1, 00142 00144 // 00157 AUDIO_CODEC_MP3 = 2, 00158 00160 AUDIO_CODEC_UNCOMPRESSED = 3, 00161 00163 // 00167 AUDIO_CODEC_NELLYMOSER_8HZ_MONO = 5, 00168 00170 // 00174 AUDIO_CODEC_NELLYMOSER = 6, 00175 00177 AUDIO_CODEC_AAC = 10, 00178 00180 AUDIO_CODEC_SPEEX = 11 00181 00182 // NOTE: if you add more elements here remember to 00183 // also add them to the output operator! 00184 }; 00185 00186 DSOEXPORT std::ostream& operator<< (std::ostream& os, const audioCodecType& t); 00187 00189 // 00195 class AudioInfo 00196 { 00197 00198 public: 00199 00201 // 00226 AudioInfo(int codeci, boost::uint16_t sampleRatei, 00227 boost::uint16_t sampleSizei, bool stereoi, 00228 boost::uint64_t durationi, codecType typei) 00229 : 00230 codec(codeci), 00231 sampleRate(sampleRatei), 00232 sampleSize(sampleSizei), 00233 stereo(stereoi), 00234 duration(durationi), 00235 type(typei) 00236 { 00237 } 00238 00240 // 00245 int codec; 00246 00247 boost::uint16_t sampleRate; 00248 00250 boost::uint16_t sampleSize; 00251 00252 bool stereo; 00253 00254 boost::uint64_t duration; 00255 00256 codecType type; 00257 00259 // 00263 class ExtraInfo { 00264 public: 00265 virtual ~ExtraInfo() {} 00266 }; 00267 00269 // 00272 std::auto_ptr<ExtraInfo> extra; 00273 }; 00274 00276 // 00281 class VideoInfo 00282 { 00283 public: 00284 00286 // 00313 VideoInfo(int codeci, boost::uint16_t widthi, boost::uint16_t heighti, 00314 boost::uint16_t frameRatei, boost::uint64_t durationi, 00315 codecType typei) 00316 : 00317 codec(codeci), 00318 width(widthi), 00319 height(heighti), 00320 frameRate(frameRatei), 00321 duration(durationi), 00322 type(typei) 00323 { 00324 } 00325 00326 int codec; 00327 boost::uint16_t width; 00328 boost::uint16_t height; 00329 boost::uint16_t frameRate; 00330 boost::uint64_t duration; 00331 codecType type; 00332 00334 // 00338 class ExtraInfo { 00339 public: 00340 virtual ~ExtraInfo() {} 00341 }; 00342 00344 // 00347 std::auto_ptr<ExtraInfo> extra; 00348 }; 00349 00350 DSOEXPORT std::ostream& operator << (std::ostream& os, const VideoInfo& vi); 00351 00352 00353 class EncodedExtraData { 00354 00355 public: 00356 virtual ~EncodedExtraData() {} 00357 00358 }; 00359 00361 class EncodedVideoFrame 00362 { 00363 public: 00364 00366 // 00379 EncodedVideoFrame(boost::uint8_t* data, boost::uint32_t size, 00380 unsigned int frameNum, 00381 boost::uint64_t timestamp=0) 00382 : 00383 _size(size), 00384 _data(data), 00385 _frameNum(frameNum), 00386 _timestamp(timestamp) 00387 {} 00388 00390 const boost::uint8_t* data() const { return _data.get(); } 00391 00393 boost::uint32_t dataSize() const { return _size; } 00394 00396 boost::uint64_t timestamp() const { return _timestamp; } 00397 00399 unsigned frameNum() const { return _frameNum; } 00400 00401 // FIXME: should have better encapsulation for this sort of stuff. 00402 std::auto_ptr<EncodedExtraData> extradata; 00403 private: 00404 00405 boost::uint32_t _size; 00406 boost::scoped_array<boost::uint8_t> _data; 00407 unsigned int _frameNum; 00408 boost::uint64_t _timestamp; 00409 }; 00410 00412 class EncodedAudioFrame 00413 { 00414 public: 00415 boost::uint32_t dataSize; 00416 boost::scoped_array<boost::uint8_t> data; 00417 boost::uint64_t timestamp; 00418 00419 // FIXME: should have better encapsulation for this sort of stuff. 00420 std::auto_ptr<EncodedExtraData> extradata; 00421 }; 00422 00424 // 00431 class MediaParser 00432 { 00433 public: 00434 00436 // 00438 typedef std::multimap<boost::uint64_t, boost::shared_ptr<SimpleBuffer> > 00439 MetaTags; 00440 00441 typedef std::vector<MetaTags::mapped_type> OrderedMetaTags; 00442 MediaParser(std::auto_ptr<IOChannel> stream); 00443 00444 // Classes with virtual methods (virtual classes) 00445 // must have a virtual destructor, or the destructors 00446 // of subclasses will never be invoked, tipically resulting 00447 // in memory leaks.. 00448 // 00449 virtual ~MediaParser(); 00450 00454 // 00461 virtual bool seek(boost::uint32_t& time)=0; 00462 00464 // 00472 DSOEXPORT boost::uint64_t getBufferLength() const; 00473 00475 // 00477 DSOEXPORT bool isBufferEmpty() const; 00478 00480 DSOEXPORT boost::uint64_t getBufferTime() const 00481 { 00482 boost::mutex::scoped_lock lock(_bufferTimeMutex); 00483 return _bufferTime; 00484 } 00485 00487 // 00491 DSOEXPORT void setBufferTime(boost::uint64_t t) 00492 { 00493 boost::mutex::scoped_lock lock(_bufferTimeMutex); 00494 _bufferTime=t; 00495 } 00496 00498 // 00504 DSOEXPORT bool nextFrameTimestamp(boost::uint64_t& ts) const; 00505 00507 // 00513 DSOEXPORT bool nextVideoFrameTimestamp(boost::uint64_t& ts) const; 00514 00516 // 00522 DSOEXPORT std::auto_ptr<EncodedVideoFrame> nextVideoFrame(); 00523 00525 // 00531 DSOEXPORT bool nextAudioFrameTimestamp(boost::uint64_t& ts) const; 00532 00534 // 00540 DSOEXPORT std::auto_ptr<EncodedAudioFrame> nextAudioFrame(); 00541 00543 // 00547 VideoInfo* getVideoInfo() { return _videoInfo.get(); } 00548 00550 // 00554 AudioInfo* getAudioInfo() { return _audioInfo.get(); } 00555 00557 // 00563 bool parsingCompleted() const { return _parsingComplete; } 00564 00566 // 00573 virtual bool indexingCompleted() const { return true; } 00574 00576 virtual boost::uint64_t getBytesLoaded() const { return 0; } 00577 00579 boost::uint64_t getBytesTotal() const 00580 { 00581 return _stream->size(); 00582 } 00583 00585 // 00593 virtual bool parseNextChunk()=0; 00594 00596 // 00601 // 00604 virtual void fetchMetaTags(OrderedMetaTags& tags, boost::uint64_t ts); 00605 00606 protected: 00607 00609 00611 std::auto_ptr<VideoInfo> _videoInfo; 00612 00614 std::auto_ptr<AudioInfo> _audioInfo; 00615 00617 bool _parsingComplete; 00618 00620 boost::uint64_t _bytesLoaded; 00621 00623 00625 void startParserThread(); 00626 00628 // 00634 void stopParserThread(); 00635 00637 void clearBuffers(); 00638 00640 // 00643 void pushEncodedAudioFrame(std::auto_ptr<EncodedAudioFrame> frame); 00644 00646 // 00649 void pushEncodedVideoFrame(std::auto_ptr<EncodedVideoFrame> frame); 00650 00652 std::auto_ptr<IOChannel> _stream; 00653 mutable boost::mutex _streamMutex; 00654 00655 static void parserLoopStarter(MediaParser* mp) 00656 { 00657 mp->parserLoop(); 00658 } 00659 00668 void parserLoop(); 00669 00670 bool parserThreadKillRequested() const 00671 { 00672 boost::mutex::scoped_lock lock(_parserThreadKillRequestMutex); 00673 return _parserThreadKillRequested; 00674 } 00675 00676 boost::uint64_t _bufferTime; 00677 mutable boost::mutex _bufferTimeMutex; 00678 00679 std::auto_ptr<boost::thread> _parserThread; 00680 boost::barrier _parserThreadStartBarrier; 00681 mutable boost::mutex _parserThreadKillRequestMutex; 00682 bool _parserThreadKillRequested; 00683 boost::condition _parserThreadWakeup; 00684 00690 void waitIfNeeded(boost::mutex::scoped_lock& qMutexLock); 00691 00692 void wakeupParserThread(); 00693 00695 mutable boost::mutex _qMutex; 00696 00697 00699 mutable boost::mutex _bytesLoadedMutex; 00700 00702 // 00708 bool bufferFull() const; 00709 00713 bool _seekRequest; 00714 00715 private: 00716 00717 typedef std::deque<EncodedVideoFrame*> VideoFrames; 00718 typedef std::deque<EncodedAudioFrame*> AudioFrames; 00719 00721 // 00726 const EncodedVideoFrame* peekNextVideoFrame() const; 00727 00729 // 00734 const EncodedAudioFrame* peekNextAudioFrame() const; 00735 00736 00738 // 00741 VideoFrames _videoFrames; 00742 00744 // 00747 AudioFrames _audioFrames; 00748 00749 void requestParserThreadKill() 00750 { 00751 boost::mutex::scoped_lock lock(_parserThreadKillRequestMutex); 00752 _parserThreadKillRequested=true; 00753 _parserThreadWakeup.notify_all(); 00754 } 00755 00757 boost::uint64_t audioBufferLength() const; 00758 00760 boost::uint64_t videoBufferLength() const; 00761 00763 boost::uint64_t getBufferLengthNoLock() const; 00764 00765 }; 00766 00767 00768 } // gnash.media namespace 00769 } // namespace gnash 00770 00771 #endif // __MEDIAPARSER_H__