165 changes: 150 additions & 15 deletions libavfilter/vf_xfade_vulkan.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ enum XFadeTransitions {
SLIDEUP,
SLIDELEFT,
SLIDERIGHT,
CIRCLEOPEN,
CIRCLECLOSE,
DISSOLVE,
PIXELIZE,
WIPETL,
WIPETR,
WIPEBL,
WIPEBR,
NB_TRANSITIONS,
};

Expand Down Expand Up @@ -179,16 +187,135 @@ static const char transition_slideright[] = {
C(0, } )
};

#define SHADER_CIRCLE_COMMON \
C(0, void circle(int idx, ivec2 pos, float progress, bool open) ) \
C(0, { ) \
C(1, const ivec2 half_size = imageSize(output_images[idx]) / 2; ) \
C(1, const float z = dot(half_size, half_size); ) \
C(1, float p = ((open ? (1.0 - progress) : progress) - 0.5) * 3.0; ) \
C(1, ivec2 dsize = pos - half_size; ) \
C(1, float sm = dot(dsize, dsize) / z + p; ) \
C(1, vec4 a = texture(a_images[idx], pos); ) \
C(1, vec4 b = texture(b_images[idx], pos); ) \
C(1, imageStore(output_images[idx], pos, \
mix(open ? b : a, open ? a : b, \
smoothstep(0.f, 1.f, sm))); ) \
C(0, } )

static const char transition_circleopen[] = {
SHADER_CIRCLE_COMMON
C(0, void transition(int idx, ivec2 pos, float progress) )
C(0, { )
C(1, circle(idx, pos, progress, true); )
C(0, } )
};

static const char transition_circleclose[] = {
SHADER_CIRCLE_COMMON
C(0, void transition(int idx, ivec2 pos, float progress) )
C(0, { )
C(1, circle(idx, pos, progress, false); )
C(0, } )
};

#define SHADER_FRAND_FUNC \
C(0, float frand(vec2 v) ) \
C(0, { ) \
C(1, return fract(sin(dot(v, vec2(12.9898, 78.233))) * 43758.545); ) \
C(0, } )

static const char transition_dissolve[] = {
SHADER_FRAND_FUNC
C(0, void transition(int idx, ivec2 pos, float progress) )
C(0, { )
C(1, float sm = frand(pos) * 2.0 + (1.0 - progress) * 2.0 - 1.5; )
C(1, vec4 a = texture(a_images[idx], pos); )
C(1, vec4 b = texture(b_images[idx], pos); )
C(1, imageStore(output_images[idx], pos, sm >= 0.5 ? a : b); )
C(0, } )
};

static const char transition_pixelize[] = {
C(0, void transition(int idx, ivec2 pos, float progress) )
C(0, { )
C(1, ivec2 size = imageSize(output_images[idx]); )
C(1, float d = min(progress, 1.0 - progress); )
C(1, float dist = ceil(d * 50.0) / 50.0; )
C(1, float sq = 2.0 * dist * min(size.x, size.y) / 20.0; )
C(1, float sx = dist > 0.0 ? min((floor(pos.x / sq) + 0.5) * sq, size.x - 1) : pos.x; )
C(1, float sy = dist > 0.0 ? min((floor(pos.y / sq) + 0.5) * sq, size.y - 1) : pos.y; )
C(1, vec4 a = texture(a_images[idx], vec2(sx, sy)); )
C(1, vec4 b = texture(b_images[idx], vec2(sx, sy)); )
C(1, imageStore(output_images[idx], pos, mix(a, b, progress)); )
C(0, } )
};

static const char transition_wipetl[] = {
C(0, void transition(int idx, ivec2 pos, float progress) )
C(0, { )
C(1, ivec2 size = imageSize(output_images[idx]); )
C(1, float zw = size.x * (1.0 - progress); )
C(1, float zh = size.y * (1.0 - progress); )
C(1, vec4 a = texture(a_images[idx], pos); )
C(1, vec4 b = texture(b_images[idx], pos); )
C(1, imageStore(output_images[idx], pos, (pos.y <= zh && pos.x <= zw) ? a : b); )
C(0, } )
};

static const char transition_wipetr[] = {
C(0, void transition(int idx, ivec2 pos, float progress) )
C(0, { )
C(1, ivec2 size = imageSize(output_images[idx]); )
C(1, float zw = size.x * (progress); )
C(1, float zh = size.y * (1.0 - progress); )
C(1, vec4 a = texture(a_images[idx], pos); )
C(1, vec4 b = texture(b_images[idx], pos); )
C(1, imageStore(output_images[idx], pos, (pos.y <= zh && pos.x > zw) ? a : b); )
C(0, } )
};

static const char transition_wipebl[] = {
C(0, void transition(int idx, ivec2 pos, float progress) )
C(0, { )
C(1, ivec2 size = imageSize(output_images[idx]); )
C(1, float zw = size.x * (1.0 - progress); )
C(1, float zh = size.y * (progress); )
C(1, vec4 a = texture(a_images[idx], pos); )
C(1, vec4 b = texture(b_images[idx], pos); )
C(1, imageStore(output_images[idx], pos, (pos.y > zh && pos.x <= zw) ? a : b); )
C(0, } )
};

static const char transition_wipebr[] = {
C(0, void transition(int idx, ivec2 pos, float progress) )
C(0, { )
C(1, ivec2 size = imageSize(output_images[idx]); )
C(1, float zw = size.x * (progress); )
C(1, float zh = size.y * (progress); )
C(1, vec4 a = texture(a_images[idx], pos); )
C(1, vec4 b = texture(b_images[idx], pos); )
C(1, imageStore(output_images[idx], pos, (pos.y > zh && pos.x > zw) ? a : b); )
C(0, } )
};

static const char* transitions_map[NB_TRANSITIONS] = {
[FADE] = transition_fade,
[WIPELEFT] = transition_wipeleft,
[WIPERIGHT] = transition_wiperight,
[WIPEUP] = transition_wipeup,
[WIPEDOWN] = transition_wipedown,
[SLIDEDOWN] = transition_slidedown,
[SLIDEUP] = transition_slideup,
[SLIDELEFT] = transition_slideleft,
[SLIDERIGHT]= transition_slideright,
[FADE] = transition_fade,
[WIPELEFT] = transition_wipeleft,
[WIPERIGHT] = transition_wiperight,
[WIPEUP] = transition_wipeup,
[WIPEDOWN] = transition_wipedown,
[SLIDEDOWN] = transition_slidedown,
[SLIDEUP] = transition_slideup,
[SLIDELEFT] = transition_slideleft,
[SLIDERIGHT] = transition_slideright,
[CIRCLEOPEN] = transition_circleopen,
[CIRCLECLOSE] = transition_circleclose,
[DISSOLVE] = transition_dissolve,
[PIXELIZE] = transition_pixelize,
[WIPETL] = transition_wipetl,
[WIPETR] = transition_wipetr,
[WIPEBL] = transition_wipebl,
[WIPEBR] = transition_wipebr,
};

static av_cold int init_vulkan(AVFilterContext *avctx)
Expand Down Expand Up @@ -530,15 +657,23 @@ static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h)

