Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (11)
Showing
with 707 additions and 48 deletions
......@@ -3179,6 +3179,11 @@ AS_IF([test "$enable_libplacebo" != "no"], [
])
AM_CONDITIONAL([HAVE_LIBPLACEBO], [test "$enable_libplacebo" != "no"])
dnl
dnl OpenGL filter pl_scale
dnl
PKG_HAVE_WITH_MODULES([LIBPLACEBO_SCALE], [libplacebo >= 4.167])
dnl
dnl OpenGL
dnl
......
......@@ -217,6 +217,14 @@ struct vlc_list_it vlc_list_it_start(const struct vlc_list *head)
return it;
}
static inline
struct vlc_list_it vlc_list_it_reverse_start(const struct vlc_list *head)
{
struct vlc_list *first = head->prev;
return (struct vlc_list_it){ head, first, first->prev };
}
static inline bool vlc_list_it_continue(const struct vlc_list_it *restrict it)
{
return it->current != it->head;
......@@ -230,6 +238,14 @@ static inline void vlc_list_it_next(struct vlc_list_it *restrict it)
it->next = next->next;
}
static inline void vlc_list_it_prev(struct vlc_list_it *restrict it)
{
struct vlc_list *next = it->next;
it->current = next;
it->next = next->prev;
}
#define vlc_list_entry_aligned_size(p) \
((sizeof (*(p)) + sizeof (max_align_t) - 1) / sizeof (max_align_t))
......@@ -266,6 +282,28 @@ static inline void vlc_list_it_next(struct vlc_list_it *restrict it)
pos, member), true); \
vlc_list_it_next(&(vlc_list_it__##pos)))
/**
* List iteration macro.
*
* This macro iterates over all elements (excluding the head) of a list,
* in reversed order from the first to the last.
*
* For each iteration, it sets the cursor variable to the current element.
*
* \param pos Cursor pointer variable identifier.
* \param head Head pointer of the list to iterate [IN].
* \param member Identifier of the member of the data type
* serving as list node.
* \note It it safe to delete the current item while iterating.
* It is however <b>not</b> safe to delete another item.
*/
#define vlc_list_reverse_foreach(pos, head, member) \
for (struct vlc_list_it vlc_list_it_##pos = vlc_list_it_reverse_start(head); \
vlc_list_it_continue(&(vlc_list_it_##pos)) \
&& ((pos) = vlc_list_entry_p((vlc_list_it_##pos).current, \
pos, member), true); \
vlc_list_it_prev(&(vlc_list_it_##pos)))
/**
* Converts a list node pointer to an element pointer.
*
......
......@@ -343,7 +343,7 @@ static int Control (vout_display_t *vd, int query)
// don't return an error or we need to handle reset_pictures
return VLC_SUCCESS;
vout_display_opengl_SetWindowAspectRatio(sys->vgl, (float)place.width / place.height);
vout_display_opengl_SetOutputSize(sys->vgl, place.width, place.height);
OpenglUnlock(sys->gl);
sys->place = place;
......
......@@ -465,3 +465,20 @@ enum pl_chroma_location vlc_placebo_ChromaLoc(const video_format_t *fmt)
return locs[fmt->chroma_location];
}
int vlc_placebo_PlaneComponents(const video_format_t *fmt,
struct pl_plane planes[4]) {
const struct fmt_desc *desc = FindDesc(fmt->i_chroma);
if (!desc)
return 0;
for (int i = 0; i < desc->num_planes; i++) {
const struct plane_desc *p = &desc->planes[i];
planes[i].components = p->components;
for (int c = 0; c < p->components; ++c)
planes[i].component_mapping[c] = p->comp_map[c];
}
return desc->num_planes;
}
......@@ -36,6 +36,8 @@ struct pl_color_space vlc_placebo_ColorSpace(const video_format_t *);
struct pl_color_repr vlc_placebo_ColorRepr(const video_format_t *);
enum pl_chroma_location vlc_placebo_ChromaLoc(const video_format_t *);
int vlc_placebo_PlaneComponents(const video_format_t *, struct pl_plane[4]);
// Fill a pl_plane_data array with various data. Returns the number of planes,
// or 0 if the format is unsupported by the libplacebo API. If `buf` is set,
// then all addresses of the picture_t must lie within `buf`'s mapped memory.
......
......@@ -373,7 +373,7 @@ static int Control (vout_display_t *vd, int query)
if (vlc_gl_MakeCurrent (sys->gl) != VLC_SUCCESS)
return VLC_SUCCESS;
vout_display_opengl_SetWindowAspectRatio(sys->vgl, (float)place.width / place.height);
vout_display_opengl_SetOutputSize(sys->vgl, place.width, place.height);
/* For resize, we call glViewport in reshape and not here.
This has the positive side effect that we avoid erratic sizing as we animate every resize. */
......
......@@ -124,6 +124,34 @@ libglfilter_mock_plugin_la_CFLAGS = -DUSE_OPENGL_ES2=1
noinst_LTLIBRARIES += libglfilter_mock_plugin.la
endif
if HAVE_LIBPLACEBO_SCALE
libpl_scale_plugin_la_SOURCES = video_output/opengl/pl_scale.c
libpl_scale_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBPLACEBO_CFLAGS)
libpl_scale_plugin_la_LIBADD = $(LIBPLACEBO_LIBS)
if HAVE_GL
libpl_scale_plugin_la_LIBADD += libvlc_opengl.la
video_filter_LTLIBRARIES += libpl_scale_plugin.la
endif
if HAVE_DARWIN
video_filter_LTLIBRARIES += libpl_scale_plugin.la
if HAVE_OSX
libpl_scale_plugin_la_LIBADD += libvlc_opengl.la
else
libpl_scale_plugin_la_LIBADD += libvlc_opengles.la
libpl_scale_plugin_la_CPPFLAGS += -DUSE_OPENGL_ES2=1
endif
endif
if HAVE_ANDROID
libpl_scale_plugin_la_LIBADD += libvlc_opengles.la
libpl_scale_plugin_la_CPPFLAGS += -DUSE_OPENGL_ES2=1
video_filter_LTLIBRARIES += libpl_scale_plugin.la
endif
endif
libegl_display_generic_plugin_la_SOURCES = video_output/opengl/egl_display_generic.c
libegl_display_generic_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) $(EGL_FLAGS)
libegl_display_generic_plugin_la_LIBADD = $(EGL_LIBS)
......
......@@ -225,8 +225,8 @@ static void PictureDisplay (vout_display_t *vd, picture_t *pic)
{
if (sys->place_changed)
{
float window_ar = (float)sys->place.width / sys->place.height;
vout_display_opengl_SetWindowAspectRatio(sys->vgl, window_ar);
vout_display_opengl_SetOutputSize(sys->vgl, sys->place.width,
sys->place.height);
vout_display_opengl_Viewport(sys->vgl, sys->place.x, sys->place.y,
sys->place.width, sys->place.height);
sys->place_changed = false;
......
......@@ -184,42 +184,23 @@ InitFramebuffersOut(struct vlc_gl_filter_priv *priv)
struct vlc_gl_filter *filter = &priv->filter;
if (filter->config.filter_planes)
{
struct vlc_gl_format *glfmt = &priv->glfmt_in;
priv->tex_count = glfmt->tex_count;
vt->GenFramebuffers(priv->tex_count, priv->framebuffers_out);
vt->GenTextures(priv->tex_count, priv->textures_out);
for (unsigned i = 0; i < glfmt->tex_count; ++i)
{
memcpy(priv->tex_widths, priv->plane_widths,
priv->tex_count * sizeof(*priv->tex_widths));
memcpy(priv->tex_heights, priv->plane_heights,
priv->tex_count * sizeof(*priv->tex_heights));
/* Init one framebuffer and texture for each plane */
int ret =
InitPlane(priv, i, priv->tex_widths[i], priv->tex_heights[i]);
if (ret != VLC_SUCCESS)
{
DeleteFramebuffersOut(priv);
return ret;
}
}
}
priv->tex_count = priv->glfmt_in.tex_count;
else
{
priv->tex_count = 1;
/* Create a texture having the expected size */
vt->GenFramebuffers(1, priv->framebuffers_out);
vt->GenTextures(1, priv->textures_out);
vt->GenFramebuffers(priv->tex_count, priv->framebuffers_out);
vt->GenTextures(priv->tex_count, priv->textures_out);
priv->tex_widths[0] = priv->size_out.width;
priv->tex_heights[0] = priv->size_out.height;
memcpy(priv->tex_widths, priv->plane_widths,
priv->tex_count * sizeof(*priv->tex_widths));
memcpy(priv->tex_heights, priv->plane_heights,
priv->tex_count * sizeof(*priv->tex_heights));
int ret = InitPlane(priv, 0, priv->tex_widths[0], priv->tex_heights[0]);
for (unsigned i = 0; i < priv->tex_count; ++i)
{
/* Init one framebuffer and texture for each plane */
int ret =
InitPlane(priv, i, priv->tex_widths[i], priv->tex_heights[i]);
if (ret != VLC_SUCCESS)
{
DeleteFramebuffersOut(priv);
......@@ -314,3 +295,42 @@ vlc_gl_filter_InitPlaneSizes(struct vlc_gl_filter *filter)
priv->plane_heights[0] = priv->size_out.height;
}
}
void
vlc_gl_filter_ApplyOutputSize(struct vlc_gl_filter *filter)
{
struct vlc_gl_filter_priv *priv = vlc_gl_filter_PRIV(filter);
vlc_gl_filter_InitPlaneSizes(filter);
const opengl_vtable_t *vt = &priv->filter.api->vt;
GL_ASSERT_NOERROR(vt);
unsigned msaa_level = filter->config.msaa_level;
if (msaa_level)
{
vt->BindRenderbuffer(GL_RENDERBUFFER, priv->renderbuffer_msaa);
vt->RenderbufferStorageMultisample(GL_RENDERBUFFER, msaa_level,
GL_RGBA8,
priv->size_out.width,
priv->size_out.height);
}
if (priv->tex_count)
{
memcpy(priv->tex_widths, priv->plane_widths,
priv->tex_count * sizeof(*priv->tex_widths));
memcpy(priv->tex_heights, priv->plane_heights,
priv->tex_count * sizeof(*priv->tex_heights));
for (unsigned plane = 0; plane < priv->tex_count; ++plane)
{
vt->BindTexture(GL_TEXTURE_2D, priv->textures_out[plane]);
vt->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, priv->tex_widths[plane],
priv->tex_heights[plane], 0, GL_RGBA,
GL_UNSIGNED_BYTE, NULL);
}
}
GL_ASSERT_NOERROR(vt);
}
......@@ -62,6 +62,37 @@ struct vlc_gl_filter_ops {
* Free filter resources
*/
void (*close)(struct vlc_gl_filter *filter);
/**
* Request a (responsive) filter to adapt its output size (optional)
*
* A responsive filter is a filter for which the size of the produced
* pictures depends on the output (e.g. display) size rather than the
* input. This is for example the case for a renderer.
*
* A new output size is requested (size_out). The filter is authorized to
* change the size_out to enforce its own constraints.
*
* In addition, it may request to the previous filter (if any) an optimal
* size it wants to receive. If set to non-zero value, this previous filter
* will receive this size as its requested size (and so on).
*
* \retval true if the resize is accepted (possibly with a modified
* size_out)
* \retval false if the resize is rejected (included on error)
*/
int (*request_output_size)(struct vlc_gl_filter *filter,
struct vlc_gl_tex_size *size_out,
struct vlc_gl_tex_size *optimal_in);
/**
* Callback to notify input size changes
*
* When a filter changes its output size as a result of
* request_output_size(), the next filter is notified by this callback.
*/
void (*on_input_size_change)(struct vlc_gl_filter *filter,
const struct vlc_gl_tex_size *size);
};
/**
......
......@@ -94,4 +94,7 @@ vlc_gl_filter_InitFramebuffers(struct vlc_gl_filter *filter, bool is_last);
void
vlc_gl_filter_InitPlaneSizes(struct vlc_gl_filter *filter);
void
vlc_gl_filter_ApplyOutputSize(struct vlc_gl_filter *filter);
#endif
......@@ -517,3 +517,55 @@ vlc_gl_filters_SetViewport(struct vlc_gl_filters *filters, int x, int y,
filters->viewport.width = width;
filters->viewport.height = height;
}
int
vlc_gl_filters_SetOutputSize(struct vlc_gl_filters *filters, unsigned width,
unsigned height)
{
bool resized = false;
struct vlc_gl_tex_size req = { width, height };
struct vlc_gl_filter *next = NULL;
struct vlc_gl_filter_priv *priv;
vlc_list_reverse_foreach(priv, &filters->list, node)
{
struct vlc_gl_filter *filter = &priv->filter;
if (!filter->ops->request_output_size) {
/* Could not propagate further */
break;
}
struct vlc_gl_tex_size optimal_in = {0};
int ret =
filter->ops->request_output_size(filter, &req, &optimal_in);
if (ret != VLC_SUCCESS)
break;
/* The filter may have modified the requested size */
priv->size_out = req;
/* Recreate the framebuffers/textures with the new size */
vlc_gl_filter_ApplyOutputSize(filter);
resized = true;
/* Notify the next filter of the input size change */
if (next && next->ops->on_input_size_change)
next->ops->on_input_size_change(next, &req);
if (!optimal_in.width || !optimal_in.height)
/* No specific input size requested, do not propagate further */
break;
/* Request the previous filter to output at the optimal input size of
* the current filter. */
req = optimal_in;
/* The filters are iterated backwards, so the current filter will
* become the next filter. */
next = filter;
}
return resized ? VLC_SUCCESS : VLC_EGENERIC;
}
......@@ -106,4 +106,11 @@ void
vlc_gl_filters_SetViewport(struct vlc_gl_filters *filters, int x, int y,
unsigned width, unsigned height);
/**
* Change the output size
*/
int
vlc_gl_filters_SetOutputSize(struct vlc_gl_filters *filters, unsigned width,
unsigned height);
#endif
/*****************************************************************************
* pl_scale.c
*****************************************************************************
* Copyright (C) 2021 VLC authors and VideoLAN
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "limits.h"
#include <vlc_common.h>
#include <vlc_picture.h>
#include <vlc_plugin.h>
#include <vlc_modules.h>
#include <vlc_opengl.h>
#include <vlc_filter.h>
#include <libplacebo/context.h>
#include <libplacebo/gpu.h>
#include <libplacebo/opengl.h>
#include <libplacebo/renderer.h>
#include "video_output/opengl/filter.h"
#include "video_output/opengl/gl_api.h"
#include "video_output/opengl/gl_common.h"
#include "video_output/opengl/gl_util.h"
#include "video_output/opengl/sampler.h"
#include "video_output/libplacebo/utils.h"
// Without this commit, libplacebo as used by this filter makes VLC
// assert/crash by closing file descriptors:
// https://github.com/haasn/libplacebo/commit/39fc39d31d65968709b4a05c571a0d85c918058d
static_assert(PL_API_VER >= 167, "pl_scale requires libplacebo >= 4.167");
#define CFG_PREFIX "plscale-"
static const char *const filter_options[] = {
"upscaler", "downscaler", NULL,
};
struct sys
{
GLuint id;
GLuint vbo;
pl_log pl_log;
pl_opengl pl_opengl;
pl_renderer pl_renderer;
/* Cached representation of pl_frame to wrap the raw textures */
struct pl_frame frame_in;
struct pl_frame frame_out;
struct pl_render_params render_params;
unsigned out_width;
unsigned out_height;
};
static void
DestroyTextures(pl_gpu gpu, unsigned count, pl_tex textures[])
{
for (unsigned i = 0; i < count; ++i)
pl_tex_destroy(gpu, &textures[i]);
}
static int
WrapTextures(pl_gpu gpu, unsigned count, const GLuint textures[],
const GLsizei tex_widths[], const GLsizei tex_heights[],
GLenum tex_target, pl_tex out[])
{
for (unsigned i = 0; i < count; ++i)
{
struct pl_opengl_wrap_params opengl_wrap_params = {
.texture = textures[i],
.width = tex_widths[i],
.height = tex_heights[i],
.target = tex_target,
.iformat = GL_RGBA8,
};
out[i] = pl_opengl_wrap(gpu, &opengl_wrap_params);
if (!out[i])
{
if (i)
DestroyTextures(gpu, i - 1, out);
return VLC_EGENERIC;
}
}
return VLC_SUCCESS;
}
static pl_tex
WrapFramebuffer(pl_gpu gpu, GLuint framebuffer, unsigned width, unsigned height)
{
struct pl_opengl_wrap_params opengl_wrap_params = {
.framebuffer = framebuffer,
.width = width,
.height = height,
.iformat = GL_RGBA8,
};
return pl_opengl_wrap(gpu, &opengl_wrap_params);
}
static int
Draw(struct vlc_gl_filter *filter, const struct vlc_gl_picture *pic,
const struct vlc_gl_input_meta *meta)
{
(void) meta;
struct sys *sys = filter->sys;
const opengl_vtable_t *vt = &filter->api->vt;
const struct vlc_gl_format *glfmt = filter->glfmt_in;
pl_gpu gpu = sys->pl_opengl->gpu;
struct pl_frame *frame_in = &sys->frame_in;
struct pl_frame *frame_out = &sys->frame_out;
struct pl_render_params *render_params = &sys->render_params;
if (pic->mtx_has_changed)
{
const float *mtx = pic->mtx;
/* The direction is either horizontal or vertical, and the two vectors
* are orthogonal */
assert((!mtx[1] && !mtx[2]) || (!mtx[0] && !mtx[3]));
/* Is the video rotated by 90° (or 270°)? */
bool rotated90 = !mtx[0];
/*
* The same rotation+flip orientation may be encoded in different ways
* in libplacebo. For example, hflip the crop rectangle and use a 90°
* rotation is equivalent to vflip the crop rectangle and use a 270°
* rotation.
*
* To get a unique solution, limit the rotation to be either 0 or 90,
* and encode the remaining in the crop rectangle.
*/
frame_in->rotation = rotated90 ? PL_ROTATION_90 : PL_ROTATION_0;
/* Apply 90° to the coords if necessary */
float coords[] = {
rotated90 ? 1 : 0, 0,
rotated90 ? 0 : 1, 1,
};
vlc_gl_picture_ToTexCoords(pic, 2, coords, coords);
unsigned w = glfmt->tex_widths[0];
unsigned h = glfmt->tex_heights[0];
struct pl_rect2df *r = &frame_in->crop;
r->x0 = coords[0] * w;
r->y0 = coords[1] * h;
r->x1 = coords[2] * w;
r->y1 = coords[3] * h;
}
GLint value;
vt->GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &value);
GLuint final_draw_framebuffer = value; /* as GLuint */
pl_tex texs_in[PICTURE_PLANE_MAX];
int ret = WrapTextures(gpu, glfmt->tex_count, pic->textures,
glfmt->tex_widths, glfmt->tex_heights,
glfmt->tex_target, texs_in);
if (ret != VLC_SUCCESS)
goto end;
/* Only changes the plane textures from the cached pl_frame */
for (unsigned i = 0; i < glfmt->tex_count; ++i)
frame_in->planes[i].texture = texs_in[i];
pl_tex tex_out = WrapFramebuffer(gpu, final_draw_framebuffer,
sys->out_width, sys->out_height);
if (!tex_out)
goto destroy_texs_in;
frame_out->planes[0].texture = tex_out;
bool ok = pl_render_image(sys->pl_renderer, frame_in, frame_out,
render_params);
if (!ok)
ret = VLC_EGENERIC;
DestroyTextures(gpu, 1, &tex_out);
destroy_texs_in:
DestroyTextures(gpu, glfmt->tex_count, texs_in);
end:
vt->BindFramebuffer(GL_DRAW_FRAMEBUFFER, final_draw_framebuffer);
return ret;
}
static int
RequestOutputSize(struct vlc_gl_filter *filter,
struct vlc_gl_tex_size *req,
struct vlc_gl_tex_size *optimal_in)
{
struct sys *sys = filter->sys;
sys->out_width = req->width;
sys->out_height = req->height;
/* Do not propagate resizing to previous filters */
(void) optimal_in;
return VLC_SUCCESS;
}
static void
Close(struct vlc_gl_filter *filter)
{
struct sys *sys = filter->sys;
pl_renderer_destroy(&sys->pl_renderer);
pl_opengl_destroy(&sys->pl_opengl);
pl_log_destroy(&sys->pl_log);
free(sys);
}
static vlc_gl_filter_open_fn Open;
static int
Open(struct vlc_gl_filter *filter, const config_chain_t *config,
const struct vlc_gl_format *glfmt, struct vlc_gl_tex_size *size_out)
{
(void) config;
/* By default, do not scale. The dimensions will be modified dynamically by
* request_output_size(). */
unsigned width = glfmt->tex_widths[0];
unsigned height = glfmt->tex_heights[0];
config_ChainParse(filter, CFG_PREFIX, filter_options, config);
int upscaler = var_InheritInteger(filter, CFG_PREFIX "upscaler");
int downscaler = var_InheritInteger(filter, CFG_PREFIX "downscaler");
if (upscaler < 0 || (size_t) upscaler >= ARRAY_SIZE(scale_values)
|| upscaler == SCALE_CUSTOM)
{
msg_Err(filter, "Unsupported upscaler: %d", upscaler);
return VLC_EGENERIC;
}
if (downscaler < 0 || (size_t) downscaler >= ARRAY_SIZE(scale_values)
|| downscaler == SCALE_CUSTOM)
{
msg_Err(filter, "Unsupported downscaler: %d", downscaler);
return VLC_EGENERIC;
}
struct sys *sys = filter->sys = malloc(sizeof(*sys));
if (!sys)
return VLC_EGENERIC;
sys->pl_log = vlc_placebo_CreateContext(VLC_OBJECT(filter));
if (!sys->pl_log)
goto error_free_sys;
struct pl_opengl_params opengl_params = {
.debug = true,
};
sys->pl_opengl = pl_opengl_create(sys->pl_log, &opengl_params);
if (!sys->pl_opengl)
goto error_destroy_pl_log;
pl_gpu gpu = sys->pl_opengl->gpu;
sys->pl_renderer = pl_renderer_create(sys->pl_log, gpu);
if (!sys->pl_renderer)
goto error_destroy_pl_opengl;
sys->frame_in = (struct pl_frame) {
.num_planes = glfmt->tex_count,
.repr = vlc_placebo_ColorRepr(&glfmt->fmt),
.color = vlc_placebo_ColorSpace(&glfmt->fmt),
};
/* Initialize frame_in.planes */
int plane_count =
vlc_placebo_PlaneComponents(&glfmt->fmt, sys->frame_in.planes);
if ((unsigned) plane_count != glfmt->tex_count) {
msg_Err(filter, "Unexpected plane count (%d) != tex count (%u)",
plane_count, glfmt->tex_count);
goto error_destroy_pl_opengl;
}
sys->frame_out = (struct pl_frame) {
.num_planes = 1,
.planes = {
{
.components = 4,
.component_mapping = {
PL_CHANNEL_R,
PL_CHANNEL_G,
PL_CHANNEL_B,
PL_CHANNEL_A,
},
},
},
};
sys->render_params = pl_render_default_params;
sys->render_params.upscaler = scale_config[upscaler];
sys->render_params.downscaler = scale_config[downscaler];
static const struct vlc_gl_filter_ops ops = {
.draw = Draw,
.close = Close,
.request_output_size = RequestOutputSize,
};
filter->ops = &ops;
sys->out_width = size_out->width = width;
sys->out_height = size_out->height = height;
return VLC_SUCCESS;
error_destroy_pl_opengl:
pl_opengl_destroy(&sys->pl_opengl);
error_destroy_pl_log:
pl_log_destroy(&sys->pl_log);
error_free_sys:
free(sys);
return VLC_EGENERIC;
}
vlc_module_begin()
set_shortname("pl_scale")
set_description("OpenGL scaler")
set_category(CAT_VIDEO)
set_subcategory(SUBCAT_VIDEO_VFILTER)
set_capability("opengl filter", 0)
set_callback(Open)
add_shortcut("pl_scale");
#define UPSCALER_TEXT "OpenGL upscaler"
#define UPSCALER_LONGTEXT "Upscaler filter to apply during rendering"
add_integer(CFG_PREFIX "upscaler", SCALE_BUILTIN, UPSCALER_TEXT, \
UPSCALER_LONGTEXT) \
change_integer_list(scale_values, scale_text) \
#define DOWNSCALER_TEXT "OpenGL downscaler"
#define DOWNSCALER_LONGTEXT "Downscaler filter to apply during rendering"
add_integer(CFG_PREFIX "downscaler", SCALE_BUILTIN, DOWNSCALER_TEXT, \
DOWNSCALER_LONGTEXT) \
change_integer_list(scale_values, scale_text) \
vlc_module_end()
......@@ -359,13 +359,17 @@ vlc_gl_renderer_SetViewpoint(struct vlc_gl_renderer *renderer,
return VLC_SUCCESS;
}
void
vlc_gl_renderer_SetWindowAspectRatio(struct vlc_gl_renderer *renderer,
float f_sar)
static void
vlc_gl_renderer_SetOutputSize(struct vlc_gl_renderer *renderer, unsigned width,
unsigned height)
{
float f_sar = (float) width / height;
/* Each time the window size changes, we must recompute the minimum zoom
* since the aspect ration changes.
* We must also set the new current zoom value. */
renderer->target_width = width;
renderer->target_height = height;
renderer->f_sar = f_sar;
UpdateFOVy(renderer);
UpdateZ(renderer);
......@@ -374,6 +378,23 @@ vlc_gl_renderer_SetWindowAspectRatio(struct vlc_gl_renderer *renderer,
getViewpointMatrixes(renderer, fmt->projection_mode);
}
static int
RequestOutputSize(struct vlc_gl_filter *filter,
struct vlc_gl_tex_size *req,
struct vlc_gl_tex_size *optimal_in)
{
struct vlc_gl_renderer *renderer = filter->sys;
vlc_gl_renderer_SetOutputSize(renderer, req->width, req->height);
/* The optimal input size is the size for which the renderer do not need to
* scale */
optimal_in->width = renderer->target_width;
optimal_in->height = renderer->target_height;
return VLC_SUCCESS;
}
static int BuildSphere(GLfloat **vertexCoord, GLfloat **textureCoord, unsigned *nbVertices,
GLushort **indices, unsigned *nbIndices)
{
......@@ -760,6 +781,7 @@ vlc_gl_renderer_Open(struct vlc_gl_filter *filter,
static const struct vlc_gl_filter_ops filter_ops = {
.draw = Draw,
.close = Close,
.request_output_size = RequestOutputSize,
};
filter->ops = &filter_ops;
filter->sys = renderer;
......
......@@ -94,6 +94,11 @@ struct vlc_gl_renderer
float f_fovy; /* to avoid recalculating them when needed. */
float f_z; /* Position of the camera on the shpere radius vector */
float f_sar;
/* Original size from which f_sar is computed
* f_sar = (float) target_width / target_height */
unsigned target_width;
unsigned target_height;
};
vlc_gl_filter_open_fn vlc_gl_renderer_Open;
......@@ -102,8 +107,4 @@ int
vlc_gl_renderer_SetViewpoint(struct vlc_gl_renderer *renderer,
const vlc_viewpoint_t *p_vp);
void
vlc_gl_renderer_SetWindowAspectRatio(struct vlc_gl_renderer *renderer,
float f_sar);
#endif /* include-guard */
......@@ -147,6 +147,34 @@ vout_display_opengl_t *vout_display_opengl_New(video_format_t *fmt,
goto delete_interop;
}
int upscaler = var_InheritInteger(gl, "pl-upscaler");
int downscaler = var_InheritInteger(gl, "pl-downscaler");
if (upscaler || downscaler)
{
char upscaler_value[12];
char downscaler_value[12];
snprintf(upscaler_value, sizeof(upscaler_value), "%d", upscaler);
snprintf(downscaler_value, sizeof(downscaler_value), "%d", downscaler);
upscaler_value[sizeof(upscaler_value) - 1] = '\0';
downscaler_value[sizeof(downscaler_value) - 1] = '\0';
config_chain_t cfg = {
.psz_name = (char *) "upscaler",
.psz_value = upscaler_value,
.p_next = &(config_chain_t) {
.psz_name = (char *) "downscaler",
.psz_value = downscaler_value,
},
};
struct vlc_gl_filter *scale_filter =
vlc_gl_filters_Append(vgl->filters, "pl_scale", &cfg);
if (!scale_filter)
msg_Warn(gl, "Could not load pl_scale");
}
/* The renderer is the only filter, for now */
struct vlc_gl_filter *renderer_filter =
vlc_gl_filters_Append(vgl->filters, "renderer", NULL);
......@@ -241,10 +269,14 @@ int vout_display_opengl_SetViewpoint(vout_display_opengl_t *vgl,
return vlc_gl_renderer_SetViewpoint(vgl->renderer, p_vp);
}
void vout_display_opengl_SetWindowAspectRatio(vout_display_opengl_t *vgl,
float f_sar)
void vout_display_opengl_SetOutputSize(vout_display_opengl_t *vgl,
unsigned width, unsigned height)
{
vlc_gl_renderer_SetWindowAspectRatio(vgl->renderer, f_sar);
int ret = vlc_gl_filters_SetOutputSize(vgl->filters, width, height);
/* The renderer, last filter in the chain, necessarily accepts the new
* output size */
assert(ret == VLC_SUCCESS);
(void) ret;
}
void vout_display_opengl_Viewport(vout_display_opengl_t *vgl, int x, int y,
......
......@@ -34,6 +34,12 @@
#ifdef HAVE_LIBPLACEBO
#include "../libplacebo/utils.h"
#define UPSCALER_TEXT "OpenGL upscaler"
#define UPSCALER_LONGTEXT "Upscaler filter to apply during rendering"
#define DOWNSCALER_TEXT "OpenGL downscaler"
#define DOWNSCALER_LONGTEXT "Downscaler filter to apply during rendering"
#if PL_API_VER >= 10
#define add_desat_params() \
......@@ -51,6 +57,13 @@
#endif
#define add_glopts_placebo() \
set_section(N_("Scaling"), NULL) \
add_integer("pl-upscaler", SCALE_BUILTIN, UPSCALER_TEXT, \
UPSCALER_LONGTEXT) \
change_integer_list(scale_values, scale_text) \
add_integer("pl-downscaler", SCALE_BUILTIN, DOWNSCALER_TEXT, \
DOWNSCALER_LONGTEXT) \
change_integer_list(scale_values, scale_text) \
set_section(N_("Colorspace conversion"), NULL) \
add_integer("rendering-intent", pl_color_map_default_params.intent, \
RENDER_INTENT_TEXT, RENDER_INTENT_LONGTEXT) \
......@@ -95,8 +108,8 @@ void vout_display_opengl_Delete(vout_display_opengl_t *vgl);
int vout_display_opengl_SetViewpoint(vout_display_opengl_t *vgl, const vlc_viewpoint_t*);
void vout_display_opengl_SetWindowAspectRatio(vout_display_opengl_t *vgl,
float f_sar);
void vout_display_opengl_SetOutputSize(vout_display_opengl_t *vgl,
unsigned width, unsigned height);
void vout_display_opengl_Viewport(vout_display_opengl_t *vgl, int x, int y,
unsigned width, unsigned height);
......
......@@ -231,7 +231,7 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
const int width = place.width;
const int height = place.height;
vlc_gl_Resize (sys->gl, width, height);
vout_display_opengl_SetWindowAspectRatio(sys->vgl, (float)width / height);
vout_display_opengl_SetOutputSize(sys->vgl, width, height);
vout_display_opengl_Viewport(sys->vgl, place.x, place.y, width, height);
sys->area.place_changed = false;
}
......
......@@ -56,6 +56,8 @@ int main (void)
vlc_list_init(&head);
vlc_list_foreach(elem, &head, node)
assert(0); /* No iteration on an empty list */
vlc_list_reverse_foreach(elem, &head, node)
assert(0); /* No iteration on an empty list */
assert(vlc_list_is_empty(&head));
vlc_list_init(&head); /* List can be reinitialized */
......@@ -64,6 +66,10 @@ int main (void)
vlc_list_foreach(elem, &head, node)
assert(elem->i == 1), count++;
assert(count == 1);
count = 0;
vlc_list_reverse_foreach(elem, &head, node)
assert(elem->i == 1), count++;
assert(count == 1);
back = make_elem(2);
vlc_list_append(back, &head);
......@@ -71,6 +77,10 @@ int main (void)
vlc_list_foreach(elem, &head, node)
assert(elem->i == count + 1), count++;
assert(count == 2);
count = 0;
vlc_list_reverse_foreach(elem, &head, node)
assert(elem->i == 2 - count), count++;
assert(count == 2);
vlc_list_prepend(make_elem(3), &head);
vlc_list_remove(head.prev); /* remove number 2 */
......@@ -87,6 +97,17 @@ int main (void)
}
assert(vlc_list_is_empty(&head));
vlc_list_prepend(make_elem(3), &head);
vlc_list_reverse_foreach(elem, &head, node)
{
vlc_list_remove(&elem->node);
free(elem);
}
assert(vlc_list_is_empty(&head));
/*
* Create a list from 10 to 30, inserting the 10 last element first
*/
for (int i = 20; i < 30; i++)
vlc_list_append(make_elem(i), &head);
for (int i = 19; i >= 10; i--)
......