Video: Remove non-ffmpeg AVI support

Blender had a very limited (only uncompressed or MJPEG frames) .avi file
support, for both reading and writing. This is something that ffmpeg can
fully do.

This removes all of that. 3500 lines of code gone, primary motivations being:
- ffmpeg can read and write .avi files just fine, including ones with
  uncompressed or MJPEG frames.
- Blender's ffmpeg integration could also be taught to produce uncompressed or
  MJPEG .avi files, but TBH I don't see a particular reason to do that. Modern
  formats like H264 are better in every way, and already support "lossless"
  option if needed.
- The "Lite" blender build configuration was excluding both ffmpeg and avi
  anyway, so that config is something that can't read nor write any movies.

User visible changes:

- In scene image output type, under Video section now there's only Ffmpeg Video
  (AVI Raw and AVI JPEG are gone)
- Whenever loading an existing file, if output was one of AVI Raw / AVI JPEG,
  it is set to Ffmpeg Video.

Pull Request: https://projects.blender.org/blender/blender/pulls/118409
This commit is contained in:
Aras Pranckevicius
2024-02-20 13:15:50 +01:00
committed by Aras Pranckevicius
parent 6d88285cd2
commit f09c7dc4ba
33 changed files with 62 additions and 3573 deletions

View File

@@ -412,7 +412,6 @@ option(WITH_IMAGE_CINEON "Enable CINEON and DPX Image Support" ON)
option(WITH_IMAGE_WEBP "Enable WebP Image Support" ON)
# Audio/Video format support
option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg)" ON)
option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ON)
option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" ON)
@@ -2390,7 +2389,6 @@ if(FIRST_RUN)
info_cfg_option(WITH_IMAGE_OPENJPEG)
info_cfg_text("Audio:")
info_cfg_option(WITH_CODEC_AVI)
info_cfg_option(WITH_CODEC_FFMPEG)
info_cfg_option(WITH_CODEC_SNDFILE)
info_cfg_option(WITH_COREAUDIO)

View File

@@ -12,7 +12,6 @@ set(WITH_ALEMBIC ON CACHE BOOL "" FORCE)
set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
set(WITH_BULLET ON CACHE BOOL "" FORCE)
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR_CPU ON CACHE BOOL "" FORCE)

View File

@@ -15,7 +15,6 @@ set(WITH_BLENDER_THUMBNAILER OFF CACHE BOOL "" FORCE)
set(WITH_BOOST OFF CACHE BOOL "" FORCE)
set(WITH_BUILDINFO OFF CACHE BOOL "" FORCE)
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_AVI OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG OFF CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE OFF CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR_CPU OFF CACHE BOOL "" FORCE)

View File

@@ -16,7 +16,6 @@ set(WITH_ASSERT_ABORT OFF CACHE BOOL "" FORCE)
set(WITH_AUDASPACE ON CACHE BOOL "" FORCE)
set(WITH_BUILDINFO ON CACHE BOOL "" FORCE)
set(WITH_BULLET ON CACHE BOOL "" FORCE)
set(WITH_CODEC_AVI ON CACHE BOOL "" FORCE)
set(WITH_CODEC_FFMPEG ON CACHE BOOL "" FORCE)
set(WITH_CODEC_SNDFILE ON CACHE BOOL "" FORCE)
set(WITH_COMPOSITOR_CPU ON CACHE BOOL "" FORCE)

View File

@@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 4
#define BLENDER_FILE_SUBVERSION 5
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@@ -644,13 +644,6 @@ if(WITH_IMAGE_WEBP)
add_definitions(-DWITH_WEBP)
endif()
if(WITH_CODEC_AVI)
list(APPEND INC
../io/avi
)
add_definitions(-DWITH_AVI)
endif()
if(WITH_CODEC_FFMPEG)
list(APPEND SRC
intern/writeffmpeg.cc

View File

@@ -17,16 +17,13 @@
#include "BLI_utildefines.h"
#include "BKE_report.hh"
#ifdef WITH_AVI
# include "BLI_blenlib.h"
# include "BKE_main.hh"
#ifdef WITH_FFMPEG
# include "BKE_writeffmpeg.hh"
#endif
#include "BKE_writeavi.h"
/* ********************** general blender movie support ***************************** */
static int start_stub(void * /*context_v*/,
const Scene * /*scene*/,
RenderData * /*rd*/,
@@ -61,44 +58,10 @@ static void *context_create_stub()
static void context_free_stub(void * /*context_v*/) {}
#ifdef WITH_AVI
# include "AVI_avi.h"
/* callbacks */
static int start_avi(void *context_v,
const Scene *scene,
RenderData *rd,
int rectx,
int recty,
ReportList *reports,
bool preview,
const char *suffix);
static void end_avi(void *context_v);
static int append_avi(void *context_v,
RenderData *rd,
int start_frame,
int frame,
int *pixels,
int rectx,
int recty,
const char *suffix,
ReportList *reports);
static void filepath_avi(char filepath[FILE_MAX],
const RenderData *rd,
bool preview,
const char *suffix);
static void *context_create_avi(void);
static void context_free_avi(void *context_v);
#endif /* WITH_AVI */
#ifdef WITH_FFMPEG
# include "BKE_writeffmpeg.hh"
#endif
bMovieHandle *BKE_movie_handle_get(const char imtype)
{
static bMovieHandle mh = {nullptr};
/* stub callbacks in case none of the movie formats is supported */
/* Stub callbacks in case ffmpeg is not compiled in. */
mh.start_movie = start_stub;
mh.append_movie = append_stub;
mh.end_movie = end_stub;
@@ -106,19 +69,10 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
mh.context_create = context_create_stub;
mh.context_free = context_free_stub;
/* set the default handle, as builtin */
#ifdef WITH_AVI
mh.start_movie = start_avi;
mh.append_movie = append_avi;
mh.end_movie = end_avi;
mh.get_movie_path = filepath_avi;
mh.context_create = context_create_avi;
mh.context_free = context_free_avi;
#endif
/* do the platform specific handles */
#ifdef WITH_FFMPEG
if (ELEM(imtype,
R_IMF_IMTYPE_AVIRAW,
R_IMF_IMTYPE_AVIJPEG,
R_IMF_IMTYPE_FFMPEG,
R_IMF_IMTYPE_H264,
R_IMF_IMTYPE_XVID,
@@ -132,178 +86,13 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
mh.context_create = BKE_ffmpeg_context_create;
mh.context_free = BKE_ffmpeg_context_free;
}
#endif
/* in case all above are disabled */
#else
(void)imtype;
#endif
return (mh.append_movie != append_stub) ? &mh : nullptr;
}
/* ****************************************************************** */
#ifdef WITH_AVI
static void filepath_avi(char filepath[FILE_MAX],
const RenderData *rd,
bool preview,
const char *suffix)
{
int sfra, efra;
if (filepath == nullptr) {
return;
}
if (preview) {
sfra = rd->psfra;
efra = rd->pefra;
}
else {
sfra = rd->sfra;
efra = rd->efra;
}
BLI_strncpy(filepath, rd->pic, FILE_MAX);
BLI_path_abs(filepath, BKE_main_blendfile_path_from_global());
BLI_file_ensure_parent_dir_exists(filepath);
if (rd->scemode & R_EXTENSION) {
if (!BLI_path_extension_check(filepath, ".avi")) {
BLI_path_frame_range(filepath, FILE_MAX, sfra, efra, 4);
BLI_strncat(filepath, ".avi", FILE_MAX);
}
}
else {
if (BLI_path_frame_check_chars(filepath)) {
BLI_path_frame_range(filepath, FILE_MAX, sfra, efra, 4);
}
}
BLI_path_suffix(filepath, FILE_MAX, suffix, "");
}
static int start_avi(void *context_v,
const Scene * /*scene*/,
RenderData *rd,
int rectx,
int recty,
ReportList *reports,
bool preview,
const char *suffix)
{
int x, y;
char filepath[FILE_MAX];
AviFormat format;
int quality;
double framerate;
AviMovie *avi = static_cast<AviMovie *>(context_v);
filepath_avi(filepath, rd, preview, suffix);
x = rectx;
y = recty;
quality = rd->im_format.quality;
framerate = double(rd->frs_sec) / double(rd->frs_sec_base);
if (rd->im_format.imtype != R_IMF_IMTYPE_AVIJPEG) {
format = AVI_FORMAT_AVI_RGB;
}
else {
format = AVI_FORMAT_MJPEG;
}
if (AVI_open_compress(filepath, avi, 1, format) != AVI_ERROR_NONE) {
BKE_report(reports, RPT_ERROR, "Cannot open or start AVI movie file");
return 0;
}
AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x);
AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y);
AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality);
AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate);
avi->interlace = 0;
avi->odd_fields = 0;
printf("Created avi: %s\n", filepath);
return 1;
}
static int append_avi(void *context_v,
RenderData * /*rd*/,
int start_frame,
int frame,
int *pixels,
int rectx,
int recty,
const char * /*suffix*/,
ReportList * /*reports*/)
{
uint *rt1, *rt2, *rectot;
int x, y;
char *cp, rt;
AviMovie *avi = static_cast<AviMovie *>(context_v);
if (avi == nullptr) {
return 0;
}
/* NOTE(@zr): that LIBAVI free's the buffer (stupid interface). */
rectot = static_cast<uint *>(MEM_mallocN(rectx * recty * sizeof(int), "rectot"));
rt1 = rectot;
rt2 = (uint *)pixels + (recty - 1) * rectx;
/* Flip Y and convert to ABGR. */
for (y = 0; y < recty; y++, rt1 += rectx, rt2 -= rectx) {
memcpy(rt1, rt2, rectx * sizeof(int));
cp = (char *)rt1;
for (x = rectx; x > 0; x--) {
rt = cp[0];
cp[0] = cp[3];
cp[3] = rt;
rt = cp[1];
cp[1] = cp[2];
cp[2] = rt;
cp += 4;
}
}
AVI_write_frame(avi, (frame - start_frame), AVI_FORMAT_RGB32, rectot, rectx * recty * 4);
// printf("added frame %3d (frame %3d in avi): ", frame, frame-start_frame);
return 1;
}
static void end_avi(void *context_v)
{
AviMovie *avi = static_cast<AviMovie *>(context_v);
if (avi == nullptr) {
return;
}
AVI_close_compress(avi);
}
static void *context_create_avi()
{
AviMovie *avi = static_cast<AviMovie *>(MEM_mallocN(sizeof(AviMovie), "avimovie"));
return avi;
}
static void context_free_avi(void *context_v)
{
AviMovie *avi = static_cast<AviMovie *>(context_v);
if (avi) {
MEM_freeN(avi);
}
}
#endif /* WITH_AVI */
void BKE_movie_filepath_get(char filepath[/*FILE_MAX*/ 1024],
const RenderData *rd,
bool preview,

View File

@@ -1939,6 +1939,13 @@ static bool seq_filter_bilinear_to_auto(Sequence *seq, void * /*user_data*/)
return true;
}
static void image_settings_avi_to_ffmpeg(Scene *sce)
{
if (ELEM(sce->r.im_format.imtype, R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG)) {
sce->r.im_format.imtype = R_IMF_IMTYPE_FFMPEG;
}
}
void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 1)) {
@@ -2953,6 +2960,12 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 402, 5)) {
LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
image_settings_avi_to_ffmpeg(sce);
}
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.

View File

