Changeset 4016


Ignore:
Timestamp:
Apr 4, 2012 5:05:50 AM (8 years ago)
Author:
bennylp
Message:

Fixed #1478: AVI player virtual device. Initial spec:

  • Currently only Works with raw video and audio AVI files
  • Added --play-avi and --auto-play-avi options in pjsua
  • No A/V synchronization yet
Location:
pjproject/trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjmedia/build/Makefile

    r3982 r4016  
    9090# 
    9191export PJMEDIA_VIDEODEV_SRCDIR = ../src/pjmedia-videodev 
    92 export PJMEDIA_VIDEODEV_OBJS +=  errno.o videodev.o ffmpeg_dev.o \ 
     92export PJMEDIA_VIDEODEV_OBJS +=  errno.o videodev.o avi_dev.o ffmpeg_dev.o \ 
    9393                                colorbar_dev.o v4l2_dev.o 
    9494export PJMEDIA_VIDEODEV_CFLAGS += $(_CFLAGS) 
  • pjproject/trunk/pjmedia/include/pjmedia-videodev/config.h

    r3715 r4016  
    123123#endif 
    124124 
     125 
     126/** 
     127 * Enable support for AVI player virtual capture device. 
     128 * 
     129 * Default: 1 
     130 */ 
     131#ifndef PJMEDIA_VIDEO_DEV_HAS_AVI 
     132#   define PJMEDIA_VIDEO_DEV_HAS_AVI            1 
     133#endif 
     134 
     135 
    125136/** 
    126137 * @} 
  • pjproject/trunk/pjmedia/include/pjmedia-videodev/videodev.h

    r3893 r4016  
    560560/** 
    561561 * Register a supported video device factory to the video device subsystem. 
     562 * Application can either register a function to create the factory, or 
     563 * an instance of an already created factory. 
     564 * 
    562565 * This function can only be called after calling 
    563566 * #pjmedia_vid_dev_subsys_init(). 
    564567 * 
    565  * @param vdf       The video device factory. 
     568 * @param vdf       The factory creation function. Either vdf or factory 
     569 *                  argument must be specified. 
     570 * @param factory   Factory instance. Either vdf or factory 
     571 *                  argument must be specified. 
    566572 * 
    567573 * @return          PJ_SUCCESS on successful operation or the appropriate 
     
    569575 */ 
    570576PJ_DECL(pj_status_t) 
    571 pjmedia_vid_register_factory(pjmedia_vid_dev_factory_create_func_ptr vdf); 
     577pjmedia_vid_register_factory(pjmedia_vid_dev_factory_create_func_ptr vdf, 
     578                             pjmedia_vid_dev_factory *factory); 
    572579 
    573580 
     
    578585 * is currently in use, then the behavior is undefined. 
    579586 * 
    580  * @param vdf       The video device factory. 
     587 * @param vdf       The video device factory. Either vdf or factory argument 
     588 *                  must be specified. 
     589 * @param factory   The factory instance. Either vdf or factory argument 
     590 *                  must be specified. 
    581591 * 
    582592 * @return          PJ_SUCCESS on successful operation or the appropriate 
     
    584594 */ 
    585595PJ_DECL(pj_status_t) 
    586 pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr vdf); 
     596pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr vdf, 
     597                               pjmedia_vid_dev_factory *factory); 
    587598 
    588599 
  • pjproject/trunk/pjmedia/include/pjmedia-videodev/videodev_imp.h

    r3893 r4016  
    192192 
    193193 
    194  
     194/** 
     195 * Internal API: return the factory instance and device index that's local 
     196 * to the factory for a given device ID. 
     197 * 
     198 * @param id            Device id. 
     199 * @param p_f           Out: factory instance 
     200 * @param p_local_index Out: device index within the factory 
     201 * 
     202 * @return              PJ_SUCCESS on success. 
     203 */ 
     204PJ_DECL(pj_status_t) 
     205pjmedia_vid_dev_get_local_index(pjmedia_vid_dev_index id, 
     206                                pjmedia_vid_dev_factory **p_f, 
     207                                unsigned *p_local_index); 
     208 
     209/** 
     210 * Internal API: return the global device index given a factory instance and 
     211 * a local device index. 
     212 * 
     213 * @param f             Factory. 
     214 * @param local_idx     Local index. 
     215 * @param pid           Returned global index. 
     216 * 
     217 * @return              PJ_SUCCESS on success. 
     218 */ 
     219PJ_DEF(pj_status_t) 
     220pjmedia_vid_dev_get_global_index(const pjmedia_vid_dev_factory *f, 
     221                                 unsigned local_idx, 
     222                                 pjmedia_vid_dev_index *pid); 
    195223 
    196224/** 
  • pjproject/trunk/pjmedia/include/pjmedia_videodev.h

    r3715 r4016  
    2727#include <pjmedia-videodev/videodev.h> 
    2828#include <pjmedia-videodev/videodev_imp.h> 
     29#include <pjmedia-videodev/avi_dev.h> 
    2930 
    3031#endif  /* __PJMEDIA_VIDEODEV_H__ */ 
  • pjproject/trunk/pjmedia/src/pjmedia-videodev/videodev.c

    r3893 r4016  
    408408/* API: register a video device factory to the video device subsystem. */ 
    409409PJ_DEF(pj_status_t) 
    410 pjmedia_vid_register_factory(pjmedia_vid_dev_factory_create_func_ptr adf) 
    411 { 
     410pjmedia_vid_register_factory(pjmedia_vid_dev_factory_create_func_ptr adf, 
     411                             pjmedia_vid_dev_factory *factory) 
     412{ 
     413    pj_bool_t refresh = PJ_FALSE; 
    412414    pj_status_t status; 
    413415 
     
    416418 
    417419    vid_subsys.drv[vid_subsys.drv_cnt].create = adf; 
    418     status = init_driver(vid_subsys.drv_cnt, PJ_FALSE); 
     420    vid_subsys.drv[vid_subsys.drv_cnt].f = factory; 
     421 
     422    if (factory) { 
     423        /* Call factory->init() */ 
     424        status = factory->op->init(factory); 
     425        if (status != PJ_SUCCESS) { 
     426            factory->op->destroy(factory); 
     427            return status; 
     428        } 
     429        refresh = PJ_TRUE; 
     430    } 
     431 
     432    status = init_driver(vid_subsys.drv_cnt, refresh); 
    419433    if (status == PJ_SUCCESS) { 
    420434        vid_subsys.drv_cnt++; 
     
    428442/* API: unregister a video device factory from the video device subsystem. */ 
    429443PJ_DEF(pj_status_t) 
    430 pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr adf) 
     444pjmedia_vid_unregister_factory(pjmedia_vid_dev_factory_create_func_ptr adf, 
     445                               pjmedia_vid_dev_factory *factory) 
    431446{ 
    432447    unsigned i, j; 
     
    438453        struct driver *drv = &vid_subsys.drv[i]; 
    439454 
    440         if (drv->create == adf) { 
     455        if ((factory && drv->f==factory) || (adf && drv->create == adf)) { 
    441456            for (j = drv->start_idx; j < drv->start_idx + drv->dev_cnt; j++) 
    442457            { 
     
    579594} 
    580595 
     596/* API: lookup device id */ 
     597PJ_DEF(pj_status_t) 
     598pjmedia_vid_dev_get_local_index(pjmedia_vid_dev_index id, 
     599                                pjmedia_vid_dev_factory **p_f, 
     600                                unsigned *p_local_index) 
     601{ 
     602    return lookup_dev(id, p_f, p_local_index); 
     603} 
     604 
     605/* API: from factory and local index, get global index */ 
     606PJ_DEF(pj_status_t) 
     607pjmedia_vid_dev_get_global_index(const pjmedia_vid_dev_factory *f, 
     608                                 unsigned local_idx, 
     609                                 pjmedia_vid_dev_index *pid) 
     610{ 
     611    PJ_ASSERT_RETURN(f->sys.drv_idx >= 0 && f->sys.drv_idx < MAX_DRIVERS, 
     612                     PJ_EINVALIDOP); 
     613    *pid = local_idx; 
     614    return make_global_index(f->sys.drv_idx, pid); 
     615} 
     616 
    581617/* API: Get device information. */ 
    582618PJ_DEF(pj_status_t) pjmedia_vid_dev_get_info(pjmedia_vid_dev_index id, 
  • pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c

    r3999 r4016  
    4444#define RING_INTERVAL       3000 
    4545 
     46#define MAX_AVI             4 
    4647 
    4748/* Call specific data */ 
     
    136137    struct app_vid          vid; 
    137138    unsigned                aud_cnt; 
     139 
     140    /* AVI to play */ 
     141    unsigned                avi_cnt; 
     142    pj_str_t                avi[MAX_AVI]; 
     143    pj_bool_t               avi_auto_play; 
     144    pjmedia_vid_dev_index   avi_dev_id; 
     145    pjsua_conf_port_id      avi_slot; 
    138146} app_config; 
    139147 
     
    330338    puts  ("  --vcapture-dev=id   Video capture device ID (default=-1)"); 
    331339    puts  ("  --vrender-dev=id    Video render device ID (default=-1)"); 
     340    puts  ("  --play-avi=FILE     Load this AVI as virtual capture device"); 
     341    puts  ("  --auto-play-avi     Automatically play the AVI media to call"); 
    332342#endif 
    333343 
     
    400410    cfg->ringback_slot = PJSUA_INVALID_ID; 
    401411    cfg->ring_slot = PJSUA_INVALID_ID; 
     412 
     413    cfg->avi_dev_id = PJMEDIA_VID_INVALID_DEV; 
     414    cfg->avi_slot = PJSUA_INVALID_ID; 
    402415 
    403416    for (i=0; i<PJ_ARRAY_SIZE(cfg->acc_cfg); ++i) 
     
    577590           OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE, 
    578591           OPT_VIDEO, OPT_EXTRA_AUDIO, 
    579            OPT_VCAPTURE_DEV, OPT_VRENDER_DEV, 
     592           OPT_VCAPTURE_DEV, OPT_VRENDER_DEV, OPT_PLAY_AVI, OPT_AUTO_PLAY_AVI 
    580593    }; 
    581594    struct pj_getopt_option long_options[] = { 
     
    703716        { "vcapture-dev", 1, 0, OPT_VCAPTURE_DEV}, 
    704717        { "vrender-dev",  1, 0, OPT_VRENDER_DEV}, 
     718        { "play-avi",   1, 0, OPT_PLAY_AVI}, 
     719        { "auto-play-avi", 0, 0, OPT_AUTO_PLAY_AVI}, 
    705720        { NULL, 0, 0, 0} 
    706721    }; 
     
    14961511            cfg->vid.vrender_dev = atoi(pj_optarg); 
    14971512            cur_acc->vid_rend_dev = cfg->vid.vrender_dev; 
     1513            break; 
     1514 
     1515        case OPT_PLAY_AVI: 
     1516            if (app_config.avi_cnt >= MAX_AVI) { 
     1517                PJ_LOG(1,(THIS_FILE, "Too many AVIs")); 
     1518                return -1; 
     1519            } 
     1520            app_config.avi[app_config.avi_cnt++] = pj_str(pj_optarg); 
     1521            break; 
     1522 
     1523        case OPT_AUTO_PLAY_AVI: 
     1524            app_config.avi_auto_play = PJ_TRUE; 
    14981525            break; 
    14991526 
     
    20822109    if (config->vid.vrender_dev != PJMEDIA_VID_DEFAULT_RENDER_DEV) { 
    20832110        pj_ansi_sprintf(line, "--vrender-dev %d\n", config->vid.vrender_dev); 
     2111        pj_strcat2(&cfg, line); 
     2112    } 
     2113    for (i=0; i<config->avi_cnt; ++i) { 
     2114        pj_ansi_sprintf(line, "--play-avi %s\n", config->avi[i].ptr); 
     2115        pj_strcat2(&cfg, line); 
     2116    } 
     2117    if (config->avi_auto_play) { 
     2118        pj_ansi_sprintf(line, "--auto-play-avi\n"); 
    20842119        pj_strcat2(&cfg, line); 
    20852120    } 
     
    27882823            pjsua_conf_connect(app_config.wav_port, call_conf_slot); 
    27892824            connect_sound = PJ_FALSE; 
     2825        } 
     2826 
     2827        /* Stream AVI, if desired */ 
     2828        if (app_config.avi_auto_play && 
     2829            app_config.avi_slot != PJSUA_INVALID_ID) 
     2830        { 
     2831            pjsua_conf_connect(app_config.avi_slot, call_conf_slot); 
    27902832        } 
    27912833 
     
    39764018    acc_cfg->vid_cap_dev = app_config.vid.vcapture_dev; 
    39774019    acc_cfg->vid_rend_dev = app_config.vid.vrender_dev; 
     4020 
     4021    if (app_config.avi_auto_play && 
     4022        app_config.avi_dev_id != PJMEDIA_VID_INVALID_DEV) 
     4023    { 
     4024        acc_cfg->vid_cap_dev = app_config.avi_dev_id; 
     4025    } 
    39784026} 
    39794027 
     
    56365684    } 
    56375685 
     5686    /* Create AVI player virtual devices */ 
     5687    if (app_config.avi_cnt) { 
     5688#if PJMEDIA_VIDEO_DEV_HAS_AVI 
     5689        pjmedia_vid_dev_factory *avi_factory; 
     5690 
     5691        status = pjmedia_avi_dev_create_factory(pjsua_get_pool_factory(), 
     5692                                                app_config.avi_cnt, 
     5693                                                &avi_factory); 
     5694        if (status != PJ_SUCCESS) { 
     5695            PJ_PERROR(1,(THIS_FILE, status, "Error creating AVI factory")); 
     5696            goto on_error; 
     5697        } 
     5698 
     5699        for (i=0; i<app_config.avi_cnt; ++i) { 
     5700            pjmedia_avi_dev_param avdp; 
     5701            pjmedia_vid_dev_index avid; 
     5702            unsigned strm_idx, strm_cnt; 
     5703 
     5704            pjmedia_avi_dev_param_default(&avdp); 
     5705            avdp.path = app_config.avi[i]; 
     5706 
     5707            status =  pjmedia_avi_dev_alloc(avi_factory, &avdp, &avid); 
     5708            if (status != PJ_SUCCESS) { 
     5709                PJ_PERROR(1,(THIS_FILE, status, 
     5710                             "Error creating AVI player for %.*s", 
     5711                             (int)avdp.path.slen, avdp.path.ptr)); 
     5712                goto on_error; 
     5713            } 
     5714 
     5715            PJ_LOG(4,(THIS_FILE, "AVI player %.*s created, dev_id=%d", 
     5716                      (int)avdp.title.slen, avdp.title.ptr, avid)); 
     5717            app_config.avi_dev_id = avid; 
     5718 
     5719            strm_cnt = pjmedia_avi_streams_get_num_streams(avdp.avi_streams); 
     5720            for (strm_idx=0; strm_idx<strm_cnt; ++strm_idx) { 
     5721                pjmedia_port *aud; 
     5722                pjmedia_format *fmt; 
     5723                pjsua_conf_port_id slot; 
     5724                char fmt_name[5]; 
     5725 
     5726                aud = pjmedia_avi_streams_get_stream(avdp.avi_streams, 
     5727                                                     strm_idx); 
     5728                fmt = &aud->info.fmt; 
     5729 
     5730                pjmedia_fourcc_name(fmt->id, fmt_name); 
     5731 
     5732                if (fmt->id == PJMEDIA_FORMAT_PCM) { 
     5733                    status = pjsua_conf_add_port(app_config.pool, aud, 
     5734                                                 &slot); 
     5735                    if (status == PJ_SUCCESS) { 
     5736                        PJ_LOG(4,(THIS_FILE, 
     5737                                  "AVI %.*s: audio added to slot %d", 
     5738                                  (int)avdp.title.slen, avdp.title.ptr, 
     5739                                  slot)); 
     5740                        app_config.avi_slot = slot; 
     5741                    } 
     5742                } else { 
     5743                    PJ_LOG(4,(THIS_FILE, 
     5744                              "AVI %.*s: audio ignored, format=%s", 
     5745                              (int)avdp.title.slen, avdp.title.ptr, 
     5746                              fmt_name)); 
     5747                } 
     5748            } 
     5749        } 
     5750#else 
     5751        PJ_LOG(2,(THIS_FILE, 
     5752                  "Warning: --play-avi is ignored because AVI is disabled")); 
     5753#endif  /* PJMEDIA_VIDEO_DEV_HAS_AVI */ 
     5754    } 
     5755 
    56385756    /* Add UDP transport unless it's disabled. */ 
    56395757    if (!app_config.no_udp) { 
  • pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h

    r3999 r4016  
    3535/* Include all PJMEDIA-CODEC headers. */ 
    3636#include <pjmedia-codec.h> 
     37 
     38/* Videodev too */ 
     39#include <pjmedia_videodev.h> 
    3740 
    3841/* Include all PJSIP-UA headers */ 
Note: See TracChangeset for help on using the changeset viewer.