1 /* 2 SPDX-FileCopyrightText: 2003 Fabrice Bellard 3 SPDX-FileCopyrightText: 2020 Mladen Milinkovic <max@smoothware.net> 4 5 SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 8 #ifndef VIDEOSTATE_H 9 #define VIDEOSTATE_H 10 11 #include <cmath> 12 13 #include "videoplayer/backend/videodecoder.h" 14 #include "videoplayer/backend/audiodecoder.h" 15 #include "videoplayer/backend/subtitledecoder.h" 16 #include "videoplayer/backend/framequeue.h" 17 #include "videoplayer/backend/packetqueue.h" 18 #include "videoplayer/backend/streamdemuxer.h" 19 #include "videoplayer/backend/clock.h" 20 21 #include <QString> 22 #include <QWaitCondition> 23 24 extern "C" { 25 #include "libavformat/avformat.h" 26 #include "libavcodec/avfft.h" 27 } 28 29 30 #define MAX_VOLUME 1.0 31 32 #define MAX_QUEUE_SIZE (15 * 1024 * 1024) 33 #define MIN_FRAMES 25 34 #define EXTERNAL_CLOCK_MIN_FRAMES 2 35 #define EXTERNAL_CLOCK_MAX_FRAMES 10 36 37 // no AV sync correction is done if below the minimum AV sync threshold 38 #define AV_SYNC_THRESHOLD_MIN 0.04 39 // AV sync correction is done if above the maximum AV sync threshold 40 #define AV_SYNC_THRESHOLD_MAX 0.1 41 // If a frame duration is longer than this, it will not be duplicated to compensate AV sync 42 #define AV_SYNC_FRAMEDUP_THRESHOLD 0.1 43 44 // external clock speed adjustment constants for realtime sources based on buffer fullness 45 #define EXTERNAL_CLOCK_SPEED_MIN 0.900 46 #define EXTERNAL_CLOCK_SPEED_MAX 1.010 47 #define EXTERNAL_CLOCK_SPEED_STEP 0.001 48 49 // polls for possible required screen refresh at least this often, should be less than 1/fps 50 #define REFRESH_RATE 0.01 51 52 #define CURSOR_HIDE_DELAY 1000000 53 54 #define USE_ONEPASS_SUBTITLE_RENDER 1 55 56 // TODO: support audio and subtitle rendering 57 #undef AUDIO_VISUALIZATION 58 #undef VIDEO_SUBTITLE 59 60 namespace SubtitleComposer { 61 class RenderThread; 62 class GLRenderer; 63 64 enum { 65 AV_SYNC_AUDIO_MASTER, 66 AV_SYNC_VIDEO_MASTER, 67 AV_SYNC_EXTERNAL_CLOCK 68 }; 69 70 enum ShowMode { 71 SHOW_MODE_NONE = -1, 72 SHOW_MODE_VIDEO = 0, 73 #ifdef AUDIO_VISUALIZATION 74 SHOW_MODE_WAVES, 75 SHOW_MODE_RDFT, 76 #endif 77 SHOW_MODE_NB 78 }; 79 80 class VideoState { 81 friend class FFPlayer; 82 friend class RenderThread; 83 friend class AudioDecoder; 84 friend class VideoDecoder; 85 friend class SubtitleDecoder; 86 friend class PacketQueue; 87 friend class FrameQueue; 88 friend class StreamDemuxer; 89 90 private: 91 VideoState(); 92 streamHasEnoughPackets(AVStream * st,int streamId,PacketQueue * q)93 inline bool streamHasEnoughPackets(AVStream *st, int streamId, PacketQueue *q) { 94 return streamId < 0 95 || q->abortRequested() 96 || (st->disposition & AV_DISPOSITION_ATTACHED_PIC) 97 || (q->nbPackets() > MIN_FRAMES && (!q->duration() || av_q2d(st->time_base) * q->duration() > 1.0)); 98 } 99 streamsHaveEnoughPackets()100 inline bool streamsHaveEnoughPackets() { 101 return audPQ.size() + vidPQ.size() + subPQ.size() > MAX_QUEUE_SIZE 102 || (streamHasEnoughPackets(audStream, audStreamIdx, &audPQ) 103 && streamHasEnoughPackets(vidStream, vidStreamIdx, &vidPQ) 104 && streamHasEnoughPackets(subStream, subStreamIdx, &subPQ)); 105 } 106 reachedEOF()107 inline bool reachedEOF() { 108 return (!audStream || (audDec.finished() == audPQ.serial())) 109 && (!vidStream || (vidDec.finished() == vidPQ.serial() && vidFQ.nbRemaining() == 0)); 110 } 111 position()112 inline double position() { 113 const double pos = masterTime(); 114 return std::isnan(pos) ? double(seekPos) / AV_TIME_BASE : pos; 115 } 116 117 int masterSyncType(); 118 Clock * masterClock(); 119 double masterTime(); 120 void checkExternalClockSpeed(); 121 122 void notifyLoaded(); 123 void notifySpeed(); 124 void notifyState(); 125 126 private: // settings 127 int seek_by_bytes = -1; 128 int av_sync_type = AV_SYNC_AUDIO_MASTER; 129 int64_t start_time = AV_NOPTS_VALUE; 130 int fast = 0; 131 int genpts = 0; 132 int lowres = 0; 133 int framedrop = -1; 134 int infinite_buffer = -1; 135 double rdftspeed = 0.02; 136 int autorotate = 1; 137 138 private: 139 bool abortRequested = false; 140 bool paused = false; 141 bool lastPaused = false; 142 int step = 0; 143 int readPauseReturn = 0; 144 bool queueAttachmentsReq = false; 145 bool seekReq = false; 146 double seekDecoder = 0.; 147 int seekFlags = 0; 148 int64_t seekPos = 0; 149 AVFormatContext *fmtContext = nullptr; 150 bool realTime = false; 151 152 FFPlayer *player = nullptr; 153 StreamDemuxer *demuxer = nullptr; 154 GLRenderer *glRenderer = nullptr; 155 RenderThread *renderThread = nullptr; 156 157 ShowMode showMode = SHOW_MODE_NONE; 158 bool forceRefresh = true; 159 160 Clock audClk; 161 AudioDecoder audDec; 162 int audStreamIdx = -1; 163 AVStream *audStream = nullptr; 164 PacketQueue audPQ; 165 int frameDropsLate = 0; 166 167 #ifdef AUDIO_VISUALIZATION 168 QVector<int16_t> sample_array; 169 int sample_array_index = 0; 170 int last_i_start = 0; 171 RDFTContext *rdft = nullptr; 172 int rdft_bits = 0; 173 FFTSample *rdft_data = nullptr; 174 double last_vis_time = 0.; 175 #endif 176 177 Clock extClk; 178 179 SubtitleDecoder subDec; 180 int subStreamIdx = -1; 181 AVStream *subStream = nullptr; 182 PacketQueue subPQ; 183 FrameQueue subFQ; 184 #ifdef VIDEO_SUBTITLE 185 SwsContext *subConvertCtx = nullptr; 186 #endif 187 188 Clock vidClk; 189 VideoDecoder vidDec; 190 double frameTimer = 0.; 191 double frameLastReturnedTime = 0.; 192 int vidStreamIdx = -1; 193 AVStream *vidStream = nullptr; 194 PacketQueue vidPQ; 195 FrameQueue vidFQ; 196 double maxFrameDuration = 0.; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity 197 bool eof = false; 198 199 QString filename; 200 201 int lastVideoStream = -1; 202 int lastAudioStream = -1; 203 int lastSubtitleStream = -1; 204 205 QWaitCondition *continueReadThread = nullptr; 206 }; 207 } 208 209 #endif // VIDEOSTATE_H 210