Blender V4.3
ffmpeg_codecs.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "testing/testing.h"
6
7extern "C" {
8#include "ffmpeg_compat.h"
9
10#include <libavcodec/avcodec.h>
11#include <libavutil/channel_layout.h>
12#include <libavutil/log.h>
13}
14
15namespace {
16
17bool test_vcodec(const AVCodec *codec, AVPixelFormat pixelformat)
18{
19 av_log_set_level(AV_LOG_QUIET);
20 bool result = false;
21 if (codec) {
22 AVCodecContext *ctx = avcodec_alloc_context3(codec);
23 if (ctx) {
24 ctx->time_base.num = 1;
25 ctx->time_base.den = 25;
26 ctx->pix_fmt = pixelformat;
27 ctx->width = 720;
28 ctx->height = 576;
29 int open = avcodec_open2(ctx, codec, NULL);
30 if (open >= 0) {
31 avcodec_free_context(&ctx);
32 result = true;
33 }
34 }
35 }
36 return result;
37}
38bool test_acodec(const AVCodec *codec, AVSampleFormat fmt)
39{
40 av_log_set_level(AV_LOG_QUIET);
41 bool result = false;
42 if (codec) {
43 AVCodecContext *ctx = avcodec_alloc_context3(codec);
44 if (ctx) {
45 ctx->sample_fmt = fmt;
46 ctx->sample_rate = 48000;
47#ifdef FFMPEG_USE_OLD_CHANNEL_VARS
48 ctx->channel_layout = AV_CH_LAYOUT_MONO;
49#else
50 av_channel_layout_from_mask(&ctx->ch_layout, AV_CH_LAYOUT_MONO);
51#endif
52 ctx->bit_rate = 128000;
53 int open = avcodec_open2(ctx, codec, NULL);
54 if (open >= 0) {
55 avcodec_free_context(&ctx);
56 result = true;
57 }
58 }
59 }
60 return result;
61}
62
63bool test_codec_video_by_codecid(AVCodecID codec_id, AVPixelFormat pixelformat)
64{
65 bool result = false;
66 const AVCodec *codec = avcodec_find_encoder(codec_id);
67 if (codec) {
68 result = test_vcodec(codec, pixelformat);
69 }
70 return result;
71}
72
73bool test_codec_video_by_name(const char *codecname, AVPixelFormat pixelformat)
74{
75 bool result = false;
76 const AVCodec *codec = avcodec_find_encoder_by_name(codecname);
77 if (codec) {
78 result = test_vcodec(codec, pixelformat);
79 }
80 return result;
81}
82
83bool test_codec_audio_by_codecid(AVCodecID codec_id, AVSampleFormat fmt)
84{
85 bool result = false;
86 const AVCodec *codec = avcodec_find_encoder(codec_id);
87 if (codec) {
88 result = test_acodec(codec, fmt);
89 }
90 return result;
91}
92
93bool test_codec_audio_by_name(const char *codecname, AVSampleFormat fmt)
94{
95 bool result = false;
96 const AVCodec *codec = avcodec_find_encoder_by_name(codecname);
97 if (codec) {
98 result = test_acodec(codec, fmt);
99 }
100 return result;
101}
102
103#define str(s) #s
104#define FFMPEG_TEST_VCODEC_ID(codec, fmt) \
105 TEST(ffmpeg, codec##_##fmt) \
106 { \
107 EXPECT_TRUE(test_codec_video_by_codecid(codec, fmt)); \
108 }
109
110#define FFMPEG_TEST_VCODEC_NAME(codec, fmt) \
111 TEST(ffmpeg, codec##_##fmt) \
112 { \
113 EXPECT_TRUE(test_codec_video_by_name(str(codec), fmt)); \
114 }
115
116#define FFMPEG_TEST_ACODEC_ID(codec, fmt) \
117 TEST(ffmpeg, codec##_##fmt) \
118 { \
119 EXPECT_TRUE(test_codec_audio_by_codecid(codec, fmt)); \
120 }
121
122#define FFMPEG_TEST_ACODEC_NAME(codec, fmt) \
123 TEST(ffmpeg, codec) \
124 { \
125 EXPECT_TRUE(test_codec_audio_by_name(str(codec), fmt)); \
126 }
127
128} // namespace
129
130/* generic codec ID's used in blender */
131
132FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_HUFFYUV, AV_PIX_FMT_BGRA)
133FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_HUFFYUV, AV_PIX_FMT_RGB32)
134FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_FFV1, AV_PIX_FMT_RGB32)
135FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_QTRLE, AV_PIX_FMT_ARGB)
136FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_VP9, AV_PIX_FMT_YUVA420P)
137FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_PNG, AV_PIX_FMT_RGBA)
138FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_H264, AV_PIX_FMT_YUV420P)
139FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG4, AV_PIX_FMT_YUV420P)
140FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_THEORA, AV_PIX_FMT_YUV420P)
141FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_DVVIDEO, AV_PIX_FMT_YUV420P)
142FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG1VIDEO, AV_PIX_FMT_YUV420P)
143FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_MPEG2VIDEO, AV_PIX_FMT_YUV420P)
144FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_FLV1, AV_PIX_FMT_YUV420P)
145FFMPEG_TEST_VCODEC_ID(AV_CODEC_ID_AV1, AV_PIX_FMT_YUV420P)
146
147/* Audio codecs */
148
149FFMPEG_TEST_ACODEC_ID(AV_CODEC_ID_AAC, AV_SAMPLE_FMT_FLTP)
150FFMPEG_TEST_ACODEC_ID(AV_CODEC_ID_AC3, AV_SAMPLE_FMT_FLTP)
151FFMPEG_TEST_ACODEC_ID(AV_CODEC_ID_FLAC, AV_SAMPLE_FMT_S16)
152FFMPEG_TEST_ACODEC_ID(AV_CODEC_ID_MP2, AV_SAMPLE_FMT_S16)
153FFMPEG_TEST_ACODEC_ID(AV_CODEC_ID_MP3, AV_SAMPLE_FMT_FLTP)
154FFMPEG_TEST_ACODEC_ID(AV_CODEC_ID_OPUS, AV_SAMPLE_FMT_FLT)
155FFMPEG_TEST_ACODEC_ID(AV_CODEC_ID_PCM_S16LE, AV_SAMPLE_FMT_S16)
156FFMPEG_TEST_ACODEC_ID(AV_CODEC_ID_VORBIS, AV_SAMPLE_FMT_FLTP)
157
158/* Libraries we count on ffmpeg being linked against */
159
160FFMPEG_TEST_VCODEC_NAME(libtheora, AV_PIX_FMT_YUV420P)
161FFMPEG_TEST_VCODEC_NAME(libx264, AV_PIX_FMT_YUV420P)
162FFMPEG_TEST_VCODEC_NAME(libvpx, AV_PIX_FMT_YUV420P)
163FFMPEG_TEST_VCODEC_NAME(libopenjpeg, AV_PIX_FMT_YUV420P)
164/* aom's AV1 encoder is "libaom-av1". FFMPEG_TEST_VCODEC_NAME(libaom-av1, ...)
165 * will not work because the dash will not work with the test macro. */
166TEST(ffmpeg, libaom_av1_AV_PIX_FMT_YUV420P)
167{
168 EXPECT_TRUE(test_codec_video_by_name("libaom-av1", AV_PIX_FMT_YUV420P));
169}
170FFMPEG_TEST_ACODEC_NAME(libvorbis, AV_SAMPLE_FMT_FLTP)
171FFMPEG_TEST_ACODEC_NAME(libopus, AV_SAMPLE_FMT_FLT)
172FFMPEG_TEST_ACODEC_NAME(libmp3lame, AV_SAMPLE_FMT_FLTP)
#define NULL
#define FFMPEG_TEST_VCODEC_NAME(codec, fmt)
TEST(ffmpeg, libaom_av1_AV_PIX_FMT_YUV420P)
#define FFMPEG_TEST_ACODEC_NAME(codec, fmt)
#define FFMPEG_TEST_ACODEC_ID(codec, fmt)
#define FFMPEG_TEST_VCODEC_ID(codec, fmt)