File indexing completed on 2024-06-16 04:38:31
0001 /* 0002 SPDX-FileCopyrightText: 2003 Fabrice Bellard 0003 SPDX-FileCopyrightText: 2020-2022 Mladen Milinkovic <max@smoothware.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #ifndef VIDEOSTATE_H 0009 #define VIDEOSTATE_H 0010 0011 #include <cmath> 0012 0013 #include "videoplayer/backend/videodecoder.h" 0014 #include "videoplayer/backend/audiodecoder.h" 0015 #include "videoplayer/backend/subtitledecoder.h" 0016 #include "videoplayer/backend/framequeue.h" 0017 #include "videoplayer/backend/packetqueue.h" 0018 #include "videoplayer/backend/streamdemuxer.h" 0019 #include "videoplayer/backend/clock.h" 0020 0021 #include <QString> 0022 #include <QWaitCondition> 0023 0024 extern "C" { 0025 #include "libavformat/avformat.h" 0026 #include "libavcodec/avfft.h" 0027 #include "libswscale/swscale.h" 0028 } 0029 0030 0031 #define MAX_VOLUME 1.0 0032 0033 #define MAX_QUEUE_SIZE (15 * 1024 * 1024) 0034 #define MIN_FRAMES 25 0035 #define EXTERNAL_CLOCK_MIN_FRAMES 2 0036 #define EXTERNAL_CLOCK_MAX_FRAMES 10 0037 0038 // no AV sync correction is done if below the minimum AV sync threshold 0039 #define AV_SYNC_THRESHOLD_MIN 0.04 0040 // AV sync correction is done if above the maximum AV sync threshold 0041 #define AV_SYNC_THRESHOLD_MAX 0.1 0042 // If a frame duration is longer than this, it will not be duplicated to compensate AV sync 0043 #define AV_SYNC_FRAMEDUP_THRESHOLD 0.1 0044 0045 // external clock speed adjustment constants for realtime sources based on buffer fullness 0046 #define EXTERNAL_CLOCK_SPEED_MIN 0.900 0047 #define EXTERNAL_CLOCK_SPEED_MAX 1.010 0048 #define EXTERNAL_CLOCK_SPEED_STEP 0.001 0049 0050 // polls for possible required screen refresh at least this often, should be less than 1/fps 0051 #define REFRESH_RATE 0.01 0052 0053 #define CURSOR_HIDE_DELAY 1000000 0054 0055 #define USE_ONEPASS_SUBTITLE_RENDER 1 0056 0057 // TODO: support audio and subtitle rendering 0058 #undef AUDIO_VISUALIZATION 0059 #undef VIDEO_SUBTITLE 0060 0061 namespace SubtitleComposer { 0062 class RenderThread; 0063 class GLRenderer; 0064 0065 enum { 0066 AV_SYNC_AUDIO_MASTER, 0067 AV_SYNC_VIDEO_MASTER, 0068 AV_SYNC_EXTERNAL_CLOCK 0069 }; 0070 0071 enum ShowMode { 0072 SHOW_MODE_NONE = -1, 0073 SHOW_MODE_VIDEO = 0, 0074 #ifdef AUDIO_VISUALIZATION 0075 SHOW_MODE_WAVES, 0076 SHOW_MODE_RDFT, 0077 #endif 0078 SHOW_MODE_NB 0079 }; 0080 0081 class VideoState { 0082 friend class FFPlayer; 0083 friend class RenderThread; 0084 friend class AudioDecoder; 0085 friend class VideoDecoder; 0086 friend class SubtitleDecoder; 0087 friend class PacketQueue; 0088 friend class FrameQueue; 0089 friend class StreamDemuxer; 0090 0091 private: 0092 VideoState(); 0093 0094 inline bool streamHasEnoughPackets(AVStream *st, int streamId, PacketQueue *q) { 0095 return streamId < 0 0096 || q->abortRequested() 0097 || (st->disposition & AV_DISPOSITION_ATTACHED_PIC) 0098 || (q->nbPackets() > MIN_FRAMES && (!q->duration() || av_q2d(st->time_base) * q->duration() > 1.0)); 0099 } 0100 0101 inline bool streamsHaveEnoughPackets() { 0102 return audPQ.size() + vidPQ.size() + subPQ.size() > MAX_QUEUE_SIZE 0103 || (streamHasEnoughPackets(audStream, audStreamIdx, &audPQ) 0104 && streamHasEnoughPackets(vidStream, vidStreamIdx, &vidPQ) 0105 && streamHasEnoughPackets(subStream, subStreamIdx, &subPQ)); 0106 } 0107 0108 inline bool reachedEOF() { 0109 return (!audStream || (audDec.finished() == audPQ.serial())) 0110 && (!vidStream || (vidDec.finished() == vidPQ.serial() && vidFQ.nbRemaining() == 0)); 0111 } 0112 0113 inline double position() { 0114 const double pos = masterTime(); 0115 return std::isnan(pos) ? double(seekPos) / AV_TIME_BASE : pos; 0116 } 0117 0118 int masterSyncType(); 0119 Clock * masterClock(); 0120 double masterTime(); 0121 void checkExternalClockSpeed(); 0122 0123 void notifyLoaded(); 0124 void notifySpeed(); 0125 void notifyState(); 0126 0127 private: // settings 0128 int seek_by_bytes = -1; 0129 int av_sync_type = AV_SYNC_AUDIO_MASTER; 0130 int64_t start_time = AV_NOPTS_VALUE; 0131 int fast = 0; 0132 int genpts = 0; 0133 int lowres = 0; 0134 int framedrop = -1; 0135 int infinite_buffer = -1; 0136 double rdftspeed = 0.02; 0137 int autorotate = 1; 0138 0139 private: 0140 bool abortRequested = false; 0141 bool paused = false; 0142 bool lastPaused = false; 0143 int step = 0; 0144 int readPauseReturn = 0; 0145 bool queueAttachmentsReq = false; 0146 bool seekReq = false; 0147 double seekDecoder = 0.; 0148 int seekFlags = 0; 0149 int64_t seekPos = 0; 0150 AVFormatContext *fmtContext = nullptr; 0151 bool realTime = false; 0152 0153 FFPlayer *player = nullptr; 0154 StreamDemuxer *demuxer = nullptr; 0155 GLRenderer *glRenderer = nullptr; 0156 RenderThread *renderThread = nullptr; 0157 0158 ShowMode showMode = SHOW_MODE_NONE; 0159 bool forceRefresh = true; 0160 0161 Clock audClk; 0162 AudioDecoder audDec; 0163 int audStreamIdx = -1; 0164 AVStream *audStream = nullptr; 0165 PacketQueue audPQ; 0166 int frameDropsLate = 0; 0167 0168 #ifdef AUDIO_VISUALIZATION 0169 QVector<int16_t> sample_array; 0170 int sample_array_index = 0; 0171 int last_i_start = 0; 0172 RDFTContext *rdft = nullptr; 0173 int rdft_bits = 0; 0174 FFTSample *rdft_data = nullptr; 0175 double last_vis_time = 0.; 0176 #endif 0177 0178 Clock extClk; 0179 0180 SubtitleDecoder subDec; 0181 int subStreamIdx = -1; 0182 AVStream *subStream = nullptr; 0183 PacketQueue subPQ; 0184 FrameQueue subFQ; 0185 #ifdef VIDEO_SUBTITLE 0186 SwsContext *subConvertCtx = nullptr; 0187 #endif 0188 0189 Clock vidClk; 0190 VideoDecoder vidDec; 0191 double frameTimer = 0.; 0192 double frameLastReturnedTime = 0.; 0193 int vidStreamIdx = -1; 0194 AVStream *vidStream = nullptr; 0195 PacketQueue vidPQ; 0196 FrameQueue vidFQ; 0197 double maxFrameDuration = 0.; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity 0198 bool eof = false; 0199 0200 QString filename; 0201 0202 int lastVideoStream = -1; 0203 int lastAudioStream = -1; 0204 int lastSubtitleStream = -1; 0205 0206 QWaitCondition *continueReadThread = nullptr; 0207 }; 0208 } 0209 0210 #endif // VIDEOSTATE_H