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 "media/clip/media_clip_implementation.h" 11 #include "ffmpeg/ffmpeg_utility.h" 12 13 extern "C" { 14 #include <libswscale/swscale.h> 15 #include <libavutil/opt.h> 16 } // extern "C" 17 #include <deque> 18 19 //#include "media/streaming/media_streaming_utility.h" 20 21 namespace Media { 22 namespace Clip { 23 namespace internal { 24 25 constexpr auto kMaxInMemory = 10 * 1024 * 1024; 26 27 class FFMpegReaderImplementation : public ReaderImplementation { 28 public: 29 FFMpegReaderImplementation(Core::FileLocation *location, QByteArray *data); 30 31 ReadResult readFramesTill(crl::time frameMs, crl::time systemMs) override; 32 33 crl::time frameRealTime() const override; 34 crl::time framePresentationTime() const override; 35 36 bool renderFrame(QImage &to, bool &hasAlpha, const QSize &size) override; 37 38 crl::time durationMs() const override; 39 40 bool start(Mode mode, crl::time &positionMs) override; 41 bool inspectAt(crl::time &positionMs); 42 43 QString logData() const; 44 45 bool isGifv() const; 46 47 ~FFMpegReaderImplementation(); 48 49 private: 50 ReadResult readNextFrame(); 51 void processReadFrame(); 52 53 enum class PacketResult { 54 Ok, 55 EndOfFile, 56 Error, 57 }; 58 PacketResult readPacket(FFmpeg::Packet &packet); 59 void processPacket(FFmpeg::Packet &&packet); 60 crl::time countPacketMs(const FFmpeg::Packet &packet) const; 61 PacketResult readAndProcessPacket(); 62 63 enum class Rotation { 64 None, 65 Degrees90, 66 Degrees180, 67 Degrees270, 68 }; 69 Rotation rotationFromDegrees(int degrees) const; rotationSwapWidthHeight()70 bool rotationSwapWidthHeight() const { 71 return (_rotation == Rotation::Degrees90) || (_rotation == Rotation::Degrees270); 72 } 73 74 static int _read(void *opaque, uint8_t *buf, int buf_size); 75 static int64_t _seek(void *opaque, int64_t offset, int whence); 76 77 Mode _mode = Mode::Silent; 78 79 Rotation _rotation = Rotation::None; 80 81 uchar *_ioBuffer = nullptr; 82 AVIOContext *_ioContext = nullptr; 83 AVFormatContext *_fmtContext = nullptr; 84 AVCodecContext *_codecContext = nullptr; 85 int _streamId = 0; 86 FFmpeg::FramePointer _frame; 87 bool _opened = false; 88 bool _hadFrame = false; 89 bool _frameRead = false; 90 int _skippedInvalidDataPackets = 0; 91 92 bool _hasAudioStream = false; 93 crl::time _lastReadVideoMs = 0; 94 crl::time _lastReadAudioMs = 0; 95 96 std::deque<FFmpeg::Packet> _packetQueue; 97 98 int _width = 0; 99 int _height = 0; 100 SwsContext *_swsContext = nullptr; 101 QSize _swsSize; 102 103 crl::time _frameMs = 0; 104 int _nextFrameDelay = 0; 105 int _currentFrameDelay = 0; 106 107 crl::time _frameTime = 0; 108 crl::time _frameTimeCorrection = 0; 109 110 }; 111 112 } // namespace internal 113 } // namespace Clip 114 } // namespace Media 115