@@ -124,16 +124,6 @@ if(WITH_IMAGE_OPENJPEG)
add_definitions(-DWITH_OPENJPEG ${OPENJPEG_DEFINES})
endif()
if(WITH_CODEC_AVI)
list(APPEND INC
../io/avi
)
list(APPEND LIB
bf_avi
)
add_definitions(-DWITH_AVI)
endif()
if(WITH_CODEC_FFMPEG)
list(APPEND INC
../../../intern/ffmpeg

View File

@@ -397,9 +397,11 @@ bool IMB_ispic_type_matches(const char *filepath, int filetype);
int IMB_ispic_type_from_memory(const unsigned char *buf, size_t buf_size);
int IMB_ispic_type(const char *filepath);
enum class ImbAnimType { NotAnim, Sequence, Movie, Ffmpeg };
bool IMB_isanim(const char *filepath);
int imb_get_anim_type(const char *filepath);
ImbAnimType imb_get_anim_type(const char *filepath);
/**
* Test if color-space conversions of pixels in buffer need to take into account alpha.

View File

@@ -8,19 +8,6 @@
#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>
@@ -34,10 +21,6 @@
#include "imbuf.hh"
#ifdef WITH_AVI
# include "AVI_avi.h"
#endif
#include "IMB_imbuf.hh"
#include "IMB_imbuf_types.hh"
@@ -49,29 +32,12 @@ extern "C" {
}
#endif
/* more endianness... should move to a separate file... */
#ifdef __BIG_ENDIAN__
# define LITTLE_LONG SWAP_LONG
#else
# define LITTLE_LONG ENDIAN_NOP
#endif
/** #ImBufAnim::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 ImBufAnimIndex;
struct ImBufAnim {
int ib_flags;
int curtype;
ImbAnimType curtype;
int cur_position; /* index 0 = 1e, 1 = 2e, enz. */
int duration_in_frames;
int frs_sec;
@@ -93,19 +59,6 @@ struct ImBufAnim {
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;

View File

@@ -6,26 +6,6 @@
* \ingroup imbuf
*/
#ifdef _WIN32
# include "BLI_winstuff.h"
# include <vfw.h>
# undef AVIIF_KEYFRAME /* redefined in AVI_avi.h */
# undef AVIIF_LIST /* redefined in AVI_avi.h */
# define FIXCC(fcc) \
{ \
if (fcc == 0) { \
fcc = mmioFOURCC('N', 'o', 'n', 'e'); \
} \
if (fcc == BI_RLE8) { \
fcc = mmioFOURCC('R', 'l', 'e', '8'); \
} \
} \
(void)0
#endif
#include <cctype>
#include <climits>
#include <cmath>
@@ -47,10 +27,6 @@
#include "MEM_guardedalloc.h"
#ifdef WITH_AVI
# include "AVI_avi.h"
#endif
#include "IMB_imbuf.hh"
#include "IMB_imbuf_types.hh"
@@ -95,47 +71,6 @@ static void free_anim_movie(ImBufAnim * /*anim*/)
/* pass */
}
#ifdef WITH_AVI
static void free_anim_avi(ImBufAnim *anim)
{
# if defined(_WIN32)
int i;
# endif
if (anim == nullptr) {
return;
}
if (anim->avi == nullptr) {
return;
}
AVI_close(anim->avi);
MEM_freeN(anim->avi);
anim->avi = nullptr;
# if defined(_WIN32)
if (anim->pgf) {
AVIStreamGetFrameClose(anim->pgf);
anim->pgf = nullptr;
}
for (i = 0; i < anim->avistreams; i++) {
AVIStreamRelease(anim->pavi[i]);
}
anim->avistreams = 0;
if (anim->pfileopen) {
AVIFileRelease(anim->pfile);
anim->pfileopen = 0;
AVIFileExit();
}
# endif
anim->duration_in_frames = 0;
}
#endif /* WITH_AVI */
#ifdef WITH_FFMPEG
static void free_anim_ffmpeg(ImBufAnim *anim);
#endif
@@ -149,10 +84,6 @@ void IMB_free_anim(ImBufAnim *anim)
free_anim_movie(anim);
#ifdef WITH_AVI
free_anim_avi(anim);
#endif
#ifdef WITH_FFMPEG
free_anim_ffmpeg(anim);
#endif
@@ -183,7 +114,7 @@ void IMB_close_anim_proxies(ImBufAnim *anim)
IDProperty *IMB_anim_load_metadata(ImBufAnim *anim)
{
switch (anim->curtype) {
case ANIM_FFMPEG: {
case ImbAnimType::Ffmpeg: {
#ifdef WITH_FFMPEG
AVDictionaryEntry *entry = nullptr;
@@ -203,12 +134,11 @@ IDProperty *IMB_anim_load_metadata(ImBufAnim *anim)
#endif
break;
}
case ANIM_SEQUENCE:
case ANIM_AVI:
case ANIM_MOVIE:
case ImbAnimType::Sequence:
case ImbAnimType::Movie:
/* TODO */
break;
case ANIM_NONE:
case ImbAnimType::NotAnim:
default:
break;
}
@@ -244,15 +174,10 @@ ImBufAnim *IMB_open_anim(const char *filepath,
bool IMB_anim_can_produce_frames(const ImBufAnim *anim)
{
#if !(defined(WITH_AVI) || defined(WITH_FFMPEG))
#if !defined(WITH_FFMPEG)
UNUSED_VARS(anim);
#endif
#ifdef WITH_AVI
if (anim->avi != nullptr) {
return true;
}
#endif
#ifdef WITH_FFMPEG
if (anim->pCodecCtx != nullptr) {
return true;
@@ -266,179 +191,6 @@ void IMB_suffix_anim(ImBufAnim *anim, const char *suffix)
STRNCPY(anim->suffix, suffix);
}
#ifdef WITH_AVI
static int startavi(ImBufAnim *anim)
{
AviError avierror;
# if defined(_WIN32)
HRESULT hr;
int i, firstvideo = -1;
int streamcount;
BYTE abFormat[1024];
LONG l;
LPBITMAPINFOHEADER lpbi;
AVISTREAMINFO avis;
streamcount = anim->streamindex;
# endif
anim->avi = MEM_cnew<AviMovie>("animavi");
if (anim->avi == nullptr) {
printf("Can't open avi: %s\n", anim->filepath);
return -1;
}
avierror = AVI_open_movie(anim->filepath, anim->avi);
# if defined(_WIN32)
if (avierror == AVI_ERROR_COMPRESSION) {
AVIFileInit();
hr = AVIFileOpen(&anim->pfile, anim->filepath, OF_READ, 0L);
if (hr == 0) {
anim->pfileopen = 1;
for (i = 0; i < MAXNUMSTREAMS; i++) {
if (AVIFileGetStream(anim->pfile, &anim->pavi[i], 0L, i) != AVIERR_OK) {
break;
}
AVIStreamInfo(anim->pavi[i], &avis, sizeof(avis));
if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) {
if (streamcount > 0) {
streamcount--;
continue;
}
anim->pgf = AVIStreamGetFrameOpen(anim->pavi[i], nullptr);
if (anim->pgf) {
firstvideo = i;
/* get stream length */
anim->avi->header->TotalFrames = AVIStreamLength(anim->pavi[i]);
/* get information about images inside the stream */
l = sizeof(abFormat);
AVIStreamReadFormat(anim->pavi[i], 0, &abFormat, &l);
lpbi = (LPBITMAPINFOHEADER)abFormat;
anim->avi->header->Height = lpbi->biHeight;
anim->avi->header->Width = lpbi->biWidth;
}
else {
FIXCC(avis.fccHandler);
FIXCC(avis.fccType);
printf("Can't find AVI decoder for type : %4.4hs/%4.4hs\n",
(LPSTR)&avis.fccType,
(LPSTR)&avis.fccHandler);
}
}
}
/* register number of opened avistreams */
anim->avistreams = i;
/*
* Couldn't get any video streams out of this file
*/
if ((anim->avistreams == 0) || (firstvideo == -1)) {
avierror = AVI_ERROR_FORMAT;
}
else {
avierror = AVI_ERROR_NONE;
anim->firstvideo = firstvideo;
}
}
else {
AVIFileExit();
}
}
# endif
if (avierror != AVI_ERROR_NONE) {
AVI_print_error(avierror);
printf("Error loading avi: %s\n", anim->filepath);
free_anim_avi(anim);
return -1;
}
anim->duration_in_frames = anim->avi->header->TotalFrames;
anim->start_offset = 0.0f;
anim->params = nullptr;
anim->x = anim->avi->header->Width;
anim->y = anim->avi->header->Height;
anim->interlacing = 0;
anim->orientation = 0;
anim->framesize = anim->x * anim->y * 4;
anim->cur_position = 0;
# if 0
printf("x:%d y:%d size:%d interlace:%d dur:%d\n",
anim->x,
anim->y,
anim->framesize,
anim->interlacing,
anim->duration_in_frames);
# endif
return 0;
}
#endif /* WITH_AVI */
#ifdef WITH_AVI
static ImBuf *avi_fetchibuf(ImBufAnim *anim, int position)
{
ImBuf *ibuf = nullptr;
int *tmp;
int y;
if (anim == nullptr) {
return nullptr;
}
# if defined(_WIN32)
if (anim->avistreams) {
LPBITMAPINFOHEADER lpbi;
if (anim->pgf) {
lpbi = static_cast<LPBITMAPINFOHEADER>(
AVIStreamGetFrame(anim->pgf, position + AVIStreamStart(anim->pavi[anim->firstvideo])));
if (lpbi) {
ibuf = IMB_ibImageFromMemory(
(const uchar *)lpbi, 100, IB_rect, anim->colorspace, "<avi_fetchibuf>");
/* Oh brother... */
}
}
}
else
# endif
{
ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect | IB_uninitialized_pixels);
tmp = static_cast<int *>(AVI_read_frame(
anim->avi, AVI_FORMAT_RGB32, position, AVI_get_stream(anim->avi, AVIST_VIDEO, 0)));
if (tmp == nullptr) {
printf("Error reading frame from AVI: '%s'\n", anim->filepath);
IMB_freeImBuf(ibuf);
return nullptr;
}
for (y = 0; y < anim->y; y++) {
memcpy(&(ibuf->byte_buffer.data)[((anim->y - y) - 1) * anim->x],
&tmp[y * anim->x],
anim->x * 4);
}
MEM_freeN(tmp);
}
ibuf->byte_buffer.colorspace = colormanage_colorspace_get_named(anim->colorspace);
return ibuf;
}
#endif /* WITH_AVI */
#ifdef WITH_FFMPEG
static int startffmpeg(ImBufAnim *anim)
@@ -1482,7 +1234,7 @@ static void free_anim_ffmpeg(ImBufAnim *anim)
*/
static bool anim_getnew(ImBufAnim *anim)
{
BLI_assert(anim->curtype == ANIM_NONE);
BLI_assert(anim->curtype == ImbAnimType::NotAnim);
if (anim == nullptr) {
/* Nothing to initialize. */
return false;
@@ -1490,10 +1242,6 @@ static bool anim_getnew(ImBufAnim *anim)
free_anim_movie(anim);
#ifdef WITH_AVI
free_anim_avi(anim);
#endif
#ifdef WITH_FFMPEG
free_anim_ffmpeg(anim);
#endif
@@ -1501,7 +1249,7 @@ static bool anim_getnew(ImBufAnim *anim)
anim->curtype = imb_get_anim_type(anim->filepath);
switch (anim->curtype) {
case ANIM_SEQUENCE: {
case ImbAnimType::Sequence: {
ImBuf *ibuf = IMB_loadiffname(anim->filepath, anim->ib_flags, anim->colorspace);
if (ibuf) {
STRNCPY(anim->filepath_first, anim->filepath);
@@ -1513,26 +1261,20 @@ static bool anim_getnew(ImBufAnim *anim)
}
break;
}
case ANIM_MOVIE:
case ImbAnimType::Movie:
if (startmovie(anim)) {
return false;
}
break;
#ifdef WITH_AVI
case ANIM_AVI:
if (startavi(anim)) {
printf("couldn't start avi\n");
return false;
}
break;
#endif
#ifdef WITH_FFMPEG
case ANIM_FFMPEG:
case ImbAnimType::Ffmpeg:
if (startffmpeg(anim)) {
return false;
}
break;
#endif
default:
break;
}
return true;
}
@@ -1558,7 +1300,7 @@ ImBuf *IMB_anim_previewframe(ImBufAnim *anim)
IMB_metadata_set_field(ibuf->metadata, "Thumb::Video::Frames", value);
#ifdef WITH_FFMPEG
if (anim->pFormatCtx && anim->curtype == ANIM_FFMPEG) {
if (anim->pFormatCtx && anim->curtype == ImbAnimType::Ffmpeg) {
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
AVRational frame_rate = av_guess_frame_rate(anim->pFormatCtx, v_st, nullptr);
if (frame_rate.num != 0) {
@@ -1589,7 +1331,7 @@ ImBuf *IMB_anim_absolute(ImBufAnim *anim,
filter_y = (anim->ib_flags & IB_animdeinterlace);
if (preview_size == IMB_PROXY_NONE) {
if (anim->curtype == ANIM_NONE) {
if (anim->curtype == ImbAnimType::NotAnim) {
if (!anim_getnew(anim)) {
return nullptr;
}
@@ -1613,7 +1355,7 @@ ImBuf *IMB_anim_absolute(ImBufAnim *anim,
}
switch (anim->curtype) {
case ANIM_SEQUENCE: {
case ImbAnimType::Sequence: {
constexpr size_t filepath_size = BOUNDED_ARRAY_TYPE_SIZE<decltype(anim->filepath_first)>();
char head[filepath_size], tail[filepath_size];
ushort digits;
@@ -1627,23 +1369,15 @@ ImBuf *IMB_anim_absolute(ImBufAnim *anim,
}
break;
}
case ANIM_MOVIE:
case ImbAnimType::Movie:
ibuf = movie_fetchibuf(anim, position);
if (ibuf) {
anim->cur_position = position;
IMB_convert_rgba_to_abgr(ibuf);
}
break;
#ifdef WITH_AVI
case ANIM_AVI:
ibuf = avi_fetchibuf(anim, position);
if (ibuf) {
anim->cur_position = position;
}
break;
#endif
#ifdef WITH_FFMPEG
case ANIM_FFMPEG:
case ImbAnimType::Ffmpeg:
ibuf = ffmpeg_fetchibuf(anim, position, tc);
if (ibuf) {
anim->cur_position = position;
@@ -1651,6 +1385,8 @@ ImBuf *IMB_anim_absolute(ImBufAnim *anim,
filter_y = 0; /* done internally */
break;
#endif
default:
break;
}
if (ibuf) {

View File

@@ -26,22 +26,4 @@
# define O_BINARY 0
#endif
#define SWAP_SHORT(x) (((x & 0xff) << 8) | ((x >> 8) & 0xff))
#define SWAP_LONG(x) \
(((x) << 24) | (((x) & 0xff00) << 8) | (((x) >> 8) & 0xff00) | (((x) >> 24) & 0xff))
#define ENDIAN_NOP(x) (x)
#ifdef __BIG_ENDIAN__
# define LITTLE_SHORT SWAP_SHORT
# define LITTLE_LONG SWAP_LONG
# define BIG_SHORT ENDIAN_NOP
# define BIG_LONG ENDIAN_NOP
#else
# define LITTLE_SHORT ENDIAN_NOP
# define LITTLE_LONG ENDIAN_NOP
# define BIG_SHORT SWAP_SHORT
# define BIG_LONG SWAP_LONG
#endif
#define IMB_DPI_DEFAULT 72.0

View File

@@ -30,10 +30,6 @@
#include "IMB_indexer.hh"
#include "imbuf.hh"
#ifdef WITH_AVI
# include "AVI_avi.h"
#endif
#ifdef WITH_FFMPEG
extern "C" {
# include "ffmpeg_compat.h"
@@ -463,7 +459,7 @@ static void get_tc_filepath(ImBufAnim *anim, IMB_Timecode_Type tc, char *filepat
* ---------------------------------------------------------------------- */
struct IndexBuildContext {
int anim_type;
ImbAnimType anim_type;
};
/* ----------------------------------------------------------------------
@@ -1240,172 +1236,6 @@ static bool indexer_need_to_build_proxy(FFmpegIndexBuilderContext *context)
#endif
/* ----------------------------------------------------------------------
* - internal AVI (fallback) rebuilder
* ---------------------------------------------------------------------- */
#ifdef WITH_AVI
struct FallbackIndexBuilderContext {
int anim_type;
ImBufAnim *anim;
AviMovie *proxy_ctx[IMB_PROXY_MAX_SLOT];
int proxy_sizes_in_use;
};
static AviMovie *alloc_proxy_output_avi(
ImBufAnim *anim, const char *filepath, int width, int height, int quality)
{
int x, y;
AviFormat format;
double framerate;
AviMovie *avi;
/* It doesn't really matter for proxies, but sane defaults help anyways. */
short frs_sec = 25;
float frs_sec_base = 1.0;
IMB_anim_get_fps(anim, false, &frs_sec, &frs_sec_base);
x = width;
y = height;
framerate = double(frs_sec) / double(frs_sec_base);
avi = MEM_cnew<AviMovie>("avimovie");
format = AVI_FORMAT_MJPEG;
if (AVI_open_compress(filepath, avi, 1, format) != AVI_ERROR_NONE) {
MEM_freeN(avi);
return nullptr;
}
AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x);
AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y);
AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality);
AVI_set_compress_option(avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate);
avi->interlace = 0;
avi->odd_fields = 0;
return avi;
}
static IndexBuildContext *index_fallback_create_context(ImBufAnim *anim,
int /*tcs_in_use*/,
int proxy_sizes_in_use,
int quality)
{
FallbackIndexBuilderContext *context;
int i;
/* since timecode indices only work with ffmpeg right now,
* don't know a sensible fallback here...
*
* so no proxies...
*/
if (proxy_sizes_in_use == IMB_PROXY_NONE) {
return nullptr;
}
context = MEM_cnew<FallbackIndexBuilderContext>("fallback index builder context");
context->anim = anim;
context->proxy_sizes_in_use = proxy_sizes_in_use;
memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx));
for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
if (context->proxy_sizes_in_use & proxy_sizes[i]) {
char filepath[FILE_MAX];
get_proxy_filepath(anim, proxy_sizes[i], filepath, true);
BLI_file_ensure_parent_dir_exists(filepath);
context->proxy_ctx[i] = alloc_proxy_output_avi(
anim, filepath, anim->x * proxy_fac[i], anim->y * proxy_fac[i], quality);
}
}
return (IndexBuildContext *)context;
}
static void index_rebuild_fallback_finish(FallbackIndexBuilderContext *context, const bool stop)
{
ImBufAnim *anim = context->anim;
char filepath[FILE_MAX];
char filepath_tmp[FILE_MAX];
int i;
for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
if (context->proxy_sizes_in_use & proxy_sizes[i]) {
AVI_close_compress(context->proxy_ctx[i]);
MEM_freeN(context->proxy_ctx[i]);
get_proxy_filepath(anim, proxy_sizes[i], filepath_tmp, true);
get_proxy_filepath(anim, proxy_sizes[i], filepath, false);
if (stop) {
unlink(filepath_tmp);
}
else {
unlink(filepath);
rename(filepath_tmp, filepath);
}
}
}
}
static void index_rebuild_fallback(FallbackIndexBuilderContext *context,
const bool *stop,
bool *do_update,
float *progress)
{
int count = IMB_anim_get_duration(context->anim, IMB_TC_NONE);
int i, pos;
ImBufAnim *anim = context->anim;
for (pos = 0; pos < count; pos++) {
ImBuf *ibuf = IMB_anim_absolute(anim, pos, IMB_TC_NONE, IMB_PROXY_NONE);
ImBuf *tmp_ibuf = IMB_dupImBuf(ibuf);
float next_progress = float(pos) / float(count);
if (*progress != next_progress) {
*progress = next_progress;
*do_update = true;
}
if (*stop) {
break;
}
IMB_flipy(tmp_ibuf);
for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
if (context->proxy_sizes_in_use & proxy_sizes[i]) {
int x = anim->x * proxy_fac[i];
int y = anim->y * proxy_fac[i];
ImBuf *s_ibuf = IMB_dupImBuf(tmp_ibuf);
IMB_scalefastImBuf(s_ibuf, x, y);
IMB_convert_rgba_to_abgr(s_ibuf);
/* note that libavi free's the buffer... */
uint8_t *rect = IMB_steal_byte_buffer(s_ibuf);
AVI_write_frame(context->proxy_ctx[i], pos, AVI_FORMAT_RGB32, rect, x * y * 4);
IMB_freeImBuf(s_ibuf);
}
}
IMB_freeImBuf(tmp_ibuf);
IMB_freeImBuf(ibuf);
}
}
#endif /* WITH_AVI */
/* ----------------------------------------------------------------------
* - public API
* ---------------------------------------------------------------------- */
@@ -1469,7 +1299,7 @@ IndexBuildContext *IMB_anim_index_rebuild_context(ImBufAnim *anim,
switch (anim->curtype) {
#ifdef WITH_FFMPEG
case ANIM_FFMPEG:
case ImbAnimType::Ffmpeg:
context = index_ffmpeg_create_context(
anim, tcs_in_use, proxy_sizes_to_build, quality, build_only_on_bad_performance);
break;
@@ -1478,9 +1308,6 @@ IndexBuildContext *IMB_anim_index_rebuild_context(ImBufAnim *anim,
#endif
default:
#ifdef WITH_AVI
context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality);
#endif
break;
}
@@ -1503,16 +1330,13 @@ void IMB_anim_index_rebuild(IndexBuildContext *context,
{
switch (context->anim_type) {
#ifdef WITH_FFMPEG
case ANIM_FFMPEG:
case ImbAnimType::Ffmpeg:
if (indexer_need_to_build_proxy((FFmpegIndexBuilderContext *)context)) {
index_rebuild_ffmpeg((FFmpegIndexBuilderContext *)context, stop, do_update, progress);
}
break;
#endif
default:
#ifdef WITH_AVI
index_rebuild_fallback((FallbackIndexBuilderContext *)context, stop, do_update, progress);
#endif
break;
}
@@ -1523,14 +1347,11 @@ void IMB_anim_index_rebuild_finish(IndexBuildContext *context, const bool stop)
{
switch (context->anim_type) {
#ifdef WITH_FFMPEG
case ANIM_FFMPEG:
case ImbAnimType::Ffmpeg:
index_rebuild_ffmpeg_finish((FFmpegIndexBuilderContext *)context, stop);
break;
#endif
default:
#ifdef WITH_AVI
index_rebuild_fallback_finish((FallbackIndexBuilderContext *)context, stop);
#endif
break;
}

View File

@@ -171,16 +171,6 @@ bool IMB_ispic(const char *filepath)
return (IMB_ispic_type(filepath) != IMB_FTYPE_NONE);
}
static bool isavi(const char *filepath)
{
#ifdef WITH_AVI
return AVI_is_avi(filepath);
#else
(void)filepath;
return false;
#endif
}
#ifdef WITH_FFMPEG
/* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */
@@ -309,7 +299,7 @@ static int isffmpeg(const char *filepath)
}
#endif
int imb_get_anim_type(const char *filepath)
ImbAnimType imb_get_anim_type(const char *filepath)
{
BLI_stat_t st;
@@ -323,58 +313,48 @@ int imb_get_anim_type(const char *filepath)
# ifdef WITH_FFMPEG
/* stat test below fails on large files > 4GB */
if (isffmpeg(filepath)) {
return ANIM_FFMPEG;
return ImbAnimType::Ffmpeg;
}
# endif
if (BLI_stat(filepath, &st) == -1) {
return 0;
return ImbAnimType::NotAnim;
}
if (((st.st_mode) & S_IFMT) != S_IFREG) {
return 0;
}
if (isavi(filepath)) {
return ANIM_AVI;
return ImbAnimType::NotAnim;
}
if (ismovie(filepath)) {
return ANIM_MOVIE;
return ImbAnimType::Movie;
}
#else /* !_WIN32 */
if (BLI_stat(filepath, &st) == -1) {
return 0;
return ImbAnimType::NotAnim;
}
if (((st.st_mode) & S_IFMT) != S_IFREG) {
return 0;
return ImbAnimType::NotAnim;
}
if (ismovie(filepath)) {
return ANIM_MOVIE;
return ImbAnimType::Movie;
}
# ifdef WITH_FFMPEG
if (isffmpeg(filepath)) {
return ANIM_FFMPEG;
return ImbAnimType::Ffmpeg;
}
# endif
if (isavi(filepath)) {
return ANIM_AVI;
}
#endif /* !_WIN32 */
/* Assume a single image is part of an image sequence. */
if (IMB_ispic(filepath)) {
return ANIM_SEQUENCE;
return ImbAnimType::Sequence;
}
return ANIM_NONE;
return ImbAnimType::NotAnim;
}
bool IMB_isanim(const char *filepath)
{
int type;
type = imb_get_anim_type(filepath);
return (type && type != ANIM_SEQUENCE);
ImbAnimType type = imb_get_anim_type(filepath);
return (type != ImbAnimType::NotAnim && type != ImbAnimType::Sequence);
}

View File

@@ -26,10 +26,6 @@ if(WITH_ALEMBIC)
add_subdirectory(alembic)
endif()
if(WITH_CODEC_AVI)
add_subdirectory(avi)
endif()
if(WITH_OPENCOLLADA)
add_subdirectory(collada)
endif()

View File

@@ -1,290 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* \section avi_about About the AVI module
*
* This is external code. It provides avi file import/export and
* conversions. It has been adapted to make use of Blender memory
* management functions, and because of this it needs module
* blenlib. You need to provide this lib when linking with libavi.a .
*
* \subsection avi_issues Known issues with AVI
*
* - avi uses #MEM_mallocN, #MEM_freeN from blenlib.
* - Not all functions that are used externally are properly
* prototyped.
*
* This header has not been split, since it interleaves type defines
* and functions. You would need the types to be able to include the
* function headers anyway. And, after all, it is someone else's
* code. So we keep it like this.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "BLI_sys_types.h"
#include <stdio.h> /* for FILE */
typedef struct _AviChunk {
int fcc;
int size;
} AviChunk;
typedef struct _AviList {
int fcc;
int size;
int ids;
} AviList;
typedef struct _AviMainHeader {
int fcc;
int size;
int MicroSecPerFrame; /* MicroSecPerFrame - timing between frames */
int MaxBytesPerSec; /* MaxBytesPerSec - approx bps system must handle */
int PaddingGranularity;
int Flags;
/** had idx1 chunk */
#define AVIF_HASINDEX 0x00000010
/** must use idx1 chunk to determine order */
#define AVIF_MUSTUSEINDEX 0x00000020
/** AVI file is interleaved */
#define AVIF_ISINTERLEAVED 0x00000100
#define AVIF_TRUSTCKTYPE 0x00000800
/** specially allocated used for capturing real time video */
#define AVIF_WASCAPTUREFILE 0x00010000
/** contains copyrighted data */
#define AVIF_COPYRIGHTED 0x00020000
int TotalFrames;
int InitialFrames; /* InitialFrames - initial frame before interleaving */
int Streams;
int SuggestedBufferSize;
int Width;
int Height;
int Reserved[4];
} AviMainHeader;
typedef struct _AviStreamHeader {
int fcc;
int size;
int Type;
#define AVIST_VIDEO FCC("vids")
#define AVIST_AUDIO FCC("auds")
#define AVIST_MIDI FCC("mids")
#define AVIST_TEXT FCC("txts")
int Handler;
int Flags;
#define AVISF_DISABLED 0x00000001
#define AVISF_VIDEO_PALCHANGES 0x00010000
short Priority;
short Language;
int InitialFrames;
int Scale;
int Rate;
int Start;
int Length;
int SuggestedBufferSize;
int Quality;
int SampleSize;
short left;
short top;
short right;
short bottom;
} AviStreamHeader;
typedef struct _AviBitmapInfoHeader {
int fcc;
int size;
int Size;
int Width;
int Height;
short Planes;
short BitCount;
int Compression;
int SizeImage;
int XPelsPerMeter;
int YPelsPerMeter;
int ClrUsed;
int ClrImportant;
} AviBitmapInfoHeader;
typedef struct _AviMJPEGUnknown {
int a;
int b;
int c;
int d;
int e;
int f;
int g;
} AviMJPEGUnknown;
typedef struct _AviIndexEntry {
int ChunkId;
int Flags;
#define AVIIF_LIST 0x00000001
#define AVIIF_KEYFRAME 0x00000010
#define AVIIF_NO_TIME 0x00000100
#define AVIIF_COMPRESSOR 0x0FFF0000
int Offset;
int Size;
} AviIndexEntry;
typedef struct _AviIndex {
int fcc;
int size;
AviIndexEntry *entrys;
} AviIndex;
typedef enum {
/** The most basic of forms, 3 bytes per pixel, 1 per r, g, b. */
AVI_FORMAT_RGB24,
/** The second most basic of forms, 4 bytes per pixel, 1 per r, g, b, alpha. */
AVI_FORMAT_RGB32,
/** Same as above, but is in the weird AVI order (bottom to top, left to right). */
AVI_FORMAT_AVI_RGB,
/** Motion-JPEG. */
AVI_FORMAT_MJPEG,
} AviFormat;
typedef struct _AviStreamRec {
AviStreamHeader sh;
void *sf;
int sf_size;
AviFormat format;
} AviStreamRec;
typedef struct _AviMovie {
FILE *fp;
int type;
#define AVI_MOVIE_READ 0
#define AVI_MOVIE_WRITE 1
int64_t size;
AviMainHeader *header;
AviStreamRec *streams;
AviIndexEntry *entries;
int index_entries;
int64_t movi_offset;
int64_t read_offset;
int64_t *offset_table;
/* Local data goes here */
int interlace;
int odd_fields;
} AviMovie;
typedef enum {
AVI_ERROR_NONE = 0,
AVI_ERROR_COMPRESSION,
AVI_ERROR_OPEN,
AVI_ERROR_READING,
AVI_ERROR_WRITING,
AVI_ERROR_FORMAT,
AVI_ERROR_ALLOC,
AVI_ERROR_FOUND,
AVI_ERROR_OPTION,
} AviError;
/* belongs to the option-setting function. */
typedef enum {
AVI_OPTION_WIDTH = 0,
AVI_OPTION_HEIGHT,
AVI_OPTION_QUALITY,
AVI_OPTION_FRAMERATE,
} AviOption;
/* The offsets that will always stay the same in AVI files we
* write... used to seek around to the places where we need to write
* the sizes */
#define AVI_RIFF_SOFF 4L
#define AVI_HDRL_SOFF 16L
/**
* This is a sort of MAKE_ID thing. Used in imbuf :( It is used
* through options in the AVI header (AviStreamHeader). */
#define FCC(ch4) (ch4[0] | ch4[1] << 8 | ch4[2] << 16 | ch4[3] << 24)
/**
* Test whether this is an avi-format.
*/
bool AVI_is_avi(const char *filepath);
/**
* Open a compressed file, decompress it into memory.
*/
AviError AVI_open_compress(const char *filepath, AviMovie *movie, int streams, ...);
/**
* Finalize a compressed output stream.
*/
AviError AVI_close_compress(AviMovie *movie);
/**
* Choose a compression option for \<movie\>. Possible options are
* AVI_OPTION_TYPE_MAIN, AVI_OPTION_TYPE_STRH, AVI_OPTION_TYPE_STRF
*/
AviError AVI_set_compress_option(
AviMovie *movie, int option_type, int stream, AviOption option, void *opt_data);
/* TODO: there should be some explanation about what these mean. */
/**
* Compression option, for use in avi_set_compress_option
*/
#define AVI_OPTION_TYPE_MAIN 0
/**
* Compression option, for use in avi_set_compress_option
*/
#define AVI_OPTION_TYPE_STRH 1
/**
* Compression option, for use in avi_set_compress_option
*/
#define AVI_OPTION_TYPE_STRF 2
/**
* Direct the streams \<avist_type\> to \<movie\>. Redirect \<stream_num\>
* streams.
*/
int AVI_get_stream(AviMovie *movie, int avist_type, int stream_num);
/**
* Open a movie stream from file.
*/
AviError AVI_open_movie(const char *filepath, AviMovie *movie);
/**
* Read a frame from a movie stream.
*/
void *AVI_read_frame(AviMovie *movie, AviFormat format, int frame, int stream);
/**
* Close an open movie stream.
*/
AviError AVI_close(AviMovie *movie);
/**
* Write frames to a movie stream.
*/
AviError AVI_write_frame(AviMovie *movie, int frame_num, ...);
/**
* Unused but still external
*/
AviError AVI_print_error(AviError error);
#ifdef __cplusplus
}
#endif

View File

@@ -1,38 +0,0 @@
# SPDX-FileCopyrightText: 2006 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
set(INC
.
../../imbuf
)
set(INC_SYS
${JPEG_INCLUDE_DIR}
)
set(SRC
intern/avi.cc
intern/avi_codecs.cc
intern/avi_endian.cc
intern/avi_mjpeg.cc
intern/avi_options.cc
intern/avi_rgb.cc
intern/avi_rgb32.cc
AVI_avi.h
intern/avi_endian.h
intern/avi_intern.h
intern/avi_mjpeg.h
intern/avi_rgb.h
intern/avi_rgb32.h
)
set(LIB
${JPEG_LIBRARIES}
PRIVATE bf::blenlib
PRIVATE bf::dna
PRIVATE bf::intern::guardedalloc
)
blender_add_lib(bf_avi "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

View File

@@ -1,1048 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* This is external code.
*/
#include <cctype>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
#include "MEM_guardedalloc.h"
#include "BLI_fileops.h"
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#include "AVI_avi.h"
#include "avi_intern.h"
#include "avi_endian.h"
static int AVI_DEBUG = 0;
static char DEBUG_FCC[4];
#define DEBUG_PRINT(x) \
if (AVI_DEBUG) { \
printf("AVI DEBUG: " x); \
} \
(void)0
/* local functions */
char *fcc_to_char(uint fcc);
char *tcc_to_char(uint tcc);
/* implementation */
uint GET_FCC(FILE *fp)
{
uchar tmp[4];
tmp[0] = getc(fp);
tmp[1] = getc(fp);
tmp[2] = getc(fp);
tmp[3] = getc(fp);
return FCC(tmp);
}
uint GET_TCC(FILE *fp)
{
char tmp[5];
tmp[0] = getc(fp);
tmp[1] = getc(fp);
tmp[2] = 0;
tmp[3] = 0;
return FCC(tmp);
}
char *fcc_to_char(uint fcc)
{
DEBUG_FCC[0] = (fcc) & 127;
DEBUG_FCC[1] = (fcc >> 8) & 127;
DEBUG_FCC[2] = (fcc >> 16) & 127;
DEBUG_FCC[3] = (fcc >> 24) & 127;
return DEBUG_FCC;
}
char *tcc_to_char(uint tcc)
{
DEBUG_FCC[0] = (tcc) & 127;
DEBUG_FCC[1] = (tcc >> 8) & 127;
DEBUG_FCC[2] = 0;
DEBUG_FCC[3] = 0;
return DEBUG_FCC;
}
int AVI_get_stream(AviMovie *movie, int avist_type, int stream_num)
{
int cur_stream;
if (movie == nullptr) {
return -AVI_ERROR_OPTION;
}
for (cur_stream = 0; cur_stream < movie->header->Streams; cur_stream++) {
if (movie->streams[cur_stream].sh.Type == avist_type) {
if (stream_num == 0) {
return cur_stream;
}
stream_num--;
}
}
return -AVI_ERROR_FOUND;
}
static int fcc_get_stream(int fcc)
{
char fccs[4];
fccs[0] = fcc;
fccs[1] = fcc >> 8;
fccs[2] = fcc >> 16;
fccs[3] = fcc >> 24;
return 10 * (fccs[0] - '0') + (fccs[1] - '0');
}
static bool fcc_is_data(int fcc)
{
char fccs[4];
fccs[0] = fcc;
fccs[1] = fcc >> 8;
fccs[2] = fcc >> 16;
fccs[3] = fcc >> 24;
if (!isdigit(fccs[0]) || !isdigit(fccs[1]) || !ELEM(fccs[2], 'd', 'w')) {
return false;
}
if (!ELEM(fccs[3], 'b', 'c')) {
return false;
}
return true;
}
AviError AVI_print_error(AviError in_error)
{
int error;
if (int(in_error) < 0) {
error = -in_error;
}
else {
error = in_error;
}
switch (error) {
case AVI_ERROR_NONE:
break;
case AVI_ERROR_COMPRESSION:
printf("AVI ERROR: compressed in an unsupported format\n");
break;
case AVI_ERROR_OPEN:
printf("AVI ERROR: could not open file\n");
break;
case AVI_ERROR_READING:
printf("AVI ERROR: could not read from file\n");
break;
case AVI_ERROR_WRITING:
printf("AVI ERROR: could not write to file\n");
break;
case AVI_ERROR_FORMAT:
printf("AVI ERROR: file is in an illegal or unrecognized format\n");
break;
case AVI_ERROR_ALLOC:
printf("AVI ERROR: error encountered while allocating memory\n");
break;
case AVI_ERROR_OPTION:
printf("AVI ERROR: program made illegal request\n");
break;
case AVI_ERROR_FOUND:
printf("AVI ERROR: movie did not contain expected item\n");
break;
default:
break;
}
return in_error;
}
bool AVI_is_avi(const char *filepath)
{
int temp, fcca, j;
AviMovie movie = {nullptr};
AviMainHeader header;
AviBitmapInfoHeader bheader;
int movie_tracks = 0;
DEBUG_PRINT("opening movie\n");
movie.type = AVI_MOVIE_READ;
movie.fp = BLI_fopen(filepath, "rb");
movie.offset_table = nullptr;
if (movie.fp == nullptr) {
return false;
}
if (GET_FCC(movie.fp) != FCC("RIFF") || !(movie.size = GET_FCC(movie.fp))) {
fclose(movie.fp);
return false;
}
movie.header = &header;
if (GET_FCC(movie.fp) != FCC("AVI ") || GET_FCC(movie.fp) != FCC("LIST") || !GET_FCC(movie.fp) ||
GET_FCC(movie.fp) != FCC("hdrl") || (movie.header->fcc = GET_FCC(movie.fp)) != FCC("avih") ||
!(movie.header->size = GET_FCC(movie.fp)))
{
DEBUG_PRINT("bad initial header info\n");
fclose(movie.fp);
return false;
}
movie.header->MicroSecPerFrame = GET_FCC(movie.fp);
movie.header->MaxBytesPerSec = GET_FCC(movie.fp);
movie.header->PaddingGranularity = GET_FCC(movie.fp);
movie.header->Flags = GET_FCC(movie.fp);
movie.header->TotalFrames = GET_FCC(movie.fp);
movie.header->InitialFrames = GET_FCC(movie.fp);
movie.header->Streams = GET_FCC(movie.fp);
movie.header->SuggestedBufferSize = GET_FCC(movie.fp);
movie.header->Width = GET_FCC(movie.fp);
movie.header->Height = GET_FCC(movie.fp);
movie.header->Reserved[0] = GET_FCC(movie.fp);
movie.header->Reserved[1] = GET_FCC(movie.fp);
movie.header->Reserved[2] = GET_FCC(movie.fp);
movie.header->Reserved[3] = GET_FCC(movie.fp);
BLI_fseek(movie.fp, movie.header->size - 14 * 4, SEEK_CUR);
/* Limit number of streams to some reasonable amount to prevent
* buffer overflow vulnerabilities. */
if (movie.header->Streams < 1 || movie.header->Streams > 65536) {
DEBUG_PRINT("Number of streams should be in range 1-65536\n");
fclose(movie.fp);
return false;
}
movie.streams = (AviStreamRec *)MEM_calloc_arrayN(
movie.header->Streams, sizeof(AviStreamRec), "moviestreams");
for (temp = 0; temp < movie.header->Streams; temp++) {
if (GET_FCC(movie.fp) != FCC("LIST") || !GET_FCC(movie.fp) ||
GET_FCC(movie.fp) != FCC("strl") ||
(movie.streams[temp].sh.fcc = GET_FCC(movie.fp)) != FCC("strh") ||
!(movie.streams[temp].sh.size = GET_FCC(movie.fp)))
{
DEBUG_PRINT("bad stream header information\n");
MEM_freeN(movie.streams);
fclose(movie.fp);
return false;
}
movie.streams[temp].sh.Type = GET_FCC(movie.fp);
movie.streams[temp].sh.Handler = GET_FCC(movie.fp);
fcca = movie.streams[temp].sh.Handler;
if (movie.streams[temp].sh.Type == FCC("vids")) {
if (fcca == FCC("DIB ") || fcca == FCC("RGB ") || fcca == FCC("rgb ") ||
fcca == FCC("RAW ") || fcca == 0)
{
movie.streams[temp].format = AVI_FORMAT_AVI_RGB;
}
else if (fcca == FCC("mjpg") || fcca == FCC("MJPG")) {
movie.streams[temp].format = AVI_FORMAT_MJPEG;
}
else {
MEM_freeN(movie.streams);
fclose(movie.fp);
return false;
}
movie_tracks++;
}
movie.streams[temp].sh.Flags = GET_FCC(movie.fp);
movie.streams[temp].sh.Priority = GET_TCC(movie.fp);
movie.streams[temp].sh.Language = GET_TCC(movie.fp);
movie.streams[temp].sh.InitialFrames = GET_FCC(movie.fp);
movie.streams[temp].sh.Scale = GET_FCC(movie.fp);
movie.streams[temp].sh.Rate = GET_FCC(movie.fp);
movie.streams[temp].sh.Start = GET_FCC(movie.fp);
movie.streams[temp].sh.Length = GET_FCC(movie.fp);
movie.streams[temp].sh.SuggestedBufferSize = GET_FCC(movie.fp);
movie.streams[temp].sh.Quality = GET_FCC(movie.fp);
movie.streams[temp].sh.SampleSize = GET_FCC(movie.fp);
movie.streams[temp].sh.left = GET_TCC(movie.fp);
movie.streams[temp].sh.top = GET_TCC(movie.fp);
movie.streams[temp].sh.right = GET_TCC(movie.fp);
movie.streams[temp].sh.bottom = GET_TCC(movie.fp);
BLI_fseek(movie.fp, movie.streams[temp].sh.size - 14 * 4, SEEK_CUR);
if (GET_FCC(movie.fp) != FCC("strf")) {
DEBUG_PRINT("no stream format information\n");
MEM_freeN(movie.streams);
fclose(movie.fp);
return false;
}
movie.streams[temp].sf_size = GET_FCC(movie.fp);
if (movie.streams[temp].sh.Type == FCC("vids")) {
j = movie.streams[temp].sf_size - (sizeof(AviBitmapInfoHeader) - 8);
if (j >= 0) {
AviBitmapInfoHeader *bi;
movie.streams[temp].sf = &bheader;
bi = (AviBitmapInfoHeader *)movie.streams[temp].sf;
bi->fcc = FCC("strf");
bi->size = movie.streams[temp].sf_size;
bi->Size = GET_FCC(movie.fp);
bi->Width = GET_FCC(movie.fp);
bi->Height = GET_FCC(movie.fp);
bi->Planes = GET_TCC(movie.fp);
bi->BitCount = GET_TCC(movie.fp);
bi->Compression = GET_FCC(movie.fp);
bi->SizeImage = GET_FCC(movie.fp);
bi->XPelsPerMeter = GET_FCC(movie.fp);
bi->YPelsPerMeter = GET_FCC(movie.fp);
bi->ClrUsed = GET_FCC(movie.fp);
bi->ClrImportant = GET_FCC(movie.fp);
fcca = bi->Compression;
if (movie.streams[temp].format == AVI_FORMAT_AVI_RGB) {
if (fcca == FCC("DIB ") || fcca == FCC("RGB ") || fcca == FCC("rgb ") ||
fcca == FCC("RAW ") || fcca == 0)
{
/* pass */
}
else if (fcca == FCC("mjpg") || fcca == FCC("MJPG")) {
movie.streams[temp].format = AVI_FORMAT_MJPEG;
}
else {
MEM_freeN(movie.streams);
fclose(movie.fp);
return false;
}
}
}
if (j > 0) {
BLI_fseek(movie.fp, j, SEEK_CUR);
}
}
else {
BLI_fseek(movie.fp, movie.streams[temp].sf_size, SEEK_CUR);
}
/* Walk to the next LIST */
while (GET_FCC(movie.fp) != FCC("LIST")) {
temp = GET_FCC(movie.fp);
if (temp < 0 || BLI_ftell(movie.fp) > movie.size) {
DEBUG_PRINT("incorrect size in header or error in AVI\n");
MEM_freeN(movie.streams);
fclose(movie.fp);
return false;
}
BLI_fseek(movie.fp, temp, SEEK_CUR);
}
BLI_fseek(movie.fp, -4L, SEEK_CUR);
}
MEM_freeN(movie.streams);
fclose(movie.fp);
/* at least one video track is needed */
return (movie_tracks != 0);
}
AviError AVI_open_movie(const char *filepath, AviMovie *movie)
{
int temp, fcca, size, j;
DEBUG_PRINT("opening movie\n");
memset(movie, 0, sizeof(AviMovie));
movie->type = AVI_MOVIE_READ;
movie->fp = BLI_fopen(filepath, "rb");
movie->offset_table = nullptr;
if (movie->fp == nullptr) {
return AVI_ERROR_OPEN;
}
if (GET_FCC(movie->fp) != FCC("RIFF") || !(movie->size = GET_FCC(movie->fp))) {
return AVI_ERROR_FORMAT;
}
movie->header = (AviMainHeader *)MEM_mallocN(sizeof(AviMainHeader), "movieheader");
if (GET_FCC(movie->fp) != FCC("AVI ") || GET_FCC(movie->fp) != FCC("LIST") ||
!GET_FCC(movie->fp) || GET_FCC(movie->fp) != FCC("hdrl") ||
(movie->header->fcc = GET_FCC(movie->fp)) != FCC("avih") ||
!(movie->header->size = GET_FCC(movie->fp)))
{
DEBUG_PRINT("bad initial header info\n");
return AVI_ERROR_FORMAT;
}
movie->header->MicroSecPerFrame = GET_FCC(movie->fp);
movie->header->MaxBytesPerSec = GET_FCC(movie->fp);
movie->header->PaddingGranularity = GET_FCC(movie->fp);
movie->header->Flags = GET_FCC(movie->fp);
movie->header->TotalFrames = GET_FCC(movie->fp);
movie->header->InitialFrames = GET_FCC(movie->fp);
movie->header->Streams = GET_FCC(movie->fp);
movie->header->SuggestedBufferSize = GET_FCC(movie->fp);
movie->header->Width = GET_FCC(movie->fp);
movie->header->Height = GET_FCC(movie->fp);
movie->header->Reserved[0] = GET_FCC(movie->fp);
movie->header->Reserved[1] = GET_FCC(movie->fp);
movie->header->Reserved[2] = GET_FCC(movie->fp);
movie->header->Reserved[3] = GET_FCC(movie->fp);
BLI_fseek(movie->fp, movie->header->size - 14 * 4, SEEK_CUR);
/* Limit number of streams to some reasonable amount to prevent
* buffer overflow vulnerabilities. */
if (movie->header->Streams < 1 || movie->header->Streams > 65536) {
DEBUG_PRINT("Number of streams should be in range 1-65536\n");
return AVI_ERROR_FORMAT;
}
movie->streams = (AviStreamRec *)MEM_calloc_arrayN(
movie->header->Streams, sizeof(AviStreamRec), "moviestreams");
for (temp = 0; temp < movie->header->Streams; temp++) {
if (GET_FCC(movie->fp) != FCC("LIST") || !GET_FCC(movie->fp) ||
GET_FCC(movie->fp) != FCC("strl") ||
(movie->streams[temp].sh.fcc = GET_FCC(movie->fp)) != FCC("strh") ||
!(movie->streams[temp].sh.size = GET_FCC(movie->fp)))
{
DEBUG_PRINT("bad stream header information\n");
return AVI_ERROR_FORMAT;
}
movie->streams[temp].sh.Type = GET_FCC(movie->fp);
movie->streams[temp].sh.Handler = GET_FCC(movie->fp);
fcca = movie->streams[temp].sh.Handler;
if (movie->streams[temp].sh.Type == FCC("vids")) {
if (fcca == FCC("DIB ") || fcca == FCC("RGB ") || fcca == FCC("rgb ") ||
fcca == FCC("RAW ") || fcca == 0)
{
movie->streams[temp].format = AVI_FORMAT_AVI_RGB;
}
else if (fcca == FCC("mjpg") || fcca == FCC("MJPG")) {
movie->streams[temp].format = AVI_FORMAT_MJPEG;
}
else {
return AVI_ERROR_COMPRESSION;
}
}
movie->streams[temp].sh.Flags = GET_FCC(movie->fp);
movie->streams[temp].sh.Priority = GET_TCC(movie->fp);
movie->streams[temp].sh.Language = GET_TCC(movie->fp);
movie->streams[temp].sh.InitialFrames = GET_FCC(movie->fp);
movie->streams[temp].sh.Scale = GET_FCC(movie->fp);
movie->streams[temp].sh.Rate = GET_FCC(movie->fp);
movie->streams[temp].sh.Start = GET_FCC(movie->fp);
movie->streams[temp].sh.Length = GET_FCC(movie->fp);
movie->streams[temp].sh.SuggestedBufferSize = GET_FCC(movie->fp);
movie->streams[temp].sh.Quality = GET_FCC(movie->fp);
movie->streams[temp].sh.SampleSize = GET_FCC(movie->fp);
movie->streams[temp].sh.left = GET_TCC(movie->fp);
movie->streams[temp].sh.top = GET_TCC(movie->fp);
movie->streams[temp].sh.right = GET_TCC(movie->fp);
movie->streams[temp].sh.bottom = GET_TCC(movie->fp);
BLI_fseek(movie->fp, movie->streams[temp].sh.size - 14 * 4, SEEK_CUR);
if (GET_FCC(movie->fp) != FCC("strf")) {
DEBUG_PRINT("no stream format information\n");
return AVI_ERROR_FORMAT;
}
movie->streams[temp].sf_size = GET_FCC(movie->fp);
if (movie->streams[temp].sh.Type == FCC("vids")) {
j = movie->streams[temp].sf_size - (sizeof(AviBitmapInfoHeader) - 8);
if (j >= 0) {
AviBitmapInfoHeader *bi;
movie->streams[temp].sf = MEM_mallocN(sizeof(AviBitmapInfoHeader), "streamformat");
bi = (AviBitmapInfoHeader *)movie->streams[temp].sf;
bi->fcc = FCC("strf");
bi->size = movie->streams[temp].sf_size;
bi->Size = GET_FCC(movie->fp);
bi->Width = GET_FCC(movie->fp);
bi->Height = GET_FCC(movie->fp);
bi->Planes = GET_TCC(movie->fp);
bi->BitCount = GET_TCC(movie->fp);
bi->Compression = GET_FCC(movie->fp);
bi->SizeImage = GET_FCC(movie->fp);
bi->XPelsPerMeter = GET_FCC(movie->fp);
bi->YPelsPerMeter = GET_FCC(movie->fp);
bi->ClrUsed = GET_FCC(movie->fp);
bi->ClrImportant = GET_FCC(movie->fp);
fcca = bi->Compression;
if (movie->streams[temp].format == AVI_FORMAT_AVI_RGB) {
if (fcca == FCC("DIB ") || fcca == FCC("RGB ") || fcca == FCC("rgb ") ||
fcca == FCC("RAW ") || fcca == 0)
{
/* pass */
}
else if (fcca == FCC("mjpg") || fcca == FCC("MJPG")) {
movie->streams[temp].format = AVI_FORMAT_MJPEG;
}
else {
return AVI_ERROR_COMPRESSION;
}
}
}
if (j > 0) {
BLI_fseek(movie->fp, j, SEEK_CUR);
}
}
else {
BLI_fseek(movie->fp, movie->streams[temp].sf_size, SEEK_CUR);
}
/* Walk to the next LIST */
while (GET_FCC(movie->fp) != FCC("LIST")) {
temp = GET_FCC(movie->fp);
if (temp < 0 || BLI_ftell(movie->fp) > movie->size) {
DEBUG_PRINT("incorrect size in header or error in AVI\n");
return AVI_ERROR_FORMAT;
}
BLI_fseek(movie->fp, temp, SEEK_CUR);
}
BLI_fseek(movie->fp, -4L, SEEK_CUR);
}
while (true) {
temp = GET_FCC(movie->fp);
size = GET_FCC(movie->fp);
if (size == 0) {
break;
}
if (temp == FCC("LIST")) {
if (GET_FCC(movie->fp) == FCC("movi")) {
break;
}
BLI_fseek(movie->fp, size - 4, SEEK_CUR);
}
else {
BLI_fseek(movie->fp, size, SEEK_CUR);
}
if (BLI_ftell(movie->fp) > movie->size) {
DEBUG_PRINT("incorrect size in header or error in AVI\n");
return AVI_ERROR_FORMAT;
}
}
movie->movi_offset = BLI_ftell(movie->fp);
movie->read_offset = movie->movi_offset;
/* Read in the index if the file has one, otherwise create one */
if (movie->header->Flags & AVIF_HASINDEX) {
BLI_fseek(movie->fp, size - 4, SEEK_CUR);
if (GET_FCC(movie->fp) != FCC("idx1")) {
DEBUG_PRINT("bad index information\n");
return AVI_ERROR_FORMAT;
}
movie->index_entries = GET_FCC(movie->fp) / sizeof(AviIndexEntry);
if (movie->index_entries == 0) {
DEBUG_PRINT("no index entries\n");
return AVI_ERROR_FORMAT;
}
movie->entries = (AviIndexEntry *)MEM_mallocN(movie->index_entries * sizeof(AviIndexEntry),
"movieentries");
for (temp = 0; temp < movie->index_entries; temp++) {
movie->entries[temp].ChunkId = GET_FCC(movie->fp);
movie->entries[temp].Flags = GET_FCC(movie->fp);
movie->entries[temp].Offset = GET_FCC(movie->fp);
movie->entries[temp].Size = GET_FCC(movie->fp);
if (AVI_DEBUG) {
printf("Index entry %04d: ChunkId:%s Flags:%d Offset:%d Size:%d\n",
temp,
fcc_to_char(movie->entries[temp].ChunkId),
movie->entries[temp].Flags,
movie->entries[temp].Offset,
movie->entries[temp].Size);
}
}
/* Some AVI's have offset entries in absolute coordinates
* instead of an offset from the movie beginning... this is...
* wacky, but we need to handle it. The wacky offset always
* starts at movi_offset it seems... so we'll check that.
* Note the offset needs an extra 4 bytes for some
* undetermined reason */
if (movie->entries[0].Offset == movie->movi_offset) {
movie->read_offset = 4;
}
}
DEBUG_PRINT("movie successfully opened\n");
return AVI_ERROR_NONE;
}
void *AVI_read_frame(AviMovie *movie, AviFormat format, int frame, int stream)
{
int cur_frame = -1, i = 0, rewind = 1;
void *buffer;
/* Retrieve the record number of the desired frame in the index
* If a chunk has Size 0 we need to rewind to previous frame */
while (rewind && frame > -1) {
i = 0;
cur_frame = -1;
rewind = 0;
while (cur_frame < frame && i < movie->index_entries) {
if (fcc_is_data(movie->entries[i].ChunkId) &&
fcc_get_stream(movie->entries[i].ChunkId) == stream)
{
if ((cur_frame == frame - 1) && (movie->entries[i].Size == 0)) {
rewind = 1;
frame = frame - 1;
}
else {
cur_frame++;
}
}
i++;
}
}
if (cur_frame != frame) {
return nullptr;
}
BLI_fseek(movie->fp, movie->read_offset + movie->entries[i - 1].Offset, SEEK_SET);
size_t size = GET_FCC(movie->fp);
buffer = MEM_mallocN(size, "readbuffer");
if (fread(buffer, 1, size, movie->fp) != size) {
MEM_freeN(buffer);
return nullptr;
}
buffer = avi_format_convert(movie, stream, buffer, movie->streams[stream].format, format, &size);
return buffer;
}
AviError AVI_close(AviMovie *movie)
{
int i;
fclose(movie->fp);
for (i = 0; i < movie->header->Streams; i++) {
if (movie->streams[i].sf != nullptr) {
MEM_freeN(movie->streams[i].sf);
}
}
MEM_freeN(movie->header);
MEM_freeN(movie->streams);
if (movie->entries != nullptr) {
MEM_freeN(movie->entries);
}
if (movie->offset_table != nullptr) {
MEM_freeN(movie->offset_table);
}
return AVI_ERROR_NONE;
}
AviError AVI_open_compress(const char *filepath, AviMovie *movie, int streams, ...)
{
va_list ap;
AviList list;
AviChunk chunk;
int i;
int64_t header_pos1, header_pos2;
int64_t stream_pos1, stream_pos2;
int64_t junk_pos;
movie->type = AVI_MOVIE_WRITE;
movie->fp = BLI_fopen(filepath, "wb");
movie->index_entries = 0;
if (movie->fp == nullptr) {
return AVI_ERROR_OPEN;
}
movie->offset_table = (int64_t *)MEM_mallocN((1 + streams * 2) * sizeof(int64_t), "offsettable");
for (i = 0; i < 1 + streams * 2; i++) {
movie->offset_table[i] = -1L;
}
movie->entries = nullptr;
movie->header = (AviMainHeader *)MEM_mallocN(sizeof(AviMainHeader), "movieheader");
movie->header->fcc = FCC("avih");
movie->header->size = 56;
movie->header->MicroSecPerFrame = 66667;
movie->header->MaxBytesPerSec = 0;
movie->header->PaddingGranularity = 0;
movie->header->Flags = AVIF_HASINDEX | AVIF_MUSTUSEINDEX;
movie->header->TotalFrames = 0;
movie->header->InitialFrames = 0;
movie->header->Streams = streams;
movie->header->SuggestedBufferSize = 0;
movie->header->Width = 0;
movie->header->Height = 0;
movie->header->Reserved[0] = 0;
movie->header->Reserved[1] = 0;
movie->header->Reserved[2] = 0;
movie->header->Reserved[3] = 0;
/* Limit number of streams to some reasonable amount to prevent
* buffer overflow vulnerabilities. */
if (movie->header->Streams < 0 || movie->header->Streams > 65536) {
DEBUG_PRINT("Number of streams should be in range 0-65536\n");
return AVI_ERROR_FORMAT;
}
movie->streams = (AviStreamRec *)MEM_mallocN(sizeof(AviStreamRec) * movie->header->Streams,
"moviestreams");
va_start(ap, streams);
for (i = 0; i < movie->header->Streams; i++) {
movie->streams[i].format = AviFormat(va_arg(ap, int));
movie->streams[i].sh.fcc = FCC("strh");
movie->streams[i].sh.size = 56;
movie->streams[i].sh.Type = avi_get_format_type(movie->streams[i].format);
if (movie->streams[i].sh.Type == 0) {
va_end(ap);
return AVI_ERROR_FORMAT;
}
movie->streams[i].sh.Handler = avi_get_format_fcc(movie->streams[i].format);
if (movie->streams[i].sh.Handler == 0) {
va_end(ap);
return AVI_ERROR_FORMAT;
}
movie->streams[i].sh.Flags = 0;
movie->streams[i].sh.Priority = 0;
movie->streams[i].sh.Language = 0;
movie->streams[i].sh.InitialFrames = 0;
movie->streams[i].sh.Scale = 66667;
movie->streams[i].sh.Rate = 1000000;
movie->streams[i].sh.Start = 0;
movie->streams[i].sh.Length = 0;
movie->streams[i].sh.SuggestedBufferSize = 0;
movie->streams[i].sh.Quality = 10000;
movie->streams[i].sh.SampleSize = 0;
movie->streams[i].sh.left = 0;
movie->streams[i].sh.top = 0;
movie->streams[i].sh.right = 0;
movie->streams[i].sh.bottom = 0;
if (movie->streams[i].sh.Type == FCC("vids")) {
movie->streams[i].sf = MEM_mallocN(sizeof(AviBitmapInfoHeader), "moviestreamformatS");
movie->streams[i].sf_size = sizeof(AviBitmapInfoHeader);
((AviBitmapInfoHeader *)movie->streams[i].sf)->fcc = FCC("strf");
((AviBitmapInfoHeader *)movie->streams[i].sf)->size = movie->streams[i].sf_size - 8;
((AviBitmapInfoHeader *)movie->streams[i].sf)->Size = movie->streams[i].sf_size - 8;
((AviBitmapInfoHeader *)movie->streams[i].sf)->Width = 0;
((AviBitmapInfoHeader *)movie->streams[i].sf)->Height = 0;
((AviBitmapInfoHeader *)movie->streams[i].sf)->Planes = 1;
((AviBitmapInfoHeader *)movie->streams[i].sf)->BitCount = 24;
((AviBitmapInfoHeader *)movie->streams[i].sf)->Compression = avi_get_format_compression(
movie->streams[i].format);
((AviBitmapInfoHeader *)movie->streams[i].sf)->SizeImage = 0;
((AviBitmapInfoHeader *)movie->streams[i].sf)->XPelsPerMeter = 0;
((AviBitmapInfoHeader *)movie->streams[i].sf)->YPelsPerMeter = 0;
((AviBitmapInfoHeader *)movie->streams[i].sf)->ClrUsed = 0;
((AviBitmapInfoHeader *)movie->streams[i].sf)->ClrImportant = 0;
}
}
list.fcc = FCC("RIFF");
list.size = 0;
list.ids = FCC("AVI ");
awrite(movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
list.fcc = FCC("LIST");
list.size = 0;
list.ids = FCC("hdrl");
awrite(movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
header_pos1 = BLI_ftell(movie->fp);
movie->offset_table[0] = BLI_ftell(movie->fp);
awrite(movie, movie->header, 1, sizeof(AviMainHeader), movie->fp, AVI_MAINH);
for (i = 0; i < movie->header->Streams; i++) {
list.fcc = FCC("LIST");
list.size = 0;
list.ids = FCC("strl");
awrite(movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
stream_pos1 = BLI_ftell(movie->fp);
movie->offset_table[1 + i * 2] = BLI_ftell(movie->fp);
awrite(movie, &movie->streams[i].sh, 1, sizeof(AviStreamHeader), movie->fp, AVI_STREAMH);
movie->offset_table[1 + i * 2 + 1] = BLI_ftell(movie->fp);
awrite(movie, movie->streams[i].sf, 1, movie->streams[i].sf_size, movie->fp, AVI_BITMAPH);
stream_pos2 = BLI_ftell(movie->fp);
BLI_fseek(movie->fp, stream_pos1 - 8, SEEK_SET);
PUT_FCCN((stream_pos2 - stream_pos1 + 4L), movie->fp);
BLI_fseek(movie->fp, stream_pos2, SEEK_SET);
}
junk_pos = BLI_ftell(movie->fp);
if (junk_pos < 2024 - 8) {
chunk.fcc = FCC("JUNK");
chunk.size = 2024 - 8 - int(junk_pos);
awrite(movie, &chunk, 1, sizeof(AviChunk), movie->fp, AVI_CHUNK);
for (i = 0; i < chunk.size; i++) {
putc(0, movie->fp);
}
}
header_pos2 = BLI_ftell(movie->fp);
list.fcc = FCC("LIST");
list.size = 0;
list.ids = FCC("movi");
awrite(movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
movie->movi_offset = BLI_ftell(movie->fp) - 8L;
BLI_fseek(movie->fp, AVI_HDRL_SOFF, SEEK_SET);
PUT_FCCN((header_pos2 - header_pos1 + 4L), movie->fp);
va_end(ap);
return AVI_ERROR_NONE;
}
AviError AVI_write_frame(AviMovie *movie, int frame_num, ...)
{
AviList list;
AviChunk chunk;
va_list ap;
int stream;
int64_t rec_off;
AviFormat format;
void *buffer;
if (frame_num < 0) {
return AVI_ERROR_OPTION;
}
/* Allocate the new memory for the index entry */
if (frame_num >= movie->index_entries) {
const size_t entry_size = (movie->header->Streams + 1) * sizeof(AviIndexEntry);
movie->entries = (AviIndexEntry *)MEM_recallocN(movie->entries, (frame_num + 1) * entry_size);
movie->index_entries = frame_num + 1;
}
/* Slap a new record entry onto the end of the file */
BLI_fseek(movie->fp, 0L, SEEK_END);
list.fcc = FCC("LIST");
list.size = 0;
list.ids = FCC("rec ");
awrite(movie, &list, 1, sizeof(AviList), movie->fp, AVI_LIST);
rec_off = BLI_ftell(movie->fp) - 8L;
/* Write a frame for every stream */
va_start(ap, frame_num);
for (stream = 0; stream < movie->header->Streams; stream++) {
uint tbuf = 0;
format = AviFormat(va_arg(ap, int));
buffer = va_arg(ap, void *);
size_t size = va_arg(ap, int);
/* Convert the buffer into the output format */
buffer = avi_format_convert(
movie, stream, buffer, format, movie->streams[stream].format, &size);
/* Write the header info for this data chunk */
BLI_fseek(movie->fp, 0L, SEEK_END);
chunk.fcc = avi_get_data_id(format, stream);
chunk.size = size;
if (size % 4) {
chunk.size += 4 - size % 4;
}
awrite(movie, &chunk, 1, sizeof(AviChunk), movie->fp, AVI_CHUNK);
/* Write the index entry for this data chunk */
movie->entries[frame_num * (movie->header->Streams + 1) + stream + 1].ChunkId = chunk.fcc;
movie->entries[frame_num * (movie->header->Streams + 1) + stream + 1].Flags = AVIIF_KEYFRAME;
movie->entries[frame_num * (movie->header->Streams + 1) + stream + 1].Offset = int(
BLI_ftell(movie->fp) - 12L - movie->movi_offset);
movie->entries[frame_num * (movie->header->Streams + 1) + stream + 1].Size = chunk.size;
/* Write the chunk */
awrite(movie, buffer, 1, size, movie->fp, AVI_RAW);
MEM_freeN(buffer);
if (size % 4) {
awrite(movie, &tbuf, 1, 4 - size % 4, movie->fp, AVI_RAW);
}
/* Update the stream headers length field */
movie->streams[stream].sh.Length++;
BLI_fseek(movie->fp, movie->offset_table[1 + stream * 2], SEEK_SET);
awrite(movie, &movie->streams[stream].sh, 1, sizeof(AviStreamHeader), movie->fp, AVI_STREAMH);
}
va_end(ap);
/* Record the entry for the new record */
BLI_fseek(movie->fp, 0L, SEEK_END);
movie->entries[frame_num * (movie->header->Streams + 1)].ChunkId = FCC("rec ");
movie->entries[frame_num * (movie->header->Streams + 1)].Flags = AVIIF_LIST;
movie->entries[frame_num * (movie->header->Streams + 1)].Offset = int(rec_off - 8L -
movie->movi_offset);
movie->entries[frame_num * (movie->header->Streams + 1)].Size = int(BLI_ftell(movie->fp) -
(rec_off + 4L));
/* Update the record size */
BLI_fseek(movie->fp, rec_off, SEEK_SET);
PUT_FCCN(movie->entries[frame_num * (movie->header->Streams + 1)].Size, movie->fp);
/* Update the main header information in the file */
movie->header->TotalFrames++;
BLI_fseek(movie->fp, movie->offset_table[0], SEEK_SET);
awrite(movie, movie->header, 1, sizeof(AviMainHeader), movie->fp, AVI_MAINH);
return AVI_ERROR_NONE;
}
AviError AVI_close_compress(AviMovie *movie)
{
int temp, movi_size, i;
if (movie->fp == nullptr) {
/* none of the allocations below were done if the file failed to open */
return AVI_ERROR_FOUND;
}
BLI_fseek(movie->fp, 0L, SEEK_END);
movi_size = int(BLI_ftell(movie->fp));
PUT_FCC("idx1", movie->fp);
PUT_FCCN((movie->index_entries * (movie->header->Streams + 1) * 16), movie->fp);
for (temp = 0; temp < movie->index_entries * (movie->header->Streams + 1); temp++) {
awrite(movie, &movie->entries[temp], 1, sizeof(AviIndexEntry), movie->fp, AVI_INDEXE);
}
temp = int(BLI_ftell(movie->fp));
BLI_fseek(movie->fp, AVI_RIFF_SOFF, SEEK_SET);
PUT_FCCN((temp - 8L), movie->fp);
BLI_fseek(movie->fp, movie->movi_offset, SEEK_SET);
PUT_FCCN((movi_size - (movie->movi_offset + 4L)), movie->fp);
fclose(movie->fp);
for (i = 0; i < movie->header->Streams; i++) {
if (movie->streams && (movie->streams[i].sf != nullptr)) {
MEM_freeN(movie->streams[i].sf);
}
}
MEM_freeN(movie->header);
if (movie->entries != nullptr) {
MEM_freeN(movie->entries);
}
if (movie->streams != nullptr) {
MEM_freeN(movie->streams);
}
if (movie->offset_table != nullptr) {
MEM_freeN(movie->offset_table);
}
return AVI_ERROR_NONE;
}

View File

@@ -1,125 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* This is external code. Identify and convert different avi-files.
*/
#include "AVI_avi.h"
#include "avi_intern.h"
#include "avi_mjpeg.h"
#include "avi_rgb.h"
#include "avi_rgb32.h"
#include "BLI_string.h"
void *avi_format_convert(
AviMovie *movie, int stream, void *buffer, AviFormat from, AviFormat to, size_t *size)
{
if (from == to) {
return buffer;
}
if (from != AVI_FORMAT_RGB24 && to != AVI_FORMAT_RGB24) {
return avi_format_convert(
movie,
stream,
avi_format_convert(movie, stream, buffer, from, AVI_FORMAT_RGB24, size),
AVI_FORMAT_RGB24,
to,
size);
}
switch (to) {
case AVI_FORMAT_RGB24:
switch (from) {
case AVI_FORMAT_AVI_RGB:
buffer = avi_converter_from_avi_rgb(movie, stream, static_cast<uchar *>(buffer), size);
break;
case AVI_FORMAT_MJPEG:
buffer = avi_converter_from_mjpeg(movie, stream, static_cast<uchar *>(buffer), size);
break;
case AVI_FORMAT_RGB32:
buffer = avi_converter_from_rgb32(movie, stream, static_cast<uchar *>(buffer), size);
break;
default:
break;
}
break;
case AVI_FORMAT_AVI_RGB:
buffer = avi_converter_to_avi_rgb(movie, stream, static_cast<uchar *>(buffer), size);
break;
case AVI_FORMAT_MJPEG:
buffer = avi_converter_to_mjpeg(movie, stream, static_cast<uchar *>(buffer), size);
break;
case AVI_FORMAT_RGB32:
buffer = avi_converter_to_rgb32(movie, stream, static_cast<uchar *>(buffer), size);
break;
default:
break;
}
return buffer;
}
int avi_get_data_id(AviFormat format, int stream)
{
char fcc[5];
if (avi_get_format_type(format) == FCC("vids")) {
SNPRINTF(fcc, "%2.2ddc", stream);
}
else if (avi_get_format_type(format) == FCC("auds")) {
SNPRINTF(fcc, "%2.2ddc", stream);
}
else {
return 0;
}
return FCC(fcc);
}
int avi_get_format_type(AviFormat format)
{
switch (format) {
case AVI_FORMAT_RGB24:
case AVI_FORMAT_RGB32:
case AVI_FORMAT_AVI_RGB:
case AVI_FORMAT_MJPEG:
return FCC("vids");
default:
return 0;
}
}
int avi_get_format_fcc(AviFormat format)
{
switch (format) {
case AVI_FORMAT_RGB24:
case AVI_FORMAT_RGB32:
case AVI_FORMAT_AVI_RGB:
return FCC("DIB ");
case AVI_FORMAT_MJPEG:
return FCC("MJPG");
default:
return 0;
}
}
int avi_get_format_compression(AviFormat format)
{
switch (format) {
case AVI_FORMAT_RGB24:
case AVI_FORMAT_RGB32:
case AVI_FORMAT_AVI_RGB:
return 0;
case AVI_FORMAT_MJPEG:
return FCC("MJPG");
default:
return 0;
}
}

View File

@@ -1,188 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* This is external code. Streams bytes to output depending on the
* endianness of the system.
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "AVI_avi.h"
#include "avi_endian.h"
#include "avi_intern.h"
#ifdef __BIG_ENDIAN__
# include "MEM_guardedalloc.h"
#endif
#ifdef __BIG_ENDIAN__
/* copied from BLI_endian_switch_inline.h */
static void invert(int *val)
{
int tval = *val;
*val = (tval >> 24) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | (tval << 24);
}
static void sinvert(short int *val)
{
short tval = *val;
*val = (tval >> 8) | (tval << 8);
}
static void Ichunk(AviChunk *chunk)
{
invert(&chunk->fcc);
invert(&chunk->size);
}
#endif
#ifdef __BIG_ENDIAN__
static void Ilist(AviList *list)
{
invert(&list->fcc);
invert(&list->size);
invert(&list->ids);
}
static void Imainh(AviMainHeader *mainh)
{
invert(&mainh->fcc);
invert(&mainh->size);
invert(&mainh->MicroSecPerFrame);
invert(&mainh->MaxBytesPerSec);
invert(&mainh->PaddingGranularity);
invert(&mainh->Flags);
invert(&mainh->TotalFrames);
invert(&mainh->InitialFrames);
invert(&mainh->Streams);
invert(&mainh->SuggestedBufferSize);
invert(&mainh->Width);
invert(&mainh->Height);
invert(&mainh->Reserved[0]);
invert(&mainh->Reserved[1]);
invert(&mainh->Reserved[2]);
invert(&mainh->Reserved[3]);
}
static void Istreamh(AviStreamHeader *streamh)
{
invert(&streamh->fcc);
invert(&streamh->size);
invert(&streamh->Type);
invert(&streamh->Handler);
invert(&streamh->Flags);
sinvert(&streamh->Priority);
sinvert(&streamh->Language);
invert(&streamh->InitialFrames);
invert(&streamh->Scale);
invert(&streamh->Rate);
invert(&streamh->Start);
invert(&streamh->Length);
invert(&streamh->SuggestedBufferSize);
invert(&streamh->Quality);
invert(&streamh->SampleSize);
sinvert(&streamh->left);
sinvert(&streamh->right);
sinvert(&streamh->top);
sinvert(&streamh->bottom);
}
static void Ibitmaph(AviBitmapInfoHeader *bitmaph)
{
invert(&bitmaph->fcc);
invert(&bitmaph->size);
invert(&bitmaph->Size);
invert(&bitmaph->Width);
invert(&bitmaph->Height);
sinvert(&bitmaph->Planes);
sinvert(&bitmaph->BitCount);
invert(&bitmaph->Compression);
invert(&bitmaph->SizeImage);
invert(&bitmaph->XPelsPerMeter);
invert(&bitmaph->YPelsPerMeter);
invert(&bitmaph->ClrUsed);
invert(&bitmaph->ClrImportant);
}
static void Imjpegu(AviMJPEGUnknown *mjpgu)
{
invert(&mjpgu->a);
invert(&mjpgu->b);
invert(&mjpgu->c);
invert(&mjpgu->d);
invert(&mjpgu->e);
invert(&mjpgu->f);
invert(&mjpgu->g);
}
static void Iindexe(AviIndexEntry *indexe)
{
invert(&indexe->ChunkId);
invert(&indexe->Flags);
invert(&indexe->Offset);
invert(&indexe->Size);
}
#endif /* __BIG_ENDIAN__ */
void awrite(AviMovie *movie, const void *datain, int block, int size, FILE *fp, int type)
{
#ifdef __BIG_ENDIAN__
void *data;
data = MEM_mallocN(size, "avi endian");
memcpy(data, datain, size);
switch (type) {
case AVI_RAW:
fwrite(data, block, size, fp);
break;
case AVI_CHUNK:
Ichunk((AviChunk *)data);
fwrite(data, block, size, fp);
break;
case AVI_LIST:
Ilist((AviList *)data);
fwrite(data, block, size, fp);
break;
case AVI_MAINH:
Imainh((AviMainHeader *)data);
fwrite(data, block, size, fp);
break;
case AVI_STREAMH:
Istreamh((AviStreamHeader *)data);
fwrite(data, block, size, fp);
break;
case AVI_BITMAPH:
Ibitmaph((AviBitmapInfoHeader *)data);
if (size == sizeof(AviBitmapInfoHeader) + sizeof(AviMJPEGUnknown)) {
Imjpegu((AviMJPEGUnknown *)((char *)data + sizeof(AviBitmapInfoHeader)));
}
fwrite(data, block, size, fp);
break;
case AVI_MJPEGU:
Imjpegu((AviMJPEGUnknown *)data);
fwrite(data, block, size, fp);
break;
case AVI_INDEXE:
Iindexe((AviIndexEntry *)data);
fwrite(data, block, size, fp);
break;
default:
break;
}
MEM_freeN(data);
#else /* __BIG_ENDIAN__ */
(void)movie; /* unused */
(void)type; /* unused */
fwrite(datain, block, size, fp);
#endif /* __BIG_ENDIAN__ */
}

View File

@@ -1,30 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* This is external code.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define AVI_RAW 0
#define AVI_CHUNK 1
#define AVI_LIST 2
#define AVI_MAINH 3
#define AVI_STREAMH 4
#define AVI_BITMAPH 5
#define AVI_INDEXE 6
#define AVI_MJPEGU 7
void awrite(AviMovie *movie, const void *datain, int block, int size, FILE *fp, int type);
#ifdef __cplusplus
}
#endif

View File

@@ -1,55 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*/
#pragma once
#include <stdio.h> /* for FILE */
#ifdef __cplusplus
extern "C" {
#endif
unsigned int GET_FCC(FILE *fp);
unsigned int GET_TCC(FILE *fp);
#define PUT_FCC(ch4, fp) \
{ \
putc(ch4[0], fp); \
putc(ch4[1], fp); \
putc(ch4[2], fp); \
putc(ch4[3], fp); \
} \
(void)0
#define PUT_FCCN(num, fp) \
{ \
putc((num >> 0) & 0377, fp); \
putc((num >> 8) & 0377, fp); \
putc((num >> 16) & 0377, fp); \
putc((num >> 24) & 0377, fp); \
} \
(void)0
#define PUT_TCC(ch2, fp) \
{ \
putc(ch2[0], fp); \
putc(ch2[1], fp); \
} \
(void)0
void *avi_format_convert(
AviMovie *movie, int stream, void *buffer, AviFormat from, AviFormat to, size_t *size);
int avi_get_data_id(AviFormat format, int stream);
int avi_get_format_type(AviFormat format);
int avi_get_format_fcc(AviFormat format);
int avi_get_format_compression(AviFormat format);
#ifdef __cplusplus
}
#endif

View File

@@ -1,552 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* This is external code. Converts between AVI and MPEG/JPEG.
*/
#include <cstdlib>
#include <cstring>
#include "AVI_avi.h"
#include "MEM_guardedalloc.h"
#include "BLI_math_base.h"
#include "IMB_imbuf.hh"
#include <jerror.h>
#include <jpeglib.h>
#include "avi_mjpeg.h"
static void jpegmemdestmgr_build(j_compress_ptr cinfo, uchar *buffer, size_t bufsize);
static void jpegmemsrcmgr_build(j_decompress_ptr dinfo, const uchar *buffer, size_t bufsize);
static size_t numbytes;
static void add_huff_table(j_decompress_ptr dinfo,
JHUFF_TBL **htblptr,
const UINT8 *bits,
const size_t bits_size,
const UINT8 *val,
const size_t val_size)
{
if (*htblptr == nullptr) {
*htblptr = jpeg_alloc_huff_table((j_common_ptr)dinfo);
}
memcpy((*htblptr)->bits, bits, min_zz(sizeof((*htblptr)->bits), bits_size));
memcpy((*htblptr)->huffval, val, min_zz(sizeof((*htblptr)->huffval), val_size));
/* Initialize sent_table false so table will be written to JPEG file. */
(*htblptr)->sent_table = FALSE;
}
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
/* IMPORTANT: these are only valid for 8-bit data precision! */
static void std_huff_tables(j_decompress_ptr dinfo)
{
static const UINT8 bits_dc_luminance[17] = {
/* 0-base */
0,
0,
1,
5,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
};
static const UINT8 val_dc_luminance[] = {
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
};
static const UINT8 bits_dc_chrominance[17] = {
/* 0-base */
0,
0,
3,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
};
static const UINT8 val_dc_chrominance[] = {
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
};
static const UINT8 bits_ac_luminance[17] = {
/* 0-base */
0,
0,
2,
1,
3,
3,
2,
4,
3,
5,
5,
4,
4,
0,
0,
1,
0x7d,
};
static const UINT8 val_ac_luminance[] = {
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52,
0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45,
0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
};
static const UINT8 bits_ac_chrominance[17] = {
/* 0-base */
0,
0,
2,
1,
2,
4,
4,
3,
4,
7,
5,
4,
4,
0,
1,
2,
0x77,
};
static const UINT8 val_ac_chrominance[] = {
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61,
0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33,
0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18,
0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
};
add_huff_table(dinfo,
&dinfo->dc_huff_tbl_ptrs[0],
bits_dc_luminance,
sizeof(bits_dc_luminance),
val_dc_luminance,
sizeof(val_dc_luminance));
add_huff_table(dinfo,
&dinfo->ac_huff_tbl_ptrs[0],
bits_ac_luminance,
sizeof(bits_ac_luminance),
val_ac_luminance,
sizeof(val_ac_luminance));
add_huff_table(dinfo,
&dinfo->dc_huff_tbl_ptrs[1],
bits_dc_chrominance,
sizeof(bits_dc_chrominance),
val_dc_chrominance,
sizeof(val_dc_chrominance));
add_huff_table(dinfo,
&dinfo->ac_huff_tbl_ptrs[1],
bits_ac_chrominance,
sizeof(bits_ac_chrominance),
val_ac_chrominance,
sizeof(val_ac_chrominance));
}
static int Decode_JPEG(uchar *inBuffer, uchar *outBuffer, uint width, uint height, size_t bufsize)
{
jpeg_decompress_struct dinfo;
jpeg_error_mgr jerr;
(void)width; /* unused */
numbytes = 0;
dinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&dinfo);
jpegmemsrcmgr_build(&dinfo, inBuffer, bufsize);
jpeg_read_header(&dinfo, TRUE);
if (dinfo.dc_huff_tbl_ptrs[0] == nullptr) {
std_huff_tables(&dinfo);
}
dinfo.out_color_space = JCS_RGB;
dinfo.dct_method = JDCT_IFAST;
jpeg_start_decompress(&dinfo);
size_t rowstride = dinfo.output_width * dinfo.output_components;
for (size_t y = 0; y < dinfo.output_height; y++) {
jpeg_read_scanlines(&dinfo, (JSAMPARRAY)&outBuffer, 1);
outBuffer += rowstride;
}
jpeg_finish_decompress(&dinfo);
if (dinfo.output_height >= height) {
return 0;
}
inBuffer += numbytes;
jpegmemsrcmgr_build(&dinfo, inBuffer, bufsize - numbytes);
numbytes = 0;
jpeg_read_header(&dinfo, TRUE);
if (dinfo.dc_huff_tbl_ptrs[0] == nullptr) {
std_huff_tables(&dinfo);
}
jpeg_start_decompress(&dinfo);
rowstride = dinfo.output_width * dinfo.output_components;
for (size_t y = 0; y < dinfo.output_height; y++) {
jpeg_read_scanlines(&dinfo, (JSAMPARRAY)&outBuffer, 1);
outBuffer += rowstride;
}
jpeg_finish_decompress(&dinfo);
jpeg_destroy_decompress(&dinfo);
return 1;
}
static void Compress_JPEG(
int quality, uchar *outbuffer, const uchar *inBuffer, int width, int height, size_t bufsize)
{
jpeg_compress_struct cinfo;
jpeg_error_mgr jerr;
uchar marker[60];
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpegmemdestmgr_build(&cinfo, outbuffer, bufsize);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_colorspace(&cinfo, JCS_YCbCr);
jpeg_set_quality(&cinfo, quality, TRUE);
cinfo.dc_huff_tbl_ptrs[0]->sent_table = TRUE;
cinfo.dc_huff_tbl_ptrs[1]->sent_table = TRUE;
cinfo.ac_huff_tbl_ptrs[0]->sent_table = TRUE;
cinfo.ac_huff_tbl_ptrs[1]->sent_table = TRUE;
cinfo.comp_info[0].component_id = 0;
cinfo.comp_info[0].v_samp_factor = 1;
cinfo.comp_info[1].component_id = 1;
cinfo.comp_info[2].component_id = 2;
cinfo.write_JFIF_header = FALSE;
jpeg_start_compress(&cinfo, FALSE);
int i = 0;
marker[i++] = 'A';
marker[i++] = 'V';
marker[i++] = 'I';
marker[i++] = '1';
marker[i++] = 0;
while (i < 60) {
marker[i++] = 32;
}
jpeg_write_marker(&cinfo, JPEG_APP0, marker, 60);
i = 0;
while (i < 60) {
marker[i++] = 0;
}
jpeg_write_marker(&cinfo, JPEG_COM, marker, 60);
size_t rowstride = cinfo.image_width * cinfo.input_components;
for (size_t y = 0; y < cinfo.image_height; y++) {
jpeg_write_scanlines(&cinfo, (JSAMPARRAY)&inBuffer, 1);
inBuffer += rowstride;
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
}
static void interlace(uchar *to, uchar *from, int width, int height)
{
size_t i, rowstride = width * 3;
for (i = 0; i < height; i++) {
if (i & 1) {
memcpy(&to[i * rowstride], &from[(i / 2 + height / 2) * rowstride], rowstride);
}
else {
memcpy(&to[i * rowstride], &from[(i / 2) * rowstride], rowstride);
}
}
}
static void deinterlace(int odd, uchar *to, uchar *from, int width, int height)
{
size_t i, rowstride = width * 3;
for (i = 0; i < height; i++) {
if ((i & 1) == odd) {
memcpy(&to[(i / 2 + height / 2) * rowstride], &from[i * rowstride], rowstride);
}
else {
memcpy(&to[(i / 2) * rowstride], &from[i * rowstride], rowstride);
}
}
}
void *avi_converter_from_mjpeg(AviMovie *movie, int stream, uchar *buffer, const size_t *size)
{
int deint;
uchar *buf;
(void)stream; /* unused */
buf = static_cast<uchar *>(imb_alloc_pixels(movie->header->Height,
movie->header->Width,
3,
sizeof(uchar),
true,
"avi.avi_converter_from_mjpeg 1"));
if (!buf) {
return nullptr;
}
deint = Decode_JPEG(buffer, buf, movie->header->Width, movie->header->Height, *size);
MEM_freeN(buffer);
if (deint) {
buffer = static_cast<uchar *>(imb_alloc_pixels(movie->header->Height,
movie->header->Width,
3,
sizeof(uchar),
true,
"avi.avi_converter_from_mjpeg 2"));
if (buffer) {
interlace(buffer, buf, movie->header->Width, movie->header->Height);
}
MEM_freeN(buf);
buf = buffer;
}
return buf;
}
void *avi_converter_to_mjpeg(AviMovie *movie, int stream, uchar *buffer, size_t *size)
{
uchar *buf;
size_t bufsize = *size;
numbytes = 0;
*size = 0;
buf = static_cast<uchar *>(imb_alloc_pixels(movie->header->Height,
movie->header->Width,
3,
sizeof(uchar),
true,
"avi.avi_converter_to_mjpeg 1"));
if (!buf) {
return nullptr;
}
if (!movie->interlace) {
Compress_JPEG(movie->streams[stream].sh.Quality / 100,
buf,
buffer,
movie->header->Width,
movie->header->Height,
bufsize);
*size += numbytes;
}
else {
deinterlace(movie->odd_fields, buf, buffer, movie->header->Width, movie->header->Height);
MEM_freeN(buffer);
buffer = buf;
buf = static_cast<uchar *>(imb_alloc_pixels(movie->header->Height,
movie->header->Width,
3,
sizeof(uchar),
true,
"avi.avi_converter_to_mjpeg 1"));
if (buf) {
Compress_JPEG(movie->streams[stream].sh.Quality / 100,
buf,
buffer,
movie->header->Width,
movie->header->Height / 2,
bufsize / 2);
*size += numbytes;
numbytes = 0;
Compress_JPEG(movie->streams[stream].sh.Quality / 100,
buf + *size,
buffer + size_t(movie->header->Height / 2) * size_t(movie->header->Width) * 3,
movie->header->Width,
movie->header->Height / 2,
bufsize / 2);
*size += numbytes;
}
}
MEM_freeN(buffer);
return buf;
}
/* Compression from memory */
static void jpegmemdestmgr_init_destination(j_compress_ptr cinfo)
{
(void)cinfo; /* unused */
}
static boolean jpegmemdestmgr_empty_output_buffer(j_compress_ptr cinfo)
{
(void)cinfo; /* unused */
return TRUE;
}
static void jpegmemdestmgr_term_destination(j_compress_ptr cinfo)
{
numbytes -= cinfo->dest->free_in_buffer;
MEM_freeN(cinfo->dest);
}
static void jpegmemdestmgr_build(j_compress_ptr cinfo, uchar *buffer, size_t bufsize)
{
cinfo->dest = static_cast<jpeg_destination_mgr *>(
MEM_mallocN(sizeof(*(cinfo->dest)), "avi.jpegmemdestmgr_build"));
cinfo->dest->init_destination = jpegmemdestmgr_init_destination;
cinfo->dest->empty_output_buffer = jpegmemdestmgr_empty_output_buffer;
cinfo->dest->term_destination = jpegmemdestmgr_term_destination;
cinfo->dest->next_output_byte = buffer;
cinfo->dest->free_in_buffer = bufsize;
numbytes = bufsize;
}
/* Decompression from memory */
static void jpegmemsrcmgr_init_source(j_decompress_ptr dinfo)
{
(void)dinfo;
}
static boolean jpegmemsrcmgr_fill_input_buffer(j_decompress_ptr dinfo)
{
uchar *buf = (uchar *)dinfo->src->next_input_byte - 2;
/* if we get called, must have run out of data */
WARNMS(dinfo, JWRN_JPEG_EOF);
buf[0] = (JOCTET)0xFF;
buf[1] = (JOCTET)JPEG_EOI;
dinfo->src->next_input_byte = buf;
dinfo->src->bytes_in_buffer = 2;
return TRUE;
}
static void jpegmemsrcmgr_skip_input_data(j_decompress_ptr dinfo, long skip_count)
{
if (dinfo->src->bytes_in_buffer < skip_count) {
skip_count = dinfo->src->bytes_in_buffer;
}
dinfo->src->next_input_byte += skip_count;
dinfo->src->bytes_in_buffer -= skip_count;
}
static void jpegmemsrcmgr_term_source(j_decompress_ptr dinfo)
{
numbytes -= dinfo->src->bytes_in_buffer;
MEM_freeN(dinfo->src);
}
static void jpegmemsrcmgr_build(j_decompress_ptr dinfo, const uchar *buffer, size_t bufsize)
{
dinfo->src = static_cast<jpeg_source_mgr *>(
MEM_mallocN(sizeof(*(dinfo->src)), "avi.jpegmemsrcmgr_build"));
dinfo->src->init_source = jpegmemsrcmgr_init_source;
dinfo->src->fill_input_buffer = jpegmemsrcmgr_fill_input_buffer;
dinfo->src->skip_input_data = jpegmemsrcmgr_skip_input_data;
dinfo->src->resync_to_restart = jpeg_resync_to_restart;
dinfo->src->term_source = jpegmemsrcmgr_term_source;
dinfo->src->bytes_in_buffer = bufsize;
dinfo->src->next_input_byte = buffer;
numbytes = bufsize;
}

View File

@@ -1,20 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void *avi_converter_from_mjpeg(AviMovie *movie, int stream, uchar *buffer, const size_t *size);
void *avi_converter_to_mjpeg(AviMovie *movie, int stream, uchar *buffer, size_t *size);
#ifdef __cplusplus
}
#endif

View File

@@ -1,134 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* This is external code. Sets some compression related options
* (width, height quality, frame-rate).
*/
#include "AVI_avi.h"
#include "BLI_fileops.h"
#include "avi_endian.h"
#include "avi_intern.h"
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
/* avi_set_compress_options gets its own file... now don't WE feel important? */
AviError AVI_set_compress_option(
AviMovie *movie, int option_type, int stream, AviOption option, void *opt_data)
{
int i;
int useconds;
(void)stream; /* unused */
if (movie->header->TotalFrames != 0) {
/* Can't change parameters after we have already started writing frames. */
return AVI_ERROR_OPTION;
}
switch (option_type) {
case AVI_OPTION_TYPE_MAIN:
switch (option) {
case AVI_OPTION_WIDTH:
movie->header->Width = *((int *)opt_data);
movie->header->SuggestedBufferSize = movie->header->Width * movie->header->Height * 3;
for (i = 0; i < movie->header->Streams; i++) {
if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
((AviBitmapInfoHeader *)movie->streams[i].sf)->Width = *((int *)opt_data);
movie->streams[i].sh.SuggestedBufferSize = movie->header->SuggestedBufferSize;
movie->streams[i].sh.right = *((int *)opt_data);
((AviBitmapInfoHeader *)movie->streams[i].sf)->SizeImage =
movie->header->SuggestedBufferSize;
BLI_fseek(movie->fp, movie->offset_table[1 + i * 2 + 1], SEEK_SET);
awrite(movie,
movie->streams[i].sf,
1,
movie->streams[i].sf_size,
movie->fp,
AVI_BITMAPH);
}
}
break;
case AVI_OPTION_HEIGHT:
movie->header->Height = *((int *)opt_data);
movie->header->SuggestedBufferSize = movie->header->Width * movie->header->Height * 3;
for (i = 0; i < movie->header->Streams; i++) {
if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
((AviBitmapInfoHeader *)movie->streams[i].sf)->Height = *((int *)opt_data);
movie->streams[i].sh.SuggestedBufferSize = movie->header->SuggestedBufferSize;
movie->streams[i].sh.bottom = *((int *)opt_data);
((AviBitmapInfoHeader *)movie->streams[i].sf)->SizeImage =
movie->header->SuggestedBufferSize;
BLI_fseek(movie->fp, movie->offset_table[1 + i * 2 + 1], SEEK_SET);
awrite(movie,
movie->streams[i].sf,
1,
movie->streams[i].sf_size,
movie->fp,
AVI_BITMAPH);
}
}
break;
case AVI_OPTION_QUALITY:
for (i = 0; i < movie->header->Streams; i++) {
if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
movie->streams[i].sh.Quality = *((int *)opt_data) * 100;
BLI_fseek(movie->fp, movie->offset_table[1 + i * 2 + 1], SEEK_SET);
awrite(movie,
movie->streams[i].sf,
1,
movie->streams[i].sf_size,
movie->fp,
AVI_BITMAPH);
}
}
break;
case AVI_OPTION_FRAMERATE:
useconds = int(1000000 / *((double *)opt_data));
if (useconds) {
movie->header->MicroSecPerFrame = useconds;
}
for (i = 0; i < movie->header->Streams; i++) {
if (avi_get_format_type(movie->streams[i].format) == FCC("vids")) {
movie->streams[i].sh.Scale = movie->header->MicroSecPerFrame;
BLI_fseek(movie->fp, movie->offset_table[1 + i * 2 + 1], SEEK_SET);
awrite(movie,
movie->streams[i].sf,
1,
movie->streams[i].sf_size,
movie->fp,
AVI_BITMAPH);
}
}
break;
}
BLI_fseek(movie->fp, movie->offset_table[0], SEEK_SET);
awrite(movie, movie->header, 1, sizeof(AviMainHeader), movie->fp, AVI_MAINH);
break;
case AVI_OPTION_TYPE_STRH:
break;
case AVI_OPTION_TYPE_STRF:
break;
default:
return AVI_ERROR_OPTION;
}
return AVI_ERROR_NONE;
}

View File

@@ -1,142 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* This is external code. Converts RGB-type AVI files.
*/
#include <cstdlib>
#include <cstring>
#include "MEM_guardedalloc.h"
#include "AVI_avi.h"
#include "avi_rgb.h"
#include "IMB_imbuf.hh"
#include "BLI_utildefines.h"
/* implementation */
void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, uchar *buffer, const size_t *size)
{
uchar *buf;
AviBitmapInfoHeader *bi;
short bits = 32;
(void)size; /* unused */
bi = (AviBitmapInfoHeader *)movie->streams[stream].sf;
if (bi) {
bits = bi->BitCount;
}
if (bits == 16) {
ushort *pxl;
uchar *to;
#ifdef __BIG_ENDIAN__
uchar *pxla;
#endif
buf = static_cast<uchar *>(imb_alloc_pixels(
movie->header->Height, movie->header->Width, 3, sizeof(uchar), false, "fromavirgbbuf"));
if (buf) {
size_t y = movie->header->Height;
to = buf;
while (y--) {
pxl = (ushort *)(buffer + y * movie->header->Width * 2);
#ifdef __BIG_ENDIAN__
pxla = (uchar *)pxl;
#endif
size_t x = movie->header->Width;
while (x--) {
#ifdef __BIG_ENDIAN__
int i = pxla[0];
pxla[0] = pxla[1];
pxla[1] = i;
pxla += 2;
#endif
*(to++) = ((*pxl >> 10) & 0x1f) * 8;
*(to++) = ((*pxl >> 5) & 0x1f) * 8;
*(to++) = (*pxl & 0x1f) * 8;
pxl++;
}
}
}
MEM_freeN(buffer);
return buf;
}
buf = static_cast<uchar *>(imb_alloc_pixels(
movie->header->Height, movie->header->Width, 3, sizeof(uchar), false, "fromavirgbbuf"));
if (buf) {
size_t rowstride = movie->header->Width * 3;
BLI_assert(bits != 16);
if (movie->header->Width % 2) {
rowstride++;
}
for (size_t y = 0; y < movie->header->Height; y++) {
memcpy(&buf[y * movie->header->Width * 3],
&buffer[((movie->header->Height - 1) - y) * rowstride],
movie->header->Width * 3);
}
for (size_t y = 0; y < size_t(movie->header->Height) * size_t(movie->header->Width) * 3;
y += 3)
{
int i = buf[y];
buf[y] = buf[y + 2];
buf[y + 2] = i;
}
}
MEM_freeN(buffer);
return buf;
}
void *avi_converter_to_avi_rgb(AviMovie *movie, int stream, uchar *buffer, size_t *size)
{
uchar *buf;
(void)stream; /* unused */
size_t rowstride = movie->header->Width * 3;
/* AVI files has uncompressed lines 4-byte aligned */
rowstride = (rowstride + 3) & ~3;
*size = movie->header->Height * rowstride;
buf = static_cast<uchar *>(MEM_mallocN(*size, "toavirgbbuf"));
for (size_t y = 0; y < movie->header->Height; y++) {
memcpy(&buf[y * rowstride],
&buffer[((movie->header->Height - 1) - y) * movie->header->Width * 3],
movie->header->Width * 3);
}
for (size_t y = 0; y < movie->header->Height; y++) {
for (size_t x = 0; x < movie->header->Width * 3; x += 3) {
int i = buf[y * rowstride + x];
buf[y * rowstride + x] = buf[y * rowstride + x + 2];
buf[y * rowstride + x + 2] = i;
}
}
MEM_freeN(buffer);
return buf;
}

View File

@@ -1,23 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void *avi_converter_from_avi_rgb(AviMovie *movie,
int stream,
unsigned char *buffer,
const size_t *size);
void *avi_converter_to_avi_rgb(AviMovie *movie, int stream, unsigned char *buffer, size_t *size);
#ifdef __cplusplus
}
#endif

View File

@@ -1,79 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*
* This is external code. Converts between rgb32 and avi.
*/
#include <cstdlib>
#include <cstring>
#include "MEM_guardedalloc.h"
#include "IMB_imbuf.hh"
#include "AVI_avi.h"
#include "avi_rgb32.h"
void *avi_converter_from_rgb32(AviMovie *movie, int stream, uchar *buffer, size_t *size)
{
uchar *buf;
(void)stream; /* unused */
*size = size_t(movie->header->Height) * size_t(movie->header->Width) * 3;
buf = static_cast<uchar *>(imb_alloc_pixels(
movie->header->Height, movie->header->Width, 3, sizeof(uchar), false, "fromrgb32buf"));
if (!buf) {
return nullptr;
}
size_t rowstridea = movie->header->Width * 3;
size_t rowstrideb = movie->header->Width * 4;
for (size_t y = 0; y < movie->header->Height; y++) {
for (size_t x = 0; x < movie->header->Width; x++) {
buf[y * rowstridea + x * 3 + 0] = buffer[y * rowstrideb + x * 4 + 3];
buf[y * rowstridea + x * 3 + 1] = buffer[y * rowstrideb + x * 4 + 2];
buf[y * rowstridea + x * 3 + 2] = buffer[y * rowstrideb + x * 4 + 1];
}
}
MEM_freeN(buffer);
return buf;
}
void *avi_converter_to_rgb32(AviMovie *movie, int stream, uchar *buffer, size_t *size)
{
uchar *buf;
uchar *to, *from;
(void)stream; /* unused */
*size = size_t(movie->header->Height) * size_t(movie->header->Width) * 4;
buf = static_cast<uchar *>(imb_alloc_pixels(
movie->header->Height, movie->header->Width, 4, sizeof(uchar), false, "torgb32buf"));
if (!buf) {
return nullptr;
}
memset(buf, 255, *size);
to = buf;
from = buffer;
size_t i = size_t(movie->header->Height) * size_t(movie->header->Width);
while (i--) {
memcpy(to, from, 3);
to += 4;
from += 3;
}
MEM_freeN(buffer);
return buf;
}

View File

@@ -1,20 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup avi
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void *avi_converter_from_rgb32(AviMovie *movie, int stream, unsigned char *buffer, size_t *size);
void *avi_converter_to_rgb32(AviMovie *movie, int stream, unsigned char *buffer, size_t *size);
#ifdef __cplusplus
}
#endif

View File

@@ -384,18 +384,8 @@ const EnumPropertyItem rna_enum_image_type_items[] = {
IMAGE_TYPE_ITEMS_IMAGE_ONLY
RNA_ENUM_ITEM_HEADING(N_("Movie"), nullptr),
{R_IMF_IMTYPE_AVIJPEG,
"AVI_JPEG",
ICON_FILE_MOVIE,
"AVI JPEG",
"Output video in AVI JPEG format"},
{R_IMF_IMTYPE_AVIRAW, "AVI_RAW", ICON_FILE_MOVIE, "AVI Raw", "Output video in AVI Raw format"},
#ifdef WITH_FFMPEG
{R_IMF_IMTYPE_FFMPEG,
"FFMPEG",
ICON_FILE_MOVIE,
"FFmpeg Video",
"The most versatile way to output video files"},
{R_IMF_IMTYPE_FFMPEG, "FFMPEG", ICON_FILE_MOVIE, "FFmpeg Video", ""},
#endif
{0, nullptr, 0, nullptr, nullptr},
};

View File

@@ -180,10 +180,6 @@ if(WITH_BULLET)
add_definitions(-DWITH_BULLET)
endif()
if(WITH_CODEC_AVI)
add_definitions(-DWITH_AVI)
endif()
if(WITH_CODEC_FFMPEG)
list(APPEND INC_SYS
${FFMPEG_INCLUDE_DIRS}

View File

@@ -89,11 +89,8 @@ static PyObject *make_builtopts_info()
SetObjIncref(Py_False);
#endif
#ifdef WITH_AVI
SetObjIncref(Py_True);
#else
/* AVI */
SetObjIncref(Py_False);
#endif
#ifdef WITH_FFMPEG
SetObjIncref(Py_True);