241 lines
7.2 KiB
C
241 lines
7.2 KiB
C
/*
|
|
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.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 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
|
|
*/
|
|
#include <pjmedia-videodev/videodev_imp.h>
|
|
#include <pj/assert.h>
|
|
|
|
|
|
#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
|
|
|
|
|
|
#define THIS_FILE "videodev.c"
|
|
|
|
|
|
/* extern functions to create factories */
|
|
#if PJMEDIA_VIDEO_DEV_HAS_DSHOW
|
|
pjmedia_vid_dev_factory* pjmedia_dshow_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_CBAR_SRC
|
|
pjmedia_vid_dev_factory* pjmedia_cbar_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_METAL
|
|
pjmedia_vid_dev_factory* pjmedia_metal_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_SDL
|
|
pjmedia_vid_dev_factory* pjmedia_sdl_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_FFMPEG
|
|
pjmedia_vid_dev_factory* pjmedia_ffmpeg_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_V4L2
|
|
pjmedia_vid_dev_factory* pjmedia_v4l2_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_QT
|
|
pjmedia_vid_dev_factory* pjmedia_qt_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_DARWIN
|
|
pjmedia_vid_dev_factory* pjmedia_darwin_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_OPENGL
|
|
pjmedia_vid_dev_factory* pjmedia_opengl_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#if PJMEDIA_VIDEO_DEV_HAS_ANDROID
|
|
pjmedia_vid_dev_factory* pjmedia_and_factory(pj_pool_factory *pf);
|
|
#endif
|
|
|
|
#define MAX_DRIVERS PJMEDIA_VID_DEV_MAX_DRIVERS
|
|
#define MAX_DEVS PJMEDIA_VID_DEV_MAX_DEVS
|
|
|
|
|
|
/* API: Initialize the video device subsystem. */
|
|
PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_init(pj_pool_factory *pf)
|
|
{
|
|
unsigned i;
|
|
pj_status_t status = PJ_SUCCESS;
|
|
pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
|
|
|
|
/* Allow init() to be called multiple times as long as there is matching
|
|
* number of shutdown().
|
|
*/
|
|
if (vid_subsys->init_count++ != 0) {
|
|
return PJ_SUCCESS;
|
|
}
|
|
|
|
/* Register error subsystem */
|
|
pj_register_strerror(PJMEDIA_VIDEODEV_ERRNO_START,
|
|
PJ_ERRNO_SPACE_SIZE,
|
|
&pjmedia_videodev_strerror);
|
|
|
|
/* Init */
|
|
vid_subsys->pf = pf;
|
|
vid_subsys->drv_cnt = 0;
|
|
vid_subsys->dev_cnt = 0;
|
|
|
|
/* Register creation functions */
|
|
#if PJMEDIA_VIDEO_DEV_HAS_V4L2
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_v4l2_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_QT
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_qt_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_METAL
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_metal_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_OPENGL
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_opengl_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_DARWIN
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_darwin_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_DSHOW
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_dshow_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_FFMPEG
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_ffmpeg_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_SDL
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_sdl_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_ANDROID
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_and_factory;
|
|
#endif
|
|
#if PJMEDIA_VIDEO_DEV_HAS_CBAR_SRC
|
|
/* Better put colorbar at the last, so the default capturer will be
|
|
* a real capturer, if any.
|
|
*/
|
|
vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_cbar_factory;
|
|
#endif
|
|
|
|
/* Initialize each factory and build the device ID list */
|
|
for (i=0; i<vid_subsys->drv_cnt; ++i) {
|
|
status = pjmedia_vid_driver_init(i, PJ_FALSE);
|
|
if (status != PJ_SUCCESS) {
|
|
pjmedia_vid_driver_deinit(i);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return vid_subsys->dev_cnt ? PJ_SUCCESS : status;
|
|
}
|
|
|
|
/* API: register a video device factory to the video device subsystem. */
|
|
PJ_DEF(pj_status_t)
|
|
pjmedia_vid_register_factory(pjmedia_vid_dev_factory_create_func_ptr adf,
|
|
pjmedia_vid_dev_factory *factory)
|
|
{
|
|
pj_bool_t refresh = PJ_FALSE;
|
|
pj_status_t status;
|
|
pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
|
|
|
|
if (vid_subsys->init_count == 0)
|
|
return PJMEDIA_EVID_INIT;
|
|
|
|
vid_subsys->drv[vid_subsys->drv_cnt].create = adf;
|
|
vid_subsys->drv[vid_subsys->drv_cnt].f = factory;
|
|
|
|
if (factory) {
|
|
/* Call factory->init() */
|
|
status = factory->op->init(factory);
|
|
if (status != PJ_SUCCESS) {
|
|
factory->op->destroy(factory);
|
|
return status;
|
|
}
|
|
refresh = PJ_TRUE;
|
|
}
|
|
|
|
status = pjmedia_vid_driver_init(vid_subsys->drv_cnt, refresh);
|
|
if (status == PJ_SUCCESS) {
|
|
vid_subsys->drv_cnt++;
|
|
} else {
|
|
pjmedia_vid_driver_deinit(vid_subsys->drv_cnt);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/* API: unregister a video device factory from the video device subsystem. */
|
|
PJ_DEF(pj_status_t)
|
|
pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr adf,
|
|
pjmedia_vid_dev_factory *factory)
|
|
{
|
|
unsigned i, j;
|
|
pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
|
|
|
|
if (vid_subsys->init_count == 0)
|
|
return PJMEDIA_EVID_INIT;
|
|
|
|
for (i=0; i<vid_subsys->drv_cnt; ++i) {
|
|
pjmedia_vid_driver *drv = &vid_subsys->drv[i];
|
|
|
|
if ((factory && drv->f==factory) || (adf && drv->create == adf)) {
|
|
for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++)
|
|
{
|
|
vid_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV;
|
|
}
|
|
|
|
pjmedia_vid_driver_deinit(i);
|
|
pj_bzero(drv, sizeof(*drv));
|
|
return PJ_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return PJMEDIA_EVID_ERR;
|
|
}
|
|
|
|
/* API: get the pool factory registered to the video device subsystem. */
|
|
PJ_DEF(pj_pool_factory*) pjmedia_vid_dev_subsys_get_pool_factory(void)
|
|
{
|
|
pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
|
|
return vid_subsys->pf;
|
|
}
|
|
|
|
/* API: Shutdown the video device subsystem. */
|
|
PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_shutdown(void)
|
|
{
|
|
unsigned i;
|
|
pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys();
|
|
|
|
/* Allow shutdown() to be called multiple times as long as there is
|
|
* matching number of init().
|
|
*/
|
|
if (vid_subsys->init_count == 0) {
|
|
return PJ_SUCCESS;
|
|
}
|
|
--vid_subsys->init_count;
|
|
|
|
if (vid_subsys->init_count == 0) {
|
|
for (i=0; i<vid_subsys->drv_cnt; ++i) {
|
|
pjmedia_vid_driver_deinit(i);
|
|
}
|
|
|
|
pj_bzero(vid_subsys, sizeof(pjmedia_vid_subsys));
|
|
}
|
|
return PJ_SUCCESS;
|
|
}
|
|
|
|
|
|
#endif /* PJMEDIA_HAS_VIDEO */
|