static const AVOption xfade_vulkan_options[] = {
{ "transition", "set cross fade transition", OFFSET(transition), AV_OPT_TYPE_INT, {.i64=FADE}, 0, NB_TRANSITIONS-1, FLAGS, "transition" },
{ "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, "transition" },
{ "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, "transition" },
{ "fade", "fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADE}, 0, 0, FLAGS, "transition" },
{ "wipeleft", "wipe left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPELEFT}, 0, 0, FLAGS, "transition" },
{ "wiperight", "wipe right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPERIGHT}, 0, 0, FLAGS, "transition" },
{ "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, "transition" },
{ "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, "transition" },
{ "wipeup", "wipe up transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEUP}, 0, 0, FLAGS, "transition" },
{ "wipedown", "wipe down transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEDOWN}, 0, 0, FLAGS, "transition" },
{ "slidedown", "slide down transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEDOWN}, 0, 0, FLAGS, "transition" },
{ "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, "transition" },
{ "slideup", "slide up transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDEUP}, 0, 0, FLAGS, "transition" },
{ "slideleft", "slide left transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDELEFT}, 0, 0, FLAGS, "transition" },
{ "slideright","slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, "transition" },
{ "slideright", "slide right transition", 0, AV_OPT_TYPE_CONST, {.i64=SLIDERIGHT}, 0, 0, FLAGS, "transition" },
{ "circleopen", "circleopen transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLEOPEN}, 0, 0, FLAGS, "transition" },
{ "circleclose", "circleclose transition", 0, AV_OPT_TYPE_CONST, {.i64=CIRCLECLOSE}, 0, 0, FLAGS, "transition" },
{ "dissolve", "dissolve transition", 0, AV_OPT_TYPE_CONST, {.i64=DISSOLVE}, 0, 0, FLAGS, "transition" },
{ "pixelize", "pixelize transition", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE}, 0, 0, FLAGS, "transition" },
{ "wipetl", "wipe top left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETL}, 0, 0, FLAGS, "transition" },
{ "wipetr", "wipe top right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPETR}, 0, 0, FLAGS, "transition" },
{ "wipebl", "wipe bottom left transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBL}, 0, 0, FLAGS, "transition" },
{ "wipebr", "wipe bottom right transition", 0, AV_OPT_TYPE_CONST, {.i64=WIPEBR}, 0, 0, FLAGS, "transition" },
{ "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS },
{ "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS },
{ NULL }
Expand Down
2 changes: 0 additions & 2 deletions libavfilter/vsrc_testsrc_vulkan.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,6 @@ static av_cold int init_filter(AVFilterContext *ctx, enum TestSrcVulkanMode mode

s->initialized = 1;

return 0;

fail:
if (spv_opaque)
spv->free_shader(spv, &spv_opaque);
Expand Down
25 changes: 11 additions & 14 deletions libavfilter/x86/vf_ssim.asm
Original file line number Diff line number Diff line change
Expand Up @@ -228,25 +228,22 @@ cglobal ssim_end_line, 3, 3, 7, sum0, sum1, w

; subpd the ones we added too much
test wd, wd
jz .end
jz .end
add wd, 4
test wd, 3
jz .skip3
test wd, 2
jz .skip2
test wd, 1
jz .skip1
.skip3:
cmp wd, 1
jz .skip3
cmp wd, 2
jz .skip2
.skip1: ; 3 valid => skip 1 invalid
psrldq m5, 8
subpd m6, m5
jmp .end
.skip2:
psrldq m5, 8
jmp .end
.skip2: ; 2 valid => skip 2 invalid
subpd m6, m5
jmp .end
.skip3: ; 1 valid => skip 3 invalid
psrldq m3, 8
subpd m0, m3
jmp .end
.skip1:
psrldq m3, 16
subpd m6, m5

.end:
Expand Down
7 changes: 5 additions & 2 deletions libavformat/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ OBJS-$(CONFIG_IMAGE_HDR_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_J2K_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_JPEG_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_JPEGLS_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += img2dec.o img2.o jpegxl_probe.o
OBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PAM_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER) += img2dec.o img2.o
OBJS-$(CONFIG_IMAGE_PCX_PIPE_DEMUXER) += img2dec.o img2.o
Expand Down Expand Up @@ -320,7 +320,7 @@ OBJS-$(CONFIG_IVF_MUXER) += ivfenc.o
OBJS-$(CONFIG_IVR_DEMUXER) += rmdec.o rm.o rmsipr.o
OBJS-$(CONFIG_JACOSUB_DEMUXER) += jacosubdec.o subtitles.o
OBJS-$(CONFIG_JACOSUB_MUXER) += jacosubenc.o rawenc.o
OBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_anim_dec.o jpegxl_probe.o
OBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_anim_dec.o
OBJS-$(CONFIG_JV_DEMUXER) += jvdec.o
OBJS-$(CONFIG_KUX_DEMUXER) += flvdec.o
OBJS-$(CONFIG_KVAG_DEMUXER) += kvag.o
Expand Down Expand Up @@ -433,6 +433,7 @@ OBJS-$(CONFIG_OMA_DEMUXER) += omadec.o pcm.o oma.o
OBJS-$(CONFIG_OMA_MUXER) += omaenc.o rawenc.o oma.o id3v2enc.o
OBJS-$(CONFIG_OPUS_MUXER) += oggenc.o \
vorbiscomment.o
OBJS-$(CONFIG_OSQ_DEMUXER) += osq.o rawdec.o
OBJS-$(CONFIG_PAF_DEMUXER) += paf.o
OBJS-$(CONFIG_PCM_ALAW_DEMUXER) += pcmdec.o pcm.o
OBJS-$(CONFIG_PCM_ALAW_MUXER) += pcmenc.o rawenc.o
Expand Down Expand Up @@ -717,6 +718,8 @@ SHLIBOBJS += log2_tab.o to_upper4.o
SHLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o
SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o
SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o
SHLIBOBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += jpegxl_parse.o
SHLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER) += jpegxl_parse.o
SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o
SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o
SHLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o
Expand Down
1 change: 1 addition & 0 deletions libavformat/allformats.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ extern const FFOutputFormat ff_ogv_muxer;
extern const AVInputFormat ff_oma_demuxer;
extern const FFOutputFormat ff_oma_muxer;
extern const FFOutputFormat ff_opus_muxer;
extern const AVInputFormat ff_osq_demuxer;
extern const AVInputFormat ff_paf_demuxer;
extern const AVInputFormat ff_pcm_alaw_demuxer;
extern const FFOutputFormat ff_pcm_alaw_muxer;
Expand Down
3 changes: 3 additions & 0 deletions libavformat/hls.c
Original file line number Diff line number Diff line change
Expand Up @@ -2506,6 +2506,9 @@ static int hls_read_seek(AVFormatContext *s, int stream_index,
/* Flush the packet queue of the subdemuxer. */
ff_read_frame_flush(pls->ctx);

/* Reset the init segment so it's re-fetched and served appropiately */
pls->cur_init_section = NULL;

pls->seek_timestamp = seek_timestamp;
pls->seek_flags = flags;

Expand Down
4 changes: 2 additions & 2 deletions libavformat/img2dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#include "avio_internal.h"
#include "internal.h"
#include "img2.h"
#include "jpegxl_probe.h"
#include "libavcodec/jpegxl_parse.h"
#include "libavcodec/mjpeg.h"
#include "libavcodec/vbn.h"
#include "libavcodec/xwd.h"
Expand Down Expand Up @@ -850,7 +850,7 @@ static int jpegxl_probe(const AVProbeData *p)
if (AV_RL16(b) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE)
return 0;
#if CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER
if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size, 1) >= 0)
if (ff_jpegxl_parse_codestream_header(p->buf, p->buf_size, NULL, 5) >= 0)
return AVPROBE_SCORE_MAX - 2;
#endif
return 0;
Expand Down
132 changes: 31 additions & 101 deletions libavformat/jpegxl_anim_dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,96 +28,28 @@
#include <stdint.h>
#include <string.h>

#include "libavcodec/bytestream.h"
#define BITSTREAM_READER_LE
#include "libavcodec/get_bits.h"

#include "libavcodec/jpegxl.h"
#include "libavcodec/jpegxl_parse.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"

#include "avformat.h"
#include "internal.h"
#include "jpegxl_probe.h"

typedef struct JXLAnimDemuxContext {
AVBufferRef *initial;
} JXLAnimDemuxContext;

/*
* copies as much of the codestream into the buffer as possible
* pass a shorter buflen to request less
* returns the number of bytes consumed from input, may be greater than input_len
* if the input doesn't end on an ISOBMFF-box boundary
*/
static int jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len,
uint8_t *buffer, int buflen, int *copied) {
GetByteContext gb;
*copied = 0;
bytestream2_init(&gb, input_buffer, input_len);

while (1) {
uint64_t size;
uint32_t tag;
int head_size = 8;

if (bytestream2_get_bytes_left(&gb) < 16)
break;

size = bytestream2_get_be32(&gb);
if (size == 1) {
size = bytestream2_get_be64(&gb);
head_size = 16;
}
/* invalid ISOBMFF size */
if (size && size <= head_size)
return AVERROR_INVALIDDATA;
if (size)
size -= head_size;

tag = bytestream2_get_le32(&gb);
if (tag == MKTAG('j', 'x', 'l', 'p')) {
if (bytestream2_get_bytes_left(&gb) < 4)
break;
bytestream2_skip(&gb, 4);
if (size) {
if (size <= 4)
return AVERROR_INVALIDDATA;
size -= 4;
}
}
/*
* size = 0 means "until EOF". this is legal but uncommon
* here we just set it to the remaining size of the probe buffer
*/
if (!size)
size = bytestream2_get_bytes_left(&gb);

if (tag == MKTAG('j', 'x', 'l', 'c') || tag == MKTAG('j', 'x', 'l', 'p')) {
if (size > buflen - *copied)
size = buflen - *copied;
/*
* arbitrary chunking of the payload makes this memcpy hard to avoid
* in practice this will only be performed one or two times at most
*/
*copied += bytestream2_get_buffer(&gb, buffer + *copied, size);
} else {
bytestream2_skip(&gb, size);
}
if (bytestream2_get_bytes_left(&gb) <= 0 || *copied >= buflen)
break;
}

return bytestream2_tell(&gb);
}

static int jpegxl_anim_probe(const AVProbeData *p)
{
uint8_t buffer[4096 + AV_INPUT_BUFFER_PADDING_SIZE];
int copied;
int copied = 0, ret;
FFJXLMetadata meta = { 0 };

/* this is a raw codestream */
if (AV_RL16(p->buf) == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) {
if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size, 1) >= 1)
ret = ff_jpegxl_parse_codestream_header(p->buf, p->buf_size, &meta, 5);
if (ret >= 0 && meta.animation_offset > 0)
return AVPROBE_SCORE_MAX;

return 0;
Expand All @@ -127,10 +59,13 @@ static int jpegxl_anim_probe(const AVProbeData *p)
if (AV_RL64(p->buf) != FF_JPEGXL_CONTAINER_SIGNATURE_LE)
return 0;

if (jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer, sizeof(buffer) - AV_INPUT_BUFFER_PADDING_SIZE, &copied) <= 0 || copied <= 0)
if (ff_jpegxl_collect_codestream_header(p->buf, p->buf_size, buffer,
sizeof(buffer) - AV_INPUT_BUFFER_PADDING_SIZE, &copied) <= 0
|| copied <= 0)
return 0;

if (ff_jpegxl_verify_codestream_header(buffer, copied, 0) >= 1)
ret = ff_jpegxl_parse_codestream_header(buffer, copied, &meta, 10);
if (ret >= 0 && meta.animation_offset > 0)
return AVPROBE_SCORE_MAX;

return 0;
Expand All @@ -141,13 +76,10 @@ static int jpegxl_anim_read_header(AVFormatContext *s)
JXLAnimDemuxContext *ctx = s->priv_data;
AVIOContext *pb = s->pb;
AVStream *st;
int offset = 0;
uint8_t head[256 + AV_INPUT_BUFFER_PADDING_SIZE];
const int sizeofhead = sizeof(head) - AV_INPUT_BUFFER_PADDING_SIZE;
int headsize = 0;
int ctrl;
AVRational tb;
GetBitContext gbi, *gb = &gbi;
int headsize = 0, ret;
FFJXLMetadata meta = { 0 };

uint64_t sig16 = avio_rl16(pb);
if (sig16 == FF_JPEGXL_CODESTREAM_SIGNATURE_LE) {
Expand All @@ -167,7 +99,7 @@ static int jpegxl_anim_read_header(AVFormatContext *s)
return AVERROR_INVALIDDATA;
avio_skip(pb, 2); // first box always 12 bytes
while (1) {
int copied;
int copied = 0;
uint8_t buf[4096];
int read = avio_read(pb, buf, sizeof(buf));
if (read < 0)
Expand All @@ -183,32 +115,27 @@ static int jpegxl_anim_read_header(AVFormatContext *s)
if (av_buffer_realloc(&ctx->initial, ctx->initial->size + read) < 0)
return AVERROR(ENOMEM);
}
jpegxl_collect_codestream_header(buf, read, head + headsize, sizeofhead - headsize, &copied);
ff_jpegxl_collect_codestream_header(buf, read, head + headsize, sizeofhead - headsize, &copied);
memcpy(ctx->initial->data + (ctx->initial->size - read), buf, read);
headsize += copied;
if (headsize >= sizeofhead || read < sizeof(buf))
break;
}
}

/* offset in bits of the animation header */
offset = ff_jpegxl_verify_codestream_header(head, headsize, 0);
if (offset <= 0)
return AVERROR_INVALIDDATA;
if (init_get_bits8(gb, head, headsize) < 0)
ret = ff_jpegxl_parse_codestream_header(head, headsize, &meta, 0);
if (ret < 0 || meta.animation_offset <= 0)
return AVERROR_INVALIDDATA;
skip_bits_long(gb, offset);

st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);

st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_JPEGXL;
ctrl = get_bits(gb, 2);
tb.den = (const uint32_t[]){100, 1000, 1, 1}[ctrl] + get_bits_long(gb, (const uint32_t[]){0, 0, 10, 30}[ctrl]);
ctrl = get_bits(gb, 2);
tb.num = (const uint32_t[]){1, 1001, 1, 1}[ctrl] + get_bits_long(gb, (const uint32_t[]){0, 0, 8, 10}[ctrl]);
avpriv_set_pts_info(st, 1, tb.num, tb.den);
avpriv_set_pts_info(st, 1, meta.timebase.num, meta.timebase.den);
ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL;

return 0;
}
Expand All @@ -222,17 +149,17 @@ static int jpegxl_anim_read_packet(AVFormatContext *s, AVPacket *pkt)
int64_t size;
size_t offset = 0;

if ((size = avio_size(pb)) < 0)
size = avio_size(pb);
if (size < 0)
return size;

/* animated JXL this big should not exist */
if (size > INT_MAX)
return AVERROR_INVALIDDATA;
if (size == 0)
size = 4096;

if (ctx->initial && size < ctx->initial->size)
size = ctx->initial->size;

if ((ret = av_new_packet(pkt, size)) < 0)
ret = av_new_packet(pkt, size);
if (ret < 0)
return ret;

if (ctx->initial) {
Expand All @@ -241,8 +168,11 @@ static int jpegxl_anim_read_packet(AVFormatContext *s, AVPacket *pkt)
av_buffer_unref(&ctx->initial);
}

if ((ret = avio_read(pb, pkt->data + offset, size - offset)) < 0)
ret = avio_read(pb, pkt->data + offset, size - offset);
if (ret < 0)
return ret;
if (ret < size - offset)
pkt->size = ret + offset;

return 0;
}
Expand All @@ -265,7 +195,7 @@ const AVInputFormat ff_jpegxl_anim_demuxer = {
.read_packet = jpegxl_anim_read_packet,
.read_close = jpegxl_anim_close,
.flags_internal = FF_FMT_INIT_CLEANUP,
.flags = AVFMT_GENERIC_INDEX,
.flags = AVFMT_GENERIC_INDEX | AVFMT_NOTIMESTAMPS,
.mime_type = "image/jxl",
.extensions = "jxl",
};
22 changes: 22 additions & 0 deletions libavformat/jpegxl_parse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* JPEG XL Header Parser Stub
* Copyright (c) 2023 Leo Izen <leo.izen@gmail.com>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "libavcodec/jpegxl_parse.c"
412 changes: 0 additions & 412 deletions libavformat/jpegxl_probe.c

This file was deleted.

64 changes: 0 additions & 64 deletions libavformat/matroska.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "libavutil/stereo3d.h"

#include "matroska.h"

/* If you add a tag here that is not in ff_codec_bmp_tags[]
Expand Down Expand Up @@ -145,65 +143,3 @@ const char * const ff_matroska_video_stereo_mode[MATROSKA_VIDEO_STEREOMODE_TYPE_
"block_lr",
"block_rl",
};

const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT] = {
"left",
"right",
"background",
};

int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode)
{
AVStereo3D *stereo;
int ret;

stereo = av_stereo3d_alloc();
if (!stereo)
return AVERROR(ENOMEM);

// note: the missing breaks are intentional
switch (stereo_mode) {
case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO:
stereo->type = AV_STEREO3D_2D;
break;
case MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT:
stereo->flags |= AV_STEREO3D_FLAG_INVERT;
case MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT:
stereo->type = AV_STEREO3D_SIDEBYSIDE;
break;
case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP:
stereo->flags |= AV_STEREO3D_FLAG_INVERT;
case MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM:
stereo->type = AV_STEREO3D_TOPBOTTOM;
break;
case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL:
stereo->flags |= AV_STEREO3D_FLAG_INVERT;
case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR:
stereo->type = AV_STEREO3D_CHECKERBOARD;
break;
case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL:
stereo->flags |= AV_STEREO3D_FLAG_INVERT;
case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR:
stereo->type = AV_STEREO3D_LINES;
break;
case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL:
stereo->flags |= AV_STEREO3D_FLAG_INVERT;
case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR:
stereo->type = AV_STEREO3D_COLUMNS;
break;
case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL:
stereo->flags |= AV_STEREO3D_FLAG_INVERT;
case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR:
stereo->type = AV_STEREO3D_FRAMESEQUENCE;
break;
}

ret = av_stream_add_side_data(st, AV_PKT_DATA_STEREO3D, (uint8_t *)stereo,
sizeof(*stereo));
if (ret < 0) {
av_freep(&stereo);
return ret;
}

return 0;
}
41 changes: 37 additions & 4 deletions libavformat/matroska.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#define AVFORMAT_MATROSKA_H

#include "libavcodec/codec_id.h"
#include "avformat.h"
#include "metadata.h"

/* EBML version supported */
Expand Down Expand Up @@ -386,8 +385,44 @@ typedef struct CodecTags{
extern const CodecTags ff_mkv_codec_tags[];
extern const CodecTags ff_webm_codec_tags[];
extern const AVMetadataConv ff_mkv_metadata_conv[];

/* The following macro contains all the information about which
* MATROSKA_VIDEO_STEREOMODE_TYPE_* correspond to which AVStereo3D
* structures and also the relevant horizontal/vertical divisors
* as well as WebM compatibility.
*
* MAP and MKV_ONLY are macros to be provided by the user.
* MAP(MatroskaVideoStereoModeType, AVStereo3DType, AV_STEREO3D_FLAG_*,
* HALF_WIDTH, HALF_HEIGHT, WebM-compatibility)
* is for the stereo modes that have a Stereo3D counterpart.
* MKV_ONLY(MatroskaVideoStereoModeType, HALF_WIDTH, HALF_HEIGHT, WebM)
* is for those that don't have a Stereo3D counterpart.
* */
#define STEREOMODE_STEREO3D_MAPPING(MAP, MKV_ONLY) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_MONO, AV_STEREO3D_2D, 0, 0, 0, 1) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT, AV_STEREO3D_SIDEBYSIDE, 0, 1, 0, 1) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP, AV_STEREO3D_TOPBOTTOM, \
AV_STEREO3D_FLAG_INVERT, 0, 1, 1) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM, AV_STEREO3D_TOPBOTTOM, 0, 0, 1, 1) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL, AV_STEREO3D_CHECKERBOARD, \
AV_STEREO3D_FLAG_INVERT, 0, 0, 0) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR, AV_STEREO3D_CHECKERBOARD, 0, 0, 0, 0) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL, AV_STEREO3D_LINES, \
AV_STEREO3D_FLAG_INVERT, 0, 1, 0) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR, AV_STEREO3D_LINES, 0, 0, 1, 0) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL, AV_STEREO3D_COLUMNS, \
AV_STEREO3D_FLAG_INVERT, 1, 0, 0) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR, AV_STEREO3D_COLUMNS, 0, 1, 0, 0) \
MKV_ONLY(MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_CYAN_RED, 0, 0, 0) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT, AV_STEREO3D_SIDEBYSIDE, \
AV_STEREO3D_FLAG_INVERT, 1, 0, 1) \
MKV_ONLY(MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG, 0, 0, 0) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR, AV_STEREO3D_FRAMESEQUENCE, \
0, 0, 0, 0) \
MAP(MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL, AV_STEREO3D_FRAMESEQUENCE, \
AV_STEREO3D_FLAG_INVERT, 0, 0, 0)

extern const char * const ff_matroska_video_stereo_mode[MATROSKA_VIDEO_STEREOMODE_TYPE_NB];
extern const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT];

/* AVStream Metadata tag keys for WebM Dash Manifest */
#define INITIALIZATION_RANGE "webm_dash_manifest_initialization_range"
Expand All @@ -401,8 +436,6 @@ extern const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_P
#define TRACK_NUMBER "webm_dash_manifest_track_number"
#define CODEC_PRIVATE_SIZE "webm_dash_manifest_codec_priv_size"

int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode);

#define DVCC_DVVC_BLOCK_TYPE_NAME "Dolby Vision configuration"

#endif /* AVFORMAT_MATROSKA_H */
44 changes: 41 additions & 3 deletions libavformat/matroskadec.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,12 @@ static const CodecMime mkv_mime_tags[] = {
{"" , AV_CODEC_ID_NONE}
};

static const char * const matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT] = {
"left",
"right",
"background",
};

static const char *const matroska_doctypes[] = { "matroska", "webm" };

/*
Expand Down Expand Up @@ -2157,6 +2163,37 @@ static void mkv_stereo_mode_display_mul(int stereo_mode,
}
}

static int mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode)
{
static const struct {
char type;
char flags;
} stereo_mode_conv [] = {
#define STEREO_MODE_CONV(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
[(STEREOMODETYPE)] = { .type = (STEREO3DTYPE), .flags = (FLAGS) },
#define IGNORE(STEREOMODETYPE, WDIV, HDIV, WEBM)
STEREOMODE_STEREO3D_MAPPING(STEREO_MODE_CONV, IGNORE)
};
AVStereo3D *stereo;
int ret;

stereo = av_stereo3d_alloc();
if (!stereo)
return AVERROR(ENOMEM);

stereo->type = stereo_mode_conv[stereo_mode].type;
stereo->flags = stereo_mode_conv[stereo_mode].flags;

ret = av_stream_add_side_data(st, AV_PKT_DATA_STEREO3D, (uint8_t *)stereo,
sizeof(*stereo));
if (ret < 0) {
av_freep(&stereo);
return ret;
}

return 0;
}

static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) {
const MatroskaTrackVideoColor *color = track->video.color.elem;
const MatroskaMasteringMeta *mastering_meta;
Expand Down Expand Up @@ -2991,7 +3028,7 @@ static int matroska_parse_tracks(AVFormatContext *s)
if (planes[j].type >= MATROSKA_VIDEO_STEREO_PLANE_COUNT)
continue;
snprintf(buf, sizeof(buf), "%s_%d",
ff_matroska_video_stereo_plane[planes[j].type], i);
matroska_video_stereo_plane[planes[j].type], i);
for (k=0; k < matroska->tracks.nb_elem; k++)
if (planes[j].uid == tracks[k].uid && tracks[k].stream) {
av_dict_set(&tracks[k].stream->metadata,
Expand All @@ -3001,8 +3038,9 @@ static int matroska_parse_tracks(AVFormatContext *s)
}
// add stream level stereo3d side data if it is a supported format
if (track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB &&
track->video.stereo_mode != 10 && track->video.stereo_mode != 12) {
int ret = ff_mkv_stereo3d_conv(st, track->video.stereo_mode);
track->video.stereo_mode != MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_CYAN_RED &&
track->video.stereo_mode != MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG) {
int ret = mkv_stereo3d_conv(st, track->video.stereo_mode);
if (ret < 0)
return ret;
}
Expand Down
143 changes: 73 additions & 70 deletions libavformat/matroskaenc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1580,95 +1580,99 @@ static void mkv_write_field_order(EbmlWriter *writer, int is_webm,

#define MAX_STEREO_MODE_ELEMS 1
static int mkv_write_stereo_mode(AVFormatContext *s, EbmlWriter *writer,
AVStream *st, int is_webm,
const AVStream *st, int is_webm,
int *h_width, int *h_height)
{
const char *error_message_addendum = "";
const AVDictionaryEntry *tag;
MatroskaVideoStereoModeType format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB;
const AVStereo3D *stereo;

/* The following macros create bitfields where the ith bit
* indicates whether the MatroskaVideoStereoModeType with that value
* uses double width/height or is WebM compatible. */
#define FLAG(STEREOMODETYPE, BOOL) | (BOOL) << (STEREOMODETYPE)
#define WDIV1(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
FLAG(STEREOMODETYPE, WDIV)
#define WDIV2(STEREOMODETYPE, WDIV, HDIV, WEBM) \
FLAG(STEREOMODETYPE, WDIV)
// The zero in the following line consumes the first '|'.
const unsigned width_bitfield = 0 STEREOMODE_STEREO3D_MAPPING(WDIV1, WDIV2);

#define HDIV1(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
FLAG(STEREOMODETYPE, HDIV)
#define HDIV2(STEREOMODETYPE, WDIV, HDIV, WEBM) \
FLAG(STEREOMODETYPE, HDIV)
const unsigned height_bitfield = 0 STEREOMODE_STEREO3D_MAPPING(HDIV1, HDIV2);

#define WEBM1(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
FLAG(STEREOMODETYPE, WEBM)
#define WEBM2(STEREOMODETYPE, WDIV, HDIV, WEBM) \
FLAG(STEREOMODETYPE, WEBM)
const unsigned webm_bitfield = 0 STEREOMODE_STEREO3D_MAPPING(WEBM1, WEBM2);

*h_width = 1;
*h_height = 1;
// convert metadata into proper side data and add it to the stream

if ((tag = av_dict_get(st->metadata, "stereo_mode", NULL, 0)) ||
(tag = av_dict_get( s->metadata, "stereo_mode", NULL, 0))) {
int stereo_mode = atoi(tag->value);

for (int i = 0; i < MATROSKA_VIDEO_STEREOMODE_TYPE_NB; i++)
if (!strcmp(tag->value, ff_matroska_video_stereo_mode[i])){
stereo_mode = i;
format = i;
break;
}

if (stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB &&
stereo_mode != 10 && stereo_mode != 12) {
int ret = ff_mkv_stereo3d_conv(st, stereo_mode);
if (ret < 0)
return ret;
if (format == MATROSKA_VIDEO_STEREOMODE_TYPE_NB) {
long stereo_mode = strtol(tag->value, NULL, 0);
if ((unsigned long)stereo_mode >= MATROSKA_VIDEO_STEREOMODE_TYPE_NB)
goto fail;
format = stereo_mode;
}
}
} else {
const AVStereo3D *stereo;
/* The following macro presumes all MATROSKA_VIDEO_STEREOMODE_TYPE_*
* values to be in the range 0..254. */
#define STEREOMODE(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \
[(STEREO3DTYPE)][!!((FLAGS) & AV_STEREO3D_FLAG_INVERT)] = (STEREOMODETYPE) + 1,
#define IGNORE(STEREOMODETYPE, WDIV, HDIV, WEBM)
static const unsigned char conversion_table[][2] = {
STEREOMODE_STEREO3D_MAPPING(STEREOMODE, IGNORE)
};
int fmt;

stereo = (const AVStereo3D*)av_stream_get_side_data(st, AV_PKT_DATA_STEREO3D,
NULL);
if (!stereo)
return 0;

stereo = (const AVStereo3D*)av_stream_get_side_data(st, AV_PKT_DATA_STEREO3D,
NULL);
if (stereo) {
switch (stereo->type) {
case AV_STEREO3D_2D:
format = MATROSKA_VIDEO_STEREOMODE_TYPE_MONO;
break;
case AV_STEREO3D_SIDEBYSIDE:
format = (stereo->flags & AV_STEREO3D_FLAG_INVERT)
? MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT
: MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT;
*h_width = 2;
break;
case AV_STEREO3D_TOPBOTTOM:
format = MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM;
if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
format--;
*h_height = 2;
break;
case AV_STEREO3D_CHECKERBOARD:
format = MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR;
if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
format--;
break;
case AV_STEREO3D_LINES:
format = MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR;
if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
format--;
*h_height = 2;
break;
case AV_STEREO3D_COLUMNS:
format = MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR;
if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
format--;
*h_width = 2;
break;
case AV_STEREO3D_FRAMESEQUENCE:
format = MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR;
if (stereo->flags & AV_STEREO3D_FLAG_INVERT)
format++;
break;
}
}
/* A garbage AVStereo3D or something with no Matroska analogon. */
if ((unsigned)stereo->type >= FF_ARRAY_ELEMS(conversion_table))
return 0;

if (format == MATROSKA_VIDEO_STEREOMODE_TYPE_NB)
return 0;
fmt = conversion_table[stereo->type][!!(stereo->flags & AV_STEREO3D_FLAG_INVERT)];
/* Format with no Matroska analogon; ignore it */
if (!fmt)
return 0;
format = fmt - 1;
}

// if webm, do not write unsupported modes
if ((is_webm &&
format > MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM &&
format != MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT)
|| format >= MATROSKA_VIDEO_STEREOMODE_TYPE_NB) {
av_log(s, AV_LOG_ERROR,
"The specified stereo mode is not valid.\n");
return AVERROR(EINVAL);
if (is_webm && !(webm_bitfield >> format)) {
error_message_addendum = " for WebM";
goto fail;
}

*h_width = 1 << ((width_bitfield >> format) & 1);
*h_height = 1 << ((height_bitfield >> format) & 1);

// write StereoMode if format is valid
ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOSTEREOMODE, format);

return 0;
fail:
av_log(s, AV_LOG_ERROR,
"The specified stereo mode is not valid%s.\n",
error_message_addendum);
return AVERROR(EINVAL);
}

