- Timestamp:
- Aug 8, 2011 5:41:19 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia-videodev/sdl_dev.c
r3676 r3689 28 28 # include "TargetConditionals.h" 29 29 # include <Foundation/Foundation.h> 30 #endif /* PJ_DARWINOS */ 30 # define SDL_USE_ONE_THREAD_PER_DISPLAY 1 31 #elif defined(PJ_WIN32) && PJ_WIN32 != 0 32 # define SDL_USE_ONE_THREAD_PER_DISPLAY 1 33 #else 34 # define SDL_USE_ONE_THREAD_PER_DISPLAY 0 35 #endif 31 36 32 37 #include <SDL.h> … … 35 40 # include "SDL_opengl.h" 36 41 # define OPENGL_DEV_IDX 1 37 #else /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */38 # define OPENGL_DEV_IDX -99939 42 #endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 40 43 … … 100 103 @public 101 104 struct sdl_stream *strm; 105 struct sdl_factory *sf; 106 pjmedia_event_type ev_type; 107 pj_status_t status; 102 108 } 103 109 … … 118 124 }; 119 125 126 /* Linked list of streams */ 127 struct stream_list 128 { 129 PJ_DECL_LIST_MEMBER(struct stream_list); 130 struct sdl_stream *stream; 131 }; 132 120 133 /* sdl_ factory */ 121 134 struct sdl_factory … … 127 140 unsigned dev_count; 128 141 struct sdl_dev_info *dev_info; 129 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 130 NSAutoreleasePool *apool; 131 SDLDelegate *delegate; 132 #endif /* PJ_DARWINOS */ 142 143 pj_thread_t *sdl_thread; /**< SDL thread. */ 144 pj_status_t status; 145 pj_sem_t *sem; 146 pj_mutex_t *mutex; 147 struct stream_list streams; 148 pj_bool_t is_quitting; 133 149 }; 134 150 … … 144 160 145 161 pj_thread_t *sdl_thread; /**< SDL thread. */ 162 pj_bool_t is_initialized; 146 163 pj_bool_t is_quitting; 164 pj_bool_t is_destroyed; 147 165 pj_bool_t is_running; 148 166 pj_bool_t render_exited; … … 151 169 pjmedia_rect_size *new_disp_size; 152 170 pj_timestamp last_ts; 171 pjmedia_frame frame; 172 pj_size_t frame_buf_size; 173 struct stream_list list_entry; 174 struct sdl_factory *sf; 153 175 154 176 #if SDL_VERSION_ATLEAST(1,3,0) … … 169 191 GLuint texture; 170 192 #endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 171 void *tex_buf;172 pj_size_t tex_buf_size;173 174 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0175 NSAutoreleasePool *apool;176 SDLDelegate *delegate;177 const pjmedia_frame *frame;178 #endif /* PJ_DARWINOS */179 180 /* For frame conversion */181 pjmedia_converter *conv;182 pjmedia_conversion_param conv_param;183 pjmedia_frame conv_buf;184 193 185 194 pjmedia_video_apply_fmt_param vafp; 186 195 }; 187 196 197 struct sdl_dev_t 198 { 199 struct sdl_factory *sf; 200 struct sdl_stream *strm; 201 }; 188 202 189 203 /* Prototypes */ … … 220 234 static pj_status_t sdl_stream_destroy(pjmedia_vid_dev_stream *strm); 221 235 236 static int sdl_thread(void * data); 237 222 238 /* Operations */ 223 239 static pjmedia_vid_dev_factory_op factory_op = … … 265 281 } 266 282 267 268 283 /* API: init factory */ 269 284 static pj_status_t sdl_factory_init(pjmedia_vid_dev_factory *f) … … 272 287 struct sdl_dev_info *ddi; 273 288 unsigned i, j; 289 struct sdl_dev_t sdl_dev; 290 pj_status_t status; 274 291 SDL_version version; 275 SDL_VERSION(&version); 276 277 #if SDL_VERSION_ATLEAST(1,3,0) 278 # if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 279 sf->apool = [[NSAutoreleasePool alloc] init]; 280 sf->delegate = [[SDLDelegate alloc] init]; 281 [sf->delegate performSelectorOnMainThread:@selector(sdl_init) 282 withObject:nil waitUntilDone:YES]; 283 # else /* PJ_DARWINOS */ 284 /* Initialize the SDL library */ 285 if (SDL_Init(SDL_INIT_VIDEO)) 292 293 pj_list_init(&sf->streams); 294 status = pj_mutex_create_recursive(sf->pool, "sdl_factory", 295 &sf->mutex); 296 if (status != PJ_SUCCESS) 297 return status; 298 299 status = pj_sem_create(sf->pool, NULL, 0, 1, &sf->sem); 300 if (status != PJ_SUCCESS) 301 return status; 302 303 sf->status = PJ_EUNKNOWN; 304 sdl_dev.sf = sf; 305 sdl_dev.strm = NULL; 306 status = pj_thread_create(sf->pool, "sdl_thread", sdl_thread, 307 &sdl_dev, 0, 0, &sf->sdl_thread); 308 if (status != PJ_SUCCESS) { 286 309 return PJMEDIA_EVID_INIT; 287 # endif /* PJ_DARWINOS */ 288 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 310 } 311 312 while (sf->status == PJ_EUNKNOWN) 313 pj_thread_sleep(10); 314 315 if (sf->status != PJ_SUCCESS) 316 return sf->status; 289 317 290 318 sf->dev_count = 1; … … 330 358 } 331 359 360 SDL_VERSION(&version); 332 361 PJ_LOG(4, (THIS_FILE, "SDL %d.%d initialized", 333 362 version.major, version.minor)); … … 342 371 pj_pool_t *pool = sf->pool; 343 372 373 pj_assert(pj_list_empty(&sf->streams)); 374 375 sf->is_quitting = PJ_TRUE; 376 if (sf->sdl_thread) { 377 pj_sem_post(sf->sem); 378 pj_thread_join(sf->sdl_thread); 379 } 380 381 if (sf->mutex) { 382 pj_mutex_destroy(sf->mutex); 383 sf->mutex = NULL; 384 } 385 386 if (sf->sem) { 387 pj_sem_destroy(sf->sem); 388 sf->sem = NULL; 389 } 390 344 391 sf->pool = NULL; 345 392 pj_pool_release(pool); 346 347 #if SDL_VERSION_ATLEAST(1,3,0)348 # if defined(PJ_DARWINOS) && PJ_DARWINOS!=0349 [sf->delegate performSelectorOnMainThread:@selector(sdl_quit)350 withObject:nil waitUntilDone:YES];351 [sf->delegate release];352 [sf->apool release];353 # else /* PJ_DARWINOS */354 SDL_Quit();355 # endif /* PJ_DARWINOS */356 #endif /* SDL_VERSION_ATLEAST(1,3,0) */357 393 358 394 return PJ_SUCCESS; … … 507 543 Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE; 508 544 545 # if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 509 546 if (strm->param.rend_id == OPENGL_DEV_IDX) 510 547 flags |= SDL_WINDOW_OPENGL; 548 # endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 511 549 512 550 if (strm->param.flags & PJMEDIA_VID_DEV_CAP_OUTPUT_WINDOW) { … … 588 626 if (!strm->texture) 589 627 return PJMEDIA_EVID_SYSERR; 590 591 # if !defined(PJ_DARWINOS) || PJ_DARWINOS == 0592 /**593 * OpenGL drawing must be in the same594 * thread that calls SDL_SetVideoMode(), hence we need a buffer595 * for the frame from sdl_stream_put_frame()596 */597 if (strm->vafp.framebytes > strm->tex_buf_size) {598 strm->tex_buf_size = strm->vafp.framebytes;599 strm->tex_buf = pj_pool_alloc(strm->pool, strm->vafp.framebytes);600 }601 # endif /* PJ_DARWINOS */602 628 } else 603 629 #endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ … … 611 637 612 638 strm->pitch = strm->rect.w * SDL_BYTESPERPIXEL(sdl_info->sdl_format); 613 614 # if !defined(PJ_DARWINOS) || PJ_DARWINOS == 0615 if (strm->vafp.framebytes > strm->tex_buf_size) {616 strm->tex_buf_size = strm->vafp.framebytes;617 strm->tex_buf = pj_pool_alloc(strm->pool, strm->vafp.framebytes);618 }619 # endif /* !PJ_DARWINOS */620 639 } 621 640 #else /* SDL_VERSION_ATLEAST(1,3,0) */ … … 639 658 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 640 659 660 if (strm->vafp.framebytes > strm->frame_buf_size) { 661 strm->frame_buf_size = strm->vafp.framebytes; 662 strm->frame.buf = pj_pool_alloc(strm->pool, strm->vafp.framebytes); 663 } 664 641 665 return PJ_SUCCESS; 642 666 } … … 644 668 static pj_status_t sdl_create(struct sdl_stream *strm) 645 669 { 670 strm->is_initialized = PJ_TRUE; 671 646 672 #if !(SDL_VERSION_ATLEAST(1,3,0)) 647 673 if (SDL_Init(SDL_INIT_VIDEO)) { 648 674 strm->status = PJMEDIA_EVID_INIT; 649 goto on_return;675 return strm->status; 650 676 } 651 677 #endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ … … 658 684 659 685 strm->status = sdl_create_view(strm, &strm->param.fmt); 660 if (strm->status != PJ_SUCCESS)661 goto on_return;662 663 on_return:664 if (strm->status != PJ_SUCCESS) {665 sdl_destroy(strm, PJ_TRUE);666 #if !(SDL_VERSION_ATLEAST(1,3,0))667 SDL_Quit();668 #endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */669 strm->screen = NULL;670 }671 672 686 return strm->status; 673 687 } … … 675 689 static void detect_fmt_change(struct sdl_stream *strm) 676 690 { 691 strm->status = PJ_SUCCESS; 677 692 if (strm->new_fmt || strm->new_disp_size) { 678 /* Stop the stream */679 sdl_stream_stop((pjmedia_vid_dev_stream *)strm);680 681 693 if (strm->new_disp_size) 682 694 pj_memcpy(&strm->param.disp_size, strm->new_disp_size, … … 690 702 if (strm->new_fmt) 691 703 pjmedia_format_copy(&strm->param.fmt, strm->new_fmt); 692 /* Restart the stream */693 sdl_stream_start((pjmedia_vid_dev_stream *)strm);694 704 } 695 705 strm->new_fmt = NULL; … … 698 708 } 699 709 710 static pj_status_t put_frame(struct sdl_stream *stream, 711 const pjmedia_frame *frame) 712 { 713 if (!stream->is_running) 714 return PJ_SUCCESS; 715 716 if (stream->surf) { 717 if (SDL_MUSTLOCK(stream->surf)) { 718 if (SDL_LockSurface(stream->surf) < 0) { 719 PJ_LOG(3, (THIS_FILE, "Unable to lock SDL surface")); 720 return PJMEDIA_EVID_NOTREADY; 721 } 722 } 723 724 pj_memcpy(stream->surf->pixels, frame->buf, 725 stream->vafp.framebytes); 726 727 if (SDL_MUSTLOCK(stream->surf)) { 728 SDL_UnlockSurface(stream->surf); 729 } 730 #if SDL_VERSION_ATLEAST(1,3,0) 731 SDL_UpdateWindowSurface(stream->window); 732 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 733 SDL_BlitSurface(stream->surf, NULL, stream->screen, &stream->dstrect); 734 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 735 } else if (stream->overlay) { 736 int i, sz, offset; 737 738 if (SDL_LockYUVOverlay(stream->overlay) < 0) { 739 PJ_LOG(3, (THIS_FILE, "Unable to lock SDL overlay")); 740 return PJMEDIA_EVID_NOTREADY; 741 } 742 743 for (i = 0, offset = 0; i < stream->overlay->planes; i++) { 744 sz = stream->vafp.plane_bytes[i]; 745 pj_memcpy(stream->overlay->pixels[i], 746 (char *)frame->buf + offset, sz); 747 offset += sz; 748 } 749 750 SDL_UnlockYUVOverlay(stream->overlay); 751 SDL_DisplayYUVOverlay(stream->overlay, &stream->dstrect); 752 } 753 #if SDL_VERSION_ATLEAST(1,3,0) 754 else if (stream->scr_tex) { 755 SDL_UpdateTexture(stream->scr_tex, NULL, frame->buf, stream->pitch); 756 SDL_RenderClear(stream->renderer); 757 SDL_RenderCopy(stream->renderer, stream->scr_tex, NULL, NULL); 758 SDL_RenderPresent(stream->renderer); 759 } 760 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 700 761 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 701 static void draw_gl(struct sdl_stream *stream, void *tex_buf) 702 { 703 if (stream->texture) { 762 else if (stream->param.rend_id == OPENGL_DEV_IDX && stream->texture) { 704 763 glBindTexture(GL_TEXTURE_2D, stream->texture); 705 764 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); … … 707 766 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 708 767 stream->rect.w, stream->rect.h, 0, 709 GL_RGBA, GL_UNSIGNED_BYTE, tex_buf);768 GL_RGBA, GL_UNSIGNED_BYTE, frame->buf); 710 769 glBegin(GL_TRIANGLE_STRIP); 711 770 glTexCoord2f(0, 0); glVertex2i(0, 0); … … 721 780 # endif /* SDL_VERSION_ATLEAST(1,3,0) */ 722 781 } 723 }724 782 #endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 725 783 726 static void draw_texture(struct sdl_stream *stream, void *tex_buf) 727 { 784 return PJ_SUCCESS; 785 } 786 787 static struct sdl_stream* find_stream(struct sdl_factory *sf, 788 Uint32 windowID, 789 pjmedia_event *pevent) 790 { 791 struct stream_list *it, *itBegin; 792 struct sdl_stream *strm = NULL; 793 794 itBegin = &sf->streams; 795 for (it = itBegin->next; it != itBegin; it = it->next) { 728 796 #if SDL_VERSION_ATLEAST(1,3,0) 729 SDL_UpdateTexture(stream->scr_tex, NULL, tex_buf, stream->pitch); 730 SDL_RenderClear(stream->renderer); 731 SDL_RenderCopy(stream->renderer, stream->scr_tex, NULL, NULL); 732 SDL_RenderPresent(stream->renderer); 797 if (SDL_GetWindowID(it->stream->window) == windowID) 733 798 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 734 PJ_UNUSED_ARG(stream); 735 PJ_UNUSED_ARG(tex_buf); 799 PJ_UNUSED_ARG(windowID); 736 800 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 737 } 738 739 static void handle_event(struct sdl_stream *strm) 740 { 741 const pjmedia_video_format_info *vfi; 742 pjmedia_video_format_detail *vfd; 743 pj_bool_t notify_wnd_closed_event = PJ_FALSE; 801 { 802 strm = it->stream; 803 break; 804 } 805 } 806 807 if (strm) 808 pjmedia_event_init(pevent, PJMEDIA_EVENT_NONE, &strm->last_ts, 809 &strm->base.epub); 810 811 return strm; 812 } 813 814 static int poll_event(struct sdl_factory *sf, pjmedia_event *pevent, 815 struct sdl_stream **strm) 816 { 817 int retval; 744 818 SDL_Event sevent; 745 pjmedia_event pevent; 746 747 vfi = pjmedia_get_video_format_info(pjmedia_video_format_mgr_instance(), 748 strm->param.fmt.id); 749 vfd = pjmedia_format_get_video_format_detail(&strm->param.fmt, PJ_TRUE); 750 751 if (strm->tex_buf) { 752 #if SDL_VERSION_ATLEAST(1,3,0) 753 if (strm->scr_tex) { 754 draw_texture(strm, strm->tex_buf); 755 } 756 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 757 if (0) { } 758 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 759 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL 760 else if (strm->param.rend_id == OPENGL_DEV_IDX) { 761 draw_gl(strm, strm->tex_buf); 762 } 763 #endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */ 764 } 765 766 detect_fmt_change(strm); 767 768 /** 769 * The event polling must be placed in the same thread that 770 * call SDL_SetVideoMode(). Please consult the official doc of 771 * SDL_PumpEvents(). 772 */ 773 while (SDL_PollEvent(&sevent)) { 774 pjmedia_event_init(&pevent, PJMEDIA_EVENT_NONE, &strm->last_ts, 775 &strm->base.epub); 819 820 retval = SDL_PollEvent(&sevent); 821 if (retval) { 822 #if !(SDL_VERSION_ATLEAST(1,3,0)) 823 *strm = find_stream(sf, 0, pevent); 824 pj_assert(strm); 825 #endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 776 826 777 827 switch(sevent.type) { 778 828 case SDL_MOUSEBUTTONDOWN: 779 pevent.type = PJMEDIA_EVENT_MOUSE_BTN_DOWN; 829 #if SDL_VERSION_ATLEAST(1,3,0) 830 *strm = find_stream(sf, sevent.button.windowID, pevent); 831 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 832 pevent->type = PJMEDIA_EVENT_MOUSE_BTN_DOWN; 780 833 break; 781 834 #if SDL_VERSION_ATLEAST(1,3,0) 782 835 case SDL_WINDOWEVENT: 836 *strm = find_stream(sf, sevent.window.windowID, pevent); 783 837 switch (sevent.window.event) { 784 838 case SDL_WINDOWEVENT_RESIZED: 785 pevent .type = PJMEDIA_EVENT_WND_RESIZED;786 pevent .data.wnd_resized.new_size.w =839 pevent->type = PJMEDIA_EVENT_WND_RESIZED; 840 pevent->data.wnd_resized.new_size.w = 787 841 sevent.window.data1; 788 pevent .data.wnd_resized.new_size.h =842 pevent->data.wnd_resized.new_size.h = 789 843 sevent.window.data2; 790 844 break; 845 case SDL_WINDOWEVENT_CLOSE: 846 pevent->type = PJMEDIA_EVENT_WND_CLOSING; 847 break; 791 848 } 792 849 break; 793 850 #else /* SDL_VERSION_ATLEAST(1,3,0) */ 794 851 case SDL_VIDEORESIZE: 795 pevent .type = PJMEDIA_EVENT_WND_RESIZED;796 pevent .data.wnd_resized.new_size.w = sevent.resize.w;797 pevent .data.wnd_resized.new_size.h = sevent.resize.h;852 pevent->type = PJMEDIA_EVENT_WND_RESIZED; 853 pevent->data.wnd_resized.new_size.w = sevent.resize.w; 854 pevent->data.wnd_resized.new_size.h = sevent.resize.h; 798 855 break; 799 856 case SDL_QUIT: 800 pevent .type = PJMEDIA_EVENT_WND_CLOSING;857 pevent->type = PJMEDIA_EVENT_WND_CLOSING; 801 858 break; 802 859 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 803 860 } 804 805 if (pevent.type != PJMEDIA_EVENT_NONE) { 806 pj_status_t status; 807 808 status = pjmedia_event_publish(&strm->base.epub, &pevent); 861 } 862 863 return retval; 864 } 865 866 static struct sdl_stream* handle_event(struct sdl_factory *sf, 867 struct sdl_stream *rcv_strm, 868 pjmedia_event_type *ev_type) 869 { 870 struct sdl_stream *strm = NULL; 871 pjmedia_event pevent; 872 873 *ev_type = PJMEDIA_EVENT_NONE; 874 while (poll_event(sf, &pevent, &strm)) { 875 *ev_type = pevent.type; 876 if (pevent.type != PJMEDIA_EVENT_NONE && strm && 877 (!rcv_strm || rcv_strm == strm)) 878 { 879 pjmedia_event_publish(&strm->base.epub, &pevent); 809 880 810 881 switch (pevent.type) { 811 882 case PJMEDIA_EVENT_WND_RESIZED: 812 883 strm->new_disp_size = &pevent.data.wnd_resized.new_size; 884 strm->status = PJ_SUCCESS; 813 885 detect_fmt_change(strm); 886 if (strm->status != PJ_SUCCESS) 887 return strm; 814 888 break; 815 889 … … 825 899 */ 826 900 strm->is_quitting = PJ_TRUE; 827 notify_wnd_closed_event = PJ_TRUE;828 901 sdl_stream_stop(&strm->base); 829 goto on_return; 830 902 903 return strm; 831 904 default: 832 905 /* Just to prevent gcc warning about unused enums */ … … 836 909 } 837 910 838 return; 839 840 on_return: 841 sdl_destroy(strm, PJ_TRUE); 842 #if !(SDL_VERSION_ATLEAST(1,3,0)) 843 SDL_Quit(); 844 #endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 845 strm->screen = NULL; 846 847 if (notify_wnd_closed_event) { 848 pjmedia_event pevent; 849 850 pjmedia_event_init(&pevent, PJMEDIA_EVENT_WND_CLOSED, &strm->last_ts, 851 &strm->base.epub); 852 pjmedia_event_publish(&strm->base.epub, &pevent); 853 } 854 855 /* 856 * Note: don't access the stream after this point, it might have 857 * been destroyed 858 */ 911 return strm; 859 912 } 860 913 861 914 static int sdl_thread(void * data) 862 915 { 863 struct sdl_stream *strm = (struct sdl_stream*)data; 916 struct sdl_dev_t *sdl_dev = (struct sdl_dev_t *)data; 917 struct sdl_factory *sf = sdl_dev->sf; 918 struct sdl_stream *strm = sdl_dev->strm; 864 919 865 920 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 866 while(!strm->is_quitting) { 867 [strm->delegate performSelectorOnMainThread:@selector(handle_event) 868 withObject:nil waitUntilDone:YES]; 869 } 870 [strm->delegate performSelectorOnMainThread:@selector(sdl_destroy) 871 withObject:nil waitUntilDone:YES]; 921 NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init]; 922 SDLDelegate *delegate = [[SDLDelegate alloc] init]; 923 #endif /* PJ_DARWINOS */ 924 925 #if SDL_VERSION_ATLEAST(1,3,0) 926 # if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 927 [delegate performSelectorOnMainThread:@selector(sdl_init) 928 withObject:nil waitUntilDone:YES]; 929 if (delegate->status != PJ_SUCCESS) 930 goto on_error; 931 # else /* PJ_DARWINOS */ 932 /* Initialize the SDL library */ 933 if (SDL_Init(SDL_INIT_VIDEO)) { 934 sf->status = PJMEDIA_EVID_INIT; 935 goto on_error; 936 } 937 # endif /* PJ_DARWINOS */ 938 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 939 sf->status = PJ_SUCCESS; 940 941 while (!sf->is_quitting) { 942 struct stream_list *it, *itBegin; 943 pjmedia_event_type ev_type; 944 struct sdl_stream *ev_stream; 945 946 pj_mutex_lock(sf->mutex); 947 948 if (!strm && pj_list_empty(&sf->streams)) { 949 /* Wait until there is any stream. */ 950 pj_mutex_unlock(sf->mutex); 951 pj_sem_wait(sf->sem); 952 pj_mutex_lock(sf->mutex); 953 } 954 955 itBegin = &sf->streams; 956 for (it = itBegin->next; it != itBegin; it = it->next) { 957 if ((strm && it->stream != strm) || it->stream->is_quitting) 958 continue; 959 960 if (!it->stream->is_initialized) { 961 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 962 delegate->strm = it->stream; 963 [delegate performSelectorOnMainThread:@selector(sdl_create) 964 withObject:nil waitUntilDone:YES]; 965 #else /* PJ_DARWINOS */ 966 sdl_create(it->stream); 967 #endif /* PJ_DARWINOS */ 968 } 969 970 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 971 delegate->strm = it->stream; 972 [delegate performSelectorOnMainThread:@selector(detect_fmt_change) 973 withObject:nil waitUntilDone:YES]; 974 [delegate performSelectorOnMainThread:@selector(put_frame) 975 withObject:nil waitUntilDone:YES]; 976 #else /* PJ_DARWINOS */ 977 detect_fmt_change(it->stream); 978 put_frame(it->stream, &it->stream->frame); 979 #endif /* PJ_DARWINOS */ 980 } 981 982 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 983 delegate->sf = sf; 984 delegate->strm = strm; 985 [delegate performSelectorOnMainThread:@selector(handle_event) 986 withObject:nil waitUntilDone:YES]; 987 ev_stream = delegate->strm; 988 ev_type = delegate->ev_type; 989 #else /* PJ_DARWINOS */ 990 ev_stream = handle_event(sf, strm, &ev_type); 991 #endif /* PJ_DARWINOS */ 992 993 itBegin = &sf->streams; 994 for (it = itBegin->next; it != itBegin; it = it->next) { 995 if ((strm && it->stream != strm) || !it->stream->is_quitting || 996 it->stream->is_destroyed) 997 continue; 998 999 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 1000 delegate->strm = it->stream; 1001 [delegate performSelectorOnMainThread:@selector(sdl_destroy) 1002 withObject:nil waitUntilDone:YES]; 872 1003 # if !(SDL_VERSION_ATLEAST(1,3,0)) 873 [strm->delegate performSelectorOnMainThread:@selector(sdl_quit)874 withObject:nil waitUntilDone:YES];1004 [delegate performSelectorOnMainThread:@selector(sdl_quit) 1005 withObject:nil waitUntilDone:YES]; 875 1006 # endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 876 1007 #else /* PJ_DARWINOS */ 877 sdl_create(strm); 878 while(!strm->is_quitting) { 879 handle_event(strm); 880 } 881 sdl_destroy(strm, PJ_TRUE); 1008 sdl_destroy(it->stream, PJ_TRUE); 882 1009 # if !(SDL_VERSION_ATLEAST(1,3,0)) 883 SDL_Quit();1010 SDL_Quit(); 884 1011 # endif /* !(SDL_VERSION_ATLEAST(1,3,0)) */ 885 1012 #endif /* PJ_DARWINOS */ 886 strm->screen = NULL; 1013 it->stream->screen = NULL; 1014 it->stream->is_destroyed = PJ_TRUE; 1015 1016 if (ev_type == PJMEDIA_EVENT_WND_CLOSING && 1017 it->stream == ev_stream) 1018 { 1019 pjmedia_event p_event; 1020 1021 pjmedia_event_init(&p_event, PJMEDIA_EVENT_WND_CLOSED, 1022 &it->stream->last_ts, 1023 &it->stream->base.epub); 1024 pjmedia_event_publish(&it->stream->base.epub, &p_event); 1025 1026 /* 1027 * Note: don't access the stream after this point, it 1028 * might have been destroyed 1029 */ 1030 } 1031 1032 if (strm) { 1033 pj_mutex_unlock(sf->mutex); 1034 return 0; 1035 } 1036 } 1037 1038 pj_mutex_unlock(sf->mutex); 1039 } 1040 1041 on_error: 1042 #if SDL_VERSION_ATLEAST(1,3,0) 1043 # if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 1044 [delegate performSelectorOnMainThread:@selector(sdl_quit) 1045 withObject:nil waitUntilDone:YES]; 1046 [delegate release]; 1047 [apool release]; 1048 # else /* PJ_DARWINOS */ 1049 SDL_Quit(); 1050 # endif /* PJ_DARWINOS */ 1051 #endif /* SDL_VERSION_ATLEAST(1,3,0) */ 887 1052 888 1053 return 0; 889 }890 891 static pj_status_t put_frame(struct sdl_stream *stream,892 const pjmedia_frame *frame)893 {894 pj_status_t status = PJ_SUCCESS;895 896 stream->last_ts.u64 = frame->timestamp.u64;897 898 if (!stream->is_running) {899 stream->render_exited = PJ_TRUE;900 goto on_return;901 }902 903 if (frame->size==0 || frame->buf==NULL ||904 frame->size < stream->vafp.framebytes)905 goto on_return;906 907 if (stream->surf) {908 if (SDL_MUSTLOCK(stream->surf)) {909 if (SDL_LockSurface(stream->surf) < 0) {910 PJ_LOG(3, (THIS_FILE, "Unable to lock SDL surface"));911 status = PJMEDIA_EVID_NOTREADY;912 goto on_return;913 }914 }915 916 pj_memcpy(stream->surf->pixels, frame->buf,917 stream->vafp.framebytes);918 919 if (SDL_MUSTLOCK(stream->surf)) {920 SDL_UnlockSurface(stream->surf);921 }922 SDL_BlitSurface(stream->surf, NULL, stream->screen, &stream->dstrect);923 #if SDL_VERSION_ATLEAST(1,3,0)924 SDL_UpdateWindowSurface(stream->window);925 #else /* SDL_VERSION_ATLEAST(1,3,0) */926 SDL_UpdateRect(stream->screen, 0, 0, 0, 0);927 #endif /* SDL_VERSION_ATLEAST(1,3,0) */928 } else if (stream->overlay) {929 int i, sz, offset;930 931 if (SDL_LockYUVOverlay(stream->overlay) < 0) {932 PJ_LOG(3, (THIS_FILE, "Unable to lock SDL overlay"));933 status = PJMEDIA_EVID_NOTREADY;934 goto on_return;935 }936 937 for (i = 0, offset = 0; i < stream->overlay->planes; i++) {938 sz = stream->vafp.plane_bytes[i];939 pj_memcpy(stream->overlay->pixels[i],940 (char *)frame->buf + offset, sz);941 offset += sz;942 }943 944 SDL_UnlockYUVOverlay(stream->overlay);945 SDL_DisplayYUVOverlay(stream->overlay, &stream->dstrect);946 }947 #if SDL_VERSION_ATLEAST(1,3,0)948 else if (stream->scr_tex) {949 if (stream->tex_buf)950 pj_memcpy(stream->tex_buf, frame->buf, stream->vafp.framebytes);951 else952 draw_texture(stream, frame->buf);953 }954 #endif /* SDL_VERSION_ATLEAST(1,3,0) */955 #if PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL956 else if (stream->param.rend_id == OPENGL_DEV_IDX) {957 if (stream->tex_buf)958 pj_memcpy(stream->tex_buf, frame->buf, stream->vafp.framebytes);959 else960 draw_gl(stream, frame->buf);961 }962 #endif /* PJMEDIA_VIDEO_DEV_SDL_HAS_OPENGL */963 964 on_return:965 stream->status = status;966 return status;967 1054 } 968 1055 … … 973 1060 struct sdl_stream *stream = (struct sdl_stream*)strm; 974 1061 975 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 976 stream->frame = frame; 977 [stream->delegate performSelectorOnMainThread:@selector(put_frame) 978 withObject:nil waitUntilDone:YES]; 979 980 return stream->status; 981 #else /* PJ_DARWINOS */ 982 return put_frame(stream, frame); 983 #endif /* PJ_DARWINOS */ 1062 stream->last_ts.u64 = frame->timestamp.u64; 1063 1064 if (!stream->is_running) { 1065 stream->render_exited = PJ_TRUE; 1066 return PJ_SUCCESS; 1067 } 1068 1069 if (frame->size==0 || frame->buf==NULL || 1070 frame->size < stream->vafp.framebytes) 1071 return PJ_SUCCESS; 1072 1073 pj_memcpy(stream->frame.buf, frame->buf, stream->vafp.framebytes); 1074 1075 return PJ_SUCCESS; 984 1076 } 985 1077 … … 999 1091 PJ_ASSERT_RETURN(param->dir == PJMEDIA_DIR_RENDER, PJ_EINVAL); 1000 1092 1093 #if !SDL_VERSION_ATLEAST(1,3,0) 1094 /* Prior to 1.3, SDL does not support multiple renderers. */ 1095 pj_mutex_lock(sf->mutex); 1096 if (!pj_list_empty(&sf->streams) { 1097 pj_mutex_unlock(sf->mutex); 1098 return PJMEDIA_EVID_NOTREADY; 1099 } 1100 pj_mutex_unlock(sf->mutex); 1101 #endif 1102 1001 1103 /* Create and Initialize stream descriptor */ 1002 1104 pool = pj_pool_create(sf->pf, "sdl-dev", 1000, 1000, NULL); … … 1006 1108 pj_memcpy(&strm->param, param, sizeof(*param)); 1007 1109 strm->pool = pool; 1110 strm->sf = sf; 1008 1111 pj_memcpy(&strm->vid_cb, cb, sizeof(*cb)); 1009 1112 strm->user_data = user_data; 1010 1113 pjmedia_event_publisher_init(&strm->base.epub, PJMEDIA_SIG_VID_DEV_SDL); 1114 pj_list_init(&strm->list_entry); 1115 strm->list_entry.stream = strm; 1011 1116 1012 1117 /* Create render stream here */ 1013 1118 if (param->dir & PJMEDIA_DIR_RENDER) { 1119 struct sdl_dev_t sdl_dev; 1120 1014 1121 strm->status = PJ_SUCCESS; 1015 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 1016 strm->apool = [[NSAutoreleasePool alloc] init]; 1017 strm->delegate = [[SDLDelegate alloc]init]; 1018 strm->delegate->strm = strm; 1019 /* On Darwin OS, we need to call SDL functions in the main thread */ 1020 [strm->delegate performSelectorOnMainThread:@selector(sdl_create) 1021 withObject:nil waitUntilDone:YES]; 1022 if ((status = strm->status) != PJ_SUCCESS) { 1023 goto on_error; 1024 } 1025 #endif /* PJ_DARWINOS */ 1026 status = pj_thread_create(pool, "sdl_thread", sdl_thread, 1027 strm, 0, 0, &strm->sdl_thread); 1028 1122 sdl_dev.sf = strm->sf; 1123 sdl_dev.strm = strm; 1124 pj_mutex_lock(strm->sf->mutex); 1125 #if !SDL_USE_ONE_THREAD_PER_DISPLAY 1126 if (pj_list_empty(&strm->sf->streams)) 1127 pj_sem_post(strm->sf->sem); 1128 #endif /* !SDL_USE_ONE_THREAD_PER_DISPLAY */ 1129 pj_list_insert_after(&strm->sf->streams, &strm->list_entry); 1130 pj_mutex_unlock(strm->sf->mutex); 1131 1132 #if SDL_USE_ONE_THREAD_PER_DISPLAY 1133 status = pj_thread_create(pool, "sdl_thread", sdl_thread, 1134 &sdl_dev, 0, 0, &strm->sdl_thread); 1029 1135 if (status != PJ_SUCCESS) { 1030 1136 goto on_error; 1031 1137 } 1138 #endif /* SDL_USE_ONE_THREAD_PER_DISPLAY */ 1032 1139 1033 1140 while(strm->status == PJ_SUCCESS && !strm->surf && !strm->overlay … … 1191 1298 if (cap == PJMEDIA_VID_DEV_CAP_FORMAT) { 1192 1299 strm->new_fmt = (pjmedia_format *)pval; 1193 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=01194 [strm->delegate performSelectorOnMainThread:1195 @selector(detect_fmt_change)1196 withObject:nil waitUntilDone:YES];1197 #endif /* PJ_DARWINOS */1198 1300 while (strm->new_fmt) 1199 1301 pj_thread_sleep(10); … … 1207 1309 */ 1208 1310 strm->new_fmt = &strm->param.fmt; 1209 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=01210 [strm->delegate performSelectorOnMainThread:1211 @selector(detect_fmt_change)1212 withObject:nil waitUntilDone:YES];1213 #endif /* PJ_DARWINOS */1214 1311 while (strm->new_fmt) 1215 1312 pj_thread_sleep(10); … … 1229 1326 } else if (cap == PJMEDIA_VID_DEV_CAP_OUTPUT_RESIZE) { 1230 1327 strm->new_disp_size = (pjmedia_rect_size *)pval; 1231 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=01232 [strm->delegate performSelectorOnMainThread:1233 @selector(detect_fmt_change)1234 withObject:nil waitUntilDone:YES];1235 #endif /* PJ_DARWINOS */1236 1328 while (strm->new_disp_size) 1237 1329 pj_thread_sleep(10); … … 1266 1358 /* Wait for renderer put_frame() to finish */ 1267 1359 stream->is_running = PJ_FALSE; 1268 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=01269 if (![NSThread isMainThread])1270 #endif /* PJ_DARWINOS */1271 1360 for (i=0; !stream->render_exited && i<50; ++i) 1272 1361 pj_thread_sleep(10); … … 1289 1378 if (stream->sdl_thread) 1290 1379 pj_thread_join(stream->sdl_thread); 1291 } 1292 1293 #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 1294 if (stream->delegate) { 1295 [stream->delegate release]; 1296 stream->delegate = NULL; 1297 } 1298 if (stream->apool) { 1299 [stream->apool release]; 1300 stream->apool = NULL; 1301 } 1302 #endif /* PJ_DARWINOS */ 1380 while (!stream->is_destroyed) { 1381 pj_thread_sleep(10); 1382 } 1383 } 1384 1385 pj_mutex_lock(stream->sf->mutex); 1386 if (!pj_list_empty(&stream->list_entry)) 1387 pj_list_erase(&stream->list_entry); 1388 pj_mutex_unlock(stream->sf->mutex); 1389 1303 1390 pj_pool_release(stream->pool); 1304 1305 1391 1306 1392 return PJ_SUCCESS; … … 1313 1399 if (SDL_Init(SDL_INIT_VIDEO)) { 1314 1400 PJ_LOG(4, (THIS_FILE, "Cannot initialize SDL")); 1315 } 1401 status = PJMEDIA_EVID_INIT; 1402 } 1403 status = PJ_SUCCESS; 1316 1404 } 1317 1405 … … 1338 1426 - (void)handle_event 1339 1427 { 1340 handle_event(strm);1428 strm = handle_event(sf, strm, &ev_type); 1341 1429 } 1342 1430 1343 1431 - (void)put_frame 1344 1432 { 1345 put_frame(strm, strm->frame);1433 put_frame(strm, &strm->frame); 1346 1434 } 1347 1435
Note: See TracChangeset
for help on using the changeset viewer.