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(
const bool& exitIOThreadSignalled);
218 bool addSeekEndPacket(
const bool& exitIOThreadSignalled,
double seekTargetSecs);
224 bool addEndOfFilePacket(
const bool& exitIOThreadSignalled);
229 bool addIOFinishedPacket(
const bool& exitIOThreadSignalled);
237 bool addPacket(AVPacket& packet,
const bool& exitIOThreadSignalled);
244 bool waitForFrameQueueEmpty(
bool& exitIOThreadSignalled);
249 void cancelWaitForFrameQueueEmpty();
254 void resetWaitForFrameQueueEmpty();
259 bool waitForEndOfFileProcessed();
264 void cancelWaitForEndOfFileProcessed();
269 void resetEndOfFileProcessed();
274 void waitSeekStartPacketProcessed();
280 int waitForReceiveFrame();
285 void drainSeekFrameQueue();
298 Frame tryPopFrame(
double pts);
308 Frame popSeekFrame();
313 void notifyStartIOThread();
318 void notifyExitIOThread();
331 enum class EDecodeFrameResult
339 EDecodeFrameResult decodeFrame(AVFrame& frame,
int& frameFirstPacketDTS);
340 AVPacket* popPacket();
341 void clearFrameQueue(std::queue<Frame>& frameQueue,
bool emitCallback);
344 using FrameQueue = std::queue<Frame>;
347 AVCodec* mCodec =
nullptr;
348 AVCodecContext* mCodecContext =
nullptr;
352 std::thread mDecodeThread;
353 OnClearFrameQueueFunction mOnClearFrameQueueFunction;
354 bool mExitDecodeThreadSignalled =
false;
356 FrameQueue mFrameQueue;
357 FrameQueue mSeekFrameQueue;
358 FrameQueue* mActiveFrameQueue = &mFrameQueue;
359 mutable std::mutex mFrameQueueMutex;
360 std::condition_variable mFrameDataAvailableCondition;
361 std::condition_variable mFrameQueueRoomAvailableCondition;
362 bool mCancelWaitFrameQueueEmpty =
false;
365 std::queue<AVPacket*> mPacketQueue;
366 std::mutex mPacketQueueMutex;
367 std::condition_variable mPacketAvailableCondition;
369 bool mFinishedProducingFrames =
false;
371 std::unique_ptr<AVPacket> mSeekStartPacket;
372 std::unique_ptr<AVPacket> mSeekEndPacket;
373 std::unique_ptr<AVPacket> mEndOfFilePacket;
374 std::unique_ptr<AVPacket> mIOFinishedPacket;
375 double mSeekTargetSecs;
377 utility::AutoResetEvent mEndOfFileProcessedEvent;
378 utility::AutoResetEvent mSeekStartProcessedEvent;
379 utility::AutoResetEvent mReceiveFrameEvent;
380 int mReceiveFrameResult = 0;
382 double mLastFramePTSSecs = 0.0;
383 int mFrameFirstPacketDTS = -INT_MAX;
406 Video(
const std::string& path);
444 Frame update(
double deltaTime);
452 void play(
double time = 0.0);
465 void stop(
bool blocking);
471 void seek(
double seconds);
496 const std::string&
getPath()
const {
return mPath; }
501 bool hasAudio()
const {
return mAudioState.isValid(); }
520 enum class EProducePacketResult : uint8_t
524 GotUnknownPacket = 4,
525 GotPacket = GotAudioPacket | GotVideoPacket | GotUnknownPacket,
530 enum class IOThreadState
542 static bool sInitAVState(AVState& destState,
const AVStream& stream, AVDictionary*& options, utility::ErrorState& errorState);
552 void startIOThread();
560 EProducePacketResult ProducePacket(AVState* targetState);
566 void exitIOThread(
bool join);
572 bool getNextAudioFrame(
const AudioFormat& targetAudioFormat);
577 void clearPacketQueue();
582 void clearFrameQueue();
587 void onClearVideoFrameQueue();
592 void onClearAudioFrameQueue();
597 void setErrorOccurred(
const std::string& errorMessage);
602 void finishSeeking(AVState& seekState,
bool shouldDrainFrameQueue);
607 void setSeekTarget(AVState& seekState,
double seekTargetSecs);
613 void setIOThreadState(IOThreadState threadState);
619 bool allocatePacket(uint64_t inPacketSize);
625 void deallocatePacket(uint64_t inPacketSize);
634 void decodeAudioStream(
bool enabled);
644 bool OnAudioCallback(uint8_t* dataBuffer,
int sizeInBytes,
const AudioFormat& targetAudioFormat);
648 static const double sClockMax;
649 AVFormatContext* mFormatContext =
nullptr;
650 bool mPlaying =
false;
653 float mDuration = 0.0f;
654 double mSystemClockSecs = sClockMax;
655 double mAudioDecodeClockSecs = -1;
656 double mAudioClockSecs = -1;
658 std::string mErrorMessage;
660 std::mutex mTotalPacketQueueSizeLock;
661 std::condition_variable mPacketQueueRoomAvailableCondition;
662 uint64_t mTotalPacketQueueSize = 0;
666 AVState* mSeekState =
nullptr;
667 std::thread mIOThread;
669 bool mExitIOThreadSignalled =
false;
671 int64_t mSeekKeyframeTarget = -1;
672 int64_t mSeekTarget = -1;
673 double mSeekTargetSecs = 0.0f;
675 SwrContext* mAudioResampleContext =
nullptr;
676 Frame mCurrentAudioFrame;
677 std::vector<uint8_t> mAudioResampleBuffer;
678 uint8_t* mCurrentAudioBuffer =
nullptr;
679 uint64_t mAudioFrameReadOffset = 0;
680 uint64_t mAudioFrameSize = 0;
681 bool mDecodeAudio =
false;
682 IOThreadState mIOThreadState = IOThreadState::Playing;