Commit 998cdbcc authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

Merge branch 'dev_bb10'

Conflicts:
	CMakeLists.txt
	src/CMakeLists.txt
parents f85d7f60 dec5261a
......@@ -94,7 +94,7 @@ cmake_dependent_option(ENABLE_XV "Enable XV support." ${ENABLE_X11_DEFAULT_VALUE
cmake_dependent_option(ENABLE_THEORA "Enable theora video codec support." YES "ENABLE_VIDEO" NO)
cmake_dependent_option(ENABLE_VPX "Build mediastreamer2 with VPX codec." YES "ENABLE_VIDEO" NO)
option(ENABLE_MKV "Enable support of MKV files reading and writing." YES)
cmake_dependent_option(ENABLE_QNX "Build medistreamer2 with BB10 filters." NO "ENABLE_VIDEO" NO)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
......@@ -252,6 +252,7 @@ if(ENABLE_VPX)
set(ENABLE_VPX OFF CACHE BOOL "Build mediastreamer2 with VPX codec." FORCE)
endif()
endif()
<<<<<<< HEAD
if(ENABLE_MKV)
find_package(Matroska2)
if(NOT MATROSKA2_FOUND)
......@@ -259,6 +260,18 @@ if(ENABLE_MKV)
endif()
endif()
=======
if (ENABLE_QNX)
find_package(Screen)
if(NOT SCREEN_FOUND)
message(FATAL_ERROR "SCREEN NOT FOUND")
endif()
find_package(CamApi)
if(NOT CAMAPI_FOUND)
message(FATAL_ERROR "CAMAPI NOT FOUND")
endif()
endif()
>>>>>>> dev_bb10
if(ENABLE_SOUND AND NOT(WIN32 OR ENABLE_ALSA OR ENABLE_ARTSC OR ENABLE_MACSND OR ENABLE_MACAQSND OR ENABLE_OSS OR ENABLE_PORTAUDIO OR ENABLE_PULSEAUDIO OR ENABLE_QSA))
message(FATAL_ERROR "Could not find a support sound driver API. Use -DENABLE_SOUND=NO if you don't care about having sound.")
......@@ -335,7 +348,12 @@ endif()
if(MSVC)
include_directories(${MSVC_INCLUDE_DIR})
endif()
if (SCREEN_FOUND)
include_directories(${SCREEN_INCLUDE_DIRS})
endif()
if (CAMAPI_FOUND)
include_directories(${CAMAPI_INCLUDE_DIRS})
endif()
if(ENABLE_DEBUG_LOGS)
add_definitions(-DDEBUG)
......@@ -381,6 +399,9 @@ endif()
if(ENABLE_QSA)
set(__QSA_ENABLED__ 1)
endif()
if(ENABLE_QNX)
set(__QNX__ 1)
endif()
if(SPEEX_FOUND)
set(HAVE_SPEEXDSP 1)
endif()
......
############################################################################
# FindQSA.txt
# Copyright (C) 2014 Belledonne Communications, Grenoble France
#
############################################################################
#
# 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 2
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
############################################################################
#
# - Find the libcamapi include file and library
#
# CAMAPI_FOUND - system has libcamapi
# CAMAPI_INCLUDE_DIRS - the libcamapi include directory
# CAMAPI_LIBRARIES - The libraries needed to use libcamapi
include(CheckSymbolExists)
include(CMakePushCheckState)
set(_CAMAPI_ROOT_PATHS
${CMAKE_INSTALL_PREFIX}
)
find_path(CAMAPI_INCLUDE_DIRS
NAMES camera/camera_api.h
HINTS _CAMAPI_ROOT_PATHS
PATH_SUFFIXES include
)
find_library(CAMAPI_LIBRARIES
NAMES camapi
HINTS _CAMAPI_ROOT_PATHS
PATH_SUFFIXES lib
)
if(CAMAPI_LIBRARIES)
list(APPEND CMAKE_REQUIRED_INCLUDES ${CAMAPI_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CAMAPI_LIBRARIES})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CAMAPI
DEFAULT_MSG
CAMAPI_INCLUDE_DIRS CAMAPI_LIBRARIES
)
mark_as_advanced(CAMAPI_INCLUDE_DIRS CAMAPI_LIBRARIES)
############################################################################
# FindQSA.txt
# Copyright (C) 2014 Belledonne Communications, Grenoble France
#
############################################################################
#
# 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 2
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
############################################################################
#
# - Find the libscreen include file and library
#
# SCREEN_FOUND - system has libscreen
# SCREEN_INCLUDE_DIRS - the libscreen include directory
# SCREEN_LIBRARIES - The libraries needed to use libscreen
include(CheckSymbolExists)
include(CMakePushCheckState)
set(_SCREEN_ROOT_PATHS
${CMAKE_INSTALL_PREFIX}
)
find_path(SCREEN_INCLUDE_DIRS
NAMES screen/screen.h
HINTS _SCREEN_ROOT_PATHS
PATH_SUFFIXES include
)
find_library(SCREEN_LIBRARIES
NAMES screen
HINTS _SCREEN_ROOT_PATHS
PATH_SUFFIXES lib
)
if(SCREEN_LIBRARIES)
list(APPEND CMAKE_REQUIRED_INCLUDES ${SCREEN_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${SCREEN_LIBRARIES})
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SCREEN
DEFAULT_MSG
SCREEN_INCLUDE_DIRS SCREEN_LIBRARIES
)
mark_as_advanced(SCREEN_INCLUDE_DIRS SCREEN_LIBRARIES)
......@@ -144,7 +144,9 @@ typedef enum MSFilterId{
MS_QSA_WRITE_ID,
MS_MKV_RECORDER_ID,
MS_MKV_PLAYER_ID,
MS_VAD_DTX_ID
MS_VAD_DTX_ID,
MS_BB10_DISPLAY_ID,
MS_BB10_CAPTURE_ID
} MSFilterId;
......
......@@ -256,6 +256,14 @@ if(ENABLE_VIDEO)
)
endif()
endif()
if (ENABLE_QNX)
list (APPEND VOIP_SOURCE_FILES
videofilters/bb10_display.cpp
videofilters/bb10_capture.cpp
)
set_source_files_properties(videofilters/bb10_display.cpp PROPERTIES LANGUAGE CXX)
set_source_files_properties(videofilters/bb10_capture.cpp PROPERTIES LANGUAGE CXX)
endif()
if(FFMPEG_FOUND)
list(APPEND VOIP_SOURCE_FILES
utils/ffmpeg-priv.c
......@@ -418,6 +426,11 @@ if(VPX_FOUND)
endif()
if(MATROSKA2_FOUND)
list(APPEND VOIP_LIBS ${MATROSKA2_LIBRARIES})
if (SCREEN_FOUND)
list(APPEND VOIP_LIBS ${SCREEN_LIBRARIES})
endif()
if (CAMAPI_FOUND)
list(APPEND VOIP_LIBS ${CAMAPI_LIBRARIES})
endif()
if(ENABLE_STATIC)
......
......@@ -457,8 +457,12 @@ static void ms_qsa_write_process(MSFilter *f) {
memset(&params, 0, sizeof(params));
params.channel = SND_PCM_CHANNEL_PLAYBACK;
params.mode = SND_PCM_MODE_BLOCK;
params.start_mode = SND_PCM_START_FULL;
params.stop_mode = SND_PCM_STOP_STOP;
if (strcmp(d->pcmdev, "voice") == 0) {
params.start_mode = SND_PCM_START_FULL;
} else {
params.start_mode = SND_PCM_START_DATA;
}
params.stop_mode = SND_PCM_STOP_STOP;
params.buf.block.frag_size = pi.max_fragment_size;
params.buf.block.frags_min = 1;
params.buf.block.frags_max = -1;
......@@ -496,6 +500,7 @@ static void ms_qsa_write_process(MSFilter *f) {
goto setup_failure;
}
ms_message("PCM playback device %s", d->pcmdev);
ms_message("Format %s", snd_pcm_get_format_name(setup.format.format));
ms_message("Frag Size %d", setup.buf.block.frag_size);
ms_message("Total Frags %d", setup.buf.block.frags);
......@@ -521,25 +526,26 @@ static void ms_qsa_write_process(MSFilter *f) {
}
if (FD_ISSET(d->fd, &fdset) > 0) {
if (ms_bufferizer_get_avail(d->bufferizer) >= d->buffer_size) {
ms_bufferizer_read(d->bufferizer, d->buffer, d->buffer_size);
written = snd_pcm_plugin_write(d->handle, d->buffer, d->buffer_size);
if (written < d->buffer_size) {
ms_warning("%s: snd_pcm_plugin_write(%d) failed: %d", __FUNCTION__, d->buffer_size, errno);
memset(&status, 0, sizeof(status));
status.channel = SND_PCM_CHANNEL_PLAYBACK;
err = snd_pcm_plugin_status(d->handle, &status);
memset(&status, 0, sizeof(status));
status.channel = SND_PCM_CHANNEL_PLAYBACK;
err = snd_pcm_plugin_status(d->handle, &status);
if (err != 0) {
ms_error("%s: snd_pcm_plugin_status() failed: %s", __FUNCTION__, snd_strerror(err));
goto setup_failure;
}
if ((status.status == SND_PCM_STATUS_PREPARED) || (status.status == SND_PCM_STATUS_RUNNING)) {
ms_bufferizer_read(d->bufferizer, d->buffer, d->buffer_size);
written = snd_pcm_plugin_write(d->handle, d->buffer, d->buffer_size);
if (written < d->buffer_size) {
ms_warning("%s: snd_pcm_plugin_write(%d) failed: %s", __FUNCTION__, d->buffer_size, strerror(errno));
if (written < 0) written = 0;
}
} else if ((status.status == SND_PCM_STATUS_READY) || (status.status == SND_PCM_STATUS_UNDERRUN)) {
err = snd_pcm_plugin_prepare(d->handle, SND_PCM_CHANNEL_PLAYBACK);
if (err != 0) {
ms_error("%s: snd_pcm_plugin_status() failed: %s", __FUNCTION__, snd_strerror(err));
ms_error("%s: snd_pcm_plugin_prepare() failed: %s", __FUNCTION__, snd_strerror(err));
goto setup_failure;
}
if ((status.status == SND_PCM_STATUS_READY) || (status.status == SND_PCM_STATUS_UNDERRUN)) {
err = snd_pcm_plugin_prepare(d->handle, SND_PCM_CHANNEL_PLAYBACK);
if (err != 0) {
ms_error("%s: snd_pcm_plugin_prepare() failed: %s", __FUNCTION__, snd_strerror(err));
goto setup_failure;
}
}
if (written < 0) written = 0;
}
}
}
......@@ -590,7 +596,6 @@ static void ms_qsa_write_uninit(MSFilter *f) {
ms_free(d);
}
/******************************************************************************
* Methods to configure the QSA playback filter *
*****************************************************************************/
......@@ -617,9 +622,8 @@ static int ms_qsa_write_set_nchannels(MSFilter *f, void *arg) {
int nchannels = *((int *)arg);
if ((nchannels >= d->info.min_voices) && (nchannels <= d->info.max_voices)) {
d->nchannels = nchannels;
return 0;
}
return -1;
return 0; // Return 0 even if set didn't work to force the app to call the getter to have the correct value
}
static int ms_qsa_write_get_nchannels(MSFilter *f, void *arg) {
......
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/msvideo.h"
#include "mediastreamer2/mswebcam.h"
#include "mediastreamer2/msticker.h"
#include <camera/camera_api.h>
static const char *error_to_string(camera_error_t error) {
switch (error) {
case CAMERA_EOK:
return "CAMERA_EOK";
case CAMERA_EINVAL:
return "CAMERA_EINVAL";
case CAMERA_ENODEV:
return "CAMERA_ENODEV";
case CAMERA_EMFILE:
return "CAMERA_EMFILE";
case CAMERA_EBADF:
return "CAMERA_EBADF";
case CAMERA_EACCESS:
return "CAMERA_EACCESS";
case CAMERA_EBADR:
return "CAMERA_EBADR";
case CAMERA_ENODATA:
return "CAMERA_ENODATA";
case CAMERA_ENOENT:
return "CAMERA_ENOENT";
case CAMERA_ENOMEM:
return "CAMERA_ENOMEM";
case CAMERA_EOPNOTSUPP:
return "CAMERA_EOPNOTSUPP";
case CAMERA_ETIMEDOUT:
return "CAMERA_ETIMEDOUT";
case CAMERA_EALREADY:
return "CAMERA_EALREADY";
case CAMERA_EBUSY:
return "CAMERA_EBUSY";
case CAMERA_ENOSPC:
return "CAMERA_ENOSPC";
case CAMERA_EUNINIT:
return "CAMERA_EUNINIT";
case CAMERA_EREGFAULT:
return "CAMERA_EREGFAULT";
case CAMERA_EMICINUSE:
return "CAMERA_EMICINUSE";
case CAMERA_EDESKTOPCAMERAINUSE:
return "CAMERA_EDESKTOPCAMERAINUSE";
case CAMERA_EPOWERDOWN:
return "CAMERA_EPOWERDOWN";
case CAMERA_3ALOCKED:
return "CAMERA_3ALOCKED";
case CAMERA_EVIEWFINDERFROZEN:
return "CAMERA_EVIEWFINDERFROZEN";
case CAMERA_EOVERFLOW:
return "CAMERA_EOVERFLOW";
case CAMERA_ETHERMALSHUTDOWN:
return "CAMERA_ETHERMALSHUTDOWN";
default:
return "UNKNOWN";
}
return "UNKNOWN";
}
static const char *vfmode_to_string(camera_vfmode_t mode) {
switch (mode) {
case CAMERA_VFMODE_DEFAULT:
return "CAMERA_VFMODE_DEFAULT";
case CAMERA_VFMODE_PHOTO:
return "CAMERA_VFMODE_PHOTO";
case CAMERA_VFMODE_CONTINUOUS_BURST:
return "CAMERA_VFMODE_CONTINUOUS_BURST";
case CAMERA_VFMODE_FIXED_BURST:
return "CAMERA_VFMODE_FIXED_BURST";
case CAMERA_VFMODE_EV_BRACKETING:
return "CAMERA_VFMODE_EV_BRACKETING";
case CAMERA_VFMODE_VIDEO:
return "CAMERA_VFMODE_VIDEO";
case CAMERA_VFMODE_VIDEO_SNAPSHOT:
return "CAMERA_VFMODE_VIDEO_SNAPSHOT";
case CAMERA_VFMODE_HIGH_SPEED_VIDEO:
return "CAMERA_VFMODE_HIGH_SPEED_VIDEO";
case CAMERA_VFMODE_HDR_VIDEO:
return "CAMERA_VFMODE_HDR_VIDEO";
case CAMERA_VFMODE_NUM_MODES:
return "CAMERA_VFMODE_NUM_MODES";
default:
return "UNKNOWN";
}
return "UNKNOWN";
}
typedef struct BB10Capture {
MSVideoSize vsize;
float framerate;
MSQueue rq;
ms_mutex_t mutex;
camera_unit_t camera;
camera_handle_t cam_handle;
char *window_group;
char *window_id;
bool_t camera_openned;
bool_t capture_started;
MSAverageFPS avgfps;
} BB10Capture;
static void bb10capture_video_callback(camera_handle_t cam_handle, camera_buffer_t *buffer, void *arg) {
BB10Capture *d = (BB10Capture *)arg;
mblk_t *om = NULL;
MSYuvBufAllocator *yba = ms_yuv_buf_allocator_new();
if (buffer->frametype == CAMERA_FRAMETYPE_NV12) {
om = copy_ycbcrbiplanar_to_true_yuv_with_rotation(yba,
buffer->framebuf,
buffer->framebuf + buffer->framedesc.nv12.uv_offset,
0,
buffer->framedesc.nv12.width,
buffer->framedesc.nv12.height,
buffer->framedesc.nv12.stride,
buffer->framedesc.nv12.uv_stride,
TRUE);
}
if (om != NULL) {
ms_mutex_lock(&d->mutex);
ms_queue_put(&d->rq, om);
ms_mutex_unlock(&d->mutex);
}
ms_yuv_buf_allocator_free(yba);
}
static void bb10capture_open_camera(BB10Capture *d) {
camera_error_t error;
if (d->camera_openned) {
ms_warning("[bb10_capture] camera already openned, skipping...");
return;
}
ms_message("[bb10_capture] openning %s camera", d->camera == CAMERA_UNIT_FRONT ? "front" : (d->camera == CAMERA_UNIT_REAR ? "rear" : "unknown"));
error = camera_open(d->camera, CAMERA_MODE_RW, &(d->cam_handle));
if (error == CAMERA_EOK) {
d->camera_openned = TRUE;
} else {
ms_error("[bb10_capture] openning %i camera failed: %s", d->camera, error_to_string(error));
}
}
static void bb10capture_start_capture(BB10Capture *d) {
if (!d->camera_openned) {
ms_error("[bb10_capture] camera not openned, skipping...");
return;
}
if (d->capture_started) {
ms_warning("[bb10_capture] capture already started, skipping...");
return;
}
camera_set_vf_mode(d->cam_handle, CAMERA_VFMODE_VIDEO);
camera_set_vf_property(d->cam_handle, CAMERA_IMGPROP_WIDTH, d->vsize.width, CAMERA_IMGPROP_HEIGHT, d->vsize.height);
camera_set_vf_property(d->cam_handle, CAMERA_IMGPROP_FORMAT, CAMERA_FRAMETYPE_NV12);
if (d->framerate > 0) {
camera_set_vf_property(d->cam_handle, CAMERA_IMGPROP_VARIABLEFRAMERATE, 1);
camera_set_vf_property(d->cam_handle, CAMERA_IMGPROP_MINFRAMERATE, (double)d->framerate, CAMERA_IMGPROP_FRAMERATE, (double)d->framerate);
}
camera_start_viewfinder(d->cam_handle, bb10capture_video_callback, NULL, d);
d->capture_started = TRUE;
}
static void bb10capture_stop_capture(BB10Capture *d) {
if (!d->capture_started) {
ms_warning("[bb10_capture] capture not started, skipping...");
return;
}
camera_stop_viewfinder(d->cam_handle);
d->capture_started = FALSE;
}
static void bb10capture_close_camera(BB10Capture *d) {
if (!d->camera_openned) {
ms_warning("[bb10_capture] camera not openned, skipping...");
return;
}
camera_close(d->cam_handle);
d->camera_openned = FALSE;
}
static void bb10capture_init(MSFilter *f) {
BB10Capture *d = (BB10Capture*) ms_new0(BB10Capture, 1);
MSVideoSize def_size;
camera_error_t error;
d->camera_openned = FALSE;
d->capture_started = FALSE;
def_size.width = MS_VIDEO_SIZE_QVGA_W;
def_size.height = MS_VIDEO_SIZE_QVGA_H;
d->framerate = 15.0;
d->vsize = def_size;
d->camera = CAMERA_UNIT_NONE;
ms_queue_init(&d->rq);
f->data = d;
}
static void bb10capture_uninit(MSFilter *f) {
BB10Capture *d = (BB10Capture*) f->data;
ms_mutex_destroy(&d->mutex);
ms_free(d);
}
static void bb10capture_preprocess(MSFilter *f) {
BB10Capture *d = (BB10Capture*) f->data;
bb10capture_open_camera(d);
ms_average_fps_init(&d->avgfps, "[bb10_capture] fps=%f");
bb10capture_start_capture(d);
}
static void bb10capture_postprocess(MSFilter *f) {
BB10Capture *d = (BB10Capture*) f->data;
bb10capture_stop_capture(d);
bb10capture_close_camera(d);
}
static void bb10capture_process(MSFilter *f) {
BB10Capture *d = (BB10Capture*) f->data;
mblk_t *om = NULL;
mblk_t *tmp = NULL;
uint32_t timestamp = 0;
ms_filter_lock(f);
ms_mutex_lock(&d->mutex);
while ((tmp = ms_queue_get(&d->rq)) != NULL) {
if (om != NULL) freemsg(om);
om = tmp;
}
ms_mutex_unlock(&d->mutex);
if (om != NULL) {
timestamp = f->ticker->time * 90;/* rtp uses a 90000 Hz clockrate for video*/
mblk_set_timestamp_info(om, timestamp);
ms_queue_put(f->outputs[0], om);
ms_average_fps_update(&d->avgfps, f->ticker->time);
}
ms_filter_unlock(f);
}
static int bb10capture_set_vsize(MSFilter *f, void *arg) {
BB10Capture *d = (BB10Capture*) f->data;
ms_filter_lock(f);
d->vsize = *(MSVideoSize*)arg;
if (d->capture_started) {
bb10capture_stop_capture(d);
}
bb10capture_start_capture(d);
ms_filter_unlock(f);
return 0;
}
static int bb10capture_set_fps(MSFilter *f, void *arg){
BB10Capture *d = (BB10Capture*) f->data;
ms_filter_lock(f);
d->framerate = *(float*)arg;
if (d->capture_started) {
bb10capture_stop_capture(d);
}
bb10capture_start_capture(d);
ms_filter_unlock(f);
return 0;
}
static int bb10capture_get_vsize(MSFilter *f, void *arg) {
BB10Capture *d = (BB10Capture*) f->data;
*(MSVideoSize*)arg = d->vsize;
return 0;
}
static int bb10capture_get_fps(MSFilter *f, void *arg){
BB10Capture *d = (BB10Capture*) f->data;
if (f->ticker){
*(float*)arg=ms_average_fps_get(&d->avgfps);
}else {
*(float*)arg = d->framerate;
}
return 0;
}
static int bb10capture_get_pixfmt(MSFilter *f, void *arg) {
BB10Capture *d = (BB10Capture*) f->data;
MSPixFmt pix_fmt = MS_YUV420P;
*(MSPixFmt*)arg = pix_fmt;
return 0;
}
static MSFilterMethod ms_bb10capture_methods[] = {
{ MS_FILTER_SET_VIDEO_SIZE, bb10capture_set_vsize },
{ MS_FILTER_SET_FPS, bb10capture_set_fps },
{ MS_FILTER_GET_VIDEO_SIZE, bb10capture_get_vsize },
{ MS_FILTER_GET_FPS, bb10capture_get_fps },
{ MS_FILTER_GET_PIX_FMT, bb10capture_get_pixfmt },
{ 0, NULL }
};
MSFilterDesc ms_bb10_capture_desc = {