00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <errno.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030
00031 #include <photon/PtWidget.h>
00032 #include <photon/PtWindow.h>
00033 #include <photon/PtLabel.h>
00034 #include <photon/PdDirect.h>
00035
00036 #include <vlc/vlc.h>
00037 #include <vlc/intf.h>
00038 #include <vlc/vout.h>
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define MAX_DIRECTBUFFERS 2
00049
00050 #define MODE_NORMAL_MEM 0
00051 #define MODE_SHARED_MEM 1
00052 #define MODE_VIDEO_MEM 2
00053 #define MODE_VIDEO_OVERLAY 3
00054
00055 struct vout_sys_t
00056 {
00057
00058 int i_mode;
00059
00060
00061 PtWidget_t * p_window;
00062
00063
00064 PgColor_t p_colors[255];
00065
00066
00067 int i_img_type;
00068
00069
00070
00071
00072 PgVideoChannel_t * p_channel;
00073 int i_vc_flags;
00074 int i_vc_format;
00075
00076 int i_screen_depth;
00077 int i_bytes_per_pixel;
00078 int i_bytes_per_line;
00079
00080
00081 PhPoint_t pos;
00082 PhDim_t dim;
00083 PhPoint_t old_pos;
00084 PhDim_t old_dim;
00085 PhDim_t screen_dim;
00086 PhRect_t frame;
00087 };
00088
00089
00090
00091
00092
00093
00094
00095
00096 struct picture_sys_t
00097 {
00098
00099 PhImage_t * p_image;
00100
00101
00102 PdOffscreenContext_t * p_ctx[3];
00103 char * p_buf[3];
00104 };
00105
00106
00107
00108
00109
00110 static int QNXInit ( vout_thread_t * );
00111 static void QNXEnd ( vout_thread_t * );
00112 static int QNXManage ( vout_thread_t * );
00113 static void QNXDisplay ( vout_thread_t *, picture_t * );
00114
00115 static int QNXInitDisplay ( vout_thread_t * );
00116 static int QNXCreateWnd ( vout_thread_t * );
00117 static int QNXDestroyWnd ( vout_thread_t * );
00118
00119 static int NewPicture ( vout_thread_t *, picture_t *, int );
00120 static void FreePicture ( vout_thread_t *, picture_t * );
00121 static int ResizeOverlayOutput ( vout_thread_t * );
00122 static void SetPalette ( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
00123
00124
00125
00126
00127
00128
00129
00130
00131 int E_(OpenVideo) ( vlc_object_t *p_this )
00132 {
00133 vout_thread_t * p_vout = (vout_thread_t *)p_this;
00134
00135
00136 if( PtInit( "/dev/photon" ) != 0 )
00137 {
00138 msg_Err( p_vout, "unable to connect to photon" );
00139 return( 1 );
00140 }
00141
00142
00143 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
00144 if( p_vout->p_sys == NULL )
00145 {
00146 msg_Err( p_vout, "out of memory" );
00147 return( 1 );
00148 }
00149
00150 memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
00151
00152 p_vout->b_fullscreen = config_GetInt( p_vout, "fullscreen" );
00153 p_vout->p_sys->i_mode = config_GetInt( p_vout, "overlay" ) ?
00154 MODE_VIDEO_OVERLAY : MODE_VIDEO_MEM;
00155 p_vout->p_sys->dim.w = p_vout->i_window_width;
00156 p_vout->p_sys->dim.h = p_vout->i_window_height;
00157
00158
00159 if( QNXInitDisplay( p_vout ) || QNXCreateWnd( p_vout ) )
00160 {
00161 free( p_vout->p_sys );
00162 return( 1 );
00163 }
00164
00165 p_vout->pf_init = QNXInit;
00166 p_vout->pf_end = QNXEnd;
00167 p_vout->pf_manage = QNXManage;
00168 p_vout->pf_render = NULL;
00169 p_vout->pf_display = QNXDisplay;
00170
00171 return( 0 );
00172 }
00173
00174
00175
00176
00177
00178
00179
00180 static int QNXInit( vout_thread_t *p_vout )
00181 {
00182 int i_index;
00183 picture_t *p_pic;
00184
00185 I_OUTPUTPICTURES = 0;
00186
00187 switch( p_vout->p_sys->i_mode )
00188 {
00189 case MODE_NORMAL_MEM:
00190 case MODE_SHARED_MEM:
00191 p_vout->output.i_width = p_vout->p_sys->dim.w;
00192 p_vout->output.i_height = p_vout->p_sys->dim.h;
00193
00194
00195 p_vout->output.i_aspect = p_vout->p_sys->dim.w
00196 * VOUT_ASPECT_FACTOR / p_vout->p_sys->dim.h;
00197 break;
00198
00199 case MODE_VIDEO_MEM:
00200 p_vout->output.i_width = p_vout->p_sys->dim.w;
00201 p_vout->output.i_height = p_vout->p_sys->dim.h;
00202
00203
00204 p_vout->output.i_aspect = p_vout->p_sys->dim.w
00205 * VOUT_ASPECT_FACTOR / p_vout->p_sys->dim.h;
00206 break;
00207
00208 case MODE_VIDEO_OVERLAY:
00209 p_vout->output.i_width = p_vout->render.i_width;
00210 p_vout->output.i_height = p_vout->render.i_height;
00211 p_vout->output.i_aspect = p_vout->render.i_aspect;
00212
00213 if (ResizeOverlayOutput(p_vout))
00214 {
00215 return (1);
00216 }
00217 break;
00218
00219 default:
00220
00221 break;
00222 }
00223
00224
00225 while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
00226 {
00227 p_pic = NULL;
00228
00229
00230 for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
00231 {
00232 if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
00233 {
00234 p_pic = p_vout->p_picture + i_index;
00235 break;
00236 }
00237 }
00238
00239
00240 if( p_pic == NULL || NewPicture( p_vout, p_pic, I_OUTPUTPICTURES ) )
00241 {
00242 break;
00243 }
00244
00245 p_pic->i_status = DESTROYED_PICTURE;
00246 p_pic->i_type = DIRECT_PICTURE;
00247
00248 PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
00249
00250 I_OUTPUTPICTURES++;
00251 }
00252
00253 return( 0 );
00254 }
00255
00256
00257
00258
00259
00260
00261
00262 static void QNXEnd( vout_thread_t *p_vout )
00263 {
00264 int i_index;
00265
00266
00267 for( i_index = I_OUTPUTPICTURES ; i_index ; )
00268 {
00269 i_index--;
00270 FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
00271 }
00272 }
00273
00274
00275
00276
00277
00278
00279 void E_(CloseVideo) ( vlc_object_t *p_this )
00280 {
00281 vout_thread_t * p_vout = (vout_thread_t *)p_this;
00282
00283
00284 QNXDestroyWnd( p_vout );
00285
00286
00287 free( p_vout->p_sys );
00288 }
00289
00290
00291
00292
00293
00294
00295
00296 static int QNXManage( vout_thread_t *p_vout )
00297 {
00298 int i_ev, i_buflen;
00299 PhEvent_t *p_event;
00300 vlc_bool_t b_repos = 0;
00301
00302 if (p_vout->b_die == 1)
00303 {
00304 return ( 0 );
00305 }
00306
00307
00308 i_buflen = sizeof( PhEvent_t ) * 4;
00309 if( ( p_event = malloc( i_buflen ) ) == NULL )
00310 {
00311 msg_Err( p_vout, "out of memory" );
00312 return( 1 );
00313 }
00314
00315
00316 do
00317 {
00318 memset( p_event, 0, i_buflen );
00319 i_ev = PhEventPeek( p_event, i_buflen );
00320
00321 if( i_ev == Ph_RESIZE_MSG )
00322 {
00323 i_buflen = PhGetMsgSize( p_event );
00324 if( ( p_event = realloc( p_event, i_buflen ) ) == NULL )
00325 {
00326 msg_Err( p_vout, "out of memory" );
00327 return( 1 );
00328 }
00329 }
00330 else if( i_ev == Ph_EVENT_MSG )
00331 {
00332 PtEventHandler( p_event );
00333
00334 if( p_event->type == Ph_EV_WM )
00335 {
00336 PhWindowEvent_t *p_ev = PhGetData( p_event );
00337
00338 switch( p_ev->event_f )
00339 {
00340 case Ph_WM_CLOSE:
00341 p_vout->p_vlc->b_die = 1;
00342 break;
00343
00344 case Ph_WM_MOVE:
00345 p_vout->p_sys->pos.x = p_ev->pos.x;
00346 p_vout->p_sys->pos.y = p_ev->pos.y;
00347 b_repos = 1;
00348 break;
00349
00350 case Ph_WM_RESIZE:
00351 p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
00352 p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
00353 p_vout->p_sys->dim.w = p_ev->size.w;
00354 p_vout->p_sys->dim.h = p_ev->size.h;
00355 p_vout->i_changes |= VOUT_SIZE_CHANGE;
00356 break;
00357 }
00358 }
00359 else if( p_event->type == Ph_EV_KEY )
00360 {
00361 PhKeyEvent_t *p_ev = PhGetData( p_event );
00362 long i_key = p_ev->key_sym;
00363
00364 if( ( p_ev->key_flags & Pk_KF_Key_Down ) &&
00365 ( p_ev->key_flags & Pk_KF_Sym_Valid ) )
00366 {
00367 switch( i_key )
00368 {
00369 case Pk_q:
00370 case Pk_Q:
00371 p_vout->p_vlc->b_die = 1;
00372 break;
00373
00374 case Pk_f:
00375 case Pk_F:
00376 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
00377 break;
00378
00379 case Pk_c:
00380 case Pk_C:
00381 p_vout->b_grayscale = ! p_vout->b_grayscale;
00382 p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
00383 break;
00384
00385 default:
00386 break;
00387 }
00388 }
00389 }
00390 }
00391 } while( i_ev != -1 && i_ev != 0 );
00392
00393 free( p_event );
00394
00395
00396
00397
00398 if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
00399 {
00400 PhDim_t dim;
00401
00402 p_vout->b_fullscreen = !p_vout->b_fullscreen;
00403 p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
00404
00405 if( p_vout->b_fullscreen )
00406 {
00407 p_vout->p_sys->old_pos.x = p_vout->p_sys->pos.x;
00408 p_vout->p_sys->old_pos.y = p_vout->p_sys->pos.y;
00409 p_vout->p_sys->pos.x = p_vout->p_sys->pos.y = 0;
00410 dim.w = p_vout->p_sys->screen_dim.w + 1;
00411 dim.h = p_vout->p_sys->screen_dim.h + 1;
00412 }
00413 else
00414 {
00415 p_vout->p_sys->pos.x = p_vout->p_sys->old_pos.x;
00416 p_vout->p_sys->pos.y = p_vout->p_sys->old_pos.y;
00417 dim.w = p_vout->p_sys->old_dim.w + 1;
00418 dim.h = p_vout->p_sys->old_dim.h + 1;
00419 }
00420
00421
00422 PtSetResource( p_vout->p_sys->p_window,
00423 Pt_ARG_WINDOW_RENDER_FLAGS,
00424 p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
00425 Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
00426
00427
00428 PtSetResource( p_vout->p_sys->p_window,
00429 Pt_ARG_POS, &p_vout->p_sys->pos, 0 );
00430 PtSetResource( p_vout->p_sys->p_window,
00431 Pt_ARG_DIM, &dim, 0 );
00432
00433
00434 PtDamageWidget( p_vout->p_sys->p_window );
00435 }
00436
00437
00438
00439
00440 if( p_vout->i_changes & VOUT_SIZE_CHANGE )
00441 {
00442 p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
00443
00444 if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00445 {
00446 ResizeOverlayOutput(p_vout);
00447 }
00448 #if 0
00449 else
00450 {
00451 p_vout->output.i_width = p_vout->p_sys->dim.w;
00452 p_vout->output.i_height = p_vout->p_sys->dim.h;
00453 p_vout->i_changes |= VOUT_YUV_CHANGE;
00454
00455 QNXEnd( p_vout );
00456 if( QNXInit( p_vout ) )
00457 {
00458 msg_Err( p_vout, "cannot resize display" );
00459 return( 1 );
00460 }
00461 }
00462 #endif
00463
00464 msg_Dbg( p_vout, "video display resized (%dx%d)",
00465 p_vout->p_sys->dim.w, p_vout->p_sys->dim.h );
00466 }
00467
00468
00469
00470
00471 if( b_repos && p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00472 {
00473 ResizeOverlayOutput(p_vout);
00474 }
00475
00476 return( i_ev == -1 );
00477 }
00478
00479
00480
00481
00482
00483
00484
00485 static void QNXDisplay( vout_thread_t *p_vout, picture_t *p_pic )
00486 {
00487 if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
00488 p_vout->p_sys->i_mode == MODE_SHARED_MEM )
00489 {
00490 PhPoint_t pos = { 0, 0 };
00491
00492 PgSetRegion( PtWidgetRid( p_vout->p_sys->p_window ) );
00493 if (p_vout->p_sys->i_screen_depth == 8)
00494 {
00495 PgSetPalette( p_vout->p_sys->p_colors, 0, 0, 255, Pg_PALSET_SOFT, 0);
00496 }
00497 PgDrawPhImagemx( &pos, p_pic->p_sys->p_image, 0 );
00498 PgFlush();
00499 }
00500 else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM )
00501 {
00502 PhRect_t rc = { { 0, 0 }, { p_vout->output.i_width, p_vout->output.i_height } };
00503
00504
00505 PgContextBlit( p_pic->p_sys->p_ctx[0], &rc, NULL, &rc );
00506 PgFlush();
00507 }
00508 }
00509
00510
00511
00512
00513 static int QNXInitDisplay( vout_thread_t * p_vout )
00514 {
00515 PgHWCaps_t hwcaps;
00516 PgDisplaySettings_t cfg;
00517 PgVideoModeInfo_t minfo;
00518
00519
00520 if( PgGetGraphicsHWCaps( &hwcaps ) != 0 )
00521 {
00522 msg_Err( p_vout, "unable to get gfx card capabilities" );
00523 return( 1 );
00524 }
00525
00526
00527 if( PgGetVideoMode( &cfg ) != 0 )
00528 {
00529 msg_Err( p_vout, "unable to get current video mode" );
00530 return( 1 );
00531 }
00532
00533
00534 if( PgGetVideoModeInfo( cfg.mode, &minfo ) != 0 )
00535 {
00536 msg_Err( p_vout, "unable to get info for video mode" );
00537 return( 1 );
00538 }
00539
00540 if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00541 {
00542 int i = 0;
00543 PgScalerCaps_t vcaps;
00544
00545 if( ( p_vout->p_sys->p_channel =
00546 PgCreateVideoChannel( Pg_VIDEO_CHANNEL_SCALER, 0 ) ) == NULL )
00547 {
00548 msg_Err( p_vout, "unable to create video channel" );
00549 printf("errno = %d\n", errno);
00550 p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
00551 }
00552 else
00553 {
00554 vcaps.size = sizeof( vcaps );
00555 while( PgGetScalerCapabilities( p_vout->p_sys->p_channel,
00556 i++, &vcaps ) == 0 )
00557 {
00558 printf("vcaps.format = 0x%x\n", vcaps.format);
00559 if( vcaps.format == Pg_VIDEO_FORMAT_YV12 ||
00560 vcaps.format == Pg_VIDEO_FORMAT_YUV420 ||
00561 vcaps.format == Pg_VIDEO_FORMAT_YUY2 ||
00562 vcaps.format == Pg_VIDEO_FORMAT_UYVY ||
00563 vcaps.format == Pg_VIDEO_FORMAT_RGB555 ||
00564 vcaps.format == Pg_VIDEO_FORMAT_RGB565 ||
00565 vcaps.format == Pg_VIDEO_FORMAT_RGB8888 )
00566 {
00567 p_vout->p_sys->i_vc_flags = vcaps.flags;
00568 p_vout->p_sys->i_vc_format = vcaps.format;
00569 }
00570
00571 vcaps.size = sizeof( vcaps );
00572 }
00573
00574 if( p_vout->p_sys->i_vc_format == 0 )
00575 {
00576 msg_Warn( p_vout, "need YV12, YUY2 or RGB8888 overlay" );
00577
00578 p_vout->p_sys->i_mode = MODE_NORMAL_MEM;
00579 }
00580 }
00581 }
00582
00583
00584 if( p_vout->p_sys->i_mode == MODE_NORMAL_MEM &&
00585 (minfo.bits_per_pixel != 8) &&
00586 hwcaps.currently_available_video_ram >=
00587 ( ( minfo.width * minfo.height * minfo.bits_per_pixel * MAX_DIRECTBUFFERS) / 8 ) )
00588 {
00589 p_vout->p_sys->i_mode = MODE_VIDEO_MEM;
00590 printf("Using video memory...\n");
00591 }
00592
00593 p_vout->p_sys->i_img_type = minfo.type;
00594 p_vout->p_sys->screen_dim.w = minfo.width;
00595 p_vout->p_sys->screen_dim.h = minfo.height;
00596 p_vout->p_sys->i_screen_depth = minfo.bits_per_pixel;
00597
00598 switch( p_vout->p_sys->i_screen_depth )
00599 {
00600 case 8:
00601 p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
00602 p_vout->p_sys->i_bytes_per_pixel = 1;
00603 p_vout->output.pf_setpalette = SetPalette;
00604 break;
00605
00606 case 15:
00607 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
00608 p_vout->p_sys->i_bytes_per_pixel = 2;
00609 p_vout->output.i_rmask = 0x7c00;
00610 p_vout->output.i_gmask = 0x03e0;
00611 p_vout->output.i_bmask = 0x001f;
00612 break;
00613
00614 case 16:
00615 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
00616 p_vout->p_sys->i_bytes_per_pixel = 2;
00617 p_vout->output.i_rmask = 0xf800;
00618 p_vout->output.i_gmask = 0x07e0;
00619 p_vout->output.i_bmask = 0x001f;
00620 break;
00621
00622 case 24:
00623 p_vout->output.i_chroma = VLC_FOURCC('R','V','2','4');
00624 p_vout->p_sys->i_bytes_per_pixel = 3;
00625 p_vout->output.i_rmask = 0xff0000;
00626 p_vout->output.i_gmask = 0x00ff00;
00627 p_vout->output.i_bmask = 0x0000ff;
00628 break;
00629
00630 case 32:
00631 default:
00632 p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
00633 p_vout->p_sys->i_bytes_per_pixel = 4;
00634 p_vout->output.i_rmask = 0xff0000;
00635 p_vout->output.i_gmask = 0x00ff00;
00636 p_vout->output.i_bmask = 0x0000ff;
00637 break;
00638 }
00639
00640 return( 0 );
00641 }
00642
00643
00644
00645
00646 static int QNXCreateWnd( vout_thread_t * p_vout )
00647 {
00648 PtArg_t args[8];
00649 PhPoint_t pos = { 0, 0 };
00650 PgColor_t color = Pg_BLACK;
00651
00652 if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00653 {
00654 if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
00655 {
00656 color = PgGetOverlayChromaColor();
00657 }
00658 }
00659
00660
00661 if( p_vout->b_fullscreen )
00662 {
00663 p_vout->p_sys->old_dim.w = p_vout->p_sys->dim.w;
00664 p_vout->p_sys->old_dim.h = p_vout->p_sys->dim.h;
00665 p_vout->output.i_width = p_vout->p_sys->dim.w = p_vout->p_sys->screen_dim.w;
00666 p_vout->output.i_height = p_vout->p_sys->dim.h = p_vout->p_sys->screen_dim.h;
00667 }
00668
00669
00670 PtSetArg( &args[0], Pt_ARG_POS, &pos, 0 );
00671 PtSetArg( &args[1], Pt_ARG_DIM, &p_vout->p_sys->dim, 0 );
00672 PtSetArg( &args[2], Pt_ARG_FILL_COLOR, color, 0 );
00673 PtSetArg( &args[3], Pt_ARG_WINDOW_TITLE, "VLC media player", 0 );
00674 PtSetArg( &args[4], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE, Ph_WM_CLOSE );
00675 PtSetArg( &args[5], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
00676 Ph_WM_MOVE | Ph_WM_RESIZE | Ph_WM_CLOSE );
00677 PtSetArg( &args[6], Pt_ARG_WINDOW_RENDER_FLAGS,
00678 p_vout->b_fullscreen ? Pt_FALSE : Pt_TRUE,
00679 Ph_WM_RENDER_BORDER | Ph_WM_RENDER_TITLE );
00680
00681
00682 p_vout->p_sys->p_window = PtCreateWidget( PtWindow, Pt_NO_PARENT, 7, args);
00683 if( p_vout->p_sys->p_window == NULL )
00684 {
00685 msg_Err( p_vout, "unable to create window" );
00686 return( 1 );
00687 }
00688
00689
00690 if( PtRealizeWidget( p_vout->p_sys->p_window ) != 0 )
00691 {
00692 msg_Err( p_vout, "unable to realize window widget" );
00693 PtDestroyWidget( p_vout->p_sys->p_window );
00694 return( 1 );
00695 }
00696
00697
00698 if( PtWindowFrameSize( NULL, p_vout->p_sys->p_window,
00699 &p_vout->p_sys->frame ) != 0 )
00700 {
00701 msg_Err( p_vout, "unable to get window frame size" );
00702 PtDestroyWidget( p_vout->p_sys->p_window );
00703 return( 1 );
00704 }
00705
00706 return( 0 );
00707 }
00708
00709
00710
00711
00712 static int QNXDestroyWnd( vout_thread_t * p_vout )
00713 {
00714
00715 PtUnrealizeWidget( p_vout->p_sys->p_window );
00716
00717
00718
00719 if( p_vout->p_sys->i_mode == MODE_VIDEO_OVERLAY )
00720 {
00721 PgDestroyVideoChannel( p_vout->p_sys->p_channel );
00722 }
00723
00724 return( 0 );
00725 }
00726
00727
00728
00729
00730
00731
00732
00733 static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic, int index )
00734 {
00735
00736
00737 p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
00738
00739 if( p_pic->p_sys == NULL )
00740 {
00741 return -1;
00742 }
00743
00744 switch( p_vout->p_sys->i_mode )
00745 {
00746 case MODE_NORMAL_MEM:
00747 case MODE_SHARED_MEM:
00748
00749 if( !( p_pic->p_sys->p_image = PhCreateImage( NULL,
00750 p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
00751 p_vout->p_sys->i_img_type, NULL, 0,
00752 p_vout->p_sys->i_mode == MODE_SHARED_MEM ) ) ) {
00753 msg_Err( p_vout, "cannot create image" );
00754 free( p_pic->p_sys );
00755 return( -1 );
00756 }
00757
00758 p_pic->p->p_pixels = p_pic->p_sys->p_image->image;
00759 p_pic->p->i_lines = p_pic->p_sys->p_image->size.h;
00760 p_pic->p->i_visible_lines = p_pic->p_sys->p_image->size.h;
00761 p_pic->p->i_pitch = p_pic->p_sys->p_image->bpl;
00762 p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
00763 p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
00764 * p_pic->p_sys->p_image->size.w;
00765 p_pic->i_planes = 1;
00766 break;
00767
00768 case MODE_VIDEO_MEM:
00769
00770 if( ( p_pic->p_sys->p_ctx[0] = PdCreateOffscreenContext( 0,
00771 p_vout->p_sys->dim.w, p_vout->p_sys->dim.h,
00772 Pg_OSC_MEM_PAGE_ALIGN) ) == NULL )
00773 {
00774 msg_Err( p_vout, "unable to create offscreen context" );
00775 free( p_pic->p_sys );
00776 return( -1 );
00777 }
00778
00779
00780 if( ( p_pic->p_sys->p_buf[0] =
00781 PdGetOffscreenContextPtr ( p_pic->p_sys->p_ctx[0] ) ) == NULL )
00782 {
00783 msg_Err( p_vout, "unable to get offscreen context ptr" );
00784 PhDCRelease ( p_pic->p_sys->p_ctx[0] );
00785 p_pic->p_sys->p_ctx[0] = NULL;
00786 free( p_pic->p_sys );
00787 return( -1 );
00788 }
00789
00790 p_vout->p_sys->i_bytes_per_line = p_pic->p_sys->p_ctx[0]->pitch;
00791 memset( p_pic->p_sys->p_buf[0], 0,
00792 p_vout->p_sys->i_bytes_per_line * p_vout->p_sys->dim.h );
00793
00794 p_pic->p->p_pixels = p_pic->p_sys->p_buf[0];
00795 p_pic->p->i_lines = p_pic->p_sys->p_ctx[0]->dim.h;
00796 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[0]->dim.h;
00797 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[0]->pitch;
00798 p_pic->p->i_pixel_pitch = p_vout->p_sys->i_bytes_per_pixel;
00799 p_pic->p->i_visible_pitch = p_vout->p_sys->i_bytes_per_pixel
00800 * p_pic->p_sys->p_ctx[0]->dim.w;
00801 p_pic->i_planes = 1;
00802 break;
00803
00804 case MODE_VIDEO_OVERLAY:
00805 if (index == 0)
00806 {
00807 p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane1;
00808 p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane1;
00809 p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane1;
00810 }
00811 else
00812 {
00813 p_pic->p_sys->p_ctx[Y_PLANE] = p_vout->p_sys->p_channel->yplane2;
00814 p_pic->p_sys->p_ctx[U_PLANE] = p_vout->p_sys->p_channel->uplane2;
00815 p_pic->p_sys->p_ctx[V_PLANE] = p_vout->p_sys->p_channel->vplane2;
00816 }
00817
00818 p_pic->p_sys->p_buf[Y_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[Y_PLANE] );
00819 if( p_pic->p_sys->p_buf[Y_PLANE] == NULL )
00820 {
00821 msg_Err( p_vout, "unable to get video channel ctx ptr" );
00822 return( 1 );
00823 }
00824
00825 switch (p_vout->p_sys->i_vc_format)
00826 {
00827 case Pg_VIDEO_FORMAT_YUV420:
00828 p_vout->output.i_chroma = VLC_FOURCC('I','4','2','0');
00829
00830 p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
00831 p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );
00832
00833 if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
00834 p_pic->p_sys->p_buf[V_PLANE] == NULL )
00835 {
00836 msg_Err( p_vout, "unable to get video channel ctx ptr" );
00837 return( 1 );
00838 }
00839
00840 p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
00841 p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00842 p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00843 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00844 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00845 p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
00846
00847 p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
00848 p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
00849 p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
00850 p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
00851 p_pic->p[U_PLANE].i_pixel_pitch = 1;
00852 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
00853
00854 p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
00855 p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
00856 p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
00857 p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
00858 p_pic->p[V_PLANE].i_pixel_pitch = 1;
00859 p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
00860
00861 p_pic->i_planes = 3;
00862 break;
00863
00864 case Pg_VIDEO_FORMAT_YV12:
00865 p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
00866
00867 p_pic->p_sys->p_buf[U_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[U_PLANE] );
00868 p_pic->p_sys->p_buf[V_PLANE] = PdGetOffscreenContextPtr( p_pic->p_sys->p_ctx[V_PLANE] );
00869
00870 if( p_pic->p_sys->p_buf[U_PLANE] == NULL ||
00871 p_pic->p_sys->p_buf[V_PLANE] == NULL )
00872 {
00873 msg_Err( p_vout, "unable to get video channel ctx ptr" );
00874 return( 1 );
00875 }
00876
00877 p_pic->Y_PIXELS = p_pic->p_sys->p_buf[Y_PLANE];
00878 p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00879 p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00880 p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00881 p_pic->p[Y_PLANE].i_pixel_pitch = 1;
00882 p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
00883
00884 p_pic->U_PIXELS = p_pic->p_sys->p_buf[U_PLANE];
00885 p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
00886 p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[U_PLANE]->dim.h;
00887 p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_ctx[U_PLANE]->pitch;
00888 p_pic->p[U_PLANE].i_pixel_pitch = 1;
00889 p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
00890
00891 p_pic->V_PIXELS = p_pic->p_sys->p_buf[V_PLANE];
00892 p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
00893 p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_ctx[V_PLANE]->dim.h;
00894 p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_ctx[V_PLANE]->pitch;
00895 p_pic->p[V_PLANE].i_pixel_pitch = 1;
00896 p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
00897
00898 p_pic->i_planes = 3;
00899 break;
00900
00901 case Pg_VIDEO_FORMAT_UYVY:
00902 case Pg_VIDEO_FORMAT_YUY2:
00903 if (p_vout->p_sys->i_vc_format == Pg_VIDEO_FORMAT_UYVY)
00904 {
00905 p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
00906 }
00907 else
00908 {
00909 p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
00910 }
00911
00912 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
00913 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00914 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00915 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00916 p_pic->p->i_pixel_pitch = 4;
00917 p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
00918
00919 p_pic->i_planes = 1;
00920 break;
00921
00922 case Pg_VIDEO_FORMAT_RGB555:
00923 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
00924 p_vout->output.i_rmask = 0x001f;
00925 p_vout->output.i_gmask = 0x03e0;
00926 p_vout->output.i_bmask = 0x7c00;
00927
00928 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
00929 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00930 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00931 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00932 p_pic->p->i_pixel_pitch = 2;
00933 p_pic->p->i_visible_pitch = 2 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
00934
00935 p_pic->i_planes = 1;
00936 break;
00937
00938 case Pg_VIDEO_FORMAT_RGB565:
00939 p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
00940 p_vout->output.i_rmask = 0x001f;
00941 p_vout->output.i_gmask = 0x07e0;
00942 p_vout->output.i_bmask = 0xf800;
00943
00944 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
00945 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00946 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00947 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00948 p_pic->p->i_pixel_pitch = 4;
00949 p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
00950
00951 p_pic->i_planes = 1;
00952 break;
00953
00954 case Pg_VIDEO_FORMAT_RGB8888:
00955 p_vout->output.i_chroma = VLC_FOURCC('R','V','3','2');
00956 p_vout->output.i_rmask = 0x000000ff;
00957 p_vout->output.i_gmask = 0x0000ff00;
00958 p_vout->output.i_bmask = 0x00ff0000;
00959
00960 p_pic->p->p_pixels = p_pic->p_sys->p_buf[Y_PLANE];
00961 p_pic->p->i_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00962 p_pic->p->i_visible_lines = p_pic->p_sys->p_ctx[Y_PLANE]->dim.h;
00963 p_pic->p->i_pitch = p_pic->p_sys->p_ctx[Y_PLANE]->pitch;
00964 p_pic->p->i_pixel_pitch = 4;
00965 p_pic->p->i_visible_pitch = 4 * p_pic->p_sys->p_ctx[Y_PLANE]->dim.w;
00966
00967 p_pic->i_planes = 1;
00968 break;
00969 }
00970
00971 #if 0
00972 switch( p_vout->output.i_chroma )
00973 {
00974 #ifdef MODULE_NAME_IS_xvideo
00975 case VLC_FOURCC('Y','2','1','1'):
00976
00977 p_pic->p->p_pixels = p_pic->p_sys->p_image->data
00978 + p_pic->p_sys->p_image->offsets[0];
00979 p_pic->p->i_lines = p_vout->output.i_height;
00980 p_pic->p->i_visible_lines = p_vout->output.i_height;
00981
00982 p_pic->p->i_pitch = p_pic->p_sys->p_image->pitches[0] / 4;
00983 p_pic->p->i_pixel_pitch = 4;
00984 p_pic->p->i_visible_pitch = p_pic->p->i_pitch;
00985
00986 p_pic->i_planes = 1;
00987 break;
00988 #endif
00989
00990 #endif
00991
00992 default:
00993
00994 break;
00995 }
00996
00997 return 0;
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008 static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
01009 {
01010 if( ( p_vout->p_sys->i_mode == MODE_NORMAL_MEM ||
01011 p_vout->p_sys->i_mode == MODE_SHARED_MEM ) &&
01012 p_pic->p_sys->p_image )
01013 {
01014 PhReleaseImage( p_pic->p_sys->p_image );
01015 free( p_pic->p_sys->p_image );
01016 }
01017 else if( p_vout->p_sys->i_mode == MODE_VIDEO_MEM &&
01018 p_pic->p_sys->p_ctx[0] )
01019 {
01020 PhDCRelease( p_pic->p_sys->p_ctx[0] );
01021 }
01022
01023 free( p_pic->p_sys );
01024 }
01025
01026
01027 static int ResizeOverlayOutput(vout_thread_t *p_vout)
01028 {
01029 int i_width, i_height, i_x, i_y;
01030 int i_ret;
01031 PgScalerProps_t props;
01032
01033 props.size = sizeof( props );
01034 props.format = p_vout->p_sys->i_vc_format;
01035 props.flags = Pg_SCALER_PROP_SCALER_ENABLE |
01036 Pg_SCALER_PROP_DOUBLE_BUFFER;
01037
01038
01039 if( p_vout->p_sys->i_vc_flags & Pg_SCALER_CAP_DST_CHROMA_KEY )
01040 {
01041 props.flags |= Pg_SCALER_PROP_CHROMA_ENABLE;
01042 }
01043
01044
01045 props.viewport.ul.x = p_vout->p_sys->pos.x;
01046 props.viewport.ul.y = p_vout->p_sys->pos.y;
01047 if( !p_vout->b_fullscreen )
01048 {
01049 props.viewport.ul.x += p_vout->p_sys->frame.ul.x;
01050 props.viewport.ul.y += p_vout->p_sys->frame.ul.y;
01051 }
01052
01053
01054 vout_PlacePicture( p_vout, p_vout->p_sys->dim.w,
01055 p_vout->p_sys->dim.h,
01056 &i_x, &i_y, &i_width, &i_height );
01057
01058 props.viewport.ul.x += i_x;
01059 props.viewport.ul.y += i_y;
01060 props.viewport.lr.x = i_width + props.viewport.ul.x;
01061 props.viewport.lr.y = i_height + props.viewport.ul.y;
01062
01063
01064 props.src_dim.w = p_vout->output.i_width;
01065 props.src_dim.h = p_vout->output.i_height;
01066
01067
01068 i_ret = PgConfigScalerChannel( p_vout->p_sys->p_channel, &props );
01069
01070 if( i_ret == -1 )
01071 {
01072 msg_Err( p_vout, "unable to configure video channel" );
01073 return( 1 );
01074 }
01075
01076 return ( 0 );
01077 }
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 static void SetPalette( vout_thread_t *p_vout,
01088 uint16_t *red, uint16_t *green, uint16_t *blue )
01089 {
01090 int i;
01091
01092
01093 for( i = 0; i < 255; i++ )
01094 {
01095
01096
01097 p_vout->p_sys->p_colors[ i ] = PgRGB( red[ i ] >> 8, green[ i ] >> 8, blue[ i ] >> 8 );
01098 }
01099 }