Blender  V3.3
ffmpeg_compat.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Peter Schlaile. */
3 
13 #ifndef __FFMPEG_COMPAT_H__
14 #define __FFMPEG_COMPAT_H__
15 
16 #include <libavcodec/avcodec.h>
17 #include <libavformat/avformat.h>
18 
19 /* Check if our ffmpeg is new enough, avoids user complaints.
20  * Minimum supported version is currently 3.2.0 which mean the following library versions:
21  * libavutil > 55.30
22  * libavcodec > 57.60
23  * libavformat > 57.50
24  *
25  * We only check for one of these as they are usually updated in tandem.
26  */
27 #if (LIBAVFORMAT_VERSION_MAJOR < 57) || \
28  ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR <= 50))
29 # error "FFmpeg 3.2.0 or newer is needed, Upgrade your FFmpeg or disable it"
30 #endif
31 /* end sanity check */
32 
33 /* visual studio 2012 does not define inline for C */
34 #ifdef _MSC_VER
35 # define FFMPEG_INLINE static __inline
36 #else
37 # define FFMPEG_INLINE static inline
38 #endif
39 
40 #if (LIBAVFORMAT_VERSION_MAJOR < 59)
41 /* For versions older than ffmpeg 5.0, use the old channel layout variables.
42  * We intend to only keep this workaround for around two releases (3.5, 3.6).
43  * If it sticks around any longer, then we should consider refactoring this.
44  */
45 # define FFMPEG_USE_OLD_CHANNEL_VARS
46 #endif
47 
48 /* AV_CODEC_CAP_AUTO_THREADS was renamed to AV_CODEC_CAP_OTHER_THREADS with
49  * upstream commit
50  * github.com/FFmpeg/FFmpeg/commit/7d09579190def3ef7562399489e628f3b65714ce
51  * (lavc 58.132.100) and removed with commit
52  * github.com/FFmpeg/FFmpeg/commit/10c9a0874cb361336237557391d306d26d43f137
53  * for ffmpeg 6.0.
54  */
55 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 132, 100)
56 # define AV_CODEC_CAP_OTHER_THREADS AV_CODEC_CAP_AUTO_THREADS
57 #endif
58 
59 #if (LIBAVFORMAT_VERSION_MAJOR < 58) || \
60  ((LIBAVFORMAT_VERSION_MAJOR == 58) && (LIBAVFORMAT_VERSION_MINOR < 76))
61 # define FFMPEG_USE_DURATION_WORKAROUND 1
62 
63 /* Before ffmpeg 4.4, package duration calculation used depricated variables to calculate the
64  * packet duration. Use the function from commit
65  * github.com/FFmpeg/FFmpeg/commit/1c0885334dda9ee8652e60c586fa2e3674056586
66  * to calculate the correct framerate for ffmpeg < 4.4.
67  */
68 
70 void my_guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt)
71 {
72  if (pkt->duration < 0 && st->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
73  av_log(s,
74  AV_LOG_WARNING,
75  "Packet with invalid duration %" PRId64 " in stream %d\n",
76  pkt->duration,
77  pkt->stream_index);
78  pkt->duration = 0;
79  }
80 
81  if (pkt->duration) {
82  return;
83  }
84 
85  switch (st->codecpar->codec_type) {
86  case AVMEDIA_TYPE_VIDEO:
87  if (st->avg_frame_rate.num > 0 && st->avg_frame_rate.den > 0) {
88  pkt->duration = av_rescale_q(1, av_inv_q(st->avg_frame_rate), st->time_base);
89  }
90  else if (st->time_base.num * 1000LL > st->time_base.den) {
91  pkt->duration = 1;
92  }
93  break;
94  case AVMEDIA_TYPE_AUDIO: {
95  int frame_size = av_get_audio_frame_duration2(st->codecpar, pkt->size);
96  if (frame_size && st->codecpar->sample_rate) {
97  pkt->duration = av_rescale_q(
98  frame_size, (AVRational){1, st->codecpar->sample_rate}, st->time_base);
99  }
100  break;
101  }
102  default:
103  break;
104  }
105 }
106 #endif
107 
110 {
111  /* Some videos do not have any pts values, use dts instead in those cases if
112  * possible. Usually when this happens dts can act as pts because as all frames
113  * should then be presented in their decoded in order. IE pts == dts. */
114  if (pts == AV_NOPTS_VALUE) {
115  return dts;
116  }
117  return pts;
118 }
119 
122 {
123  return timestamp_from_pts_or_dts(picture->pts, picture->pkt_dts);
124 }
125 
126 /* -------------------------------------------------------------------- */
132 #define MAX_NEG_CROP 1024
133 
134 #define times4(x) x, x, x, x
135 #define times256(x) times4(times4(times4(times4(times4(x)))))
136 
137 static const uint8_t ff_compat_crop_tab[256 + 2 * MAX_NEG_CROP] = {
138  times256(0x00), 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
139  0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
140  0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,
141  0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E,
142  0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
143  0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
144  0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
145  0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E,
146  0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
147  0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
148  0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82,
149  0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E,
150  0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
151  0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
152  0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2,
153  0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
154  0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
155  0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
156  0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2,
157  0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE,
158  0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
159  0xFB, 0xFC, 0xFD, 0xFE, 0xFF, times256(0xFF)};
160 
161 #undef times4
162 #undef times256
163 
164 /* filter parameters: [-1 4 2 4 -1] // 8 */
167  const uint8_t *lum_m4,
168  const uint8_t *lum_m3,
169  const uint8_t *lum_m2,
170  const uint8_t *lum_m1,
171  const uint8_t *lum,
172  int size)
173 {
175  int sum;
176 
177  for (; size > 0; size--) {
178  sum = -lum_m4[0];
179  sum += lum_m3[0] << 2;
180  sum += lum_m2[0] << 1;
181  sum += lum_m1[0] << 2;
182  sum += -lum[0];
183  dst[0] = cm[(sum + 4) >> 3];
184  lum_m4++;
185  lum_m3++;
186  lum_m2++;
187  lum_m1++;
188  lum++;
189  dst++;
190  }
191 }
192 
195  uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum, int size)
196 {
198  int sum;
199 
200  for (; size > 0; size--) {
201  sum = -lum_m4[0];
202  sum += lum_m3[0] << 2;
203  sum += lum_m2[0] << 1;
204  lum_m4[0] = lum_m2[0];
205  sum += lum_m1[0] << 2;
206  sum += -lum[0];
207  lum_m2[0] = cm[(sum + 4) >> 3];
208  lum_m4++;
209  lum_m3++;
210  lum_m2++;
211  lum_m1++;
212  lum++;
213  }
214 }
215 
216 /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
217  top field is copied as is, but the bottom field is deinterlaced
218  against the top field. */
221  uint8_t *dst, int dst_wrap, const uint8_t *src1, int src_wrap, int width, int height)
222 {
223  const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
224  int y;
225 
226  src_m2 = src1;
227  src_m1 = src1;
228  src_0 = &src_m1[src_wrap];
229  src_p1 = &src_0[src_wrap];
230  src_p2 = &src_p1[src_wrap];
231  for (y = 0; y < (height - 2); y += 2) {
232  memcpy(dst, src_m1, width);
233  dst += dst_wrap;
234  deinterlace_line(dst, src_m2, src_m1, src_0, src_p1, src_p2, width);
235  src_m2 = src_0;
236  src_m1 = src_p1;
237  src_0 = src_p2;
238  src_p1 += 2 * src_wrap;
239  src_p2 += 2 * src_wrap;
240  dst += dst_wrap;
241  }
242  memcpy(dst, src_m1, width);
243  dst += dst_wrap;
244  /* do last line */
245  deinterlace_line(dst, src_m2, src_m1, src_0, src_0, src_0, width);
246 }
247 
249 int deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, int width, int height)
250 {
251  uint8_t *src_m1, *src_0, *src_p1, *src_p2;
252  int y;
253  uint8_t *buf = (uint8_t *)av_malloc(width);
254  if (!buf) {
255  return AVERROR(ENOMEM);
256  }
257 
258  src_m1 = src1;
259  memcpy(buf, src_m1, width);
260  src_0 = &src_m1[src_wrap];
261  src_p1 = &src_0[src_wrap];
262  src_p2 = &src_p1[src_wrap];
263  for (y = 0; y < (height - 2); y += 2) {
264  deinterlace_line_inplace(buf, src_m1, src_0, src_p1, src_p2, width);
265  src_m1 = src_p1;
266  src_0 = src_p2;
267  src_p1 += 2 * src_wrap;
268  src_p2 += 2 * src_wrap;
269  }
270  /* do last line */
271  deinterlace_line_inplace(buf, src_m1, src_0, src_0, src_0, width);
272  av_free(buf);
273  return 0;
274 }
275 
278  AVFrame *dst, const AVFrame *src, enum AVPixelFormat pix_fmt, int width, int height)
279 {
280  int i, ret;
281 
282  if (pix_fmt != AV_PIX_FMT_YUV420P && pix_fmt != AV_PIX_FMT_YUVJ420P &&
283  pix_fmt != AV_PIX_FMT_YUV422P && pix_fmt != AV_PIX_FMT_YUVJ422P &&
284  pix_fmt != AV_PIX_FMT_YUV444P && pix_fmt != AV_PIX_FMT_YUV411P &&
285  pix_fmt != AV_PIX_FMT_GRAY8) {
286  return -1;
287  }
288  if ((width & 3) != 0 || (height & 3) != 0) {
289  return -1;
290  }
291 
292  for (i = 0; i < 3; i++) {
293  if (i == 1) {
294  switch (pix_fmt) {
295  case AV_PIX_FMT_YUVJ420P:
296  case AV_PIX_FMT_YUV420P:
297  width >>= 1;
298  height >>= 1;
299  break;
300  case AV_PIX_FMT_YUV422P:
301  case AV_PIX_FMT_YUVJ422P:
302  width >>= 1;
303  break;
304  case AV_PIX_FMT_YUV411P:
305  width >>= 2;
306  break;
307  default:
308  break;
309  }
310  if (pix_fmt == AV_PIX_FMT_GRAY8) {
311  break;
312  }
313  }
314  if (src == dst) {
315  ret = deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i], width, height);
316  if (ret < 0) {
317  return ret;
318  }
319  }
320  else {
322  dst->data[i], dst->linesize[i], src->data[i], src->linesize[i], width, height);
323  }
324  }
325  return 0;
326 }
327 
330 #endif
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static T sum(const btAlignedObjectArray< T > &items)
SyclQueue void void * src
FFMPEG_INLINE void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum, int size)
static const uint8_t ff_compat_crop_tab[256+2 *MAX_NEG_CROP]
FFMPEG_INLINE int64_t timestamp_from_pts_or_dts(int64_t pts, int64_t dts)
#define MAX_NEG_CROP
FFMPEG_INLINE int64_t av_get_pts_from_frame(AVFrame *picture)
FFMPEG_INLINE void deinterlace_line(uint8_t *dst, const uint8_t *lum_m4, const uint8_t *lum_m3, const uint8_t *lum_m2, const uint8_t *lum_m1, const uint8_t *lum, int size)
FFMPEG_INLINE void deinterlace_bottom_field(uint8_t *dst, int dst_wrap, const uint8_t *src1, int src_wrap, int width, int height)
FFMPEG_INLINE int deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, int width, int height)
#define times256(x)
FFMPEG_INLINE void my_guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt)
Definition: ffmpeg_compat.h:70
#define FFMPEG_INLINE
Definition: ffmpeg_compat.h:37
FFMPEG_INLINE int av_image_deinterlace(AVFrame *dst, const AVFrame *src, enum AVPixelFormat pix_fmt, int width, int height)
#define PRId64
Definition: inttypes.h:78
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
return ret
__int64 int64_t
Definition: stdint.h:89
unsigned char uint8_t
Definition: stdint.h:78