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 
77 {
78 public:
79  MythUSWCCopy(int width, bool nocache = false);
80  virtual ~MythUSWCCopy();
81 
82  void copy(VideoFrame *dst, const VideoFrame *src);
83  void reset(int width);
84  void resetUSWCDetection(void);
85  void setUSWC(bool uswc);
86 
87 private:
88  void allocateCache(int width);
89 
90  uint8_t* m_cache;
91  int m_size;
92  int m_uswc;
93 };
94 
95 void MTV_PUBLIC framecopy(VideoFrame *dst, const VideoFrame *src,
96  bool useSSE = true);
97 
98 static inline void init(VideoFrame *vf, VideoFrameType _codec,
99  unsigned char *_buf, int _width, int _height, int _size,
100  const int *p = nullptr,
101  const int *o = nullptr,
102  float _aspect = -1.0f, double _rate = -1.0f,
103  int _aligned = 64);
104 static inline void clear(VideoFrame *vf);
105 static inline bool compatible(const VideoFrame *a,
106  const VideoFrame *b);
107 static inline int bitsperpixel(VideoFrameType type);
108 
109 static inline void init(VideoFrame *vf, VideoFrameType _codec,
110  unsigned char *_buf, int _width, int _height,
111  int _size, const int *p, const int *o,
112  float _aspect, double _rate, int _aligned)
113 {
114  vf->bpp = bitsperpixel(_codec);
115  vf->codec = _codec;
116  vf->buf = _buf;
117  vf->width = _width;
118  vf->height = _height;
119  vf->aspect = _aspect;
120  vf->frame_rate = _rate;
121 
122  vf->size = _size;
123  vf->frameNumber = 0;
124  vf->timecode = 0;
125 
126  vf->qscale_table = nullptr;
127  vf->qstride = 0;
128 
129  vf->interlaced_frame = 1;
130  vf->top_field_first = 1;
131  vf->repeat_pict = 0;
132  vf->forcekey = 0;
133  vf->dummy = 0;
134  vf->pix_fmt = 0;
135  vf->directrendering = 1;
136 
137  memset(vf->priv, 0, 4 * sizeof(unsigned char *));
138 
139  uint width_aligned;
140  if (!_aligned)
141  {
142  width_aligned = _width;
143  }
144  else
145  {
146  width_aligned = (_width + _aligned - 1) & ~(_aligned - 1);
147  }
148 
149  if (p)
150  {
151  memcpy(vf->pitches, p, 3 * sizeof(int));
152  }
153  else
154  {
155  if (FMT_YV12 == _codec || FMT_YUV422P == _codec)
156  {
157  vf->pitches[0] = width_aligned;
158  vf->pitches[1] = vf->pitches[2] = (width_aligned+1) >> 1;
159  }
160  else if (FMT_NV12 == _codec)
161  {
162  vf->pitches[0] = width_aligned;
163  vf->pitches[1] = width_aligned;
164  vf->pitches[2] = 0;
165  }
166  else
167  {
168  vf->pitches[0] = (width_aligned * vf->bpp) >> 3;
169  vf->pitches[1] = vf->pitches[2] = 0;
170  }
171  }
172 
173  if (o)
174  {
175  memcpy(vf->offsets, o, 3 * sizeof(int));
176  }
177  else
178  {
179  if (FMT_YV12 == _codec)
180  {
181  vf->offsets[0] = 0;
182  vf->offsets[1] = width_aligned * _height;
183  vf->offsets[2] =
184  vf->offsets[1] + ((width_aligned+1) >> 1) * ((_height+1) >> 1);
185  }
186  else if (FMT_YUV422P == _codec)
187  {
188  vf->offsets[0] = 0;
189  vf->offsets[1] = width_aligned * _height;
190  vf->offsets[2] =
191  vf->offsets[1] + ((width_aligned+1) >> 1) * _height;
192  }
193  else if (FMT_NV12 == _codec)
194  {
195  vf->offsets[0] = 0;
196  vf->offsets[1] = width_aligned * _height;
197  vf->offsets[2] = 0;
198  }
199  else
200  {
201  vf->offsets[0] = vf->offsets[1] = vf->offsets[2] = 0;
202  }
203  }
204 }
205 
206 static inline void clear(VideoFrame *vf)
207 {
208  if (!vf)
209  return;
210 
211  int uv_height = (vf->height+1) >> 1;
212  if (FMT_YV12 == vf->codec)
213  {
214  memset(vf->buf + vf->offsets[0], 0, vf->pitches[0] * vf->height);
215  memset(vf->buf + vf->offsets[1], 127, vf->pitches[1] * uv_height);
216  memset(vf->buf + vf->offsets[2], 127, vf->pitches[2] * uv_height);
217  }
218  else if (FMT_NV12 == 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  }
223 }
224 
225 static inline bool compatible(const VideoFrame *a, const VideoFrame *b)
226 {
227  if (a && b && a->codec == b->codec &&
228  (a->codec == FMT_YV12 || a->codec == FMT_NV12))
229  {
230  return (a->codec == b->codec) &&
231  (a->width == b->width) &&
232  (a->height == b->height) &&
233  (a->size == b->size);
234  }
235 
236  return a && b &&
237  (a->codec == b->codec) &&
238  (a->width == b->width) &&
239  (a->height == b->height) &&
240  (a->size == b->size) &&
241  (a->offsets[0] == b->offsets[0]) &&
242  (a->offsets[1] == b->offsets[1]) &&
243  (a->offsets[2] == b->offsets[2]) &&
244  (a->pitches[0] == b->pitches[0]) &&
245  (a->pitches[1] == b->pitches[1]) &&
246  (a->pitches[2] == b->pitches[2]);
247 }
248 
256 static inline void copy(VideoFrame *dst, const VideoFrame *src)
257 {
258  framecopy(dst, src, true);
259 }
260 
261 static inline int bitsperpixel(VideoFrameType type)
262 {
263  int res = 8;
264  switch (type)
265  {
266  case FMT_BGRA:
267  case FMT_RGBA32:
268  case FMT_ARGB32:
269  case FMT_RGB32:
270  res = 32;
271  break;
272  case FMT_RGB24:
273  res = 24;
274  break;
275  case FMT_YUV422P:
276  case FMT_YUY2:
277  res = 16;
278  break;
279  case FMT_YV12:
280  case FMT_NV12:
281  res = 12;
282  break;
283  case FMT_IA44:
284  case FMT_AI44:
285  default:
286  res = 8;
287  }
288  return res;
289 }
290 
291 static inline uint buffersize(VideoFrameType type, int width, int height,
292  int _aligned = 64)
293 {
294  int type_bpp = bitsperpixel(type);
295  uint bpp = type_bpp / 4; /* bits per pixel div common factor */
296  uint bpb = 8 / 4; /* bits per byte div common factor */
297 
298  // make sure all our pitches are a multiple of 16 bytes
299  // as U and V channels are half the size of Y channel
300  // This allow for SSE/HW accelerated code on all planes
301  // If the buffer sizes are not 32 bytes aligned, adjust.
302  // old versions of MythTV allowed people to set invalid
303  // dimensions for MPEG-4 capture, no need to segfault..
304  uint adj_w;
305  if (!_aligned)
306  {
307  adj_w = width;
308  }
309  else
310  {
311  adj_w = (width + _aligned - 1) & ~(_aligned - 1);
312  }
313  // Calculate rounding as necessary.
314  uint remainder = (adj_w * height * bpp) % bpb;
315  return (adj_w * height * bpp) / bpb + (remainder ? 1 : 0);
316 }
317 
318 static inline void copybuffer(VideoFrame *dst, uint8_t *buffer,
319  int pitch, VideoFrameType type = FMT_YV12)
320 {
321  if (type == FMT_YV12)
322  {
323  VideoFrame framein;
324  int chroma_pitch = pitch >> 1;
325  int chroma_height = dst->height >> 1;
326  int offsets[3] =
327  { 0,
328  pitch * dst->height,
329  pitch * dst->height + chroma_pitch * chroma_height };
330  int pitches[3] = { pitch, chroma_pitch, chroma_pitch };
331 
332  init(&framein, type, buffer, dst->width, dst->height, dst->size,
333  pitches, offsets);
334  copy(dst, &framein);
335  }
336  else if (type == FMT_NV12)
337  {
338  VideoFrame framein;
339  int offsets[3] = { 0, pitch * dst->height, 0 };
340  int pitches[3] = { pitch, pitch, 0 };
341 
342  init(&framein, type, buffer, dst->width, dst->height, dst->size,
343  pitches, offsets);
344  copy(dst, &framein);
345  }
346 }
347 
348 static inline void copybuffer(uint8_t *dstbuffer, const VideoFrame *src,
349  int pitch = 0, VideoFrameType type = FMT_YV12)
350 {
351  if (pitch == 0)
352  {
353  pitch = src->width;
354  }
355 
356  if (type == FMT_YV12)
357  {
358  VideoFrame frameout;
359  int chroma_pitch = pitch >> 1;
360  int chroma_height = src->height >> 1;
361  int offsets[3] =
362  { 0,
363  pitch * src->height,
364  pitch * src->height + chroma_pitch * chroma_height };
365  int pitches[3] = { pitch, chroma_pitch, chroma_pitch };
366 
367  init(&frameout, type, dstbuffer, src->width, src->height, src->size,
368  pitches, offsets);
369  copy(&frameout, src);
370  }
371  else if (type == FMT_NV12)
372  {
373  VideoFrame frameout;
374  int offsets[3] = { 0, pitch * src->height, 0 };
375  int pitches[3] = { pitch, pitch, 0 };
376 
377  init(&frameout, type, dstbuffer, src->width, src->height, src->size,
378  pitches, offsets);
379  copy(&frameout, src);
380  }
381 }
382 #endif /* __cplusplus */
383 
384 #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:318
FrameType_
Definition: mythframe.h:17
int repeat_pict
Definition: mythframe.h:59
static int bitsperpixel(VideoFrameType type)
Definition: mythframe.h:261
static bool compatible(const VideoFrame *a, const VideoFrame *b)
Definition: mythframe.h:225
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:340
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:109
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:319
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:206
uint8_t * m_cache
Definition: mythframe.h:90
int directrendering
1 if managed by FFmpeg
Definition: mythframe.h:67
int64_t disp_timecode
Definition: mythframe.h:50
struct VideoFrame_ VideoFrame
static uint buffersize(VideoFrameType type, int width, int height, int _aligned=64)
Definition: mythframe.h:291
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:256