static void mkv_write_blockadditionmapping(AVFormatContext *s, const MatroskaMuxContext *mkv,
Expand Down Expand Up @@ -1723,7 +1727,7 @@ static void mkv_write_blockadditionmapping(AVFormatContext *s, const MatroskaMux
}

static int mkv_write_track_video(AVFormatContext *s, MatroskaMuxContext *mkv,
AVStream *st, const AVCodecParameters *par,
const AVStream *st, const AVCodecParameters *par,
AVIOContext *pb)
{
const AVDictionaryEntry *tag;
Expand All @@ -1748,11 +1752,10 @@ static int mkv_write_track_video(AVFormatContext *s, MatroskaMuxContext *mkv,
if (ret < 0)
return ret;

if (((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) ||
((tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) ||
(par->format == AV_PIX_FMT_YUVA420P)) {
if (par->format == AV_PIX_FMT_YUVA420P ||
((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) ||
(tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0))) && strtol(tag->value, NULL, 0))
ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOALPHAMODE, 1);
}

// write DisplayWidth and DisplayHeight, they contain the size of
// a single source view and/or the display aspect ratio
Expand Down Expand Up @@ -3027,7 +3030,7 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt)
}
}

if (!mkv->cluster_pos)
if (mkv->cluster_pos == -1)
avio_write_marker(s->pb,
av_rescale_q(pkt->dts, s->streams[pkt->stream_index]->time_base, AV_TIME_BASE_Q),
keyframe && (mkv->have_video ? codec_type == AVMEDIA_TYPE_VIDEO : 1) ? AVIO_DATA_MARKER_SYNC_POINT : AVIO_DATA_MARKER_BOUNDARY_POINT);
Expand Down
118 changes: 118 additions & 0 deletions libavformat/osq.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* OSQ demuxer
* Copyright (c) 2023 Paul B Mahol
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "libavutil/intreadwrite.h"
#include "avio_internal.h"
#include "avformat.h"
#include "demux.h"
#include "internal.h"
#include "rawdec.h"

