Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
VideoLAN
medialibrary
Commits
36d07598
Commit
36d07598
authored
Oct 18, 2018
by
Hugo Beauzée-Luyssen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split thumbnail generation & add new core thumbnailer support
parent
919f08e7
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
462 additions
and
222 deletions
+462
-222
Makefile.am
Makefile.am
+12
-0
configure.ac
configure.ac
+4
-1
src/metadata_services/vlc/CoreThumbnailer.cpp
src/metadata_services/vlc/CoreThumbnailer.cpp
+81
-0
src/metadata_services/vlc/CoreThumbnailer.h
src/metadata_services/vlc/CoreThumbnailer.h
+40
-0
src/metadata_services/vlc/VLCThumbnailer.cpp
src/metadata_services/vlc/VLCThumbnailer.cpp
+22
-192
src/metadata_services/vlc/VLCThumbnailer.h
src/metadata_services/vlc/VLCThumbnailer.h
+14
-29
src/metadata_services/vlc/VmemThumbnailer.cpp
src/metadata_services/vlc/VmemThumbnailer.cpp
+217
-0
src/metadata_services/vlc/VmemThumbnailer.h
src/metadata_services/vlc/VmemThumbnailer.h
+72
-0
No files found.
Makefile.am
View file @
36d07598
...
...
@@ -215,6 +215,16 @@ endif
if
HAVE_LIBVLC
if
HAVE_LIBVLC4
libmedialibrary_la_SOURCES
+=
\
src/metadata_services/vlc/CoreThumbnailer.cpp
\
src/metadata_services/vlc/CoreThumbnailer.h
else
libmedialibrary_la_SOURCES
+=
\
src/metadata_services/vlc/VmemThumbnailer.cpp
\
src/metadata_services/vlc/VmemThumbnailer.h
if
HAVE_LIBJPEG
libmedialibrary_la_SOURCES
+=
src/metadata_services/vlc/imagecompressors/JpegCompressor.cpp
noinst_HEADERS
+=
src/metadata_services/vlc/imagecompressors/JpegCompressor.h
...
...
@@ -222,6 +232,8 @@ libmedialibrary_la_CPPFLAGS += $(LIBJPEG_CFLAGS)
libmedialibrary_la_LIBADD
+=
$(LIBJPEG_LIBS)
endif
endif
libmedialibrary_la_SOURCES
+=
\
src/metadata_services/vlc/VLCMetadataService.cpp
\
src/metadata_services/vlc/VLCThumbnailer.cpp
\
...
...
configure.ac
View file @
36d07598
...
...
@@ -263,7 +263,9 @@ AC_ARG_WITH(libvlc, [AC_HELP_STRING([--with-libvlc], [build with libvlc integrat
AH_TEMPLATE(HAVE_LIBVLC, [Define to 1 if libvlc integration is enabled])
AS_IF([test "${with_libvlc}" != "no"], [
AC_DEFINE(HAVE_LIBVLC)
PKG_CHECK_MODULES(VLC, libvlc >= 3.0)
PKG_CHECK_MODULES(VLC, libvlc >= 4.0, [have_libvlc4="yes"], [
PKG_CHECK_MODULES(VLC, libvlc >= 3.0)
])
PKG_CHECK_MODULES(VLCPP, libvlcpp,
[AC_MSG_RESULT([Found libvlcpp.pc])],
[
...
...
@@ -285,6 +287,7 @@ AS_IF([test "${with_libvlc}" != "no"], [
])
])
AM_CONDITIONAL(HAVE_LIBVLC, [test "${with_libvlc}" != "no"])
AM_CONDITIONAL(HAVE_LIBVLC4, [test "${have_libvlc4}" = "yes" ])
AM_CONDITIONAL([HAVE_LIBJPEG], [test "${have_libjpeg}" = "yes"])
PKG_CHECK_MODULES(SQLITE, sqlite3)
...
...
src/metadata_services/vlc/CoreThumbnailer.cpp
0 → 100644
View file @
36d07598
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2018 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* 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 "CoreThumbnailer.h"
#include "compat/ConditionVariable.h"
#include "compat/Mutex.h"
#include "Media.h"
#include "MediaLibrary.h"
#include "utils/VLCInstance.h"
#include <vlcpp/vlc.hpp>
namespace
medialibrary
{
CoreThumbnailer
::
CoreThumbnailer
(
MediaLibraryPtr
ml
)
:
m_ml
(
ml
)
{
}
bool
CoreThumbnailer
::
generate
(
medialibrary
::
MediaPtr
media
,
const
std
::
string
&
mrl
)
{
VLC
::
Media
vlcMedia
{
VLCInstance
::
get
(),
mrl
,
VLC
::
Media
::
FromType
::
FromLocation
};
auto
em
=
vlcMedia
.
eventManager
();
compat
::
ConditionVariable
cond
;
compat
::
Mutex
lock
;
auto
done
=
false
;
VLC
::
Picture
thumbnail
;
em
.
onThumbnailGenerated
([
&
cond
,
&
lock
,
&
thumbnail
,
&
done
](
const
VLC
::
Picture
*
p
)
{
{
std
::
unique_lock
<
compat
::
Mutex
>
l
(
lock
);
if
(
p
!=
nullptr
)
thumbnail
=
*
p
;
done
=
true
;
}
cond
.
notify_all
();
});
{
std
::
unique_lock
<
compat
::
Mutex
>
l
(
lock
);
auto
request
=
vlcMedia
.
thumbnailRequestByPos
(
0.3
f
,
VLC
::
Media
::
ThumbnailSeekSpeed
::
Fast
,
320
,
200
,
VLC
::
Picture
::
Type
::
Jpg
,
3000
);
if
(
request
==
nullptr
)
return
false
;
cond
.
wait
(
l
,
[
&
done
]()
{
return
done
==
true
;
}
);
}
if
(
thumbnail
.
isValid
()
==
false
)
return
false
;
auto
path
=
m_ml
->
thumbnailPath
()
+
"/"
+
std
::
to_string
(
media
->
id
()
)
+
".jpg"
;
if
(
thumbnail
.
save
(
path
)
==
false
)
return
false
;
auto
m
=
static_cast
<
Media
*>
(
media
.
get
()
);
return
m
->
setThumbnail
(
path
,
Thumbnail
::
Origin
::
Media
,
true
);
}
}
src/metadata_services/vlc/CoreThumbnailer.h
0 → 100644
View file @
36d07598
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2015-2018 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* 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.
*****************************************************************************/
#pragma once
#include "VLCThumbnailer.h"
namespace
medialibrary
{
class
CoreThumbnailer
:
public
VLCThumbnailer
::
Generator
{
public:
CoreThumbnailer
(
MediaLibraryPtr
ml
);
virtual
bool
generate
(
MediaPtr
media
,
const
std
::
string
&
mrl
)
override
;
private:
MediaLibraryPtr
m_ml
;
};
}
src/metadata_services/vlc/VLCThumbnailer.cpp
View file @
36d07598
...
...
@@ -30,21 +30,19 @@
#include "VLCThumbnailer.h"
#include "AlbumTrack.h"
#include "Album.h"
#include "Artist.h"
#include "Media.h"
#include "File.h"
#include "logging/Logger.h"
#include "MediaLibrary.h"
#include "utils/VLCInstance.h"
#include "utils/ModificationsNotifier.h"
#include "metadata_services/vlc/Common.hpp"
#ifdef HAVE_JPEG
#include "imagecompressors/JpegCompressor.h"
#include <vlcpp/vlc.hpp>
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
#include "CoreThumbnailer.h"
#else
#
error No image compressor available
#
include "VmemThumbnailer.h"
#endif
namespace
medialibrary
...
...
@@ -54,10 +52,11 @@ VLCThumbnailer::VLCThumbnailer( MediaLibraryPtr ml )
:
m_ml
(
ml
)
,
m_run
(
false
)
,
m_paused
(
false
)
,
m_prevSize
(
0
)
{
#ifdef HAVE_JPEG
m_compressor
.
reset
(
new
JpegCompressor
);
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
m_generator
.
reset
(
new
CoreThumbnailer
(
m_ml
)
);
#else
m_generator
.
reset
(
new
VmemThumbnailer
(
m_ml
)
);
#endif
}
...
...
@@ -70,8 +69,7 @@ void VLCThumbnailer::requestThumbnail( MediaPtr media )
{
{
std
::
unique_lock
<
compat
::
Mutex
>
lock
(
m_mutex
);
auto
task
=
std
::
unique_ptr
<
Task
>
(
new
Task
(
std
::
move
(
media
)
)
);
m_tasks
.
push
(
std
::
move
(
task
)
);
m_tasks
.
push
(
std
::
move
(
media
)
);
}
if
(
m_thread
.
get_id
()
==
compat
::
Thread
::
id
{}
)
{
...
...
@@ -102,7 +100,7 @@ void VLCThumbnailer::run()
LOG_INFO
(
"Starting thumbnailer thread"
);
while
(
m_run
==
true
)
{
std
::
unique_ptr
<
Task
>
task
;
MediaPtr
media
;
{
std
::
unique_lock
<
compat
::
Mutex
>
lock
(
m_mutex
);
if
(
m_tasks
.
size
()
==
0
||
m_paused
==
true
)
...
...
@@ -114,11 +112,11 @@ void VLCThumbnailer::run()
if
(
m_run
==
false
)
break
;
}
task
=
std
::
move
(
m_tasks
.
front
()
);
media
=
std
::
move
(
m_tasks
.
front
()
);
m_tasks
.
pop
();
}
bool
res
=
generateThumbnail
(
*
task
);
m_ml
->
getCb
()
->
onMediaThumbnailReady
(
task
->
media
,
res
);
bool
res
=
generateThumbnail
(
media
);
m_ml
->
getCb
()
->
onMediaThumbnailReady
(
media
,
res
);
}
LOG_INFO
(
"Exiting thumbnailer thread"
);
}
...
...
@@ -138,193 +136,25 @@ void VLCThumbnailer::stop()
}
}
bool
VLCThumbnailer
::
generateThumbnail
(
Task
&
task
)
bool
VLCThumbnailer
::
generateThumbnail
(
MediaPtr
media
)
{
assert
(
task
.
media
->
type
()
!=
Media
::
Type
::
Audio
);
assert
(
media
->
type
()
!=
Media
::
Type
::
Audio
);
auto
files
=
task
.
media
->
files
();
auto
files
=
media
->
files
();
if
(
files
.
empty
()
==
true
)
{
LOG_WARN
(
"Can't generate thumbnail for a media without associated files ("
,
task
.
media
->
title
()
);
return
false
;
}
task
.
mrl
=
files
[
0
]
->
mrl
();
LOG_INFO
(
"Generating "
,
task
.
mrl
,
" thumbnail..."
);
VLC
::
Media
vlcMedia
=
VLC
::
Media
(
VLCInstance
::
get
(),
task
.
mrl
,
VLC
::
Media
::
FromType
::
FromLocation
);
vlcMedia
.
addOption
(
":no-audio"
);
vlcMedia
.
addOption
(
":no-osd"
);
vlcMedia
.
addOption
(
":no-spu"
);
vlcMedia
.
addOption
(
":input-fast-seek"
);
vlcMedia
.
addOption
(
":avcodec-hw=none"
);
vlcMedia
.
addOption
(
":no-mkv-preload-local-dir"
);
auto
duration
=
vlcMedia
.
duration
();
if
(
duration
>
0
)
{
std
::
ostringstream
ss
;
// Duration is in ms, start-time in seconds, and we're aiming at 1/4th of the media
ss
<<
":start-time="
<<
duration
/
4000
;
vlcMedia
.
addOption
(
ss
.
str
()
);
}
task
.
mp
=
VLC
::
MediaPlayer
(
vlcMedia
);
setupVout
(
task
);
auto
res
=
MetadataCommon
::
startPlayback
(
vlcMedia
,
task
.
mp
);
if
(
res
==
false
)
{
LOG_WARN
(
"Failed to generate "
,
task
.
mrl
,
" thumbnail: Can't start playback"
);
media
->
title
()
);
return
false
;
}
auto
mrl
=
files
[
0
]
->
mrl
();
if
(
duration
<=
0
)
{
// Seek ahead to have a significant preview
res
=
seekAhead
(
task
);
if
(
res
==
false
)
{
LOG_WARN
(
"Failed to generate "
,
task
.
mrl
,
" thumbnail: Failed to seek ahead"
);
return
false
;
}
}
res
=
takeThumbnail
(
task
);
if
(
res
==
false
)
return
false
;
LOG_INFO
(
"Done generating "
,
task
.
mrl
,
" thumbnail"
);
m_ml
->
getNotifier
()
->
notifyMediaModification
(
task
.
media
);
return
true
;
}
bool
VLCThumbnailer
::
seekAhead
(
Task
&
task
)
{
float
pos
=
.0
f
;
auto
event
=
task
.
mp
.
eventManager
().
onPositionChanged
([
&
task
,
&
pos
](
float
p
)
{
std
::
unique_lock
<
compat
::
Mutex
>
lock
(
task
.
mutex
);
pos
=
p
;
task
.
cond
.
notify_all
();
});
auto
success
=
false
;
{
std
::
unique_lock
<
compat
::
Mutex
>
lock
(
task
.
mutex
);
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
task
.
mp
.
setPosition
(
.4
f
,
true
);
#else
task
.
mp
.
setPosition
(
.4
f
);
#endif
success
=
task
.
cond
.
wait_for
(
lock
,
std
::
chrono
::
seconds
(
3
),
[
&
pos
]()
{
return
pos
>=
.1
f
;
});
}
// Since we're locking a mutex for each position changed, let's unregister ASAP
event
->
unregister
();
return
success
;
}
void
VLCThumbnailer
::
setupVout
(
Task
&
task
)
{
task
.
mp
.
setVideoFormatCallbacks
(
// Setup
[
this
,
&
task
](
char
*
chroma
,
unsigned
int
*
width
,
unsigned
int
*
height
,
unsigned
int
*
pitches
,
unsigned
int
*
lines
)
{
strcpy
(
chroma
,
m_compressor
->
fourCC
()
);
const
float
inputAR
=
(
float
)
*
width
/
*
height
;
task
.
width
=
DesiredWidth
;
task
.
height
=
(
float
)
task
.
width
/
inputAR
+
1
;
if
(
task
.
height
<
DesiredHeight
)
{
// Avoid downscaling too much for really wide pictures
task
.
width
=
inputAR
*
DesiredHeight
;
task
.
height
=
DesiredHeight
;
}
auto
size
=
task
.
width
*
task
.
height
*
m_compressor
->
bpp
();
// If our buffer isn't enough anymore, reallocate a new one.
if
(
size
>
m_prevSize
)
{
m_buff
.
reset
(
new
uint8_t
[
size
]
);
m_prevSize
=
size
;
}
*
width
=
task
.
width
;
*
height
=
task
.
height
;
*
pitches
=
task
.
width
*
m_compressor
->
bpp
();
*
lines
=
task
.
height
;
return
1
;
},
// Cleanup
nullptr
);
task
.
mp
.
setVideoCallbacks
(
// Lock
[
this
](
void
**
pp_buff
)
{
*
pp_buff
=
m_buff
.
get
();
return
nullptr
;
},
//unlock
nullptr
,
//display
[
&
task
](
void
*
)
{
bool
expected
=
true
;
if
(
task
.
thumbnailRequired
.
compare_exchange_strong
(
expected
,
false
)
)
{
task
.
cond
.
notify_all
();
}
}
);
}
bool
VLCThumbnailer
::
takeThumbnail
(
Task
&
task
)
{
// lock, signal that we want a thumbnail, and wait.
{
std
::
unique_lock
<
compat
::
Mutex
>
lock
(
task
.
mutex
);
task
.
thumbnailRequired
=
true
;
bool
success
=
task
.
cond
.
wait_for
(
lock
,
std
::
chrono
::
seconds
(
15
),
[
&
task
]()
{
// Keep waiting if the vmem thread hasn't restored m_thumbnailRequired to false
return
task
.
thumbnailRequired
==
false
;
});
if
(
success
==
false
)
{
LOG_WARN
(
"Timed out while computing "
,
task
.
mrl
,
" snapshot"
);
return
false
;
}
}
task
.
mp
.
stop
();
return
compress
(
task
);
}
bool
VLCThumbnailer
::
compress
(
Task
&
task
)
{
auto
path
=
m_ml
->
thumbnailPath
();
path
+=
"/"
;
path
+=
std
::
to_string
(
task
.
media
->
id
()
)
+
"."
+
m_compressor
->
extension
();
auto
hOffset
=
task
.
width
>
DesiredWidth
?
(
task
.
width
-
DesiredWidth
)
/
2
:
0
;
auto
vOffset
=
task
.
height
>
DesiredHeight
?
(
task
.
height
-
DesiredHeight
)
/
2
:
0
;
if
(
m_compressor
->
compress
(
m_buff
.
get
(),
path
,
task
.
width
,
task
.
height
,
DesiredWidth
,
DesiredHeight
,
hOffset
,
vOffset
)
==
false
)
LOG_INFO
(
"Generating "
,
mrl
,
" thumbnail..."
);
if
(
m_generator
->
generate
(
media
,
mrl
)
==
false
)
return
false
;
auto
media
=
static_cast
<
Media
*>
(
task
.
media
.
get
()
);
media
->
setThumbnail
(
path
,
Thumbnail
::
Origin
::
Media
,
true
);
m_ml
->
getNotifier
()
->
notifyMediaModification
(
media
);
return
true
;
}
VLCThumbnailer
::
Task
::
Task
(
MediaPtr
m
)
:
media
(
std
::
move
(
m
)
)
,
width
(
0
)
,
height
(
0
)
,
thumbnailRequired
(
false
)
{
}
}
src/metadata_services/vlc/VLCThumbnailer.h
View file @
36d07598
...
...
@@ -23,32 +23,26 @@
#pragma once
#include "compat/ConditionVariable.h"
#include "compat/Thread.h"
#include "medialibrary/Types.h"
#include "Types.h"
#include <vlcpp/vlc.hpp>
#include "imagecompressors/IImageCompressor.h"
#include "parser/ParserWorker.h"
#include <queue>
#include <atomic>
namespace
medialibrary
{
class
VLCThumbnailer
{
struct
Task
public:
class
Generator
{
Task
(
MediaPtr
media
);
compat
::
Mutex
mutex
;
compat
::
ConditionVariable
cond
;
MediaPtr
media
;
std
::
string
mrl
;
uint32_t
width
;
uint32_t
height
;
VLC
::
MediaPlayer
mp
;
std
::
atomic_bool
thumbnailRequired
;
public:
virtual
~
Generator
()
=
default
;
virtual
bool
generate
(
MediaPtr
media
,
const
std
::
string
&
mrl
)
=
0
;
};
public:
explicit
VLCThumbnailer
(
MediaLibraryPtr
ml
);
virtual
~
VLCThumbnailer
();
void
requestThumbnail
(
MediaPtr
media
);
...
...
@@ -59,29 +53,20 @@ private:
void
run
();
void
stop
();
bool
generateThumbnail
(
Task
&
task
);
bool
seekAhead
(
Task
&
task
);
void
setupVout
(
Task
&
task
);
bool
takeThumbnail
(
Task
&
task
);
bool
compress
(
Task
&
task
);
bool
generateThumbnail
(
MediaPtr
task
);
private:
// Force a base width, let height be computed depending on A/R
static
const
uint32_t
DesiredWidth
=
320
;
static
const
uint32_t
DesiredHeight
=
200
;
// Aim for a 16:10 thumbnail
private:
MediaLibraryPtr
m_ml
;
compat
::
Mutex
m_mutex
;
compat
::
ConditionVariable
m_cond
;
std
::
queue
<
std
::
unique_ptr
<
Task
>
>
m_tasks
;
std
::
queue
<
MediaPtr
>
m_tasks
;
std
::
atomic_bool
m_run
;
std
::
unique_ptr
<
Generator
>
m_generator
;
compat
::
Thread
m_thread
;
bool
m_paused
;
std
::
unique_ptr
<
IImageCompressor
>
m_compressor
;
std
::
unique_ptr
<
uint8_t
[]
>
m_buff
;
uint32_t
m_prevSize
;
};
}
src/metadata_services/vlc/VmemThumbnailer.cpp
0 → 100644
View file @
36d07598
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2015-2018 Hugo Beauzée-Luyssen, Videolabs, VideoLAN
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* 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 "VmemThumbnailer.h"
#include "Media.h"
#include "Thumbnail.h"
#include "utils/VLCInstance.h"
#include "metadata_services/vlc/Common.hpp"
#ifdef HAVE_JPEG
#include "imagecompressors/JpegCompressor.h"
#else
#error No image compressor available
#endif
namespace
medialibrary
{
VmemThumbnailer
::
VmemThumbnailer
(
MediaLibraryPtr
ml
)
:
m_ml
(
ml
)
,
m_prevSize
(
0
)
{
#ifdef HAVE_JPEG
m_compressor
.
reset
(
new
JpegCompressor
);
#endif
}
bool
VmemThumbnailer
::
generate
(
MediaPtr
media
,
const
std
::
string
&
mrl
)
{
VLC
::
Media
vlcMedia
=
VLC
::
Media
(
VLCInstance
::
get
(),
mrl
,
VLC
::
Media
::
FromType
::
FromLocation
);
vlcMedia
.
addOption
(
":no-audio"
);
vlcMedia
.
addOption
(
":no-osd"
);
vlcMedia
.
addOption
(
":no-spu"
);
vlcMedia
.
addOption
(
":input-fast-seek"
);
vlcMedia
.
addOption
(
":avcodec-hw=none"
);
vlcMedia
.
addOption
(
":no-mkv-preload-local-dir"
);
auto
duration
=
vlcMedia
.
duration
();
if
(
duration
>
0
)
{
std
::
ostringstream
ss
;
// Duration is in ms, start-time in seconds, and we're aiming at 1/4th of the media
ss
<<
":start-time="
<<
duration
/
4000
;
vlcMedia
.
addOption
(
ss
.
str
()
);
}
Task
task
{
media
,
mrl
};
task
.
mp
=
VLC
::
MediaPlayer
(
vlcMedia
);
setupVout
(
task
);
auto
res
=
MetadataCommon
::
startPlayback
(
vlcMedia
,
task
.
mp
);
if
(
res
==
false
)
{
LOG_WARN
(
"Failed to generate "
,
mrl
,
" thumbnail: Can't start playback"
);
return
false
;
}
if
(
duration
<=
0
)
{
// Seek ahead to have a significant preview
res
=
seekAhead
(
task
);
if
(
res
==
false
)
{
LOG_WARN
(
"Failed to genera