Example #1
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);
    }
}
/* API: create stream */
static pj_status_t vid4lin_factory_create_stream(pjmedia_vid_dev_factory *f,
				      pjmedia_vid_dev_param *param,
				      const pjmedia_vid_dev_cb *cb,
				      void *user_data,
				      pjmedia_vid_dev_stream **p_vid_strm)
{
    vid4lin_factory *cf = (vid4lin_factory*)f;
    pj_pool_t *pool;
    vid4lin_stream *stream;
    vid4lin_dev_info *vdi;
    const vid4lin_fmt_map *fmt_map;
    const pjmedia_video_format_info *fmt_info;
    pjmedia_video_format_detail *vfd;
    pj_status_t status = PJ_SUCCESS;


    PJ_ASSERT_RETURN(f && param && p_vid_strm, PJ_EINVAL);
    PJ_ASSERT_RETURN(param->fmt.type == PJMEDIA_TYPE_VIDEO &&
		     param->fmt.detail_type == PJMEDIA_FORMAT_DETAIL_VIDEO &&
                     param->dir == PJMEDIA_DIR_CAPTURE,
		     PJ_EINVAL);
    PJ_ASSERT_RETURN(param->cap_id >= 0 && param->cap_id < cf->dev_count,
		     PJMEDIA_EVID_INVDEV);

    fmt_info = pjmedia_get_video_format_info(NULL, param->fmt.id);
    if (!fmt_info || (fmt_map=get_v4l2_format_info(param->fmt.id))==NULL)
        return PJMEDIA_EVID_BADFORMAT;

    vdi = &cf->dev_info[param->cap_id];
    vfd = pjmedia_format_get_video_format_detail(&param->fmt, PJ_TRUE);

    /* Create and Initialize stream descriptor */
    pool = pj_pool_create(cf->pf, vdi->info.name, 512, 512, NULL);
    PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM);

    stream = PJ_POOL_ZALLOC_T(pool, vid4lin_stream);
    pj_memcpy(&stream->param, param, sizeof(*param));
    stream->pool = pool;
    pj_memcpy(&stream->vid_cb, cb, sizeof(*cb));
    strncpy(stream->name, vdi->info.name, sizeof(stream->name));
    stream->name[sizeof(stream->name)-1] = '\0';
    stream->user_data = user_data;
    stream->fd = INVALID_FD;

    stream->fd = v4l2_open(vdi->dev_name, O_RDWR, 0);
    if (stream->fd < 0)
	goto on_error;

    status = vid4lin_stream_init_fmt(stream, param, fmt_map->v4l2_fmt_id);
    if (status != PJ_SUCCESS)
	goto on_error;

    if (vdi->v4l2_cap.capabilities & V4L2_CAP_STREAMING)
	status = vid4lin_stream_init_streaming(stream);

    if (status!=PJ_SUCCESS && vdi->v4l2_cap.capabilities & V4L2_CAP_STREAMING)
	status = vid4lin_stream_init_streaming_user(stream);

    if (status!=PJ_SUCCESS && vdi->v4l2_cap.capabilities & V4L2_CAP_READWRITE)
	status = vid4lin_stream_init_read_write(stream);

    if (status != PJ_SUCCESS) {
	PJ_LOG(1,(THIS_FILE, "Error: unable to initiate I/O on %s",
		  stream->name));
	goto on_error;
    }

    /* Done */
    stream->base.op = &stream_op;
    *p_vid_strm = &stream->base;

    return PJ_SUCCESS;

on_error:
    if (status == PJ_SUCCESS)
	status = PJ_RETURN_OS_ERROR(errno);

    vid4lin_stream_destroy(&stream->base);
    return status;
}