static int osq_probe(const AVProbeData *p)
{
if (AV_RL32(p->buf) != MKTAG('O','S','Q',' '))
return 0;
if (AV_RL32(p->buf + 4) != 48)
return 0;
if (AV_RL16(p->buf + 8) != 1)
return 0;
if (p->buf[10] == 0)
return 0;
if (p->buf[11] == 0)
return 0;
if (AV_RL32(p->buf + 12) == 0)
return 0;
if (AV_RL16(p->buf + 16) == 0)
return 0;

return AVPROBE_SCORE_MAX;
}

static int osq_read_header(AVFormatContext *s)
{
uint32_t t, size;
AVStream *st;
int ret;

t = avio_rl32(s->pb);
if (t != MKTAG('O','S','Q',' '))
return AVERROR_INVALIDDATA;

size = avio_rl32(s->pb);
if (size != 48)
return AVERROR_INVALIDDATA;

st = avformat_new_stream(s, NULL);
if (!st)
return AVERROR(ENOMEM);
if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
return ret;

t = avio_rl32(s->pb);
if (t != MKTAG('R','I','F','F'))
return AVERROR_INVALIDDATA;
avio_skip(s->pb, 8);

t = avio_rl32(s->pb);
if (t != MKTAG('f','m','t',' '))
return AVERROR_INVALIDDATA;
size = avio_rl32(s->pb);
avio_skip(s->pb, size);

t = avio_rl32(s->pb);
size = avio_rl32(s->pb);
while (t != MKTAG('d','a','t','a')) {
avio_skip(s->pb, size);

t = avio_rl32(s->pb);
size = avio_rl32(s->pb);
if (avio_feof(s->pb))
return AVERROR_INVALIDDATA;
}

st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
st->codecpar->codec_id = AV_CODEC_ID_OSQ;
st->codecpar->sample_rate = AV_RL32(st->codecpar->extradata + 4);
if (st->codecpar->sample_rate <= 0)
return AVERROR_INVALIDDATA;
st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
st->codecpar->ch_layout.nb_channels = st->codecpar->extradata[3];
if (st->codecpar->ch_layout.nb_channels == 0)
return AVERROR_INVALIDDATA;
st->start_time = 0;
st->duration = AV_RL32(st->codecpar->extradata + 16);
avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);

return 0;
}

const AVInputFormat ff_osq_demuxer = {
.name = "osq",
.long_name = NULL_IF_CONFIG_SMALL("raw OSQ"),
.read_probe = osq_probe,
.read_header = osq_read_header,
.read_packet = ff_raw_read_partial_packet,
.extensions = "osq",
.flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK | AVFMT_NOTIMESTAMPS,
.raw_codec_id = AV_CODEC_ID_OSQ,
.priv_data_size = sizeof(FFRawDemuxerContext),
.priv_class = &ff_raw_demuxer_class,
};
3 changes: 2 additions & 1 deletion libavformat/riff.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecParameters *par, int for_asf, int
int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int flags);

enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps);
int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int size, int big_endian);
int ff_get_wav_header(void *logctx, AVIOContext *pb, AVCodecParameters *par,
int size, int big_endian);

extern const AVCodecTag ff_codec_bmp_tags[]; // exposed through avformat_get_riff_video_tags()
extern const AVCodecTag ff_codec_wav_tags[];
Expand Down
26 changes: 14 additions & 12 deletions libavformat/riffdec.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid)
* an openended structure.
*/

static void parse_waveformatex(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par)
static void parse_waveformatex(void *logctx, AVIOContext *pb, AVCodecParameters *par)
{
ff_asf_guid subformat;
int bps;
Expand All @@ -84,21 +84,21 @@ static void parse_waveformatex(AVFormatContext *s, AVIOContext *pb, AVCodecParam
} else {
par->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat);
if (!par->codec_id)
av_log(s, AV_LOG_WARNING,
av_log(logctx, AV_LOG_WARNING,
"unknown subformat:"FF_PRI_GUID"\n",
FF_ARG_GUID(subformat));
}
}

/* "big_endian" values are needed for RIFX file format */
int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
int ff_get_wav_header(void *logctx, AVIOContext *pb,
AVCodecParameters *par, int size, int big_endian)
{
int id, channels = 0;
int id, channels = 0, ret;
uint64_t bitrate = 0;

if (size < 14) {
avpriv_request_sample(s, "wav header size < 14");
avpriv_request_sample(logctx, "wav header size < 14");
return AVERROR_INVALIDDATA;
}

Expand Down Expand Up @@ -139,19 +139,20 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
if (size >= 18 && id != 0x0165) { /* We're obviously dealing with WAVEFORMATEX */
int cbSize = avio_rl16(pb); /* cbSize */
if (big_endian) {
avpriv_report_missing_feature(s, "WAVEFORMATEX support for RIFX files");
avpriv_report_missing_feature(logctx, "WAVEFORMATEX support for RIFX files");
return AVERROR_PATCHWELCOME;
}
size -= 18;
cbSize = FFMIN(size, cbSize);
if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */
parse_waveformatex(s, pb, par);
parse_waveformatex(logctx, pb, par);
cbSize -= 22;
size -= 22;
}
if (cbSize > 0) {
if (ff_get_extradata(s, par, pb, cbSize) < 0)
return AVERROR(ENOMEM);
ret = ff_get_extradata(logctx, par, pb, cbSize);
if (ret < 0)
return ret;
size -= cbSize;
}

Expand All @@ -162,8 +163,9 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
int nb_streams, i;

size -= 4;
if (ff_get_extradata(s, par, pb, size) < 0)
return AVERROR(ENOMEM);
ret = ff_get_extradata(logctx, par, pb, size);
if (ret < 0)
return ret;
nb_streams = AV_RL16(par->extradata + 4);
par->sample_rate = AV_RL32(par->extradata + 12);
channels = 0;
Expand All @@ -177,7 +179,7 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb,
par->bit_rate = bitrate;

if (par->sample_rate <= 0) {
av_log(s, AV_LOG_ERROR,
av_log(logctx, AV_LOG_ERROR,
"Invalid sample rate: %d\n", par->sample_rate);
return AVERROR_INVALIDDATA;
}
Expand Down
2 changes: 1 addition & 1 deletion libavformat/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

#include "version_major.h"

#define LIBAVFORMAT_VERSION_MINOR 10
#define LIBAVFORMAT_VERSION_MINOR 11
#define LIBAVFORMAT_VERSION_MICRO 100

#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
Expand Down
16 changes: 14 additions & 2 deletions libavutil/channel_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,16 @@ typedef struct AVChannelLayout {
void *opaque;
} AVChannelLayout;

/**
* Macro to define native channel layouts
*
* @note This doesn't use designated initializers for compatibility with C++ 17 and older.
*/
#define AV_CHANNEL_LAYOUT_MASK(nb, m) \
{ .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = (nb), .u = { .mask = (m) }}
{ /* .order */ AV_CHANNEL_ORDER_NATIVE, \
/* .nb_channels */ (nb), \
/* .u.mask */ { m }, \
/* .opaque */ NULL }

/**
* @name Common pre-defined channel layouts
Expand Down Expand Up @@ -396,8 +404,12 @@ typedef struct AVChannelLayout {
#define AV_CHANNEL_LAYOUT_HEXADECAGONAL AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL)
#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO_DOWNMIX)
#define AV_CHANNEL_LAYOUT_22POINT2 AV_CHANNEL_LAYOUT_MASK(24, AV_CH_LAYOUT_22POINT2)

#define AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER \
{ .order = AV_CHANNEL_ORDER_AMBISONIC, .nb_channels = 4, .u = { .mask = 0 }}
{ /* .order */ AV_CHANNEL_ORDER_AMBISONIC, \
/* .nb_channels */ 4, \
/* .u.mask */ { 0 }, \
/* .opaque */ NULL }
/** @} */

struct AVBPrint;
Expand Down
89 changes: 45 additions & 44 deletions libavutil/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,26 @@ static void frame_side_data_wipe(AVFrame *frame)
wipe_side_data(&frame->side_data, &frame->nb_side_data);
}

