mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-04-14 00:58:38 +02:00
avisynth: use AviSynth+'s frame properties to set various fields
* Field Order * Chroma Location * Color Transfer Characteristics * Color Range * Color Primaries * Matrix Coefficients The existing TFF/BFF detection is retained as a fallback for older versions of AviSynth that can't access frame properties. The other properties have no legacy equivalent to detect them. Signed-off-by: Stephen Hutchinson <qyot27@gmail.com>
This commit is contained in:
parent
05c492eeb0
commit
af69e4c241
@ -19,6 +19,8 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "libavutil/attributes.h"
|
#include "libavutil/attributes.h"
|
||||||
#include "libavutil/internal.h"
|
#include "libavutil/internal.h"
|
||||||
|
|
||||||
@ -76,6 +78,9 @@ typedef struct AviSynthLibrary {
|
|||||||
AVSC_DECLARE_FUNC(avs_get_row_size_p);
|
AVSC_DECLARE_FUNC(avs_get_row_size_p);
|
||||||
AVSC_DECLARE_FUNC(avs_is_planar_rgb);
|
AVSC_DECLARE_FUNC(avs_is_planar_rgb);
|
||||||
AVSC_DECLARE_FUNC(avs_is_planar_rgba);
|
AVSC_DECLARE_FUNC(avs_is_planar_rgba);
|
||||||
|
AVSC_DECLARE_FUNC(avs_get_frame_props_ro);
|
||||||
|
AVSC_DECLARE_FUNC(avs_prop_get_int);
|
||||||
|
AVSC_DECLARE_FUNC(avs_get_env_property);
|
||||||
#undef AVSC_DECLARE_FUNC
|
#undef AVSC_DECLARE_FUNC
|
||||||
} AviSynthLibrary;
|
} AviSynthLibrary;
|
||||||
|
|
||||||
@ -153,6 +158,9 @@ static av_cold int avisynth_load_library(void)
|
|||||||
LOAD_AVS_FUNC(avs_get_row_size_p, 1);
|
LOAD_AVS_FUNC(avs_get_row_size_p, 1);
|
||||||
LOAD_AVS_FUNC(avs_is_planar_rgb, 1);
|
LOAD_AVS_FUNC(avs_is_planar_rgb, 1);
|
||||||
LOAD_AVS_FUNC(avs_is_planar_rgba, 1);
|
LOAD_AVS_FUNC(avs_is_planar_rgba, 1);
|
||||||
|
LOAD_AVS_FUNC(avs_get_frame_props_ro, 1);
|
||||||
|
LOAD_AVS_FUNC(avs_prop_get_int, 1);
|
||||||
|
LOAD_AVS_FUNC(avs_get_env_property, 1);
|
||||||
#undef LOAD_AVS_FUNC
|
#undef LOAD_AVS_FUNC
|
||||||
|
|
||||||
atexit(avisynth_atexit_handler);
|
atexit(avisynth_atexit_handler);
|
||||||
@ -236,6 +244,10 @@ static av_cold void avisynth_atexit_handler(void)
|
|||||||
static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st)
|
static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st)
|
||||||
{
|
{
|
||||||
AviSynthContext *avs = s->priv_data;
|
AviSynthContext *avs = s->priv_data;
|
||||||
|
const AVS_Map *avsmap;
|
||||||
|
AVS_VideoFrame *frame;
|
||||||
|
int framedata, error;
|
||||||
|
bool frameprop;
|
||||||
int planar = 0; // 0: packed, 1: YUV, 2: Y8, 3: Planar RGB, 4: YUVA, 5: Planar RGBA
|
int planar = 0; // 0: packed, 1: YUV, 2: Y8, 3: Planar RGB, 4: YUVA, 5: Planar RGBA
|
||||||
|
|
||||||
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
|
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||||
@ -251,19 +263,6 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st)
|
|||||||
avpriv_set_pts_info(st, 32, avs->vi->fps_denominator, avs->vi->fps_numerator);
|
avpriv_set_pts_info(st, 32, avs->vi->fps_denominator, avs->vi->fps_numerator);
|
||||||
|
|
||||||
|
|
||||||
st->codecpar->field_order = AV_FIELD_UNKNOWN;
|
|
||||||
/* AviSynth works with frame-based video, detecting field order can
|
|
||||||
* only work when avs_is_field_based returns 'false'. */
|
|
||||||
av_log(s, AV_LOG_TRACE, "avs_is_field_based: %d\n", avs_is_field_based(avs->vi));
|
|
||||||
if (avs_is_field_based(avs->vi) == 0) {
|
|
||||||
if (avs_is_tff(avs->vi)) {
|
|
||||||
st->codecpar->field_order = AV_FIELD_TT;
|
|
||||||
}
|
|
||||||
else if (avs_is_bff(avs->vi)) {
|
|
||||||
st->codecpar->field_order = AV_FIELD_BB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (avs->vi->pixel_type) {
|
switch (avs->vi->pixel_type) {
|
||||||
/* 10~16-bit YUV pix_fmts (AviSynth+) */
|
/* 10~16-bit YUV pix_fmts (AviSynth+) */
|
||||||
case AVS_CS_YUV444P10:
|
case AVS_CS_YUV444P10:
|
||||||
@ -499,6 +498,244 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st)
|
|||||||
avs->n_planes = 1;
|
avs->n_planes = 1;
|
||||||
avs->planes = avs_planes_packed;
|
avs->planes = avs_planes_packed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read AviSynth+'s frame properties to set additional info.
|
||||||
|
*
|
||||||
|
* Due to a bug preventing the C interface from accessing frame
|
||||||
|
* properties in earlier versions of interface version 8, only
|
||||||
|
* enable this if we detect version 8.1 at the minimum. */
|
||||||
|
|
||||||
|
if (!avs_library.avs_get_env_property) {
|
||||||
|
av_log(s, AV_LOG_TRACE, "%s\n",
|
||||||
|
"avs_get_env_property does not exist in AviSynth library; frame properties won't be checked.");
|
||||||
|
frameprop = false;
|
||||||
|
} else {
|
||||||
|
if (avs_library.avs_get_env_property(avs->env, AVS_AEP_INTERFACE_BUGFIX)) {
|
||||||
|
av_log(s, AV_LOG_TRACE, "%s\n", "Using interface version 8.1 or higher, reading frame properties.");
|
||||||
|
frameprop = true;
|
||||||
|
} else {
|
||||||
|
av_log(s, AV_LOG_TRACE, "%s\n", "Using interface version 8.0, need 8.1+ to read frame properties.");
|
||||||
|
frameprop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameprop = true) {
|
||||||
|
|
||||||
|
frame = avs_library.avs_get_frame(avs->clip, framedata);
|
||||||
|
avsmap = avs_library.avs_get_frame_props_ro(avs->env, frame);
|
||||||
|
|
||||||
|
/* Field order */
|
||||||
|
switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_FieldBased", 0, &error)) {
|
||||||
|
case 0:
|
||||||
|
st->codecpar->field_order = AV_FIELD_PROGRESSIVE;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
st->codecpar->field_order = AV_FIELD_BB;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
st->codecpar->field_order = AV_FIELD_TT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
st->codecpar->field_order = AV_FIELD_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color Range */
|
||||||
|
switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_ColorRange", 0, &error)) {
|
||||||
|
case 0:
|
||||||
|
st->codecpar->color_range = AVCOL_RANGE_JPEG;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
st->codecpar->color_range = AVCOL_RANGE_MPEG;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
st->codecpar->color_range = AVCOL_RANGE_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color Primaries */
|
||||||
|
switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_Primaries", 0, &error)) {
|
||||||
|
case 1:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_BT709;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_UNSPECIFIED;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_BT470M;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_BT470BG;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_SMPTE170M;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_SMPTE240M;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_FILM;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_BT2020;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_SMPTE428;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_SMPTE431;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_SMPTE432;
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_EBU3213;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
st->codecpar->color_primaries = AVCOL_PRI_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color Transfer Characteristics */
|
||||||
|
switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_Transfer", 0, &error)) {
|
||||||
|
case 1:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_BT709;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_UNSPECIFIED;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_GAMMA22;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_GAMMA28;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_SMPTE170M;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_SMPTE240M;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_LINEAR;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_LOG;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_LOG_SQRT;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_IEC61966_2_4;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_BT1361_ECG;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_IEC61966_2_1;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_BT2020_10;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_BT2020_12;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_SMPTE2084;
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_SMPTE428;
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_ARIB_STD_B67;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
st->codecpar->color_trc = AVCOL_TRC_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Matrix coefficients */
|
||||||
|
switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_Matrix", 0, &error)) {
|
||||||
|
case 0:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_RGB;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_BT709;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_UNSPECIFIED;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_FCC;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_BT470BG;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_SMPTE170M;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_SMPTE240M;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_YCGCO;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_BT2020_NCL;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_BT2020_CL;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_SMPTE2085;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_CHROMA_DERIVED_NCL;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_CHROMA_DERIVED_CL;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_ICTCP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
st->codecpar->color_space = AVCOL_SPC_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chroma Location */
|
||||||
|
switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_ChromaLocation", 0, &error)) {
|
||||||
|
case 0:
|
||||||
|
st->codecpar->chroma_location = AVCHROMA_LOC_LEFT;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
st->codecpar->chroma_location = AVCHROMA_LOC_CENTER;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
st->codecpar->chroma_location = AVCHROMA_LOC_TOPLEFT;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
st->codecpar->chroma_location = AVCHROMA_LOC_TOP;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
st->codecpar->chroma_location = AVCHROMA_LOC_BOTTOMLEFT;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
st->codecpar->chroma_location = AVCHROMA_LOC_BOTTOM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
st->codecpar->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
st->codecpar->field_order = AV_FIELD_UNKNOWN;
|
||||||
|
/* AviSynth works with frame-based video, detecting field order can
|
||||||
|
* only work when avs_is_field_based returns 'false'. */
|
||||||
|
av_log(s, AV_LOG_TRACE, "avs_is_field_based: %d\n", avs_is_field_based(avs->vi));
|
||||||
|
if (avs_is_field_based(avs->vi) == 0) {
|
||||||
|
if (avs_is_tff(avs->vi)) {
|
||||||
|
st->codecpar->field_order = AV_FIELD_TT;
|
||||||
|
}
|
||||||
|
else if (avs_is_bff(avs->vi)) {
|
||||||
|
st->codecpar->field_order = AV_FIELD_BB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user