7 #include <condition_variable> 
   13 #include <nap/resource.h> 
   14 #include <rtti/factory.h> 
   15 #include <utility/autoresetevent.h> 
   16 #include <nap/signalslot.h> 
   20 struct AVCodecParserContext;
 
   21 struct AVCodecContext;
 
   22 struct AVFormatContext;
 
  115         int64_t     mChannelLayout;         
 
  125         bool isValid()
 const { 
return mFrame != 
nullptr; }
 
  128         AVFrame*    mFrame = 
nullptr;       
 
  129         double      mPTSSecs = 0.0;         
 
  130         int         mFirstPacketDTS = 0;    
 
  160         void init(
int stream, AVCodec* codec, AVCodecContext* codecContext);
 
  170         bool isValid()
 const { 
return mStream != -1; }
 
  181         void startDecodeThread(
const OnClearFrameQueueFunction& onClearFrameQueueFunction = OnClearFrameQueueFunction());
 
  187         void exitDecodeThread(
bool join);
 
  193         bool isFinished() 
const;
 
  198         void clearFrameQueue();
 
  203         void clearPacketQueue();
 
  208         bool matchesStream(
const AVPacket& packet) 
const;
 
  213         bool addSeekStartPacket();
 
  218         bool addSeekEndPacket(
double seekTargetSecs);
 
  224         bool addEndOfFilePacket();
 
  229         bool addIOFinishedPacket();
 
  236         bool addPacket(AVPacket& packet);
 
  243         bool waitForFrameQueueEmpty(
bool& exitIOThreadSignalled);
 
  248         void cancelWaitForFrameQueueEmpty();
 
  253         void resetWaitForFrameQueueEmpty();
 
  258         bool waitForEndOfFileProcessed();
 
  263         void cancelWaitForEndOfFileProcessed();
 
  268         void resetEndOfFileProcessed();
 
  273         void waitSeekStartPacketProcessed();
 
  279         int waitForReceiveFrame();
 
  284         void drainSeekFrameQueue();
 
  297         Frame tryPopFrame(
double pts);
 
  307         Frame popSeekFrame();
 
  312         void notifyStartIOThread();
 
  317         void notifyExitIOThread();
 
  330         enum class EDecodeFrameResult
 
  338         EDecodeFrameResult decodeFrame(AVFrame& frame, 
int& frameFirstPacketDTS);
 
  339         AVPacket* popPacket();
 
  340         void clearFrameQueue(std::queue<Frame>& frameQueue, 
bool emitCallback);
 
  343         using FrameQueue = std::queue<Frame>;
 
  346         AVCodec*                    mCodec = 
nullptr;
 
  347         AVCodecContext*             mCodecContext = 
nullptr;
 
  351         std::thread                 mDecodeThread;                          
 
  352         OnClearFrameQueueFunction   mOnClearFrameQueueFunction;             
 
  353         bool                        mExitDecodeThreadSignalled = 
false;     
 
  355         FrameQueue                  mFrameQueue;                            
 
  356         FrameQueue                  mSeekFrameQueue;                        
 
  357         FrameQueue*                 mActiveFrameQueue = &mFrameQueue;       
 
  358         mutable std::mutex          mFrameQueueMutex;                       
 
  359         std::condition_variable     mFrameDataAvailableCondition;           
 
  360         std::condition_variable     mFrameQueueRoomAvailableCondition;      
 
  361         bool                        mCancelWaitFrameQueueEmpty = 
false;     
 
  364         std::queue<AVPacket*>       mPacketQueue;                           
 
  365         std::mutex                  mPacketQueueMutex;                      
 
  366         std::condition_variable     mPacketAvailableCondition;              
 
  368         bool                        mFinishedProducingFrames = 