void av_side_data_set_uninit(AVFrameSideDataSet *set)
void av_frame_side_data_set_uninit(AVFrameSideDataSet *set)
{
wipe_side_data(&set->sd, &set->nb_sd);
}

static void remove_side_data(AVFrameSideData ***sd, int *nb_side_data,
const enum AVFrameSideDataType type)
{
for (int i = *nb_side_data - 1; i >= 0; i--) {
AVFrameSideData *entry = ((*sd)[i]);
if (entry->type != type)
continue;

free_side_data(&entry);

((*sd)[i]) = ((*sd)[*nb_side_data - 1]);
(*nb_side_data)--;
}
}

AVFrame *av_frame_alloc(void)
{
AVFrame *frame = av_malloc(sizeof(*frame));
Expand Down Expand Up @@ -846,32 +861,16 @@ AVFrameSideData *av_frame_new_side_data(AVFrame *frame,
return ret;
}


AVFrameSideData *av_side_data_set_new_item(AVFrameSideDataSet *set,
enum AVFrameSideDataType type,
size_t size,
unsigned int allow_duplicates)
AVFrameSideData *av_frame_side_data_set_new_item(AVFrameSideDataSet *set,
enum AVFrameSideDataType type,
size_t size,
unsigned int flags)
{
AVBufferRef *buf = av_buffer_alloc(size);
AVFrameSideData *ret = NULL;

if (!allow_duplicates) {
for (int i = 0; i < set->nb_sd; i++) {
if (set->sd[i]->type != type)
continue;

free_side_data(&set->sd[i]);

for (int j = i + 1; j < set->nb_sd; j++) {
set->sd[j - 1] = set->sd[j];
}

// finally, cause a retry of the same index and update state
// regarding there being one less side data item in the set.
i--;
set->nb_sd--;
}
}
if (flags & AV_FRAME_SIDE_DATA_SET_FLAG_NO_DUPLICATES)
remove_side_data(&set->sd, &set->nb_sd, type);

ret = add_side_data_to_set_from_buf(set, type, buf);
if (!ret)
Expand All @@ -880,31 +879,40 @@ AVFrameSideData *av_side_data_set_new_item(AVFrameSideDataSet *set,
return ret;
}

int av_side_data_set_extend(AVFrameSideDataSet *dst,
const AVFrameSideDataSet src,
unsigned int allow_duplicates)
int av_frame_side_data_set_extend(AVFrameSideDataSet *dst,
const AVFrameSideDataSet src,
unsigned int flags)
{
if (src.nb_sd > 0 && src.nb_sd == dst->nb_sd &&
src.sd == dst->sd)
return AVERROR(EINVAL);

for (int i = 0; i < src.nb_sd; i++) {
const AVFrameSideData *sd_src = src.sd[i];
AVFrameSideData *sd_dst =
av_side_data_set_new_item(dst, sd_src->type,
sd_src->size,
allow_duplicates);
AVBufferRef *buf = av_buffer_ref(sd_src->buf);
AVFrameSideData *sd_dst =
add_side_data_to_set_from_buf(dst, sd_src->type, buf);
if (!sd_dst) {
av_side_data_set_uninit(dst);
av_buffer_unref(&buf);
av_frame_side_data_set_uninit(dst);
return AVERROR(ENOMEM);
}

memcpy(sd_dst->data, sd_src->data, sd_src->size);
{
int ret = av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
if (ret < 0) {
av_frame_side_data_set_uninit(dst);
return ret;
}
}

av_dict_copy(&sd_dst->metadata, sd_src->metadata, 0);
}

return 0;
}

AVFrameSideData *av_side_data_set_get_item(const AVFrameSideDataSet set,
enum AVFrameSideDataType type)
AVFrameSideData *av_frame_side_data_set_get_item(const AVFrameSideDataSet set,
enum AVFrameSideDataType type)
{
for (int i = 0; i < set.nb_sd; i++) {
if (set.sd[i]->type == type)
Expand All @@ -916,7 +924,7 @@ AVFrameSideData *av_side_data_set_get_item(const AVFrameSideDataSet set,
AVFrameSideData *av_frame_get_side_data(const AVFrame *frame,
enum AVFrameSideDataType type)
{
return av_side_data_set_get_item(
return av_frame_side_data_set_get_item(
(const AVFrameSideDataSet){
.sd = frame->side_data,
.nb_sd = frame->nb_side_data
Expand Down Expand Up @@ -1014,14 +1022,7 @@ FF_ENABLE_DEPRECATION_WARNINGS

void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
{
for (int i = frame->nb_side_data - 1; i >= 0; i--) {
AVFrameSideData *sd = frame->side_data[i];
if (sd->type == type) {
free_side_data(&frame->side_data[i]);
frame->side_data[i] = frame->side_data[frame->nb_side_data - 1];
frame->nb_side_data--;
}
}
remove_side_data(&frame->side_data, &frame->nb_side_data, type);
}

const char *av_frame_side_data_name(enum AVFrameSideDataType type)
Expand Down
39 changes: 20 additions & 19 deletions libavutil/frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -1063,41 +1063,42 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type);
*
* @param set the set which should be uninitialized
*/
void av_side_data_set_uninit(AVFrameSideDataSet *set);
void av_frame_side_data_set_uninit(AVFrameSideDataSet *set);

#define AV_FRAME_SIDE_DATA_SET_FLAG_NO_DUPLICATES (1 << 0)

/**
* Add a new side data entry to a set.
*
* @param set a set to which the side data should be added
* @param type type of the added side data
* @param size size of the side data
* @param allow_duplicates an unsigned integer noting whether duplicates are
* allowed or not. If duplicates are not allowed, all
* entries of the same side data type are first removed
* and freed before the new entry is added.
* @param flags Some combination of AV_FRAME_SIDE_DATA_SET_FLAG_* flags, or 0.
*
* @return newly added side data on success, NULL on error
* @return newly added side data on success, NULL on error. In case of
* AV_FRAME_SIDE_DATA_SET_FLAG_NO_DUPLICATES being set, entries
* of matching AVFrameSideDataType will be removed before the
* addition is attempted.
*/
AVFrameSideData *av_side_data_set_new_item(AVFrameSideDataSet *set,
enum AVFrameSideDataType type,
size_t size,
unsigned int allow_duplicates);
AVFrameSideData *av_frame_side_data_set_new_item(AVFrameSideDataSet *set,
enum AVFrameSideDataType type,
size_t size,
unsigned int flags);

/**
* Add multiple side data entries to a set in one go.
*
* @param dst a set to which the side data should be added
* @param src a set from which the side data should be copied from
* @param allow_duplicates an unsigned integer noting whether duplicates are
* allowed or not. If duplicates are not allowed, all
* entries of the same side data type are first removed
* and freed before the new entry is added.
* @param flags Some combination of AV_FRAME_SIDE_DATA_SET_FLAG_* flags, or 0.
*
* @return negative error code on failure, >=0 on success.
*
* @see av_frame_side_data_set_new_item regarding the flags.
*/
int av_side_data_set_extend(AVFrameSideDataSet *dst,
const AVFrameSideDataSet src,
unsigned int allow_duplicates);
int av_frame_side_data_set_extend(AVFrameSideDataSet *dst,
const AVFrameSideDataSet src,
unsigned int flags);

/**
* Get a side data entry of a specific type from a set.
Expand All @@ -1108,8 +1109,8 @@ int av_side_data_set_extend(AVFrameSideDataSet *dst,
* @return a pointer to the side data of a given type on success, NULL if there
* is no side data with such type in this set.
*/
AVFrameSideData *av_side_data_set_get_item(const AVFrameSideDataSet set,
enum AVFrameSideDataType type);
AVFrameSideData *av_frame_side_data_set_get_item(const AVFrameSideDataSet set,
enum AVFrameSideDataType type);

/**
* @}
Expand Down
17 changes: 14 additions & 3 deletions libavutil/hwcontext_vulkan.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ typedef struct VulkanDevicePriv {
VkPhysicalDeviceVulkan13Features device_features_1_3;
VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features;
VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_features;
VkPhysicalDeviceCooperativeMatrixFeaturesKHR coop_matrix_features;

/* Queues */
pthread_mutex_t **qf_mutex;
Expand Down Expand Up @@ -405,6 +406,7 @@ static const VulkanOptExtension optional_device_exts[] = {
{ VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, },
{ VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM },
{ VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT },
{ VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, FF_VK_EXT_COOP_MATRIX },

/* Imports/exports */
{ VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY },
Expand Down Expand Up @@ -1202,9 +1204,13 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
VkPhysicalDeviceTimelineSemaphoreFeatures timeline_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
};
VkPhysicalDeviceCooperativeMatrixFeaturesKHR coop_matrix_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR,
.pNext = &timeline_features,
};
VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT,
.pNext = &timeline_features,
.pNext = &coop_matrix_features,
};
VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT,
Expand Down Expand Up @@ -1242,7 +1248,9 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
p->desc_buf_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT;
p->desc_buf_features.pNext = &p->atomic_float_features;
p->atomic_float_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT;
p->atomic_float_features.pNext = NULL;
p->atomic_float_features.pNext = &p->coop_matrix_features;
p->coop_matrix_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR;
p->coop_matrix_features.pNext = NULL;

ctx->free = vulkan_device_free;

Expand Down Expand Up @@ -1304,6 +1312,8 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
p->atomic_float_features.shaderBufferFloat32Atomics = atomic_float_features.shaderBufferFloat32Atomics;
p->atomic_float_features.shaderBufferFloat32AtomicAdd = atomic_float_features.shaderBufferFloat32AtomicAdd;

p->coop_matrix_features.cooperativeMatrix = coop_matrix_features.cooperativeMatrix;

dev_info.pNext = &hwctx->device_features;

/* Setup queue family */
Expand Down Expand Up @@ -2179,7 +2189,8 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size)
}

err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags,
hwctx->nb_layers, eiinfo.handleTypes ? &eiinfo : NULL);
hwctx->nb_layers,
eiinfo.handleTypes ? &eiinfo : hwctx->create_pnext);
if (err)
return NULL;

Expand Down
15 changes: 8 additions & 7 deletions libavutil/riscv/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@
#if HAVE_INLINE_ASM
#include <stdint.h>

static inline uint64_t rdcycle64(void)
static inline uint64_t ff_read_time(void)
{
#if (__riscv_xlen >= 64)
uintptr_t cycles;

__asm__ volatile ("rdcycle %0" : "=r"(cycles));
__asm__ ("rdtime %0" : "=r" (cycles));

#else
uint64_t cycles;
uint32_t hi, lo, check;

__asm__ volatile (
"1: rdcycleh %0\n"
" rdcycle %1\n"
" rdcycleh %2\n"
__asm__ (
"1: rdtimeh %0\n"
" rdtime %1\n"
" rdtimeh %2\n"
" bne %0, %2, 1b\n" : "=r" (hi), "=r" (lo), "=r" (check));

cycles = (((uint64_t)hi) << 32) | lo;
Expand All @@ -47,7 +47,8 @@ static inline uint64_t rdcycle64(void)
return cycles;
}

#define AV_READ_TIME rdcycle64
#define AV_READ_TIME ff_read_time
#define FF_TIMER_UNITS "ticks"

#endif
#endif /* AVUTIL_RISCV_TIMER_H */
58 changes: 50 additions & 8 deletions libavutil/tests/side_data_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,61 @@ static void print_clls(const AVFrameSideDataSet set)
for (int i = 0; i < set.nb_sd; i++) {
AVFrameSideData *sd = set.sd[i];

if (sd->type != AV_FRAME_DATA_CONTENT_LIGHT_LEVEL)
printf("sd %d, %s",
i, av_frame_side_data_name(sd->type));

if (sd->type != AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) {
putchar('\n');
continue;
}

printf("sd %d, MaxCLL: %u\n",
i, ((AVContentLightMetadata *)sd->data)->MaxCLL);
printf(": MaxCLL: %u\n",
((AVContentLightMetadata *)sd->data)->MaxCLL);
}
}

int main(void)
{
AVFrameSideDataSet set = { 0 };

av_assert0(
av_frame_side_data_set_new_item(
&set, AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT, 0, 0));

// test entries in the middle
for (int value = 1; value < 4; value++) {
AVFrameSideData *sd = av_side_data_set_new_item(
AVFrameSideData *sd = av_frame_side_data_set_new_item(
&set, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
sizeof(AVContentLightMetadata), 1);
sizeof(AVContentLightMetadata), 0);

av_assert0(sd);

((AVContentLightMetadata *)sd->data)->MaxCLL = value;
}

av_assert0(
av_frame_side_data_set_new_item(
&set, AV_FRAME_DATA_SPHERICAL, 0, 0));

// test entries at the end
for (int value = 1; value < 4; value++) {
AVFrameSideData *sd = av_frame_side_data_set_new_item(
&set, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
sizeof(AVContentLightMetadata), 0);

av_assert0(sd);

((AVContentLightMetadata *)sd->data)->MaxCLL = value + 3;
}

puts("Initial addition results with duplicates:");
print_clls(set);

{
AVFrameSideData *sd = av_side_data_set_new_item(
AVFrameSideData *sd = av_frame_side_data_set_new_item(
&set, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL,
sizeof(AVContentLightMetadata), 0);
sizeof(AVContentLightMetadata),
AV_FRAME_SIDE_DATA_SET_FLAG_NO_DUPLICATES);

av_assert0(sd);

Expand All @@ -65,7 +91,23 @@ int main(void)
puts("\nFinal state after a single 'no-duplicates' addition:");
print_clls(set);

av_side_data_set_uninit(&set);
{
AVFrameSideDataSet dst_set = { 0 };
av_assert0(av_frame_side_data_set_extend(&dst_set, set, 0) >= 0);

puts("\nState of the copied set:");
print_clls(dst_set);

av_frame_side_data_set_uninit(&dst_set);
}

{
int ret = av_frame_side_data_set_extend(&set, set, 0);
printf("\nResult of trying to extend a set by itself: %s\n",
av_err2str(ret));
}

av_frame_side_data_set_uninit(&set);

return 0;
}
19 changes: 19 additions & 0 deletions libavutil/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,15 @@ static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_
#define ff_mutex_unlock pthread_mutex_unlock
#define ff_mutex_destroy pthread_mutex_destroy

#define AVCond pthread_cond_t

#define ff_cond_init pthread_cond_init
#define ff_cond_destroy pthread_cond_destroy
#define ff_cond_signal pthread_cond_signal
#define ff_cond_broadcast pthread_cond_broadcast
#define ff_cond_wait pthread_cond_wait
#define ff_cond_timedwait pthread_cond_timedwait

#define AVOnce pthread_once_t
#define AV_ONCE_INIT PTHREAD_ONCE_INIT

Expand All @@ -178,6 +187,16 @@ static inline int ff_mutex_lock(AVMutex *mutex){ return 0; }
static inline int ff_mutex_unlock(AVMutex *mutex){ return 0; }
static inline int ff_mutex_destroy(AVMutex *mutex){ return 0; }

#define AVCond char

static inline int ff_cond_init(AVCond *cond, const void *attr){ return 0; }
static inline int ff_cond_destroy(AVCond *cond){ return 0; }
static inline int ff_cond_signal(AVCond *cond){ return 0; }
static inline int ff_cond_broadcast(AVCond *cond){ return 0; }
static inline int ff_cond_wait(AVCond *cond, AVMutex *mutex){ return 0; }
static inline int ff_cond_timedwait(AVCond *cond, AVMutex *mutex,
const void *abstime){ return 0; }

#define AVOnce char
#define AV_ONCE_INIT 0

Expand Down
4 changes: 2 additions & 2 deletions libavutil/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@
*/

#define LIBAVUTIL_VERSION_MAJOR 58
#define LIBAVUTIL_VERSION_MINOR 16
#define LIBAVUTIL_VERSION_MICRO 101
#define LIBAVUTIL_VERSION_MINOR 17
#define LIBAVUTIL_VERSION_MICRO 100

#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
Expand Down
27 changes: 26 additions & 1 deletion libavutil/vulkan.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,13 @@ int ff_vk_load_props(FFVulkanContext *s)
s->hprops = (VkPhysicalDeviceExternalMemoryHostPropertiesEXT) {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT,
};
s->coop_matrix_props = (VkPhysicalDeviceCooperativeMatrixPropertiesKHR) {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
.pNext = &s->hprops,
};
s->subgroup_props = (VkPhysicalDeviceSubgroupSizeControlProperties) {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES,
.pNext = &s->hprops,
.pNext = &s->coop_matrix_props,
};
s->desc_buf_props = (VkPhysicalDeviceDescriptorBufferPropertiesEXT) {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT,
Expand Down Expand Up @@ -161,6 +165,25 @@ int ff_vk_load_props(FFVulkanContext *s)

vk->GetPhysicalDeviceQueueFamilyProperties2(s->hwctx->phys_dev, &s->tot_nb_qfs, s->qf_props);

if (s->extensions & FF_VK_EXT_COOP_MATRIX) {
vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
&s->coop_mat_props_nb, NULL);

if (s->coop_mat_props_nb) {
s->coop_mat_props = av_malloc_array(s->coop_mat_props_nb,
sizeof(VkCooperativeMatrixPropertiesKHR));
for (int i = 0; i < s->coop_mat_props_nb; i++) {
s->coop_mat_props[i] = (VkCooperativeMatrixPropertiesKHR) {
.sType = VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR,
};
}

vk->GetPhysicalDeviceCooperativeMatrixPropertiesKHR(s->hwctx->phys_dev,
&s->coop_mat_props_nb,
s->coop_mat_props);
}
}

return 0;
}

Expand Down Expand Up @@ -1861,6 +1884,7 @@ void ff_vk_pipeline_free(FFVulkanContext *s, FFVulkanPipeline *pl)

av_freep(&pl->desc_set);
av_freep(&pl->desc_bind);
av_freep(&pl->bound_buffer_indices);
av_freep(&pl->push_consts);
pl->push_consts_num = 0;
}
Expand All @@ -1870,6 +1894,7 @@ void ff_vk_uninit(FFVulkanContext *s)
av_freep(&s->query_props);
av_freep(&s->qf_props);
av_freep(&s->video_props);
av_freep(&s->coop_mat_props);

av_buffer_unref(&s->frames_ref);
}
4 changes: 4 additions & 0 deletions libavutil/vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,15 @@ typedef struct FFVulkanContext {
VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops;
VkPhysicalDeviceDescriptorBufferPropertiesEXT desc_buf_props;
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_props;
VkPhysicalDeviceCooperativeMatrixPropertiesKHR coop_matrix_props;
VkQueueFamilyQueryResultStatusPropertiesKHR *query_props;
VkQueueFamilyVideoPropertiesKHR *video_props;
VkQueueFamilyProperties2 *qf_props;
int tot_nb_qfs;

VkCooperativeMatrixPropertiesKHR *coop_mat_props;
uint32_t coop_mat_props_nb;

VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_feats;
VkPhysicalDeviceVulkan12Features feats_12;
VkPhysicalDeviceFeatures2 feats;
Expand Down
2 changes: 2 additions & 0 deletions libavutil/vulkan_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ typedef enum FFVulkanExtensions {
FF_VK_EXT_VIDEO_DECODE_H265 = 1ULL << 13, /* VK_EXT_video_decode_h265 */
FF_VK_EXT_VIDEO_DECODE_AV1 = 1ULL << 14, /* VK_MESA_video_decode_av1 */
FF_VK_EXT_ATOMIC_FLOAT = 1ULL << 15, /* VK_EXT_shader_atomic_float */
FF_VK_EXT_COOP_MATRIX = 1ULL << 16, /* VK_KHR_cooperative_matrix */

FF_VK_EXT_NO_FLAG = 1ULL << 31,
} FFVulkanExtensions;
Expand Down Expand Up @@ -80,6 +81,7 @@ typedef enum FFVulkanExtensions {
MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceImageFormatProperties2) \
MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties) \
MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties2) \
MACRO(1, 0, FF_VK_EXT_COOP_MATRIX, GetPhysicalDeviceCooperativeMatrixPropertiesKHR) \
\
/* Command pool */ \
MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateCommandPool) \
Expand Down
1 change: 1 addition & 0 deletions libavutil/vulkan_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions,
{ VK_EXT_DEBUG_UTILS_EXTENSION_NAME, FF_VK_EXT_DEBUG_UTILS },
{ VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM },
{ VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT },
{ VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, FF_VK_EXT_COOP_MATRIX },
#ifdef _WIN32
{ VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY },
{ VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM },
Expand Down
1 change: 1 addition & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ include $(SRC_PATH)/tests/fate/image.mak
include $(SRC_PATH)/tests/fate/imf.mak
include $(SRC_PATH)/tests/fate/indeo.mak
include $(SRC_PATH)/tests/fate/jpeg2000.mak
include $(SRC_PATH)/tests/fate/jxl.mak
include $(SRC_PATH)/tests/fate/libavcodec.mak
include $(SRC_PATH)/tests/fate/libavdevice.mak
include $(SRC_PATH)/tests/fate/libavformat.mak
Expand Down
2 changes: 1 addition & 1 deletion tests/checkasm/hevc_sao.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ static void check_sao_edge(HEVCDSPContext *h, int bit_depth)
if (memcmp(dst0 + j*stride, dst1 + j*stride, w*SIZEOF_PIXEL))
fail();
}
bench_new(dst1, src1 + offset, stride, offset_val, eo, block_size, block_size);
}
bench_new(dst1, src1 + offset, stride, offset_val, eo, block_size, block_size);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/fate/enc_external.mak
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fate-libsvtav1-hdr10: CMD = enc_external $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_
mp4 "-c:v libsvtav1" "-show_frames -show_entries frame=side_data_list -of flat"

