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;