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