# test for x264 MDCV and CLL passthrough during encoding
FATE_ENC_EXTERNAL-$(call ENCDEC, LIBX264 HEVC, MOV, HEVC_DEMUXER H264_DECODER) += fate-libx264-hdr10
FATE_ENC_EXTERNAL-$(call ENCDEC, LIBX264 HEVC, MOV, LIBX264_HDR10 HEVC_DEMUXER H264_DECODER) += fate-libx264-hdr10
fate-libx264-hdr10: CMD = enc_external $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_sample.hevc \
mp4 "-c:v libx264" "-show_frames -show_entries frame=side_data_list -of flat"

Expand Down
16 changes: 16 additions & 0 deletions tests/fate/jxl.mak
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# These two are animated JXL files
FATE_JPEGXL_ANIM_DEMUX += fate-jxl-anim-demux-newton
fate-jxl-anim-demux-newton: CMD = framecrc -i $(TARGET_SAMPLES)/jxl/newton.jxl -c copy
FATE_JPEGXL_ANIM_DEMUX += fate-jxl-anim-demux-icos4d
fate-jxl-anim-demux-icos4d: CMD = framecrc -i $(TARGET_SAMPLES)/jxl/icos4d.jxl -c copy

# These two are not animated JXL. They are here to check false positives.
FATE_JPEGXL_ANIM_DEMUX += fate-jxl-anim-demux-belgium
fate-jxl-anim-demux-belgium: CMD = framecrc -i $(TARGET_SAMPLES)/jxl/belgium.jxl -c copy
FATE_JPEGXL_ANIM_DEMUX += fate-jxl-anim-demux-lenna256
fate-jxl-anim-demux-lenna256: CMD = framecrc -i $(TARGET_SAMPLES)/jxl/lenna-256.jxl -c copy

