-
Notifications
You must be signed in to change notification settings - Fork 3.3k
video: merge the tiles of grid heif and avif images #17738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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); | ||
| 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; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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]; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
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; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could add nice title for this track |
||
| 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 | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.