Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 74 additions & 47 deletions demux/demux_lavf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1096,65 +1096,92 @@ static void build_editions(demuxer_t *demuxer)

#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(60, 19, 100)
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(60, 22, 100)
// Correct the display dimensions of the primary tile stream to the composed
// image size, and mark the remaining tile streams as dependent.
static void handle_tile_grid_group(demuxer_t *demuxer, AVStreamGroup *stg)
// Synthesize a virtual track that assembles an AVStreamGroupTileGrid.
static void handle_tile_grid_group(demuxer_t *demuxer, AVStreamGroup *stream_group)
{
lavf_priv_t *priv = demuxer->priv;
AVStreamGroupTileGrid *tile_grid = stg->params.tile_grid;

// AV_DISPOSITION_DEFAULT identifies the intended presentation stream.
AVStream *primary_st = NULL;
struct sh_stream *primary_sh = NULL;
for (unsigned i = 0; i < stg->nb_streams; i++) {
AVStream *st = stg->streams[i];
if (st->index < 0 || (unsigned)st->index >= (unsigned)priv->num_streams)
AVStreamGroupTileGrid *grid = stream_group->params.tile_grid;

MP_VERBOSE(demuxer, "Tile grid group: %u tiles -> %dx%d",
grid->nb_tiles, grid->width, grid->height);

struct sh_stream *vsh = demux_alloc_sh_stream(STREAM_VIDEO);
Comment thread
kasper93 marked this conversation as resolved.
vsh->group = talloc_zero(vsh, struct sh_stream_group);
MP_TARRAY_GROW(vsh->group, vsh->group->members, grid->nb_tiles);
char *graph = talloc_strdup(vsh->group, "");

for (int i = 0; i < grid->nb_tiles; i++) {
unsigned int group_idx = grid->offsets[i].idx;
if (group_idx >= stream_group->nb_streams) {
MP_ERR(demuxer, "Tile %d references out-of-range group "
"stream index %u (group has %u streams) – skipping.\n",
i, group_idx, stream_group->nb_streams);
continue;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make this hard error. It shouldn't happen really.

struct sh_stream *sh = priv->streams[st->index]->sh;
if (!sh)
continue;
if (st->disposition & AV_DISPOSITION_DEFAULT) {
primary_st = st;
primary_sh = sh;
break;
}
if (!primary_st) {
primary_st = st;
primary_sh = sh;

if (grid->offsets[i].horizontal >= grid->coded_width ||
grid->offsets[i].vertical >= grid->coded_height) {
MP_WARN(demuxer, "Tile grid offsets exceed coded canvas (%dx%d) -"
"ignoring tile grid.\n",
grid->coded_width, grid->coded_height);
goto error;
}

int ff_idx = stream_group->streams[group_idx]->index;
if (ff_idx >= 0 && ff_idx < priv->num_streams && priv->streams[ff_idx] &&
priv->streams[ff_idx]->sh) {
vsh->group->members[vsh->group->num_members++] = priv->streams[ff_idx]->sh;
} else {
MP_WARN(demuxer, "Tile grid offset %d is not associated to any stream.\n", i);
goto error;
}

graph = talloc_asprintf_append(graph, "[%d]", i);
}

if (!primary_sh) {
MP_WARN(demuxer, "Tile grid stream group %u has no usable streams.\n",
stg->index);
return;
graph = talloc_asprintf_append(graph, "xstack=inputs=%d:layout=", grid->nb_tiles);
for (int i = 0; i < grid->nb_tiles; i++) {
if (i > 0)
graph = talloc_asprintf_append(graph, "|");
graph = talloc_asprintf_append(graph, "%d_%d",
grid->offsets[i].horizontal, grid->offsets[i].vertical);
}
graph = talloc_asprintf_append(graph,
":fill=0x%02X%02X%02X@0x%02X",
grid->background[0], grid->background[1],
grid->background[2], grid->background[3]);

MP_VERBOSE(demuxer, "Tile grid group: %u tiles, canvas %dx%d, "
"visible %dx%d at offset (%d,%d)\n",
tile_grid->nb_tiles,
tile_grid->coded_width, tile_grid->coded_height,
tile_grid->width, tile_grid->height,
tile_grid->horizontal_offset, tile_grid->vertical_offset);
if (grid->coded_width != grid->width || grid->coded_height != grid->height) {
graph = talloc_asprintf_append(graph, ",crop=w=%d:h=%d:x=%d:y=%d",
grid->width, grid->height,
grid->horizontal_offset, grid->vertical_offset);
}

// width/height is the final visible region; coded_width/coded_height is
// the full canvas including padding — use the former for presentation.
primary_sh->codec->disp_w = tile_grid->width;
primary_sh->codec->disp_h = tile_grid->height;
graph = talloc_asprintf_append(graph, "[out]");
vsh->group->lavfi_graph = graph;

if (stg->metadata)
mp_tags_copy_from_av_dictionary(primary_sh->tags, stg->metadata);
struct sh_stream *primary_sh = vsh->group->members[0];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how universal that is. Probably for tiles it is ok like that.

vsh->codec->fps = primary_sh->codec->fps;
vsh->image = primary_sh->image;
vsh->still_image = primary_sh->still_image;
vsh->default_track = true;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is technically fine, but it's surprising that we don't already select bigger resolution track in compare_track function.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also assumes that the tiles are not marked as default in the first place.

vsh->codec->codec = primary_sh->codec->codec;
Comment thread
kasper93 marked this conversation as resolved.
vsh->codec->codec_desc = primary_sh->codec->codec_desc;
vsh->codec->disp_w = grid->width;
vsh->codec->disp_h = grid->height;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could add nice title for this track

    vsh->title = talloc_asprintf(virt, "Tile grid (%dx%d, %d tiles)",
                                  tile_grid->width, tile_grid->height,
                                  tile_grid->nb_tiles);

vsh->title = talloc_asprintf(vsh, "Tile grid (%dx%d, %d tiles)",
grid->width, grid->height,
grid->nb_tiles);

for (unsigned i = 0; i < stg->nb_streams; i++) {
AVStream *st = stg->streams[i];
if (st == primary_st)
continue;
if (st->index < 0 || (unsigned)st->index >= (unsigned)priv->num_streams)
continue;
struct sh_stream *sh = priv->streams[st->index]->sh;
if (sh)
sh->dependent_track = true;
}
if (stream_group->metadata)
mp_tags_copy_from_av_dictionary(vsh->tags, stream_group->metadata);

demux_add_sh_stream(demuxer, vsh);

return;

error:
talloc_free(vsh);
}
#endif

Expand Down
4 changes: 4 additions & 0 deletions filters/f_decoder_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,10 @@ static bool init_group_decoder(struct priv *p, struct mp_filter *public_f)
return false;
}

mp_require(!public_f->stream_info);
struct mp_stream_info *no_hwdec = talloc_zero(public_f, struct mp_stream_info);
Comment thread
kasper93 marked this conversation as resolved.
public_f->stream_info = no_hwdec;

enum mp_frame_type ftype;
switch (p->header->type) {
case STREAM_VIDEO: ftype = MP_FRAME_VIDEO; break;
Expand Down
7 changes: 5 additions & 2 deletions player/video.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,11 @@ static void vo_chain_uninit(struct vo_chain *vo_c)
track->vo_c = NULL;
if (vo_c->dec_src)
mp_assert(track->dec->f->pins[0] == vo_c->dec_src);
talloc_free(track->dec->f);
track->dec = NULL;
// This is NULL if a sh_stream_group's filter fails.
if (track->dec) {
talloc_free(track->dec->f);
track->dec = NULL;
}
}

if (vo_c->filter_src)
Expand Down
Loading