FATE_JPEGXL_ANIM_DEMUX += $(FATE_JPEGXL_ANIM_DEMUX-yes)

FATE_SAMPLES_FFMPEG-$(call FRAMECRC, JPEGXL_ANIM) += $(FATE_JPEGXL_ANIM_DEMUX)
fate-jxl-anim-demux: $(FATE_JPEGXL_ANIM_DEMUX)
6 changes: 3 additions & 3 deletions tests/fate/matroska.mak
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,10 @@ FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, MATROSKA, OGG_DEMUXER THEORA_DECODER)
fate-matroska-stereo_mode: CMD = transcode ogg $(TARGET_SAMPLES)/vp3/offset_test.ogv matroska \
"-c copy -write_crc32 0 -default_mode infer \
-map 0 -disposition:s:0 +original+dub -metadata:s:0 language=ger \
-map 0 -metadata:s:1 stereo_mode=left_right -metadata:s:1 language=ger-at -metadata:s:1 description-ger=Deutsch -metadata:s:1 description-fre=Français \
-map 0 -metadata:s:2 stereo_mode=bottom_top -metadata:s:2 language=eng -metadata:s:2 description-de=Deutsch -metadata:s:2 description-fra=Français \
-map 0 -metadata:s:1 stereo_mode=left_right -metadata:s:1 language=ger-at -metadata:s:1 description-ger=Deutsch -metadata:s:1 description-fre=Francais \
-map 0 -metadata:s:2 stereo_mode=bottom_top -metadata:s:2 language=eng -metadata:s:2 description-de=Deutsch -metadata:s:2 description-fra=Francais \
-map 0 -metadata:s:3 stereo_mode=row_interleaved_rl -sar:3 3:1 -disposition:3 +default -metadata:s:3 language=deu-at \
-map 0 -metadata:s:4 stereo_mode=col_interleaved_rl -sar:4 16:9 -metadata:s:4 language=fre -metadata:s:4 description-deu-at=Österreichisch \
-map 0 -metadata:s:4 stereo_mode=col_interleaved_rl -sar:4 16:9 -metadata:s:4 language=fre -metadata:s:4 description-deu-at=Oesterreichisch \
-map 0 -metadata:s:5 stereo_mode=anaglyph_cyan_red -sar:5 16:9 -disposition:5 +default -metadata:s:5 language=fra \
-map 0 -metadata:s:6 stereo_mode=12 -sar:6 2:1 -metadata:s:6 language=de -metadata:s:6 description-deu=Deutsch" \
"-map 0 -c copy" \
Expand Down
3 changes: 3 additions & 0 deletions tests/fate/monkeysaudio.mak
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ $(foreach N,$(APE_VERSIONS),$(eval $(call FATE_APE_SUITE,$(N))))
FATE_APE += fate-lossless-monkeysaudio-399
fate-lossless-monkeysaudio-399: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/luckynight-partial.ape -f s16le -af aresample

FATE_APE += fate-lossless-monkeysaudio-legacy
fate-lossless-monkeysaudio-legacy: CMD = md5 -i $(TARGET_SAMPLES)/lossless-audio/NoLegacy-cut.ape -f s32le -af aresample

FATE_SAMPLES_AVCONV-$(call DEMDEC, APE, APE) += $(FATE_APE)
fate-lossless-monkeysaudio: $(FATE_APE)
6 changes: 6 additions & 0 deletions tests/ref/fate/jxl-anim-demux-belgium
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#tb 0: 1/25
#media_type 0: video
#codec_id 0: jpegxl
#dimensions 0: 768x512
#sar 0: 0/1
0, 0, 0, 1, 32, 0xa2930a20
6 changes: 6 additions & 0 deletions tests/ref/fate/jxl-anim-demux-icos4d
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#tb 0: 1/1000
#media_type 0: video
#codec_id 0: jpegxl
#dimensions 0: 48x48
#sar 0: 0/1
0, 0, 0, 0, 67898, 0x53b6516b
6 changes: 6 additions & 0 deletions tests/ref/fate/jxl-anim-demux-lenna256
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#tb 0: 1/25
#media_type 0: video
#codec_id 0: jpegxl
#dimensions 0: 256x256
#sar 0: 0/1
0, 0, 0, 1, 8088, 0xbbfea9bd
6 changes: 6 additions & 0 deletions tests/ref/fate/jxl-anim-demux-newton
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#tb 0: 1/1000
#media_type 0: video
#codec_id 0: jpegxl
#dimensions 0: 128x96
#sar 0: 0/1
0, 0, 0, 0, 43376, 0xb2296182
1 change: 1 addition & 0 deletions tests/ref/fate/lossless-monkeysaudio-legacy
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2cd8a60478c77382dfed8b8bdf1f70e4
12 changes: 7 additions & 5 deletions tests/ref/fate/matroska-stereo_mode
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
1f074fcfb6f64ade0ad4b01f9e910515 *tests/data/fate/matroska-stereo_mode.matroska
1470758 tests/data/fate/matroska-stereo_mode.matroska
a7a220a77001e81685ec807ce5ac3bc6 *tests/data/fate/matroska-stereo_mode.matroska
1470764 tests/data/fate/matroska-stereo_mode.matroska
#extradata 0: 3510, 0x560c3919
#extradata 1: 3510, 0x560c3919
#extradata 2: 3510, 0x560c3919
Expand Down Expand Up @@ -126,7 +126,7 @@ DISPOSITION:original=0
TAG:language=ger-at
TAG:stereo_mode=left_right
TAG:DESCRIPTION-ger=Deutsch
TAG:DESCRIPTION-fre=Français
TAG:DESCRIPTION-fre=Francais
TAG:DURATION=00:00:10.000000000
[SIDE_DATA]
side_data_type=Stereo 3D
Expand All @@ -141,7 +141,7 @@ DISPOSITION:original=0
TAG:language=eng
TAG:stereo_mode=bottom_top
TAG:DESCRIPTION-ger=Deutsch
TAG:DESCRIPTION-fre=Français
TAG:DESCRIPTION-fre=Francais
TAG:DURATION=00:00:10.000000000
[SIDE_DATA]
side_data_type=Stereo 3D
Expand All @@ -168,7 +168,7 @@ DISPOSITION:dub=0
DISPOSITION:original=0
TAG:language=fre
TAG:stereo_mode=col_interleaved_rl
TAG:DESCRIPTION-DEU-AT=Österreichisch
TAG:DESCRIPTION-DEU-AT=Oesterreichisch
TAG:DURATION=00:00:10.000000000
[SIDE_DATA]
side_data_type=Stereo 3D
Expand All @@ -181,13 +181,15 @@ DISPOSITION:default=1
DISPOSITION:dub=0
DISPOSITION:original=0
TAG:language=fra
TAG:stereo_mode=anaglyph_cyan_red
TAG:DURATION=00:00:10.000000000
[/STREAM]
[STREAM]
DISPOSITION:default=0
DISPOSITION:dub=0
DISPOSITION:original=0
TAG:language=de
TAG:stereo_mode=anaglyph_green_magenta
TAG:DESCRIPTION-ger=Deutsch
TAG:DURATION=00:00:10.000000000
[/STREAM]
22 changes: 18 additions & 4 deletions tests/ref/fate/side_data_set
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
Initial addition results with duplicates:
sd 0, MaxCLL: 1
sd 1, MaxCLL: 2
sd 2, MaxCLL: 3
sd 0, Ambient viewing environment
sd 1, Content light level metadata: MaxCLL: 1
sd 2, Content light level metadata: MaxCLL: 2
sd 3, Content light level metadata: MaxCLL: 3
sd 4, Spherical Mapping
sd 5, Content light level metadata: MaxCLL: 4
sd 6, Content light level metadata: MaxCLL: 5
sd 7, Content light level metadata: MaxCLL: 6

Final state after a single 'no-duplicates' addition:
sd 0, MaxCLL: 1337
sd 0, Ambient viewing environment
sd 1, Spherical Mapping
sd 2, Content light level metadata: MaxCLL: 1337

State of the copied set:
sd 0, Ambient viewing environment
sd 1, Spherical Mapping
sd 2, Content light level metadata: MaxCLL: 1337

