-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathffmpegwrapper.h
217 lines (188 loc) · 8.58 KB
/
ffmpegwrapper.h
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/**************************************************************************************************************************************************************
ffmpegwrapper.h
Copyright © 2023 Maksim Kryukov <fagear@mail.ru>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Created: 2022-10
Signal-based Qt-wrapper for FFMPEG library.
[FFMPEGWrapper] performs:
- Capture device listing (in development);
- Opening and decoding video sources through FFMPEG library;
- Dropped frames detection;
- Output of monochrome video frames.
Typical use case:
- Connect to [sigInputReady()], [sigInputClosed()], [sigVideoError()] signals for source state tracking;
- Connect [newImage()] signal to the frame receiver;
- Call [slotOpenInput()] to open provided source;
- Call [slotGetNextFrame()] for each next video frame.
**************************************************************************************************************************************************************/
#ifndef FFMPEGWRAPPER_H
#define FFMPEGWRAPPER_H
#include <stdint.h>
#include <string>
#include <QDebug>
#include <QImage>
#include <QObject>
#include <QThread>
#include <QString>
#include "config.h"
#include "vid_preset_t.h"
#define FFWR_WIN_GDI_NAME (QObject::tr("Захват экрана Windows GDI"))
#define FFWR_WIN_GDI_CLASS "gdigrab"
#define FFWR_WIN_GDI_CAP "desktop"
#define FFWR_WIN_DSHOW_NAME (QObject::tr("Захват экрана Windows DirectShow"))
#define FFWR_WIN_DSHOW_CLASS "dshow"
#define FFWR_WIN_DSHOW_CAP "screen-capture-recorder"
#define FFWR_LIN_X11_CLASS "x11grab"
#define FFWRL_MAC_AVF_CLASS "avfoundation"
//------------------------ Video capture device descriptor.
class VCapDevice
{
public:
std::string dev_name; // Device name for the user
std::string dev_class; // Device class (gdigrab, dshow, etc.)
std::string dev_path; // Device path in OS for [avformat_open_input()]
public:
VCapDevice();
VCapDevice(const VCapDevice &in_object);
VCapDevice& operator= (const VCapDevice &in_object);
void clear();
};
//------------------------ Video capture devices list.
class VCapList
{
public:
std::vector<VCapDevice> dev_list;
public:
VCapList();
VCapList(const VCapList &in_object);
VCapList& operator= (const VCapList &in_object);
void clear();
};
//------------------------ Qt-wrapper for FFMPEG for capturing video.
class FFMPEGWrapper : public QObject
{
Q_OBJECT
public:
// Error codes for [sigVideoError()].
enum
{
FFMERR_OK, // No error.
FFMERR_EOF, // Last frame reached.
FFMERR_NOT_INIT, // Source was not opened before reading a frame.
FFMERR_NO_SRC, // Failed to open source with set parameters.
FFMERR_NO_INFO, // Failed to read any stream info.
FFMERR_NO_VIDEO, // Failed to find video stream in the source.
FFMERR_NO_DECODER, // Failed to find decoder for video stream.
FFMERR_NO_RAM_DEC, // Failed to allocate RAM for video decoder.
FFMERR_DECODER_PARAM, // Failed apply decoder parameters.
FFMERR_DECODER_START, // Failed to start video decoder.
FFMERR_NO_RAM_FB, // Failed to allocate RAM for frame buffer.
FFMERR_NO_RAM_READ, // Failed to read a packet from a decoder.
FFMERR_DECODER_NR, // Decoder was not ready for the packet.
FFMERR_DECODER_REP, // Not all frames were picked up from decoder.
FFMERR_CONV_INIT, // Failed to setup frame converter.
FFMERR_FRM_CONV, // Failed to convert to final frame.
FFMERR_UNKNOWN // Some unknown error.
};
// Default capture dimensions.
enum
{
DEF_CAP_WIDTH = 640,
DEF_CAP_HEIGHT = 480
};
// Resolution for dummy frame.
enum
{
DUMMY_CNT_MAX = 1024,
DUMMY_HEIGTH = 8
};
// Limits for enabling double width resise.
enum
{
MIN_DBL_WIDTH = 10,
MAX_DBL_WIDTH = 959
};
// Limit for cropping excess lines.
enum
{
MAX_LINES_PER_FRAME = LINES_PER_FRAME_MAX
};
// Final frame buffer pixel format.
enum
{
BUF_FMT_BW = AV_PIX_FMT_YUV420P,// Normal BW Y-decoded buffer.
BUF_FMT_COLOR = AV_PIX_FMT_GBRP // Per channel GBR-decoded buffer.
};
// Color plane IDs.
enum
{
PLANE_Y = 0, // Plane for Y level with AV_PIX_FMT_YUV420P pixel format.
PLANE_G = 0, // Plane for GREEN color with AV_PIX_FMT_GBRP pixel format.
PLANE_B = 1, // Plane for BLUE color with AV_PIX_FMT_GBRP pixel format.
PLANE_R = 2 // Plane for RED color with AV_PIX_FMT_GBRP pixel format.
};
private:
AVFormatContext *format_ctx; // Context for FFMPEG format.
const AVCodec *v_decoder; // Codec structure.
int stream_index; // Current open video stream index.
AVCodecContext *video_dec_ctx; // Context for FFMPEG decoder.
AVFrame *dec_frame; // Frame holder for FFMPEG decoded frame.
AVPacket dec_packet; // Packet container for FFMPEG decoder.
uint8_t *video_dst_data[4]; // Container for frame data from the decoder.
int video_dst_linesize[4]; // Container for frame parameters from the decoder.
SwsContext *conv_ctx; // Context for FFMPEG frame converter.
bool img_buf_free; // Final frame buffer was not allocated.
bool source_open; // Source is open.
AVPixelFormat last_frame_fmt; // Last frame format.
AVPixelFormat target_pixfmt; // Pixel format for final frame (set in [initFrameConverter()]).
uint32_t frame_count; // Number of processed frames after a source was opened.
bool file_capture; // Is source selected as file?
bool detect_drops; // Detect droped frames via DTS.
bool dts_detected; // Was DTS from new source already detected?
int64_t last_dts; // Last frame DTS (for drop detection).
bool last_double; // Last frame width was doubled.
int last_width; // Last frame width.
int last_height; // Last frame height.
uint8_t last_color_mode; // Last color mode (see [vid_preset_t.h]).
vid_preset_t crop_n_color; // Preset crop and color mode settings.
uint16_t set_width; // Preset width of source for capture (0 = disabled).
uint16_t set_height; // Preset height of source for capture (0 = disabled).
uint16_t set_x_ofs; // Preset x offset from left side (0 = disabled).
uint16_t set_y_ofs; // Preset y offset from top side (0 = disabled).
uint8_t set_fps; // Preset framerate of source (0 = disabled).
public:
explicit FFMPEGWrapper(QObject *parent = 0);
private:
bool getNextPacket();
bool needsDoubleWidth(int in_width);
int getFinalWidth(int in_width);
bool initFrameConverter(AVFrame *new_frame, uint16_t new_width, uint16_t new_height, uint8_t new_colors);
bool keepFrameInCheck(AVFrame *new_frame);
void freeFrameConverter();
public slots:
void slotLogStart();
void slotGetDeviceList();
void slotSetResize(uint16_t in_width = 0, uint16_t in_height = 0);
void slotSetTLOffset(uint16_t in_x = 0, uint16_t in_y = 0);
void slotSetFPS(uint8_t in_fps = 0);
void slotSetCropColor(vid_preset_t in_preset);
void slotSetDropDetector(bool in_drops);
void slotOpenInput(QString path, QString class_type = "");
void slotGetNextFrame();
void slotCloseInput();
signals:
void sigInputReady(int, int, uint32_t, float);
void sigInputClosed();
void sigVideoError(uint32_t);
void newDeviceList(VCapList);
void newImage(QImage, bool);
};
#endif // FFMPEGWRAPPER_H