Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
savoirfairelinux
jami-daemon
Commits
9979f93a
Commit
9979f93a
authored
Jun 18, 2012
by
Tristan Matthews
Browse files
* #12475: video: use new shm backend, video size is still buggy
parent
48f7af81
Changes
24
Hide whitespace changes
Inline
Side-by-side
daemon/src/dbus/video_controls-introspec.xml
View file @
9979f93a
...
...
@@ -112,16 +112,6 @@
</method>
<method
name=
"startPreview"
tp:name-for-bindings=
"startPreview"
>
<arg
type=
"i"
name=
"width"
direction=
"out"
>
</arg>
<arg
type=
"i"
name=
"height"
direction=
"out"
>
</arg>
<arg
type=
"i"
name=
"shmKey"
direction=
"out"
>
</arg>
<arg
type=
"i"
name=
"semKey"
direction=
"out"
>
</arg>
<arg
type=
"i"
name=
"videoBufferSize"
direction=
"out"
>
</arg>
</method>
<method
name=
"stopPreview"
tp:name-for-bindings=
"stopPreview"
>
...
...
daemon/src/dbus/video_controls.cpp
View file @
9979f93a
...
...
@@ -160,15 +160,10 @@ VideoControls::getSettings() {
return
videoPreference_
.
getSettings
();
}
void
VideoControls
::
startPreview
(
int32_t
&
width
,
int32_t
&
height
,
int32_t
&
shmKey
,
int32_t
&
semKey
,
int32_t
&
videoBufferSize
)
void
VideoControls
::
startPreview
()
{
if
(
preview_
.
get
())
{
ERROR
(
"Video preview was already started!"
);
shmKey
=
-
1
;
semKey
=
-
1
;
videoBufferSize
=
-
1
;
return
;
}
...
...
@@ -177,10 +172,6 @@ void VideoControls::startPreview(int32_t &width, int32_t &height,
map
<
string
,
string
>
args
(
videoPreference_
.
getSettings
());
preview_
.
reset
(
new
sfl_video
::
VideoPreview
(
args
));
width
=
atoi
(
args
[
"width"
].
c_str
());
height
=
atoi
(
args
[
"height"
].
c_str
());
preview_
->
getShmInfo
(
shmKey
,
semKey
,
videoBufferSize
);
}
void
VideoControls
::
stopPreview
()
...
...
daemon/src/dbus/video_controls.h
View file @
9979f93a
...
...
@@ -98,8 +98,7 @@ class VideoControls : public org::sflphone::SFLphone::VideoControls_adaptor,
std
::
string
getInputDeviceRate
();
std
::
string
getCurrentCodecName
(
const
std
::
string
&
callID
);
void
startPreview
(
int32_t
&
width
,
int32_t
&
height
,
int32_t
&
shmKey
,
int32_t
&
semKey
,
int32_t
&
bufferSize
);
void
startPreview
();
void
stopPreview
();
};
...
...
daemon/src/video/Makefile.am
View file @
9979f93a
...
...
@@ -10,8 +10,7 @@ libvideo_la_SOURCES = video_endpoint.cpp video_endpoint.h libav_utils.cpp \
video_preview.h video_preview.cpp video_v4l2.cpp
\
video_v4l2_list.cpp video_v4l2.h video_v4l2_list.h
\
video_preferences.h video_preferences.cpp
\
packet_handle.h packet_handle.cpp shared_memory.cpp
\
shared_memory.h check.h shm_sink.cpp shm_sink.h
packet_handle.h packet_handle.cpp check.h shm_header.h shm_sink.cpp shm_sink.h
libvideo_la_LIBADD
=
@LIBAVCODEC_LIBS@ @LIBAVFORMAT_LIBS@ @LIBAVDEVICE_LIBS@ @LIBSWSCALE_LIBS@ @LIBAVUTIL_LIBS@ @CCRTP_LIBS@ @UDEV_LIBS@
...
...
daemon/src/video/shared_memory.cpp
deleted
100644 → 0
View file @
48f7af81
/*
* Copyright (C) 2004-2012 Savoir-Faire Linux Inc.
*
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#include
"shared_memory.h"
// shm includes
#include
<sys/types.h>
#include
<sys/ipc.h>
#include
<sys/sem.h>
/* semaphore functions and structs. */
#include
<sys/shm.h>
#include
<cstdlib>
#include
<stdexcept>
#include
"manager.h"
#include
"logger.h"
#include
"dbus/video_controls.h"
#include
"fileutils.h"
namespace
sfl_video
{
namespace
{
// anonymous namespace
#if _SEM_SEMUN_UNDEFINED
union
semun
{
int
val
;
/* value for SETVAL */
struct
semid_ds
*
buf
;
/* buffer for IPC_STAT & IPC_SET */
unsigned
short
int
*
array
;
/* array for GETALL & SETALL */
struct
seminfo
*
__buf
;
/* buffer for IPC_INFO */
};
#endif
void
cleanupSemaphore
(
int
semaphoreSetID
)
{
semctl
(
semaphoreSetID
,
0
,
IPC_RMID
);
}
/*
* function: sem_signal. signals the process that a frame is ready.
* input: semaphore set ID.
* output: none.
*/
void
sem_signal
(
int
semaphoreSetID
)
{
/* structure for semaphore operations. */
sembuf
sem_op
;
/* signal the semaphore - increase its value by one. */
sem_op
.
sem_num
=
0
;
sem_op
.
sem_op
=
1
;
sem_op
.
sem_flg
=
0
;
semop
(
semaphoreSetID
,
&
sem_op
,
1
);
}
/* join and/or create a shared memory segment */
int
createShmKey
()
{
/* connect to and possibly create a segment with 644 permissions
(rw-r--r--) */
srand
(
time
(
NULL
));
int
proj_id
=
rand
();
return
ftok
(
fileutils
::
get_program_dir
(),
proj_id
);
}
int
createShmID
(
int
key
,
int
numBytes
)
{
int
shm_id
=
shmget
(
key
,
numBytes
,
0644
|
IPC_CREAT
);
if
(
shm_id
==
-
1
)
ERROR
(
"shmget:%m"
);
return
shm_id
;
}
/* attach a shared memory segment */
uint8_t
*
attachShm
(
int
shm_id
)
{
/* attach to the segment and get a pointer to it */
uint8_t
*
data
=
reinterpret_cast
<
uint8_t
*>
(
shmat
(
shm_id
,
(
void
*
)
0
,
0
));
if
(
data
==
reinterpret_cast
<
uint8_t
*>
(
-
1
))
{
ERROR
(
"shmat:%m"
);
data
=
NULL
;
}
return
data
;
}
void
detachShm
(
uint8_t
*
data
)
{
/* detach from the segment: */
if
(
data
and
shmdt
(
data
)
==
-
1
)
ERROR
(
"shmdt:%m"
);
}
void
destroyShm
(
int
shm_id
)
{
/* destroy it */
shmctl
(
shm_id
,
IPC_RMID
,
NULL
);
}
void
cleanupShm
(
int
shm_id
,
uint8_t
*
data
)
{
detachShm
(
data
);
destroyShm
(
shm_id
);
}
int
createSemaphoreKey
(
int
shmKey
)
{
key_t
key
;
do
key
=
ftok
(
fileutils
::
get_program_dir
(),
rand
());
while
(
key
==
shmKey
);
return
key
;
}
int
createSemaphoreSetID
(
int
semaphoreKey
)
{
/* first we create a semaphore set with a single semaphore,
whose counter is initialized to '0'. */
int
semaphoreSetID
=
semget
(
semaphoreKey
,
1
,
0600
|
IPC_CREAT
);
if
(
semaphoreSetID
==
-
1
)
{
ERROR
(
"semget:%m"
);
throw
std
::
runtime_error
(
"Could not create semaphore set"
);
}
/* semaphore value, for semctl(). */
union
semun
sem_val
;
sem_val
.
val
=
0
;
semctl
(
semaphoreSetID
,
0
,
SETVAL
,
sem_val
);
return
semaphoreSetID
;
}
}
// end anonymous namespace
SharedMemory
::
SharedMemory
(
VideoControls
&
controls
)
:
videoControls_
(
controls
),
shmKey_
(
0
),
shmID_
(
0
),
shmBuffer_
(
0
),
semaphoreSetID_
(
0
),
semaphoreKey_
(
0
),
dstWidth_
(
0
),
dstHeight_
(
0
),
bufferSize_
(
0
),
shmReady_
()
{}
void
SharedMemory
::
allocateBuffer
(
int
width
,
int
height
,
int
size
)
{
dstWidth_
=
width
;
dstHeight_
=
height
;
bufferSize_
=
size
;
shmKey_
=
createShmKey
();
shmID_
=
createShmID
(
shmKey_
,
bufferSize_
);
shmBuffer_
=
attachShm
(
shmID_
);
semaphoreKey_
=
createSemaphoreKey
(
shmKey_
);
semaphoreSetID_
=
createSemaphoreSetID
(
semaphoreKey_
);
shmReady_
.
signal
();
}
void
SharedMemory
::
publishShm
()
{
DEBUG
(
"Publishing shm: %d sem: %d size: %d"
,
shmKey_
,
semaphoreKey_
,
bufferSize_
);
videoControls_
.
receivingEvent
(
shmKey_
,
semaphoreKey_
,
bufferSize_
,
dstWidth_
,
dstHeight_
);
}
void
SharedMemory
::
waitForShm
()
{
shmReady_
.
wait
();
}
void
SharedMemory
::
frameUpdatedCallback
()
{
// signal the semaphore that a new frame is ready
sem_signal
(
semaphoreSetID_
);
}
SharedMemory
::~
SharedMemory
()
{
// free shared memory resources
videoControls_
.
stoppedReceivingEvent
(
shmKey_
,
semaphoreKey_
);
// make sure no one is waiting for the SHM event which will never come if we've error'd out
shmReady_
.
signal
();
cleanupSemaphore
(
semaphoreSetID_
);
cleanupShm
(
shmID_
,
shmBuffer_
);
}
}
// end namespace sfl_video
daemon/src/video/shared_memory.h
deleted
100644 → 0
View file @
48f7af81
/*
* Copyright (C) 2011, 2012 Savoir-Faire Linux Inc.
* Author: Tristan Matthews <tristan.matthews@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Additional permission under GNU GPL version 3 section 7:
*
* If you modify this program, or any covered work, by linking or
* combining it with the OpenSSL project's OpenSSL library (or a
* modified version of that library), containing parts covered by the
* terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
* grants you additional permission to convey the resulting work.
* Corresponding Source for a non-source form of such a combination
* shall include the source code for the parts of OpenSSL used as well
* as that of the covered work.
*/
#ifndef SHARED_MEMORY_H_
#define SHARED_MEMORY_H_
#include
"cc_thread.h"
#include
"noncopyable.h"
class
VideoControls
;
namespace
sfl_video
{
class
SharedMemory
{
private:
NON_COPYABLE
(
SharedMemory
);
/*-------------------------------------------------------------*/
/* These variables should be used in thread (i.e. run()) only! */
/*-------------------------------------------------------------*/
VideoControls
&
videoControls_
;
int
shmKey_
;
int
shmID_
;
uint8_t
*
shmBuffer_
;
int
semaphoreSetID_
;
int
semaphoreKey_
;
int
dstWidth_
;
int
dstHeight_
;
int
bufferSize_
;
ost
::
Event
shmReady_
;
public:
SharedMemory
(
VideoControls
&
controls
);
~
SharedMemory
();
void
frameUpdatedCallback
();
void
waitForShm
();
// Returns a pointer to the memory where frames should be copied
uint8_t
*
getTargetBuffer
()
{
return
shmBuffer_
;
}
int
getShmKey
()
const
{
return
shmKey_
;
}
int
getSemaphoreKey
()
const
{
return
semaphoreKey_
;
}
int
getBufferSize
()
const
{
return
bufferSize_
;
}
void
allocateBuffer
(
int
width
,
int
height
,
int
size
);
void
publishShm
();
};
}
#endif // SHARED_MEMORY_H_
daemon/src/video/shm_header.h
View file @
9979f93a
...
...
@@ -46,7 +46,6 @@ struct SHMHeader {
int
buffer_size
;
char
data
[
0
];
SHMHeader
()
:
notification
(),
mutex
(),
buffer_gen
(
0
),
buffer_size
(
0
)
{}
};
#endif
daemon/src/video/shm_sink.cpp
View file @
9979f93a
...
...
@@ -148,15 +148,15 @@ SHMSink::resize_area(size_t desired_length)
return
true
;
}
void
SHMSink
::
render
(
c
har
*
data
,
size_t
len
)
void
SHMSink
::
render
(
c
onst
std
::
vector
<
unsigned
char
>
&
data
)
{
shm_lock
();
if
(
!
resize_area
(
sizeof
(
SHMHeader
)
+
len
))
if
(
!
resize_area
(
sizeof
(
SHMHeader
)
+
data
.
size
()
))
return
;
memcpy
(
shm_area_
->
data
,
data
,
len
);
shm_area_
->
buffer_size
=
len
;
memcpy
(
shm_area_
->
data
,
&
(
*
data
.
begin
()),
data
.
size
()
);
shm_area_
->
buffer_size
=
data
.
size
()
;
shm_area_
->
buffer_gen
++
;
sem_post
(
&
shm_area_
->
notification
);
shm_unlock
();
...
...
daemon/src/video/shm_sink.h
View file @
9979f93a
...
...
@@ -38,6 +38,7 @@
#include
<semaphore.h>
#include
<string>
#include
<vector>
#include
"noncopyable.h"
class
SHMHeader
;
...
...
@@ -52,7 +53,7 @@ class SHMSink {
bool
resize_area
(
size_t
desired_length
);
void
render
(
c
har
*
data
,
size_t
len
);
void
render
(
c
onst
std
::
vector
<
unsigned
char
>
&
data
);
private:
NON_COPYABLE
(
SHMSink
);
...
...
daemon/src/video/test/README
0 → 100644
View file @
9979f93a
c++ shm_src.cpp shmclient.cpp -o shmclient `pkg-config --cflags --libs clutter-1.0` -lrt -pthread -O2
daemon/src/video/test/shm_src.cpp
View file @
9979f93a
...
...
@@ -34,7 +34,7 @@
*/
#include
"shm_src.h"
#include
"shm_header.h"
#include
"
../
shm_header.h"
#include
<sys/mman.h>
#include
<fcntl.h>
#include
<cstdio>
...
...
daemon/src/video/test/shm_src.h
View file @
9979f93a
...
...
@@ -37,7 +37,7 @@
#define SHM_SRC_H_
#include
<string>
#include
"noncopyable.h"
#include
"
../../
noncopyable.h"
class
SHMHeader
;
// Example Shared memory source, only useful for testing
...
...
@@ -46,17 +46,16 @@ class SHMHeader;
class
SHMSrc
{
public:
SHMSrc
(
const
std
::
string
&
shm_name
);
virtual
~
SHMSrc
()
{};
bool
start
();
bool
stop
();
bool
resize_area
();
void
render
(
char
*
data
,
size_t
len
);
private:
NON_COPYABLE
(
SHMSrc
);
virtual
void
render
(
char
*
data
,
size_t
len
);
protected:
void
shm_lock
();
void
shm_unlock
();
std
::
string
shm_name_
;
...
...
@@ -64,6 +63,9 @@ class SHMSrc {
SHMHeader
*
shm_area_
;
size_t
shm_area_len_
;
unsigned
buffer_gen_
;
private:
NON_COPYABLE
(
SHMSrc
);
};
#endif // SHM_SRC_H_
daemon/src/video/test/shmclient.c
deleted
100644 → 0
View file @
48f7af81
#include
<stdio.h>
#include
<stdlib.h>
#include
<sys/types.h>
#include
<sys/ipc.h>
#include
<sys/sem.h>
/* semaphore functions and structs. */
#include
<sys/shm.h>
#include
<clutter/clutter.h>
#define TEMPFILE "/tmp/frame.txt"
#if _SEM_SEMUN_UNDEFINED
union
semun
{
int
val
;
/* value for SETVAL */
struct
semid_ds
*
buf
;
/* buffer for IPC_STAT & IPC_SET */
unsigned
short
int
*
array
;
/* array for GETALL & SETALL */
struct
seminfo
*
__buf
;
/* buffer for IPC_INFO */
};
#endif
typedef
struct
{
unsigned
size
;
unsigned
width
;
unsigned
height
;
}
FrameInfo
;
struct
AppData
{
unsigned
width
;
unsigned
height
;
char
*
shm_buffer
;
int
sem_set_id
;
ClutterActor
*
texture
;
};
FrameInfo
getFrameSize
()
{
FrameInfo
info
;
/* get message out of the file */
FILE
*
tmp
=
fopen
(
TEMPFILE
,
"r"
);
fscanf
(
tmp
,
"%u
\n
%u
\n
%u
\n
"
,
&
info
.
size
,
&
info
.
width
,
&
info
.
height
);
printf
(
"Size is %u
\n
"
,
info
.
size
);
printf
(
"Width is %u
\n
"
,
info
.
width
);
printf
(
"Height is %u
\n
"
,
info
.
height
);
fclose
(
tmp
);
return
info
;
}
int
get_sem_set
()
{
/* this variable will contain the semaphore set. */
int
sem_set_id
;
key_t
key
=
ftok
(
"/tmp"
,
'b'
);
/* semaphore value, for semctl(). */
union
semun
sem_val
;
/* first we get a semaphore set with a single semaphore, */
/* whose counter is initialized to '0'. */
sem_set_id
=
semget
(
key
,
1
,
0600
);
if
(
sem_set_id
==
-
1
)
{
perror
(
"semget"
);
exit
(
1
);
}
sem_val
.
val
=
0
;
semctl
(
sem_set_id
,
0
,
SETVAL
,
sem_val
);
return
sem_set_id
;
}
/*
* function: sem_wait. wait for frame from other process
* input: semaphore set ID.
* output: none.
*/
void
sem_wait
(
int
sem_set_id
)
{
/* structure for semaphore operations. */
struct
sembuf
sem_op
;
/* wait on the semaphore, unless it's value is non-negative. */
sem_op
.
sem_num
=
0
;
sem_op
.
sem_op
=
-
1
;
sem_op
.
sem_flg
=
0
;
semop
(
sem_set_id
,
&
sem_op
,
1
);
}
/* join and/or create a shared memory segment */
int
getShm
(
unsigned
numBytes
)
{
key_t
key
;
int
shm_id
;
/* connect to a segment with 600 permissions
(r--r--r--) */
key
=
ftok
(
"/tmp"
,
'c'
);
shm_id
=
shmget
(
key
,
numBytes
,
0644
);
return
shm_id
;
}
/* attach a shared memory segment */
char
*
attachShm
(
int
shm_id
)
{
char
*
data
=
NULL
;
/* attach to the segment and get a pointer to it */
data
=
shmat
(
shm_id
,
(
void
*
)
0
,
0
);
if
(
data
==
(
char
*
)(
-
1
))
{
perror
(
"shmat"
);
data
=
NULL
;
}
return
data
;
}
void
detachShm
(
char
*
data
)
{
/* detach from the segment: */
if
(
shmdt
(
data
)
==
-
1
)
{
perror
(
"shmdt"
);
}
}
/* round integer value up to next multiple of 4 */
int
round_up_4
(
int
value
)
{
return
(
value
+
3
)
&~
3
;
}
void
readFrameFromShm
(
int
width
,
int
height
,
char
*
data
,
int
sem_set_id
,
ClutterActor
*
texture
)
{
sem_wait
(
sem_set_id
);
clutter_texture_set_from_rgb_data
(
CLUTTER_TEXTURE
(
texture
),
(
void
*
)
data
,
FALSE
,
width
,
height
,
round_up_4
(
3
*
width
),
3
,
0
,
NULL
);
}
gboolean
updateTexture
(
gpointer
data
)
{
struct
AppData
*
app
=
(
struct
AppData
*
)
data
;
readFrameFromShm
(
app
->
width
,
app
->
height
,
app
->
shm_buffer
,
app
->
sem_set_id
,
app
->
texture
);
return
TRUE
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
/* Initialize Clutter */
if
(
clutter_init
(
&
argc
,
&
argv
)
!=
CLUTTER_INIT_SUCCESS
)
return
1
;