false;       
 
  370         std::unique_ptr<AVPacket>   mSeekStartPacket;                       
 
  371         std::unique_ptr<AVPacket>   mSeekEndPacket;                         
 
  372         std::unique_ptr<AVPacket>   mEndOfFilePacket;                       
 
  373         std::unique_ptr<AVPacket>   mIOFinishedPacket;                      
 
  374         double                      mSeekTargetSecs;                        
 
  376         utility::AutoResetEvent     mEndOfFileProcessedEvent;               
 
  377         utility::AutoResetEvent     mSeekStartProcessedEvent;               
 
  378         utility::AutoResetEvent     mReceiveFrameEvent;                     
 
  379         int                         mReceiveFrameResult = 0;                
 
  381         double                      mLastFramePTSSecs = 0.0;                
 
  382         int                         mFrameFirstPacketDTS = -INT_MAX;        
 
  405         Video(
const std::string& path);
 
  443         Frame update(
double deltaTime);
 
  451         void play(
double time = 0.0);
 
  464         void stop(
bool blocking);
 
  470         void seek(
double seconds);
 
  495         const std::string& 
getPath()
 const      { 
return mPath; }
 
  500         bool hasAudio()
 const                   { 
return mAudioState.isValid(); }
 
  519         enum class EProducePacketResult : uint8_t
 
  523             GotUnknownPacket    = 4,                                                    
 
  524             GotPacket           = GotAudioPacket | GotVideoPacket | GotUnknownPacket,   
 
  529         enum class IOThreadState
 
  541         static bool sInitAVState(AVState& destState, 
const AVStream& stream, AVDictionary*& options, utility::ErrorState& errorState);
 
  551         void startIOThread();
 
  559         EProducePacketResult ProducePacket(AVState* targetState);
 
  565         void exitIOThread(
bool join);
 
  571         bool getNextAudioFrame(
const AudioFormat& targetAudioFormat);
 
  576         void clearPacketQueue();
 
  581         void clearFrameQueue();
 
  586         void onClearVideoFrameQueue();
 
  591         void onClearAudioFrameQueue();
 
  596         void setErrorOccurred(
const std::string& errorMessage);
 
  601         void finishSeeking(AVState& seekState, 
bool shouldDrainFrameQueue);
 
  606         void setSeekTarget(AVState& seekState, 
double seekTargetSecs);
 
  612         void setIOThreadState(IOThreadState threadState);
 
  618         bool allocatePacket(uint64_t inPacketSize);
 
  624         void deallocatePacket(uint64_t inPacketSize);
 
  633         void decodeAudioStream(
bool enabled);
 
  643         bool OnAudioCallback(uint8_t* dataBuffer, 
int sizeInBytes, 
const AudioFormat& targetAudioFormat);
 
  647         static const double     sClockMax;
 
  648         AVFormatContext*        mFormatContext = 
nullptr;
 
  649         bool                    mPlaying = 
false;                           
 
  652         float                   mDuration = 0.0f;                           
 
  653         double                  mSystemClockSecs = sClockMax;               
 
  654         double                  mAudioDecodeClockSecs = -1;                 
 
  655         double                  mAudioClockSecs = -1;                       
 
  657         std::string             mErrorMessage;                              
 
  659         std::mutex              mTotalPacketQueueSizeLock;                  
 
  660         std::condition_variable mPacketQueueRoomAvailableCondition;         
 
  661         uint64_t                mTotalPacketQueueSize = 0;                  
 
  665         AVState*                mSeekState = 
nullptr;                       
 
  666         std::thread             mIOThread;                                  
 
  668         bool                    mExitIOThreadSignalled = 
false;             
 
  670         int64_t                 mSeekKeyframeTarget = -1;                   
 
  671         int64_t                 mSeekTarget = -1;                           
 
  672         double                  mSeekTargetSecs = 0.0f;                     
 
  674         SwrContext*             mAudioResampleContext = 
nullptr;            
 
  675         Frame                   mCurrentAudioFrame;                         
 
  676         std::vector<uint8_t>    mAudioResampleBuffer;                       
 
  677         uint8_t*                mCurrentAudioBuffer = 
nullptr;              
 
  678         uint64_t                mAudioFrameReadOffset = 0;                  
 
  679         uint64_t                mAudioFrameSize = 0;                        
 
  680         bool                    mDecodeAudio = 
false;                       
 
  681         IOThreadState           mIOThreadState = IOThreadState::Playing;