Changeset 5255 for pjproject/trunk/pjmedia/src/pjmedia-videodev/videodev.c
- Timestamp:
- Mar 10, 2016 5:02:07 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia-videodev/videodev.c
r5125 r5255 19 19 #include <pjmedia-videodev/videodev_imp.h> 20 20 #include <pj/assert.h> 21 #include <pj/errno.h>22 #include <pj/log.h>23 #include <pj/pool.h>24 #include <pj/string.h>25 21 26 22 … … 29 25 30 26 #define THIS_FILE "videodev.c" 31 32 #define DEFINE_CAP(name, info) {name, info}33 34 /* Capability names */35 static struct cap_info36 {37 const char *name;38 const char *info;39 } cap_infos[] =40 {41 DEFINE_CAP("format", "Video format"),42 DEFINE_CAP("scale", "Input dimension"),43 DEFINE_CAP("window", "Window handle"),44 DEFINE_CAP("resize", "Renderer resize"),45 DEFINE_CAP("position", "Renderer position"),46 DEFINE_CAP("hide", "Renderer hide"),47 DEFINE_CAP("preview", "Input preview"),48 DEFINE_CAP("orientation", "Video orientation"),49 DEFINE_CAP("switch", "Switch device"),50 DEFINE_CAP("wndflags", "Window flags")51 };52 53 54 /*55 * The device index seen by application and driver is different.56 *57 * At application level, device index is index to global list of device.58 * At driver level, device index is index to device list on that particular59 * factory only.60 */61 #define MAKE_DEV_ID(f_id, index) (((f_id & 0xFFFF) << 16) | (index & 0xFFFF))62 #define GET_INDEX(dev_id) ((dev_id) & 0xFFFF)63 #define GET_FID(dev_id) ((dev_id) >> 16)64 #define DEFAULT_DEV_ID 065 27 66 28 … … 110 72 111 73 112 /* driver structure */113 struct driver114 {115 /* Creation function */116 pjmedia_vid_dev_factory_create_func_ptr create;117 /* Factory instance */118 pjmedia_vid_dev_factory *f;119 char name[32]; /* Driver name */120 unsigned dev_cnt; /* Number of devices */121 unsigned start_idx; /* Start index in global list */122 int cap_dev_idx; /* Default capture device. */123 int rend_dev_idx; /* Default render device */124 };125 126 /* The video device subsystem */127 static struct vid_subsys128 {129 unsigned init_count; /* How many times init() is called */130 pj_pool_factory *pf; /* The pool factory. */131 132 unsigned drv_cnt; /* Number of drivers. */133 struct driver drv[MAX_DRIVERS]; /* Array of drivers. */134 135 unsigned dev_cnt; /* Total number of devices. */136 pj_uint32_t dev_list[MAX_DEVS];/* Array of device IDs. */137 138 } vid_subsys;139 140 /* API: get capability name/info */141 PJ_DEF(const char*) pjmedia_vid_dev_cap_name(pjmedia_vid_dev_cap cap,142 const char **p_desc)143 {144 const char *desc;145 unsigned i;146 147 if (p_desc==NULL) p_desc = &desc;148 149 for (i=0; i<PJ_ARRAY_SIZE(cap_infos); ++i) {150 if ((1 << i)==cap)151 break;152 }153 154 if (i==PJ_ARRAY_SIZE(cap_infos)) {155 *p_desc = "??";156 return "??";157 }158 159 *p_desc = cap_infos[i].info;160 return cap_infos[i].name;161 }162 163 static pj_status_t get_cap_pointer(const pjmedia_vid_dev_param *param,164 pjmedia_vid_dev_cap cap,165 void **ptr,166 unsigned *size)167 {168 #define FIELD_INFO(name) *ptr = (void*)¶m->name; \169 *size = sizeof(param->name)170 171 switch (cap) {172 case PJMEDIA_VID_DEV_CAP_FORMAT:173 FIELD_INFO(fmt);174 break;175 case PJMEDIA_VID_DEV_CAP_INPUT_SCALE:176 FIELD_INFO(disp_size);177 break;178 case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW:179 FIELD_INFO(window);180 break;181 case PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE:182 FIELD_INFO(disp_size);183 break;184 case PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION:185 FIELD_INFO(window_pos);186 break;187 case PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE:188 FIELD_INFO(window_hide);189 break;190 case PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW:191 FIELD_INFO(native_preview);192 break;193 case PJMEDIA_VID_DEV_CAP_ORIENTATION:194 FIELD_INFO(orient);195 break;196 /* The PJMEDIA_VID_DEV_CAP_SWITCH does not have an entry in the197 * param (it doesn't make sense to open a stream and tell it198 * to switch immediately).199 */200 case PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW_FLAGS:201 FIELD_INFO(window_flags);202 break;203 default:204 return PJMEDIA_EVID_INVCAP;205 }206 207 #undef FIELD_INFO208 209 return PJ_SUCCESS;210 }211 212 /* API: set cap value to param */213 PJ_DEF(pj_status_t)214 pjmedia_vid_dev_param_set_cap( pjmedia_vid_dev_param *param,215 pjmedia_vid_dev_cap cap,216 const void *pval)217 {218 void *cap_ptr;219 unsigned cap_size;220 pj_status_t status;221 222 status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);223 if (status != PJ_SUCCESS)224 return status;225 226 pj_memcpy(cap_ptr, pval, cap_size);227 param->flags |= cap;228 229 return PJ_SUCCESS;230 }231 232 /* API: get cap value from param */233 PJ_DEF(pj_status_t)234 pjmedia_vid_dev_param_get_cap( const pjmedia_vid_dev_param *param,235 pjmedia_vid_dev_cap cap,236 void *pval)237 {238 void *cap_ptr;239 unsigned cap_size;240 pj_status_t status;241 242 status = get_cap_pointer(param, cap, &cap_ptr, &cap_size);243 if (status != PJ_SUCCESS)244 return status;245 246 if ((param->flags & cap) == 0) {247 pj_bzero(cap_ptr, cap_size);248 return PJMEDIA_EVID_INVCAP;249 }250 251 pj_memcpy(pval, cap_ptr, cap_size);252 return PJ_SUCCESS;253 }254 255 /* Internal: init driver */256 static pj_status_t init_driver(unsigned drv_idx, pj_bool_t refresh)257 {258 struct driver *drv = &vid_subsys.drv[drv_idx];259 pjmedia_vid_dev_factory *f;260 unsigned i, dev_cnt;261 pj_status_t status;262 263 if (!refresh) {264 /* Create the factory */265 f = (*drv->create)(vid_subsys.pf);266 if (!f)267 return PJ_EUNKNOWN;268 269 /* Call factory->init() */270 status = f->op->init(f);271 if (status != PJ_SUCCESS) {272 f->op->destroy(f);273 return status;274 }275 } else {276 f = drv->f;277 }278 279 /* Get number of devices */280 dev_cnt = f->op->get_dev_count(f);281 if (dev_cnt + vid_subsys.dev_cnt > MAX_DEVS) {282 PJ_LOG(4,(THIS_FILE, "%d device(s) cannot be registered because"283 " there are too many devices",284 vid_subsys.dev_cnt + dev_cnt - MAX_DEVS));285 dev_cnt = MAX_DEVS - vid_subsys.dev_cnt;286 }287 288 /* enabling this will cause pjsua-lib initialization to fail when there289 * is no video device installed in the system, even when pjsua has been290 * run with --null-video291 *292 if (dev_cnt == 0) {293 f->op->destroy(f);294 return PJMEDIA_EVID_NODEV;295 }296 */297 298 /* Fill in default devices */299 drv->rend_dev_idx = drv->cap_dev_idx = -1;300 for (i=0; i<dev_cnt; ++i) {301 pjmedia_vid_dev_info info;302 303 status = f->op->get_dev_info(f, i, &info);304 if (status != PJ_SUCCESS) {305 f->op->destroy(f);306 return status;307 }308 309 if (drv->name[0]=='\0') {310 /* Set driver name */311 pj_ansi_strncpy(drv->name, info.driver, sizeof(drv->name));312 drv->name[sizeof(drv->name)-1] = '\0';313 }314 315 if (drv->rend_dev_idx < 0 && (info.dir & PJMEDIA_DIR_RENDER)) {316 /* Set default render device */317 drv->rend_dev_idx = i;318 }319 if (drv->cap_dev_idx < 0 && (info.dir & PJMEDIA_DIR_CAPTURE)) {320 /* Set default capture device */321 drv->cap_dev_idx = i;322 }323 324 if (drv->rend_dev_idx >= 0 && drv->cap_dev_idx >= 0) {325 /* Done. */326 break;327 }328 }329 330 /* Register the factory */331 drv->f = f;332 drv->f->sys.drv_idx = drv_idx;333 drv->start_idx = vid_subsys.dev_cnt;334 drv->dev_cnt = dev_cnt;335 336 /* Register devices to global list */337 for (i=0; i<dev_cnt; ++i) {338 vid_subsys.dev_list[vid_subsys.dev_cnt++] = MAKE_DEV_ID(drv_idx, i);339 }340 341 return PJ_SUCCESS;342 }343 344 /* Internal: deinit driver */345 static void deinit_driver(unsigned drv_idx)346 {347 struct driver *drv = &vid_subsys.drv[drv_idx];348 349 if (drv->f) {350 drv->f->op->destroy(drv->f);351 drv->f = NULL;352 }353 354 drv->dev_cnt = 0;355 drv->rend_dev_idx = drv->cap_dev_idx = -1;356 }357 358 74 /* API: Initialize the video device subsystem. */ 359 75 PJ_DEF(pj_status_t) pjmedia_vid_dev_subsys_init(pj_pool_factory *pf) … … 361 77 unsigned i; 362 78 pj_status_t status = PJ_SUCCESS; 79 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 363 80 364 81 /* Allow init() to be called multiple times as long as there is matching 365 82 * number of shutdown(). 366 83 */ 367 if (vid_subsys .init_count++ != 0) {84 if (vid_subsys->init_count++ != 0) { 368 85 return PJ_SUCCESS; 369 86 } … … 375 92 376 93 /* Init */ 377 vid_subsys .pf = pf;378 vid_subsys .drv_cnt = 0;379 vid_subsys .dev_cnt = 0;94 vid_subsys->pf = pf; 95 vid_subsys->drv_cnt = 0; 96 vid_subsys->dev_cnt = 0; 380 97 381 98 /* Register creation functions */ 382 99 #if PJMEDIA_VIDEO_DEV_HAS_V4L2 383 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_v4l2_factory;100 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_v4l2_factory; 384 101 #endif 385 102 #if PJMEDIA_VIDEO_DEV_HAS_QT 386 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_qt_factory;103 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_qt_factory; 387 104 #endif 388 105 #if PJMEDIA_VIDEO_DEV_HAS_OPENGL 389 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_opengl_factory;106 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_opengl_factory; 390 107 #endif 391 108 #if PJMEDIA_VIDEO_DEV_HAS_IOS 392 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_ios_factory;109 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_ios_factory; 393 110 #endif 394 111 #if PJMEDIA_VIDEO_DEV_HAS_DSHOW 395 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_dshow_factory;112 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_dshow_factory; 396 113 #endif 397 114 #if PJMEDIA_VIDEO_DEV_HAS_FFMPEG 398 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_ffmpeg_factory;115 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_ffmpeg_factory; 399 116 #endif 400 117 #if PJMEDIA_VIDEO_DEV_HAS_SDL 401 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_sdl_factory;118 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_sdl_factory; 402 119 #endif 403 120 #if PJMEDIA_VIDEO_DEV_HAS_ANDROID 404 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_and_factory;121 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_and_factory; 405 122 #endif 406 123 #if PJMEDIA_VIDEO_DEV_HAS_CBAR_SRC … … 408 125 * a real capturer, if any. 409 126 */ 410 vid_subsys .drv[vid_subsys.drv_cnt++].create = &pjmedia_cbar_factory;127 vid_subsys->drv[vid_subsys->drv_cnt++].create = &pjmedia_cbar_factory; 411 128 #endif 412 129 413 130 /* Initialize each factory and build the device ID list */ 414 for (i=0; i<vid_subsys .drv_cnt; ++i) {415 status = init_driver(i, PJ_FALSE);131 for (i=0; i<vid_subsys->drv_cnt; ++i) { 132 status = pjmedia_vid_driver_init(i, PJ_FALSE); 416 133 if (status != PJ_SUCCESS) { 417 deinit_driver(i);134 pjmedia_vid_driver_deinit(i); 418 135 continue; 419 136 } 420 137 } 421 138 422 return vid_subsys .dev_cnt ? PJ_SUCCESS : status;139 return vid_subsys->dev_cnt ? PJ_SUCCESS : status; 423 140 } 424 141 … … 430 147 pj_bool_t refresh = PJ_FALSE; 431 148 pj_status_t status; 432 433 if (vid_subsys.init_count == 0) 149 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 150 151 if (vid_subsys->init_count == 0) 434 152 return PJMEDIA_EVID_INIT; 435 153 436 vid_subsys .drv[vid_subsys.drv_cnt].create = adf;437 vid_subsys .drv[vid_subsys.drv_cnt].f = factory;154 vid_subsys->drv[vid_subsys->drv_cnt].create = adf; 155 vid_subsys->drv[vid_subsys->drv_cnt].f = factory; 438 156 439 157 if (factory) { … … 447 165 } 448 166 449 status = init_driver(vid_subsys.drv_cnt, refresh);167 status = pjmedia_vid_driver_init(vid_subsys->drv_cnt, refresh); 450 168 if (status == PJ_SUCCESS) { 451 vid_subsys .drv_cnt++;169 vid_subsys->drv_cnt++; 452 170 } else { 453 deinit_driver(vid_subsys.drv_cnt);171 pjmedia_vid_driver_deinit(vid_subsys->drv_cnt); 454 172 } 455 173 … … 463 181 { 464 182 unsigned i, j; 465 466 if (vid_subsys.init_count == 0) 183 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 184 185 if (vid_subsys->init_count == 0) 467 186 return PJMEDIA_EVID_INIT; 468 187 469 for (i=0; i<vid_subsys .drv_cnt; ++i) {470 struct driver *drv = &vid_subsys.drv[i];188 for (i=0; i<vid_subsys->drv_cnt; ++i) { 189 pjmedia_vid_driver *drv = &vid_subsys->drv[i]; 471 190 472 191 if ((factory && drv->f==factory) || (adf && drv->create == adf)) { 473 192 for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++) 474 193 { 475 vid_subsys .dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV;194 vid_subsys->dev_list[j] = (pj_uint32_t)PJMEDIA_VID_INVALID_DEV; 476 195 } 477 196 478 deinit_driver(i);197 pjmedia_vid_driver_deinit(i); 479 198 pj_bzero(drv, sizeof(*drv)); 480 199 return PJ_SUCCESS; … … 488 207 PJ_DEF(pj_pool_factory*) pjmedia_vid_dev_subsys_get_pool_factory(void) 489 208 { 490 return vid_subsys.pf; 209 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 210 return vid_subsys->pf; 491 211 } 492 212 … … 495 215 { 496 216 unsigned i; 217 pjmedia_vid_subsys *vid_subsys = pjmedia_get_vid_subsys(); 497 218 498 219 /* Allow shutdown() to be called multiple times as long as there is 499 220 * matching number of init(). 500 221 */ 501 if (vid_subsys .init_count == 0) {222 if (vid_subsys->init_count == 0) { 502 223 return PJ_SUCCESS; 503 224 } 504 --vid_subsys .init_count;505 506 if (vid_subsys .init_count == 0) {507 for (i=0; i<vid_subsys .drv_cnt; ++i) {508 deinit_driver(i);225 --vid_subsys->init_count; 226 227 if (vid_subsys->init_count == 0) { 228 for (i=0; i<vid_subsys->drv_cnt; ++i) { 229 pjmedia_vid_driver_deinit(i); 509 230 } 510 231 511 vid_subsys .pf = NULL;232 vid_subsys->pf = NULL; 512 233 } 513 234 return PJ_SUCCESS; 514 235 } 515 236 516 /* API: Refresh the list of video devices installed in the system. */517 PJ_DEF(pj_status_t) pjmedia_vid_dev_refresh(void)518 {519 unsigned i;520 521 vid_subsys.dev_cnt = 0;522 for (i=0; i<vid_subsys.drv_cnt; ++i) {523 struct driver *drv = &vid_subsys.drv[i];524 525 if (drv->f && drv->f->op->refresh) {526 pj_status_t status = drv->f->op->refresh(drv->f);527 if (status != PJ_SUCCESS) {528 PJ_PERROR(4, (THIS_FILE, status, "Unable to refresh device "529 "list for %s", drv->name));530 }531 }532 init_driver(i, PJ_TRUE);533 }534 return PJ_SUCCESS;535 }536 537 /* API: Get the number of video devices installed in the system. */538 PJ_DEF(unsigned) pjmedia_vid_dev_count(void)539 {540 return vid_subsys.dev_cnt;541 }542 543 /* Internal: convert local index to global device index */544 static pj_status_t make_global_index(unsigned drv_idx,545 pjmedia_vid_dev_index *id)546 {547 if (*id < 0) {548 return PJ_SUCCESS;549 }550 551 /* Check that factory still exists */552 PJ_ASSERT_RETURN(vid_subsys.drv[drv_idx].f, PJ_EBUG);553 554 /* Check that device index is valid */555 PJ_ASSERT_RETURN(*id>=0 && *id<(int)vid_subsys.drv[drv_idx].dev_cnt,556 PJ_EBUG);557 558 *id += vid_subsys.drv[drv_idx].start_idx;559 return PJ_SUCCESS;560 }561 562 /* Internal: lookup device id */563 static pj_status_t lookup_dev(pjmedia_vid_dev_index id,564 pjmedia_vid_dev_factory **p_f,565 unsigned *p_local_index)566 {567 int f_id, index;568 569 if (id < 0) {570 unsigned i;571 572 if (id <= PJMEDIA_VID_INVALID_DEV)573 return PJMEDIA_EVID_INVDEV;574 575 for (i=0; i<vid_subsys.drv_cnt; ++i) {576 struct driver *drv = &vid_subsys.drv[i];577 if (id==PJMEDIA_VID_DEFAULT_CAPTURE_DEV &&578 drv->cap_dev_idx >= 0)579 {580 id = drv->cap_dev_idx;581 make_global_index(i, &id);582 break;583 } else if (id==PJMEDIA_VID_DEFAULT_RENDER_DEV &&584 drv->rend_dev_idx >= 0)585 {586 id = drv->rend_dev_idx;587 make_global_index(i, &id);588 break;589 }590 }591 592 if (id < 0) {593 return PJMEDIA_EVID_NODEFDEV;594 }595 }596 597 f_id = GET_FID(vid_subsys.dev_list[id]);598 index = GET_INDEX(vid_subsys.dev_list[id]);599 600 if (f_id < 0 || f_id >= (int)vid_subsys.drv_cnt)601 return PJMEDIA_EVID_INVDEV;602 603 if (index < 0 || index >= (int)vid_subsys.drv[f_id].dev_cnt)604 return PJMEDIA_EVID_INVDEV;605 606 *p_f = vid_subsys.drv[f_id].f;607 *p_local_index = (unsigned)index;608 609 return PJ_SUCCESS;610 611 }612 613 /* API: lookup device id */614 PJ_DEF(pj_status_t)615 pjmedia_vid_dev_get_local_index(pjmedia_vid_dev_index id,616 pjmedia_vid_dev_factory **p_f,617 unsigned *p_local_index)618 {619 return lookup_dev(id, p_f, p_local_index);620 }621 622 /* API: from factory and local index, get global index */623 PJ_DEF(pj_status_t)624 pjmedia_vid_dev_get_global_index(const pjmedia_vid_dev_factory *f,625 unsigned local_idx,626 pjmedia_vid_dev_index *pid)627 {628 PJ_ASSERT_RETURN(f->sys.drv_idx >= 0 && f->sys.drv_idx < MAX_DRIVERS,629 PJ_EINVALIDOP);630 *pid = local_idx;631 return make_global_index(f->sys.drv_idx, pid);632 }633 634 /* API: Get device information. */635 PJ_DEF(pj_status_t) pjmedia_vid_dev_get_info(pjmedia_vid_dev_index id,636 pjmedia_vid_dev_info *info)637 {638 pjmedia_vid_dev_factory *f;639 unsigned index;640 pj_status_t status;641 642 PJ_ASSERT_RETURN(info, PJ_EINVAL);643 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);644 645 if (id <= PJMEDIA_VID_INVALID_DEV)646 return PJMEDIA_EVID_INVDEV;647 648 status = lookup_dev(id, &f, &index);649 if (status != PJ_SUCCESS)650 return status;651 652 status = f->op->get_dev_info(f, index, info);653 654 /* Make sure device ID is the real ID (not PJMEDIA_VID_DEFAULT_*_DEV) */655 info->id = index;656 make_global_index(f->sys.drv_idx, &info->id);657 658 return status;659 }660 661 /* API: find device */662 PJ_DEF(pj_status_t) pjmedia_vid_dev_lookup( const char *drv_name,663 const char *dev_name,664 pjmedia_vid_dev_index *id)665 {666 pjmedia_vid_dev_factory *f = NULL;667 unsigned drv_idx, dev_idx;668 669 PJ_ASSERT_RETURN(drv_name && dev_name && id, PJ_EINVAL);670 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);671 672 for (drv_idx=0; drv_idx<vid_subsys.drv_cnt; ++drv_idx) {673 if (!pj_ansi_stricmp(drv_name, vid_subsys.drv[drv_idx].name))674 {675 f = vid_subsys.drv[drv_idx].f;676 break;677 }678 }679 680 if (!f)681 return PJ_ENOTFOUND;682 683 for (dev_idx=0; dev_idx<vid_subsys.drv[drv_idx].dev_cnt; ++dev_idx)684 {685 pjmedia_vid_dev_info info;686 pj_status_t status;687 688 status = f->op->get_dev_info(f, dev_idx, &info);689 if (status != PJ_SUCCESS)690 return status;691 692 if (!pj_ansi_stricmp(dev_name, info.name))693 break;694 }695 696 if (dev_idx==vid_subsys.drv[drv_idx].dev_cnt)697 return PJ_ENOTFOUND;698 699 *id = dev_idx;700 make_global_index(drv_idx, id);701 702 return PJ_SUCCESS;703 }704 705 /* API: Initialize the video device parameters with default values for the706 * specified device.707 */708 PJ_DEF(pj_status_t) pjmedia_vid_dev_default_param(pj_pool_t *pool,709 pjmedia_vid_dev_index id,710 pjmedia_vid_dev_param *param)711 {712 pjmedia_vid_dev_factory *f;713 unsigned index;714 pj_status_t status;715 716 PJ_ASSERT_RETURN(param, PJ_EINVAL);717 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);718 719 if (id <= PJMEDIA_VID_INVALID_DEV)720 return PJMEDIA_EVID_INVDEV;721 722 status = lookup_dev(id, &f, &index);723 if (status != PJ_SUCCESS)724 return status;725 726 status = f->op->default_param(pool, f, index, param);727 if (status != PJ_SUCCESS)728 return status;729 730 /* Normalize device IDs */731 make_global_index(f->sys.drv_idx, ¶m->cap_id);732 make_global_index(f->sys.drv_idx, ¶m->rend_id);733 734 return PJ_SUCCESS;735 }736 737 /* API: Open video stream object using the specified parameters. */738 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_create(739 pjmedia_vid_dev_param *prm,740 const pjmedia_vid_dev_cb *cb,741 void *user_data,742 pjmedia_vid_dev_stream **p_vid_strm)743 {744 pjmedia_vid_dev_factory *cap_f=NULL, *rend_f=NULL, *f=NULL;745 pj_status_t status;746 747 PJ_ASSERT_RETURN(prm && prm->dir && p_vid_strm, PJ_EINVAL);748 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);749 PJ_ASSERT_RETURN(prm->dir==PJMEDIA_DIR_CAPTURE ||750 prm->dir==PJMEDIA_DIR_RENDER ||751 prm->dir==PJMEDIA_DIR_CAPTURE_RENDER,752 PJ_EINVAL);753 754 /* Normalize cap_id */755 if (prm->dir & PJMEDIA_DIR_CAPTURE) {756 unsigned index;757 758 if (prm->cap_id < 0)759 prm->cap_id = PJMEDIA_VID_DEFAULT_CAPTURE_DEV;760 761 status = lookup_dev(prm->cap_id, &cap_f, &index);762 if (status != PJ_SUCCESS)763 return status;764 765 prm->cap_id = index;766 f = cap_f;767 }768 769 /* Normalize rend_id */770 if (prm->dir & PJMEDIA_DIR_RENDER) {771 unsigned index;772 773 if (prm->rend_id < 0)774 prm->rend_id = PJMEDIA_VID_DEFAULT_RENDER_DEV;775 776 status = lookup_dev(prm->rend_id, &rend_f, &index);777 if (status != PJ_SUCCESS)778 return status;779 780 prm->rend_id = index;781 f = rend_f;782 }783 784 PJ_ASSERT_RETURN(f != NULL, PJ_EBUG);785 786 /* For now, cap_id and rend_id must belong to the same factory */787 PJ_ASSERT_RETURN((prm->dir != PJMEDIA_DIR_CAPTURE_RENDER) ||788 (cap_f == rend_f),789 PJMEDIA_EVID_INVDEV);790 791 /* Create the stream */792 status = f->op->create_stream(f, prm, cb,793 user_data, p_vid_strm);794 if (status != PJ_SUCCESS)795 return status;796 797 /* Assign factory id to the stream */798 (*p_vid_strm)->sys.drv_idx = f->sys.drv_idx;799 return PJ_SUCCESS;800 }801 802 /* API: Get the running parameters for the specified video stream. */803 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_param(804 pjmedia_vid_dev_stream *strm,805 pjmedia_vid_dev_param *param)806 {807 pj_status_t status;808 809 PJ_ASSERT_RETURN(strm && param, PJ_EINVAL);810 PJ_ASSERT_RETURN(vid_subsys.pf, PJMEDIA_EVID_INIT);811 812 status = strm->op->get_param(strm, param);813 if (status != PJ_SUCCESS)814 return status;815 816 /* Normalize device id's */817 make_global_index(strm->sys.drv_idx, ¶m->cap_id);818 make_global_index(strm->sys.drv_idx, ¶m->rend_id);819 820 return PJ_SUCCESS;821 }822 823 /* API: Get the value of a specific capability of the video stream. */824 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_cap(825 pjmedia_vid_dev_stream *strm,826 pjmedia_vid_dev_cap cap,827 void *value)828 {829 return strm->op->get_cap(strm, cap, value);830 }831 832 /* API: Set the value of a specific capability of the video stream. */833 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_set_cap(834 pjmedia_vid_dev_stream *strm,835 pjmedia_vid_dev_cap cap,836 const void *value)837 {838 /* For fast switching, device global index needs to be converted to839 * local index before forwarding the request to the device stream.840 */841 if (cap == PJMEDIA_VID_DEV_CAP_SWITCH) {842 pjmedia_vid_dev_factory *f;843 unsigned local_idx;844 pj_status_t status;845 pjmedia_vid_dev_switch_param p = *(pjmedia_vid_dev_switch_param*)value;846 847 status = lookup_dev(p.target_id, &f, &local_idx);848 if (status != PJ_SUCCESS)849 return status;850 851 /* Make sure that current & target devices share the same factory */852 if (f->sys.drv_idx != strm->sys.drv_idx)853 return PJMEDIA_EVID_INVDEV;854 855 p.target_id = local_idx;856 return strm->op->set_cap(strm, cap, &p);857 }858 859 return strm->op->set_cap(strm, cap, value);860 }861 862 /* API: Start the stream. */863 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_start(pjmedia_vid_dev_stream *strm)864 {865 pj_status_t status;866 867 if (pjmedia_vid_dev_stream_is_running(strm))868 return PJ_SUCCESS;869 870 status = strm->op->start(strm);871 if (status == PJ_SUCCESS)872 strm->sys.is_running = PJ_TRUE;873 return status;874 }875 876 /* API: has it been started? */877 PJ_DEF(pj_bool_t)878 pjmedia_vid_dev_stream_is_running(pjmedia_vid_dev_stream *strm)879 {880 return strm->sys.is_running;881 }882 883 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_get_frame(884 pjmedia_vid_dev_stream *strm,885 pjmedia_frame *frame)886 {887 pj_assert(strm->op->get_frame);888 return strm->op->get_frame(strm, frame);889 }890 891 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_put_frame(892 pjmedia_vid_dev_stream *strm,893 const pjmedia_frame *frame)894 {895 pj_assert(strm->op->put_frame);896 return strm->op->put_frame(strm, frame);897 }898 899 /* API: Stop the stream. */900 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_stop(pjmedia_vid_dev_stream *strm)901 {902 strm->sys.is_running = PJ_FALSE;903 return strm->op->stop(strm);904 }905 906 /* API: Destroy the stream. */907 PJ_DEF(pj_status_t) pjmedia_vid_dev_stream_destroy(908 pjmedia_vid_dev_stream *strm)909 {910 strm->sys.is_running = PJ_FALSE;911 return strm->op->destroy(strm);912 }913 914 237 915 238 #endif /* PJMEDIA_HAS_VIDEO */
Note: See TracChangeset
for help on using the changeset viewer.