/* API: create stream */ pj_status_t pjmedia_vid_dev_opengl_imp_create_stream(pj_pool_t *pool, pjmedia_vid_dev_param *param, const pjmedia_vid_dev_cb *cb, void *user_data, pjmedia_vid_dev_stream **p_vid_strm) { struct andgl_stream *strm; const pjmedia_video_format_detail *vfd; pj_status_t status = PJ_SUCCESS; strm = PJ_POOL_ZALLOC_T(pool, struct andgl_stream); pj_memcpy(&strm->param, param, sizeof(*param)); strm->pool = pool; pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); strm->user_data = user_data; strm->display = EGL_NO_DISPLAY; vfd = pjmedia_format_get_video_format_detail(&strm->param.fmt, PJ_TRUE); strm->ts_inc = PJMEDIA_SPF2(param->clock_rate, &vfd->fps, 1); /* Set video format */ status = andgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_FORMAT, ¶m->fmt); if (status != PJ_SUCCESS) goto on_error; status = job_queue_create(pool, &strm->jq); if (status != PJ_SUCCESS) goto on_error; if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { status = andgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW, ¶m->window); } if (status != PJ_SUCCESS) { PJ_LOG(3, (THIS_FILE, "Failed to initialize OpenGL with the specified" " output window")); goto on_error; } PJ_LOG(4, (THIS_FILE, "Android OpenGL ES renderer successfully created")); /* Done */ strm->base.op = &stream_op; *p_vid_strm = &strm->base; return PJ_SUCCESS; on_error: andgl_stream_destroy((pjmedia_vid_dev_stream *)strm); return status; }
/* API: create stream */ static pj_status_t and_factory_create_stream( pjmedia_vid_dev_factory *ff, pjmedia_vid_dev_param *param, const pjmedia_vid_dev_cb *cb, void *user_data, pjmedia_vid_dev_stream **p_vid_strm) { and_factory *f = (and_factory*)ff; pj_pool_t *pool; and_stream *strm; and_dev_info *adi; const pjmedia_video_format_detail *vfd; const pjmedia_video_format_info *vfi; pjmedia_video_apply_fmt_param vafp; pj_uint32_t and_fmt; unsigned convert_to_i420 = 0; pj_status_t status = PJ_SUCCESS; JNIEnv *jni_env; pj_bool_t with_attach; jobject jcam; 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_bzero(&vafp, sizeof(vafp)); adi = &f->dev_info[param->cap_id]; vfd = pjmedia_format_get_video_format_detail(¶m->fmt, PJ_TRUE); vfi = pjmedia_get_video_format_info(NULL, param->fmt.id); if (param->fmt.id == PJMEDIA_FORMAT_I420 && adi->forced_i420) { /* Not really support I420, need to convert it from YV12/NV21 */ if (adi->has_nv21) { and_fmt = pj_fmt_to_and(PJMEDIA_FORMAT_NV21); convert_to_i420 = 1; } else if (adi->has_yv12) { and_fmt = pj_fmt_to_and(PJMEDIA_FORMAT_YV12); convert_to_i420 = 2; } else pj_assert(!"Bug!"); } else { and_fmt = pj_fmt_to_and(param->fmt.id); } if (!vfi || !and_fmt) return PJMEDIA_EVID_BADFORMAT; vafp.size = vfd->size; if (vfi->apply_fmt(vfi, &vafp) != PJ_SUCCESS) return PJMEDIA_EVID_BADFORMAT; /* Create and Initialize stream descriptor */ pool = pj_pool_create(f->pf, "and-dev", 512, 512, NULL); PJ_ASSERT_RETURN(pool != NULL, PJ_ENOMEM); strm = PJ_POOL_ZALLOC_T(pool, and_stream); pj_memcpy(&strm->param, param, sizeof(*param)); strm->pool = pool; strm->factory = f; pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); strm->user_data = user_data; pj_memcpy(&strm->vafp, &vafp, sizeof(vafp)); strm->ts_inc = PJMEDIA_SPF2(param->clock_rate, &vfd->fps, 1); /* Allocate buffer for YV12 -> I420 conversion */ if (convert_to_i420) { pj_assert(vfi->plane_cnt > 1); strm->convert_to_i420 = convert_to_i420; strm->convert_buf = pj_pool_alloc(pool, vafp.plane_bytes[1]); } /* Native preview */ if (param->flags & PJMEDIA_VID_DEV_CAP_INPUT_PREVIEW) { } with_attach = jni_get_env(&jni_env); /* Instantiate PjCamera */ strm->cam_size.w = (vfd->size.w > vfd->size.h? vfd->size.w: vfd->size.h); strm->cam_size.h = (vfd->size.w > vfd->size.h? vfd->size.h: vfd->size.w); jcam = (*jni_env)->NewObject(jni_env, jobjs.cam.cls, jobjs.cam.m_init, adi->dev_idx, /* idx */ strm->cam_size.w, /* w */ strm->cam_size.h, /* h */ and_fmt, /* fmt */ vfd->fps.num*1000/ vfd->fps.denum, /* fps */ (jlong)(intptr_t)strm, /* user data */ NULL /* SurfaceView */ ); if (jcam == NULL) { PJ_LOG(3, (THIS_FILE, "Unable to create PjCamera instance")); status = PJMEDIA_EVID_SYSERR; goto on_return; } strm->jcam = (jobject)(*jni_env)->NewGlobalRef(jni_env, jcam); (*jni_env)->DeleteLocalRef(jni_env, jcam); if (strm->jcam == NULL) { PJ_LOG(3, (THIS_FILE, "Unable to create global ref to PjCamera")); status = PJMEDIA_EVID_SYSERR; goto on_return; } /* Video orientation. * If we send in portrait, we need to set up orientation converter * as well. */ if ((param->flags & PJMEDIA_VID_DEV_CAP_ORIENTATION) || (vfd->size.h > vfd->size.w)) { if (param->orient == PJMEDIA_ORIENT_UNKNOWN) param->orient = PJMEDIA_ORIENT_NATURAL; and_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_ORIENTATION, ¶m->orient); } on_return: jni_detach_env(with_attach); /* Success */ if (status == PJ_SUCCESS) { strm->base.op = &stream_op; *p_vid_strm = &strm->base; } return status; }