Files
test/source/blender/imbuf/intern/IMB_anim.h
Richard Antalik f0a3d2beb2 FFmpeg: Add VFR media support
Variable frame rate (VFR) files have been difficult to work with.
This is because during sequential decoding, spacing between frames is
not always equal, but it was assumed to be equal. This can result in
movie getting out of sync with sound and difference between preview and
rendered image. A way to resolve these issues was to build and use
timecodes which is quite lengthy and resource intensive process. Such
issues are also difficult to communicate through UI because it is not
possible to predict if timecode usage would be needed.

With this patch, double buffer is used to keep previously decoded frame.
If current frame has PTS greater than what we are looking for, it is not
time to display it yet, and previous frame is displayed instead.

Each `AVFrame` has information about it's duration, so in theory double
buffering would not be needed, but in practice this information is
unreliable.

To ensure double buffer is always used, function
`ffmpeg_decode_video_frame_scan` is used for sequential decoding, even
if no scanning is expected.

This approach is similar to D6392, but this implementation does not
require seeking so it is much faster. Currently `AVFrame` is only
referenced, so no data is copied and therefore no overhead is added.

Note: There is one known issue where seeking fails even with double
buffering: Some files may seek too far in stream and miss requested
PTS. These require preseeking or greater negative subframe offset

Fixes: T86361, T72347

Reviewed By: zeddb, sergey

Differential Revision: https://developer.blender.org/D13583
2022-06-27 16:58:07 +02:00

143 lines
2.6 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
/** \file
* \ingroup imbuf
*/
#pragma once
#ifdef _WIN32
# define INC_OLE2
# include <commdlg.h>
# include <memory.h>
# include <mmsystem.h>
# include <vfw.h>
# include <windows.h>
# include <windowsx.h>
# undef AVIIF_KEYFRAME /* redefined in AVI_avi.h */
# undef AVIIF_LIST /* redefined in AVI_avi.h */
#endif /* _WIN32 */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef _WIN32
# include <io.h>
#else
# include <dirent.h>
#endif
#include "imbuf.h"
#ifdef WITH_AVI
# include "AVI_avi.h"
#endif
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_allocimbuf.h"
#ifdef WITH_FFMPEG
# include <libavcodec/avcodec.h>
# include <libavformat/avformat.h>
# include <libswscale/swscale.h>
#endif
/* more endianness... should move to a separate file... */
#ifdef __BIG_ENDIAN__
# define LITTLE_LONG SWAP_LONG
#else
# define LITTLE_LONG ENDIAN_NOP
#endif
/* anim.curtype, runtime only */
#define ANIM_NONE 0
#define ANIM_SEQUENCE (1 << 0)
#define ANIM_MOVIE (1 << 4)
#define ANIM_AVI (1 << 6)
#define ANIM_FFMPEG (1 << 8)
#define MAXNUMSTREAMS 50
struct IDProperty;
struct _AviMovie;
struct anim_index;
struct anim {
int ib_flags;
int curtype;
int cur_position; /* index 0 = 1e, 1 = 2e, enz. */
int duration_in_frames;
int frs_sec;
double frs_sec_base;
double start_offset;
int x, y;
/* for number */
char name[1024];
/* for sequence */
char first[1024];
/* movie */
void *movie;
void *track;
void *params;
int orientation;
size_t framesize;
int interlacing;
int streamindex;
/* avi */
struct _AviMovie *avi;
#if defined(_WIN32)
/* windows avi */
int avistreams;
int firstvideo;
int pfileopen;
PAVIFILE pfile;
PAVISTREAM pavi[MAXNUMSTREAMS]; /* the current streams */
PGETFRAME pgf;
#endif
#ifdef WITH_FFMPEG
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
const AVCodec *pCodec;
AVFrame *pFrameRGB;
AVFrame *pFrameDeinterlaced;
struct SwsContext *img_convert_ctx;
int videoStream;
AVFrame *pFrame;
bool pFrame_complete;
AVFrame *pFrame_backup;
bool pFrame_backup_complete;
struct ImBuf *cur_frame_final;
int64_t cur_pts;
int64_t cur_key_frame_pts;
AVPacket *cur_packet;
bool seek_before_decode;
#endif
char index_dir[768];
int proxies_tried;
int indices_tried;
struct anim *proxy_anim[IMB_PROXY_MAX_SLOT];
struct anim_index *curr_idx[IMB_TC_MAX_SLOT];
char colorspace[64];
char suffix[64]; /* MAX_NAME - multiview */
struct IDProperty *metadata;
};