Result of trying to extend a set by itself: Invalid argument
182 changes: 91 additions & 91 deletions tests/ref/fate/sub2video_basic
Original file line number Diff line number Diff line change
@@ -1,95 +1,95 @@
#tb 0: 1/25
#tb 0: 1/1000
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 720x480
#sar 0: 0/1
0, 3312, 3312, 1, 1382400, 0x00000000
0, 3312, 3312, 1, 1382400, 0x8c93c2ba
0, 3436, 3436, 1, 1382400, 0x00000000
0, 3684, 3684, 1, 1382400, 0xb02e32ca
0, 3802, 3802, 1, 1382400, 0x00000000
0, 4520, 4520, 1, 1382400, 0x83b71116
0, 4584, 4584, 1, 1382400, 0x00000000
0, 4586, 4586, 1, 1382400, 0x85547fd1
0, 4645, 4645, 1, 1382400, 0x00000000
0, 4648, 4648, 1, 1382400, 0x00000000
0, 4648, 4648, 1, 1382400, 0xb6a8f181
0, 4715, 4715, 1, 1382400, 0x00000000
0, 4717, 4717, 1, 1382400, 0xb64d1a2c
0, 4748, 4748, 1, 1382400, 0x00000000
0, 4750, 4750, 1, 1382400, 0x7b37ecf3
0, 4792, 4792, 1, 1382400, 0x00000000
0, 4993, 4993, 1, 1382400, 0xdc025bd1
0, 5027, 5027, 1, 1382400, 0x00000000
0, 5029, 5029, 1, 1382400, 0x688b294d
0, 5068, 5068, 1, 1382400, 0x00000000
0, 5070, 5070, 1, 1382400, 0xa2b33d1b
0, 5117, 5117, 1, 1382400, 0x00000000
0, 5119, 5119, 1, 1382400, 0xb3e525e3
0, 5168, 5168, 1, 1382400, 0x00000000
0, 5170, 5170, 1, 1382400, 0xaa8fbdd7
0, 5216, 5216, 1, 1382400, 0x00000000
0, 5218, 5218, 1, 1382400, 0x7b7f26dd
0, 5249, 5249, 1, 1382400, 0x00000000
0, 5251, 5251, 1, 1382400, 0x15e2f836
0, 5289, 5289, 1, 1382400, 0x00000000
0, 5291, 5291, 1, 1382400, 0x0fee9b0c
0, 5358, 5358, 1, 1382400, 0x00000000
0, 5360, 5360, 1, 1382400, 0x89d62791
0, 5429, 5429, 1, 1382400, 0x00000000
0, 5431, 5431, 1, 1382400, 0xa6a9fd74
0, 5490, 5490, 1, 1382400, 0x00000000
0, 5491, 5491, 1, 1382400, 0x7896178d
0, 5537, 5537, 1, 1382400, 0x00000000
0, 5588, 5588, 1, 1382400, 0x01751a52
0, 5647, 5647, 1, 1382400, 0x00000000
0, 5688, 5688, 1, 1382400, 0xa3959c6f
0, 5770, 5770, 1, 1382400, 0x00000000
0, 5772, 5772, 1, 1382400, 0x3d3ea47b
0, 5826, 5826, 1, 1382400, 0x00000000
0, 5828, 5828, 1, 1382400, 0x593f8b24
0, 5931, 5931, 1, 1382400, 0x00000000
0, 5933, 5933, 1, 1382400, 0x171f05ba
0, 6001, 6001, 1, 1382400, 0x00000000
0, 6003, 6003, 1, 1382400, 0xb014cdf1
0, 6054, 6054, 1, 1382400, 0x00000000
0, 6839, 6839, 1, 1382400, 0xd918e667
0, 6880, 6880, 1, 1382400, 0x00000000
0, 7386, 7386, 1, 1382400, 0xc9406331
0, 7419, 7419, 1, 1382400, 0x00000000
0, 7501, 7501, 1, 1382400, 0xaf08b10d
0, 7549, 7549, 1, 1382400, 0x00000000
0, 7551, 7551, 1, 1382400, 0x00000000
0, 7551, 7551, 1, 1382400, 0x853a9d93
0, 7589, 7589, 1, 1382400, 0x00000000
0, 7605, 7605, 1, 1382400, 0x7491a87d
0, 7647, 7647, 1, 1382400, 0x00000000
0, 7649, 7649, 1, 1382400, 0xf7383c58
0, 7697, 7697, 1, 1382400, 0x00000000
0, 7699, 7699, 1, 1382400, 0xe66be411
0, 7743, 7743, 1, 1382400, 0x00000000
0, 8032, 8032, 1, 1382400, 0xd6850362
0, 8082, 8082, 1, 1382400, 0x00000000
0, 8084, 8084, 1, 1382400, 0x3e1ed109
0, 8115, 8115, 1, 1382400, 0x00000000
0, 8116, 8116, 1, 1382400, 0x39c1b7bd
0, 8160, 8160, 1, 1382400, 0x00000000
0, 8180, 8180, 1, 1382400, 0x35b85f2e
0, 8207, 8207, 1, 1382400, 0x00000000
0, 8209, 8209, 1, 1382400, 0x00000000
0, 8209, 8209, 1, 1382400, 0x83f103e5
0, 8247, 8247, 1, 1382400, 0x00000000
0, 8249, 8249, 1, 1382400, 0xbc1ca9b3
0, 8278, 8278, 1, 1382400, 0x00000000
0, 8281, 8281, 1, 1382400, 0x94d4a51e
0, 8321, 8321, 1, 1382400, 0x00000000
0, 8323, 8323, 1, 1382400, 0xf88cdfde
0, 8367, 8367, 1, 1382400, 0x00000000
0, 8565, 8565, 1, 1382400, 0xdd51423b
0, 8611, 8611, 1, 1382400, 0x00000000
0, 8669, 8669, 1, 1382400, 0x08259fa4
0, 8708, 8708, 1, 1382400, 0x00000000
0, 8941, 8941, 1, 1382400, 0x1663fa34
0, 8994, 8994, 1, 1382400, 0x00000000
0, 8996, 8996, 1, 1382400, 0xda2ceb55
0, 9027, 9027, 1, 1382400, 0x00000000
0, 132499, 132499, 0, 1382400, 0x00000000
0, 132499, 132499, 0, 1382400, 0x8c93c2ba
0, 137459, 137459, 0, 1382400, 0x00000000
0, 147355, 147355, 0, 1382400, 0xb02e32ca
0, 152088, 152088, 0, 1382400, 0x00000000
0, 180797, 180797, 0, 1382400, 0x83b71116
0, 183357, 183357, 0, 1382400, 0x00000000
0, 183433, 183433, 0, 1382400, 0x85547fd1
0, 185799, 185799, 0, 1382400, 0x00000000
0, 185909, 185909, 0, 1382400, 0x00000000
0, 185910, 185910, 0, 1382400, 0xb6a8f181
0, 188606, 188606, 0, 1382400, 0x00000000
0, 188663, 188663, 0, 1382400, 0xb64d1a2c
0, 189925, 189925, 0, 1382400, 0x00000000
0, 190014, 190014, 0, 1382400, 0x7b37ecf3
0, 191675, 191675, 0, 1382400, 0x00000000
0, 199724, 199724, 0, 1382400, 0xdc025bd1
0, 201089, 201089, 0, 1382400, 0x00000000
0, 201175, 201175, 0, 1382400, 0x688b294d
0, 202733, 202733, 0, 1382400, 0x00000000
0, 202819, 202819, 0, 1382400, 0xa2b33d1b
0, 204684, 204684, 0, 1382400, 0x00000000
0, 204762, 204762, 0, 1382400, 0xb3e525e3
0, 206730, 206730, 0, 1382400, 0x00000000
0, 206806, 206806, 0, 1382400, 0xaa8fbdd7
0, 208637, 208637, 0, 1382400, 0x00000000
0, 208716, 208716, 0, 1382400, 0x7b7f26dd
0, 209978, 209978, 0, 1382400, 0x00000000
0, 210051, 210051, 0, 1382400, 0x15e2f836
0, 211575, 211575, 0, 1382400, 0x00000000
0, 211644, 211644, 0, 1382400, 0x0fee9b0c
0, 214306, 214306, 0, 1382400, 0x00000000
0, 214380, 214380, 0, 1382400, 0x89d62791
0, 217144, 217144, 0, 1382400, 0x00000000
0, 217225, 217225, 0, 1382400, 0xa6a9fd74
0, 219591, 219591, 0, 1382400, 0x00000000
0, 219652, 219652, 0, 1382400, 0x7896178d
0, 221483, 221483, 0, 1382400, 0x00000000
0, 223531, 223531, 0, 1382400, 0x01751a52
0, 225863, 225863, 0, 1382400, 0x00000000
0, 227510, 227510, 0, 1382400, 0xa3959c6f
0, 230809, 230809, 0, 1382400, 0x00000000
0, 230872, 230872, 0, 1382400, 0x3d3ea47b
0, 233033, 233033, 0, 1382400, 0x00000000
0, 233124, 233124, 0, 1382400, 0x593f8b24
0, 237220, 237220, 0, 1382400, 0x00000000
0, 237303, 237303, 0, 1382400, 0x171f05ba
0, 240033, 240033, 0, 1382400, 0x00000000
0, 240106, 240106, 0, 1382400, 0xb014cdf1
0, 242165, 242165, 0, 1382400, 0x00000000
0, 273556, 273556, 0, 1382400, 0xd918e667
0, 275217, 275217, 0, 1382400, 0x00000000
0, 295445, 295445, 0, 1382400, 0xc9406331
0, 296776, 296776, 0, 1382400, 0x00000000
0, 300049, 300049, 0, 1382400, 0xaf08b10d
0, 301949, 301949, 0, 1382400, 0x00000000
0, 302034, 302034, 0, 1382400, 0x00000000
0, 302035, 302035, 0, 1382400, 0x853a9d93
0, 303559, 303559, 0, 1382400, 0x00000000
0, 304203, 304203, 0, 1382400, 0x7491a87d
0, 305898, 305898, 0, 1382400, 0x00000000
0, 305947, 305947, 0, 1382400, 0xf7383c58
0, 307881, 307881, 0, 1382400, 0x00000000
0, 307957, 307957, 0, 1382400, 0xe66be411
0, 309720, 309720, 0, 1382400, 0x00000000
0, 321295, 321295, 0, 1382400, 0xd6850362
0, 323263, 323263, 0, 1382400, 0x00000000
0, 323356, 323356, 0, 1382400, 0x3e1ed109
0, 324584, 324584, 0, 1382400, 0x00000000
0, 324640, 324640, 0, 1382400, 0x39c1b7bd
0, 326403, 326403, 0, 1382400, 0x00000000
0, 327193, 327193, 0, 1382400, 0x35b85f2e
0, 328285, 328285, 0, 1382400, 0x00000000
0, 328360, 328360, 0, 1382400, 0x00000000
0, 328361, 328361, 0, 1382400, 0x83f103e5
0, 329885, 329885, 0, 1382400, 0x00000000
0, 329946, 329946, 0, 1382400, 0xbc1ca9b3
0, 331106, 331106, 0, 1382400, 0x00000000
0, 331230, 331230, 0, 1382400, 0x94d4a51e
0, 332857, 332857, 0, 1382400, 0x00000000
0, 332924, 332924, 0, 1382400, 0xf88cdfde
0, 334687, 334687, 0, 1382400, 0x00000000
0, 342600, 342600, 0, 1382400, 0xdd51423b
0, 344431, 344431, 0, 1382400, 0x00000000
0, 346771, 346771, 0, 1382400, 0x08259fa4
0, 348329, 348329, 0, 1382400, 0x00000000
0, 357640, 357640, 0, 1382400, 0x1663fa34
0, 359767, 359767, 0, 1382400, 0x00000000
0, 359834, 359834, 0, 1382400, 0xda2ceb55
0, 361096, 361096, 0, 1382400, 0x00000000
8 changes: 4 additions & 4 deletions tests/ref/fate/sub2video_time_limited
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#tb 0: 1/25
#tb 0: 1/90000
#media_type 0: video
#codec_id 0: rawvideo
#dimensions 0: 1920x1080
#sar 0: 0/1
0, 2, 2, 1, 8294400, 0x00000000
0, 2, 2, 1, 8294400, 0xa87c518f
0, 10, 10, 1, 8294400, 0xa87c518f
0, 6072, 6072, 0, 8294400, 0x00000000
0, 6072, 6072, 0, 8294400, 0xa87c518f
0, 36101, 36101, 0, 8294400, 0xa87c518f