Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
medialibrary
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
57
Issues
57
List
Boards
Labels
Service Desk
Milestones
Merge Requests
8
Merge Requests
8
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
VideoLAN
medialibrary
Commits
e3aafc3c
Commit
e3aafc3c
authored
Oct 02, 2015
by
Hugo Beauzée-Luyssen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
VLCThumbnailer: Use vmem to compute snapshots
parent
349b20ca
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
137 additions
and
48 deletions
+137
-48
src/CMakeLists.txt
src/CMakeLists.txt
+5
-1
src/MediaLibrary.cpp
src/MediaLibrary.cpp
+0
-1
src/metadata_services/vlc/VLCThumbnailer.cpp
src/metadata_services/vlc/VLCThumbnailer.cpp
+122
-46
src/metadata_services/vlc/VLCThumbnailer.h
src/metadata_services/vlc/VLCThumbnailer.h
+10
-0
No files found.
src/CMakeLists.txt
View file @
e3aafc3c
...
...
@@ -97,8 +97,12 @@ target_link_libraries(${PROJECT_NAME} ${SQLITE3_LIBRARIES})
if
(
${
WITH_VLC
}
)
find_package
(
LIBVLC REQUIRED
)
target_link_libraries
(
${
PROJECT_NAME
}
${
LIBVLC_LIBRARY
}
)
# Since VLC include a thumbnailer, we need libjpeg to encode the result
find_package
(
JPEG REQUIRED
)
target_link_libraries
(
${
PROJECT_NAME
}
${
LIBVLC_LIBRARY
}
)
target_link_libraries
(
${
PROJECT_NAME
}
${
JPEG_LIBRARIES
}
)
include_directories
(
${
LIBVLC_INCLUDE_DIR
}
)
include_directories
(
${
JPEG_INCLUDE_DIR
}
)
set
(
LIBVLCPP_DIR
""
CACHE PATH
"Path to libvlcpp's directory"
)
include_directories
(
${
LIBVLCPP_DIR
}
)
endif
()
...
...
src/MediaLibrary.cpp
View file @
e3aafc3c
...
...
@@ -81,7 +81,6 @@ bool MediaLibrary::initialize( const std::string& dbPath, const std::string& sna
{
const
char
*
args
[]
=
{
"-vv"
,
"--vout=dummy"
,
};
m_vlcInstance
=
VLC
::
Instance
(
sizeof
(
args
)
/
sizeof
(
args
[
0
]),
args
);
m_vlcInstance
.
logSet
([](
int
lvl
,
const
libvlc_log_t
*
,
std
::
string
msg
)
{
...
...
src/metadata_services/vlc/VLCThumbnailer.cpp
View file @
e3aafc3c
#include "VLCThumbnailer.h"
#include <cstring>
#include <jpeglib.h>
#include "IFile.h"
#include "logging/Logger.h"
VLCThumbnailer
::
VLCThumbnailer
(
const
VLC
::
Instance
&
vlc
)
:
m_instance
(
vlc
)
,
m_snapshotRequired
(
false
)
,
m_height
(
0
)
{
}
...
...
@@ -41,7 +45,6 @@ bool VLCThumbnailer::run( FilePtr file, void *data )
VLC
::
Media
media
(
m_instance
,
file
->
mrl
(),
VLC
::
Media
::
FromPath
);
media
.
addOption
(
":no-audio"
);
media
.
addOption
(
":avcodec-hw=none"
);
VLC
::
MediaPlayer
mp
(
media
);
setupVout
(
mp
);
...
...
@@ -53,32 +56,20 @@ bool VLCThumbnailer::run( FilePtr file, void *data )
if
(
seekAhead
(
file
,
mp
,
data
)
==
false
)
return
false
;
auto
path
=
m_ml
->
snapshotPath
();
path
+=
"/"
;
path
+=
std
::
to_string
(
file
->
id
()
)
+
".jpg"
;
if
(
mp
.
takeSnapshot
(
0
,
path
,
320
,
240
)
==
false
)
{
m_cb
->
done
(
file
,
StatusError
,
data
);
if
(
takeSnapshot
(
file
,
mp
,
data
)
==
false
)
return
false
;
}
m_cb
->
done
(
file
,
StatusSuccess
,
data
);
file
->
setSnapshot
(
path
);
return
true
;
}
bool
VLCThumbnailer
::
startPlayback
(
FilePtr
file
,
VLC
::
MediaPlayer
&
mp
,
void
*
data
)
{
bool
failed
=
true
;
int
nbVout
=
0
;
std
::
unique_lock
<
std
::
mutex
>
lock
(
m_mutex
);
// We need a valid vout to call takeSnapshot. Let's also
// assume the media player is playing when a vout is created.
mp
.
eventManager
().
onVout
([
this
,
&
failed
,
&
nbVout
](
int
nb
)
{
mp
.
eventManager
().
onPlaying
([
this
,
&
failed
]()
{
std
::
unique_lock
<
std
::
mutex
>
lock
(
m_mutex
);
failed
=
false
;
nbVout
=
nb
;
m_cond
.
notify_all
();
});
mp
.
eventManager
().
onEncounteredError
([
this
]()
{
...
...
@@ -86,9 +77,8 @@ bool VLCThumbnailer::startPlayback( FilePtr file, VLC::MediaPlayer &mp, void* da
m_cond
.
notify_all
();
});
mp
.
play
();
bool
success
=
m_cond
.
wait_for
(
lock
,
std
::
chrono
::
seconds
(
3
),
[
&
mp
,
&
nbVout
]()
{
return
(
mp
.
state
()
==
libvlc_Playing
&&
nbVout
>
0
)
||
mp
.
state
()
==
libvlc_Error
;
bool
success
=
m_cond
.
wait_for
(
lock
,
std
::
chrono
::
seconds
(
3
),
[
&
mp
]()
{
return
mp
.
state
()
==
libvlc_Playing
||
mp
.
state
()
==
libvlc_Error
;
});
if
(
success
==
false
||
failed
==
true
)
{
...
...
@@ -108,7 +98,7 @@ bool VLCThumbnailer::seekAhead( FilePtr file, VLC::MediaPlayer& mp, void* data )
pos
=
p
;
m_cond
.
notify_all
();
});
mp
.
setPosition
(
.
3
f
);
mp
.
setPosition
(
.
4
f
);
bool
success
=
m_cond
.
wait_for
(
lock
,
std
::
chrono
::
seconds
(
3
),
[
&
pos
]()
{
return
pos
>=
.1
f
;
});
...
...
@@ -122,32 +112,118 @@ bool VLCThumbnailer::seekAhead( FilePtr file, VLC::MediaPlayer& mp, void* data )
return
true
;
}
void
VLCThumbnailer
::
setupVout
(
VLC
::
MediaPlayer
&
)
void
VLCThumbnailer
::
setupVout
(
VLC
::
MediaPlayer
&
mp
)
{
mp
.
setVideoFormatCallbacks
(
// Setup
[
this
,
&
mp
](
char
*
chroma
,
unsigned
int
*
width
,
unsigned
int
*
height
,
unsigned
int
*
pitches
,
unsigned
int
*
lines
)
{
strcpy
(
chroma
,
"RV32"
);
const
float
inputAR
=
(
float
)
*
width
/
*
height
;
*
width
=
Width
;
auto
prevHeight
=
m_height
;
m_height
=
(
float
)
Width
/
inputAR
+
1
;
// If our buffer isn't enough anymore, reallocate a new one.
if
(
m_height
>
prevHeight
)
m_buff
.
reset
(
new
uint8_t
[
Width
*
m_height
*
Bpp
]
);
*
height
=
m_height
;
*
pitches
=
Width
*
Bpp
;
*
lines
=
m_height
;
return
1
;
},
// Cleanup
nullptr
);
mp
.
setVideoCallbacks
(
// Lock
[
this
](
void
**
pp_buff
)
{
*
pp_buff
=
m_buff
.
get
();
return
nullptr
;
},
//unlock
[
this
](
void
*
,
void
*
const
*
)
{
std
::
unique_lock
<
std
::
mutex
>
lock
(
m_mutex
);
if
(
m_snapshotRequired
==
true
)
{
m_snapshotRequired
=
false
;
m_cond
.
notify_all
();
}
}
,
//display
nullptr
);
}
bool
VLCThumbnailer
::
takeSnapshot
(
FilePtr
file
,
VLC
::
MediaPlayer
&
mp
,
void
*
data
)
{
return
;
// Let's use this ugly base in the future, but so far, takeSnapshot() will do.
// if ( m_buff == nullptr )
// m_buff.reset( new uint8_t[320 * 240 * 4] );
// mp.setVideoFormatCallbacks(
// // Setup
// [](char* chroma, unsigned int* width, unsigned int *height, unsigned int *pitches, unsigned int *lines) {
// strcpy( chroma, "RV32" );
// *width = 320;
// *height = 240;
// *pitches = 240 * 4;
// *lines = 240;
// return 1;
// },
// // Cleanup
// nullptr);
// mp.setVideoCallbacks(
// // Lock
// [this](void** pp_buff) {
// *pp_buff = m_buff.get();
// return nullptr;
// },
// //unlock, display
// nullptr, nullptr);
std
::
unique_ptr
<
uint8_t
[]
>
buff
;
// lock, signal that we want a snapshot, and wait.
{
std
::
unique_lock
<
std
::
mutex
>
lock
(
m_mutex
);
m_snapshotRequired
=
true
;
bool
success
=
m_cond
.
wait_for
(
lock
,
std
::
chrono
::
seconds
(
3
),
[
this
]()
{
// Keep waiting if the vmem thread hasn't restored m_snapshotRequired to false
return
m_snapshotRequired
==
true
;
});
if
(
success
==
false
)
{
m_cb
->
done
(
file
,
StatusError
,
data
);
return
false
;
}
// Prevent the vmem from screwing our snapshot over.
buff
=
std
::
move
(
m_buff
);
// set a new buffer for next snapshot, and to avoid crashing while we stop the media player
m_buff
.
reset
(
new
uint8_t
[
Width
*
m_height
*
Bpp
]
);
}
mp
.
stop
();
return
compress
(
buff
.
get
(),
file
,
data
);
}
bool
VLCThumbnailer
::
compress
(
uint8_t
*
buff
,
FilePtr
file
,
void
*
data
)
{
jpeg_compress_struct
compInfo
;
jpeg_error_mgr
jerr
;
JSAMPROW
row_pointer
[
1
];
auto
path
=
m_ml
->
snapshotPath
();
path
+=
"/"
;
path
+=
std
::
to_string
(
file
->
id
()
)
+
".jpg"
;
compInfo
.
err
=
jpeg_std_error
(
&
jerr
);
jpeg_create_compress
(
&
compInfo
);
//FIXME: Abstract this away, though libjpeg requires a FILE*...
auto
fOut
=
fopen
(
path
.
c_str
(),
"wb"
);
// ensure we always close the file.
auto
fOutPtr
=
std
::
unique_ptr
<
FILE
,
int
(
*
)(
FILE
*
)
>
(
fOut
,
&
fclose
);
if
(
fOut
==
nullptr
)
{
LOG_ERROR
(
"Failed to open snapshot file "
,
path
);
m_cb
->
done
(
file
,
StatusError
,
data
);
return
false
;
}
jpeg_stdio_dest
(
&
compInfo
,
fOut
);
compInfo
.
image_width
=
Width
;
compInfo
.
image_height
=
m_height
;
compInfo
.
input_components
=
Bpp
;
compInfo
.
in_color_space
=
JCS_EXT_BGRX
;
jpeg_set_defaults
(
&
compInfo
);
jpeg_set_quality
(
&
compInfo
,
85
,
TRUE
);
jpeg_start_compress
(
&
compInfo
,
TRUE
);
auto
stride
=
compInfo
.
image_width
*
Bpp
;
while
(
compInfo
.
next_scanline
<
compInfo
.
image_height
)
{
row_pointer
[
0
]
=
&
buff
[
compInfo
.
next_scanline
*
stride
];
jpeg_write_scanlines
(
&
compInfo
,
row_pointer
,
1
);
}
jpeg_finish_compress
(
&
compInfo
);
jpeg_destroy_compress
(
&
compInfo
);
m_cb
->
done
(
file
,
StatusSuccess
,
data
);
file
->
setSnapshot
(
path
);
return
true
;
}
src/metadata_services/vlc/VLCThumbnailer.h
View file @
e3aafc3c
...
...
@@ -18,6 +18,13 @@ private:
bool
startPlayback
(
FilePtr
file
,
VLC
::
MediaPlayer
&
mp
,
void
*
data
);
bool
seekAhead
(
FilePtr
file
,
VLC
::
MediaPlayer
&
mp
,
void
*
data
);
void
setupVout
(
VLC
::
MediaPlayer
&
mp
);
bool
takeSnapshot
(
FilePtr
file
,
VLC
::
MediaPlayer
&
mp
,
void
*
data
);
bool
compress
(
uint8_t
*
buff
,
FilePtr
file
,
void
*
data
);
private:
// Force a base width, let height be computed depending on A/R
static
const
uint32_t
Width
=
320
;
static
const
uint8_t
Bpp
=
4
;
private:
VLC
::
Instance
m_instance
;
...
...
@@ -25,5 +32,8 @@ private:
IMediaLibrary
*
m_ml
;
std
::
mutex
m_mutex
;
std
::
condition_variable
m_cond
;
// Per snapshot variables
std
::
unique_ptr
<
uint8_t
[]
>
m_buff
;
bool
m_snapshotRequired
;
uint32_t
m_height
;
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment