Пример #1
0
/*
 * Generate default attribute.
 */
static pj_status_t openh264_default_attr( pjmedia_vid_codec_factory *factory, 
				        const pjmedia_vid_codec_info *info, 
				        pjmedia_vid_codec_param *attr )
{
    const openh264_codec_desc *desc;
    unsigned i;

    PJ_ASSERT_RETURN(factory==&openh264_factory.base, PJ_EINVAL);
    PJ_ASSERT_RETURN(info && attr, PJ_EINVAL);

    desc = find_codec_desc_by_info(info);
    if (!desc) {
        return PJMEDIA_CODEC_EUNSUP;
    }

    pj_bzero(attr, sizeof(pjmedia_vid_codec_param));

    /* Scan the requested packings and use the lowest number */
    attr->packing = 0;
    for (i=0; i<15; ++i) {
		unsigned packing = (1 << i);
		if ((desc->info.packings & info->packings) & packing) {
			attr->packing = (pjmedia_vid_packing)packing;
			break;
		}
    }
    if (attr->packing == 0) {
		/* No supported packing in info */
		return PJMEDIA_CODEC_EUNSUP;
    }

    /* Direction */
    attr->dir = desc->info.dir;

    /* Encoded format */
    pjmedia_format_init_video(&attr->enc_fmt, desc->info.fmt_id,
                              desc->size.w, desc->size.h,
			      desc->fps.num, desc->fps.denum);

    /* Decoded format */
    pjmedia_format_init_video(&attr->dec_fmt, desc->info.dec_fmt_id[0],
                              desc->size.w, desc->size.h,
			      desc->fps.num, desc->fps.denum);

    /* Decoding fmtp */
    attr->dec_fmtp = desc->dec_fmtp;

    /* Bitrate */
    attr->enc_fmt.det.vid.avg_bps = desc->avg_bps;
    attr->enc_fmt.det.vid.max_bps = desc->max_bps;

    /* Encoding MTU */
    attr->enc_mtu = PJMEDIA_MAX_VID_PAYLOAD_SIZE;

    return PJ_SUCCESS;
}
Пример #2
0
static pj_status_t alt_vid_codec_default_attr( pjmedia_vid_codec_factory *factory,
                                               const pjmedia_vid_codec_info *info,
                                               pjmedia_vid_codec_param *attr )
{
    const struct alt_codec_desc *desc = find_codec_desc_by_info(info);
    unsigned i;

    if (!desc)
        return PJMEDIA_CODEC_EUNSUP;

    pj_bzero(attr, sizeof(pjmedia_vid_codec_param));

    /* Scan the requested packings and use the lowest number */
    attr->packing = 0;
    for (i=0; i<15; ++i) {
	unsigned packing = (1 << i);
	if ((desc->info.packings & info->packings) & packing) {
	    attr->packing = (pjmedia_vid_packing)packing;
	    break;
	}
    }
    if (attr->packing == 0) {
	/* No supported packing in info */
	return PJMEDIA_CODEC_EUNSUP;
    }

    /* Direction */
    attr->dir = desc->info.dir;

    /* Encoded format */
    pjmedia_format_init_video(&attr->enc_fmt, desc->info.fmt_id,
                              720, 480, 30000, 1001);

    /* Decoded format */
    pjmedia_format_init_video(&attr->dec_fmt, desc->info.dec_fmt_id[0],
                              //352, 288, 30000, 1001);
                              720, 576, 30000, 1001);

    /* Decoding fmtp */
    attr->dec_fmtp = desc->dec_fmtp;

    /* Bitrate */
    attr->enc_fmt.det.vid.avg_bps = desc->avg_bps;
    attr->enc_fmt.det.vid.max_bps = desc->max_bps;

    /* MTU */
    attr->enc_mtu = PJMEDIA_MAX_MTU;

    return PJ_SUCCESS;
}
Пример #3
0
/* API: init factory */
static pj_status_t opengl_factory_init(pjmedia_vid_dev_factory *f)
{
    struct opengl_factory *qf = (struct opengl_factory*)f;
    struct opengl_dev_info *qdi;
    unsigned l;
    
    /* Initialize input and output devices here */
    qf->dev_info = (struct opengl_dev_info*)
    pj_pool_calloc(qf->pool, 1, sizeof(struct opengl_dev_info));
    
    qf->dev_count = 0;
    qdi = &qf->dev_info[qf->dev_count++];
    pj_bzero(qdi, sizeof(*qdi));
    strcpy(qdi->info.name, "OpenGL renderer");
    strcpy(qdi->info.driver, "OpenGL");
    qdi->info.dir = PJMEDIA_DIR_RENDER;
    qdi->info.has_callback = PJ_FALSE;
    qdi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT;
    qdi->info.fmt_cnt = PJ_ARRAY_SIZE(opengl_fmts);
    qdi->info.caps |= pjmedia_vid_dev_opengl_imp_get_cap();
	
    for (l = 0; l < PJ_ARRAY_SIZE(opengl_fmts); l++) {
        pjmedia_format *fmt = &qdi->info.fmt[l];
        pjmedia_format_init_video(fmt, opengl_fmts[l], DEFAULT_WIDTH,
                                  DEFAULT_HEIGHT, DEFAULT_FPS, 1);
    }
    
    PJ_LOG(4, (THIS_FILE, "OpenGL device initialized"));
    
    return PJ_SUCCESS;
}
Пример #4
0
/* API: create default device parameter */
static pj_status_t ffmpeg_factory_default_param(pj_pool_t *pool,
                                                pjmedia_vid_dev_factory *f,
					        unsigned index,
					        pjmedia_vid_dev_param *param)
{
    ffmpeg_factory *ff = (ffmpeg_factory*)f;
    ffmpeg_dev_info *info;

    PJ_ASSERT_RETURN(index < ff->dev_count, PJMEDIA_EVID_INVDEV);

    PJ_UNUSED_ARG(pool);

    info = &ff->dev_info[index];

    pj_bzero(param, sizeof(*param));
    param->dir = PJMEDIA_DIR_CAPTURE;
    param->cap_id = index;
    param->rend_id = PJMEDIA_VID_INVALID_DEV;
    param->clock_rate = 0;

    /* Set the device capabilities here */
    param->flags = PJMEDIA_VID_DEV_CAP_FORMAT;
    param->clock_rate = 90000;
    pjmedia_format_init_video(&param->fmt, 0, 320, 240, 25, 1);
    param->fmt.id = info->base.fmt[0].id;

    return PJ_SUCCESS;
}
Пример #5
0
/*
 * Generate default attribute.
 */
static pj_status_t pj_vpx_default_attr(pjmedia_vid_codec_factory *factory,
        const pjmedia_vid_codec_info *info, pjmedia_vid_codec_param *attr) {

    PJ_ASSERT_RETURN(factory==&vpx_factory.base, PJ_EINVAL);
    PJ_ASSERT_RETURN(info && attr, PJ_EINVAL);

    TRACE_((THIS_FILE, "vpx default attr"));


    pj_bzero(attr, sizeof(pjmedia_vid_codec_param));

    /* Scan the requested packings and use the lowest number */
    attr->packing = 1;

    /* Direction */
    attr->dir = PJMEDIA_DIR_ENCODING_DECODING;

    /* Encoded format */
    pjmedia_format_init_video(&attr->enc_fmt, PJMEDIA_FORMAT_VP8,
                              DEFAULT_WIDTH, DEFAULT_HEIGHT,
                              DEFAULT_FPS, 1);

    /* Decoded format */
    pjmedia_format_init_video(&attr->dec_fmt, PJMEDIA_FORMAT_I420,
                              DEFAULT_WIDTH, DEFAULT_HEIGHT,
                              DEFAULT_FPS, 1);

    /* Decoding fmtp */
    attr->dec_fmtp.cnt = 0;

    /* Bitrate */
    attr->enc_fmt.det.vid.avg_bps = DEFAULT_AVG_BITRATE;
    attr->enc_fmt.det.vid.max_bps = DEFAULT_MAX_BITRATE;

    attr->enc_fmtp.cnt = 0;

    /* Encoding MTU */
    attr->enc_mtu = PJMEDIA_MAX_VID_PAYLOAD_SIZE;

    return PJ_SUCCESS;
}
Пример #6
0
/* Get the supported size */
static void v4l2_get_supported_size(int fd,
				    pj_uint32_t fmt_id,
				    pjmedia_vid_dev_info *info)
{
    int i=0;
    pjmedia_rect_size v4l_sizes[] =
    {
	 /* Some webcam doesn't work well using size below 320x240 */
         /*{ 128, 96 },  { 176, 144 },*/ { 320, 240 },   { 352, 240 },
         { 352, 288 },   { 352, 480 },   { 352, 576 },   { 640, 480 },
         { 704, 480 },   { 720, 480 },   { 704, 576 },   { 720, 576 },
         { 800, 600 },   { 1024, 768 },  { 1280, 720 },  { 1280, 960 },
         { 1280, 1024 }, { 1408, 960 },  { 1408, 1152 }, { 1600, 1200 },
         { 1920, 1080 }/*, { 1920, 1088 }, { 2048, 1024 }, { 2048, 1080 },
         { 2048, 1088 }, { 2048, 1536 }, { 2560, 1920 }, { 3616, 1536 },
         { 3672, 1536 }, { 3680, 1536 }, { 3840, 2160 }, { 4096, 2048 },
         { 4096, 2160 }, { 4096, 2304 }*/
    };

    const vid4lin_fmt_map *fmt_map = get_v4l2_format_info(fmt_id);
    if (fmt_map == NULL)
	return;

    for (;i<PJ_ARRAY_SIZE(v4l_sizes) &&
          info->fmt_cnt<PJMEDIA_VID_DEV_INFO_FMT_CNT;
         i++)
    {
	struct v4l2_format v4l2_fmt;
	pj_status_t status;

	pj_bzero(&v4l2_fmt, sizeof(v4l2_fmt));
	v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	v4l2_fmt.fmt.pix.width       = v4l_sizes[i].w;
	v4l2_fmt.fmt.pix.height      = v4l_sizes[i].h;
	v4l2_fmt.fmt.pix.pixelformat = fmt_map->v4l2_fmt_id;
	v4l2_fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
	status = xioctl(fd, VIDIOC_TRY_FMT, &v4l2_fmt);
	if (status != PJ_SUCCESS ||
	    v4l2_fmt.fmt.pix.pixelformat != fmt_map->v4l2_fmt_id ||
	    v4l2_fmt.fmt.pix.width != v4l_sizes[i].w ||
	    v4l2_fmt.fmt.pix.height != v4l_sizes[i].h)
	{
	    continue;
	}

	pjmedia_format_init_video(&info->fmt[info->fmt_cnt++],
				  fmt_id,
				  v4l_sizes[i].w,
				  v4l_sizes[i].h,
				  DEFAULT_FPS, 1);
    }
}
Пример #7
0
static int vidport_test(void)
{
    int i, j, k, l;
    int cap_id, rend_id;
    pjmedia_format_id test_fmts[] = {
        PJMEDIA_FORMAT_RGBA,
        PJMEDIA_FORMAT_I420
    };

    PJ_LOG(3, (THIS_FILE, " Video port tests:"));

    /* Capturer's role: active/passive. */
    for (i = 1; i >= 0; i--) {
	/* Capturer's device has_callback: TRUE/FALSE. */
	for (j = 1; j >= 0; j--) {
	    cap_id = find_device(PJMEDIA_DIR_CAPTURE, j);
	    if (cap_id < 0)
		continue;

	    /* Renderer's device has callback: TRUE/FALSE. */
	    for (k = 1; k >= 0; k--) {
		rend_id = find_device(PJMEDIA_DIR_RENDER, k);
		if (rend_id < 0)
		    continue;

		/* Check various formats to test format conversion. */
		for (l = 0; l < PJ_ARRAY_SIZE(test_fmts); ++l) {
		    pjmedia_format fmt;

		    PJ_LOG(3,(THIS_FILE,
			      "capturer %s (stream: %s) ===> "
			      "renderer %s (stream: %s)",
			      (i? "active": "passive"),
			      (j? "active": "passive"),
			      (i? "passive": "active"),
			      (k? "active": "passive")));

		    pjmedia_format_init_video(&fmt, test_fmts[l],
					      640, 480, 25, 1);
		    capture_render_loopback(i, cap_id, rend_id, &fmt);
		}
	    }
	}
    }

    return 0;
}
Пример #8
0
static int aviplay(pj_pool_t *pool, const char *fname)
{
    pjmedia_vid_port *renderer=NULL;
    pjmedia_vid_port_param param;
    const pjmedia_video_format_info *vfi;
    pjmedia_video_format_detail *vfd;
    pjmedia_snd_port *snd_port = NULL;
    pj_status_t status;
    int rc = 0;
    pjmedia_avi_streams *avi_streams;
    pjmedia_avi_stream *vid_stream, *aud_stream;
    pjmedia_port *vid_port = NULL, *aud_port = NULL;
    pjmedia_vid_codec *codec=NULL;
    avi_port_t avi_port;

    pj_bzero(&avi_port, sizeof(avi_port));

    status = pjmedia_avi_player_create_streams(pool, fname, 0, &avi_streams);
    if (status != PJ_SUCCESS) {
        PJ_PERROR(2,("", status, "    Error playing %s", fname));
        rc = 210;
        goto on_return;
    }

    vid_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams,
                 0,
                 PJMEDIA_TYPE_VIDEO);
    vid_port = pjmedia_avi_stream_get_port(vid_stream);

    if (vid_port) {
        pjmedia_vid_port_param_default(&param);

        status = pjmedia_vid_dev_default_param(pool,
                                               PJMEDIA_VID_DEFAULT_RENDER_DEV,
                                               &param.vidparam);
        if (status != PJ_SUCCESS) {
            rc = 220;
            goto on_return;
        }

        /* Create renderer, set it to active  */
        param.active = PJ_TRUE;
        param.vidparam.dir = PJMEDIA_DIR_RENDER;
        vfd = pjmedia_format_get_video_format_detail(&vid_port->info.fmt,
                PJ_TRUE);
        pjmedia_format_init_video(&param.vidparam.fmt,
                                  vid_port->info.fmt.id,
                                  vfd->size.w, vfd->size.h,
                                  vfd->fps.num, vfd->fps.denum);

        vfi = pjmedia_get_video_format_info(
                  pjmedia_video_format_mgr_instance(),
                  vid_port->info.fmt.id);
        /* Check whether the frame is encoded */
        if (!vfi || vfi->bpp == 0) {
            /* Yes, prepare codec */
            pj_str_t codec_id_st;
            unsigned info_cnt = 1, i, k;
            const pjmedia_vid_codec_info *codec_info;
            pj_str_t port_name = {"codec", 5};
            pj_uint8_t *enc_buf = NULL;
            pj_size_t enc_buf_size = 0;
            pjmedia_vid_dev_info rdr_info;
            pjmedia_port codec_port;
            codec_port_data_t codec_port_data;
            pjmedia_vid_codec_param codec_param;
            struct codec_fmt *codecp = NULL;

            /* Lookup codec */
            for (i = 0; i < sizeof(codec_fmts)/sizeof(codec_fmts[0]); i++) {
                if (vid_port->info.fmt.id == codec_fmts[i].pjmedia_id) {
                    codecp = &codec_fmts[i];
                    break;
                }
            }
            if (!codecp) {
                rc = 242;
                goto on_return;
            }
            pj_cstr(&codec_id_st, codecp->codec_id);
            status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL,
                     &codec_id_st,
                     &info_cnt,
                     &codec_info,
                     NULL);
            if (status != PJ_SUCCESS) {
                rc = 245;
                goto on_return;
            }
            status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info,
                     &codec_param);
            if (status != PJ_SUCCESS) {
                rc = 246;
                goto on_return;
            }

            pjmedia_format_copy(&codec_param.enc_fmt, &param.vidparam.fmt);

            pjmedia_vid_dev_get_info(param.vidparam.rend_id, &rdr_info);
            for (i=0; i<codec_info->dec_fmt_id_cnt; ++i) {
                for (k=0; k<rdr_info.fmt_cnt; ++k) {
                    if (codec_info->dec_fmt_id[i]==(int)rdr_info.fmt[k].id)
                    {
                        param.vidparam.fmt.id = codec_info->dec_fmt_id[i];
                        i = codec_info->dec_fmt_id_cnt;
                        break;
                    }
                }
            }

            /* Open codec */
            status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info,
                     &codec);
            if (status != PJ_SUCCESS) {
                rc = 250;
                goto on_return;
            }

            status = pjmedia_vid_codec_init(codec, pool);
            if (status != PJ_SUCCESS) {
                rc = 251;
                goto on_return;
            }

            pjmedia_format_copy(&codec_param.dec_fmt, &param.vidparam.fmt);
            codec_param.dir = PJMEDIA_DIR_DECODING;
            codec_param.packing = PJMEDIA_VID_PACKING_WHOLE;
            status = pjmedia_vid_codec_open(codec, &codec_param);
            if (status != PJ_SUCCESS) {
                rc = 252;
                goto on_return;
            }

            /* Alloc encoding buffer */
            enc_buf_size =  codec_param.dec_fmt.det.vid.size.w *
                            codec_param.dec_fmt.det.vid.size.h * 4
                            + 16; /*< padding, just in case */
            enc_buf = pj_pool_alloc(pool,enc_buf_size);

            /* Init codec port */
            pj_bzero(&codec_port, sizeof(codec_port));
            status = pjmedia_port_info_init2(&codec_port.info, &port_name,
                                             0x1234,
                                             PJMEDIA_DIR_ENCODING,
                                             &codec_param.dec_fmt);
            if (status != PJ_SUCCESS) {
                rc = 260;
                goto on_return;
            }
            pj_bzero(&codec_port_data, sizeof(codec_port_data));
            codec_port_data.codec = codec;
            codec_port_data.src_port = vid_port;
            codec_port_data.enc_buf = enc_buf;
            codec_port_data.enc_buf_size = enc_buf_size;

            codec_port.get_frame = &codec_get_frame;
            codec_port.port_data.pdata = &codec_port_data;

            /* Check whether we need to convert the decoded frame */
            if (codecp->need_conversion) {
                pjmedia_conversion_param conv_param;

                pjmedia_format_copy(&conv_param.src, &param.vidparam.fmt);
                pjmedia_format_copy(&conv_param.dst, &param.vidparam.fmt);
                conv_param.dst.id = codecp->dst_fmt;
                param.vidparam.fmt.id = conv_param.dst.id;

                status = pjmedia_converter_create(NULL, pool, &conv_param,
                                                  &codec_port_data.conv);
                if (status != PJ_SUCCESS) {
                    rc = 270;
                    goto on_return;
                }
            }

            status = pjmedia_vid_port_create(pool, &param, &renderer);
            if (status != PJ_SUCCESS) {
                rc = 230;
                goto on_return;
            }

            status = pjmedia_vid_port_connect(renderer, &codec_port,
                                              PJ_FALSE);
        } else {
            status = pjmedia_vid_port_create(pool, &param, &renderer);
            if (status != PJ_SUCCESS) {
                rc = 230;
                goto on_return;
            }

            /* Connect avi port to renderer */
            status = pjmedia_vid_port_connect(renderer, vid_port,
                                              PJ_FALSE);
        }

        if (status != PJ_SUCCESS) {
            rc = 240;
            goto on_return;
        }
    }

    aud_stream = pjmedia_avi_streams_get_stream_by_media(avi_streams,
                 0,
                 PJMEDIA_TYPE_AUDIO);
    aud_port = pjmedia_avi_stream_get_port(aud_stream);

    if (aud_port) {
        /* Create sound player port. */
        status = pjmedia_snd_port_create_player(
                     pool,				    /* pool		    */
                     -1,				    /* use default dev.	    */
                     PJMEDIA_PIA_SRATE(&aud_port->info),/* clock rate.	    */
                     PJMEDIA_PIA_CCNT(&aud_port->info), /* # of channels.	    */
                     PJMEDIA_PIA_SPF(&aud_port->info),  /* samples per frame.   */
                     PJMEDIA_PIA_BITS(&aud_port->info), /* bits per sample.	    */
                     0,				    /* options		    */
                     &snd_port			    /* returned port	    */
                 );
        if (status != PJ_SUCCESS) {
            rc = 310;
            goto on_return;
        }

        /* Connect file port to the sound player.
         * Stream playing will commence immediately.
         */
        status = pjmedia_snd_port_connect(snd_port, aud_port);
        if (status != PJ_SUCCESS) {
            rc = 330;
            goto on_return;
        }
    }

    if (vid_port) {
        pjmedia_vid_dev_cb cb;

        pj_bzero(&cb, sizeof(cb));
        avi_port.snd_port = snd_port;
        avi_port.vid_port = renderer;
        avi_port.is_running = PJ_TRUE;
        pjmedia_vid_port_set_cb(renderer, &cb, &avi_port);

        /* subscribe events */
        pjmedia_event_subscribe(NULL, &avi_event_cb, &avi_port,
                                renderer);

        if (snd_port) {
            /* Synchronize video rendering and audio playback */
            pjmedia_vid_port_set_clock_src(
                renderer,
                pjmedia_snd_port_get_clock_src(
                    snd_port, PJMEDIA_DIR_PLAYBACK));
        }


        /* Start video streaming.. */
        status = pjmedia_vid_port_start(renderer);
        if (status != PJ_SUCCESS) {
            rc = 270;
            goto on_return;
        }
    }

    while (!avi_port.is_quitting) {
        pj_thread_sleep(100);
    }

