forked from UnigramDev/Unigram
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathVideoAnimation.h
More file actions
192 lines (159 loc) · 5.02 KB
/
Copy pathVideoAnimation.h
File metadata and controls
192 lines (159 loc) · 5.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#pragma once
#include <VideoAnimation.g.h>
#include <cstdint>
#include <limits>
#include <string>
#include <fcntl.h>
#include <libyuv.h>
extern "C"
{
#include <libavformat/avformat.h>
#include <libavutil/eval.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
static const std::string av_make_error_str(int errnum)
{
char errbuf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
return (std::string)errbuf;
}
#undef av_err2str
#define av_err2str(errnum) av_make_error_str(errnum).c_str()
#define FFMPEG_AVSEEK_SIZE 0x10000
using namespace winrt::Windows::Storage::Streams;
namespace winrt::Telegram::Native::implementation
{
enum PARAM_NUM
{
PARAM_NUM_SUPPORTED_VIDEO_CODEC = 0,
PARAM_NUM_WIDTH = 1,
PARAM_NUM_HEIGHT = 2,
PARAM_NUM_BITRATE = 3,
PARAM_NUM_DURATION = 4,
PARAM_NUM_AUDIO_FRAME_SIZE = 5,
PARAM_NUM_VIDEO_FRAME_SIZE = 6,
PARAM_NUM_FRAMERATE = 7,
PARAM_NUM_ROTATION = 8,
PARAM_NUM_SUPPORTED_AUDIO_CODEC = 9,
PARAM_NUM_HAS_AUDIO = 10,
PARAM_NUM_COUNT = 11,
};
struct VideoAnimation : VideoAnimationT<VideoAnimation>
{
public:
virtual ~VideoAnimation()
{
Close();
}
void Close()
{
if (video_dec_ctx)
{
avcodec_close(video_dec_ctx);
video_dec_ctx = nullptr;
}
if (fmt_ctx)
{
avformat_close_input(&fmt_ctx);
fmt_ctx = nullptr;
}
if (frame)
{
av_frame_free(&frame);
frame = nullptr;
}
if (ioContext != nullptr)
{
if (ioContext->buffer)
{
av_freep(&ioContext->buffer);
}
avio_context_free(&ioContext);
ioContext = nullptr;
}
if (sws_ctx != nullptr)
{
sws_freeContext(sws_ctx);
sws_ctx = nullptr;
}
if (fd != INVALID_HANDLE_VALUE)
{
CloseHandle(fd);
fd = INVALID_HANDLE_VALUE;
//close(fd);
//fd = -1;
}
av_packet_unref(&orig_pkt);
video_stream_idx = -1;
video_stream = nullptr;
audio_stream = nullptr;
}
static winrt::Telegram::Native::VideoAnimation LoadFromFile(IVideoAnimationSource file, bool preview, bool limitFps);
VideoAnimation() = default;
void Stop();
void PrepareToSeek();
void SeekToMilliseconds(int64_t ms, bool precise);
int RenderSync(IBuffer buffer, int32_t width, int32_t height, bool preview, int32_t& seconds);
int RenderSync(uint8_t* pixels, int32_t width, int32_t height, bool preview, int32_t& seconds, bool& completed);
int PixelWidth()
{
return pixelWidth;
}
int PixelHeight()
{
return pixelHeight;
}
double FrameRate()
{
return framerate;
}
int Duration()
{
return duration;
}
private:
int decode_packet(VideoAnimation* info, int* got_frame);
static void requestFd(VideoAnimation* info);
static int readCallback(void* opaque, uint8_t* buf, int buf_size);
static int64_t seekCallback(void* opaque, int64_t offset, int whence);
static void RedirectLoggingOutputs(void* ptr, int level, const char* fmt, va_list vargs);
winrt::slim_mutex m_lock;
AVFormatContext* fmt_ctx = nullptr;
IVideoAnimationSource file{ nullptr };
HANDLE fileEvent = INVALID_HANDLE_VALUE;
int video_stream_idx = -1;
AVStream* video_stream = nullptr;
AVStream* audio_stream = nullptr;
AVCodecContext* video_dec_ctx = nullptr;
AVFrame* frame = nullptr;
bool has_decoded_frames = false;
AVPacket pkt;
AVPacket orig_pkt;
bool stopped = false;
bool seeking = false;
uint8_t* dst_data[1];
int32_t dst_linesize[1];
struct SwsContext* sws_ctx = nullptr;
AVIOContext* ioContext = nullptr;
unsigned char* ioBuffer = nullptr;
HANDLE fd = INVALID_HANDLE_VALUE;
//int64_t last_seek_p = 0;
bool limitFps;
const int64_t limitedDuration = 1000 / 30;
int64_t prevFrame = 0;
int64_t prevDuration = 0;
int64_t nextFrame = 0;
int32_t pixelWidth = 0;
int32_t pixelHeight = 0;
int32_t rotation = 0;
int32_t duration = 0;
double framerate = 0;
};
} // namespace winrt::Telegram::Native::implementation
namespace winrt::Telegram::Native::factory_implementation
{
struct VideoAnimation : VideoAnimationT<VideoAnimation, implementation::VideoAnimation>
{
};
} // namespace winrt::Telegram::Native::factory_implementation