"Fossies" - the Fresh Open Source Software Archive

Member "tdesktop-2.6.1/Telegram/SourceFiles/media/clip/media_clip_reader.h" (24 Feb 2021, 6544 Bytes) of package /linux/misc/tdesktop-2.6.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "media_clip_reader.h" see the Fossies "Dox" file reference documentation.

    1 /*
    2 This file is part of Telegram Desktop,
    3 the official desktop application for the Telegram messaging service.
    4 
    5 For license and copyright information please follow this link:
    6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
    7 */
    8 #pragma once
    9 
   10 #include "ui/chat/attach/attach_prepare.h"
   11 #include "ui/image/image_prepare.h"
   12 
   13 #include <QtCore/QTimer>
   14 #include <QtCore/QMutex>
   15 
   16 namespace Core {
   17 class FileLocation;
   18 } // namespace Core
   19 
   20 namespace Media {
   21 namespace Clip {
   22 
   23 enum class State {
   24     Reading,
   25     Error,
   26     Finished,
   27 };
   28 
   29 struct FrameRequest {
   30     bool valid() const {
   31         return factor > 0;
   32     }
   33     int factor = 0;
   34     int framew = 0;
   35     int frameh = 0;
   36     int outerw = 0;
   37     int outerh = 0;
   38     ImageRoundRadius radius = ImageRoundRadius::None;
   39     RectParts corners = RectPart::AllCorners;
   40 };
   41 
   42 enum ReaderSteps : int {
   43     WaitingForDimensionsStep = -3, // before ReaderPrivate read the first image and got the original frame size
   44     WaitingForRequestStep = -2, // before Reader got the original frame size and prepared the frame request
   45     WaitingForFirstFrameStep = -1, // before ReaderPrivate got the frame request and started waiting for the 1-2 delay
   46 };
   47 
   48 enum Notification : int {
   49     NotificationReinit,
   50     NotificationRepaint,
   51 };
   52 
   53 class ReaderPrivate;
   54 class Reader {
   55 public:
   56     using Callback = Fn<void(Notification)>;
   57     enum class Mode {
   58         Gif,
   59         Video,
   60     };
   61 
   62     Reader(const Core::FileLocation &location, const QByteArray &data, Callback &&callback);
   63     Reader(const QString &filepath, Callback &&callback);
   64     Reader(const QByteArray &data, Callback &&callback);
   65 
   66     // Reader can be already deleted.
   67     static void callback(Reader *reader, qint32 threadIndex, qint32 notification);
   68 
   69     void start(int framew, int frameh, int outerw, int outerh, ImageRoundRadius radius, RectParts corners);
   70     QPixmap current(int framew, int frameh, int outerw, int outerh, ImageRoundRadius radius, RectParts corners, crl::time ms);
   71     QPixmap frameOriginal() const {
   72         if (auto frame = frameToShow()) {
   73             auto result = QPixmap::fromImage(frame->original);
   74             result.detach();
   75             return result;
   76         }
   77         return QPixmap();
   78     }
   79     bool currentDisplayed() const {
   80         auto frame = frameToShow();
   81         return frame ? (frame->displayed.loadAcquire() != 0) : true;
   82     }
   83     bool autoPausedGif() const {
   84         return _autoPausedGif.loadAcquire();
   85     }
   86     bool videoPaused() const;
   87     int threadIndex() const {
   88         return _threadIndex;
   89     }
   90 
   91     int width() const;
   92     int height() const;
   93 
   94     State state() const;
   95     bool started() const {
   96         auto step = _step.loadAcquire();
   97         return (step == WaitingForFirstFrameStep) || (step >= 0);
   98     }
   99     bool ready() const;
  100 
  101     crl::time getPositionMs() const;
  102     crl::time getDurationMs() const;
  103     void pauseResumeVideo();
  104 
  105     void stop();
  106     void error();
  107     void finished();
  108 
  109     ~Reader();
  110 
  111 private:
  112     void init(const Core::FileLocation &location, const QByteArray &data);
  113 
  114     Callback _callback;
  115     State _state = State::Reading;
  116 
  117     crl::time _durationMs = 0;
  118 
  119     mutable int _width = 0;
  120     mutable int _height = 0;
  121 
  122     // -2, -1 - init, 0-5 - work, show ((state + 1) / 2) % 3 state, write ((state + 3) / 2) % 3
  123     mutable QAtomicInt _step = WaitingForDimensionsStep;
  124     struct Frame {
  125         void clear() {
  126             pix = QPixmap();
  127             original = QImage();
  128         }
  129         QPixmap pix;
  130         QImage original;
  131         FrameRequest request;
  132         QAtomicInt displayed = 0;
  133 
  134         // Should be counted from the end,
  135         // so that positionMs <= _durationMs.
  136         crl::time positionMs = 0;
  137     };
  138     mutable Frame _frames[3];
  139     Frame *frameToShow(int *index = nullptr) const; // 0 means not ready
  140     Frame *frameToWrite(int *index = nullptr) const; // 0 means not ready
  141     Frame *frameToWriteNext(bool check, int *index = nullptr) const;
  142     void moveToNextShow() const;
  143     void moveToNextWrite() const;
  144 
  145     QAtomicInt _autoPausedGif = 0;
  146     QAtomicInt _videoPauseRequest = 0;
  147     int32 _threadIndex;
  148 
  149     friend class Manager;
  150 
  151     ReaderPrivate *_private = nullptr;
  152 
  153 };
  154 
  155 class ReaderPointer {
  156 public:
  157     ReaderPointer(std::nullptr_t = nullptr) {
  158     }
  159     explicit ReaderPointer(Reader *pointer) : _pointer(pointer) {
  160     }
  161     ReaderPointer(const ReaderPointer &other) = delete;
  162     ReaderPointer &operator=(const ReaderPointer &other) = delete;
  163     ReaderPointer(ReaderPointer &&other) : _pointer(base::take(other._pointer)) {
  164     }
  165     ReaderPointer &operator=(ReaderPointer &&other) {
  166         swap(other);
  167         return *this;
  168     }
  169     void swap(ReaderPointer &other) {
  170         qSwap(_pointer, other._pointer);
  171     }
  172     Reader *get() const {
  173         return valid() ? _pointer : nullptr;
  174     }
  175     Reader *operator->() const {
  176         return get();
  177     }
  178     void setBad() {
  179         reset();
  180         _pointer = BadPointer;
  181     }
  182     void reset() {
  183         ReaderPointer temp;
  184         swap(temp);
  185     }
  186     bool isBad() const {
  187         return (_pointer == BadPointer);
  188     }
  189     bool valid() const {
  190         return _pointer && !isBad();
  191     }
  192     explicit operator bool() const {
  193         return valid();
  194     }
  195     static inline ReaderPointer Bad() {
  196         ReaderPointer result;
  197         result.setBad();
  198         return result;
  199     }
  200     ~ReaderPointer();
  201 
  202 private:
  203     Reader *_pointer = nullptr;
  204     static Reader *const BadPointer;
  205 
  206 };
  207 
  208 template <typename ...Args>
  209 inline ReaderPointer MakeReader(Args&&... args) {
  210     return ReaderPointer(new Reader(std::forward<Args>(args)...));
  211 }
  212 
  213 enum class ProcessResult {
  214     Error,
  215     Started,
  216     Finished,
  217     Paused,
  218     Repaint,
  219     CopyFrame,
  220     Wait,
  221 };
  222 
  223 class Manager : public QObject {
  224 public:
  225     explicit Manager(QThread *thread);
  226     ~Manager();
  227 
  228     int loadLevel() const {
  229         return _loadLevel;
  230     }
  231     void append(Reader *reader, const Core::FileLocation &location, const QByteArray &data);
  232     void start(Reader *reader);
  233     void update(Reader *reader);
  234     void stop(Reader *reader);
  235     bool carries(Reader *reader) const;
  236 
  237 private:
  238     void process();
  239     void finish();
  240     void callback(Reader *reader, Notification notification);
  241     void clear();
  242 
  243     QAtomicInt _loadLevel;
  244     using ReaderPointers = QMap<Reader*, QAtomicInt>;
  245     ReaderPointers _readerPointers;
  246     mutable QMutex _readerPointersMutex;
  247 
  248     ReaderPointers::const_iterator constUnsafeFindReaderPointer(ReaderPrivate *reader) const;
  249     ReaderPointers::iterator unsafeFindReaderPointer(ReaderPrivate *reader);
  250 
  251     bool handleProcessResult(ReaderPrivate *reader, ProcessResult result, crl::time ms);
  252 
  253     enum ResultHandleState {
  254         ResultHandleRemove,
  255         ResultHandleStop,
  256         ResultHandleContinue,
  257     };
  258     ResultHandleState handleResult(ReaderPrivate *reader, ProcessResult result, crl::time ms);
  259 
  260     using Readers = QMap<ReaderPrivate*, crl::time>;
  261     Readers _readers;
  262 
  263     QTimer _timer;
  264     QThread *_processingInThread = nullptr;
  265     bool _needReProcess = false;
  266 
  267 };
  268 
  269 [[nodiscard]] Ui::PreparedFileInformation::Video PrepareForSending(
  270     const QString &fname,
  271     const QByteArray &data);
  272 
  273 void Finish();
  274 
  275 } // namespace Clip
  276 } // namespace Media