on_return:
    if (snd_port) {
        pjmedia_snd_port_disconnect(snd_port);
        /* Without this sleep, Windows/DirectSound will repeteadly
         * play the last frame during destroy.
         */
        pj_thread_sleep(100);
        pjmedia_snd_port_destroy(snd_port);
    }
    if (renderer) {
        pjmedia_event_unsubscribe(NULL, &avi_event_cb, &avi_port,
                                  renderer);
        pjmedia_vid_port_destroy(renderer);
    }
    if (aud_port)
        pjmedia_port_destroy(aud_port);
    if (vid_port)
        pjmedia_port_destroy(vid_port);
    if (codec) {
        pjmedia_vid_codec_close(codec);
        pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec);
    }

    return rc;
}
/* Scan V4L2 devices */
static pj_status_t v4l2_scan_devs(vid4lin_factory *f)
{
    vid4lin_dev_info vdi[V4L2_MAX_DEVS];
    char dev_name[32];
    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_uint32_t fmt_cap[8];
	int j, fmt_cnt=0;

	pdi = &vdi[f->dev_count];

	snprintf(dev_name, sizeof(dev_name), "/dev/video%d", i);
	if (!pj_file_exists(dev_name))
	    continue;

	fd = v4l2_open(dev_name, O_RDWR, 0);
	if (fd == -1)
	    continue;

	status = xioctl(fd, VIDIOC_QUERYCAP, &pdi->v4l2_cap);
	if (status != PJ_SUCCESS) {
	    PJ_PERROR(4,(THIS_FILE, status, "Error querying %s", dev_name));
	    v4l2_close(fd);
	    continue;
	}

	if ((pdi->v4l2_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
	    v4l2_close(fd);
	    continue;
	}

	PJ_LOG(5,(THIS_FILE, "Found capture device %s", pdi->v4l2_cap.card));
	PJ_LOG(5,(THIS_FILE, "  Enumerating formats:"));
	for (j=0; fmt_cnt<PJ_ARRAY_SIZE(fmt_cap); ++j) {
	    struct v4l2_fmtdesc fdesc;
	    unsigned k;

	    pj_bzero(&fdesc, sizeof(fdesc));
	    fdesc.index = j;
	    fdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

	    status = xioctl(fd, VIDIOC_ENUM_FMT, &fdesc);
	    if (status != PJ_SUCCESS)
		break;

	    for (k=0; k<PJ_ARRAY_SIZE(v4l2_fmt_maps); ++k) {
		if (v4l2_fmt_maps[k].v4l2_fmt_id == fdesc.pixelformat) {
		    fmt_cap[fmt_cnt++] = v4l2_fmt_maps[k].pjmedia_fmt_id;
		    PJ_LOG(5,(THIS_FILE, "   Supported: %s",
			      fdesc.description));
		    break;
		}
	    }
	    if (k==PJ_ARRAY_SIZE(v4l2_fmt_maps)) {
		PJ_LOG(5,(THIS_FILE, "   Unsupported: %s", fdesc.description));
	    }
	}

	v4l2_close(fd);

	if (fmt_cnt==0) {
	    PJ_LOG(5,(THIS_FILE, "    Found no common format"));
	    continue;
	}

	strncpy(pdi->dev_name, dev_name, sizeof(pdi->dev_name));
	pdi->dev_name[sizeof(pdi->dev_name)-1] = '\0';
	strncpy(pdi->info.name, (char*)pdi->v4l2_cap.card,
		sizeof(pdi->info.name));
	pdi->info.name[sizeof(pdi->info.name)-1] = '\0';
	strncpy(pdi->info.driver, DRIVER_NAME, sizeof(pdi->info.driver));
	pdi->info.driver[sizeof(pdi->info.driver)-1] = '\0';
	pdi->info.dir = PJMEDIA_DIR_CAPTURE;
	pdi->info.has_callback = PJ_FALSE;
	pdi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT;

	pdi->info.fmt_cnt = fmt_cnt;
	for (j=0; j<fmt_cnt; ++j) {
	    pjmedia_format_init_video(&pdi->info.fmt[j],
				      fmt_cap[j],
				      DEFAULT_WIDTH,
				      DEFAULT_HEIGHT,
				      DEFAULT_FPS, 1);
	}
	if (j < fmt_cnt)
	    continue;

	f->dev_count++;
    }

    if (f->dev_count == 0)
	return PJ_SUCCESS;

    if (f->dev_count > old_count || f->dev_info == NULL) {
	f->dev_info = (vid4lin_dev_info*)
		      pj_pool_calloc(f->dev_pool,
				     f->dev_count,
				     sizeof(vid4lin_dev_info));
    }
    pj_memcpy(f->dev_info, vdi, f->dev_count * sizeof(vid4lin_dev_info));

    return PJ_SUCCESS;
}
Пример #10
0
/* API: refresh the list of devices */
static pj_status_t and_factory_refresh(pjmedia_vid_dev_factory *ff)
{
    and_factory *f = (and_factory*)ff;
    pj_status_t status = PJ_SUCCESS;

    JNIEnv *jni_env;
    pj_bool_t with_attach, found_front = PJ_FALSE;
    int i, dev_count = 0;

    /* Clean up device info and pool */
    f->dev_count = 0;
    pj_pool_reset(f->dev_pool);
    
    with_attach = jni_get_env(&jni_env);
    
    /* dev_count = PjCameraInfo::GetCameraCount() */
    dev_count = (*jni_env)->CallStaticIntMethod(jni_env, jobjs.cam_info.cls,
						jobjs.cam_info.m_get_cnt);
    if (dev_count < 0) {
        PJ_LOG(3, (THIS_FILE, "Failed to get camera count"));
        status = PJMEDIA_EVID_SYSERR;
        goto on_return;
    }

    /* Start querying device info */
    f->dev_info = (and_dev_info*)
 		  pj_pool_calloc(f->dev_pool, dev_count,
 				 sizeof(and_dev_info));

    for (i = 0; i < dev_count; i++) {
	and_dev_info *adi = &f->dev_info[f->dev_count];
	pjmedia_vid_dev_info *vdi = &adi->info;
        jobject jdev_info;
	jobject jtmp;
	int facing, max_fmt_cnt = PJMEDIA_VID_DEV_INFO_FMT_CNT;

	/* jdev_info = PjCameraInfo::GetCameraInfo(i) */
	jdev_info = (*jni_env)->CallStaticObjectMethod(
					    jni_env,
					    jobjs.cam_info.cls,
					    jobjs.cam_info.m_get_info,
					    i);
	if (jdev_info == NULL)
	    continue;

	/* Get camera facing: 0=back 1=front */
	facing = (*jni_env)->GetIntField(jni_env, jdev_info,
					 jobjs.cam_info.f_facing);
	if (facing < 0)
	    goto on_skip_dev;
	
	/* Set device ID, direction, and has_callback info */
	adi->dev_idx = i;
	vdi->id = f->dev_count;
	vdi->dir = PJMEDIA_DIR_CAPTURE;
	vdi->has_callback = PJ_TRUE;
	vdi->caps = PJMEDIA_VID_DEV_CAP_SWITCH |
		    PJMEDIA_VID_DEV_CAP_ORIENTATION;

	/* Set driver & name info */
	pj_ansi_strncpy(vdi->driver, "Android", sizeof(vdi->driver));
	adi->facing = facing;
	if (facing == 0) {
	    pj_ansi_strncpy(vdi->name, "Back camera", sizeof(vdi->name));
	} else {
	    pj_ansi_strncpy(vdi->name, "Front camera", sizeof(vdi->name));
	}

	/* Get supported sizes */
	jtmp = (*jni_env)->GetObjectField(jni_env, jdev_info,
					  jobjs.cam_info.f_sup_size);
	if (jtmp) {
	    jintArray jiarray = (jintArray*)jtmp;
	    jint *sizes;
	    jsize cnt, j;

	    cnt = (*jni_env)->GetArrayLength(jni_env, jiarray);
	    sizes = (*jni_env)->GetIntArrayElements(jni_env, jiarray, 0);
	    
	    adi->sup_size_cnt = cnt/2;
	    adi->sup_size = pj_pool_calloc(f->dev_pool, adi->sup_size_cnt,
					   sizeof(adi->sup_size[0]));
	    for (j = 0; j < adi->sup_size_cnt; j++) {
		adi->sup_size[j].w = sizes[j*2];
		adi->sup_size[j].h = sizes[j*2+1];
	    }
	    (*jni_env)->ReleaseIntArrayElements(jni_env, jiarray, sizes, 0);
	    (*jni_env)->DeleteLocalRef(jni_env, jtmp);
	} else {
	    goto on_skip_dev;
	}

	/* Get supported formats */
	jtmp = (*jni_env)->GetObjectField(jni_env, jdev_info,
					  jobjs.cam_info.f_sup_fmt);
	if (jtmp) {
	    jintArray jiarray = (jintArray*)jtmp;
	    jint *fmts;
	    jsize cnt, j;
	    pj_bool_t has_i420 = PJ_FALSE;

	    cnt = (*jni_env)->GetArrayLength(jni_env, jiarray);
	    fmts = (*jni_env)->GetIntArrayElements(jni_env, jiarray, 0);
	    for (j = 0; j < cnt; j++) {
		int k;
		pjmedia_format_id fmt = and_fmt_to_pj((pj_uint32_t)fmts[j]);
		
		/* Check for any duplicate */
		for (k = 0; k < vdi->fmt_cnt; k++) {
		    if (fmt == 0 || fmt == vdi->fmt[k].id) {
			fmt = 0;
			break;
		    }
		}

		/* Make sure we recognize this format */
		if (fmt == 0)
		    continue;

		/* Check formats for I420 conversion */
		if (fmt == PJMEDIA_FORMAT_I420) has_i420 = PJ_TRUE;
		else if (fmt == PJMEDIA_FORMAT_YV12) adi->has_yv12 = PJ_TRUE;
		else if (fmt == PJMEDIA_FORMAT_NV21) adi->has_nv21 = PJ_TRUE;

		for (k = 0; k < adi->sup_size_cnt &&
			    vdi->fmt_cnt < max_fmt_cnt-1; k++)
		{
		    /* Landscape video */
		    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++],
					      fmt,
					      adi->sup_size[k].w,
					      adi->sup_size[k].h,
					      DEFAULT_FPS, 1);
		    /* Portrait video */
		    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++],
					      fmt,
					      adi->sup_size[k].h,
					      adi->sup_size[k].w,
					      DEFAULT_FPS, 1);
		}
	    }
	    (*jni_env)->ReleaseIntArrayElements(jni_env, jiarray, fmts,
						JNI_ABORT);
	    (*jni_env)->DeleteLocalRef(jni_env, jtmp);

	    /* Pretend to support I420/IYUV, only if we support YV12/NV21 */
	    if (!has_i420 && (adi->has_yv12 || adi->has_nv21) &&
		vdi->fmt_cnt < PJ_ARRAY_SIZE(vdi->fmt))
	    {
		int k;
		adi->forced_i420 = PJ_TRUE;
		for (k = 0; k < adi->sup_size_cnt &&
			    vdi->fmt_cnt < max_fmt_cnt-1; k++)
		{
		    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++],
					      PJMEDIA_FORMAT_I420,
					      adi->sup_size[k].w,
					      adi->sup_size[k].h,
					      DEFAULT_FPS, 1);
		    pjmedia_format_init_video(&vdi->fmt[vdi->fmt_cnt++],
					      PJMEDIA_FORMAT_I420,
					      adi->sup_size[k].h,
					      adi->sup_size[k].w,
					      DEFAULT_FPS, 1);
		}
	    }
	} else {
	    goto on_skip_dev;
	}
	
	/* If this is front camera, set it as first/default (if not yet) */
	if (facing == 1) {
	    if (!found_front && f->dev_count > 0) {
		/* Swap this front cam info with one whose idx==0 */
	        and_dev_info tmp_adi;
		pj_memcpy(&tmp_adi, &f->dev_info[0], sizeof(tmp_adi));
		pj_memcpy(&f->dev_info[0], adi, sizeof(tmp_adi));
		pj_memcpy(adi, &tmp_adi, sizeof(tmp_adi));
		f->dev_info[0].info.id = 0;
		f->dev_info[f->dev_count].info.id = f->dev_count;
	    }
	    found_front = PJ_TRUE;
	}
	
	f->dev_count++;

    on_skip_dev:
	(*jni_env)->DeleteLocalRef(jni_env, jdev_info);
    }

    PJ_LOG(4, (THIS_FILE,
	       "Android video capture initialized with %d device(s):",
	       f->dev_count));
    for (i = 0; i < f->dev_count; i++) {
	and_dev_info *adi = &f->dev_info[i];
	char tmp_str[2048], *p;
	int j, plen, slen;
	PJ_LOG(4, (THIS_FILE, "%2d: %s", i, f->dev_info[i].info.name));

	/* Print supported formats */
	p = tmp_str;
	plen = sizeof(tmp_str);
	for (j = 0; j < adi->info.fmt_cnt; j++) {
	    char tmp_str2[5];
	    const pjmedia_video_format_detail *vfd =
		pjmedia_format_get_video_format_detail(&adi->info.fmt[j], 0);
	    pjmedia_fourcc_name(adi->info.fmt[j].id, tmp_str2);
	    slen = pj_ansi_snprintf(p, plen, "%s/%dx%d ",
				    tmp_str2, vfd->size.w, vfd->size.h);
	    if (slen < 0 || slen >= plen) break;
	    plen -= slen;
	    p += slen;
	}
	PJ_LOG(4, (THIS_FILE, "     supported format = %s", tmp_str));
    }

