Re #1312: Support for refreshing video device list
Add pjmedia-videodev API: pjmedia_vid_dev_refresh() and its implementation for Windows and Linux.
git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/2.0-dev@3592 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjmedia/src/pjmedia-videodev/colorbar_dev.c b/pjmedia/src/pjmedia-videodev/colorbar_dev.c
index 8c2e41e..7866e39 100644
--- a/pjmedia/src/pjmedia-videodev/colorbar_dev.c
+++ b/pjmedia/src/pjmedia-videodev/colorbar_dev.c
@@ -99,6 +99,7 @@
/* Prototypes */
static pj_status_t cbar_factory_init(pjmedia_vid_dev_factory *f);
static pj_status_t cbar_factory_destroy(pjmedia_vid_dev_factory *f);
+static pj_status_t cbar_factory_refresh(pjmedia_vid_dev_factory *f);
static unsigned cbar_factory_get_dev_count(pjmedia_vid_dev_factory *f);
static pj_status_t cbar_factory_get_dev_info(pjmedia_vid_dev_factory *f,
unsigned index,
@@ -136,7 +137,8 @@
&cbar_factory_get_dev_count,
&cbar_factory_get_dev_info,
&cbar_factory_default_param,
- &cbar_factory_create_stream
+ &cbar_factory_create_stream,
+ &cbar_factory_refresh
};
static pjmedia_vid_dev_stream_op stream_op =
@@ -228,6 +230,13 @@
return PJ_SUCCESS;
}
+/* API: refresh the list of devices */
+static pj_status_t cbar_factory_refresh(pjmedia_vid_dev_factory *f)
+{
+ PJ_UNUSED_ARG(f);
+ return PJ_SUCCESS;
+}
+
/* API: get number of devices */
static unsigned cbar_factory_get_dev_count(pjmedia_vid_dev_factory *f)
{
diff --git a/pjmedia/src/pjmedia-videodev/dshow_dev.c b/pjmedia/src/pjmedia-videodev/dshow_dev.c
index ff31b3f..5e316ff 100644
--- a/pjmedia/src/pjmedia-videodev/dshow_dev.c
+++ b/pjmedia/src/pjmedia-videodev/dshow_dev.c
@@ -82,6 +82,7 @@
{
pjmedia_vid_dev_factory base;
pj_pool_t *pool;
+ pj_pool_t *dev_pool;
pj_pool_factory *pf;
unsigned dev_count;
@@ -123,6 +124,7 @@
/* Prototypes */
static pj_status_t dshow_factory_init(pjmedia_vid_dev_factory *f);
static pj_status_t dshow_factory_destroy(pjmedia_vid_dev_factory *f);
+static pj_status_t dshow_factory_refresh(pjmedia_vid_dev_factory *f);
static unsigned dshow_factory_get_dev_count(pjmedia_vid_dev_factory *f);
static pj_status_t dshow_factory_get_dev_info(pjmedia_vid_dev_factory *f,
unsigned index,
@@ -160,7 +162,8 @@
&dshow_factory_get_dev_count,
&dshow_factory_get_dev_info,
&dshow_factory_default_param,
- &dshow_factory_create_stream
+ &dshow_factory_create_stream,
+ &dshow_factory_refresh
};
static pjmedia_vid_dev_stream_op stream_op =
@@ -199,6 +202,31 @@
/* API: init factory */
static pj_status_t dshow_factory_init(pjmedia_vid_dev_factory *f)
{
+ CoInitializeEx(NULL, COINIT_MULTITHREADED);
+
+ return dshow_factory_refresh(f);
+}
+
+/* API: destroy factory */
+static pj_status_t dshow_factory_destroy(pjmedia_vid_dev_factory *f)
+{
+ struct dshow_factory *df = (struct dshow_factory*)f;
+ pj_pool_t *pool = df->pool;
+
+ df->pool = NULL;
+ if (df->dev_pool)
+ pj_pool_release(df->dev_pool);
+ if (pool)
+ pj_pool_release(pool);
+
+ CoUninitialize();
+
+ return PJ_SUCCESS;
+}
+
+/* API: refresh the list of devices */
+static pj_status_t dshow_factory_refresh(pjmedia_vid_dev_factory *f)
+{
struct dshow_factory *df = (struct dshow_factory*)f;
struct dshow_dev_info *ddi;
int dev_count = 0;
@@ -209,9 +237,13 @@
HRESULT hr;
ULONG fetched;
- df->dev_count = 0;
+ if (df->dev_pool) {
+ pj_pool_release(df->dev_pool);
+ df->dev_pool = NULL;
+ }
- CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ df->dev_count = 0;
+ df->dev_pool = pj_pool_create(df->pf, "dshow video", 500, 500, NULL);
hr = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum,
@@ -233,7 +265,7 @@
/* Add renderer device */
dev_count += 1;
df->dev_info = (struct dshow_dev_info*)
- pj_pool_calloc(df->pool, dev_count,
+ pj_pool_calloc(df->dev_pool, dev_count,
sizeof(struct dshow_dev_info));
if (dev_count > 1) {
@@ -304,7 +336,7 @@
ddi = &df->dev_info[c];
ddi->info.fmt_cnt = sizeof(dshow_fmts)/sizeof(dshow_fmts[0]);
ddi->info.fmt = (pjmedia_format*)
- pj_pool_calloc(df->pool, ddi->info.fmt_cnt,
+ pj_pool_calloc(df->dev_pool, ddi->info.fmt_cnt,
sizeof(pjmedia_format));
for (i = 0; i < ddi->info.fmt_cnt; i++) {
@@ -321,7 +353,7 @@
// TODO:
// ddi->info.caps = PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW;
- PJ_LOG(4, (THIS_FILE, "DShow initialized, found %d devices:",
+ PJ_LOG(4, (THIS_FILE, "DShow has %d devices:",
df->dev_count));
for (c = 0; c < df->dev_count; ++c) {
PJ_LOG(4, (THIS_FILE, " dev_id %d: %s (%s)",
@@ -334,20 +366,6 @@
return PJ_SUCCESS;
}
-/* API: destroy factory */
-static pj_status_t dshow_factory_destroy(pjmedia_vid_dev_factory *f)
-{
- struct dshow_factory *df = (struct dshow_factory*)f;
- pj_pool_t *pool = df->pool;
-
- df->pool = NULL;
- pj_pool_release(pool);
-
- CoUninitialize();
-
- return PJ_SUCCESS;
-}
-
/* API: get number of devices */
static unsigned dshow_factory_get_dev_count(pjmedia_vid_dev_factory *f)
{
diff --git a/pjmedia/src/pjmedia-videodev/ffmpeg_dev.c b/pjmedia/src/pjmedia-videodev/ffmpeg_dev.c
index a2017da..2016548 100644
--- a/pjmedia/src/pjmedia-videodev/ffmpeg_dev.c
+++ b/pjmedia/src/pjmedia-videodev/ffmpeg_dev.c
@@ -60,6 +60,7 @@
pjmedia_vid_dev_factory base;
pj_pool_factory *pf;
pj_pool_t *pool;
+ pj_pool_t *dev_pool;
unsigned dev_count;
ffmpeg_dev_info dev_info[MAX_DEV_CNT];
} ffmpeg_factory;
@@ -78,6 +79,7 @@
/* Prototypes */
static pj_status_t ffmpeg_factory_init(pjmedia_vid_dev_factory *f);
static pj_status_t ffmpeg_factory_destroy(pjmedia_vid_dev_factory *f);
+static pj_status_t ffmpeg_factory_refresh(pjmedia_vid_dev_factory *f);
static unsigned ffmpeg_factory_get_dev_count(pjmedia_vid_dev_factory *f);
static pj_status_t ffmpeg_factory_get_dev_info(pjmedia_vid_dev_factory *f,
unsigned index,
@@ -115,7 +117,8 @@
&ffmpeg_factory_get_dev_count,
&ffmpeg_factory_get_dev_info,
&ffmpeg_factory_default_param,
- &ffmpeg_factory_create_stream
+ &ffmpeg_factory_create_stream,
+ &ffmpeg_factory_refresh
};
static pjmedia_vid_dev_stream_op stream_op =
@@ -219,6 +222,28 @@
/* API: init factory */
static pj_status_t ffmpeg_factory_init(pjmedia_vid_dev_factory *f)
{
+ return ffmpeg_factory_refresh(f);
+}
+
+/* API: destroy factory */
+static pj_status_t ffmpeg_factory_destroy(pjmedia_vid_dev_factory *f)
+{
+ ffmpeg_factory *ff = (ffmpeg_factory*)f;
+ pj_pool_t *pool = ff->pool;
+
+ ff->dev_count = 0;
+ ff->pool = NULL;
+ if (ff->dev_pool)
+ pj_pool_release(ff->dev_pool);
+ if (pool)
+ pj_pool_release(pool);
+
+ return PJ_SUCCESS;
+}
+
+/* API: refresh the list of devices */
+static pj_status_t ffmpeg_factory_refresh(pjmedia_vid_dev_factory *f)
+{
ffmpeg_factory *ff = (ffmpeg_factory*)f;
AVInputFormat *p;
ffmpeg_dev_info *info;
@@ -226,8 +251,15 @@
av_log_set_callback(&print_ffmpeg_log);
av_log_set_level(AV_LOG_DEBUG);
+ if (ff->dev_pool) {
+ pj_pool_release(ff->dev_pool);
+ ff->dev_pool = NULL;
+ }
+
/* TODO: this should enumerate devices, now it enumerates host APIs */
ff->dev_count = 0;
+ ff->dev_pool = pj_pool_create(ff->pf, "ffmpeg_cap_dev", 500, 500, NULL);
+
p = av_iformat_next(NULL);
while (p) {
if (p->flags & AVFMT_NOFILE) {
@@ -254,7 +286,7 @@
info->base.caps = PJMEDIA_VID_DEV_CAP_FORMAT;
info->base.fmt_cnt = 1;
info->base.fmt = (pjmedia_format*)
- pj_pool_calloc(ff->pool, info->base.fmt_cnt,
+ pj_pool_calloc(ff->dev_pool, info->base.fmt_cnt,
sizeof(pjmedia_format));
for (i = 0; i < info->base.fmt_cnt; ++i) {
pjmedia_format *fmt = &info->base.fmt[i];
@@ -270,16 +302,6 @@
return PJ_SUCCESS;
}
-/* API: destroy factory */
-static pj_status_t ffmpeg_factory_destroy(pjmedia_vid_dev_factory *f)
-{
- ffmpeg_factory *ff = (ffmpeg_factory*)f;
-
- ff->dev_count = 0;
-
- return PJ_SUCCESS;
-}
-
/* API: get number of devices */
static unsigned ffmpeg_factory_get_dev_count(pjmedia_vid_dev_factory *f)
{
diff --git a/pjmedia/src/pjmedia-videodev/sdl_dev.c b/pjmedia/src/pjmedia-videodev/sdl_dev.c
index 8c5720b..9a7e5fd 100644
--- a/pjmedia/src/pjmedia-videodev/sdl_dev.c
+++ b/pjmedia/src/pjmedia-videodev/sdl_dev.c
@@ -185,6 +185,7 @@
/* Prototypes */
static pj_status_t sdl_factory_init(pjmedia_vid_dev_factory *f);
static pj_status_t sdl_factory_destroy(pjmedia_vid_dev_factory *f);
+static pj_status_t sdl_factory_refresh(pjmedia_vid_dev_factory *f);
static unsigned sdl_factory_get_dev_count(pjmedia_vid_dev_factory *f);
static pj_status_t sdl_factory_get_dev_info(pjmedia_vid_dev_factory *f,
unsigned index,
@@ -226,7 +227,8 @@
&sdl_factory_get_dev_count,
&sdl_factory_get_dev_info,
&sdl_factory_default_param,
- &sdl_factory_create_stream
+ &sdl_factory_create_stream,
+ &sdl_factory_refresh
};
static pjmedia_vid_dev_stream_op stream_op =
@@ -356,6 +358,13 @@
return PJ_SUCCESS;
}
+/* API: refresh the list of devices */
+static pj_status_t sdl_factory_refresh(pjmedia_vid_dev_factory *f)
+{
+ PJ_UNUSED_ARG(f);
+ return PJ_SUCCESS;
+}
+
/* API: get number of devices */
static unsigned sdl_factory_get_dev_count(pjmedia_vid_dev_factory *f)
{
diff --git a/pjmedia/src/pjmedia-videodev/v4l2_dev.c b/pjmedia/src/pjmedia-videodev/v4l2_dev.c
index b5909c3..281560d 100644
--- a/pjmedia/src/pjmedia-videodev/v4l2_dev.c
+++ b/pjmedia/src/pjmedia-videodev/v4l2_dev.c
@@ -81,6 +81,7 @@
{
pjmedia_vid_dev_factory base;
pj_pool_t *pool;
+ pj_pool_t *dev_pool;
pj_pool_factory *pf;
unsigned dev_count;
@@ -119,6 +120,7 @@
/* Prototypes */
static pj_status_t vid4lin_factory_init(pjmedia_vid_dev_factory *f);
static pj_status_t vid4lin_factory_destroy(pjmedia_vid_dev_factory *f);
+static pj_status_t vid4lin_factory_refresh(pjmedia_vid_dev_factory *f);
static unsigned vid4lin_factory_get_dev_count(pjmedia_vid_dev_factory *f);
static pj_status_t vid4lin_factory_get_dev_info(pjmedia_vid_dev_factory *f,
unsigned index,
@@ -155,7 +157,8 @@
&vid4lin_factory_get_dev_count,
&vid4lin_factory_get_dev_info,
&vid4lin_factory_default_param,
- &vid4lin_factory_create_stream
+ &vid4lin_factory_create_stream,
+ &vid4lin_factory_refresh
};
static pjmedia_vid_dev_stream_op stream_op =
@@ -212,14 +215,20 @@
unsigned i, old_count;
pj_status_t status;
+ if (f->dev_pool) {
+ pj_pool_release(f->dev_pool);
+ f->dev_pool = NULL;
+ }
+
pj_bzero(vdi, sizeof(vdi));
old_count = f->dev_count;
f->dev_count = 0;
+ f->dev_pool = pj_pool_create(f->pf, DRIVER_NAME, 500, 500, NULL);
for (i=0; i<V4L2_MAX_DEVS && f->dev_count < V4L2_MAX_DEVS; ++i) {
int fd;
vid4lin_dev_info *pdi;
- pj_pool_t *pool = f->pool;
+ pj_pool_t *pool = f->dev_pool;
pj_uint32_t fmt_cap[8];
int j, fmt_cnt=0;
@@ -312,7 +321,7 @@
if (f->dev_count > old_count || f->dev_info == NULL) {
f->dev_info = (vid4lin_dev_info*)
- pj_pool_calloc(f->pool,
+ pj_pool_calloc(f->dev_pool,
f->dev_count,
sizeof(vid4lin_dev_info));
}
@@ -325,17 +334,7 @@
/* API: init factory */
static pj_status_t vid4lin_factory_init(pjmedia_vid_dev_factory *f)
{
- vid4lin_factory *cf = (vid4lin_factory*)f;
- pj_status_t status;
-
- status = v4l2_scan_devs(cf);
- if (status != PJ_SUCCESS)
- return status;
-
- PJ_LOG(4, (THIS_FILE, "Video4Linux2 initialized with %d devices",
- cf->dev_count));
-
- return PJ_SUCCESS;
+ return vid4lin_factory_refresh(f);
}
/* API: destroy factory */
@@ -344,6 +343,8 @@
vid4lin_factory *cf = (vid4lin_factory*)f;
pj_pool_t *pool = cf->pool;
+ if (cf->dev_pool)
+ pj_pool_release(cf->dev_pool);
if (cf->pool) {
cf->pool = NULL;
pj_pool_release(pool);
@@ -352,6 +353,22 @@
return PJ_SUCCESS;
}
+/* API: refresh the list of devices */
+static pj_status_t vid4lin_factory_refresh(pjmedia_vid_dev_factory *f)
+{
+ vid4lin_factory *cf = (vid4lin_factory*)f;
+ pj_status_t status;
+
+ status = v4l2_scan_devs(cf);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ PJ_LOG(4, (THIS_FILE, "Video4Linux2 has %d devices",
+ cf->dev_count));
+
+ return PJ_SUCCESS;
+}
+
/* API: get number of devices */
static unsigned vid4lin_factory_get_dev_count(pjmedia_vid_dev_factory *f)
{
diff --git a/pjmedia/src/pjmedia-videodev/videodev.c b/pjmedia/src/pjmedia-videodev/videodev.c
index 4741a40..2d65e02 100644
--- a/pjmedia/src/pjmedia-videodev/videodev.c
+++ b/pjmedia/src/pjmedia-videodev/videodev.c
@@ -210,23 +210,27 @@
}
/* Internal: init driver */
-static pj_status_t init_driver(unsigned drv_idx)
+static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh)
{
struct driver *drv = &vid_subsys.drv[drv_idx];
pjmedia_vid_dev_factory *f;
unsigned i, dev_cnt;
pj_status_t status;
- /* Create the factory */
- f = (*drv->create)(vid_subsys.pf);
- if (!f)
- return PJ_EUNKNOWN;
+ if (!refresh) {
+ /* Create the factory */
+ f = (*drv->create)(vid_subsys.pf);
+ if (!f)
+ return PJ_EUNKNOWN;
- /* Call factory->init() */
- status = f->op->init(f);
- if (status != PJ_SUCCESS) {
- f->op->destroy(f);
- return status;
+ /* Call factory->init() */
+ status = f->op->init(f);
+ if (status != PJ_SUCCESS) {
+ f->op->destroy(f);
+ return status;
+ }
+ } else {
+ f = drv->f;
}
/* Get number of devices */
@@ -356,7 +360,7 @@
/* Initialize each factory and build the device ID list */
for (i=0; i<vid_subsys.drv_cnt; ++i) {
- status = init_driver(i);
+ status = init_driver(i, PJ_FALSE);
if (status != PJ_SUCCESS) {
deinit_driver(i);
continue;
@@ -376,7 +380,7 @@
return PJMEDIA_EVID_INIT;
vid_subsys.drv[vid_subsys.drv_cnt].create = adf;
- status = init_driver(vid_subsys.drv_cnt);
+ status = init_driver(vid_subsys.drv_cnt, PJ_FALSE);
if (status == PJ_SUCCESS) {
vid_subsys.drv_cnt++;
} else {
@@ -442,6 +446,27 @@
return PJ_SUCCESS;
}
+/* API: Refresh the list of video devices installed in the system. */
+PJ_DEF(pj_status_t) pjmedia_vid_dev_refresh(void)
+{
+ unsigned i;
+
+ vid_subsys.dev_cnt = 0;
+ for (i=0; i<vid_subsys.drv_cnt; ++i) {
+ struct driver *drv = &vid_subsys.drv[i];
+
+ if (drv->f && drv->f->op->refresh) {
+ pj_status_t status = drv->f->op->refresh(drv->f);
+ if (status != PJ_SUCCESS) {
+ PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "
+ "list for %s", drv->name));
+ }
+ }
+ init_driver(i, PJ_TRUE);
+ }
+ return PJ_SUCCESS;
+}
+
/* API: Get the number of video devices installed in the system. */
PJ_DEF(unsigned) pjmedia_vid_dev_count(void)
{