- Timestamp:
- Apr 22, 2014 5:04:43 AM (11 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia-videodev/opengl_dev.h
r4812 r4821 22 22 #include <pjmedia-videodev/videodev_imp.h> 23 23 24 /* OpenGL implementation on each platform needs to implement th is and25 * stream operations.24 /* OpenGL implementation on each platform needs to implement these functions 25 * and stream operations. 26 26 */ 27 /* Get capabilities of the implementation */ 28 int pjmedia_vid_dev_opengl_imp_get_cap(void); 29 30 /* Create OpenGL stream */ 27 31 pj_status_t 28 32 pjmedia_vid_dev_opengl_imp_create_stream(pj_pool_t *pool, … … 32 36 pjmedia_vid_dev_stream **p_vid_strm); 33 37 38 /****************************************************************************/ 34 39 /* OpenGL buffers opaque structure. */ 35 40 typedef struct gl_buffers gl_buffers; -
pjproject/trunk/pjmedia/src/pjmedia-videodev/ios_opengl_dev.m
r4812 r4821 63 63 pj_timestamp frame_ts; 64 64 unsigned ts_inc; 65 pjmedia_rect_size vid_size; 65 66 66 67 gl_buffers *gl_buf; … … 69 70 CVOpenGLESTextureCacheRef vid_texture; 70 71 CVImageBufferRef pb; 72 void *pb_addr; 71 73 CVOpenGLESTextureRef texture; 72 74 }; … … 101 103 }; 102 104 105 int pjmedia_vid_dev_opengl_imp_get_cap(void) 106 { 107 return PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW | 108 PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE | 109 PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION | 110 PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE | 111 PJMEDIA_VID_DEV_CAP_ORIENTATION; 112 } 113 103 114 static iosgl_fmt_info* get_iosgl_format_info(pjmedia_format_id id) 104 115 { … … 175 186 const pjmedia_video_format_detail *vfd; 176 187 pj_status_t status = PJ_SUCCESS; 177 iosgl_fmt_info *ifi; 178 179 if (!(ifi = get_iosgl_format_info(param->fmt.id))) 180 return PJMEDIA_EVID_BADFORMAT; 188 CGRect rect; 189 CVReturn err; 181 190 182 191 strm = PJ_POOL_ZALLOC_T(pool, struct iosgl_stream); … … 189 198 strm->ts_inc = PJMEDIA_SPF2(param->clock_rate, &vfd->fps, 1); 190 199 191 if (param->dir & PJMEDIA_DIR_RENDER) { 192 CVReturn err; 193 UIWindow *window; 194 CGRect rect; 195 196 if ((param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) && 197 param->window.info.ios.window) 198 { 199 /* Get output window handle provided by the application */ 200 window = (UIWindow *)param->window.info.ios.window; 201 rect = window.bounds; 202 } else { 203 rect = CGRectMake(0, 0, strm->param.disp_size.w, 204 strm->param.disp_size.h); 205 } 206 207 strm->gl_view = [[GLView alloc] initWithFrame:rect]; 208 if (!strm->gl_view) 209 return PJ_ENOMEM; 210 strm->gl_view->stream = strm; 211 212 /* Perform OpenGL buffer initializations in the main thread. */ 213 strm->status = PJ_SUCCESS; 214 [strm->gl_view performSelectorOnMainThread:@selector(init_buffers) 215 withObject:nil waitUntilDone:YES]; 216 if ((status = strm->status) != PJ_SUCCESS) { 217 PJ_LOG(3, (THIS_FILE, "Unable to create and init OpenGL buffers")); 218 goto on_error; 219 } 220 221 /* Create a new CVOpenGLESTexture cache */ 222 err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, 223 strm->ogl_context, NULL, 224 &strm->vid_texture); 225 if (err) { 226 PJ_LOG(3, (THIS_FILE, "Unable to create OpenGL texture cache %d", 227 err)); 228 status = PJMEDIA_EVID_SYSERR; 229 goto on_error; 230 } 231 232 PJ_LOG(4, (THIS_FILE, "iOS OpenGL ES renderer successfully created")); 200 /* If OUTPUT_RESIZE flag is not used, set display size to default */ 201 if (!(param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE)) { 202 pj_bzero(&strm->param.disp_size, sizeof(strm->param.disp_size)); 203 } 204 205 /* Set video format */ 206 status = iosgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_FORMAT, 207 ¶m->fmt); 208 if (status != PJ_SUCCESS) 209 goto on_error; 210 211 rect = CGRectMake(0, 0, strm->param.disp_size.w, strm->param.disp_size.h); 212 strm->gl_view = [[GLView alloc] initWithFrame:rect]; 213 if (!strm->gl_view) 214 return PJ_ENOMEM; 215 strm->gl_view->stream = strm; 216 217 /* Perform OpenGL buffer initializations in the main thread. */ 218 strm->status = PJ_SUCCESS; 219 [strm->gl_view performSelectorOnMainThread:@selector(init_buffers) 220 withObject:nil waitUntilDone:YES]; 221 if ((status = strm->status) != PJ_SUCCESS) { 222 PJ_LOG(3, (THIS_FILE, "Unable to create and init OpenGL buffers")); 223 goto on_error; 224 } 225 226 /* Create a new CVOpenGLESTexture cache */ 227 err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, 228 strm->ogl_context, NULL, 229 &strm->vid_texture); 230 if (err) { 231 PJ_LOG(3, (THIS_FILE, "Unable to create OpenGL texture cache %d", 232 err)); 233 status = PJMEDIA_EVID_SYSERR; 234 goto on_error; 233 235 } 234 236 235 237 /* Apply the remaining settings */ 236 /* 237 if (param->flags & PJMEDIA_VID_DEV_CAP_INPUT_SCALE) { 238 iosgl_stream_set_cap(&strm->base, 239 PJMEDIA_VID_DEV_CAP_INPUT_SCALE, 240 ¶m->fmt); 241 } 242 */ 238 if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 239 iosgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW, 240 param->window.info.ios.window); 241 } 242 if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION) { 243 iosgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION, 244 ¶m->window_pos); 245 } 246 if (param->flags & PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE) { 247 iosgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE, 248 ¶m->window_hide); 249 } 250 if (param->flags & PJMEDIA_VID_DEV_CAP_ORIENTATION) { 251 iosgl_stream_set_cap(&strm->base, PJMEDIA_VID_DEV_CAP_ORIENTATION, 252 ¶m->orient); 253 } 254 255 PJ_LOG(4, (THIS_FILE, "iOS OpenGL ES renderer successfully created")); 256 243 257 /* Done */ 244 258 strm->base.op = &stream_op; … … 283 297 PJ_ASSERT_RETURN(s && pval, PJ_EINVAL); 284 298 285 if (cap==PJMEDIA_VID_DEV_CAP_INPUT_SCALE) { 286 return PJMEDIA_EVID_INVCAP; 287 } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 299 if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 288 300 pjmedia_vid_dev_hwnd *wnd = (pjmedia_vid_dev_hwnd *)pval; 289 301 wnd->info.ios.window = strm->gl_view; … … 305 317 PJ_ASSERT_RETURN(s && pval, PJ_EINVAL); 306 318 307 if (cap==PJMEDIA_VID_DEV_CAP_INPUT_SCALE) { 319 if (cap==PJMEDIA_VID_DEV_CAP_FORMAT) { 320 const pjmedia_video_format_info *vfi; 321 pjmedia_video_format_detail *vfd; 322 pjmedia_format *fmt = (pjmedia_format *)pval; 323 iosgl_fmt_info *ifi; 324 325 if (!(ifi = get_iosgl_format_info(fmt->id))) 326 return PJMEDIA_EVID_BADFORMAT; 327 328 vfi = pjmedia_get_video_format_info(pjmedia_video_format_mgr_instance(), 329 fmt->id); 330 if (!vfi) 331 return PJMEDIA_EVID_BADFORMAT; 332 333 pjmedia_format_copy(&strm->param.fmt, fmt); 334 335 vfd = pjmedia_format_get_video_format_detail(fmt, PJ_TRUE); 336 pj_memcpy(&strm->vid_size, &vfd->size, sizeof(vfd->size)); 337 if (strm->param.disp_size.w == 0 || strm->param.disp_size.h == 0) 338 pj_memcpy(&strm->param.disp_size, &vfd->size, sizeof(vfd->size)); 339 340 /* Invalidate the buffer */ 341 if (strm->pb) { 342 CVPixelBufferRelease(strm->pb); 343 strm->pb = NULL; 344 } 345 308 346 return PJ_SUCCESS; 347 } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { 348 UIView *view = (UIView *)pval; 349 strm->param.window.info.ios.window = (void *)pval; 350 dispatch_async(dispatch_get_main_queue(), 351 ^{[view addSubview:strm->gl_view];}); 352 return PJ_SUCCESS; 353 } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE) { 354 pj_memcpy(&strm->param.disp_size, pval, sizeof(strm->param.disp_size)); 355 dispatch_async(dispatch_get_main_queue(), ^{ 356 strm->gl_view.bounds = CGRectMake(0, 0, strm->param.disp_size.w, 357 strm->param.disp_size.h); 358 }); 359 return PJ_SUCCESS; 360 } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_POSITION) { 361 pj_memcpy(&strm->param.window_pos, pval, sizeof(strm->param.window_pos)); 362 dispatch_async(dispatch_get_main_queue(), ^{ 363 strm->gl_view.center = CGPointMake(strm->param.window_pos.x + 364 strm->param.disp_size.w/2.0, 365 strm->param.window_pos.y + 366 strm->param.disp_size.h/2.0); 367 }); 368 return PJ_SUCCESS; 369 } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_HIDE) { 370 dispatch_async(dispatch_get_main_queue(), ^{ 371 strm->gl_view.hidden = (BOOL)(*((pj_bool_t *)pval)); 372 }); 373 return PJ_SUCCESS; 374 } else if (cap == PJMEDIA_VID_DEV_CAP_ORIENTATION) { 375 pj_memcpy(&strm->param.orient, pval, sizeof(strm->param.orient)); 376 if (strm->param.orient == PJMEDIA_ORIENT_UNKNOWN) 377 return PJ_SUCCESS; 378 dispatch_async(dispatch_get_main_queue(), ^{ 379 strm->gl_view.transform = 380 CGAffineTransformMakeRotation(((int)strm->param.orient-1) * 381 -M_PI_2); 382 }); 383 return PJ_SUCCESS; 309 384 } 310 385 … … 331 406 CVReturn err; 332 407 333 err = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, 334 stream->param.disp_size.w, 335 stream->param.disp_size.h, 336 kCVPixelFormatType_32BGRA, 337 frame->buf, 338 stream->param.disp_size.w * 4, 339 NULL, NULL, NULL, &stream->pb); 340 if (err) { 341 PJ_LOG(3, (THIS_FILE, "Unable to create pixel buffer %d", err)); 342 return PJMEDIA_EVID_SYSERR; 408 /* Pixel buffer will only create a wrapper for the frame's buffer, 409 * so if the frame buffer changes, we have to recreate pb 410 */ 411 if (!stream->pb || (frame->buf && stream->pb_addr != frame->buf)) { 412 if (stream->pb) { 413 CVPixelBufferRelease(stream->pb); 414 stream->pb = NULL; 415 } 416 err = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, 417 stream->vid_size.w, 418 stream->vid_size.h, 419 kCVPixelFormatType_32BGRA, 420 frame->buf, 421 stream->vid_size.w * 4, 422 NULL, NULL, NULL, &stream->pb); 423 if (err) { 424 PJ_LOG(3, (THIS_FILE, "Unable to create pixel buffer %d", err)); 425 return PJMEDIA_EVID_SYSERR; 426 } 427 stream->pb_addr = frame->buf; 343 428 } 344 429 … … 348 433 stream->pb, NULL, 349 434 GL_TEXTURE_2D, GL_RGBA, 350 stream-> param.disp_size.w,351 stream-> param.disp_size.h,435 stream->vid_size.w, 436 stream->vid_size.h, 352 437 GL_BGRA, 353 438 GL_UNSIGNED_BYTE, … … 355 440 if (!stream->texture || err) { 356 441 PJ_LOG(3, (THIS_FILE, "Unable to create OpenGL texture %d", err)); 357 CVPixelBufferRelease(stream->pb);358 442 return PJMEDIA_EVID_SYSERR; 359 443 } … … 370 454 CVOpenGLESTextureCacheFlush(stream->vid_texture, 0); 371 455 CFRelease(stream->texture); 372 CVPixelBufferRelease(stream->pb);373 456 374 457 return PJ_SUCCESS; … … 396 479 397 480 iosgl_stream_stop(strm); 481 482 if (stream->pb) { 483 CVPixelBufferRelease(stream->pb); 484 stream->pb = NULL; 485 } 398 486 399 487 if (stream->vid_texture) { -
pjproject/trunk/pjmedia/src/pjmedia-videodev/opengl_dev.c
r4812 r4821 337 337 struct opengl_factory *qf = (struct opengl_factory*)f; 338 338 struct opengl_dev_info *qdi; 339 unsigned i,l;339 unsigned l; 340 340 341 341 /* Initialize input and output devices here */ … … 350 350 qdi->info.dir = PJMEDIA_DIR_RENDER; 351 351 qdi->info.has_callback = PJ_FALSE; 352 qdi->info.caps = PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW; 353 354 for (i = 0; i < qf->dev_count; i++) { 355 qdi = &qf->dev_info[i]; 356 qdi->info.fmt_cnt = PJ_ARRAY_SIZE(opengl_fmts); 357 qdi->info.caps |= PJMEDIA_VID_DEV_CAP_FORMAT; 352 qdi->info.caps = PJMEDIA_VID_DEV_CAP_FORMAT; 353 qdi->info.fmt_cnt = PJ_ARRAY_SIZE(opengl_fmts); 354 qdi->info.caps |= pjmedia_vid_dev_opengl_imp_get_cap(); 358 355 359 for (l = 0; l < PJ_ARRAY_SIZE(opengl_fmts); l++) { 360 pjmedia_format *fmt = &qdi->info.fmt[l]; 361 pjmedia_format_init_video(fmt, 362 opengl_fmts[l], 363 DEFAULT_WIDTH, 364 DEFAULT_HEIGHT, 365 DEFAULT_FPS, 1); 366 } 367 } 368 369 PJ_LOG(4, (THIS_FILE, "OpenGL initialized with %d devices", 370 qf->dev_count)); 356 for (l = 0; l < PJ_ARRAY_SIZE(opengl_fmts); l++) { 357 pjmedia_format *fmt = &qdi->info.fmt[l]; 358 pjmedia_format_init_video(fmt, opengl_fmts[l], DEFAULT_WIDTH, 359 DEFAULT_HEIGHT, DEFAULT_FPS, 1); 360 } 361 362 PJ_LOG(4, (THIS_FILE, "OpenGL device initialized")); 371 363 372 364 return PJ_SUCCESS;
Note: See TracChangeset
for help on using the changeset viewer.