on_return:
    jni_detach_env(with_attach);
    return status;
}
Пример #11
0
int CCameraPjsip::OnOpen(VideoInfo* pVideoInfo)
{
    int nRet = 0;
    pj_status_t status = PJ_FALSE;
    
    if (m_pVidDevStream)
    {
        LOG_MODEL_ERROR("CCamera", "camera has opened");
        return -1;
    }

    pj_caching_pool_init(&m_Caching_pool, &pj_pool_factory_default_policy, 0);
    pj_pool_t* pPool = pj_pool_create(&m_Caching_pool.factory,
        "carmeraPara", 1000, 1000, NULL);
    if (NULL == pPool)
    {
        LOG_MODEL_ERROR("CCamera", "pj_pool_create fail");
        return -2;
    }
    pjmedia_vid_dev_param param;
    status = pjmedia_vid_dev_default_param(pPool, m_nIndex, &param);
    if (PJ_SUCCESS != status)
    {
        LOG_MODEL_ERROR("CCamera", "pjmedia_vid_dev_default_param fail");
        pj_pool_release(pPool);
        return -3;
    }
    pj_pool_release(pPool);

    if (param.fmt.detail_type != PJMEDIA_FORMAT_DETAIL_VIDEO) {
        LOG_MODEL_ERROR("CCamera", "deivce isn't video capture");
        return -4;
    }

    if (pVideoInfo)
    {
        pjmedia_format fmt;
        pjmedia_format_init_video(&fmt, pVideoInfo->Format,
            pVideoInfo->nWidth,
            pVideoInfo->nHeight,
            pVideoInfo->nRatio,
            1
            );
        param.fmt = fmt;
        m_VideoInfo = *pVideoInfo;
    }
    param.dir = PJMEDIA_DIR_CAPTURE;
    
    status = pjmedia_vid_dev_stream_create(&param, &m_VidDevCb,
        this, &m_pVidDevStream);
    if (PJ_SUCCESS != status)
    {
        LOG_MODEL_ERROR("CCamera", "pjmedia_vid_dev_stream_create faile");
        return -5;
    }
    //检查设备指定的格式  
    pjmedia_video_format_detail *vfd;
    vfd = pjmedia_format_get_video_format_detail(&param.fmt, PJ_FALSE);
    if (vfd == NULL)
    {
        LOG_MODEL_ERROR("CCamera", "deivce don't contains the format");
        Close();
        return -6;
    }
    m_VideoInfo.nWidth = vfd->size.w;
    m_VideoInfo.nHeight = vfd->size.h;
    m_VideoInfo.nRatio = vfd->fps.num;
    m_VideoInfo.Format = (VideoFormat) param.fmt.id;

    return nRet;
}