MythTV  master
mythframe.h
Go to the documentation of this file.
1 #ifndef _FRAME_H
2 #define _FRAME_H
3 
4 #ifdef __cplusplus
5 #include <cstdint>
6 #include <cstring>
7 #else
8 #include <stdint.h>
9 #include <string.h>
10 #endif
11 #include "mythtvexp.h" // for MTV_PUBLIC
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 typedef enum FrameType_
18 {
19  FMT_NONE = -1,
20  FMT_RGB24 = 0,
35 
36 typedef struct VideoFrame_
37 {
39  unsigned char *buf;
40 
41  int width;
42  int height;
43  float aspect;
44  double frame_rate;
45  int bpp;
46  int size;
47 
48  long long frameNumber;
49  long long timecode;
50  int64_t disp_timecode;
51 
52  unsigned char *priv[4];
53 
54  unsigned char *qscale_table;
55  int qstride;
56 
60  int forcekey;
61  int dummy;
62 
63  int pitches[3];
64  int offsets[3];
65 
66  int pix_fmt;
68 } VideoFrame;
69 
70 #ifdef __cplusplus
71 }
72 #endif
73 
74 #ifdef __cplusplus
75 
76 enum class uswcState {
77  Detect,
78  Use_SSE,
79  Use_SW
80 };
81 
83 {
84 public:
85  MythUSWCCopy(int width, bool nocache = false);
86  virtual ~MythUSWCCopy();
87 
88  void copy(VideoFrame *dst, const VideoFrame *src);
89  void reset(int width);
90  void resetUSWCDetection(void);
91  void setUSWC(bool uswc);
92 
93 private:
94  void allocateCache(int width);
95 
96  uint8_t* m_cache {nullptr};
97  int m_size {0};
99 };
100 
101 void MTV_PUBLIC framecopy(VideoFrame *dst, const VideoFrame *src,
102  bool useSSE = true);
103 
104 static inline void init(VideoFrame *vf, VideoFrameType _codec,
105  unsigned char *_buf, int _width, int _height, int _size,
106  const int *p = nullptr,
107  const int *o = nullptr,
108  float _aspect = -1.0F, double _rate = -1.0F,
109  int _aligned = 64);
110 static inline void clear(VideoFrame *vf);
111 static inline bool compatible(const VideoFrame *a,
112  const VideoFrame *b);
113 static inline int bitsperpixel(VideoFrameType type);
114 
115 static inline void init(VideoFrame *vf, VideoFrameType _codec,
116  unsigned char *_buf, int _width, int _height,
117  int _size, const int *p, const int *o,
118  float _aspect, double _rate, int _aligned)
119 {
120  vf->bpp = bitsperpixel(_codec);
121  vf->codec = _codec;
122  vf->buf = _buf;
123  vf->width = _width;
124  vf->height = _height;
125  vf->aspect = _aspect;
126  vf->frame_rate = _rate;
127 
128  vf->size = _size;
129  vf->frameNumber = 0;
130  vf->timecode = 0;
131 
132  vf->qscale_table = nullptr;
133  vf->qstride = 0;
134 
135  vf->interlaced_frame = 1;
136  vf->top_field_first = 1;
137  vf->repeat_pict = 0;
138  vf->forcekey = 0;
139  vf->dummy = 0;
140  vf->pix_fmt = 0;
141  vf->directrendering = 1;
142 
143  memset(vf->priv, 0, 4 * sizeof(unsigned char *));
144 
145  uint width_aligned;
146  if (!_aligned)
147  {
148  width_aligned = _width;
149  }
150  else
151  {
152  width_aligned = (_width + _aligned - 1) & ~(_aligned - 1);
153  }
154 
155  if (p)
156  {
157  memcpy(vf->pitches, p, 3 * sizeof(int));
158  }
159  else
160  {
161  if (FMT_YV12 == _codec || FMT_YUV422P == _codec)
162  {
163  vf->pitches[0] = width_aligned;
164  vf->pitches[1] = vf->pitches[2] = (width_aligned+1) >> 1;
165  }
166  else if (FMT_NV12 == _codec)
167  {
168  vf->pitches[0] = width_aligned;
169  vf->pitches[1] = width_aligned;
170  vf->pitches[2] = 0;
171  }
172  else
173  {
174  vf->pitches[0] = (width_aligned * vf->bpp) >> 3;
175  vf->pitches[1] = vf->pitches[2] = 0;
176  }
177  }
178 
179  if (o)
180  {
181  memcpy(vf->offsets, o, 3 * sizeof(int));
182  }
183  else
184  {
185  if (FMT_YV12 == _codec)
186  {
187  vf->offsets[0] = 0;
188  vf->offsets[1] = width_aligned * _height;
189  vf->offsets[2] =
190  vf->offsets[1] + ((width_aligned+1) >> 1) * ((_height+1) >> 1);
191  }
192  else if (FMT_YUV422P == _codec)
193  {
194  vf->offsets[0] = 0;
195  vf->offsets[1] = width_aligned * _height;
196  vf->offsets[2] =
197  vf->offsets[1] + ((width_aligned+1) >> 1) * _height;
198  }
199  else if (FMT_NV12 == _codec)
200  {
201  vf->offsets[0] = 0;
202  vf->offsets[1] = width_aligned * _height;
203  vf->offsets[2] = 0;
204  }
205  else
206  {
207  vf->offsets[0] = vf->offsets[1] = vf->offsets[2] = 0;
208  }
209  }
210 }
211 
212 static inline void clear(VideoFrame *vf)
213 {
214  if (!vf)
215  return;
216 
217  int uv_height = (vf->height+1) >> 1;
218  if (FMT_YV12 == vf->codec)
219  {
220  memset(vf->buf + vf->offsets[0], 0, vf->pitches[0] * vf->height);
221  memset(vf->buf + vf->offsets[1], 127, vf->pitches[1] * uv_height);
222  memset(vf->buf + vf->offsets[2], 127, vf->pitches[2] * uv_height);
223  }
224  else if (FMT_NV12 == vf->codec)
225  {
226  memset(vf->buf + vf->offsets[0], 0, vf->pitches[0] * vf->height);
227  memset(vf->buf + vf->offsets[1], 127, vf->pitches[1] * uv_height);
228  }
229 }
230 
231 static inline bool compatible(const VideoFrame *a, const VideoFrame *b)
232 {
233  if (a && b && a->codec == b->codec &&
234  (a->codec == FMT_YV12 || a->codec == FMT_NV12))
235  {
236  return (a->codec == b->codec) &&
237  (a->width == b->width) &&
238  (a->height == b->height) &&
239  (a->size == b->size);
240  }
241 
242  return a && b &&
243  (a->codec == b->codec) &&
244  (a->width == b->width) &&
245  (a->height == b->height) &&
246  (a->size == b->size) &&
247  (a->offsets[0] == b->offsets[0]) &&
248  (a->offsets[1] == b->offsets[1]) &&
249  (a->offsets[2] == b->offsets[2]) &&
250  (a->pitches[0] == b->pitches[0]) &&
251  (a->pitches[1] == b->pitches[1]) &&
252  (a->pitches[2] == b->pitches[2]);
253 }
254 
262 static inline void copy(VideoFrame *dst, const VideoFrame *src)
263 {
264  framecopy(dst, src, true);
265 }
266 
267 static inline int bitsperpixel(VideoFrameType type)
268 {
269  int res = 8;
270  switch (type)
271  {
272  case FMT_BGRA:
273  case FMT_RGBA32:
274  case FMT_ARGB32:
275  case FMT_RGB32:
276  res = 32;
277  break;
278  case FMT_RGB24:
279  res = 24;
280  break;
281  case FMT_YUV422P:
282  case FMT_YUY2:
283  res = 16;
284  break;
285  case FMT_YV12:
286  case FMT_NV12:
287  res = 12;
288  break;
289  case FMT_IA44:
290  case FMT_AI44:
291  default:
292  res = 8;
293  }
294  return res;
295 }
296 
297 static inline uint buffersize(VideoFrameType type, int width, int height,
298  int _aligned = 64)
299 {
300  int type_bpp = bitsperpixel(type);
301  uint bpp = type_bpp / 4; /* bits per pixel div common factor */
302  uint bpb = 8 / 4; /* bits per byte div common factor */
303 
304  // make sure all our pitches are a multiple of 16 bytes
305  // as U and V channels are half the size of Y channel
306  // This allow for SSE/HW accelerated code on all planes
307  // If the buffer sizes are not 32 bytes aligned, adjust.
308  // old versions of MythTV allowed people to set invalid
309  // dimensions for MPEG-4 capture, no need to segfault..
310  uint adj_w;
311  if (!_aligned)
312  {
313  adj_w = width;
314  }
315  else
316  {
317  adj_w = (width + _aligned - 1) & ~(_aligned - 1);
318  }
319  // Calculate rounding as necessary.
320  uint remainder = (adj_w * height * bpp) % bpb;
321  return (adj_w * height * bpp) / bpb + (remainder ? 1 : 0);
322 }
323 
324 static inline void copybuffer(VideoFrame *dst, uint8_t *buffer,
325  int pitch, VideoFrameType type = FMT_YV12)
326 {
327  if (type == FMT_YV12)
328  {
329  VideoFrame framein;
330  int chroma_pitch = pitch >> 1;
331  int chroma_height = dst->height >> 1;
332  int offsets[3] =
333  { 0,
334  pitch * dst->height,
335  pitch * dst->height + chroma_pitch * chroma_height };
336  int pitches[3] = { pitch, chroma_pitch, chroma_pitch };
337 
338  init(&framein, type, buffer, dst->width, dst->height, dst->size,
339  pitches, offsets);
340  copy(dst, &framein);
341  }
342  else if (type == FMT_NV12)
343  {
344  VideoFrame framein;
345  int offsets[3] = { 0, pitch * dst->height, 0 };
346  int pitches[3] = { pitch, pitch, 0 };
347 
348  init(&framein, type, buffer, dst->width, dst->height, dst->size,
349  pitches, offsets);
350  copy(dst, &framein);
351  }
352 }
353 
354 static inline void copybuffer(uint8_t *dstbuffer, const VideoFrame *src,
355  int pitch = 0, VideoFrameType type = FMT_YV12)
356 {
357  if (pitch == 0)
358  {
359  pitch = src->width;
360  }
361 
362  if (type == FMT_YV12)
363  {
364  VideoFrame frameout;
365  int chroma_pitch = pitch >> 1;
366  int chroma_height = src->height >> 1;
367  int offsets[3] =
368  { 0,
369  pitch * src->height,
370  pitch * src->height + chroma_pitch * chroma_height };
371  int pitches[3] = { pitch, chroma_pitch, chroma_pitch };
372 
373  init(&frameout, type, dstbuffer, src->width, src->height, src->size,
374  pitches, offsets);
375  copy(&frameout, src);
376  }
377  else if (type == FMT_NV12)
378  {
379  VideoFrame frameout;
380  int offsets[3] = { 0, pitch * src->height, 0 };
381  int pitches[3] = { pitch, pitch, 0 };
382 
383  init(&frameout, type, dstbuffer, src->width, src->height, src->size,
384  pitches, offsets);
385  copy(&frameout, src);
386  }
387 }
388 #endif /* __cplusplus */
389 
390 #endif
int pitches[3]
Y, U, & V pitches.
Definition: mythframe.h:63
int qstride
Definition: mythframe.h:55
static void copybuffer(VideoFrame *dst, uint8_t *buffer, int pitch, VideoFrameType type=FMT_YV12)
Definition: mythframe.h:324
FrameType_
Definition: mythframe.h:17
uswcState
Definition: mythframe.h:76
int repeat_pict
Definition: mythframe.h:59
static int bitsperpixel(VideoFrameType type)
Definition: mythframe.h:267
static bool compatible(const VideoFrame *a, const VideoFrame *b)
Definition: mythframe.h:231
unsigned int uint
Definition: compat.h:140
int forcekey
hardware encoded .nuv
Definition: mythframe.h:60
long long timecode
Definition: mythframe.h:49
enum FrameType_ VideoFrameType
unsigned char * priv[4]
random empty storage
Definition: mythframe.h:52
unsigned char * qscale_table
Definition: mythframe.h:54
unsigned char b
Definition: ParseText.cpp:329
int offsets[3]
Y, U, & V offsets.
Definition: mythframe.h:64
void MTV_PUBLIC framecopy(VideoFrame *dst, const VideoFrame *src, bool useSSE=true)
Definition: mythframe.cpp:300
float aspect
Definition: mythframe.h:43
#define MTV_PUBLIC
Definition: mythtvexp.h:15
int height
Definition: mythframe.h:42
long long frameNumber
Definition: mythframe.h:48
int pix_fmt
Definition: mythframe.h:66
int top_field_first
1 if top field is first.
Definition: mythframe.h:58
static void clear(VideoFrame *vf)
Definition: mythframe.h:212
int directrendering
1 if managed by FFmpeg
Definition: mythframe.h:67
int64_t disp_timecode
Definition: mythframe.h:50
static void init(VideoFrame *vf, VideoFrameType _codec, unsigned char *_buf, int _width, int _height, int _size, const int *p=nullptr, const int *o=nullptr, float _aspect=-1.0F, double _rate=-1.0F, int _aligned=64)
Definition: mythframe.h:115
struct VideoFrame_ VideoFrame
static uint buffersize(VideoFrameType type, int width, int height, int _aligned=64)
Definition: mythframe.h:297
int interlaced_frame
1 if interlaced.
Definition: mythframe.h:57
unsigned char * buf
Definition: mythframe.h:39
endian dependent format, ARGB or BGRA
Definition: mythframe.h:24
double frame_rate
Definition: mythframe.h:44
VideoFrameType codec
Definition: mythframe.h:38
static void copy(VideoFrame *dst, const VideoFrame *src)
copy: copy one frame into another copy only works with the following assumptions: frames are of the s...
Definition: mythframe.h:262