minidlna_video_thumbnail_v121.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. --- Makefile.am.orig 2017-05-18 05:55:17.000000000 +0900
  2. +++ Makefile.am 2017-05-26 13:51:55.519612115 +0900
  3. @@ -53,7 +53,7 @@
  4. @LIBEXIF_LIBS@ \
  5. @LIBINTL@ \
  6. @LIBICONV@ \
  7. - -lFLAC $(flacogglibs) $(vorbislibs) $(avahilibs)
  8. + -lFLAC $(flacogglibs) $(vorbislibs) $(avahilibs) @LIBFFMPEGTHUMBNAILER_LIBS@
  9. minidlnad_LDFLAGS = @STATIC_LDFLAGS@
  10. --- albumart.c.orig 2017-05-18 05:55:17.000000000 +0900
  11. +++ albumart.c 2017-05-26 14:03:52.661089877 +0900
  12. @@ -32,6 +32,10 @@
  13. #include <jpeglib.h>
  14. +#ifdef THUMBNAIL_CREATION
  15. +#include <libffmpegthumbnailer/videothumbnailerc.h>
  16. +#endif
  17. +
  18. #include "upnpglobalvars.h"
  19. #include "albumart.h"
  20. #include "sql.h"
  21. @@ -348,14 +352,68 @@
  22. return NULL;
  23. }
  24. +#ifdef THUMBNAIL_CREATION
  25. +char *
  26. +generate_thumbnail(const char * path)
  27. +{
  28. + char *tfile = NULL;
  29. + video_thumbnailer *vt = NULL;
  30. + char cache_dir[MAXPATHLEN];
  31. +
  32. + if( art_cache_exists(path, &tfile) )
  33. + return tfile;
  34. +
  35. + if ( is_video(path) )
  36. + {
  37. +
  38. + vt = video_thumbnailer_create();
  39. + if ( !vt )
  40. + {
  41. + free(tfile);
  42. + return 0;
  43. + }
  44. + vt->thumbnail_image_type = Jpeg;
  45. + vt->thumbnail_image_quality = runtime_vars.thumb_quality;
  46. + vt->thumbnail_size = runtime_vars.thumb_width;
  47. + vt->seek_percentage = 20;
  48. + vt->overlay_film_strip = (GETFLAG(THUMB_FILMSTRIP))?1:0;
  49. +
  50. + DPRINTF(E_DEBUG, L_METADATA, "generating thumbnail: %s\n", path);
  51. +
  52. + strncpyt(cache_dir, tfile, sizeof(cache_dir));
  53. + if ( !make_dir(dirname(cache_dir), S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) &&
  54. + !video_thumbnailer_generate_thumbnail_to_file(vt, path, tfile) )
  55. + {
  56. + video_thumbnailer_destroy(vt);
  57. + return tfile;
  58. + }
  59. +
  60. + video_thumbnailer_destroy(vt);
  61. + }
  62. + free(tfile);
  63. +
  64. + return 0;
  65. +}
  66. +#endif
  67. +
  68. int64_t
  69. find_album_art(const char *path, uint8_t *image_data, int image_size)
  70. {
  71. char *album_art = NULL;
  72. int64_t ret = 0;
  73. - if( (image_size && (album_art = check_embedded_art(path, image_data, image_size))) ||
  74. - (album_art = check_for_album_file(path)) )
  75. + if(image_size)
  76. + album_art = check_embedded_art(path, image_data, image_size);
  77. +
  78. + if(!album_art)
  79. + album_art = check_for_album_file(path);
  80. +
  81. +#ifdef THUMBNAIL_CREATION
  82. + if(!album_art && GETFLAG(THUMB_MASK))
  83. + album_art = generate_thumbnail(path);
  84. +#endif
  85. +
  86. + if(album_art)
  87. {
  88. ret = sql_get_int_field(db, "SELECT ID from ALBUM_ART where PATH = '%q'", album_art);
  89. if( !ret )
  90. --- configure.ac.orig 2017-05-18 05:55:17.000000000 +0900
  91. +++ configure.ac 2017-05-26 14:08:49.528778727 +0900
  92. @@ -617,6 +617,21 @@
  93. ]
  94. )
  95. +AC_ARG_ENABLE(thumbnail,
  96. + [ --enable-thumbnail enable video thumbnail generation using libffmpegthumbnailer],[
  97. + if test "$enableval" = "yes"; then
  98. + AC_DEFINE([THUMBNAIL_CREATION],[1],[Define to 1 if you want to enable video thumbnail generation])
  99. + PKG_CHECK_MODULES([LIBFFMPEGTHUMBNAILER], libffmpegthumbnailer, ,
  100. + AC_MSG_ERROR([Unable to find libffmpegthumbnailer]))
  101. + AC_SUBST([LIBFFMPEGTHUMBNAILER_CFLAGS])
  102. + AC_SUBST([LIBFFMPEGTHUMBNAILER_LIBS])
  103. + else
  104. + AC_MSG_RESULT([no])
  105. + fi
  106. + ],[
  107. + AC_MSG_RESULT([no])
  108. + ]
  109. +)
  110. case "$target_os" in
  111. darwin*)
  112. --- minidlna.c.orig 2017-05-18 05:55:17.000000000 +0900
  113. +++ minidlna.c 2017-05-26 14:48:58.925667651 +0900
  114. @@ -539,6 +539,11 @@
  115. runtime_vars.root_container = NULL;
  116. runtime_vars.ifaces[0] = NULL;
  117. +#ifdef THUMBNAIL_CREATION
  118. + runtime_vars.thumb_width = 160;
  119. + runtime_vars.thumb_quality = 8;
  120. +#endif
  121. +
  122. /* read options file first since
  123. * command line arguments have final say */
  124. if (readoptionsfile(optionsfile) < 0)
  125. @@ -752,6 +757,30 @@
  126. if (strcasecmp(ary_options[i].value, "beacon") == 0)
  127. CLEARFLAG(TIVO_BONJOUR_MASK);
  128. break;
  129. +#ifdef THUMBNAIL_CREATION
  130. + case ENABLE_THUMB:
  131. + if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) )
  132. + SETFLAG(THUMB_MASK);
  133. + break;
  134. + case THUMB_WIDTH:
  135. + runtime_vars.thumb_width = atoi(ary_options[i].value);
  136. + if (runtime_vars.thumb_width < 120)
  137. + runtime_vars.thumb_width = 120;
  138. + if (runtime_vars.thumb_width > 480)
  139. + runtime_vars.thumb_width = 480;
  140. + break;
  141. + case THUMB_QUALITY:
  142. + runtime_vars.thumb_quality = atoi(ary_options[i].value);
  143. + if (runtime_vars.thumb_quality < 5)
  144. + runtime_vars.thumb_quality = 5;
  145. + if (runtime_vars.thumb_quality > 30)
  146. + runtime_vars.thumb_quality = 30;
  147. + break;
  148. + case ENABLE_THUMB_FILMSTRIP:
  149. + if( (strcmp(ary_options[i].value, "yes") == 0) || atoi(ary_options[i].value) )
  150. + SETFLAG(THUMB_FILMSTRIP);
  151. + break;
  152. +#endif
  153. default:
  154. DPRINTF(E_ERROR, L_GENERAL, "Unknown option in file %s\n",
  155. optionsfile);
  156. --- minidlna.conf.orig 2017-05-18 05:55:17.000000000 +0900
  157. +++ minidlna.conf 2017-05-26 14:52:57.185771270 +0900
  158. @@ -88,3 +88,15 @@
  159. # set this to yes to allow symlinks that point outside user-defined media_dirs.
  160. #wide_links=no
  161. +
  162. +# Suport to Movie Thumbnail generation. To use this option, thumbnail generation must be enable at compile time.
  163. +#enable_thumbnail=no
  164. +
  165. +# 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.
  166. +#thumbnail_width=160
  167. +
  168. +# Thumbnail Image quality. To use this option, thumbnail generation must be enable at compile time.
  169. +#thumbnail_quality=8
  170. +
  171. +# Should the thumbnail have a film strip? To use this option, thumbnail generation must be enable at compile time.
  172. +#enable_thumbnail_filmstrip=no
  173. --- options.c.orig 2017-05-18 05:55:17.000000000 +0900
  174. +++ options.c 2017-05-26 14:56:38.408012333 +0900
  175. @@ -64,7 +64,15 @@
  176. { USER_ACCOUNT, "user" },
  177. { FORCE_SORT_CRITERIA, "force_sort_criteria" },
  178. { MAX_CONNECTIONS, "max_connections" },
  179. +#ifndef THUMBNAIL_CREATION
  180. { MERGE_MEDIA_DIRS, "merge_media_dirs" },
  181. +#else
  182. + { MERGE_MEDIA_DIRS, "merge_media_dirs" },
  183. + { ENABLE_THUMB, "enable_thumbnail" },
  184. + { THUMB_WIDTH, "thumbnail_width" },
  185. + { THUMB_QUALITY, "thumbnail_quality" },
  186. + { ENABLE_THUMB_FILMSTRIP, "enable_thumbnail_filmstrip" },
  187. +#endif
  188. { WIDE_LINKS, "wide_links" },
  189. { TIVO_DISCOVERY, "tivo_discovery" },
  190. };
  191. --- options.h.orig 2017-05-18 05:55:17.000000000 +0900
  192. +++ options.h 2017-05-26 15:07:15.637791194 +0900
  193. @@ -57,7 +57,15 @@
  194. USER_ACCOUNT, /* user account to run as */
  195. FORCE_SORT_CRITERIA, /* force sorting by a given sort criteria */
  196. MAX_CONNECTIONS, /* maximum number of simultaneous connections */
  197. +#ifndef THUMBNAIL_CREATION
  198. MERGE_MEDIA_DIRS, /* don't add an extra directory level when there are multiple media dirs */
  199. +#else
  200. + MERGE_MEDIA_DIRS, /* don't add an extra directory level when there are multiple media dirs */
  201. + ENABLE_THUMB, /* enable thumbnail generation */
  202. + THUMB_WIDTH, /* thunbnail image with */
  203. + THUMB_QUALITY, /* thumnail image quality */
  204. + ENABLE_THUMB_FILMSTRIP, /* film strip overlay */
  205. +#endif
  206. WIDE_LINKS, /* allow following symlinks outside the defined media_dirs */
  207. TIVO_DISCOVERY, /* TiVo discovery protocol: bonjour or beacon. Defaults to bonjour if supported */
  208. };
  209. --- upnpglobalvars.h.orig 2017-05-18 05:55:17.000000000 +0900
  210. +++ upnpglobalvars.h 2017-05-26 15:12:44.457010482 +0900
  211. @@ -196,6 +196,11 @@
  212. #define SCANNING_MASK 0x0100
  213. #define RESCAN_MASK 0x0200
  214. +#ifdef THUMBNAIL_CREATION
  215. +#define THUMB_MASK 0x0100
  216. +#define THUMB_FILMSTRIP 0x0200
  217. +#endif
  218. +
  219. #define SETFLAG(mask) runtime_flags |= mask
  220. #define GETFLAG(mask) (runtime_flags & mask)
  221. #define CLEARFLAG(mask) runtime_flags &= ~mask
  222. --- utils.h.orig 2017-05-18 05:55:17.000000000 +0900
  223. +++ utils.h 2017-05-26 15:18:47.939957870 +0900
  224. @@ -101,4 +101,8 @@
  225. int make_dir(char * path, mode_t mode);
  226. unsigned int DJBHash(uint8_t *data, int len);
  227. +#ifdef THUMBNAIL_CREATION
  228. +int rename_artcache_dir(const char * oldpath, const char * newpath);
  229. +#endif
  230. +
  231. #endif
  232. --- minidlnatypes.h.orig 2017-05-18 05:55:17.000000000 +0900
  233. +++ minidlnatypes.h 2017-05-26 15:25:08.389784656 +0900
  234. @@ -51,6 +51,10 @@
  235. int max_connections; /* max number of simultaneous conenctions */
  236. const char *root_container; /* root ObjectID (instead of "0") */
  237. const char *ifaces[MAX_LAN_ADDR]; /* list of configured network interfaces */
  238. +#ifdef THUMBNAIL_CREATION
  239. + int thumb_width;
  240. + int thumb_quality;
  241. +#endif
  242. };
  243. struct string_s {
  244. --- monitor.c.orig 2017-05-18 05:55:17.000000000 +0900
  245. +++ monitor.c 2017-05-26 16:28:48.306100398 +0900
  246. @@ -322,6 +322,16 @@
  247. sql_exec(db, "DELETE from OBJECTS where DETAIL_ID = %lld", detailID);
  248. }
  249. snprintf(art_cache, sizeof(art_cache), "%s/art_cache%s", db_path, path);
  250. +
  251. +#ifdef THUMBNAIL_CREATION
  252. + /* Remove video thumbnails */
  253. + if ( is_video(path) )
  254. + {
  255. + char *vthumb = art_cache;
  256. + strcpy(strchr(vthumb, '\0')-4, ".jpg");
  257. + }
  258. +#endif
  259. +
  260. remove(art_cache);
  261. return 0;
  262. @@ -616,6 +626,11 @@
  263. sigdelset(&set, SIGCHLD);
  264. pthread_sigmask(SIG_BLOCK, &set, NULL);
  265. +#ifdef THUMBNAIL_CREATION
  266. + char renpath_buf[PATH_MAX];
  267. + int cookie = 0;
  268. +#endif
  269. +
  270. pollfds[0].fd = inotify_init();
  271. pollfds[0].events = POLLIN;
  272. @@ -685,6 +700,18 @@
  273. {
  274. DPRINTF(E_DEBUG, L_INOTIFY, "The directory %s was %s.\n",
  275. path_buf, (event->mask & IN_MOVED_TO ? "moved here" : "created"));
  276. +
  277. +#ifdef THUMBNAIL_CREATION
  278. + /* We do not want to regenerate the thumbnails if e rename a directory.
  279. + We should keep at least four cookies/olddir since IN_MOVED_FROM/IN_MOVED_TO may
  280. + not arrive in sequence, but one should cover most cases */
  281. + if (event->cookie == cookie && event->mask & IN_MOVED_TO)
  282. + {
  283. + DPRINTF(E_DEBUG, L_INOTIFY, "Directory rename: %s -> %s \n", renpath_buf, path_buf);
  284. + rename_artcache_dir(renpath_buf, path_buf);
  285. + }
  286. +#endif
  287. +
  288. monitor_insert_directory(pollfds[0].fd, esc_name, path_buf);
  289. }
  290. else if ( (event->mask & (IN_CLOSE_WRITE|IN_MOVED_TO|IN_CREATE)) &&
  291. @@ -717,7 +744,22 @@
  292. (event->mask & IN_ISDIR ? "directory" : "file"),
  293. path_buf, (event->mask & IN_MOVED_FROM ? "moved away" : "deleted"));
  294. if ( event->mask & IN_ISDIR )
  295. +
  296. +#ifdef THUMBNAIL_CREATION
  297. + {
  298. + if ( event->mask & IN_MOVED_FROM )
  299. + {
  300. + strncpy(renpath_buf, path_buf, sizeof(renpath_buf));
  301. + cookie = event->cookie;
  302. + }
  303. +#endif
  304. +
  305. monitor_remove_directory(pollfds[0].fd, path_buf);
  306. +
  307. +#ifdef THUMBNAIL_CREATION
  308. + }
  309. +#endif
  310. +
  311. else
  312. monitor_remove_file(path_buf);
  313. }
  314. --- utils.c.orig 2017-08-25 02:28:25.000000000 +0900
  315. +++ utils.c 2017-09-15 04:00:57.174194577 +0900
  316. @@ -531,3 +531,17 @@
  317. return ALL_MEDIA;
  318. }
  319. +
  320. +#ifdef THUMBNAIL_CREATION
  321. +int
  322. +rename_artcache_dir(const char * oldpath, const char * newpath)
  323. +{
  324. + char old_artcache[PATH_MAX];
  325. + char new_artcache[PATH_MAX];
  326. +
  327. + snprintf(old_artcache, sizeof(old_artcache), "%s/art_cache%s", db_path, oldpath);
  328. + snprintf(new_artcache, sizeof(old_artcache), "%s/art_cache%s", db_path, newpath);
  329. +
  330. + return rename(old_artcache, new_artcache);
  331. +}
  332. +#endif