Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:rguenther:plgrnd
minidlna
15-thumbnails.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 15-thumbnails.patch of Package minidlna
From: "Barak A. Pearlmutter" <barak+git@pearlmutter.net> Date: Mon, 21 Aug 2023 12:00:00 +0000 Subject: thumbnails This patch is from https://sourceforge.net/p/minidlna/patches/_discuss/thread/28a9f79d/9aca/attachment/minidlna-1.3.3-thumb.patch by https://sourceforge.net/u/wilderman/profile/ with changes to derived and cache files (configure and such) removed. --- Makefile.am | 4 ++-- albumart.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- configure.ac | 15 ++++++++++++++ minidlna.c | 29 ++++++++++++++++++++++++++ minidlna.conf | 12 +++++++++++ minidlnatypes.h | 4 ++++ monitor.c | 8 +++++++ monitor_inotify.c | 25 ++++++++++++++++++++++ options.c | 6 ++++++ options.h | 6 ++++++ upnpglobalvars.h | 5 +++++ utils.c | 14 +++++++++++++ utils.h | 3 +++ 13 files changed, 189 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index dcfc625..603ee03 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,7 +62,7 @@ minidlnad_LDADD = \ @LIBEXIF_LIBS@ \ @LIBINTL@ \ @LIBICONV@ \ - -lFLAC $(flacogglibs) $(vorbislibs) $(avahilibs) + -lFLAC $(flacogglibs) $(vorbislibs) $(avahilibs) @LIBFFMPEGTHUMBNAILER_LIBS@ testupnpdescgen_SOURCES = testupnpdescgen.c upnpdescgen.c testupnpdescgen_LDADD = \ @@ -71,7 +71,7 @@ testupnpdescgen_LDADD = \ @LIBSQLITE3_LIBS@ \ @LIBAVFORMAT_LIBS@ \ @LIBEXIF_LIBS@ \ - -lFLAC $(flacogglibs) $(vorbislibs) $(avahilibs) + -lFLAC $(flacogglibs) $(vorbislibs) $(avahilibs) @LIBFFMPEGTHUMBNAILER_LIBS@ SUFFIXES = .tmpl . diff --git a/albumart.c b/albumart.c index de026ec..28f174b 100644 --- a/albumart.c +++ b/albumart.c @@ -32,6 +32,10 @@ #include <jpeglib.h> +#ifdef THUMBNAIL_CREATION +#include <libffmpegthumbnailer/videothumbnailerc.h> +#endif + #include "upnpglobalvars.h" #include "albumart.h" #include "sql.h" @@ -348,14 +352,68 @@ found_file: return NULL; } +#ifdef THUMBNAIL_CREATION +char * +generate_thumbnail(const char * path) +{ + char *tfile = NULL; + video_thumbnailer *vt = NULL; + char cache_dir[MAXPATHLEN]; + + if( art_cache_exists(path, &tfile) ) + return tfile; + + if ( is_video(path) ) + { + + vt = video_thumbnailer_create(); + if ( !vt ) + { + free(tfile); + return 0; + } + vt->thumbnail_image_type = Jpeg; + vt->thumbnail_image_quality = runtime_vars.thumb_quality; + vt->thumbnail_size = runtime_vars.thumb_width; + vt->seek_percentage = 20; + vt->overlay_film_strip = (GETFLAG(THUMB_FILMSTRIP))?1:0; + + DPRINTF(E_DEBUG, L_METADATA, "generating thumbnail: %s\n", path); + + strncpyt(cache_dir, tfile, sizeof(cache_dir)); + if ( !make_dir(dirname(cache_dir), S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) && + !video_thumbnailer_generate_thumbnail_to_file(vt, path, tfile) ) + { + video_thumbnailer_destroy(vt); + return tfile; + } + + video_thumbnailer_destroy(vt); + } + free(tfile); + + return 0; +} +#endif + int64_t find_album_art(const char *path, uint8_t *image_data, int image_size) { char *album_art = NULL; int64_t ret = 0; - if( (image_size && (album_art = check_embedded_art(path, image_data, image_size))) || - (album_art = check_for_album_file(path)) ) + if(image_size) + album_art = check_embedded_art(path, image_data, image_size); + + if(!album_art) + album_art = check_for_album_file(path); + +#ifdef THUMBNAIL_CREATION + if(!album_art && GETFLAG(THUMB_MASK)) + album_art = generate_thumbnail(path); +#endif + + if(album_art) { ret = sql_get_int_field(db, "SELECT ID from ALBUM_ART where PATH = '%q'", album_art); if( !ret ) diff --git a/configure.ac b/configure.ac index 11421a5..2c3278b 100644 --- a/configure.ac +++ b/configure.ac @@ -642,6 +642,21 @@ AC_ARG_ENABLE(lto, ] ) +AC_ARG_ENABLE(thumbnail, + [ --enable-thumbnail enable video thumbnail generation using libffmpegthumbnailer],[ + if test "$enableval" = "yes"; then + AC_DEFINE([THUMBNAIL_CREATION],[1],[Define to 1 if you want to enable video thumbnail generation]) + PKG_CHECK_MODULES([LIBFFMPEGTHUMBNAILER], libffmpegthumbnailer, , + AC_MSG_ERROR([Unable to find libffmpegthumbnailer])) + AC_SUBST([LIBFFMPEGTHUMBNAILER_CFLAGS]) + AC_SUBST([LIBFFMPEGTHUMBNAILER_LIBS]) + else + AC_MSG_RESULT([no]) + fi + ],[ + AC_MSG_RESULT([no]) + ] +) case "$target_os" in darwin*) diff --git a/minidlna.c b/minidlna.c index 6d2d06b..74e1fac 100644 --- a/minidlna.c +++ b/minidlna.c @@ -589,6 +589,11 @@ init(int argc, char **argv) runtime_vars.root_container = NULL; runtime_vars.ifaces[0] = NULL; +#ifdef THUMBNAIL_CREATION + runtime_vars.thumb_width = 160; + runtime_vars.thumb_quality = 8; +#endif + /* read options file first since * command line arguments have final say */ if (readoptionsfile(optionsfile) < 0) @@ -812,6 +817,30 @@ init(int argc, char **argv) if (!strtobool(ary_options[i].value)) CLEARFLAG(SUBTITLES_MASK); break; +#ifdef THUMBNAIL_CREATION + case ENABLE_THUMB: + if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) ) + SETFLAG(THUMB_MASK); + break; + case THUMB_WIDTH: + runtime_vars.thumb_width = atoi(ary_options[i].value); + if (runtime_vars.thumb_width < 120) + runtime_vars.thumb_width = 120; + if (runtime_vars.thumb_width > 480) + runtime_vars.thumb_width = 480; + break; + case THUMB_QUALITY: + runtime_vars.thumb_quality = atoi(ary_options[i].value); + if (runtime_vars.thumb_quality < 5) + runtime_vars.thumb_quality = 5; + if (runtime_vars.thumb_quality > 30) + runtime_vars.thumb_quality = 30; + break; + case ENABLE_THUMB_FILMSTRIP: + if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) ) + SETFLAG(THUMB_FILMSTRIP); + break; +#endif default: DPRINTF(E_ERROR, L_GENERAL, "Unknown option in file %s\n", optionsfile); diff --git a/minidlna.conf b/minidlna.conf index 82db5f1..f6ededf 100644 --- a/minidlna.conf +++ b/minidlna.conf @@ -95,3 +95,15 @@ model_number=1 # enable subtitle support by default on unknown clients. # note: the default is yes #enable_subtitles=yes + +# Suport to Movie Thumbnail generation. To use this option, thumbnail generation must be enable at compile time. +#enable_thumbnail=no + +# The width of the thumbnail image. Large images takes more time to generate. To use this option, thumbnail generation must be enable at compile time. +#thumbnail_width=160 + +# Thumbnail Image quality. To use this option, thumbnail generation must be enable at compile time. +#thumbnail_quality=8 + +# Should the thumbnail have a film strip? To use this option, thumbnail generation must be enable at compile time. +#enable_thumbnail_filmstrip=no diff --git a/minidlnatypes.h b/minidlnatypes.h index a92cc7d..98f91b1 100644 --- a/minidlnatypes.h +++ b/minidlnatypes.h @@ -51,6 +51,10 @@ struct runtime_vars_s { int max_connections; /* max number of simultaneous conenctions */ const char *root_container; /* root ObjectID (instead of "0") */ const char *ifaces[MAX_LAN_ADDR]; /* list of configured network interfaces */ +#ifdef THUMBNAIL_CREATION + int thumb_width; + int thumb_quality; +#endif }; struct string_s { diff --git a/monitor.c b/monitor.c index b5757d9..f064ee5 100644 --- a/monitor.c +++ b/monitor.c @@ -117,6 +117,14 @@ monitor_remove_file(const char * path) sql_exec(db, "DELETE from OBJECTS where DETAIL_ID = %lld", detailID); } snprintf(art_cache, sizeof(art_cache), "%s/art_cache%s", db_path, path); +#ifdef THUMBNAIL_CREATION + /* Remove video thumbnails */ + if ( is_video(path) ) + { + char *vthumb = art_cache; + strcpy(strchr(vthumb, '\0')-4, ".jpg"); + } +#endif remove(art_cache); return 0; diff --git a/monitor_inotify.c b/monitor_inotify.c index 365b3fe..d051dd0 100644 --- a/monitor_inotify.c +++ b/monitor_inotify.c @@ -265,6 +265,10 @@ inotify_thread(void *arg) char * esc_name = NULL; struct stat st; sigset_t set; +#ifdef THUMBNAIL_CREATION + char renpath_buf[PATH_MAX]; + int cookie = 0; +#endif sigfillset(&set); sigdelset(&set, SIGCHLD); @@ -332,6 +336,16 @@ inotify_thread(void *arg) { DPRINTF(E_DEBUG, L_INOTIFY, "The directory %s was %s.\n", path_buf, (event->mask & IN_MOVED_TO ? "moved here" : "created")); +#ifdef THUMBNAIL_CREATION + /* We do not want to regenerate the thumbnails if e rename a directory. + We should keep at least four cookies/olddir since IN_MOVED_FROM/IN_MOVED_TO may + not arrive in sequence, but one should cover most cases */ + if (event->cookie == cookie && event->mask & IN_MOVED_TO) + { + DPRINTF(E_DEBUG, L_INOTIFY, "Directory rename: %s -> %s \n", renpath_buf, path_buf); + rename_artcache_dir(renpath_buf, path_buf); + } +#endif monitor_insert_directory(pollfds[0].fd, esc_name, path_buf); } else if ( (event->mask & (IN_CLOSE_WRITE|IN_MOVED_TO|IN_CREATE)) && @@ -364,7 +378,18 @@ inotify_thread(void *arg) (event->mask & IN_ISDIR ? "directory" : "file"), path_buf, (event->mask & IN_MOVED_FROM ? "moved away" : "deleted")); if ( event->mask & IN_ISDIR ) +#ifdef THUMBNAIL_CREATION + { + if ( event->mask & IN_MOVED_FROM ) + { + strncpy(renpath_buf, path_buf, sizeof(renpath_buf)); + cookie = event->cookie; + } +#endif monitor_remove_directory(pollfds[0].fd, path_buf); +#ifdef THUMBNAIL_CREATION + } +#endif else { monitor_remove_file(path_buf); diff --git a/options.c b/options.c index cee3dff..f161d60 100644 --- a/options.c +++ b/options.c @@ -68,6 +68,12 @@ static const struct { { WIDE_LINKS, "wide_links" }, { TIVO_DISCOVERY, "tivo_discovery" }, { ENABLE_SUBTITLES, "enable_subtitles" }, +#ifdef THUMBNAIL_CREATION + { ENABLE_THUMB, "enable_thumbnail" }, + { THUMB_WIDTH, "thumbnail_width" }, + { THUMB_QUALITY, "thumbnail_quality" }, + { ENABLE_THUMB_FILMSTRIP, "enable_thumbnail_filmstrip" }, +#endif }; int diff --git a/options.h b/options.h index 1ff5b22..0e8c53c 100644 --- a/options.h +++ b/options.h @@ -61,6 +61,12 @@ enum upnpconfigoptions { WIDE_LINKS, /* allow following symlinks outside the defined media_dirs */ TIVO_DISCOVERY, /* TiVo discovery protocol: bonjour or beacon. Defaults to bonjour if supported */ ENABLE_SUBTITLES, /* Enable generic subtitle support for all clients by default */ +#ifdef THUMBNAIL_CREATION + ENABLE_THUMB, /* enable thumbnail generation */ + THUMB_WIDTH, /* thunbnail image with */ + THUMB_QUALITY, /* thumnail image quality */ + ENABLE_THUMB_FILMSTRIP /* film strip overlay */ +#endif }; /* readoptionsfile() diff --git a/upnpglobalvars.h b/upnpglobalvars.h index 8a35555..66be7ba 100644 --- a/upnpglobalvars.h +++ b/upnpglobalvars.h @@ -208,6 +208,11 @@ extern uint32_t runtime_flags; #define SUBTITLES_MASK 0x0400 #define FORCE_ALPHASORT_MASK 0x0800 +#ifdef THUMBNAIL_CREATION +#define THUMB_MASK 0x1000 +#define THUMB_FILMSTRIP 0x2000 +#endif + #define SETFLAG(mask) runtime_flags |= mask #define GETFLAG(mask) (runtime_flags & mask) #define CLEARFLAG(mask) runtime_flags &= ~mask diff --git a/utils.c b/utils.c index 03ba850..eb809b8 100644 --- a/utils.c +++ b/utils.c @@ -576,3 +576,17 @@ timevalfix(struct timeval *t1) t1->tv_usec -= 1000000; } } + +#ifdef THUMBNAIL_CREATION +int +rename_artcache_dir(const char * oldpath, const char * newpath) +{ + char old_artcache[PATH_MAX]; + char new_artcache[PATH_MAX]; + + snprintf(old_artcache, sizeof(old_artcache), "%s/art_cache%s", db_path, oldpath); + snprintf(new_artcache, sizeof(old_artcache), "%s/art_cache%s", db_path, newpath); + + return rename(old_artcache, new_artcache); +} +#endif diff --git a/utils.h b/utils.h index 84b9923..641b57b 100644 --- a/utils.h +++ b/utils.h @@ -100,6 +100,9 @@ const char *mime_to_ext(const char * mime); /* Others */ int make_dir(char * path, mode_t mode); unsigned int DJBHash(uint8_t *data, int len); +#ifdef THUMBNAIL_CREATION +int rename_artcache_dir(const char * oldpath, const char * newpath); +#endif /* Timeval manipulations */ void timevaladd(struct timeval *t1, const struct timeval *t2);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor