--- gui/interface.c 2007-10-07 21:49:27.000000000 +0200 +++ gui/interface.c 2007-10-23 15:42:03.000000000 +0200 @@ -46,6 +46,9 @@ #ifdef USE_DVDREAD #include "stream/stream_dvd.h" #endif +#ifdef USE_DVDNAV +#include "stream/stream_dvdnav.h" +#endif int vcd_seek_to_track(void *vcd, int track); @@ -514,6 +517,9 @@ #ifdef USE_DVDREAD dvd_priv_t * dvdp = (dvd_priv_t *) arg; #endif +#ifdef USE_DVDNAV + dvdnav_priv_t * dvdnavp = (dvdnav_priv_t *) arg; +#endif if (guiIntfStruct.mpcontext) { audio_out = mpctx_get_audio_out(guiIntfStruct.mpcontext); @@ -590,6 +596,24 @@ guiIntfStruct.Track=dvd_title + 1; break; #endif +#ifdef USE_DVDNAV + case guiSetDVDNAV: + guiIntfStruct.DVDNAV.titles=dvdnavp->titles_nr; + guiIntfStruct.DVDNAV.chapters=dvdnavp->chapters_nr; + guiIntfStruct.DVDNAV.current_title=dvdnavp->title; + guiIntfStruct.DVDNAV.current_chapter=dvdnavp->part; + guiIntfStruct.DVDNAV.nr_of_audio_channels=dvdnavp->nr_of_channels; + memcpy( guiIntfStruct.DVDNAV.audio_streams, + dvdnavp->audio_streams, + sizeof( dvdnavp->audio_streams ) ); + guiIntfStruct.DVDNAV.nr_of_subtitles=dvdnavp->nr_of_subtitles; + memcpy( guiIntfStruct.DVDNAV.subtitles, + dvdnavp->subtitles, + sizeof( dvdnavp->subtitles ) ); + guiIntfStruct.DVDNAV.current_title=dvdnavp->title; + guiIntfStruct.DVDNAV.current_chapter=dvdnavp->part; + break; +#endif case guiSetStream: guiIntfStruct.StreamType=stream->type; switch( stream->type ) @@ -599,6 +623,11 @@ guiGetEvent( guiSetDVD,(char *)stream->priv ); break; #endif +#ifdef USE_DVDNAV + case STREAMTYPE_DVDNAV: + guiGetEvent( guiSetDVDNAV,(char *)stream->priv ); + break; +#endif #ifdef HAVE_VCD case STREAMTYPE_VCD: { @@ -746,6 +775,17 @@ dvd_angle=guiIntfStruct.Angle; break; #endif +#ifdef USE_DVDNAV + case STREAMTYPE_DVDNAV: + { + char tmp[512]; + sprintf( tmp,"dvdnav://"); + guiSetFilename( guiIntfStruct.Filename,tmp ); + } + dvd_chapter=guiIntfStruct.Chapter; + dvd_angle=guiIntfStruct.Angle; + break; +#endif } //if ( guiIntfStruct.StreamType != STREAMTYPE_PLAYLIST ) // Does not make problems anymore! { @@ -1108,6 +1148,10 @@ #ifdef USE_DVDREAD if ( (unsigned int)vparam & guiDVD ) memset( &guiIntfStruct.DVD,0,sizeof( guiDVDStruct ) ); #endif +#ifdef USE_DVDNAV + if ( (unsigned int)vparam & guiDVDNAV ) + memset( &guiIntfStruct.DVDNAV,0,sizeof( guiDVDNAVStruct ) ); +#endif #ifdef HAVE_VCD if ( (unsigned int)vparam & guiVCD ) guiIntfStruct.VCDTracks=0; #endif --- gui/interface.h 2007-10-07 21:49:27.000000000 +0200 +++ gui/interface.h 2007-10-23 15:42:03.000000000 +0200 @@ -10,6 +10,9 @@ #ifdef USE_DVDREAD #include "stream/stream.h" #endif +#ifdef USE_DVDNAV + #include "stream/stream_dvdnav.h" +#endif typedef struct { @@ -50,6 +53,22 @@ } guiDVDStruct; #endif +#ifdef USE_DVDNAV +typedef struct +{ + int titles; + int chapters; + int angles; + int current_chapter; + int current_title; + int current_angle; + int nr_of_audio_channels; + stream_language_t audio_streams[32]; + int nr_of_subtitles; + stream_language_t subtitles[32]; +} guiDVDNAVStruct; +#endif + typedef struct { int message; @@ -73,6 +92,13 @@ int Chapter; #endif +#ifdef USE_DVDNAV + guiDVDNAVStruct DVDNAV; + int NavTitle; + int NavAngle; + int NavChapter; +#endif + #ifdef HAVE_VCD int VCDTracks; #endif @@ -133,6 +159,9 @@ #define guiSetParameters 16 #define guiSetAfilter 17 #define guiSetContext 18 +#ifdef USE_DVDNAV +#define guiSetDVDNAV 19 +#endif #define guiSetStop 0 #define guiSetPlay 1 @@ -141,6 +170,9 @@ #define guiDVD 1 #define guiVCD 2 #define guiFilenames 4 +#ifdef USE_DVDNAV +#define guiDVDNAV 8 +#endif #define guiALL 0xffffffff extern int use_gui; --- gui/app.h 2007-10-07 21:49:27.000000000 +0200 +++ gui/app.h 2007-10-23 15:42:03.000000000 +0200 @@ -62,6 +62,10 @@ #define evSetVideo 46 #define evSetSubtitle 47 // 48 ... +//#ifdef USE_DVDNAV +#define evPlayDVDNAV 49 +#define evMenuDVDNAV 50 +//#endif #define evExit 1000 @@ -81,6 +85,12 @@ #define evSubtitleLoaded 5011 #define evSetVCDTrack 5012 #define evSetURL 5013 +//#ifdef USE_DVDNAV +#define evSetDVDNAVAudio 5014 +#define evSetDVDNAVSubtitle 5015 +#define evSetDVDNAVTitle 5016 +#define evSetDVDNAVChapter 5017 +//#endif #define evFName 7000 #define evMovieTime 7001 --- gui/mplayer/gtk/menu.c 2007-10-07 21:49:27.000000000 +0200 +++ gui/mplayer/gtk/menu.c 2007-10-23 15:42:03.000000000 +0200 @@ -377,6 +377,9 @@ GtkWidget * DVDSubMenu; +#ifdef USE_DVDNAV +GtkWidget * DVDNAVSubMenu; +#endif GtkWidget * DVDTitleMenu; GtkWidget * DVDChapterMenu; GtkWidget * DVDAudioLanguageMenu; @@ -410,6 +413,9 @@ #ifdef USE_DVDREAD AddMenuItem( window1, (const char*)playdvd_xpm, SubMenu,MSGTR_MENU_PlayDVD, evPlayDVD ); #endif +#ifdef USE_DVDNAV + AddMenuItem( window1, (const char*)playdvd_xpm, SubMenu,MSGTR_MENU_PlayDVDNAV, evPlayDVDNAV ); +#endif AddMenuItem( window1, (const char*)url_xpm, SubMenu,MSGTR_MENU_PlayURL, evSetURL ); AddMenuItem( window1, (const char*)sub_xpm, SubMenu,MSGTR_MENU_LoadSubtitle" ", evLoadSubtitle ); AddMenuItem( window1, (const char*)delsub_xpm, SubMenu,MSGTR_MENU_DropSubtitle,evDropSubtitle ); @@ -527,6 +533,87 @@ gtk_widget_set_sensitive( MenuItem,FALSE ); } #endif +#ifdef USE_DVDNAV + DVDNAVSubMenu=AddSubMenu( window1, (const char*)dvd_xpm, Menu,MSGTR_MENU_DVDNAV ); + AddMenuItem( window1, (const char*)playdvd_xpm, DVDNAVSubMenu,MSGTR_MENU_PlayDisc" ", evPlayDVDNAV ); + MenuItem=AddMenuItem( window1, (const char*)prefs_xpm, DVDNAVSubMenu,MSGTR_MENU_MenuDVDNAV" ", evMenuDVDNAV ); + if (guiIntfStruct.DVDNAV.current_title==0) + gtk_widget_set_sensitive( MenuItem,FALSE ); else + gtk_widget_set_sensitive( MenuItem,TRUE ); +// AddMenuItem( DVDNAVSubMenu,MSGTR_MENU_ShowDVDMenu, evNone ); + AddSeparator( DVDNAVSubMenu ); + DVDTitleMenu=AddSubMenu( window1, (const char*)title_xpm, DVDNAVSubMenu,MSGTR_MENU_Titles ); + if ( guiIntfStruct.DVDNAV.titles ) + { + char tmp[32]; int i; + for ( i=1 ; i<= guiIntfStruct.DVDNAV.titles;i++ ) + { + snprintf( tmp,32,MSGTR_MENU_Title,i); + AddMenuCheckItem( window1, (const char*)empty1px_xpm, DVDTitleMenu,tmp, + guiIntfStruct.DVDNAV.current_title == i, + (i << 16) + evSetDVDNAVTitle ); + } + } + else + { + MenuItem=AddMenuItem( window1, (const char*)empty_xpm, DVDTitleMenu,MSGTR_MENU_None,evNone ); + gtk_widget_set_sensitive( MenuItem,FALSE ); + } + DVDChapterMenu=AddSubMenu( window1, (const char*)chapter_xpm, DVDNAVSubMenu,MSGTR_MENU_Chapters ); + if ( guiIntfStruct.DVDNAV.chapters ) + { + char tmp[32]; int i; + for ( i=1;i <= guiIntfStruct.DVDNAV.chapters;i++ ) + { + snprintf( tmp,32,MSGTR_MENU_Chapter,i ); + AddMenuCheckItem( window1, (const char*)empty1px_xpm, DVDChapterMenu,tmp,guiIntfStruct.DVDNAV.current_chapter == i, + ( i << 16 ) + evSetDVDNAVChapter ); + } + } + else + { + MenuItem=AddMenuItem( window1, (const char*)empty_xpm, DVDChapterMenu,MSGTR_MENU_None,evNone ); + gtk_widget_set_sensitive( MenuItem,FALSE ); + } + DVDAudioLanguageMenu=AddSubMenu( window1, (const char*)tongue_xpm, DVDNAVSubMenu,MSGTR_MENU_AudioLanguages ); + if ( guiIntfStruct.DVDNAV.nr_of_audio_channels ) + { + char tmp[64]; int i, id = guiIntfStruct.demuxer ? ((demuxer_t *)guiIntfStruct.demuxer)->audio->id : audio_id; + for ( i=0;i < guiIntfStruct.DVDNAV.nr_of_audio_channels;i++ ) + { + snprintf( tmp,64,"%s - %s %s",GetLanguage( guiIntfStruct.DVDNAV.audio_streams[i].language ), + ChannelTypes[ guiIntfStruct.DVDNAV.audio_streams[i].type ], + ChannelNumbers[ guiIntfStruct.DVDNAV.audio_streams[i].channels ] ); +// if ( id == -1 ) id=audio_id; //guiIntfStruct.DVD.audio_streams[i].id; + AddMenuCheckItem( window1, (const char*)dolby_xpm, DVDAudioLanguageMenu,tmp, + id == guiIntfStruct.DVDNAV.audio_streams[i].id, + ( guiIntfStruct.DVDNAV.audio_streams[i].id << 16 ) + evSetDVDNAVAudio ); + } + } + else + { + MenuItem=AddMenuItem( window1, (const char*)empty_xpm, DVDAudioLanguageMenu,MSGTR_MENU_None,evNone ); + gtk_widget_set_sensitive( MenuItem,FALSE ); + } + DVDSubtitleLanguageMenu=AddSubMenu( window1, (const char*)tonguebla_xpm, DVDNAVSubMenu,MSGTR_MENU_SubtitleLanguages ); + if ( guiIntfStruct.DVDNAV.nr_of_subtitles ) + { + char tmp[64]; int i; + AddMenuItem( window1, (const char*)empty1px_xpm, DVDSubtitleLanguageMenu,MSGTR_MENU_None,( (unsigned short)-1 << 16 ) + evSetDVDNAVSubtitle ); + for ( i=0;i < guiIntfStruct.DVDNAV.nr_of_subtitles;i++ ) + { + snprintf( tmp,64,"%s",GetLanguage( guiIntfStruct.DVDNAV.subtitles[i].language ) ); + AddMenuCheckItem( window1, (const char*)empty1px_xpm, DVDSubtitleLanguageMenu,tmp, + dvdsub_id == guiIntfStruct.DVDNAV.subtitles[i].id, + ( guiIntfStruct.DVDNAV.subtitles[i].id << 16 ) + evSetDVDNAVSubtitle ); + } + } + else + { + MenuItem=AddMenuItem( window1, (const char*)empty_xpm, DVDSubtitleLanguageMenu,MSGTR_MENU_None,evNone ); + gtk_widget_set_sensitive( MenuItem,FALSE ); + } +#endif // if ( guiIntfStruct.Playing ) { @@ -575,7 +662,7 @@ } /* cheap subtitle switching for non-DVD streams */ - if ( global_sub_size && guiIntfStruct.StreamType != STREAMTYPE_DVD ) + if ( global_sub_size && guiIntfStruct.StreamType != STREAMTYPE_DVD && guiIntfStruct.StreamType != STREAMTYPE_DVDNAV ) { int i; SubMenu=AddSubMenu( window1, (const char*)empty_xpm, Menu, MSGTR_MENU_Subtitles ); --- gui/mplayer/mw.c 2007-10-07 21:49:27.000000000 +0200 +++ gui/mplayer/mw.c 2007-10-23 15:42:03.000000000 +0200 @@ -33,6 +33,8 @@ #define GUI_REDRAW_WAIT 375 +#define FIXME_GTK_MENU_ActivateMenuItem_PARAM 1 + #include "play.h" #include "widgets.h" @@ -80,6 +82,7 @@ { int iparam = (int)param; mixer_t *mixer = mpctx_get_mixer(guiIntfStruct.mpcontext); + char cmd_str[40]; switch( msg ) { @@ -129,6 +132,16 @@ guiIntfStruct.StreamType=STREAMTYPE_DVD; goto play; #endif +#ifdef USE_DVDNAV + case evPlayDVDNAV: + guiIntfStruct.DVDNAV.current_title=1; + guiIntfStruct.DVDNAV.current_chapter=1; + guiIntfStruct.DVDNAV.current_angle=1; +play_dvdnav_2: + gtkSet( gtkClearStruct,0,(void *)(guiALL - guiDVDNAV) ); + guiIntfStruct.StreamType=STREAMTYPE_DVDNAV; + goto play; +#endif case evPlay: case evPlaySwitchToPause: play: @@ -178,6 +191,21 @@ } break; #endif +#ifdef USE_DVDNAV + case STREAMTYPE_DVDNAV: + gtkSet( gtkClearStruct,0, + (void *)(guiALL - guiDVDNAV - guiFilenames) ); + if ( !dvd_device ) dvd_device=gstrdup( DEFAULT_DVD_DEVICE ); + mplSetFileName( NULL,dvd_device,STREAMTYPE_DVDNAV ); + if ( guiIntfStruct.Playing != 2 ) + { + guiIntfStruct.Title=guiIntfStruct.DVDNAV.current_title; + guiIntfStruct.Chapter=guiIntfStruct.DVDNAV.current_chapter; + guiIntfStruct.Angle=guiIntfStruct.DVDNAV.current_angle; + guiIntfStruct.DiskChanged=1; + } + break; +#endif } guiIntfStruct.NewPlay=1; mplPlay(); @@ -202,6 +230,50 @@ goto play_dvd_2; break; #endif +#ifdef USE_DVDNAV + case evSetDVDNAVSubtitle: +#ifdef FIXME_GTK_MENU_ActivateMenuItem_PARAM + dvdsub_id=gtkPopupMenuParam; +#else + dvdsub_id=iparam; +#endif + sprintf(cmd_str,"sub_select %d",dvdsub_id); + mp_input_queue_cmd(mp_input_parse_cmd(cmd_str)); + break; + case evSetDVDNAVAudio: +#ifdef FIXME_GTK_MENU_ActivateMenuItem_PARAM + audio_id=gtkPopupMenuParam; +#else + audio_id=iparam; +#endif + sprintf(cmd_str,"switch_audio %d",audio_id); + mp_input_queue_cmd(mp_input_parse_cmd(cmd_str)); + break; + case evSetDVDNAVChapter: +#ifdef FIXME_GTK_MENU_ActivateMenuItem_PARAM + sprintf(cmd_str,"switch_chapter %d",gtkPopupMenuParam); +#else + sprintf(cmd_str,"switch_chapter %d",iparam); +#endif + mp_input_queue_cmd(mp_input_parse_cmd(cmd_str)); + guiIntfStruct.DVDNAV.current_chapter=iparam; + break; + case evSetDVDNAVTitle: +#ifdef FIXME_GTK_MENU_ActivateMenuItem_PARAM + sprintf(cmd_str,"switch_title %d",gtkPopupMenuParam); +#else + sprintf(cmd_str,"switch_title %d",iparam); +#endif + mp_input_queue_cmd(mp_input_parse_cmd(cmd_str)); + guiIntfStruct.DVDNAV.current_title=iparam; + guiIntfStruct.DVDNAV.current_chapter=1; + guiIntfStruct.DVDNAV.current_angle=1; + break; + case evMenuDVDNAV: + sprintf(cmd_str,"dvdnav 5"); + mp_input_queue_cmd(mp_input_parse_cmd(cmd_str)); + break; +#endif case evPause: case evPauseSwitchToPlay: @@ -339,6 +411,10 @@ default: movie_aspect=-1; } wsClearWindow( appMPlayer.subWindow ); +#ifdef USE_DVDNAV + if ( guiIntfStruct.StreamType == STREAMTYPE_DVDNAV ) goto play_dvdnav_2; + else +#endif #ifdef USE_DVDREAD if ( guiIntfStruct.StreamType == STREAMTYPE_DVD || guiIntfStruct.StreamType == STREAMTYPE_VCD ) goto play_dvd_2; else --- gui/mplayer/sw.c 2007-10-07 21:49:27.000000000 +0200 +++ gui/mplayer/sw.c 2007-10-23 15:42:03.000000000 +0200 @@ -19,6 +19,18 @@ extern int boxMoved; extern int sx,sy; extern int i,pot; +extern int enable_mouse_movements; + +#ifdef USE_DVDNAV +#include "input/input.h" +#include "input/mouse.h" +//extern int dvdnav_window_width; +//extern int dvdnav_window_height; +//extern int dvdnav_mouse_x; +//extern int dvdnav_mouse_y; +//extern int dvdnav_mouse_button; +//extern int dvdnav_mouse_set; +#endif void mplSubDraw( void ) { @@ -66,8 +78,19 @@ sx=X; sy=Y; msButton=wsPLMouseButton; mplSubMoved=0; +#ifdef USE_DVDNAV + mplayer_put_key(MOUSE_BTN0); +#endif break; case wsMoveMouse: +#ifdef USE_DVDNAV + if(enable_mouse_movements) + { + char cmd_str[40]; + sprintf(cmd_str,"set_mouse_pos %i %i", X, Y); + mp_input_queue_cmd(mp_input_parse_cmd(cmd_str)); + } +#endif switch ( msButton ) { case wsPLMouseButton: --- gui/mplayer/common.c 2007-10-07 21:49:27.000000000 +0200 +++ gui/mplayer/common.c 2007-10-23 15:56:25.000000000 +0200 @@ -60,6 +60,15 @@ else av_strlcat( tmp,MSGTR_NoChapter,tmplen ); break; #endif +#ifdef USE_DVDNAV + case STREAMTYPE_DVDNAV: + if ( guiIntfStruct.DVDNAV.current_chapter ) + snprintf(tmp,tmplen,MSGTR_Chapter, + guiIntfStruct.DVDNAV.current_chapter ); + else + av_strlcat( tmp,MSGTR_NoChapter,tmplen ); + break; +#endif #ifdef HAVE_VCD case STREAMTYPE_VCD: snprintf( tmp,tmplen,MSGTR_VCDTrack,guiIntfStruct.Track ); @@ -164,6 +173,9 @@ #ifdef USE_DVDREAD case STREAMTYPE_DVD: av_strlcat( trbuf,"d",sizeof( trbuf ) ); break; #endif +#ifdef USE_DVDNAV + case STREAMTYPE_DVDNAV: av_strlcat( trbuf,"d",sizeof( trbuf ) ); break; +#endif default: av_strlcat( trbuf," ",sizeof( trbuf ) ); break; } break; --- gui/mplayer/play.c 2007-10-07 21:49:27.000000000 +0200 +++ gui/mplayer/play.c 2007-10-23 15:42:03.000000000 +0200 @@ -92,6 +92,11 @@ guiIntfStruct.DVD.current_chapter=1; guiIntfStruct.DVD.current_angle=1; #endif +#ifdef USE_DVDNAV + guiIntfStruct.DVDNAV.current_title=1; + guiIntfStruct.DVDNAV.current_chapter=1; + guiIntfStruct.DVDNAV.current_angle=1; +#endif if ( !appMPlayer.subWindow.isFullScreen && gtkShowVideoWindow) { @@ -279,6 +284,10 @@ case STREAMTYPE_DVD: break; #endif +#ifdef USE_DVDNAV + case STREAMTYPE_DVDNAV: + break; +#endif #ifdef HAVE_VCD case STREAMTYPE_VCD: break; @@ -315,6 +324,16 @@ guiIntfStruct.Track=guiIntfStruct.DVD.current_title; break; #endif +#ifdef USE_DVDNAV + case STREAMTYPE_DVDNAV: + if ( --guiIntfStruct.DVDNAV.current_chapter == 0 ) + { + guiIntfStruct.DVDNAV.current_chapter=1; + if ( --guiIntfStruct.DVDNAV.current_title <= 0 ) { guiIntfStruct.DVDNAV.current_title=1; stop=1; } + } + guiIntfStruct.Track=guiIntfStruct.DVDNAV.current_title; + break; +#endif #ifdef HAVE_VCD case STREAMTYPE_VCD: if ( --guiIntfStruct.Track == 0 ) { guiIntfStruct.Track=1; stop=1; } @@ -351,6 +370,16 @@ guiIntfStruct.Track=guiIntfStruct.DVD.current_title; break; #endif +#ifdef USE_DVDNAV + case STREAMTYPE_DVDNAV: + if ( guiIntfStruct.DVDNAV.current_chapter++ == guiIntfStruct.DVDNAV.chapters ) + { + guiIntfStruct.DVDNAV.current_chapter=1; + if ( ++guiIntfStruct.DVDNAV.current_title > guiIntfStruct.DVDNAV.titles ) { guiIntfStruct.DVDNAV.current_title=guiIntfStruct.DVDNAV.titles; stop=1; } + } + guiIntfStruct.Track=guiIntfStruct.DVDNAV.current_title; + break; +#endif #ifdef HAVE_VCD case STREAMTYPE_VCD: if ( ++guiIntfStruct.Track > guiIntfStruct.VCDTracks ) { guiIntfStruct.Track=guiIntfStruct.VCDTracks; stop=1; } --- help/help_mp-en.h 2007-10-07 21:49:32.000000000 +0200 +++ help/help_mp-en.h 2007-10-23 15:43:13.000000000 +0200 @@ -824,6 +824,10 @@ #define MSGTR_MENU_Track "Track %d" #define MSGTR_MENU_VideoTrack "Video track" #define MSGTR_MENU_Subtitles "Subtitles" +// mpdvdnav - gui +#define MSGTR_MENU_DVDNAV "DVDNAV" +#define MSGTR_MENU_PlayDVDNAV "Play DVDNAV..." +#define MSGTR_MENU_MenuDVDNAV "Main DVD Menu" // --- equalizer // Note: If you change MSGTR_EQU_Audio please see if it still fits MSGTR_PREFERENCES_Audio --- libmpcodecs/vf_expand.c 2007-10-07 21:49:25.000000000 +0200 +++ libmpcodecs/vf_expand.c 2007-10-08 21:09:26.000000000 +0200 @@ -96,7 +96,7 @@ } } -static void draw_func(int x0,int y0, int w,int h,unsigned char* src, unsigned char *srca, int stride){ +static void draw_func(int x0,int y0, int w,int h,int dp,unsigned char* src, unsigned char *srca, int stride){ unsigned char* dst; if(!vo_osd_changed_flag && vf->dmpi->planes[0]==vf->priv->fb_ptr){ // ok, enough to update the area inside the video, leave the black bands @@ -124,19 +124,19 @@ switch(vf->dmpi->imgfmt){ case IMGFMT_BGR15: case IMGFMT_RGB15: - vo_draw_alpha_rgb15(w,h,src,srca,stride,dst,vf->dmpi->stride[0]); + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]); break; case IMGFMT_BGR16: case IMGFMT_RGB16: - vo_draw_alpha_rgb16(w,h,src,srca,stride,dst,vf->dmpi->stride[0]); + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]); break; case IMGFMT_BGR24: case IMGFMT_RGB24: - vo_draw_alpha_rgb24(w,h,src,srca,stride,dst,vf->dmpi->stride[0]); + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]); break; case IMGFMT_BGR32: case IMGFMT_RGB32: - vo_draw_alpha_rgb32(w,h,src,srca,stride,dst,vf->dmpi->stride[0]); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]); break; case IMGFMT_YV12: case IMGFMT_I420: @@ -145,13 +145,13 @@ case IMGFMT_IF09: case IMGFMT_Y800: case IMGFMT_Y8: - vo_draw_alpha_yv12(w,h,src,srca,stride,dst,vf->dmpi->stride[0]); + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]); break; case IMGFMT_YUY2: - vo_draw_alpha_yuy2(w,h,src,srca,stride,dst,vf->dmpi->stride[0]); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,dst,vf->dmpi->stride[0]); break; case IMGFMT_UYVY: - vo_draw_alpha_yuy2(w,h,src,srca,stride,dst+1,vf->dmpi->stride[0]); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,dst+1,vf->dmpi->stride[0]); break; } } --- input/input.c 2007-10-07 21:49:26.000000000 +0200 +++ input/input.c 2007-10-23 16:38:47.000000000 +0200 @@ -112,6 +112,8 @@ { MP_CMD_GET_META_TRACK, "get_meta_track", 0, { {-1,{0}} } }, { MP_CMD_GET_META_GENRE, "get_meta_genre", 0, { {-1,{0}} } }, { MP_CMD_SWITCH_AUDIO, "switch_audio", 0, { { MP_CMD_ARG_INT,{-1} }, {-1,{0}} } }, + { MP_CMD_SWITCH_TITLE, "switch_title", 0, { { MP_CMD_ARG_INT,{-1} }, {-1,{0}} } }, + { MP_CMD_SWITCH_CHAPTER, "switch_chapter", 0, { { MP_CMD_ARG_INT,{-1} }, {-1,{0}} } }, #ifdef USE_TV { MP_CMD_TV_START_SCAN, "tv_start_scan", 0, { {-1,{0}} }}, { MP_CMD_TV_STEP_CHANNEL, "tv_step_channel", 1, { { MP_CMD_ARG_INT ,{0}}, {-1,{0}} }}, --- input/input.h 2007-10-07 21:49:26.000000000 +0200 +++ input/input.h 2007-10-23 16:30:59.000000000 +0200 @@ -99,6 +99,8 @@ #define MP_CMD_TV_TELETEXT_ADD_DEC 98 #define MP_CMD_TV_TELETEXT_GO_LINK 99 #define MP_CMD_TV_START_SCAN 100 +#define MP_CMD_SWITCH_TITLE 101 +#define MP_CMD_SWITCH_CHAPTER 102 #define MP_CMD_GUI_EVENTS 5000 #define MP_CMD_GUI_LOADFILE 5001 --- libvo/vo_fbdev.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_fbdev.c 2007-10-08 21:09:26.000000000 +0200 @@ -558,7 +558,7 @@ static int fb_line_len; static int fb_xres; static int fb_yres; -static void (*draw_alpha_p)(int w, int h, unsigned char *src, +static void (*draw_alpha_p)(int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride, unsigned char *dst, int dstride); @@ -1049,14 +1049,14 @@ return 0; } -static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { unsigned char *dst; dst = center + fb_line_len * y0 + fb_pixel_size * x0; - (*draw_alpha_p)(w, h, src, srca, stride, dst, fb_line_len); + (*draw_alpha_p)(w, h, dp, src, srca, stride, dst, fb_line_len); } static int draw_frame(uint8_t *src[]) { return 1; } @@ -1170,6 +1170,13 @@ return get_image(data); case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data)); + case VOCTRL_YUVSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + if (fb_bpp == 32 || fb_bpp==24 || fb_bpp==16 || fb_bpp==15) return VO_TRUE; + return VO_FALSE; } #ifdef CONFIG_VIDIX --- libvo/vo_directfb2.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_directfb2.c 2007-10-08 21:09:26.000000000 +0200 @@ -1442,6 +1442,20 @@ return(directfb_get_video_eq(data, value)); } + case VOCTRL_YUVSPU_SUPPORT: + if (pixel_format==DSPF_I420 || pixel_format==DSPF_YV12) return VO_TRUE; + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + if (pixel_format==DSPF_RGB32 || pixel_format==DSPF_ARGB || pixel_format==DSPF_RGB24 || + pixel_format==DSPF_RGB16) return VO_TRUE; +#if DIRECTFBVERSION > 915 + if (pixel_format==DSPF_ARGB1555) return VO_TRUE; +#else + if (pixel_format==DSPF_RGB15) return VO_TRUE; +#endif + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + return VO_FALSE; }; return VO_NOTIMPL; } @@ -1455,7 +1469,7 @@ // hopefully will be removed soon -static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { void *dst; @@ -1474,35 +1488,51 @@ switch(pixel_format) { case DSPF_RGB32: case DSPF_ARGB: - vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 4*x0,pitch); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 4*x0,pitch); break; case DSPF_RGB24: - vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 3*x0,pitch); + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 3*x0,pitch); break; case DSPF_RGB16: - vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch); + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch); break; #if DIRECTFBVERSION > DFB_VERSION(0,9,15) case DSPF_ARGB1555: #else case DSPF_RGB15: #endif - vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch); + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,((uint8_t *) dst)+pitch*y0 + 2*x0,pitch); break; case DSPF_YUY2: - vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0,pitch); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0,pitch); break; case DSPF_UYVY: - vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0 + 1,pitch); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 2*x0 + 1,pitch); break; case DSPF_I420: case DSPF_YV12: - vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 1*x0,pitch); + switch (dp) { + case DEST_PLANES_Y: + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*y0 + 1*x0,pitch); + break; + case DEST_PLANES_U: + if (pixel_format==DSPF_YV12) + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*height/4 + pitch*y0 + 1*x0,pitch); + else + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*height/2 + pitch*y0 + 1*x0,pitch); + break; + case DEST_PLANES_V: + if (pixel_format==DSPF_YV12) + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*height/2 + pitch*y0 + 1*x0,pitch); + else + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) dst) + pitch*height/4 + pitch*y0 + 1*x0,pitch); + break; + } break; } --- libvo/vo_vesa.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_vesa.c 2007-10-08 21:09:26.000000000 +0200 @@ -47,6 +47,7 @@ #include "vosub_vidix.h" #endif #include "mp_msg.h" +#include "help_mp.h" #include "libswscale/swscale.h" #include "libmpcodecs/vf_scale.h" @@ -108,7 +109,7 @@ static unsigned video_mode; /* selected video mode for playback */ static struct VesaModeInfoBlock video_mode_info; static int flip_trigger = 0; -static void (*draw_alpha_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride); +static void (*draw_alpha_fnc)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride); /* multibuffering */ uint8_t* video_base; /* should be never changed */ @@ -296,7 +297,7 @@ /* Please comment it out if you want have OSD within movie */ /*#define OSD_OUTSIDE_MOVIE 1*/ -static void draw_alpha_32(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride) +static void draw_alpha_32(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride) { int dstride=HAS_DGA()?video_mode_info.XResolution:dstW; #ifndef OSD_OUTSIDE_MOVIE @@ -306,10 +307,10 @@ y0 += y_offset; } #endif - vo_draw_alpha_rgb32(w,h,src,srca,stride,dga_buffer+4*(y0*dstride+x0),4*dstride); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,dga_buffer+4*(y0*dstride+x0),4*dstride); } -static void draw_alpha_24(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride) +static void draw_alpha_24(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride) { int dstride=HAS_DGA()?video_mode_info.XResolution:dstW; #ifndef OSD_OUTSIDE_MOVIE @@ -319,10 +320,10 @@ y0 += y_offset; } #endif - vo_draw_alpha_rgb24(w,h,src,srca,stride,dga_buffer+3*(y0*dstride+x0),3*dstride); + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,dga_buffer+3*(y0*dstride+x0),3*dstride); } -static void draw_alpha_16(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride) +static void draw_alpha_16(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride) { int dstride=HAS_DGA()?video_mode_info.XResolution:dstW; #ifndef OSD_OUTSIDE_MOVIE @@ -332,10 +333,10 @@ y0 += y_offset; } #endif - vo_draw_alpha_rgb16(w,h,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride); + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride); } -static void draw_alpha_15(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride) +static void draw_alpha_15(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride) { int dstride=HAS_DGA()?video_mode_info.XResolution:dstW; #ifndef OSD_OUTSIDE_MOVIE @@ -345,15 +346,16 @@ y0 += y_offset; } #endif - vo_draw_alpha_rgb15(w,h,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride); + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,dga_buffer+2*(y0*dstride+x0),2*dstride); } -static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride) +static void draw_alpha_null(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride) { UNUSED(x0); UNUSED(y0); UNUSED(w); UNUSED(h); + UNUSED(dp); UNUSED(src); UNUSED(srca); UNUSED(stride); @@ -1103,6 +1105,14 @@ switch (request) { case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data)); + case VOCTRL_YUVSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + if (dstFourcc == IMGFMT_BGR15 || dstFourcc == IMGFMT_BGR16 || dstFourcc == IMGFMT_BGR24 || + dstFourcc == IMGFMT_BGR32 || dstFourcc == IMGFMT_BGR16) return VO_TRUE; + return VO_FALSE; } #ifdef CONFIG_VIDIX --- libvo/osd.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/osd.c 2007-10-08 21:09:26.000000000 +0200 @@ -11,8 +11,9 @@ #include #include "cpudetect.h" #include "mangle.h" +#include "video_out.h" -#ifdef ARCH_X86 +#if defined(ARCH_X86) || defined(ARCH_X86_64) #define CAN_COMPILE_X86_ASM #endif @@ -101,152 +102,152 @@ #endif //CAN_COMPILE_X86_ASM -void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +void vo_draw_alpha_yv12(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM // ordered by speed / fastest first if(gCpuCaps.hasMMX2) - vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) - vo_draw_alpha_yv12_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.hasMMX) - vo_draw_alpha_yv12_MMX(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); else - vo_draw_alpha_yv12_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_yv12_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #else //RUNTIME_CPUDETECT #ifdef HAVE_MMX2 - vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_3DNOW) - vo_draw_alpha_yv12_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_MMX) - vo_draw_alpha_yv12_MMX(w, h, src, srca, srcstride, dstbase, dststride); -#elif defined(ARCH_X86) - vo_draw_alpha_yv12_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); +#elif defined(ARCH_X86) || defined(ARCH_X86_64) + vo_draw_alpha_yv12_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_yv12_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yv12_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #endif //!RUNTIME_CPUDETECT } -void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +void vo_draw_alpha_yuy2(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM // ordered by speed / fastest first if(gCpuCaps.hasMMX2) - vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) - vo_draw_alpha_yuy2_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.hasMMX) - vo_draw_alpha_yuy2_MMX(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); else - vo_draw_alpha_yuy2_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_yuy2_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #else //RUNTIME_CPUDETECT #ifdef HAVE_MMX2 - vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_3DNOW) - vo_draw_alpha_yuy2_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_MMX) - vo_draw_alpha_yuy2_MMX(w, h, src, srca, srcstride, dstbase, dststride); -#elif defined(ARCH_X86) - vo_draw_alpha_yuy2_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); +#elif defined(ARCH_X86) || defined(ARCH_X86_64) + vo_draw_alpha_yuy2_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_yuy2_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_yuy2_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #endif //!RUNTIME_CPUDETECT } -void vo_draw_alpha_uyvy(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +void vo_draw_alpha_uyvy(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM // ordered by speed / fastest first if(gCpuCaps.hasMMX2) - vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) - vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.hasMMX) - vo_draw_alpha_uyvy_MMX(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); else - vo_draw_alpha_uyvy_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_uyvy_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #else //RUNTIME_CPUDETECT #ifdef HAVE_MMX2 - vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_3DNOW) - vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_MMX) - vo_draw_alpha_uyvy_MMX(w, h, src, srca, srcstride, dstbase, dststride); -#elif defined(ARCH_X86) - vo_draw_alpha_uyvy_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); +#elif defined(ARCH_X86) || defined(ARCH_X86_64) + vo_draw_alpha_uyvy_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_uyvy_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_uyvy_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #endif //!RUNTIME_CPUDETECT } -void vo_draw_alpha_rgb24(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +void vo_draw_alpha_rgb24(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM // ordered by speed / fastest first if(gCpuCaps.hasMMX2) - vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) - vo_draw_alpha_rgb24_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.hasMMX) - vo_draw_alpha_rgb24_MMX(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); else - vo_draw_alpha_rgb24_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_rgb24_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #else //RUNTIME_CPUDETECT #ifdef HAVE_MMX2 - vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_3DNOW) - vo_draw_alpha_rgb24_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_MMX) - vo_draw_alpha_rgb24_MMX(w, h, src, srca, srcstride, dstbase, dststride); -#elif defined(ARCH_X86) - vo_draw_alpha_rgb24_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); +#elif defined(ARCH_X86) || defined(ARCH_X86_64) + vo_draw_alpha_rgb24_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_rgb24_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb24_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #endif //!RUNTIME_CPUDETECT } -void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +void vo_draw_alpha_rgb32(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM // ordered by speed / fastest first if(gCpuCaps.hasMMX2) - vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) - vo_draw_alpha_rgb32_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.hasMMX) - vo_draw_alpha_rgb32_MMX(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); else - vo_draw_alpha_rgb32_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_rgb32_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #else //RUNTIME_CPUDETECT #ifdef HAVE_MMX2 - vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_MMX2(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_3DNOW) - vo_draw_alpha_rgb32_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_3DNow(w, h, dp, src, srca, srcstride, dstbase, dststride); #elif defined (HAVE_MMX) - vo_draw_alpha_rgb32_MMX(w, h, src, srca, srcstride, dstbase, dststride); -#elif defined(ARCH_X86) - vo_draw_alpha_rgb32_X86(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_MMX(w, h, dp, src, srca, srcstride, dstbase, dststride); +#elif defined(ARCH_X86) || defined(ARCH_X86_64) + vo_draw_alpha_rgb32_X86(w, h, dp, src, srca, srcstride, dstbase, dststride); #else - vo_draw_alpha_rgb32_C(w, h, src, srca, srcstride, dstbase, dststride); + vo_draw_alpha_rgb32_C(w, h, dp, src, srca, srcstride, dstbase, dststride); #endif #endif //!RUNTIME_CPUDETECT } @@ -288,7 +289,7 @@ mp_msg(MSGT_OSD,MSGL_INFO,"Using MMX (with tiny bit 3DNow) Optimized OnScreenDisplay\n"); #elif defined (HAVE_MMX) mp_msg(MSGT_OSD,MSGL_INFO,"Using MMX Optimized OnScreenDisplay\n"); -#elif defined(ARCH_X86) +#elif defined(ARCH_X86) || defined(ARCH_X86_64) mp_msg(MSGT_OSD,MSGL_INFO,"Using X86 Optimized OnScreenDisplay\n"); #else mp_msg(MSGT_OSD,MSGL_INFO,"Using Unoptimized OnScreenDisplay\n"); @@ -297,8 +298,10 @@ } } -void vo_draw_alpha_rgb15(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +void vo_draw_alpha_rgb15(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ int y; +switch (dp) { + case DEST_PLANES_Y : for(y=0;y>5)&0x1F; + unsigned char b=(dst[x]>>10)&0x1F; + r=(((r*srca[x])>>5)+src[x])>>3; + dst[x]=(b<<10)|(g<<5)|r; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + case DEST_PLANES_G: + for(y=0;y>5)&0x1F; + unsigned char b=(dst[x]>>10)&0x1F; + g=(((g*srca[x])>>5)+src[x])>>3; + dst[x]=(b<<10)|(g<<5)|r; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + case DEST_PLANES_BR: + for(y=0;y>5)&0x1F; + unsigned char b=(dst[x]>>10)&0x1F; + b=(((b*srca[x])>>5)+src[x])>>3; + dst[x]=(b<<10)|(g<<5)|r; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + } } -void vo_draw_alpha_rgb16(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +void vo_draw_alpha_rgb16(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ int y; +switch (dp) { + case DEST_PLANES_Y : for(y=0;y>11)&0x1F; + unsigned char g=(dst[x]>>5)&0x3F; + r=(((r*srca[x])>>5)+src[x])>>3; + dst[x]=(b<<11)|(g<<5)|r; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + case DEST_PLANES_G : + for(y=0;y>5)&0x3F; + unsigned char b=(dst[x]>>11)&0x1F; + g=(((g*srca[x])>>6)+src[x])>>2; + dst[x]=(b<<11)|(g<<5)|r; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + case DEST_PLANES_BR : + for(y=0;y>5)&0x3F; + unsigned char b=(dst[x]>>11)&0x1F; + b=(((b*srca[x])>>5)+src[x])>>3; + dst[x]=(b<<11)|(g<<5)|r; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + } } --- libvo/osd.h 2007-10-07 21:49:28.000000000 +0200 +++ libvo/osd.h 2007-10-08 21:09:26.000000000 +0200 @@ -7,13 +7,13 @@ extern void vo_draw_alpha_init(void); // build tables -extern void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); -extern void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); -extern void vo_draw_alpha_uyvy(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); -extern void vo_draw_alpha_rgb24(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); -extern void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); -extern void vo_draw_alpha_rgb15(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); -extern void vo_draw_alpha_rgb16(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); +extern void vo_draw_alpha_yv12(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); +extern void vo_draw_alpha_yuy2(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); +extern void vo_draw_alpha_uyvy(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); +extern void vo_draw_alpha_rgb24(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); +extern void vo_draw_alpha_rgb32(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); +extern void vo_draw_alpha_rgb15(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); +extern void vo_draw_alpha_rgb16(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); #endif --- libvo/sub.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/sub.c 2007-10-08 21:09:26.000000000 +0200 @@ -154,11 +154,12 @@ } // renders the buffer -inline static void vo_draw_text_from_buffer(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){ +inline static void vo_draw_text_from_buffer(mp_osd_obj_t* obj,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)){ if (obj->allocated > 0) { draw_alpha(obj->bbox.x1,obj->bbox.y1, obj->bbox.x2-obj->bbox.x1, obj->bbox.y2-obj->bbox.y1, + DEST_PLANES_Y, obj->bitmap_buffer, obj->alpha_buffer, obj->stride); @@ -1022,7 +1023,7 @@ obj->flags |= OSDFLAG_BBOX; } -inline static void vo_draw_spudec_sub(mp_osd_obj_t* obj, void (*draw_alpha)(int x0, int y0, int w, int h, unsigned char* src, unsigned char* srca, int stride)) +inline static void vo_draw_spudec_sub(mp_osd_obj_t* obj, void (*draw_alpha)(int x0, int y0, int w, int h, int dp, unsigned char* src, unsigned char* srca, int stride)) { spudec_draw_scaled(vo_spudec, obj->dxs, obj->dys, draw_alpha); } @@ -1223,7 +1224,7 @@ } } -void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)){ +void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)){ mp_osd_obj_t* obj=vo_osd_list; vo_update_osd(dxs,dys); while(obj){ --- libvo/sub.h 2007-10-07 21:49:28.000000000 +0200 +++ libvo/sub.h 2007-10-08 21:09:26.000000000 +0200 @@ -120,7 +120,7 @@ //extern void vo_draw_text_osd(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); //extern void vo_draw_text_progbar(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); //extern void vo_draw_text_sub(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); -extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); +extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)); extern void vo_remove_text(int dxs,int dys,void (*remove)(int x0,int y0, int w,int h)); void vo_init_osd(void); --- libvo/vo_xvmc.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_xvmc.c 2007-10-08 21:09:26.000000000 +0200 @@ -93,12 +93,12 @@ static int free_element; -static void (*draw_osd_fnc)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride); +static void (*draw_osd_fnc)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride); static void (*clear_osd_fnc)(int x0,int y0, int w,int h); static void (*init_osd_fnc)(void); -static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride); -static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride); +static void draw_osd_AI44(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride); +static void draw_osd_IA44(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride); static void clear_osd_subpic(int x0,int y0, int w,int h); static void init_osd_yuv_pal(void); @@ -854,7 +854,7 @@ subpicture_alloc = 1; } -static void draw_osd_IA44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ +static void draw_osd_IA44(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ int ox,oy; int rez; @@ -874,7 +874,7 @@ } } -static void draw_osd_AI44(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ +static void draw_osd_AI44(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ int ox,oy; int rez; if( mp_msg_test(MSGT_VO,MSGL_DBG4) ) --- libvo/vo_dfbmga.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_dfbmga.c 2007-10-08 21:09:26.000000000 +0200 @@ -925,7 +925,7 @@ } static void -vo_draw_alpha_alut44( int w, int h, +vo_draw_alpha_alut44( int w, int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, @@ -956,6 +956,7 @@ static void draw_alpha( int x0, int y0, int w, int h, + int dp, unsigned char *src, unsigned char *srca, int stride ) @@ -980,38 +981,47 @@ switch (subframe_format) { case DSPF_ALUT44: - vo_draw_alpha_alut44( w, h, src, srca, stride, + vo_draw_alpha_alut44( w, h, dp, src, srca, stride, ((uint8_t *) dst) + pitch * y0 + x0, pitch ); break; case DSPF_RGB32: case DSPF_ARGB: - vo_draw_alpha_rgb32( w, h, src, srca, stride, + vo_draw_alpha_rgb32( w, h, dp, src, srca, stride, (( uint8_t *) dst) + pitch * y0 + 4 * x0, pitch ); break; case DSPF_RGB24: - vo_draw_alpha_rgb24( w, h, src, srca, stride, + vo_draw_alpha_rgb24( w, h, dp, src, srca, stride, ((uint8_t *) dst) + pitch * y0 + 3 * x0, pitch ); break; case DSPF_RGB16: - vo_draw_alpha_rgb16( w, h, src, srca, stride, + vo_draw_alpha_rgb16( w, h, dp, src, srca, stride, ((uint8_t *) dst) + pitch * y0 + 2 * x0, pitch ); break; case DSPF_ARGB1555: - vo_draw_alpha_rgb15( w, h, src, srca, stride, + vo_draw_alpha_rgb15( w, h, dp, src, srca, stride, ((uint8_t *) dst) + pitch * y0 + 2 * x0, pitch ); break; case DSPF_YUY2: - vo_draw_alpha_yuy2( w, h, src, srca, stride, + switch (dp) { + case DEST_PLANES_Y: + vo_draw_alpha_yuy2( w, h, dp, src, srca, stride, ((uint8_t *) dst) + pitch * y0 + 2 * x0, pitch ); break; + case DEST_PLANES_YUYV: + vo_draw_alpha_yv12( w, h, dp, src, srca, stride, + ((uint8_t *) dst) + pitch * y0 + 2 * x0, + pitch ); + break; + } + break; case DSPF_UYVY: - vo_draw_alpha_yuy2( w, h, src, srca, stride, + vo_draw_alpha_yuy2( w, h, dp, src, srca, stride, ((uint8_t *) dst) + pitch * y0 + 2 * x0 + 1, pitch ); break; @@ -1021,10 +1031,34 @@ #endif case DSPF_I420: case DSPF_YV12: - vo_draw_alpha_yv12( w, h, src, srca, stride, + switch (dp) { + case DEST_PLANES_Y: + vo_draw_alpha_yv12( w, h, dp, src, srca, stride, ((uint8_t *) dst) + pitch * y0 + x0, pitch ); break; + case DEST_PLANES_U: + if (subframe_format==DSPF_YV12) + vo_draw_alpha_yv12( w, h, dp, src, srca, stride, + ((uint8_t *) dst) + pitch * y0 + x0 + pitch * in_height, + pitch ); + else + vo_draw_alpha_yv12( w, h, dp, src, srca, stride, + ((uint8_t *) dst) + pitch * y0 + x0 + pitch * (in_height+in_height/2), + pitch ); + break; + case DEST_PLANES_V: + if (subframe_format==DSPF_YV12) + vo_draw_alpha_yv12( w, h, dp, src, srca, stride, + ((uint8_t *) dst) + pitch * y0 + x0 + pitch * (in_height+in_height/2), + pitch ); + else + vo_draw_alpha_yv12( w, h, dp, src, srca, stride, + ((uint8_t *) dst) + pitch * y0 + x0 + pitch * in_height, + pitch ); + break; + } + break; } subframe->Unlock( subframe ); @@ -1419,6 +1453,18 @@ return get_equalizer( data, value ); } + case VOCTRL_YUVSPU_SUPPORT: + if (subframe_format==DSPF_I420 || subframe_format==DSPF_YV12) return VO_TRUE; + return VO_FALSE; + case VOCTRL_YUYSPU_SUPPORT: + if (subframe_format==DSPF_YUY2) return VO_TRUE; + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + if (subframe_format==DSPF_RGB32 || subframe_format==DSPF_ARGB || subframe_format==DSPF_RGB24 || + subframe_format==DSPF_RGB16 || subframe_format==DSPF_ARGB1555) return VO_TRUE; + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + return VO_FALSE; } return VO_NOTIMPL; --- libvo/vo_quartz.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_quartz.c 2007-10-08 21:12:20.000000000 +0200 @@ -129,7 +129,7 @@ #include "osdep/keycodes.h" -extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); +extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)); //PROTOTYPE///////////////////////////////////////////////////////////////// static OSStatus KeyEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData); @@ -194,23 +194,23 @@ } } -static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) +static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { switch (image_format) { case IMGFMT_RGB32: - vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*imgRect.right+x0),4*imgRect.right); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,image_data+4*(y0*imgRect.right+x0),4*imgRect.right); break; case IMGFMT_YV12: case IMGFMT_IYUV: case IMGFMT_I420: - vo_draw_alpha_yv12(w,h,src,srca,stride, ((char*)P) + be2me_32(P->componentInfoY.offset) + x0 + y0 * imgRect.right, imgRect.right); + vo_draw_alpha_yv12(w,h,dp,src,srca,stride, ((char*)P) + P->componentInfoY.offset + x0 + y0 * imgRect.right, imgRect.right); break; case IMGFMT_UYVY: - vo_draw_alpha_uyvy(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2); + vo_draw_alpha_uyvy(w,h,dp,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2); break; case IMGFMT_YUY2: - vo_draw_alpha_yuy2(w,h,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((char*)P) + (x0 + y0 * imgRect.right) * 2,imgRect.right*2); break; } } --- libvo/vo_directx.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_directx.c 2007-10-08 21:12:56.000000000 +0200 @@ -86,7 +86,7 @@ static BOOL (WINAPI* myGetMonitorInfo)(HMONITOR, LPMONITORINFO) = NULL; static RECT last_rect = {0xDEADC0DE, 0xDEADC0DE, 0xDEADC0DE, 0xDEADC0DE}; -extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); +extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)); extern int vidmode; /***************************************************************************** @@ -144,37 +144,62 @@ LIBVO_EXTERN(directx) -static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { + uint8_t *d; + uint32_t uvstride=dstride/2; switch(image_format) { case IMGFMT_YV12 : case IMGFMT_I420 : case IMGFMT_IYUV : case IMGFMT_YVU9 : - vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) image) + dstride*y0 + x0,dstride); + switch (dp) { + case DEST_PLANES_Y: + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + dstride*y0 + x0,dstride); + break; + case DEST_PLANES_U: + if(image_format == IMGFMT_YV12) + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + image_height*dstride + uvstride*y0 + x0,uvstride); + else + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + image_height*dstride + uvstride*(image_height/2) + uvstride*y0 + x0,uvstride); + break; + case DEST_PLANES_V: + if(image_format == IMGFMT_YV12) + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + image_height*dstride + uvstride*(image_height/2) + uvstride*y0 + x0,uvstride); + else + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image) + image_height*dstride + uvstride*y0 + x0,uvstride); + break; + } break; case IMGFMT_YUY2 : - vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) image)+ dstride*y0 + 2*x0 ,dstride); + switch (dp) { + case DEST_PLANES_Y: + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) image)+ dstride*y0 + 2*x0 ,dstride); + break; + case DEST_PLANES_YUYV: + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) image)+ dstride*y0 + 2*x0 ,dstride); + break; + } break; case IMGFMT_UYVY : - vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) image) + dstride*y0 + 2*x0 + 1,dstride); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) image) + dstride*y0 + 2*x0 + 1,dstride); break; case IMGFMT_RGB15: case IMGFMT_BGR15: - vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride); + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride); break; case IMGFMT_RGB16: case IMGFMT_BGR16: - vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride); + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,((uint8_t *) image)+dstride*y0+2*x0,dstride); break; case IMGFMT_RGB24: case IMGFMT_BGR24: - vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride); + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride); break; case IMGFMT_RGB32: case IMGFMT_BGR32: - vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,((uint8_t *) image)+dstride*y0+4*x0,dstride); break; } } @@ -1576,6 +1601,25 @@ } aspect_save_screenres(vo_screenwidth, vo_screenheight); return VO_TRUE; + case VOCTRL_YUVSPU_SUPPORT: { + if (image_format==IMGFMT_YV12 || image_format==IMGFMT_I420 || + image_format==IMGFMT_IYUV || image_format==IMGFMT_YVU9) return VO_TRUE; + return VO_FALSE; + } + case VOCTRL_YUYSPU_SUPPORT: { + if (image_format==IMGFMT_YUY2) return VO_TRUE; + return VO_FALSE; + } + case VOCTRL_RGBSPU_SUPPORT: { + if (image_format==IMGFMT_RGB15 || image_format==IMGFMT_RGB16 || + image_format==IMGFMT_RGB32) return VO_TRUE; + return VO_FALSE; + } + case VOCTRL_BGRSPU_SUPPORT: { + if (image_format==IMGFMT_BGR15 || image_format==IMGFMT_BGR16 || + image_format==IMGFMT_BGR32) return VO_TRUE; + return VO_FALSE; + } case VOCTRL_RESET: last_rect.left = 0xDEADC0DE; // reset window position cache // fall-through intended --- libvo/osd_template.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/osd_template.c 2007-10-08 21:09:26.000000000 +0200 @@ -27,7 +27,7 @@ #define EMMS "emms" #endif -static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +static inline void RENAME(vo_draw_alpha_yv12)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ int y; #if defined(FAST_OSD) && !defined(HAVE_MMX) w=w>>1; @@ -97,7 +97,7 @@ return; } -static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +static inline void RENAME(vo_draw_alpha_yuy2)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ int y; #if defined(FAST_OSD) && !defined(HAVE_MMX) w=w>>1; @@ -169,7 +169,7 @@ return; } -static inline void RENAME(vo_draw_alpha_uyvy)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +static inline void RENAME(vo_draw_alpha_uyvy)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ int y; #if defined(FAST_OSD) w=w>>1; @@ -193,8 +193,10 @@ } } -static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +static inline void RENAME(vo_draw_alpha_rgb24)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ int y; +switch (dp) { + case DEST_PLANES_Y: #ifdef HAVE_MMX asm volatile( "pxor %%mm7, %%mm7\n\t" @@ -299,13 +301,61 @@ asm volatile(EMMS:::"memory"); #endif return; + case DEST_PLANES_RB: + for(y=0;y>8)+src[x]; + } + dst+=3; // 24bpp + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + case DEST_PLANES_G: + for(y=0;y>8)+src[x]; + } + dst+=3; // 24bpp + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + case DEST_PLANES_BR: + for(y=0;y>8)+src[x]; + } + dst+=3; // 24bpp + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + } } -static inline void RENAME(vo_draw_alpha_rgb32)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ +static inline void RENAME(vo_draw_alpha_rgb32)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ int y; #ifdef WORDS_BIGENDIAN dstbase++; #endif +switch (dp) { + case DEST_PLANES_Y: #ifdef HAVE_MMX #ifdef HAVE_3DNOW asm volatile( @@ -464,4 +514,44 @@ asm volatile(EMMS:::"memory"); #endif return; + case DEST_PLANES_RB: + for(y=0;y>8)+src[x])&0xff; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + case DEST_PLANES_G: + for(y=0;y>8)+src[x])&0xff; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + case DEST_PLANES_BR: + for(y=0;y>8)+src[x])&0xff; + } + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } + return; + } } --- libvo/vo_yuv4mpeg.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_yuv4mpeg.c 2007-10-08 21:09:26.000000000 +0200 @@ -181,25 +181,37 @@ } } -static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { switch (using_format) { case IMGFMT_YV12: - vo_draw_alpha_yv12(w, h, src, srca, stride, + switch (dp) { + case DEST_PLANES_Y: + vo_draw_alpha_yv12(w, h, dp, src, srca, stride, image + y0 * image_width + x0, image_width); break; + case DEST_PLANES_U: + if (image_u) vo_draw_alpha_yv12(w, h, dp, src, srca, stride, + image_u + y0 * image_width + x0, image_width); + break; + case DEST_PLANES_V: + if (image_v) vo_draw_alpha_yv12(w, h, dp, src, srca, stride, + image_v + y0 * image_width + x0, image_width); + break; + } + break; case IMGFMT_BGR|24: case IMGFMT_RGB|24: if (config_interlace != Y4M_ILACE_BOTTOM_FIRST) - vo_draw_alpha_rgb24(w, h, src, srca, stride, + vo_draw_alpha_rgb24(w, h, dp, src, srca, stride, rgb_buffer + (y0 * image_width + x0) * 3, image_width * 3); else { swap_fields (rgb_buffer, image_height, image_width * 3); - vo_draw_alpha_rgb24(w, h, src, srca, stride, + vo_draw_alpha_rgb24(w, h, dp, src, srca, stride, rgb_buffer + (y0 * image_width + x0) * 3, image_width * 3); swap_fields (rgb_buffer, image_height, image_width * 3); @@ -545,6 +557,15 @@ return query_format(*((uint32_t*)data)); case VOCTRL_DUPLICATE_FRAME: return write_last_frame(); + case VOCTRL_YUVSPU_SUPPORT: + if (using_format==IMGFMT_YV12) return VO_TRUE; + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + if (using_format==IMGFMT_RGB|24) return VO_TRUE; + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + if (using_format==IMGFMT_BGR|24) return VO_TRUE; + return VO_FALSE; } return VO_NOTIMPL; } --- libvo/video_out.h 2007-10-07 21:49:28.000000000 +0200 +++ libvo/video_out.h 2007-10-08 21:09:26.000000000 +0200 @@ -85,6 +85,15 @@ int w,h; } mp_win_t; +// Current vo is YUV mode +#define VOCTRL_YUVSPU_SUPPORT 33 +// Current vo is RGB mode +#define VOCTRL_RGBSPU_SUPPORT 34 +// Current vo is BGR mode +#define VOCTRL_BGRSPU_SUPPORT 35 +// Current vo is YUY mode +#define VOCTRL_YUYSPU_SUPPORT 36 + #define VO_TRUE 1 #define VO_FALSE 0 #define VO_ERROR -1 @@ -97,6 +106,15 @@ #define VOFLAG_FLIPPING 0x08 #define VOFLAG_XOVERLAY_SUB_VO 0x10000 +// dest planes (draw_alpha) +#define DEST_PLANES_Y 0 // Y planes (default) +#define DEST_PLANES_U 1 // U planes in YUV mode +#define DEST_PLANES_V 2 // V planes in YUV mode +#define DEST_PLANES_RB 3 // R or B planes in RGB or BGR mode +#define DEST_PLANES_G 4 // G planes in RGB or BGR mode +#define DEST_PLANES_BR 5 // B or R planes in RGB or BGR mode +#define DEST_PLANES_YUYV 6 // Yuv (all) planes in YUYv mode + typedef struct vo_info_s { /* driver name ("Matrox Millennium G200/G400" */ --- libvo/vosub_vidix.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vosub_vidix.c 2007-10-08 21:09:26.000000000 +0200 @@ -276,7 +276,7 @@ } } -static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride) +static void draw_alpha(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride) { uint32_t apitch,bespitch; void *lvo_mem; @@ -290,36 +290,57 @@ case IMGFMT_IF09: case IMGFMT_Y8: case IMGFMT_Y800: + switch (dp) { + case DEST_PLANES_Y: bespitch = (vidix_play.src.w + apitch) & (~apitch); - vo_draw_alpha_yv12(w,h,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch); + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch); + break; + case DEST_PLANES_U: + lvo_mem = vidix_mem + vidix_play.offsets[next_frame] + vidix_play.offset.u; + lvo_mem += dstrides.u*y0/2 + x0; + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem,dstrides.u/2); + break; + case DEST_PLANES_V: + lvo_mem = vidix_mem + vidix_play.offsets[next_frame] + vidix_play.offset.v; + lvo_mem += dstrides.v*y0/2 + x0; + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem,dstrides.v/2); + break; + } break; case IMGFMT_YUY2: bespitch = (vidix_play.src.w*2 + apitch) & (~apitch); - vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+bespitch*y0+2*x0,bespitch); + switch (dp) { + case DEST_PLANES_Y: + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+2*x0,bespitch); + break; + case DEST_PLANES_YUYV: + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch); + break; + } break; case IMGFMT_UYVY: bespitch = (vidix_play.src.w*2 + apitch) & (~apitch); - vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+bespitch*y0+2*x0+1,bespitch); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+2*x0+1,bespitch); break; case IMGFMT_RGB32: case IMGFMT_BGR32: bespitch = (vidix_play.src.w*4 + apitch) & (~apitch); - vo_draw_alpha_rgb32(w,h,src,srca,stride,lvo_mem+y0*bespitch+4*x0,bespitch); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,lvo_mem+y0*bespitch+4*x0,bespitch); break; case IMGFMT_RGB24: case IMGFMT_BGR24: bespitch = (vidix_play.src.w*3 + apitch) & (~apitch); - vo_draw_alpha_rgb24(w,h,src,srca,stride,lvo_mem+y0*bespitch+3*x0,bespitch); + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,lvo_mem+y0*bespitch+3*x0,bespitch); break; case IMGFMT_RGB16: case IMGFMT_BGR16: bespitch = (vidix_play.src.w*2 + apitch) & (~apitch); - vo_draw_alpha_rgb16(w,h,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch); + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch); break; case IMGFMT_RGB15: case IMGFMT_BGR15: bespitch = (vidix_play.src.w*2 + apitch) & (~apitch); - vo_draw_alpha_rgb15(w,h,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch); + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,lvo_mem+y0*bespitch+2*x0,bespitch); break; default: return; @@ -505,7 +526,7 @@ next_frame = i; memset(vidix_mem + vidix_play.offsets[i], 0x80, vidix_play.frame_size); - draw_alpha(0, 0, image_width, image_height, tmp, tmpa, image_width); + draw_alpha(0, 0, image_width, image_height, DEST_PLANES_Y, tmp, tmpa, image_width); } free(tmp); free(tmpa); @@ -693,6 +714,16 @@ return VO_TRUE; } + case VOCTRL_YUVSPU_SUPPORT: + if((vidix_play.fourcc==IMGFMT_YV12 || vidix_play.fourcc==IMGFMT_YV12 || vidix_play.fourcc==IMGFMT_IYUV || + vidix_play.fourcc==IMGFMT_I420 || vidix_play.fourcc==IMGFMT_YVU9 || vidix_play.fourcc==IMGFMT_IF09 || + vidix_play.fourcc==IMGFMT_Y8 || vidix_play.fourcc==IMGFMT_Y800) && + !(vidix_play.flags & VID_PLAY_INTERLEAVED_UV)) return VO_TRUE; + return VO_FALSE; + case VOCTRL_YUYSPU_SUPPORT: + if((vidix_play.fourcc==IMGFMT_YUY2) && + !(vidix_play.flags & VID_PLAY_INTERLEAVED_UV)) return VO_TRUE; + return VO_FALSE; } return VO_NOTIMPL; // WARNING: we drop extra parameters (...) here! --- libvo/vo_dga.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_dga.c 2007-10-08 21:09:26.000000000 +0200 @@ -227,7 +227,7 @@ //--------------------------------------------------------- -static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { @@ -243,19 +243,19 @@ { case 32: - vo_draw_alpha_rgb32(w, h, src, srca, stride, d + 4 * offset, + vo_draw_alpha_rgb32(w, h, dp, src, srca, stride, d + 4 * offset, 4 * buffer_stride); break; case 24: - vo_draw_alpha_rgb24(w, h, src, srca, stride, d + 3 * offset, + vo_draw_alpha_rgb24(w, h, dp, src, srca, stride, d + 3 * offset, 3 * buffer_stride); break; case 15: - vo_draw_alpha_rgb15(w, h, src, srca, stride, d + 2 * offset, + vo_draw_alpha_rgb15(w, h, dp, src, srca, stride, d + 2 * offset, 2 * buffer_stride); break; case 16: - vo_draw_alpha_rgb16(w, h, src, srca, stride, d + 2 * offset, + vo_draw_alpha_rgb16(w, h, dp, src, srca, stride, d + 2 * offset, 2 * buffer_stride); break; } @@ -981,6 +981,14 @@ return get_image(data); case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t *) data)); + case VOCTRL_YUVSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + if(HW_MODE.vdm_mplayer_depth==32 || HW_MODE.vdm_mplayer_depth==24 || + HW_MODE.vdm_mplayer_depth==15 || HW_MODE.vdm_mplayer_depth==16) return VO_TRUE; + return VO_FALSE; } return VO_NOTIMPL; } --- libvo/vo_gl2.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_gl2.c 2007-10-08 21:13:44.000000000 +0200 @@ -84,7 +84,7 @@ static int use_glFinish; static void (*draw_alpha_fnc) - (int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride); + (int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride); /* The squares that are tiled to make up the game screen polygon */ @@ -430,23 +430,23 @@ glLoadIdentity(); } -static void draw_alpha_32(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ - vo_draw_alpha_rgb32(w,h,src,srca,stride,ImageData+4*(y0*image_width+x0),4*image_width); +static void draw_alpha_32(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,ImageData+4*(y0*image_width+x0),4*image_width); } -static void draw_alpha_24(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ - vo_draw_alpha_rgb24(w,h,src,srca,stride,ImageData+3*(y0*image_width+x0),3*image_width); +static void draw_alpha_24(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,ImageData+3*(y0*image_width+x0),3*image_width); } -static void draw_alpha_16(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ - vo_draw_alpha_rgb16(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width); +static void draw_alpha_16(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width); } -static void draw_alpha_15(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ - vo_draw_alpha_rgb15(w,h,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width); +static void draw_alpha_15(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,ImageData+2*(y0*image_width+x0),2*image_width); } -static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ +static void draw_alpha_null(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ } #ifdef GL_WIN32 @@ -919,6 +919,13 @@ case VOCTRL_UPDATE_SCREENINFO: update_xinerama_info(); return VO_TRUE; + case VOCTRL_YUVSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + if (image_bpp==15 || image_bpp==16 || image_bpp==24 || image_bpp==32) return VO_TRUE; + return VO_FALSE; } return VO_NOTIMPL; } --- libvo/vo_x11.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_x11.c 2007-10-08 21:09:26.000000000 +0200 @@ -60,7 +60,7 @@ LIBVO_EXTERN(x11) /* private prototypes */ static void Display_Image(XImage * myximage, unsigned char *ImageData); -static void (*draw_alpha_fnc) (int x0, int y0, int w, int h, +static void (*draw_alpha_fnc) (int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride); @@ -108,39 +108,39 @@ } -static void draw_alpha_32(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha_32(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { - vo_draw_alpha_rgb32(w, h, src, srca, stride, + vo_draw_alpha_rgb32(w, h, dp, src, srca, stride, ImageData + 4 * (y0 * image_width + x0), 4 * image_width); } -static void draw_alpha_24(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha_24(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { - vo_draw_alpha_rgb24(w, h, src, srca, stride, + vo_draw_alpha_rgb24(w, h, dp, src, srca, stride, ImageData + 3 * (y0 * image_width + x0), 3 * image_width); } -static void draw_alpha_16(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha_16(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { - vo_draw_alpha_rgb16(w, h, src, srca, stride, + vo_draw_alpha_rgb16(w, h, dp, src, srca, stride, ImageData + 2 * (y0 * image_width + x0), 2 * image_width); } -static void draw_alpha_15(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha_15(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { - vo_draw_alpha_rgb15(w, h, src, srca, stride, + vo_draw_alpha_rgb15(w, h, dp, src, srca, stride, ImageData + 2 * (y0 * image_width + x0), 2 * image_width); } -static void draw_alpha_null(int x0, int y0, int w, int h, +static void draw_alpha_null(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { @@ -797,6 +797,14 @@ case VOCTRL_UPDATE_SCREENINFO: update_xinerama_info(); return VO_TRUE; + case VOCTRL_YUVSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + if (out_format == IMGFMT_BGR15 || out_format == IMGFMT_BGR16 || + out_format == IMGFMT_BGR24 || out_format == IMGFMT_BGR32) return VO_TRUE; + return VO_FALSE; } return VO_NOTIMPL; } --- libvo/vo_sdl.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_sdl.c 2007-10-08 21:09:26.000000000 +0200 @@ -287,7 +287,7 @@ * **/ -static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ +static void draw_alpha(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ struct sdl_priv_s *priv = &sdl_priv; if(priv->osd_has_changed) { @@ -328,16 +328,43 @@ case IMGFMT_YV12: case IMGFMT_I420: case IMGFMT_IYUV: - vo_draw_alpha_yv12(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]); + switch (dp) { + case DEST_PLANES_Y : + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]); + break; + case DEST_PLANES_U : + SDL_OVR_LOCK(-1) + if (priv->format==IMGFMT_YV12) + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) (priv->overlay->pixels[1]))+priv->overlay->pitches[1]*y0+x0,priv->overlay->pitches[1]); + else + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) (priv->overlay->pixels[2]))+priv->overlay->pitches[2]*y0+x0,priv->overlay->pitches[2]); + SDL_OVR_UNLOCK + break; + case DEST_PLANES_V : + SDL_OVR_LOCK(-1) + if (priv->format==IMGFMT_YV12) + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) (priv->overlay->pixels[2]))+priv->overlay->pitches[2]*y0+x0,priv->overlay->pitches[2]); + else + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) (priv->overlay->pixels[1]))+priv->overlay->pitches[1]*y0+x0,priv->overlay->pitches[1]); + SDL_OVR_UNLOCK + break; + } break; case IMGFMT_YUY2: case IMGFMT_YVYU: x0 *= 2; - vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]); + switch (dp) { + case DEST_PLANES_Y : + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]); + break; + case DEST_PLANES_YUYV : + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]); + break; + } break; case IMGFMT_UYVY: x0 *= 2; - vo_draw_alpha_yuy2(w,h,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,((uint8_t *) *(priv->overlay->pixels))+priv->overlay->pitches[0]*y0+x0,priv->overlay->pitches[0]); break; default: @@ -346,19 +373,19 @@ switch(priv->format) { case IMGFMT_RGB15: case IMGFMT_BGR15: - vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch); + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch); break; case IMGFMT_RGB16: case IMGFMT_BGR16: - vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch); + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch); break; case IMGFMT_RGB24: case IMGFMT_BGR24: - vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch); + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch); break; case IMGFMT_RGB32: case IMGFMT_BGR32: - vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,((uint8_t *) priv->surface->pixels)+y0*priv->surface->pitch+x0,priv->surface->pitch); break; } } @@ -367,19 +394,19 @@ switch(priv->format) { case IMGFMT_RGB15: case IMGFMT_BGR15: - vo_draw_alpha_rgb15(w,h,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch); + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch); break; case IMGFMT_RGB16: case IMGFMT_BGR16: - vo_draw_alpha_rgb16(w,h,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch); + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch); break; case IMGFMT_RGB24: case IMGFMT_BGR24: - vo_draw_alpha_rgb24(w,h,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch); + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch); break; case IMGFMT_RGB32: case IMGFMT_BGR32: - vo_draw_alpha_rgb32(w,h,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,((uint8_t *) priv->rgbsurface->pixels)+y0*priv->rgbsurface->pitch+x0,priv->rgbsurface->pitch); break; } } @@ -1727,6 +1754,18 @@ mp_msg(MSGT_VO,MSGL_DBG2, "SDL: Set fullscreen mode\n"); } } return VO_TRUE; + case VOCTRL_YUVSPU_SUPPORT: + if (priv->format == IMGFMT_YV12 || priv->format == IMGFMT_I420 || priv->format==IMGFMT_IYUV) return VO_TRUE; + return VO_FALSE; + case VOCTRL_YUYSPU_SUPPORT: + if (priv->format==IMGFMT_YUY2) return VO_TRUE; + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + if (priv->mode == RGB) return VO_TRUE; + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + if (priv->mode == BGR) return VO_TRUE; + return VO_FALSE; } return VO_NOTIMPL; --- libvo/vesa_lvo.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vesa_lvo.c 2007-10-08 21:09:26.000000000 +0200 @@ -233,50 +233,51 @@ } } -static void draw_alpha_null(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride) +static void draw_alpha_null(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride) { UNUSED(x0); UNUSED(y0); UNUSED(w); UNUSED(h); + UNUSED(dp); UNUSED(src); UNUSED(srca); UNUSED(stride); } -static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride) +static void draw_alpha(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride) { uint32_t bespitch = /*(*/mga_vid_config.src_width;// + 15) & ~15; switch(mga_vid_config.format){ case IMGFMT_BGR15: case IMGFMT_RGB15: - vo_draw_alpha_rgb15(w,h,src,srca,stride,lvo_mem+2*(y0*bespitch+x0),2*bespitch); + vo_draw_alpha_rgb15(w,h,dp,src,srca,stride,lvo_mem+2*(y0*bespitch+x0),2*bespitch); break; case IMGFMT_BGR16: case IMGFMT_RGB16: - vo_draw_alpha_rgb16(w,h,src,srca,stride,lvo_mem+2*(y0*bespitch+x0),2*bespitch); + vo_draw_alpha_rgb16(w,h,dp,src,srca,stride,lvo_mem+2*(y0*bespitch+x0),2*bespitch); break; case IMGFMT_BGR24: case IMGFMT_RGB24: - vo_draw_alpha_rgb24(w,h,src,srca,stride,lvo_mem+3*(y0*bespitch+x0),3*bespitch); + vo_draw_alpha_rgb24(w,h,dp,src,srca,stride,lvo_mem+3*(y0*bespitch+x0),3*bespitch); break; case IMGFMT_BGR32: case IMGFMT_RGB32: - vo_draw_alpha_rgb32(w,h,src,srca,stride,lvo_mem+4*(y0*bespitch+x0),4*bespitch); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,lvo_mem+4*(y0*bespitch+x0),4*bespitch); break; case IMGFMT_YV12: case IMGFMT_IYUV: case IMGFMT_I420: - vo_draw_alpha_yv12(w,h,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch); + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,lvo_mem+bespitch*y0+x0,bespitch); break; case IMGFMT_YUY2: - vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+2*(bespitch*y0+x0),bespitch); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,lvo_mem+2*(bespitch*y0+x0),bespitch); break; case IMGFMT_UYVY: - vo_draw_alpha_yuy2(w,h,src,srca,stride,lvo_mem+2*(bespitch*y0+x0)+1,bespitch); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,lvo_mem+2*(bespitch*y0+x0)+1,bespitch); break; default: - draw_alpha_null(x0,y0,w,h,src,srca,stride); + draw_alpha_null(x0,y0,w,h,dp,src,srca,stride); } } --- libvo/vo_aa.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_aa.c 2007-10-08 21:09:26.000000000 +0200 @@ -510,7 +510,7 @@ aa_close(c); } -static void draw_alpha(int x,int y, int w,int h, unsigned char* src, unsigned char *srca, int stride){ +static void draw_alpha(int x,int y, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ int i,j; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { --- libvo/vo_xv.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_xv.c 2007-10-08 21:09:26.000000000 +0200 @@ -93,47 +93,83 @@ static uint32_t drwX, drwY, drwBorderWidth, drwDepth; static uint32_t max_width = 0, max_height = 0; // zero means: not set -static void (*draw_alpha_fnc) (int x0, int y0, int w, int h, +static int support_yuvspu = VO_FALSE; +static int support_yuyspu = VO_FALSE; + +static void (*draw_alpha_fnc) (int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride); -static void draw_alpha_yv12(int x0, int y0, int w, int h, +static void draw_alpha_yv12(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { + switch (dp) { + case DEST_PLANES_U: { + x0 += image_width/2 * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x); + vo_draw_alpha_yv12(w, h, dp, src, srca, stride, + xvimage[current_buf]->data + + xvimage[current_buf]->offsets[1] + + xvimage[current_buf]->pitches[1] * y0 + x0, + xvimage[current_buf]->pitches[1]); + break; } + case DEST_PLANES_V: { + x0 += image_width/2 * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x); + vo_draw_alpha_yv12(w, h, dp, src, srca, stride, + xvimage[current_buf]->data + + xvimage[current_buf]->offsets[2] + + xvimage[current_buf]->pitches[2] * y0 + x0, + xvimage[current_buf]->pitches[2]); + break; } + case DEST_PLANES_Y: { x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x); - vo_draw_alpha_yv12(w, h, src, srca, stride, + vo_draw_alpha_yv12(w, h, dp, src, srca, stride, xvimage[current_buf]->data + xvimage[current_buf]->offsets[0] + xvimage[current_buf]->pitches[0] * y0 + x0, xvimage[current_buf]->pitches[0]); } + } -static void draw_alpha_yuy2(int x0, int y0, int w, int h, +} + +static void draw_alpha_yuy2(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { + switch (dp) { + case DEST_PLANES_Y: + x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x); + vo_draw_alpha_yuy2(w, h, dp, src, srca, stride, + xvimage[current_buf]->data + + xvimage[current_buf]->offsets[0] + + xvimage[current_buf]->pitches[0] * y0 + 2 * x0, + xvimage[current_buf]->pitches[0]); + break; + case DEST_PLANES_YUYV: x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x); - vo_draw_alpha_yuy2(w, h, src, srca, stride, + vo_draw_alpha_yv12(w, h, dp, src, srca, stride, xvimage[current_buf]->data + xvimage[current_buf]->offsets[0] + xvimage[current_buf]->pitches[0] * y0 + 2 * x0, xvimage[current_buf]->pitches[0]); + break; + } } -static void draw_alpha_uyvy(int x0, int y0, int w, int h, +static void draw_alpha_uyvy(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { x0 += image_width * (vo_panscan_x >> 1) / (vo_dwidth + vo_panscan_x); - vo_draw_alpha_yuy2(w, h, src, srca, stride, + vo_draw_alpha_yuy2(w, h, dp, src, srca, stride, xvimage[current_buf]->data + xvimage[current_buf]->offsets[0] + xvimage[current_buf]->pitches[0] * y0 + 2 * x0 + 1, xvimage[current_buf]->pitches[0]); } -static void draw_alpha_null(int x0, int y0, int w, int h, +static void draw_alpha_null(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { @@ -328,11 +364,13 @@ { case IMGFMT_YV12: case IMGFMT_I420: + support_yuvspu = VO_TRUE; case IMGFMT_IYUV: draw_alpha_fnc = draw_alpha_yv12; break; case IMGFMT_YUY2: case IMGFMT_YVYU: + support_yuyspu = VO_TRUE; draw_alpha_fnc = draw_alpha_yuy2; break; case IMGFMT_UYVY: @@ -914,6 +952,14 @@ case VOCTRL_UPDATE_SCREENINFO: update_xinerama_info(); return VO_TRUE; + case VOCTRL_YUVSPU_SUPPORT: + return support_yuvspu; + case VOCTRL_RGBSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_YUYSPU_SUPPORT: + return support_yuyspu; } return VO_NOTIMPL; } --- libvo/vo_fbdev2.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_fbdev2.c 2007-10-08 21:09:26.000000000 +0200 @@ -79,7 +79,7 @@ static int fb_bpp; // 32: 32 24: 24 16: 16 15: 15 static size_t fb_size; // size of frame_buffer static int fb_line_len; // length of one line in bytes -static void (*draw_alpha_p)(int w, int h, unsigned char *src, +static void (*draw_alpha_p)(int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride, unsigned char *dst, int dstride); @@ -317,7 +317,7 @@ return 0; } -static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, +static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { unsigned char *dst; @@ -330,7 +330,7 @@ dst = next_frame + (in_width * y0 + x0) * fb_pixel_size; dstride = in_width * fb_pixel_size; #endif - (*draw_alpha_p)(w, h, src, srca, stride, dst, dstride); + (*draw_alpha_p)(w, h, dp, src, srca, stride, dst, dstride); } static void draw_osd(void) @@ -403,6 +403,13 @@ switch (request) { case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data)); + case VOCTRL_YUVSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_RGBSPU_SUPPORT: + return VO_FALSE; + case VOCTRL_BGRSPU_SUPPORT: + if (fb_bpp == 32 || fb_bpp==24 || fb_bpp==16 || fb_bpp==15) return VO_TRUE; + return VO_FALSE; } return VO_NOTIMPL; } --- libvo/vo_macosx.m 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_macosx.m 2007-10-08 21:09:26.000000000 +0200 @@ -73,17 +73,17 @@ LIBVO_EXTERN(macosx) extern void mplayer_put_key(int code); -extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); +extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)); -static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) +static void draw_alpha(int x0, int y0, int w, int h, int dp, unsigned char *src, unsigned char *srca, int stride) { switch (image_format) { case IMGFMT_RGB32: - vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*image_width+x0),4*image_width); + vo_draw_alpha_rgb32(w,h,dp,src,srca,stride,image_data+4*(y0*image_width+x0),4*image_width); break; case IMGFMT_YUY2: - vo_draw_alpha_yuy2(w,h,src,srca,stride,image_data + (x0 + y0 * image_width) * 2,image_width*2); + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,image_data + (x0 + y0 * image_width) * 2,image_width*2); break; } } --- libvo/vo_dxr3.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/vo_dxr3.c 2007-10-08 21:09:26.000000000 +0200 @@ -669,7 +669,7 @@ return 0; } -static void draw_alpha(int x, int y, int w, int h, unsigned char* src, unsigned char *srca, int srcstride) +static void draw_alpha(int x, int y, int w, int h, int dp, unsigned char* src, unsigned char *srca, int srcstride) { #ifdef SPU_SUPPORT unsigned char *buf = &osdpicbuf[(y * osdpicbuf_w) + x]; --- libvo/mga_common.c 2007-10-07 21:49:28.000000000 +0200 +++ libvo/mga_common.c 2008-01-12 23:57:48.000000000 +0100 @@ -25,20 +25,51 @@ #endif static uint32_t drwcX,drwcY,dwidth,dheight; -static void draw_alpha(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride){ +static void draw_alpha(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride){ + uint8_t *dest; uint32_t bespitch = (mga_vid_config.src_width + 31) & ~31; x0+=mga_vid_config.src_width*(vo_panscan_x>>1)/(vo_dwidth+vo_panscan_x); switch(mga_vid_config.format){ case MGA_VID_FORMAT_YV12: case MGA_VID_FORMAT_IYUV: case MGA_VID_FORMAT_I420: - vo_draw_alpha_yv12(w,h,src,srca,stride,vid_data+bespitch*y0+x0,bespitch); + switch (dp) { + case DEST_PLANES_Y : + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,vid_data+bespitch*y0+x0,bespitch); + break; + case DEST_PLANES_U : + dest = vid_data + bespitch*mga_vid_config.src_height + bespitch/2 * y0/2 + x0/2; + if(mga_vid_config.format==MGA_VID_FORMAT_YV12) + dest += bespitch/2*mga_vid_config.src_height / 2; + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,dest,bespitch/2); + break; + case DEST_PLANES_V : + dest = vid_data + bespitch*mga_vid_config.src_height + bespitch/2 * y0/2 + x0/2; + if(mga_vid_config.format!=MGA_VID_FORMAT_YV12) + dest += bespitch/2*mga_vid_config.src_height / 2; + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,dest,bespitch/2); + break; + } break; case MGA_VID_FORMAT_YUY2: - vo_draw_alpha_yuy2(w,h,src,srca,stride,vid_data+2*(bespitch*y0+x0),2*bespitch); + switch (dp) { + case DEST_PLANES_Y : + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,vid_data+2*(bespitch*y0+x0),2*bespitch); + break; + case DEST_PLANES_YUYV : + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,vid_data+2*(bespitch*y0+x0),2*bespitch); + break; + } break; case MGA_VID_FORMAT_UYVY: - vo_draw_alpha_yuy2(w,h,src,srca,stride,vid_data+2*(bespitch*y0+x0)+1,2*bespitch); + switch (dp) { + case DEST_PLANES_Y : + vo_draw_alpha_yuy2(w,h,dp,src,srca,stride,vid_data+2*(bespitch*y0+x0)+1,2*bespitch); + break; + case DEST_PLANES_YUYV : + vo_draw_alpha_yv12(w,h,dp,src,srca,stride,vid_data+2*(bespitch*y0+x0)+1,2*bespitch); + break; + } break; } } --- command.c 2007-10-07 21:49:33.000000000 +0200 +++ command.c 2008-01-12 23:59:22.000000000 +0100 @@ -710,6 +710,10 @@ reinit_audio_chain(); } } +#ifdef USE_DVDNAV + if (mpctx->stream->type == STREAMTYPE_DVDNAV) + dvdnav_reg_mp_aid(mpctx->stream, audio_id); +#endif mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_TRACK=%d\n", audio_id); return M_PROPERTY_OK; default: @@ -1358,6 +1362,10 @@ d_sub->id = dvdsub_id; } #endif +#ifdef USE_DVDNAV + if (mpctx->stream->type == STREAMTYPE_DVDNAV) + dvdnav_reg_mp_sid(mpctx->stream, dvdsub_id); +#endif update_subtitles(mpctx->sh_video, d_sub, 1); return M_PROPERTY_OK; @@ -2772,16 +2780,29 @@ if (mpctx->stream->type != STREAMTYPE_DVDNAV) break; - if (mp_dvdnav_handle_input - (mpctx->stream, cmd->args[0].v.i, &button)) { - uninit_player(INITED_ALL - (INITED_STREAM | INITED_INPUT | - (fixed_vo ? INITED_VO : 0))); - brk_cmd = 2; - } else if (button > 0) + mp_dvdnav_handle_input(mpctx->stream, + cmd->args[0].v.i, &button); + if (button > 0) set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, "Selected button number %d", button); } break; + case MP_CMD_SWITCH_TITLE:{ + if (mpctx->stream->type != STREAMTYPE_DVDNAV) + break; + + mp_dvdnav_switch_title(mpctx->stream, + cmd->args[0].v.i); + } + break; + case MP_CMD_SWITCH_CHAPTER:{ + if (mpctx->stream->type != STREAMTYPE_DVDNAV) + break; + + mp_dvdnav_switch_chapter(mpctx->stream, + cmd->args[0].v.i); + } + break; #endif default: --- libmenu/menu.c 2007-10-07 21:49:32.000000000 +0200 +++ libmenu/menu.c 2007-10-08 21:09:27.000000000 +0200 @@ -21,6 +21,7 @@ #include "m_option.h" #include "m_struct.h" #include "menu.h" +#include "libvo/video_out.h" extern menu_info_t menu_info_cmdlist; extern menu_info_t menu_info_pt; @@ -256,7 +257,7 @@ ///////////////////////////// Helpers //////////////////////////////////// -typedef void (*draw_alpha_f)(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); +typedef void (*draw_alpha_f)(int w,int h, int dp, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride); inline static draw_alpha_f get_draw_alpha(uint32_t fmt) { switch(fmt) { @@ -369,7 +370,7 @@ while (*txt) { int c=utf8_get_char(&txt); if ((font=vo_font->font[c])>=0 && (x + vo_font->width[c] <= mpi->w) && (y + vo_font->pic_a[font]->h <= mpi->h)) - draw_alpha(vo_font->width[c], vo_font->pic_a[font]->h, + draw_alpha(vo_font->width[c], vo_font->pic_a[font]->h,DEST_PLANES_Y, vo_font->pic_b[font]->bmp+vo_font->start[c], vo_font->pic_a[font]->bmp+vo_font->start[c], vo_font->pic_a[font]->w, @@ -539,7 +540,7 @@ if(font >= 0) { int cs = (vo_font->pic_a[font]->h - vo_font->height) / 2; if ((sx + vo_font->width[c] < xmax) && (sy + vo_font->height < ymax) ) - draw_alpha(vo_font->width[c], vo_font->height, + draw_alpha(vo_font->width[c], vo_font->height, DEST_PLANES_Y, vo_font->pic_b[font]->bmp+vo_font->start[c] + cs * vo_font->pic_a[font]->w, vo_font->pic_a[font]->bmp+vo_font->start[c] + @@ -647,7 +648,7 @@ char pic[stride*h],pic_alpha[stride*h]; memset(pic,g,stride*h); memset(pic_alpha,alpha,stride*h); - draw_alpha(w,h,pic,pic_alpha,stride, + draw_alpha(w,h,DEST_PLANES_Y,pic,pic_alpha,stride, mpi->planes[0] + y * mpi->stride[0] + x * (mpi->bpp>>3), mpi->stride[0]); } --- mplayer.c 2007-10-07 21:49:33.000000000 +0200 +++ mplayer.c 2008-01-12 23:46:15.000000000 +0100 @@ -170,7 +170,20 @@ #endif #ifdef USE_DVDNAV +#include "libmpcodecs/img_format.h" +#include "libmpcodecs/mp_image.h" +#include "libvo/fastmemcpy.h" #include "stream/stream_dvdnav.h" +// vo color mode: +// -1 : no settings +// 0 : Y +// 1 : YUV +// 2 : RGB +// 3 : BGR +// 4 : YUYV +int dvdnav_color_spu_flg = -1; +// enable/disable SPU menu button +int dvdnav_color_spu = 1; #endif #include "libmpcodecs/dec_audio.h" @@ -614,6 +627,17 @@ current_module="uninit_vo"; mpctx->video_out->uninit(); mpctx->video_out=NULL; +#ifdef USE_DVDNAV + // free stored decoded image + if (mpctx->smpi) free_mp_image(mpctx->smpi); + mpctx->smpi=NULL; + // free last video read frame + if (mpctx->last_buffer) free(mpctx->last_buffer); + // clear buffers + mpctx->last_buffer=NULL; + mpctx->last_start=NULL; + mpctx->last_in_size=0; +#endif } // Must be after libvo uninit, as few vo drivers (svgalib) have tty code. @@ -1679,6 +1703,290 @@ return time_frame; } +// DVDNAV *FIXME* +#ifdef USE_DVDNAV +// +// store decoded video image +// +mp_image_t* mp_dvdnav_copympi(mp_image_t* tompi, + mp_image_t* frommpi) { + mp_image_t* mpi; + + if (!frommpi) return NULL; + // Do not store B-frames + if (frommpi->pict_type==3) return tompi; + if (tompi && tompi->w==frommpi->w && + tompi->h==frommpi->h && + tompi->imgfmt==frommpi->imgfmt) + mpi=tompi; + else { + if (tompi) free_mp_image(tompi); + if (frommpi->w==0 || frommpi->h==0) return NULL; + mpi=alloc_mpi(frommpi->w,frommpi->h,frommpi->imgfmt); + } + copy_mpi(mpi,frommpi); + return mpi; +} + +// +// set audio in dvdnav +// +static int mp_dvdnav_audio_handle() { + + int dvdnav_audio_num=mp_dvdnav_get_audio(mpctx->stream); + int current_id=mpctx->demuxer->audio->id; + int dvdnav_audio; + + dvdnav_audio=dvdnav_aid_from_audio_num(mpctx->stream,dvdnav_audio_num); + dvdnav_audio=dvdnav_reg_nav_aid(mpctx->stream, dvdnav_audio); + if(dvdnav_audio==-1) return 0; // fail seek + if(current_id==dvdnav_audio) return 0; // no change + audio_id = demuxer_switch_audio(mpctx->demuxer, dvdnav_audio); // switch audio + if((current_id & 0x0F)==(dvdnav_audio &0x0F)) return 0; // if unchanged audio codec then no reinit audio + + if(audio_id == -2 || (audio_id > -1 && mpctx->demuxer->audio->id != current_id && current_id != -2)) + uninit_player(INITED_AO | INITED_ACODEC); + if(audio_id > -1 && mpctx->demuxer->audio->id != current_id) { + sh_audio_t *sh2; + sh2 = mpctx->demuxer->a_streams[mpctx->demuxer->audio->id]; + if(sh2) { + sh2->ds = mpctx->demuxer->audio; + mpctx->sh_audio = sh2; + reinit_audio_chain(); + } + } + return 1; +} + +// +// set dvdnav subtile +// +static void mp_dvdnav_spu_handle() { + mpctx->global_sub_size=dvdnav_number_of_subs(mpctx->stream); + if(!mp_dvdnav_is_spu_change(mpctx->stream)) return; // is unchanged dvdnav subtitle + int dvdnav_spu=mp_dvdnav_get_spu(mpctx->stream); + if (!mpctx->d_sub) return; + if(dvdnav_spu<0) dvdnav_spu=-2; + dvdnav_spu=dvdnav_reg_nav_sid(mpctx->stream, dvdnav_spu); + if (mpctx->d_sub) { + dvdsub_id = dvdnav_spu; + mpctx->d_sub->id = dvdnav_spu; + } +return; +} + +// +// set dvd menu buttons +// +static void mp_dvdnav_highlight_handle(int stream_is_change) { + nav_highlight_t highlight; + unsigned int *spu_clut; + + if (!dvdnav_color_spu) return; // is disable dvdnav color spu + if (dvdnav_color_spu_flg==-1) { // is unsettings vo color mode + dvdnav_color_spu_flg=0; + if (mpctx->video_out) { // query vo color mode + if (!dvdnav_color_spu_flg && mpctx->video_out->control(VOCTRL_YUVSPU_SUPPORT,NULL)==VO_TRUE) + dvdnav_color_spu_flg=DVDNAV_SPU_YUV; + if (!dvdnav_color_spu_flg && mpctx->video_out->control(VOCTRL_YUYSPU_SUPPORT,NULL)==VO_TRUE) + dvdnav_color_spu_flg=DVDNAV_SPU_YUY; + if (!dvdnav_color_spu_flg && mpctx->video_out->control(VOCTRL_RGBSPU_SUPPORT,NULL)==VO_TRUE) + dvdnav_color_spu_flg=DVDNAV_SPU_RGB; + if (!dvdnav_color_spu_flg && mpctx->video_out->control(VOCTRL_BGRSPU_SUPPORT,NULL)==VO_TRUE) + dvdnav_color_spu_flg=DVDNAV_SPU_BGR; +// if (!dvdnav_color_spu_flg) +// mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_MPDVDNAV_NoColorSpu); + } + } + spu_clut = mp_dvdnav_get_spu_clut(mpctx->stream); + mp_dvdnav_get_highlight(mpctx->stream,&highlight); + if (highlight.sx==0 && highlight.sy==0 && highlight.ex==0 && highlight.ey==0) { // is no button + if (stream_is_change || (spudec_visible(vo_spudec) && !mpctx->global_sub_size)) { + spudec_update_palette(vo_spudec,spu_clut); + spudec_dvdnav_mode(vo_spudec, 0, dvdnav_color_spu_flg); /* spu menu button off */ + spudec_dvdnav_area(vo_spudec,highlight.sx,highlight.sy,highlight.ex, + highlight.ey,highlight.palette); /* set spu button area & palette */ + if(vo_spudec) spudec_reset(vo_spudec); + vo_osd_changed(OSDTYPE_SPU); + } + } else { + spudec_update_palette(vo_spudec,spu_clut); + spudec_dvdnav_mode(vo_spudec, 1, dvdnav_color_spu_flg); /* spu menu button on */ + spudec_dvdnav_area(vo_spudec,highlight.sx,highlight.sy,highlight.ex, + highlight.ey,highlight.palette); /* set spu button area & palette */ + vo_osd_changed(OSDTYPE_SPU); + if (!vo_spudec || !spudec_visible(vo_spudec)) { // if unsucessful spu button visible + osd_set_nav_box(highlight.sx,highlight.sy,highlight.ex,highlight.ey); // then use simple box + vo_osd_changed(OSDTYPE_DVDNAV); + } else { + osd_set_nav_box(0,0,0,0); // id sucessful spu button visible the + vo_osd_changed(OSDTYPE_DVDNAV); // then hide simple box + } + } +} + +// +// query: dvdnav stream change (cell, title, audio or subtitle) +// +static int mp_dvdnav_is_stream_change() { + if (!mp_dvdnav_is_change(mpctx->stream)) return 0; + //mp_dvdnav_set_audio_channels(mpctx->stream,mpctx->demuxer); + return 1; +} + +// +// video frame preprocess: before decode_video() +// +static void* mp_dvdnav_decode_video_pre(int *in_size, + unsigned char **start, mp_image_t* decoded_frame) { + int dvdnav_audio,dvdnav_spu; + + // change in dvdnav stream + if (mp_dvdnav_iscellchage(mpctx->stream,0)) { + // suspend read from dvdnav stream, and set auto_wait + mp_dvdnav_wait_read(mpctx->stream, 1, 1); + // free last stored frame image + if (mpctx->smpi) free_mp_image(mpctx->smpi); + mpctx->smpi=NULL; + // clear buffers + if (mpctx->last_buffer) free(mpctx->last_buffer); + mpctx->last_buffer=NULL; + mpctx->last_in_size=0; + if (mpctx->d_sub) { + dvdsub_id = -2; + if(0<=(dvdnav_spu=mp_dvdnav_get_spu(mpctx->stream))) { + dvdsub_id = dvdnav_spu; + mpctx->d_sub->id = dvdnav_spu; + } + } + if (mpctx->sh_video) { + // clear video pts + mpctx->d_video->pts=0.0f; + mpctx->sh_video->pts=0.0f; + mpctx->sh_video->i_pts=0.0f; + mpctx->sh_video->last_pts=0.0f; + mpctx->sh_video->num_buffered_pts=0; + mpctx->sh_video->num_frames=0; + mpctx->sh_video->num_frames_decoded=0; + mpctx->sh_video->timer=0.0f; + mpctx->sh_video->stream_delay=0.0f; + mpctx->demuxer->stream_pts=MP_NOPTS_VALUE; + mpctx->sh_video->timer=0; + } + if (mpctx->sh_audio) { + dvdnav_audio=dvdnav_aid_from_audio_num(mpctx->stream, + mp_dvdnav_get_audio(mpctx->stream)); + if(dvdnav_audio!=-1 && mpctx->demuxer->audio->id!=dvdnav_audio) + audio_id = demuxer_switch_audio(mpctx->demuxer, dvdnav_audio); // switch audio + // free audio packs and reset + ds_free_packs(mpctx->d_audio); + audio_delay -= mpctx->sh_audio->stream_delay; + mpctx->delay=-audio_delay; + mpctx->audio_out->reset(); + resync_audio_stream(mpctx->sh_audio); + } + audio_delay=0.0f; + correct_pts=0; + // clear all eof flags + mpctx->d_video->eof=mpctx->d_audio->eof= + mpctx->stream->eof=0; + // set nav menu + mp_dvdnav_highlight_handle(1); + // enable read from dvdnav stream + mp_dvdnav_wait_read(mpctx->stream, 0, 1); + // reset cell change flag + mp_dvdnav_iscellchage(mpctx->stream,1); + } +// Wait or still frame (in_size==-1): if frame decode OK then return stored image + if (*in_size<0 && !mpctx->last_buffer && mpctx->smpi && + !mpctx->libmpeg2_count) + decoded_frame=mpctx->smpi; + mpctx->dup_frame=0; + if (*in_size<0 && mpctx->last_buffer) { + mpctx->dup_frame=1; + if (!mpctx->libmpeg2_count) + mpctx->libmpeg2_count=5; + // is valid last video buffer (required libmpeg2!) + if (mpctx->last_start) { + // Set start, in_size and copy frame data from stored frame + *start=mpctx->last_start; + *in_size=mpctx->last_in_size; + memcpy(*start,mpctx->last_buffer,*in_size); + } else { + *start=mpctx->last_buffer; + *in_size=mpctx->last_in_size; + } + } + return decoded_frame; +} + +// +// video frame postprocess: after decode_video() +// +static void* mp_dvdnav_decode_video_post(int in_size, + unsigned char *start, mp_image_t* decoded_frame, + sh_video_t *sh_video, int drop_frame) { + float len; + + if (in_size<0) { + if (mpctx->last_buffer) { + // free buffer + free(mpctx->last_buffer); + mpctx->last_buffer=NULL; + mpctx->last_in_size=0; + } + // get duration of part + len = demuxer_get_time_length(mpctx->demuxer); + if ((mpctx->sh_video->pts>=len || !mpctx->smpi) && + mpctx->sh_video->pts>0.0 && len>0.0) { + // clear still frame in dvdnav + mp_dvdnav_still_skip(mpctx->stream); + // clear wait in dvdnav + mp_dvdnav_wait_skip(mpctx->stream); + } + // increment video frame + mpctx->sh_video->pts+=1/mpctx->sh_video->fps; + } else { + if (mpctx->dup_frame) { + if (mpctx->libmpeg2_count) + mpctx->libmpeg2_count--; + if (!mpctx->libmpeg2_count) { + // clear buffers + if (mpctx->last_buffer) + free(mpctx->last_buffer); + mpctx->last_buffer=NULL; + mpctx->last_in_size=0; + if (!decoded_frame && !mpctx->smpi) { + mp_msg(MSGT_CPLAYER,MSGL_ERR, + "Can't decode still frame.\n" + "Please, you try play dvdnav to -vc ffmpeg12 option.\n"); + mpctx->eof=1; + } + } + // no duplicate mode + } else { + // clear buffer + if (mpctx->last_buffer) + free(mpctx->last_buffer); + mpctx->last_in_size=in_size; + // allocate buffer and store read video frame data + mpctx->last_buffer=malloc(in_size); + mpctx->last_start=start; + if (mpctx->last_buffer) + memcpy(mpctx->last_buffer,start,in_size); + else + mpctx->last_in_size=-1; + } + // if decoded OK and no stored image then store image + if (decoded_frame && mpctx->smpi!=decoded_frame) { + mpctx->smpi=mp_dvdnav_copympi(mpctx->smpi,decoded_frame); + } + } + return decoded_frame; +} + +#endif + static void adjust_sync_and_print_status(int between_frames, float timing_error) { current_module="av_sync"; @@ -1881,8 +2189,16 @@ //============================== SLEEP: =================================== // flag 256 means: libvo driver does its timing (dvb card) - if (*time_frame > 0.001 && !(vo_flags&256)) + update_osd_msg(); + if (*time_frame > 0.001 && !(vo_flags&256)) { *time_frame = timing_sleep(*time_frame); + // if we slept long call this once BEFORE adding new messages, + // otherwise it can kill changed messages as "too old" on the next call + update_osd_msg(); + if (*time_frame > 0) + return 1; + } + return frame_time_remaining; } @@ -2002,7 +2318,7 @@ *blit_frame = 0; // Don't blit if we hit EOF if (!correct_pts) { unsigned char* start=NULL; - void *decoded_frame; + void *decoded_frame=NULL; int drop_frame=0; int in_size; @@ -2010,6 +2326,17 @@ frame_time = sh_video->next_frame_time; in_size = video_read_frame(sh_video, &sh_video->next_frame_time, &start, force_fps); +#ifdef USE_DVDNAV + // wait, still frame or EOF + if (mpctx->stream->type==STREAMTYPE_DVDNAV && in_size < 0) { + if (mp_dvdnav_isreallyeof(mpctx->stream)) printf("really eof *************\n"); + if (mp_dvdnav_isreallyeof(mpctx->stream)) return -1; + // if not (wait, still frame) then clear eof flags + if (mpctx->d_video) mpctx->d_video->eof=0; + if (mpctx->d_audio) mpctx->d_audio->eof=0; + mpctx->stream->eof=0; + } else +#endif if (in_size < 0) return -1; if (in_size > max_framesize) @@ -2040,8 +2367,22 @@ update_teletext(sh_video, mpctx->demuxer, 0); update_osd_msg(); current_module = "decode_video"; +#ifdef USE_DVDNAV + if (mpctx->stream->type==STREAMTYPE_DVDNAV) + // call dvdnav video preprocess + decoded_frame=mp_dvdnav_decode_video_pre(&in_size, + &start,decoded_frame); + // if stored image then do not call decode_video() + if (in_size>0 && !decoded_frame) +#endif decoded_frame = decode_video(sh_video, start, in_size, drop_frame, sh_video->pts); +#ifdef USE_DVDNAV + if (mpctx->stream->type==STREAMTYPE_DVDNAV) + // call dvdnav video postprocess + decoded_frame=mp_dvdnav_decode_video_post(in_size, + start,decoded_frame,sh_video, drop_frame); +#endif current_module = "filter_video"; *blit_frame = (decoded_frame && filter_video(sh_video, decoded_frame, sh_video->pts)); @@ -2326,7 +2667,7 @@ if(strstr(base, "gmplayer")) use_gui=1; } - + if (use_gui) enable_mouse_movements=1; mconfig = m_config_new(); m_config_register_options(mconfig,mplayer_opts); // TODO : add something to let modules register their options @@ -3351,6 +3692,17 @@ end_at.type = END_AT_NONE; } +#ifdef USE_DVDNAV +// free stored image +if (mpctx->smpi) free_mp_image(mpctx->smpi); +mpctx->smpi=NULL; +if (mpctx->stream->type==STREAMTYPE_DVDNAV) { + // enable read from dvdnav stream and set auto wait mode + mp_dvdnav_wait_read(mpctx->stream, 0, 1); + // clear cell change flag + mp_dvdnav_iscellchage(mpctx->stream,1); + } +#endif while(!mpctx->eof){ float aq_sleep_time=0; @@ -3432,6 +3784,8 @@ if (!frame_time_remaining && blit_frame) { unsigned int t2=GetTimer(); + update_osd_msg(); + mpctx->video_out->draw_osd(); if(vo_config_count) mpctx->video_out->flip_page(); mpctx->num_buffered_frames--; @@ -3476,10 +3830,25 @@ #ifdef USE_DVDNAV if (mpctx->stream->type == STREAMTYPE_DVDNAV) { + if(dvdnav_color_spu==0) { nav_highlight_t hl; mp_dvdnav_get_highlight (mpctx->stream, &hl); osd_set_nav_box (hl.sx, hl.sy, hl.ex, hl.ey); vo_osd_changed (OSDTYPE_DVDNAV); + } else { + if (mp_dvdnav_is_stream_change()) { // is cell change (title, part, audio, subtitle) + double ar=-1.0; + if(stream_control(mpctx->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED) + mpctx->sh_video->stream_aspect = ar; + mp_dvdnav_audio_handle(); // call audio process + mp_dvdnav_spu_handle(); // call subtitle process +#ifdef HAVE_NEW_GUI + if ( use_gui ) guiGetEvent( guiSetStream,(char *)mpctx->stream ); // update gui dvdnav stream info +#endif + mp_dvdnav_highlight_handle(1); // update dvdnav menu + } else + mp_dvdnav_highlight_handle(0); + } } #endif @@ -3488,6 +3857,7 @@ current_module="pause"; if (mpctx->osd_function == OSD_PAUSE) { + update_osd_msg(); pause_loop(); mpctx->was_paused = 1; } @@ -3530,6 +3900,7 @@ if(rel_seek_secs || abs_seek_pos){ if (seek(mpctx, rel_seek_secs, abs_seek_pos) >= 0) { + time_frame = 0; // Set OSD: if(!loop_seek){ if( !edl_decision ) --- dvdread/ifo_read.c 2007-10-07 21:49:28.000000000 +0200 +++ dvdread/ifo_read.c 2007-10-14 12:59:03.000000000 +0200 @@ -755,6 +755,10 @@ B2N_16(pgc->cell_playback_offset); B2N_16(pgc->cell_position_offset); + for(i = 0; i < 8; i++) + B2N_16(*((uint16_t*)&pgc->audio_control[i])); + for(i = 0; i < 32; i++) + B2N_32(*((uint32_t*)&pgc->subp_control[i])); for(i = 0; i < 16; i++) B2N_32(pgc->palette[i]); --- dvdread/ifo_types.h 2007-10-07 21:49:28.000000000 +0200 +++ dvdread/ifo_types.h 2007-10-14 12:59:59.000000000 +0200 @@ -424,18 +424,18 @@ unsigned int zero4 : 3; unsigned int s_panscan : 5; /* stream for 16:9 with pan&scan data on 4:3 display */ #else - unsigned int s_4p3 : 5; /* stream for 4:3 on any display */ - unsigned int zero1 : 2; - unsigned int present : 1; - - unsigned int s_wide : 5; /* stream for 16:9 on widescreen display */ - unsigned int zero2 : 3; + unsigned int s_panscan : 5; /* stream for 16:9 with pan&scan data on 4:3 display */ + unsigned int zero4 : 3; unsigned int s_lbox : 5; /* stream for 16:9 on letterboxed 4:3 display */ unsigned int zero3 : 3; - unsigned int s_panscan : 5; /* stream for 16:9 with pan&scan data on 4:3 display */ - unsigned int zero4 : 3; + unsigned int s_wide : 5; /* stream for 16:9 on widescreen display */ + unsigned int zero2 : 3; + + unsigned int s_4p3 : 5; /* stream for 4:3 on any display */ + unsigned int zero1 : 2; + unsigned int present : 1; #endif } ATTRIBUTE_PACKED subp_mapping_t; @@ -447,12 +447,13 @@ unsigned int present : 1; unsigned int zero1 : 4; unsigned int s_audio : 3; + uint8_t zero2; #else + uint8_t zero2; unsigned int s_audio : 3; unsigned int zero1 : 4; unsigned int present : 1; #endif - uint8_t zero2; } ATTRIBUTE_PACKED audio_mapping_t; /** --- spudec.c 2007-10-07 21:49:33.000000000 +0200 +++ spudec.c 2007-10-23 17:35:17.000000000 +0200 @@ -94,6 +94,52 @@ int spu_changed; unsigned int forced_subs_only; /* flag: 0=display all subtitle, !0 display only forced subtitles */ unsigned int is_forced_sub; /* true if current subtitle is a forced subtitle */ + + packet_t *last_packet; + unsigned int widthuv, heightuv, strideuv; + unsigned int start_coluv, end_coluv; + unsigned int start_rowuv, end_rowuv; + size_t image_sizeuv; + size_t scaled_image_sizeuv; + size_t image_sizeyuy; + + unsigned int scaled_frame_widthuv, scaled_frame_heightuv; + unsigned int scaled_start_coluv, scaled_start_rowuv; + unsigned int scaled_widthuv, scaled_heightuv, scaled_strideuv; + unsigned char *scaled_imageu; + unsigned char *scaled_imagev; + unsigned char *scaled_aimageuv; + + unsigned int hpalette[4]; + unsigned int halpha[4]; + unsigned int hcuspal[4]; + + unsigned char *imageu; /* u value from yUv */ + unsigned char *imagev; /* v value from yuV*/ + unsigned char *aimageuv; /* alpha with uv*/ + unsigned char *imageyuy; /* yuy2 */ + unsigned char *aimageyuy; /* alpha with yuy2*/ + unsigned int strideyuy; + + int dvdnav_color_spu; /* flag: 0 = grayscale SPU, 1 = YUV color SPU 2 = RGB 3 = BGR */ + + int dvdnav_menu; /* flag: 0=normal subtitle, 1=dvdnav menu */ + unsigned int dvdnav_sx; /* dvdnav menu item box */ + unsigned int dvdnav_ex; + unsigned int dvdnav_sy; + unsigned int dvdnav_ey; + unsigned int dvdnav_modify; /* dvdnav menu item box is modify */ + uint32_t dvdnav_palette; /* dvdnav menu button palette */ + unsigned int dvdnav_x0; /* dvdnav menu item draw_alpha coordinates */ + unsigned int dvdnav_y0; + unsigned int dvdnav_w; + unsigned int dvdnav_h; + unsigned char *dvdnav_image; /* dvdnav menu item image */ + unsigned char *dvdnav_aimage; /* dvdnav menu item alpha */ + unsigned int dvdnav_stride; + unsigned int dvdnav_allocated; + unsigned int dvdnav_scalex; + unsigned int dvdnav_scaley; } spudec_handle_t; static void spudec_queue_packet(spudec_handle_t *this, packet_t *packet) @@ -213,11 +259,147 @@ } else { mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: update_spu: malloc requested %d bytes\n", 2 * this->stride * this->height); } +// +// Cut the sub to visible part UV planes +// + unsigned char *imageu; + unsigned char *imagev; + switch (this->dvdnav_color_spu) { + case DVDNAV_SPU_YUV: + case DVDNAV_SPU_YUY: + for (fy = 0; fy < this->image_sizeuv && !this->aimageuv[fy]; fy++); + for (ly = this->strideuv * this->heightuv-1; + ly && !this->aimageuv[ly]; ly--); + first_y = fy / this->strideuv; + last_y = ly / this->strideuv; + this->start_rowuv += first_y; + // Some subtitles trigger this condition + if (last_y + 1 > first_y ) { + this->heightuv = last_y - first_y +1; + } else { + this->heightuv = 0; + this->image_sizeuv = 0; + return; + } + // printf("new h %d new start %d (sz %d st %d)---\n\n", this->height, this->start_row, this->image_size, this->stride); + imageu = malloc(3 * this->strideuv * this->heightuv); + if(imageu){ + this->image_sizeuv = this->strideuv * this->heightuv; + imagev = imageu + this->image_sizeuv; + aimage = imagev + this->image_sizeuv; + memcpy(imageu, this->imageu + this->strideuv * first_y, + this->image_sizeuv); + memcpy(imagev, this->imagev + this->strideuv * first_y, + this->image_sizeuv); + memcpy(aimage, this->aimageuv + this->strideuv * first_y, + this->image_sizeuv); + free(this->imageu); + this->imageu = imageu; + this->imagev = imagev; + this->aimageuv = aimage; + } else { + mp_msg(MSGT_SPUDEC, MSGL_FATAL, + "Fatal: update_spu: malloc requested %d bytes\n", + 3 * this->strideuv * this->height); + } + break; + case DVDNAV_SPU_RGB: + case DVDNAV_SPU_BGR: + this->image_sizeuv = this->stride * this->height; + imageu = malloc(2 * this->stride * this->height); + if(imageu){ + imagev = imageu + this->image_size; + memcpy(imageu, this->imageu + this->stride * first_y, this->image_size); + memcpy(imagev, this->imagev + this->stride * first_y, this->image_size); + free(this->imageu); + this->imageu = imageu; + this->imagev = imagev; + this->aimageuv = NULL; + } else { + mp_msg(MSGT_SPUDEC, MSGL_FATAL, + "Fatal: update_spu: malloc requested %d bytes\n", + 2 * this->stride * this->height); + } + break; + } +} + +// +// Convert yuv color to rgb color +// +void spu_yuv_to_rgb(unsigned int y,unsigned int u,unsigned int v, + unsigned int *r,unsigned int *g,unsigned int *b) +{ +int ty,tu,tv; +int tr,tg,tb; +ty=y;tv=u;tu=v; +tr = (298*(ty-16)+408*(tv-128))/256; +tg = (298*(ty-16)-100*(tu-128)-208*(tv-128))/256; +tb = (298*(ty-16)+516*(tu-128))/256; +if(tr>255) tr=255; if(tr<0) tr=0; +if(tg>255) tg=255; if(tg<0) tg=0; +if(tb>255) tb=255; if(tb<0) tb=0; +*r=tr; *g=tg; *b=tb; +return; +} + +// +// Fill to spu image buffer +// y : image col +// x : start pos in image row +// len : fill length in image row +// color : Y: (YUV,YUY,Y), Red: (RGB) or Blue: (BGR) +// coloru: U: (YUV,YUY), Green: (RGB,BGR) +// colorv: V: (YUV,YUY), Blue: (RGB) or Red (BGR) +// alpha: alpha channel +static void spudec_process_fill(spudec_handle_t *this, int x, int y, int len, + unsigned char color, unsigned char coloru, unsigned char colorv, + unsigned char alpha) +{ +unsigned int corrx, corry, corrl; +if (this->stride-x-len<0) return; +if (len<0) return; +switch (this->dvdnav_color_spu) + { + case DVDNAV_SPU_YUV: + case DVDNAV_SPU_YUY: + corry=y & 0x01; + corrx=x & 0x01; + corrl=len & 0x01; + memset(this->image + y * this->stride + x, color, len); + memset(this->aimage + y * this->stride + x, alpha, len); + memset(this->imageu + (y-corry)/2 * this->strideuv + (x+corrx)/2, coloru, + (len-corrl)/2); + memset(this->imagev + (y-corry)/2 * this->strideuv + (x+corrx)/2, colorv, + (len-corrl)/2); + memset(this->aimageuv + (y-corry)/2 * this->strideuv + (x+corrx)/2, alpha, + (len-corrl)/2); + break; + case DVDNAV_SPU_RGB: + case DVDNAV_SPU_BGR: + memset(this->image + y * this->stride + x, color, len); + memset(this->imageu + y * this->stride + x, coloru, len); + memset(this->imagev + y * this->stride + x, colorv, len); + memset(this->aimage + y * this->stride + x, alpha, len); + break; + default: + memset(this->image + y * this->stride + x, color, len); + memset(this->aimage + y * this->stride + x, alpha, len); + break; +} } static void spudec_process_data(spudec_handle_t *this, packet_t *packet) { unsigned int cmap[4], alpha[4]; + unsigned int thpalette[4], thalpha[4]; /* dvdnav highlight menu palette */ + unsigned int hcmap[4], halpha[4]; /* dvdnav highlight map */ + unsigned int cmapu[4], cmapv[4]; + unsigned int hcmapu[4], hcmapv[4]; + unsigned int control_start; + unsigned int current_nibble[2]; + unsigned int ty,tu,tv,tr,tg,tb; + int deinterlace_oddness; unsigned int i, x, y; this->scaled_frame_width = 0; @@ -229,6 +411,18 @@ this->height = packet->height; this->width = packet->width; this->stride = packet->stride; + this->strideuv = packet->stride; + control_start = packet->control_start; + current_nibble[0]=packet->current_nibble[0]; + current_nibble[1]=packet->current_nibble[1]; + deinterlace_oddness=packet->deinterlace_oddness; + + this->start_coluv = packet->start_col/2; + this->end_coluv = packet->end_col/2; + this->start_rowuv = packet->start_row/2; + this->end_rowuv = packet->end_row/2; + this->heightuv = packet->height/2+1; + this->widthuv = packet->width/2+1; for (i = 0; i < 4; ++i) { alpha[i] = mkalpha(packet->alpha[i]); if (alpha[i] == 0) @@ -244,7 +438,92 @@ cmap[i] = 256 - alpha[i]; } } - + if (this->dvdnav_menu) { + for (i = 0; i < 4; ++i) { /* use button palette */ + thalpha[i]=(this->dvdnav_palette >> ((3-i)*4)) & 0x0f; + thpalette[i]=(this->dvdnav_palette >> (16+(3-i)*4)) & 0x0f; + halpha[i] = mkalpha(thalpha[i]); + hcmap[i] = ((this->global_palette[thpalette[i]] >> 16) & 0xff); + if (alpha[i] == 0) {cmap[i] = 0; cmapu[i] = 0; cmapv[i] = 0;} else { + if (cmap[i] + alpha[i] > 255) + cmap[i] = 256 - alpha[i]; + switch (this->dvdnav_color_spu) { + case DVDNAV_SPU_YUV: + case DVDNAV_SPU_YUY: + cmap[i] = ((this->global_palette[packet->palette[i]] >> 16) & 0xff); // Y + cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8; + cmapu[i] = ((this->global_palette[packet->palette[i]] >> 8) & 0xff); // u + cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8; + cmapv[i] = ((this->global_palette[packet->palette[i]] >> 0) & 0xff); // v + cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8; + break; + case DVDNAV_SPU_RGB: + ty = ((this->global_palette[packet->palette[i]] >> 16) & 0xff); // Y + tu = ((this->global_palette[packet->palette[i]] >> 8) & 0xff); // u + tv = ((this->global_palette[packet->palette[i]] >> 0) & 0xff); // v + spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb); + cmap[i] = tr; // Red + cmapu[i] = tg; // Green + cmapv[i] = tb; // Blue + cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8; + cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8; + cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8; + break; + case DVDNAV_SPU_BGR: + ty = ((this->global_palette[packet->palette[i]] >> 16) & 0xff); // Y + tu = ((this->global_palette[packet->palette[i]] >> 8) & 0xff); // u + tv = ((this->global_palette[packet->palette[i]] >> 0) & 0xff); // v + spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb); + cmap[i] = tb; // Blue + cmapu[i] = tg; // Green + cmapv[i] = tr; // Red + cmap[i] = ((0x100-alpha[i])*cmap[i]) >> 8; + cmapu[i] = ((0x100-alpha[i])*cmapu[i]) >> 8; + cmapv[i] = ((0x100-alpha[i])*cmapv[i]) >> 8; + break; + } + } + if (halpha[i] == 0) {hcmap[i] = 0; hcmapu[i] = 0; hcmapv[i] = 0;} else { + if (hcmap[i] + halpha[i] > 255) + hcmap[i] = 256 - halpha[i]; + switch (this->dvdnav_color_spu) { + case DVDNAV_SPU_YUV: + case DVDNAV_SPU_YUY: + hcmap[i] = ((this->global_palette[thpalette[i]] >> 16) & 0xff); // Y + hcmap[i] = ((0x100-halpha[i])*hcmap[i]) >> 8; + hcmapu[i] = ((this->global_palette[thpalette[i]] >> 8) & 0xff); // u + hcmapu[i] = ((0x100-halpha[i])*hcmapu[i]) >> 8; + hcmapv[i] = ((this->global_palette[thpalette[i]] >> 0) & 0xff); // v + hcmapv[i] = ((0x100-halpha[i])*hcmapv[i]) >> 8; + break; + case DVDNAV_SPU_RGB: + ty = ((this->global_palette[thpalette[i]] >> 16) & 0xff); // Y + tu = ((this->global_palette[thpalette[i]] >> 8) & 0xff); // u + tv = ((this->global_palette[thpalette[i]] >> 0) & 0xff); // v + spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb); + hcmap[i] = tr; + hcmapu[i] = tg; + hcmapv[i] = tb; + hcmap[i] = ((0x100-halpha[i])*hcmap[i]) >> 8; + hcmapu[i] = ((0x100-halpha[i])*hcmapu[i]) >> 8; + hcmapv[i] = ((0x100-halpha[i])*hcmapv[i]) >> 8; + break; + case DVDNAV_SPU_BGR: + ty = ((this->global_palette[thpalette[i]] >> 16) & 0xff); // Y + tu = ((this->global_palette[thpalette[i]] >> 8) & 0xff); // u + tv = ((this->global_palette[thpalette[i]] >> 0) & 0xff); // v + spu_yuv_to_rgb(ty,tu,tv,&tr,&tg,&tb); + hcmap[i] = tb; + hcmapu[i] = tg; + hcmapv[i] = tr; + hcmap[i] = ((0x100-halpha[i])*hcmap[i]) >> 8; + hcmapu[i] = ((0x100-halpha[i])*hcmapu[i]) >> 8; + hcmapv[i] = ((0x100-halpha[i])*hcmapv[i]) >> 8; + break; + } + } + } +} if (this->image_size < this->stride * this->height) { if (this->image != NULL) { free(this->image); @@ -258,6 +537,58 @@ } if (this->image == NULL) return; +// Alloc 2nd image buffer (uv) +if(this->dvdnav_menu && this->dvdnav_color_spu) + { + if (this->imageyuy) + { + free(this->imageyuy); + this->imageyuy=NULL; + this->aimageyuy=NULL; + } + if (this->dvdnav_color_spu==DVDNAV_SPU_YUV || + this->dvdnav_color_spu==DVDNAV_SPU_YUY) + { + if (this->image_sizeuv < this->strideuv * this->heightuv) + { + if (this->imageu != NULL) + { + free(this->imageu); + this->image_sizeuv = 0; + } + this->imageu = malloc(3 * this->strideuv * this->heightuv); + if (this->imageu) + { + this->image_sizeuv = this->strideuv * this->heightuv; + this->imagev = this->imageu + this->image_sizeuv; + this->aimageuv = this->imagev + this->image_sizeuv; + } + } + memset(this->imageu,0,3 * this->strideuv * this->heightuv); + } else { + if (this->image_sizeuv < this->stride * this->height) + { + if (this->imageu != NULL) + { + free(this->imageu); + this->image_sizeuv = 0; + } + this->imageu = malloc(2 * this->stride * this->height); + if (this->imageu) + { + this->image_sizeuv = this->stride * this->height; + this->imagev = this->imageu + this->image_sizeuv; + this->aimageuv = this->imagev + this->image_sizeuv; + } + } + memset(this->imageu,0,2 * this->stride * this->height); + } + if (this->imageu == NULL) return; + } else { + if (this->imageu) free(this->imageu); + this->imageu=NULL; + this->image_sizeuv=0; + } /* Kludge: draw_alpha needs width multiple of 8. */ if (this->width < this->stride) @@ -292,8 +623,89 @@ if (len > this->width - x || len == 0) len = this->width - x; /* FIXME have to use palette and alpha map*/ +// +// Fill dvdnav menu area to image buffer +// + if (this->dvdnav_menu) + { + if (this->start_row+y>=this->dvdnav_sy && + this->start_row+y<=this->dvdnav_ey) + { + if (this->start_col+x>=this->dvdnav_sx && + this->start_col+x+len<=this->dvdnav_ex) + spudec_process_fill(this, + x, + y, + len, + hcmap[color], hcmapu[color], hcmapv[color], halpha[color]); + else if(this->start_col+xdvdnav_sx && + this->start_col+x+len>this->dvdnav_sx && + this->start_col+x+len<=this->dvdnav_ex) + { + spudec_process_fill(this, + x, + y, + this->dvdnav_sx-this->start_col-x, + cmap[color], cmapu[color], cmapv[color], alpha[color]); + spudec_process_fill(this, + this->dvdnav_sx-this->start_col, + y, + len+this->start_col+x-this->dvdnav_sx, + hcmap[color], hcmapu[color], hcmapv[color], halpha[color]); + } + else if(this->start_col+xdvdnav_sx && + this->start_col+x+len>this->dvdnav_sx && + this->start_col+x+len>this->dvdnav_ex) + { + spudec_process_fill(this, + x, + y, + this->dvdnav_sx-this->start_col-x, + cmap[color], cmapu[color], cmapv[color], alpha[color]); + spudec_process_fill(this, + this->dvdnav_sx-this->start_col, + y, + this->dvdnav_ex-this->dvdnav_sx, + hcmap[color], hcmapu[color], hcmapv[color], halpha[color]); + spudec_process_fill(this, + this->dvdnav_ex-this->start_col, + y, + x+len+this->start_col-this->dvdnav_ex, + cmap[color], cmapu[color], cmapv[color], alpha[color]); + } + else if(this->start_col+x>=this->dvdnav_sx && + this->start_col+xdvdnav_ex && + this->start_col+x+len>this->dvdnav_ex) + { + spudec_process_fill(this, + x, + y, + this->dvdnav_ex-this->start_col-x, + hcmap[color], hcmapu[color], hcmapv[color], halpha[color]); + spudec_process_fill(this, + this->dvdnav_ex-this->start_col, + y, + len+this->start_col+x-this->dvdnav_ex, + cmap[color], cmapu[color], cmapv[color], alpha[color]); + } + else + spudec_process_fill(this, + x, + y, + len, + cmap[color], cmapu[color], cmapv[color], alpha[color]); + } else + spudec_process_fill(this, + x, + y, + len, + cmap[color], cmapu[color], cmapv[color], alpha[color]); + } + else + { memset(this->image + y * this->stride + x, cmap[color], len); memset(this->aimage + y * this->stride + x, alpha[color], len); + } x += len; if (x >= this->width) { next_line(packet); @@ -301,7 +713,12 @@ ++y; } } + packet->control_start = control_start; + packet->current_nibble[0]=current_nibble[0]; + packet->current_nibble[1]=current_nibble[1]; + packet->deinterlace_oddness=deinterlace_oddness; spudec_cut_image(this); +//printf("spudec_process_data: w: %i h: %i end\n",this->height,this->width); } @@ -316,6 +733,7 @@ { int used[16],i,cused,start,step,color; +//printf("spudec:c1 ");for(i=0;i<16;i++) printf("%x ",this->global_palette[i]); printf("\n"); memset(used, 0, sizeof(used)); for (i=0; i<4; i++) if (packet->alpha[i]) /* !Transparent? */ @@ -339,6 +757,7 @@ start += step; } } +//printf("spudec:c2 ");for(i=0;i<16;i++) printf("%x ",this->global_palette[i]); printf("\n"); } static void spudec_process_control(spudec_handle_t *this, unsigned int pts100) @@ -586,6 +1005,7 @@ spu->now_pts = 0; spu->end_pts = 0; spu->packet_size = spu->packet_offset = 0; +// if (spu->last_packet) {printf("free4\n");spudec_free_packet(spu->last_packet); spu->last_packet=NULL;} } void spudec_heartbeat(void *this, unsigned int pts100) @@ -593,13 +1013,22 @@ spudec_handle_t *spu = (spudec_handle_t*) this; spu->now_pts = pts100; + if(spu->queue_head) spu->queue_head->start_pts=0; while (spu->queue_head != NULL && pts100 >= spu->queue_head->start_pts) { packet_t *packet = spudec_dequeue_packet(spu); spu->start_pts = packet->start_pts; spu->end_pts = packet->end_pts; - if (spu->auto_palette) + if (spu->auto_palette && !spu->dvdnav_menu) compute_palette(spu, packet); spudec_process_data(spu, packet); + if (spu->dvdnav_menu) + { + if(spu->last_packet) + { + spudec_free_packet(spu->last_packet); + } + spu->last_packet=packet; + } else spudec_free_packet(packet); spu->spu_changed = 1; } @@ -605,12 +1034,18 @@ } } + int spudec_visible(void *this){ spudec_handle_t *spu = (spudec_handle_t *)this; + if(!spu) return 0; + if (spu->dvdnav_menu && spu->height > 0) + { + if(spu->height>0) spu->end_pts=UINT_MAX; + return 1; + } int ret=(spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->height > 0); -// printf("spu visible: %d \n",ret); return ret; } @@ -622,12 +1057,102 @@ } } -void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)) +void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)) { spudec_handle_t *spu = (spudec_handle_t *)this; if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->image) { - draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height, + if (spu->dvdnav_menu) + { /* spu menu mode? */ + switch (spu->dvdnav_color_spu) + { +// +// Draw spu menu Y,u and v planes in YUV mode +// + case DVDNAV_SPU_YUV: + draw_alpha(spu->start_col, + spu->start_row, + spu->width, + spu->height, + DEST_PLANES_Y, + spu->image, + spu->aimage, + spu->stride); + draw_alpha(spu->start_coluv, + spu->start_rowuv, + spu->widthuv, + spu->heightuv, + DEST_PLANES_U, + spu->imageu, + spu->aimageuv, + spu->strideuv); + draw_alpha(spu->start_coluv, + spu->start_rowuv, + spu->widthuv, + spu->heightuv, + DEST_PLANES_V, + spu->imagev, + spu->aimageuv, + spu->strideuv); + break; +// +// Draw spu menu all planes in YUY mode +// + case DVDNAV_SPU_YUY: + if (!spu->imageyuy) spudec_create_yuy(spu,0); + if (spu->imageyuy) draw_alpha(spu->start_col, + spu->start_row, + spu->width*2, + spu->height/2, + DEST_PLANES_YUYV, + spu->imageyuy, + spu->aimageyuy, + spu->strideyuy); + break; +// +// Draw spu menu Red,Blue and Green on RGB or BGR mode +// + case DVDNAV_SPU_RGB: + case DVDNAV_SPU_BGR: + draw_alpha(spu->start_col, + spu->start_row, + spu->width, spu->height, + DEST_PLANES_BR, + spu->imagev, + spu->aimage, + spu->stride); + draw_alpha(spu->start_col, + spu->start_row, + spu->width, + spu->height, + DEST_PLANES_G, + spu->imageu, + spu->aimage, + spu->stride); + draw_alpha(spu->start_col, + spu->start_row, + spu->width, + spu->height, + DEST_PLANES_RB, + spu->image, + spu->aimage, + spu->stride); + break; +// +// Draw spu menu Y planes in normal mode +// + default: + draw_alpha(spu->start_col, + spu->start_row, + spu->width, + spu->height, + DEST_PLANES_Y, + spu->image, + spu->aimage, + spu->stride); + } + } else + draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,DEST_PLANES_Y, spu->image, spu->aimage, spu->stride); spu->spu_changed = 0; } @@ -737,6 +1262,125 @@ } } +// +// bilinear scale: u and v planes +// +static void scale_image_uv(int x, int y, scale_pixel* table_x, + scale_pixel* table_y, spudec_handle_t * spu) +{ + int alpha[4]; + int coloru[4]; + int colorv[4]; + unsigned int scale[4]; + int base = table_y[y].position * spu->strideuv + table_x[x].position; + int scaled = y * spu->scaled_strideuv + x; + alpha[0] = canon_alpha(spu->aimageuv[base]); + alpha[1] = canon_alpha(spu->aimageuv[base + 1]); + alpha[2] = canon_alpha(spu->aimageuv[base + spu->strideuv]); + alpha[3] = canon_alpha(spu->aimageuv[base + spu->strideuv + 1]); + coloru[0] = spu->imageu[base]; + coloru[1] = spu->imageu[base + 1]; + coloru[2] = spu->imageu[base + spu->strideuv]; + coloru[3] = spu->imageu[base + spu->strideuv + 1]; + colorv[0] = spu->imagev[base]; + colorv[1] = spu->imagev[base + 1]; + colorv[2] = spu->imagev[base + spu->strideuv]; + colorv[3] = spu->imagev[base + spu->strideuv + 1]; +// FIXME: color hack!!! +// scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0]; +// scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1]; +// scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2]; +// scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3]; + scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * 0x100; + scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * 0x100; + scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * 0x100; + scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * 0x100; + spu->scaled_imageu[scaled] = + (coloru[0] * scale[0] + + coloru[1] * scale[1] + + coloru[2] * scale[2] + + coloru[3] * scale[3])>>24; + spu->scaled_imagev[scaled] = + (colorv[0] * scale[0] + + colorv[1] * scale[1] + + colorv[2] * scale[2] + + colorv[3] * scale[3])>>24; + scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0]; + scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1]; + scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2]; + scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3]; + spu->scaled_aimageuv[scaled] = + (scale[0] + scale[1] + scale[2] + scale[3]) >> 16; + if (spu->scaled_aimageuv[scaled]){ + spu->scaled_aimageuv[scaled] = 256 - spu->scaled_aimageuv[scaled]; + if(spu->scaled_aimageuv[scaled] + spu->scaled_imageu[scaled] > 255) + spu->scaled_imageu[scaled] = 256 - spu->scaled_aimageuv[scaled]; + if(spu->scaled_aimageuv[scaled] + spu->scaled_imagev[scaled] > 255) + spu->scaled_imagev[scaled] = 256 - spu->scaled_aimageuv[scaled]; + } +} + +// +// bilinear scale: Red, Green and Blue planes +// +static void scale_image_rgb(int x, int y, scale_pixel* table_x, scale_pixel* table_y, spudec_handle_t * spu) +{ + int alpha[4]; + int colorr[4]; + int colorg[4]; + int colorb[4]; + unsigned int scale[4]; + int base = table_y[y].position * spu->stride + table_x[x].position; + int scaled = y * spu->scaled_stride + x; + alpha[0] = canon_alpha(spu->aimage[base]); + alpha[1] = canon_alpha(spu->aimage[base + 1]); + alpha[2] = canon_alpha(spu->aimage[base + spu->stride]); + alpha[3] = canon_alpha(spu->aimage[base + spu->stride + 1]); + colorr[0] = spu->image[base]; + colorr[1] = spu->image[base + 1]; + colorr[2] = spu->image[base + spu->stride]; + colorr[3] = spu->image[base + spu->stride + 1]; + colorg[0] = spu->imageu[base]; + colorg[1] = spu->imageu[base + 1]; + colorg[2] = spu->imageu[base + spu->stride]; + colorg[3] = spu->imageu[base + spu->stride + 1]; + colorb[0] = spu->imagev[base]; + colorb[1] = spu->imagev[base + 1]; + colorb[2] = spu->imagev[base + spu->stride]; + colorb[3] = spu->imagev[base + spu->stride + 1]; + scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0]; + scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1]; + scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2]; + scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3]; + spu->scaled_image[scaled] = + (colorr[0] * scale[0] + + colorr[1] * scale[1] + + colorr[2] * scale[2] + + colorr[3] * scale[3])>>24; + spu->scaled_imageu[scaled] = + (colorg[0] * scale[0] + + colorg[1] * scale[1] + + colorg[2] * scale[2] + + colorg[3] * scale[3])>>24; + spu->scaled_imagev[scaled] = + (colorb[0] * scale[0] + + colorb[1] * scale[1] + + colorb[2] * scale[2] + + colorb[3] * scale[3])>>24; + spu->scaled_aimage[scaled] = + (scale[0] + scale[1] + scale[2] + scale[3]) >> 16; + if (spu->scaled_aimage[scaled]){ + spu->scaled_aimage[scaled] = 256 - spu->scaled_aimage[scaled]; + if(spu->scaled_aimage[scaled] + spu->scaled_image[scaled] > 255) + spu->scaled_image[scaled] = 256 - spu->scaled_aimage[scaled]; + if(spu->scaled_aimage[scaled] + spu->scaled_imageu[scaled] > 255) + spu->scaled_imageu[scaled] = 256 - spu->scaled_aimage[scaled]; + if(spu->scaled_aimage[scaled] + spu->scaled_imagev[scaled] > 255) + spu->scaled_imagev[scaled] = 256 - spu->scaled_aimage[scaled]; + } +} + + void sws_spu_image(unsigned char *d1, unsigned char *d2, int dw, int dh, int ds, unsigned char *s1, unsigned char *s2, int sw, int sh, int ss) { @@ -763,68 +1407,358 @@ sws_freeContext(ctx); } -void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)) +// +// Convert Yuv image to YuY image +// +void spudec_create_yuy(void *this, int spu_scaled) +{ +spudec_handle_t *spu = this; +unsigned char *dptr; +unsigned char *daptr; +unsigned char *sptry; +unsigned char *sptru; +unsigned char *sptrv; +unsigned char *saptr; +unsigned char *saptruv; +int y,x; + +if (spu_scaled) { + spu->strideyuy=spu->scaled_stride*2; + spu->imageyuy=malloc(spu->strideyuy*(spu->height+2)*2); + memset(spu->imageyuy,0,spu->strideyuy*(spu->height+2)*2); + spu->aimageyuy=spu->imageyuy+spu->strideyuy*spu->scaled_height; + for(y=0;yscaled_height;y++) { + dptr=spu->imageyuy+y*spu->strideyuy; + daptr=spu->aimageyuy+y*spu->strideyuy; + sptry=spu->scaled_image+y*spu->scaled_stride; + sptru=spu->scaled_imageu+y/2*spu->scaled_strideuv; + sptrv=spu->scaled_imagev+y/2*spu->scaled_strideuv; + saptr=spu->scaled_aimage+y*spu->scaled_stride; + saptruv=spu->scaled_aimageuv+y/2*spu->scaled_strideuv; + for(x=0;xscaled_widthuv-1;x++) { + *dptr++=*sptry++; + *dptr++=*sptrv++; + *dptr++=*sptry++; + *dptr++=*sptru++; + *daptr++=*saptr++; + *daptr++=*saptruv; + *daptr++=*saptr++; + *daptr++=*saptruv++; + } } + } else { + spu->strideyuy=spu->stride*2; + spu->imageyuy=malloc(spu->strideyuy*(spu->height+2)*2); + memset(spu->imageyuy,0,spu->strideyuy*(spu->height+2)*2); + spu->aimageyuy=spu->imageyuy+spu->strideyuy*spu->height; + for(y=0;yheight;y++) { + dptr=spu->imageyuy+y*spu->strideyuy; + daptr=spu->aimageyuy+y*spu->strideyuy; + sptry=spu->image+y*spu->stride; + sptru=spu->imageu+y/2*spu->strideuv; + sptrv=spu->imagev+y/2*spu->strideuv; + saptr=spu->aimage+y*spu->stride; + saptruv=spu->aimageuv+y/2*spu->strideuv; + for(x=0;xwidthuv-1;x++) { + *dptr++=*sptry++; + *dptr++=*sptrv++; + *dptr++=*sptry++; + *dptr++=*sptru++; + *daptr++=*saptr++; + *daptr++=*saptruv; + *daptr++=*saptr++; + *daptr++=*saptruv++; + } } + } +} + +// +// Sws scale: u and v planes +// +void sws_spu_image_uv(unsigned char *du, unsigned char *dv, unsigned char *d2, + int dw, int dh, int ds, unsigned char *su, unsigned char *sv, + unsigned char *s2, int sw, int sh, int ss) +{ +struct SwsContext *ctx; +static SwsFilter filter; +static int firsttime = 1; +static float oldvar; +int i; + +if (!firsttime && oldvar != spu_gaussvar) sws_freeVec(filter.lumH); +if (firsttime) + { + filter.lumH = filter.lumV = + filter.chrH = filter.chrV = sws_getGaussianVec(spu_gaussvar, 3.0); + sws_normalizeVec(filter.lumH, 1.0); + firsttime = 0; + oldvar = spu_gaussvar; + } + +ctx=sws_getContext(sw, sh, PIX_FMT_GRAY8, dw, dh, PIX_FMT_GRAY8, SWS_GAUSS, &filter, NULL, NULL); +sws_scale(ctx,&su,&ss,0,sh,&du,&ds); +sws_scale(ctx,&sv,&ss,0,sh,&dv,&ds); +for (i=ss*sh-1; i>=0; i--) + if (!s2[i]) s2[i] = 255; //else s2[i] = 1; +sws_scale(ctx,&s2,&ss,0,sh,&d2,&ds); +for (i=ds*dh-1; i>=0; i--) + if (d2[i]==0) d2[i] = 1; + else if (d2[i]==255) d2[i] = 0; +sws_freeContext(ctx); +} + +// +// Sws scale: Red, Green and Blue planes +// +void sws_spu_image_rgb(unsigned char *dr, unsigned char *dg, unsigned char *db, + unsigned char *d2, int dw, int dh, int ds, + unsigned char *sr,unsigned char *sg,unsigned char *sb, + unsigned char *s2, int sw, int sh, int ss) +{ +struct SwsContext *ctx; +static SwsFilter filter; +static int firsttime = 1; +static float oldvar; +int i; + +if (!firsttime && oldvar != spu_gaussvar) sws_freeVec(filter.lumH); +if (firsttime) + { + filter.lumH = filter.lumV = + filter.chrH = filter.chrV = sws_getGaussianVec(spu_gaussvar, 3.0); + sws_normalizeVec(filter.lumH, 1.0); + firsttime = 0; + oldvar = spu_gaussvar; + } + +ctx=sws_getContext(sw, sh, PIX_FMT_GRAY8, dw, dh, PIX_FMT_GRAY8, SWS_GAUSS, &filter, NULL, NULL); +sws_scale(ctx,&sr,&ss,0,sh,&dr,&ds); +sws_scale(ctx,&sg,&ss,0,sh,&dg,&ds); +sws_scale(ctx,&sb,&ss,0,sh,&db,&ds); +for (i=ss*sh-1; i>=0; i--) if (!s2[i]) s2[i] = 255; //else s2[i] = 1; +sws_scale(ctx,&s2,&ss,0,sh,&d2,&ds); +for (i=ds*dh-1; i>=0; i--) + if (d2[i]==0) d2[i] = 1; + else if (d2[i]==255) d2[i] = 0; +sws_freeContext(ctx); +} + +// +// Enable/disable dvdmenu mode, and set color mode +// cflg = 0: Y SPU +// cflg = 1: YUV SPU +// cflg = 2: RGB SPU +// cflg = 3: BGR SPU +// cflg = 4: YUY SPU +// +void spudec_dvdnav_mode(void *this, int mode, int cflg) +{ /* set/clear spu menu mode */ +spudec_handle_t *spu = (spudec_handle_t *)this; +if (!spu) return; +spu->dvdnav_menu=mode; +if (mode) + spu->dvdnav_color_spu=cflg; + else + spu->dvdnav_color_spu=0; +if (!spu->dvdnav_menu && spu->last_packet) + { + spudec_free_packet(spu->last_packet); + spu->last_packet=NULL; + } +return; +} + +// +// Set dvd menu button draw area and palette +// +void spudec_dvdnav_area(void *this, uint16_t sx, uint16_t sy, uint16_t ex, + uint16_t ey, uint32_t palette) +{ +spudec_handle_t *spu = this; +if (!spu) return; +if (spu->dvdnav_sx==FFMIN(sx,ex) && + spu->dvdnav_ex==FFMAX(sx,ex) && + spu->dvdnav_sy==FFMIN(sy,ey) && + spu->dvdnav_ey==FFMAX(sy,ey) && + spu->dvdnav_palette==palette) return; +spu->dvdnav_sx=FFMIN(sx,ex); /* set spu button area, palette & on */ +spu->dvdnav_ex=FFMAX(sx,ex); +spu->dvdnav_sy=FFMIN(sy,ey); +spu->dvdnav_ey=FFMAX(sy,ey); +spu->dvdnav_palette=palette; +spu->dvdnav_modify=1; +if (spu->dvdnav_menu && spu->last_packet) + { +// if (spu->auto_palette) +// compute_palette(spu, spu->last_packet); + spudec_process_data(spu, spu->last_packet); + } +return; +} + +// +// Set dvd menu button palette +// +void spudec_dvdnav_palette(void *this, uint32_t palette) +{ +spudec_handle_t *spu = this; +if (!spu) return; +spu->dvdnav_palette=palette; /* set spu button palette */ +return; +} + +// +// Draw scaled image in YUV and YUY mode +// Note: expanded spudec_draw_scale with half size uv planes +// +void spudec_draw_scaled_yuv(void *me, unsigned int dxs, unsigned int dys, + void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)) { spudec_handle_t *spu = (spudec_handle_t *)me; scale_pixel *table_x; scale_pixel *table_y; + unsigned int scalex = 0; + unsigned int scaley = 0; if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) { // check if only forced subtitles are requested if( (spu->forced_subs_only) && !(spu->is_forced_sub) ){ - return; - } + return;} - if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || spu->orig_frame_height == 0 - || (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) { + if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || + spu->orig_frame_height == 0 || + (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) +{ if (spu->image) { - draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height, - spu->image, spu->aimage, spu->stride); - spu->spu_changed = 0; + if (spu->dvdnav_color_spu==DVDNAV_SPU_YUY) { + if (!spu->imageyuy) spudec_create_yuy(spu,0); + if (spu->imageyuy) draw_alpha(spu->start_col, + spu->start_row, + spu->width*2, + spu->heightuv*2, + DEST_PLANES_YUYV, + spu->imageyuy, + spu->aimageyuy, + spu->strideyuy); + } else { + draw_alpha(spu->start_col, + spu->start_row, + spu->width, + spu->height, + DEST_PLANES_Y, + spu->image, + spu->aimage, + spu->stride); + if(spu->dvdnav_color_spu && spu->imageu && spu->aimageuv) + draw_alpha(spu->start_coluv, + spu->start_rowuv, + spu->widthuv, + spu->heightuv, + DEST_PLANES_U, + spu->imageu, + spu->aimageuv, + spu->strideuv); + if(spu->dvdnav_color_spu && spu->imagev && spu->aimageuv) + draw_alpha(spu->start_coluv, + spu->start_rowuv, + spu->widthuv, + spu->heightuv, + DEST_PLANES_V, + spu->imagev, + spu->aimageuv, + spu->strideuv); } + spu->spu_changed = 0; } - else { - if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) { /* Resizing is needed */ + } else { + if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) + { /* Resizing is needed */ /* scaled_x = scalex * x / 0x100 scaled_y = scaley * y / 0x100 order of operations is important because of rounding. */ - unsigned int scalex = 0x100 * dxs / spu->orig_frame_width; - unsigned int scaley = 0x100 * dys / spu->orig_frame_height; + scalex = 0x100 * dxs / spu->orig_frame_width; + scaley = 0x100 * dys / spu->orig_frame_height; + spu->scaled_start_col = spu->start_col * scalex / 0x100; spu->scaled_start_row = spu->start_row * scaley / 0x100; spu->scaled_width = spu->width * scalex / 0x100; spu->scaled_height = spu->height * scaley / 0x100; + spu->scaled_start_coluv = spu->start_coluv * scalex / 0x100; + spu->scaled_start_rowuv = spu->start_rowuv * scaley / 0x100; + spu->scaled_widthuv = spu->widthuv * scalex / 0x100; + spu->scaled_heightuv = spu->heightuv * scaley / 0x100; /* Kludge: draw_alpha needs width multiple of 8 */ spu->scaled_stride = (spu->scaled_width + 7) & ~7; - if (spu->scaled_image_size < spu->scaled_stride * spu->scaled_height) { - if (spu->scaled_image) { + spu->scaled_strideuv = (spu->scaled_widthuv + 7) & ~7; + if (spu->scaled_image_size < spu->scaled_stride * + (spu->scaled_height+2)) +{ + if (spu->scaled_image) + { free(spu->scaled_image); spu->scaled_image_size = 0; } - spu->scaled_image = malloc(2 * spu->scaled_stride * spu->scaled_height); - if (spu->scaled_image) { - spu->scaled_image_size = spu->scaled_stride * spu->scaled_height; + spu->scaled_image = malloc(2 * spu->scaled_stride * + (spu->scaled_height+2)); + if (spu->scaled_image) +{ + memset(spu->scaled_image,0, + 2 * spu->scaled_stride * (spu->scaled_height+2)); + spu->scaled_image_size = spu->scaled_stride * + (spu->scaled_height+2); spu->scaled_aimage = spu->scaled_image + spu->scaled_image_size; } } + if (spu->scaled_image_sizeuv < spu->scaled_strideuv * + (spu->scaled_heightuv+2)) +{ + if (spu->scaled_imageu) + { + free(spu->scaled_imageu); + spu->scaled_image_sizeuv = 0; + } + spu->scaled_imageu = malloc(3 * spu->scaled_strideuv * + (spu->scaled_height+2)); + if (spu->scaled_imageu) + { + memset(spu->scaled_imageu,0,3 * spu->scaled_strideuv * + (spu->scaled_height+2)); + spu->scaled_image_sizeuv = spu->scaled_strideuv * + (spu->scaled_heightuv+2); + spu->scaled_imagev = spu->scaled_imageu + + spu->scaled_image_sizeuv; + spu->scaled_aimageuv = spu->scaled_imagev + + spu->scaled_image_sizeuv; + } + } if (spu->scaled_image) { unsigned int x, y; if (spu->scaled_width <= 1 || spu->scaled_height <= 1) { goto nothing_to_do; } - switch(spu_aamode&15) { + if (spu->scaled_widthuv <= 1 || spu->scaled_heightuv <= 1) { + goto nothing_to_do; + } + switch(spu_aamode&15) + { case 4: sws_spu_image(spu->scaled_image, spu->scaled_aimage, spu->scaled_width, spu->scaled_height, spu->scaled_stride, spu->image, spu->aimage, spu->width, spu->height, spu->stride); + sws_spu_image_uv(spu->scaled_imageu, spu->scaled_imagev, + spu->scaled_aimageuv, spu->scaled_widthuv, + spu->scaled_heightuv, spu->scaled_strideuv, + spu->imageu, spu->imagev, spu->aimageuv, + spu->widthuv, spu->heightuv, spu->strideuv); break; case 3: table_x = calloc(spu->scaled_width, sizeof(scale_pixel)); table_y = calloc(spu->scaled_height, sizeof(scale_pixel)); - if (!table_x || !table_y) { - mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: spudec_draw_scaled: calloc failed\n"); + if (!table_x || !table_y) + { + mp_msg(MSGT_SPUDEC, MSGL_FATAL, + "Fatal: spudec_draw_scaled: calloc failed\n"); } scale_table(0, 0, spu->width - 1, spu->scaled_width - 1, table_x); scale_table(0, 0, spu->height - 1, spu->scaled_height - 1, table_y); @@ -833,17 +1767,52 @@ scale_image(x, y, table_x, table_y, spu); free(table_x); free(table_y); + table_x = calloc(spu->scaled_widthuv, sizeof(scale_pixel)); + table_y = calloc(spu->scaled_heightuv, sizeof(scale_pixel)); + if (!table_x || !table_y) { + mp_msg(MSGT_SPUDEC, MSGL_FATAL, + "Fatal: spudec_draw_scaled: calloc failed\n"); + } + scale_table(0, 0, spu->widthuv - 1, spu->scaled_widthuv - 1, + table_x); + scale_table(0, 0, spu->heightuv - 1, spu->scaled_heightuv - 1, + table_y); + for (y = 0; y < spu->scaled_heightuv; y++) + for (x = 0; x < spu->scaled_widthuv; x++) + scale_image_uv(x, y, table_x, table_y, spu); + free(table_x); + free(table_y); break; case 0: /* no antialiasing */ - for (y = 0; y < spu->scaled_height; ++y) { + for (y = 0; y < spu->scaled_height; ++y) + { int unscaled_y = y * 0x100 / scaley; int strides = spu->stride * unscaled_y; int scaled_strides = spu->scaled_stride * y; - for (x = 0; x < spu->scaled_width; ++x) { + for (x = 0; x < spu->scaled_width; ++x) + { int unscaled_x = x * 0x100 / scalex; - spu->scaled_image[scaled_strides + x] = spu->image[strides + unscaled_x]; - spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x]; + spu->scaled_image[scaled_strides + x] = + spu->image[strides + unscaled_x]; + spu->scaled_aimage[scaled_strides + x] = + spu->aimage[strides + unscaled_x]; + } + } + for (y = 0; y < spu->scaled_heightuv; ++y) + { + int unscaled_y = y * 0x100 / scaley; + int strides = spu->strideuv * unscaled_y; + int scaled_strides = spu->scaled_strideuv * y; + for (x = 0; x < spu->scaled_widthuv; ++x) + { + int unscaled_x = x * 0x100 / scalex; + spu->scaled_imageu[scaled_strides + x] = + spu->imageu[strides + unscaled_x]; + spu->scaled_imagev[scaled_strides + x] = + spu->imagev[strides + unscaled_x]; + spu->scaled_aimageuv[scaled_strides + x] = + spu->aimageuv[strides + unscaled_x]; } } break; @@ -851,13 +1820,18 @@ { /* Intermediate antialiasing. */ for (y = 0; y < spu->scaled_height; ++y) { - const unsigned int unscaled_top = y * spu->orig_frame_height / dys; - unsigned int unscaled_bottom = (y + 1) * spu->orig_frame_height / dys; + const unsigned int unscaled_top = + y * spu->orig_frame_height / dys; + unsigned int unscaled_bottom = + (y + 1) * spu->orig_frame_height / dys; if (unscaled_bottom >= spu->height) unscaled_bottom = spu->height - 1; - for (x = 0; x < spu->scaled_width; ++x) { - const unsigned int unscaled_left = x * spu->orig_frame_width / dxs; - unsigned int unscaled_right = (x + 1) * spu->orig_frame_width / dxs; + for (x = 0; x < spu->scaled_width; ++x) + { + const unsigned int unscaled_left = + x * spu->orig_frame_width / dxs; + unsigned int unscaled_right = + (x + 1) * spu->orig_frame_width / dxs; unsigned int color = 0; unsigned int alpha = 0; unsigned int walkx, walky; @@ -865,7 +1839,8 @@ if (unscaled_right >= spu->width) unscaled_right = spu->width - 1; for (walky = unscaled_top; walky <= unscaled_bottom; ++walky) - for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) { + for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) + { base = walky * spu->stride + walkx; tmp = canon_alpha(spu->aimage[base]); alpha += tmp; @@ -874,7 +1849,8 @@ base = y * spu->scaled_stride + x; spu->scaled_image[base] = alpha ? color / alpha : 0; spu->scaled_aimage[base] = - alpha * (1 + unscaled_bottom - unscaled_top) * (1 + unscaled_right - unscaled_left); + alpha * (1 + unscaled_bottom - unscaled_top) * + (1 + unscaled_right - unscaled_left); /* spu->scaled_aimage[base] = alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */ if (spu->scaled_aimage[base]) { @@ -884,6 +1860,51 @@ } } } + for (y = 0; y < spu->scaled_heightuv; ++y) { + const unsigned int unscaled_top = y * + (spu->orig_frame_height/2) / (dys/2); + unsigned int unscaled_bottom = (y + 1) * + (spu->orig_frame_height/2) / (dys/2); + if (unscaled_bottom >= spu->heightuv) + unscaled_bottom = spu->heightuv - 1; + for (x = 0; x < spu->scaled_widthuv; ++x) { + const unsigned int unscaled_left = x * + (spu->orig_frame_width/2) / (dxs/2); + unsigned int unscaled_right = (x + 1) * + (spu->orig_frame_width/2) / (dxs/2); + unsigned int coloru = 0; + unsigned int colorv = 0; + unsigned int alpha = 0; + unsigned int walkx, walky; + unsigned int base, tmp; + if (unscaled_right >= spu->widthuv) + unscaled_right = spu->widthuv - 1; + for (walky = unscaled_top; walky <= unscaled_bottom; ++walky) + for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) + { + base = walky * spu->strideuv + walkx; + tmp = canon_alpha(spu->aimageuv[base]); + alpha += tmp; + coloru += tmp * spu->imageu[base]; + colorv += tmp * spu->imagev[base]; + } + base = y * spu->scaled_strideuv + x; + spu->scaled_imageu[base] = alpha ? coloru / alpha : 0; + spu->scaled_imagev[base] = alpha ? colorv / alpha : 0; + spu->scaled_aimageuv[base] = + alpha * (1 + unscaled_bottom - unscaled_top) * + (1 + unscaled_right - unscaled_left); + /* spu->scaled_aimage[base] = + alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */ + if (spu->scaled_aimageuv[base]) { + spu->scaled_aimageuv[base] = 256 - spu->scaled_aimageuv[base]; + if (spu->scaled_aimageuv[base] + spu->scaled_imageu[base] > 255) + spu->scaled_imageu[base] = 256 - spu->scaled_aimageuv[base]; + if (spu->scaled_aimageuv[base] + spu->scaled_imagev[base] > 255) + spu->scaled_imagev[base] = 256 - spu->scaled_aimageuv[base]; + } + } + } } break; case 2: @@ -943,7 +1964,8 @@ for (x = 0; x < spu->scaled_width; ++x) { const double unscaled_x = x * inv_scalex; const double unscaled_x_right = unscaled_x + inv_scalex; - const unsigned int left_right_column = FFMIN(unscaled_x_right, unscaled_x + 1.0); + const unsigned int left_right_column = + FFMIN(unscaled_x_right, unscaled_x + 1.0); const double left = left_right_column - unscaled_x; const unsigned int width = unscaled_x_right > left_right_column ? (unsigned int) unscaled_x_right - left_right_column @@ -964,13 +1986,17 @@ */ /* 1: top left part */ base = spu->stride * (unsigned int) unscaled_y; - tmp = left * top * canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]); + tmp = left * top * + canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]); alpha += tmp; color += tmp * spu->image[base + (unsigned int) unscaled_x]; /* 2: top center part */ if (width > 0) { unsigned int walkx; - for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) { + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) + { base = spu->stride * (unsigned int) unscaled_y + walkx; tmp = /* 1.0 * */ top * canon_alpha(spu->aimage[base]); alpha += tmp; @@ -979,7 +2005,1070 @@ } /* 3: top right part */ if (right > 0.0) { - base = spu->stride * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right; + base = spu->stride * (unsigned int) unscaled_y + + (unsigned int) unscaled_x_right; + tmp = right * top * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + /* 4: center left part */ + if (height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) + { + base = spu->stride * walky + (unsigned int) unscaled_x; + tmp = left /* * 1.0 */ * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + } + /* 5: center part */ + if (width > 0 && height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) + { + unsigned int walkx; + base = spu->stride * walky; + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) { + tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimage[base + walkx]); + alpha += tmp; + color += tmp * spu->image[base + walkx]; + } + } + } + /* 6: center right part */ + if (right > 0.0 && height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) + { + base = spu->stride * walky + + (unsigned int) unscaled_x_right; + tmp = right /* * 1.0 */ * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + } + /* 7: bottom left part */ + if (bottom > 0.0) { + base = spu->stride * (unsigned int) unscaled_y_bottom + + (unsigned int) unscaled_x; + tmp = left * bottom * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + /* 8: bottom center part */ + if (width > 0 && bottom > 0.0) { + unsigned int walkx; + base = spu->stride * (unsigned int) unscaled_y_bottom; + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) + { + tmp = /* 1.0 * */ bottom * + canon_alpha(spu->aimage[base + walkx]); + alpha += tmp; + color += tmp * spu->image[base + walkx]; + } + } + /* 9: bottom right part */ + if (right > 0.0 && bottom > 0.0) { + base = spu->stride * (unsigned int) + unscaled_y_bottom + (unsigned int) unscaled_x_right; + tmp = right * bottom * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + /* Finally mix these transparency and brightness information suitably */ + base = spu->scaled_stride * y + x; + spu->scaled_image[base] = alpha > 0 ? color / alpha : 0; + spu->scaled_aimage[base] = alpha * scalex * scaley / 0x10000; + if (spu->scaled_aimage[base]) { + spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255) + spu->scaled_image[base] = 256 - spu->scaled_aimage[base]; + } + } + } + for (y = 0; y < spu->scaled_heightuv; ++y) { + const double unscaled_y = y * inv_scaley; + const double unscaled_y_bottom = unscaled_y + inv_scaley; + const unsigned int top_low_row = + FFMIN(unscaled_y_bottom, unscaled_y + 1.0); + const double top = top_low_row - unscaled_y; + const unsigned int height = unscaled_y_bottom > top_low_row + ? (unsigned int) unscaled_y_bottom - top_low_row + : 0; + const double bottom = unscaled_y_bottom > top_low_row + ? unscaled_y_bottom - floor(unscaled_y_bottom) + : 0.0; + for (x = 0; x < spu->scaled_widthuv; ++x) { + const double unscaled_x = x * inv_scalex; + const double unscaled_x_right = unscaled_x + inv_scalex; + const unsigned int left_right_column = + FFMIN(unscaled_x_right, unscaled_x + 1.0); + const double left = left_right_column - unscaled_x; + const unsigned int width = unscaled_x_right > left_right_column + ? (unsigned int) unscaled_x_right - left_right_column + : 0; + const double right = unscaled_x_right > left_right_column + ? unscaled_x_right - floor(unscaled_x_right) + : 0.0; + double coloru = 0.0; + double colorv = 0.0; + double alpha = 0.0; + double tmp; + unsigned int base; + /* Now use these informations to compute a good alpha, + and lightness. The sum is on each of the 9 + region's surface and alpha and lightness. + + transformed alpha = sum(surface * alpha) / sum(surface) + transformed color = sum(surface * alpha * color) / sum(surface * alpha) + */ + /* 1: top left part */ + base = spu->strideuv * (unsigned int) unscaled_y; + tmp = left * top * + canon_alpha(spu->aimageuv[base + (unsigned int) unscaled_x]); + alpha += tmp; + coloru += tmp * spu->imageu[base + (unsigned int) unscaled_x]; + colorv += tmp * spu->imagev[base + (unsigned int) unscaled_x]; + /* 2: top center part */ + if (width > 0) { + unsigned int walkx; + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) + { + base = spu->strideuv * (unsigned int) unscaled_y + walkx; + tmp = /* 1.0 * */ top * canon_alpha(spu->aimageuv[base]); + alpha += tmp; + coloru += tmp * spu->imageu[base]; + colorv += tmp * spu->imagev[base]; + } + } + /* 3: top right part */ + if (right > 0.0) { + base = spu->strideuv * (unsigned int) unscaled_y + + (unsigned int) unscaled_x_right; + tmp = right * top * canon_alpha(spu->aimageuv[base]); + alpha += tmp; + coloru += tmp * spu->imageu[base]; + colorv += tmp * spu->imagev[base]; + } + /* 4: center left part */ + if (height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) + { + base = spu->strideuv * walky + (unsigned int) unscaled_x; + tmp = left /* * 1.0 */ * canon_alpha(spu->aimageuv[base]); + alpha += tmp; + coloru += tmp * spu->imageu[base]; + colorv += tmp * spu->imagev[base]; + } + } + /* 5: center part */ + if (width > 0 && height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) + { + unsigned int walkx; + base = spu->strideuv * walky; + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) + { + tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimageuv[base + walkx]); + alpha += tmp; + coloru += tmp * spu->imageu[base + walkx]; + colorv += tmp * spu->imagev[base + walkx]; + } + } + } + /* 6: center right part */ + if (right > 0.0 && height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) + { + base = spu->strideuv * walky + + (unsigned int) unscaled_x_right; + tmp = right /* * 1.0 */ * canon_alpha(spu->aimageuv[base]); + alpha += tmp; + coloru += tmp * spu->imageu[base]; + colorv += tmp * spu->imagev[base]; + } + } + /* 7: bottom left part */ + if (bottom > 0.0) { + base = spu->strideuv * (unsigned int) unscaled_y_bottom + + (unsigned int) unscaled_x; + tmp = left * bottom * canon_alpha(spu->aimageuv[base]); + alpha += tmp; + coloru += tmp * spu->imageu[base]; + colorv += tmp * spu->imagev[base]; + } + /* 8: bottom center part */ + if (width > 0 && bottom > 0.0) { + unsigned int walkx; + base = spu->strideuv * (unsigned int) unscaled_y_bottom; + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) { + tmp = /* 1.0 * */ bottom * canon_alpha(spu->aimageuv[base + walkx]); + alpha += tmp; + coloru += tmp * spu->imageu[base + walkx]; + colorv += tmp * spu->imagev[base + walkx]; + } + } + /* 9: bottom right part */ + if (right > 0.0 && bottom > 0.0) { + base = spu->strideuv * (unsigned int) unscaled_y_bottom + + (unsigned int) unscaled_x_right; + tmp = right * bottom * canon_alpha(spu->aimageuv[base]); + alpha += tmp; + coloru += tmp * spu->imageu[base]; + colorv += tmp * spu->imagev[base]; + } + /* Finally mix these transparency and brightness information suitably */ + base = spu->scaled_strideuv * y + x; + spu->scaled_imageu[base] = alpha > 0 ? coloru / alpha : 0; + spu->scaled_imagev[base] = alpha > 0 ? colorv / alpha : 0; + spu->scaled_aimageuv[base] = alpha * scalex * scaley / 0x10000; + if (spu->scaled_aimageuv[base]) { + spu->scaled_aimageuv[base] = 256 - spu->scaled_aimageuv[base]; + if (spu->scaled_aimageuv[base] + spu->scaled_imageu[base] > 255) + spu->scaled_imageu[base] = 256 - spu->scaled_aimageuv[base]; + if (spu->scaled_aimageuv[base] + spu->scaled_imagev[base] > 255) + spu->scaled_imagev[base] = 256 - spu->scaled_aimageuv[base]; + } + } + } + } + } +nothing_to_do: + /* Kludge: draw_alpha needs width multiple of 8. */ + if (spu->scaled_width < spu->scaled_stride) + for (y = 0; y < spu->scaled_height; ++y) { + memset(spu->scaled_aimage + y * spu->scaled_stride + + spu->scaled_width, 0, + spu->scaled_stride - spu->scaled_width); + } + spu->scaled_frame_width = dxs; + spu->scaled_frame_height = dys; + if (spu->scaled_widthuv < spu->scaled_strideuv) + for (y = 0; y < spu->scaled_heightuv; ++y) { + memset(spu->scaled_aimageuv + y * spu->scaled_stride + + spu->scaled_widthuv, 0, + spu->scaled_strideuv - spu->scaled_widthuv); + } + spu->scaled_frame_widthuv = dxs/2; + spu->scaled_frame_heightuv = dys/2; + } + } + if (spu->scaled_image){ + switch (spu_alignment) { + case 0: + spu->scaled_start_row = dys*sub_pos/100; + if (spu->scaled_start_row + spu->scaled_height > dys) + spu->scaled_start_row = dys - spu->scaled_height; + spu->scaled_start_rowuv = (dys/2)*sub_pos/100; + if (spu->scaled_start_rowuv + spu->scaled_heightuv > (dys/2)) + spu->scaled_start_rowuv = (dys/2) - spu->scaled_heightuv; + break; + case 1: + spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height/2; + if (sub_pos < 50) { + if (spu->scaled_start_row < 0) spu->scaled_start_row = 0; + } else { + if (spu->scaled_start_row + spu->scaled_height > dys) + spu->scaled_start_row = dys - spu->scaled_height; + } + spu->scaled_start_rowuv = (dys/2)*sub_pos/100 - spu->scaled_heightuv/2; + if (sub_pos < 50) { + if (spu->scaled_start_rowuv < 0) spu->scaled_start_rowuv = 0; + } else { + if (spu->scaled_start_rowuv + spu->scaled_heightuv > (dys/2)) + spu->scaled_start_rowuv = (dys/2) - spu->scaled_heightuv; + } + break; + case 2: + spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height; + if (spu->scaled_start_row < 0) spu->scaled_start_row = 0; + spu->scaled_start_rowuv = (dys/2)*sub_pos/100 - spu->scaled_heightuv; + if (spu->scaled_start_rowuv < 0) spu->scaled_start_rowuv = 0; + break; + } + if (spu->dvdnav_color_spu==DVDNAV_SPU_YUY) { +// Convert yuv to yuy + if (!spu->imageyuy) spudec_create_yuy(spu,1); +// Draw yuy + if (spu->imageyuy) draw_alpha(spu->scaled_start_col, + spu->scaled_start_row, + spu->scaled_width*2, + spu->scaled_height, + DEST_PLANES_YUYV, + spu->imageyuy, + spu->aimageyuy, + spu->strideyuy); + } else { +// Draw yuv Y, u and v planes + draw_alpha(spu->scaled_start_col, + spu->scaled_start_row, + spu->scaled_width, + spu->scaled_height, + DEST_PLANES_Y, + spu->scaled_image, + spu->scaled_aimage, + spu->scaled_stride); + draw_alpha(spu->scaled_start_coluv, + spu->scaled_start_rowuv, + spu->scaled_widthuv, + spu->scaled_heightuv, + DEST_PLANES_U, + spu->scaled_imageu, + spu->scaled_aimageuv, + spu->scaled_strideuv); + draw_alpha(spu->scaled_start_coluv, + spu->scaled_start_rowuv, + spu->scaled_widthuv, + spu->scaled_heightuv, + DEST_PLANES_V, + spu->scaled_imagev, + spu->scaled_aimageuv, + spu->scaled_strideuv); + } + spu->spu_changed = 0; + } + } + } + else + { + mp_msg(MSGT_SPUDEC,MSGL_DBG2, + "SPU not displayed: start_pts=%d end_pts=%d now_pts=%d\n", + spu->start_pts, spu->end_pts, spu->now_pts); + } +} + +// +// Draw scaled image in RGB and BGR mode +// Note: expanded spudec_draw_scale with Green and Blue planes (Y->Red planes) +// +void spudec_draw_scaled_rgb(void *me, unsigned int dxs, unsigned int dys, + void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)) +{ + spudec_handle_t *spu = (spudec_handle_t *)me; + scale_pixel *table_x; + scale_pixel *table_y; + unsigned int scalex = 0; + unsigned int scaley = 0; + + if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) { + + // check if only forced subtitles are requested + if( (spu->forced_subs_only) && !(spu->is_forced_sub) ){ + return; + } + + if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || + spu->orig_frame_height == 0 || + (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) { + if (spu->image) + { + draw_alpha(spu->start_col, + spu->start_row, + spu->width, + spu->height, + DEST_PLANES_RB, + spu->image, + spu->aimage, + spu->stride); + draw_alpha(spu->start_col, + spu->start_row, + spu->width, + spu->height, + DEST_PLANES_G, + spu->imageu, + spu->aimage, + spu->stride); + draw_alpha(spu->start_col, + spu->start_row, + spu->width, + spu->height, + DEST_PLANES_BR, + spu->imagev, + spu->aimage, + spu->stride); + spu->spu_changed = 0; + } + } + else { + if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) { /* Resizing is needed */ + /* scaled_x = scalex * x / 0x100 + scaled_y = scaley * y / 0x100 + order of operations is important because of rounding. */ + scalex = 0x100 * dxs / spu->orig_frame_width; + scaley = 0x100 * dys / spu->orig_frame_height; + + spu->scaled_start_col = spu->start_col * scalex / 0x100; + spu->scaled_start_row = spu->start_row * scaley / 0x100; + spu->scaled_width = spu->width * scalex / 0x100; + spu->scaled_height = spu->height * scaley / 0x100; + /* Kludge: draw_alpha needs width multiple of 8 */ + spu->scaled_stride = (spu->scaled_width + 7) & ~7; + if (spu->scaled_image_size < spu->scaled_stride * spu->scaled_height) { + if (spu->scaled_image) { + free(spu->scaled_image); + if (spu->scaled_imageu) + free(spu->scaled_imageu); + spu->scaled_image_size = 0; + } + spu->scaled_image = malloc(2 * spu->scaled_stride * spu->scaled_height); + spu->scaled_imageu = malloc(3 * spu->scaled_stride * spu->scaled_height); + if (spu->scaled_image) { + spu->scaled_image_size = spu->scaled_stride * spu->scaled_height; + spu->scaled_aimage = spu->scaled_image + spu->scaled_image_size; + } + if (spu->scaled_imageu) { + spu->scaled_imagev = spu->scaled_imageu + spu->scaled_image_size; + } + } + if (spu->scaled_image) { + unsigned int x, y; + if (spu->scaled_width <= 1 || spu->scaled_height <= 1) { + goto nothing_to_do; + } + switch(spu_aamode&15) { + case 4: + sws_spu_image_rgb(spu->scaled_image,spu->scaled_imageu, + spu->scaled_imagev, spu->scaled_aimage, + spu->scaled_width, spu->scaled_height, spu->scaled_stride, + spu->image, spu->imageu, spu->imagev, spu->aimage, + spu->width, spu->height, spu->stride); + break; + case 3: + table_x = calloc(spu->scaled_width, sizeof(scale_pixel)); + table_y = calloc(spu->scaled_height, sizeof(scale_pixel)); + if (!table_x || !table_y) { + mp_msg(MSGT_SPUDEC, MSGL_FATAL, + "Fatal: spudec_draw_scaled: calloc failed\n"); + } + scale_table(0, 0, spu->width - 1, spu->scaled_width - 1, table_x); + scale_table(0, 0, spu->height - 1, spu->scaled_height - 1, table_y); + for (y = 0; y < spu->scaled_height; y++) + for (x = 0; x < spu->scaled_width; x++) + scale_image_rgb(x, y, table_x, table_y, spu); + free(table_x); + free(table_y); + break; + case 0: + /* no antialiasing */ + for (y = 0; y < spu->scaled_height; ++y) { + int unscaled_y = y * 0x100 / scaley; + int strides = spu->stride * unscaled_y; + int scaled_strides = spu->scaled_stride * y; + for (x = 0; x < spu->scaled_width; ++x) { + int unscaled_x = x * 0x100 / scalex; + spu->scaled_image[scaled_strides + x] = + spu->image[strides + unscaled_x]; + spu->scaled_imageu[scaled_strides + x] = + spu->imageu[strides + unscaled_x]; + spu->scaled_imagev[scaled_strides + x] = + spu->imagev[strides + unscaled_x]; + spu->scaled_aimage[scaled_strides + x] = + spu->aimage[strides + unscaled_x]; + } + } + break; + case 1: + { + /* Intermediate antialiasing. */ + for (y = 0; y < spu->scaled_height; ++y) { + const unsigned int unscaled_top = y * + spu->orig_frame_height / dys; + unsigned int unscaled_bottom = (y + 1) * + spu->orig_frame_height / dys; + if (unscaled_bottom >= spu->height) + unscaled_bottom = spu->height - 1; + for (x = 0; x < spu->scaled_width; ++x) { + const unsigned int unscaled_left = x * + spu->orig_frame_width / dxs; + unsigned int unscaled_right = (x + 1) * + spu->orig_frame_width / dxs; + unsigned int colorr = 0; + unsigned int colorg = 0; + unsigned int colorb = 0; + unsigned int alpha = 0; + unsigned int walkx, walky; + unsigned int base, tmp; + if (unscaled_right >= spu->width) + unscaled_right = spu->width - 1; + for (walky = unscaled_top; walky <= unscaled_bottom; ++walky) + for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) { + base = walky * spu->stride + walkx; + tmp = canon_alpha(spu->aimage[base]); + alpha += tmp; + colorr += tmp * spu->image[base]; + colorg += tmp * spu->imageu[base]; + colorb += tmp * spu->imagev[base]; + } + base = y * spu->scaled_stride + x; + spu->scaled_image[base] = alpha ? colorr / alpha : 0; + spu->scaled_imageu[base] = alpha ? colorg / alpha : 0; + spu->scaled_imagev[base] = alpha ? colorb / alpha : 0; + spu->scaled_aimage[base] = + alpha * (1 + unscaled_bottom - unscaled_top) * (1 + unscaled_right - unscaled_left); + /* spu->scaled_aimage[base] = + alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */ + if (spu->scaled_aimage[base]) { + spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255) + spu->scaled_image[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_imageu[base] > 255) + spu->scaled_imageu[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_imagev[base] > 255) + spu->scaled_imagev[base] = 256 - spu->scaled_aimage[base]; + } + } + } + } + break; + case 2: + { + /* Best antialiasing. Very slow. */ + /* Any pixel (x, y) represents pixels from the original + rectangular region comprised between the columns + unscaled_y and unscaled_y + 0x100 / scaley and the rows + unscaled_x and unscaled_x + 0x100 / scalex + + The original rectangular region that the scaled pixel + represents is cut in 9 rectangular areas like this: + + +---+-----------------+---+ + | 1 | 2 | 3 | + +---+-----------------+---+ + | | | | + | 4 | 5 | 6 | + | | | | + +---+-----------------+---+ + | 7 | 8 | 9 | + +---+-----------------+---+ + + The width of the left column is at most one pixel and + it is never null and its right column is at a pixel + boundary. The height of the top row is at most one + pixel it is never null and its bottom row is at a + pixel boundary. The width and height of region 5 are + integral values. The width of the right column is + what remains and is less than one pixel. The height + of the bottom row is what remains and is less than + one pixel. + + The row above 1, 2, 3 is unscaled_y. The row between + 1, 2, 3 and 4, 5, 6 is top_low_row. The row between 4, + 5, 6 and 7, 8, 9 is (unsigned int)unscaled_y_bottom. + The row beneath 7, 8, 9 is unscaled_y_bottom. + + The column left of 1, 4, 7 is unscaled_x. The column + between 1, 4, 7 and 2, 5, 8 is left_right_column. The + column between 2, 5, 8 and 3, 6, 9 is (unsigned + int)unscaled_x_right. The column right of 3, 6, 9 is + unscaled_x_right. */ + const double inv_scalex = (double) 0x100 / scalex; + const double inv_scaley = (double) 0x100 / scaley; + for (y = 0; y < spu->scaled_height; ++y) { + const double unscaled_y = y * inv_scaley; + const double unscaled_y_bottom = unscaled_y + inv_scaley; + const unsigned int top_low_row = + FFMIN(unscaled_y_bottom, unscaled_y + 1.0); + const double top = top_low_row - unscaled_y; + const unsigned int height = unscaled_y_bottom > top_low_row + ? (unsigned int) unscaled_y_bottom - top_low_row + : 0; + const double bottom = unscaled_y_bottom > top_low_row + ? unscaled_y_bottom - floor(unscaled_y_bottom) + : 0.0; + for (x = 0; x < spu->scaled_width; ++x) { + const double unscaled_x = x * inv_scalex; + const double unscaled_x_right = unscaled_x + inv_scalex; + const unsigned int left_right_column = + FFMIN(unscaled_x_right, unscaled_x + 1.0); + const double left = left_right_column - unscaled_x; + const unsigned int width = unscaled_x_right > left_right_column + ? (unsigned int) unscaled_x_right - left_right_column + : 0; + const double right = unscaled_x_right > left_right_column + ? unscaled_x_right - floor(unscaled_x_right) + : 0.0; + double colorr = 0.0; + double colorg = 0.0; + double colorb = 0.0; + double alpha = 0.0; + double tmp; + unsigned int base; + /* Now use these informations to compute a good alpha, + and lightness. The sum is on each of the 9 + region's surface and alpha and lightness. + + transformed alpha = sum(surface * alpha) / sum(surface) + transformed color = sum(surface * alpha * color) / sum(surface * alpha) + */ + /* 1: top left part */ + base = spu->stride * (unsigned int) unscaled_y; + tmp = left * top * canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]); + alpha += tmp; + colorr += tmp * spu->image[base + (unsigned int) unscaled_x]; + colorg += tmp * spu->imageu[base + (unsigned int) unscaled_x]; + colorb += tmp * spu->imagev[base + (unsigned int) unscaled_x]; + /* 2: top center part */ + if (width > 0) { + unsigned int walkx; + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) { + base = spu->stride * (unsigned int) unscaled_y + walkx; + tmp = /* 1.0 * */ top * canon_alpha(spu->aimage[base]); + alpha += tmp; + colorr += tmp * spu->image[base]; + colorg += tmp * spu->imageu[base]; + colorb += tmp * spu->imagev[base]; + } + } + /* 3: top right part */ + if (right > 0.0) { + base = spu->stride * (unsigned int) unscaled_y + + (unsigned int) unscaled_x_right; + tmp = right * top * canon_alpha(spu->aimage[base]); + alpha += tmp; + colorr += tmp * spu->image[base]; + colorg += tmp * spu->imageu[base]; + colorb += tmp * spu->imagev[base]; + } + /* 4: center left part */ + if (height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) { + base = spu->stride * walky + (unsigned int) unscaled_x; + tmp = left /* * 1.0 */ * canon_alpha(spu->aimage[base]); + alpha += tmp; + colorr += tmp * spu->image[base]; + colorg += tmp * spu->imageu[base]; + colorb += tmp * spu->imagev[base]; + } + } + /* 5: center part */ + if (width > 0 && height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) { + unsigned int walkx; + base = spu->stride * walky; + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) { + tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimage[base + walkx]); + alpha += tmp; + colorr += tmp * spu->image[base + walkx]; + colorg += tmp * spu->imageu[base + walkx]; + colorb += tmp * spu->imagev[base + walkx]; + } + } + } + /* 6: center right part */ + if (right > 0.0 && height > 0) { + unsigned int walky; + for (walky = top_low_row; + walky < (unsigned int) unscaled_y_bottom; + ++walky) { + base = spu->stride * walky + (unsigned int) unscaled_x_right; + tmp = right /* * 1.0 */ * canon_alpha(spu->aimage[base]); + alpha += tmp; + colorr += tmp * spu->image[base]; + colorg += tmp * spu->imageu[base]; + colorb += tmp * spu->imagev[base]; + } + } + /* 7: bottom left part */ + if (bottom > 0.0) { + base = spu->stride * (unsigned int) unscaled_y_bottom + + (unsigned int) unscaled_x; + tmp = left * bottom * canon_alpha(spu->aimage[base]); + alpha += tmp; + colorr += tmp * spu->image[base]; + colorg += tmp * spu->imageu[base]; + colorb += tmp * spu->imagev[base]; + } + /* 8: bottom center part */ + if (width > 0 && bottom > 0.0) { + unsigned int walkx; + base = spu->stride * (unsigned int) unscaled_y_bottom; + for (walkx = left_right_column; + walkx < (unsigned int) unscaled_x_right; + ++walkx) { + tmp = /* 1.0 * */ bottom * canon_alpha(spu->aimage[base + walkx]); + alpha += tmp; + colorr += tmp * spu->image[base + walkx]; + colorg += tmp * spu->imageu[base + walkx]; + colorb += tmp * spu->imagev[base + walkx]; + } + } + /* 9: bottom right part */ + if (right > 0.0 && bottom > 0.0) { + base = spu->stride * (unsigned int) unscaled_y_bottom + + (unsigned int) unscaled_x_right; + tmp = right * bottom * canon_alpha(spu->aimage[base]); + alpha += tmp; + colorr += tmp * spu->image[base]; + colorg += tmp * spu->imageu[base]; + colorb += tmp * spu->imagev[base]; + } + /* Finally mix these transparency and brightness information suitably */ + base = spu->scaled_stride * y + x; + spu->scaled_image[base] = alpha > 0 ? colorr / alpha : 0; + spu->scaled_imageu[base] = alpha > 0 ? colorg / alpha : 0; + spu->scaled_imagev[base] = alpha > 0 ? colorb / alpha : 0; + spu->scaled_aimage[base] = alpha * scalex * scaley / 0x10000; + if (spu->scaled_aimage[base]) { + spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255) + spu->scaled_image[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_imageu[base] > 255) + spu->scaled_imageu[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_imagev[base] > 255) + spu->scaled_imagev[base] = 256 - spu->scaled_aimage[base]; + } + } + } + } + } +nothing_to_do: + /* Kludge: draw_alpha needs width multiple of 8. */ + if (spu->scaled_width < spu->scaled_stride) + for (y = 0; y < spu->scaled_height; ++y) { + memset(spu->scaled_aimage + y * spu->scaled_stride + + spu->scaled_width, 0, + spu->scaled_stride - spu->scaled_width); + } + spu->scaled_frame_width = dxs; + spu->scaled_frame_height = dys; + } + } + if (spu->scaled_image){ + switch (spu_alignment) { + case 0: + spu->scaled_start_row = dys*sub_pos/100; + if (spu->scaled_start_row + spu->scaled_height > dys) + spu->scaled_start_row = dys - spu->scaled_height; + break; + case 1: + spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height/2; + if (sub_pos < 50) { + if (spu->scaled_start_row < 0) spu->scaled_start_row = 0; + } else { + if (spu->scaled_start_row + spu->scaled_height > dys) + spu->scaled_start_row = dys - spu->scaled_height; + } + break; + case 2: + spu->scaled_start_row = dys*sub_pos/100 - spu->scaled_height; + if (spu->scaled_start_row < 0) spu->scaled_start_row = 0; + break; + } +// Draw planes: Red in RGB mode or Blue in BGR mode + draw_alpha(spu->scaled_start_col, + spu->scaled_start_row, + spu->scaled_width, + spu->scaled_height, + DEST_PLANES_RB, + spu->scaled_image, + spu->scaled_aimage, + spu->scaled_stride); +// Draw Green planes in RGB and BGR mode + draw_alpha(spu->scaled_start_col, + spu->scaled_start_row, + spu->scaled_width, + spu->scaled_height, + DEST_PLANES_G, + spu->scaled_imageu, + spu->scaled_aimage, + spu->scaled_stride); +// Draw planes: Blue in RGB mode or Red in BGR mode + draw_alpha(spu->scaled_start_col, + spu->scaled_start_row, + spu->scaled_width, + spu->scaled_height, + DEST_PLANES_BR, + spu->scaled_imagev, + spu->scaled_aimage, + spu->scaled_stride); + spu->spu_changed = 0; + } + } + } + else + { + mp_msg(MSGT_SPUDEC,MSGL_DBG2, + "SPU not displayed: start_pts=%d end_pts=%d now_pts=%d\n", + spu->start_pts, spu->end_pts, spu->now_pts); + } +} + +void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)) +{ + spudec_handle_t *spu = (spudec_handle_t *)me; + scale_pixel *table_x; + scale_pixel *table_y; + if (spu->dvdnav_menu) { + switch (spu->dvdnav_color_spu) + { +// +// Draw scaled image in YUV and YUY mode +// + case DVDNAV_SPU_YUV: + case DVDNAV_SPU_YUY: + spudec_draw_scaled_yuv(me,dxs,dys,draw_alpha); + return; + break; +// +// Draw scaled image in RGB and BGR mode +// + case DVDNAV_SPU_RGB: + case DVDNAV_SPU_BGR: + spudec_draw_scaled_rgb(me,dxs,dys,draw_alpha); + return; + break; + } + } +// +// Draw scaled image in Y mode (default) +// + if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) { + + // check if only forced subtitles are requested + if( (spu->forced_subs_only) && !(spu->is_forced_sub) ){ + return; + } + + if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || spu->orig_frame_height == 0 + || (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) { + if (spu->image) + { + draw_alpha(spu->start_col, spu->start_row, spu->width, spu->height,DEST_PLANES_Y, + spu->image, spu->aimage, spu->stride); + spu->spu_changed = 0; + } + } + else { + if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) { /* Resizing is needed */ + /* scaled_x = scalex * x / 0x100 + scaled_y = scaley * y / 0x100 + order of operations is important because of rounding. */ + unsigned int scalex = 0x100 * dxs / spu->orig_frame_width; + unsigned int scaley = 0x100 * dys / spu->orig_frame_height; + spu->scaled_start_col = spu->start_col * scalex / 0x100; + spu->scaled_start_row = spu->start_row * scaley / 0x100; + spu->scaled_width = spu->width * scalex / 0x100; + spu->scaled_height = spu->height * scaley / 0x100; + /* Kludge: draw_alpha needs width multiple of 8 */ + spu->scaled_stride = (spu->scaled_width + 7) & ~7; + if (spu->scaled_image_size < spu->scaled_stride * spu->scaled_height) { + if (spu->scaled_image) { + free(spu->scaled_image); + spu->scaled_image_size = 0; + } + spu->scaled_image = malloc(2 * spu->scaled_stride * spu->scaled_height); + if (spu->scaled_image) { + spu->scaled_image_size = spu->scaled_stride * spu->scaled_height; + spu->scaled_aimage = spu->scaled_image + spu->scaled_image_size; + } + } + if (spu->scaled_image) { + unsigned int x, y; + if (spu->scaled_width <= 1 || spu->scaled_height <= 1) { + goto nothing_to_do; + } + switch(spu_aamode&15) { + case 4: + sws_spu_image(spu->scaled_image, spu->scaled_aimage, + spu->scaled_width, spu->scaled_height, spu->scaled_stride, + spu->image, spu->aimage, spu->width, spu->height, spu->stride); + break; + case 3: + table_x = calloc(spu->scaled_width, sizeof(scale_pixel)); + table_y = calloc(spu->scaled_height, sizeof(scale_pixel)); + if (!table_x || !table_y) { + mp_msg(MSGT_SPUDEC, MSGL_FATAL, "Fatal: spudec_draw_scaled: calloc failed\n"); + } + scale_table(0, 0, spu->width - 1, spu->scaled_width - 1, table_x); + scale_table(0, 0, spu->height - 1, spu->scaled_height - 1, table_y); + for (y = 0; y < spu->scaled_height; y++) + for (x = 0; x < spu->scaled_width; x++) + scale_image(x, y, table_x, table_y, spu); + free(table_x); + free(table_y); + break; + case 0: + /* no antialiasing */ + for (y = 0; y < spu->scaled_height; ++y) { + int unscaled_y = y * 0x100 / scaley; + int strides = spu->stride * unscaled_y; + int scaled_strides = spu->scaled_stride * y; + for (x = 0; x < spu->scaled_width; ++x) { + int unscaled_x = x * 0x100 / scalex; + spu->scaled_image[scaled_strides + x] = spu->image[strides + unscaled_x]; + spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x]; + } + } + break; + case 1: + { + /* Intermediate antialiasing. */ + for (y = 0; y < spu->scaled_height; ++y) { + const unsigned int unscaled_top = y * spu->orig_frame_height / dys; + unsigned int unscaled_bottom = (y + 1) * spu->orig_frame_height / dys; + if (unscaled_bottom >= spu->height) + unscaled_bottom = spu->height - 1; + for (x = 0; x < spu->scaled_width; ++x) { + const unsigned int unscaled_left = x * spu->orig_frame_width / dxs; + unsigned int unscaled_right = (x + 1) * spu->orig_frame_width / dxs; + unsigned int color = 0; + unsigned int alpha = 0; + unsigned int walkx, walky; + unsigned int base, tmp; + if (unscaled_right >= spu->width) + unscaled_right = spu->width - 1; + for (walky = unscaled_top; walky <= unscaled_bottom; ++walky) + for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) { + base = walky * spu->stride + walkx; + tmp = canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + base = y * spu->scaled_stride + x; + spu->scaled_image[base] = alpha ? color / alpha : 0; + spu->scaled_aimage[base] = + alpha * (1 + unscaled_bottom - unscaled_top) * (1 + unscaled_right - unscaled_left); + /* spu->scaled_aimage[base] = + alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */ + if (spu->scaled_aimage[base]) { + spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255) + spu->scaled_image[base] = 256 - spu->scaled_aimage[base]; + } + } + } + } + break; + case 2: + { + /* Best antialiasing. Very slow. */ + /* Any pixel (x, y) represents pixels from the original + rectangular region comprised between the columns + unscaled_y and unscaled_y + 0x100 / scaley and the rows + unscaled_x and unscaled_x + 0x100 / scalex + + The original rectangular region that the scaled pixel + represents is cut in 9 rectangular areas like this: + + +---+-----------------+---+ + | 1 | 2 | 3 | + +---+-----------------+---+ + | | | | + | 4 | 5 | 6 | + | | | | + +---+-----------------+---+ + | 7 | 8 | 9 | + +---+-----------------+---+ + + The width of the left column is at most one pixel and + it is never null and its right column is at a pixel + boundary. The height of the top row is at most one + pixel it is never null and its bottom row is at a + pixel boundary. The width and height of region 5 are + integral values. The width of the right column is + what remains and is less than one pixel. The height + of the bottom row is what remains and is less than + one pixel. + + The row above 1, 2, 3 is unscaled_y. The row between + 1, 2, 3 and 4, 5, 6 is top_low_row. The row between 4, + 5, 6 and 7, 8, 9 is (unsigned int)unscaled_y_bottom. + The row beneath 7, 8, 9 is unscaled_y_bottom. + + The column left of 1, 4, 7 is unscaled_x. The column + between 1, 4, 7 and 2, 5, 8 is left_right_column. The + column between 2, 5, 8 and 3, 6, 9 is (unsigned + int)unscaled_x_right. The column right of 3, 6, 9 is + unscaled_x_right. */ + const double inv_scalex = (double) 0x100 / scalex; + const double inv_scaley = (double) 0x100 / scaley; + for (y = 0; y < spu->scaled_height; ++y) { + const double unscaled_y = y * inv_scaley; + const double unscaled_y_bottom = unscaled_y + inv_scaley; + const unsigned int top_low_row = FFMIN(unscaled_y_bottom, unscaled_y + 1.0); + const double top = top_low_row - unscaled_y; + const unsigned int height = unscaled_y_bottom > top_low_row + ? (unsigned int) unscaled_y_bottom - top_low_row + : 0; + const double bottom = unscaled_y_bottom > top_low_row + ? unscaled_y_bottom - floor(unscaled_y_bottom) + : 0.0; + for (x = 0; x < spu->scaled_width; ++x) { + const double unscaled_x = x * inv_scalex; + const double unscaled_x_right = unscaled_x + inv_scalex; + const unsigned int left_right_column = FFMIN(unscaled_x_right, unscaled_x + 1.0); + const double left = left_right_column - unscaled_x; + const unsigned int width = unscaled_x_right > left_right_column + ? (unsigned int) unscaled_x_right - left_right_column + : 0; + const double right = unscaled_x_right > left_right_column + ? unscaled_x_right - floor(unscaled_x_right) + : 0.0; + double color = 0.0; + double alpha = 0.0; + double tmp; + unsigned int base; + /* Now use these informations to compute a good alpha, + and lightness. The sum is on each of the 9 + region's surface and alpha and lightness. + + transformed alpha = sum(surface * alpha) / sum(surface) + transformed color = sum(surface * alpha * color) / sum(surface * alpha) + */ + /* 1: top left part */ + base = spu->stride * (unsigned int) unscaled_y; + tmp = left * top * canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]); + alpha += tmp; + color += tmp * spu->image[base + (unsigned int) unscaled_x]; + /* 2: top center part */ + if (width > 0) { + unsigned int walkx; + for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) { + base = spu->stride * (unsigned int) unscaled_y + walkx; + tmp = /* 1.0 * */ top * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + } + /* 3: top right part */ + if (right > 0.0) { + base = spu->stride * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right; tmp = right * top * canon_alpha(spu->aimage[base]); alpha += tmp; color += tmp * spu->image[base]; @@ -1082,7 +3171,7 @@ break; } draw_alpha(spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height, - spu->scaled_image, spu->scaled_aimage, spu->scaled_stride); + DEST_PLANES_Y,spu->scaled_image, spu->scaled_aimage, spu->scaled_stride); spu->spu_changed = 0; } } @@ -1166,6 +3255,21 @@ free(spu->scaled_image); if (spu->image) free(spu->image); + if (spu->dvdnav_image) // Free dvdnav SPU image + free(spu->dvdnav_image); + if (spu->dvdnav_aimage) // Free dvdnav SPU image alpha + free(spu->dvdnav_aimage); + + if (spu->imageu) // Free dvdnav SPU uv or GB image + free(spu->imageu); + if (spu->imageyuy) // Free dvdnav SPU YUY image + free(spu->imageyuy); + spu->imageyuy=NULL; + if (spu->scaled_imageu) // Free dvdnav SPU uv or GB alpha + free(spu->scaled_imageu); + + if (spu->last_packet) {spudec_free_packet(spu->last_packet); spu->last_packet=NULL;} + spu->dvdnav_allocated = 0; free(spu); } } --- spudec.h 2007-10-07 21:49:33.000000000 +0200 +++ spudec.h 2007-10-08 21:10:30.000000000 +0200 @@ -5,8 +5,38 @@ void spudec_heartbeat(void *this, unsigned int pts100); void spudec_assemble(void *this, unsigned char *packet, unsigned int len, unsigned int pts100); -void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); -void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); +void spudec_draw(void *this, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)); +void spudec_draw_scaled(void *this, unsigned int dxs, unsigned int dys, void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)); + +#define DVDNAV_SPU_YUV 1 +#define DVDNAV_SPU_RGB 2 +#define DVDNAV_SPU_BGR 3 +#define DVDNAV_SPU_YUY 4 + +// Convert yuv color to rgb color +void spu_yuv_to_rgb(unsigned int y,unsigned int u,unsigned int v, + unsigned int *r,unsigned int *g,unsigned int *b); +// Enable/disable dvdmenu mode, and set color mode +// cflg = 0: Y SPU (default) +// cflg = 1: YUV SPU +// cflg = 2: RGB SPU +// cflg = 3: BGR SPU +// cflg = 4: YUY SPU +void spudec_dvdnav_mode(void *this, int mode, int cflg); +// Set dvd menu button draw area and palette +void spudec_dvdnav_area(void *this, uint16_t sx, uint16_t sy, + uint16_t ex, uint16_t ey, uint32_t palette); +// Set dvd menu button palette +void spudec_dvdnav_palette(void *this, uint32_t palette); +// Draw scaled image in YUV and YUY mode +void spudec_draw_scaled_yuv(void *me, unsigned int dxs, unsigned int dys, + void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)); +// Draw scaled image in RGB and BGR mode +void spudec_draw_scaled_rgb(void *me, unsigned int dxs, unsigned int dys, + void (*draw_alpha)(int x0,int y0, int w,int h, int dp, unsigned char* src, unsigned char *srca, int stride)); +// Convert Yuv image to YuY image +void spudec_create_yuy(void *this, int spu_scaled); + void spudec_update_palette(void *this, unsigned int *palette); void *spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height); void *spudec_new_scaled_vobsub(unsigned int *palette, unsigned int *cuspal, unsigned int custom, unsigned int frame_width, unsigned int frame_height); --- mp_core.h 2007-10-07 21:49:33.000000000 +0200 +++ mp_core.h 2007-10-08 20:48:06.000000000 +0200 @@ -99,6 +99,14 @@ #endif int was_paused; +#ifdef USE_DVDNAV + void *smpi; // store last decoded video image + void *last_buffer; // store last read video frame + void *last_start; // video read buffer ptr + int last_in_size; // last read size + int libmpeg2_count; // libmpeg2 repeat decode counter + int dup_frame; // duplicate frame mode +#endif } MPContext; --- stream/stream_dvdnav.c 2007-10-07 21:49:26.000000000 +0200 +++ stream/stream_dvdnav.c 2008-01-13 00:18:58.000000000 +0100 @@ -10,6 +10,7 @@ #include "stream.h" #include "libmpdemux/demuxer.h" #include "stream_dvdnav.h" +#include "stream_dvd_common.h" #include "libvo/video_out.h" #include "libavutil/common.h" #include "spudec.h" @@ -18,16 +19,13 @@ #include "help_mp.h" extern char *dvd_device; -extern int dvd_chapter; -extern int dvd_last_chapter; -extern int dvd_angle; extern char *audio_lang, *dvdsub_lang; static struct stream_priv_s { int track; char* device; } stream_priv_dflts = { - 0, + -1, NULL }; @@ -114,6 +112,8 @@ dvdnav_get_current_highlight (priv->dvdnav, &(hlev->buttonN)); hlev->display = display_mode; /* show */ + if (hlev->buttonN > pnavpci->hli.hl_gi.btn_ns && pnavpci->hli.hl_gi.btn_ns > 0) + hlev->buttonN = pnavpci->hli.hl_gi.btn_ns; if (hlev->buttonN > 0 && pnavpci->hli.hl_gi.btn_ns > 0 && hlev->display) { for (btnum = 0; btnum < pnavpci->hli.hl_gi.btn_ns; btnum++) { btni_t *btni = &(pnavpci->hli.btnit[btnum]); @@ -138,6 +138,8 @@ static int dvdnav_stream_read(dvdnav_priv_t * priv, unsigned char *buf, int *len) { int event = DVDNAV_NOP; + uint32_t nextstill; + dvdnav_still_event_t *still_event; if (!len) return -1; *len=-1; @@ -154,7 +156,18 @@ case DVDNAV_NAV_PACKET: return event; case DVDNAV_STILL_FRAME: { - dvdnav_still_skip(priv->dvdnav); // don't let dvdnav stall on this image + still_event = (dvdnav_still_event_t*)(buf); + priv->still_length=still_event->length; + // set still frame duration + if (priv->still_length!=255) + priv->duration = priv->still_length * 1000; + else + priv->duration = 0; + // FIXME: TIME HACK + if (priv->still_length<=1) { + pci_t* pnavpci = dvdnav_get_current_nav_pci( priv->dvdnav ); + priv->duration = mp_dvdtimetomsec(&(pnavpci->pci_gi.e_eltm)); + } break; } case DVDNAV_HIGHLIGHT: { @@ -162,20 +175,54 @@ break; } case DVDNAV_CELL_CHANGE: { + priv->status &= ~NAV_FLAG_WAIT_SKIP; // clear + priv->status |= NAV_FLAG_STREAM_CHANGE; // changed stream + priv->status |= NAV_FLAG_SPU_CHANGE; // changed SPU dvdnav_cell_change_event_t *ev = (dvdnav_cell_change_event_t*)buf; if(ev->pgc_length) priv->duration = ev->pgc_length/90; + if (dvdnav_is_domain_vts(priv->dvdnav)) // set vts domain + priv->status |= NAV_FLAG_VTS_DOMAIN; + else + priv->status &= ~NAV_FLAG_VTS_DOMAIN; + + nextstill = dvdnav_get_next_still_flag(priv->dvdnav); + if(nextstill==0xff) { + priv->duration = 0; + priv->still_length = nextstill; + } else if(nextstill) { + priv->duration = nextstill * 1000; + priv->still_length = nextstill; + } + dvdnav_get_highlight (priv, 1); break; } case DVDNAV_SPU_CLUT_CHANGE: { memcpy(priv->spu_clut, buf, 16*sizeof(unsigned int)); - priv->spu_set = 1; + priv->status |= NAV_FLAG_SPU_SET; // spu clut valid break; } - case DVDNAV_WAIT: + case DVDNAV_WAIT: { + // if don't open demuxer then suspend read in dvdnav stream + // else wait skip + if ((priv->status & NAV_FLAG_WAIT_SKIP) && + !(priv->status & NAV_FLAG_WAIT)) dvdnav_wait_skip(priv->dvdnav); + else + priv->status |= NAV_FLAG_WAIT; break; } + case DVDNAV_VTS_CHANGE: { + priv->status &= ~NAV_FLAG_WAIT_SKIP; + priv->status |= NAV_FLAG_STREAM_CHANGE; // changed stream + break; + } + case DVDNAV_SPU_STREAM_CHANGE: { + priv->status |= NAV_FLAG_STREAM_CHANGE; // changed stream + priv->status |= NAV_FLAG_SPU_CHANGE; // changed SPU + break; + } + } *len=0; } @@ -231,6 +278,11 @@ int event; dvdnav_priv_t* priv=s->priv; + // is suspend read + if (priv->status & NAV_FLAG_WAIT_READ) { + len=-1; + return len; + } len=0; if(!s->end_pos) update_title_len(s); @@ -243,16 +295,29 @@ return 0; } switch (event) { - case DVDNAV_STOP: + case DVDNAV_STOP: { + priv->status |= NAV_FLAG_EOFSTREAM; // really eof + return len; + } case DVDNAV_BLOCK_OK: case DVDNAV_NAV_PACKET: return len; + case DVDNAV_STILL_FRAME: return len; + case DVDNAV_WAIT: { // wait active + if (priv->status & NAV_FLAG_WAIT) return len; + break; + } case DVDNAV_VTS_CHANGE: { int tit = 0, part = 0; dvdnav_vts_change_event_t *vts_event = (dvdnav_vts_change_event_t *)s->buffer; mp_msg(MSGT_CPLAYER,MSGL_INFO, "DVDNAV, switched to title: %d\r\n", vts_event->new_vtsN); + priv->status |= NAV_FLAG_CELL_CHANGE; // changed stream + priv->status &= ~NAV_FLAG_WAIT_SKIP; // clear + priv->status &= ~NAV_FLAG_WAIT; s->end_pos = 0; update_title_len(s); + if (priv->status & NAV_FLAG_WAIT_READ_AUTO) + priv->status |= NAV_FLAG_WAIT_READ; // skip read from dvdnav stream if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK) { mp_msg(MSGT_CPLAYER,MSGL_V, "\r\nDVDNAV, NEW TITLE %d\r\n", tit); dvdnav_get_highlight (priv, 0); @@ -262,6 +327,11 @@ break; } case DVDNAV_CELL_CHANGE: { + priv->status |= NAV_FLAG_CELL_CHANGE; // changed stream + priv->status &= ~NAV_FLAG_WAIT_SKIP; // clear + priv->status &= ~NAV_FLAG_WAIT; + if (priv->status & NAV_FLAG_WAIT_READ_AUTO) + priv->status |= NAV_FLAG_WAIT_READ; // skip read from dvdnav stream if(priv->title > 0 && dvd_last_chapter > 0) { int tit=0, part=0; if(dvdnav_current_title_info(priv->dvdnav, &tit, &part) == DVDNAV_STATUS_OK && part > dvd_last_chapter) @@ -311,7 +381,7 @@ } case STREAM_CTRL_GET_TIME_LENGTH: { - if(priv->duration) + if (priv->duration || priv->still_length) { *((double *)arg) = (double)priv->duration / 1000.0; return 1; @@ -374,10 +444,8 @@ } if(dvd_chapter > 0) dvdnav_part_play(priv->dvdnav, p->track, dvd_chapter); - } else if(p->track == -1) - dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root); - else { - mp_msg(MSGT_OPEN,MSGL_INFO,"dvdnav_stream, you didn't specify a track number (as in dvdnav://1), playing whole disc\n"); + } else if (p->track == 0) { + if(dvdnav_menu_call(priv->dvdnav, DVD_MENU_Root) != DVDNAV_STATUS_OK) dvdnav_menu_call(priv->dvdnav, DVD_MENU_Title); } if(dvd_angle > 1) @@ -394,7 +462,7 @@ *file_format = DEMUXER_TYPE_MPEG_PS; update_title_len(stream); - if(!stream->pos) + if(!stream->pos && p->track>0) mp_msg(MSGT_OPEN,MSGL_ERR, "INIT ERROR: couldn't get init pos %s\r\n", dvdnav_err_to_string(priv->dvdnav)); mp_msg(MSGT_OPEN,MSGL_INFO, "Remember to disable MPlayer's cache when playing dvdnav:// streams (adding -nocache to your command line)\r\n"); @@ -403,15 +471,14 @@ } -int mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) { +void mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button) { dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; dvdnav_t *nav = priv->dvdnav; dvdnav_status_t status=DVDNAV_STATUS_ERR; pci_t *pci = dvdnav_get_current_nav_pci(nav); - int reset = 0; if(cmd != MP_CMD_DVDNAV_SELECT && !pci) - return 0; + return; switch(cmd) { case MP_CMD_DVDNAV_UP: @@ -428,26 +495,22 @@ break; case MP_CMD_DVDNAV_MENU: status = dvdnav_menu_call(nav,DVD_MENU_Root); - reset = 1; break; case MP_CMD_DVDNAV_PREVMENU: { int title=0, part=0; dvdnav_current_title_info(nav, &title, &part); if(title) { - if(dvdnav_menu_call(nav, DVD_MENU_Part) == DVDNAV_STATUS_OK - || dvdnav_menu_call(nav, DVD_MENU_Title) == DVDNAV_STATUS_OK) { - reset = 1; + if((status=dvdnav_menu_call(nav, DVD_MENU_Part)) == DVDNAV_STATUS_OK) + break; + if((status=dvdnav_menu_call(nav, DVD_MENU_Title)) == DVDNAV_STATUS_OK) break; } - } - if(dvdnav_menu_call(nav, DVD_MENU_Root) == DVDNAV_STATUS_OK) - reset = 1; + status=dvdnav_menu_call(nav, DVD_MENU_Root); } break; case MP_CMD_DVDNAV_SELECT: status = dvdnav_button_activate(nav, pci); - if(status == DVDNAV_STATUS_OK) reset = 1; break; case MP_CMD_DVDNAV_MOUSECLICK: /* @@ -458,7 +521,6 @@ This last call always works well */ status = dvdnav_mouse_activate(nav, pci, priv->mousex, priv->mousey); - if(status == DVDNAV_STATUS_OK) reset = 1; break; default: mp_msg(MSGT_CPLAYER, MSGL_V, "Unknown DVDNAV cmd %d\n", cmd); @@ -468,7 +530,7 @@ if(status == DVDNAV_STATUS_OK) dvdnav_get_current_highlight(nav, button); - return reset; + return; } void mp_dvdnav_update_mouse_pos(stream_t *stream, int32_t x, int32_t y, int* button) { @@ -530,6 +592,41 @@ } /** + * \brief dvdnav_aid_from_audio_num() returns the audio id corresponding to the logical number + * \param stream: - stream pointer + * \param audio_num: logical number + * \return -1 on error, current subtitle id if successful + */ +int dvdnav_aid_from_audio_num(stream_t *stream, int audio_num) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + int k; + uint8_t format, lg; + +#ifdef DVDNAV_FORMAT_AC3 + //this macro is defined only in libdvdnav-cvs + for(k=0; k<32; k++) { + lg = dvdnav_get_audio_logical_stream(priv->dvdnav, k); + if(lg == 0xff) continue; + if(lg != audio_num) continue; + format = dvdnav_audio_stream_format(priv->dvdnav, lg); + switch(format) { + case DVDNAV_FORMAT_AC3: + return k+128; + case DVDNAV_FORMAT_DTS: + return k+136; + case DVDNAV_FORMAT_LPCM: + return k+160; + case DVDNAV_FORMAT_MPEGAUDIO: + return k; + default: + return -1; + } + } +#endif + return -1; +} + +/** * \brief dvdnav_lang_from_aid() assigns to buf the language corresponding to audio id 'aid' * \param stream: - stream pointer * \param sid: physical subtitle id @@ -611,6 +708,7 @@ dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; uint8_t lg, k, n=0; + if (!(priv->status & NAV_FLAG_VTS_DOMAIN)) return 0; for(k=0; k<32; k++) { lg = dvdnav_get_spu_logical_stream(priv->dvdnav, k); if(lg == 0xff) continue; @@ -626,8 +724,8 @@ */ unsigned int *mp_dvdnav_get_spu_clut(stream_t *stream) { dvdnav_priv_t *priv=(dvdnav_priv_t*)stream->priv; - if(!priv->spu_set) return NULL; - return priv->spu_clut; + if (!(priv->status & NAV_FLAG_SPU_SET)) return NULL; // invalid spu clut + return priv->spu_clut; // valid spu clut } /** @@ -639,10 +737,252 @@ dvdnav_priv_t *priv = (dvdnav_priv_t *) stream->priv; dvdnav_highlight_event_t hlev = priv->hlev; + dvdnav_get_highlight (priv, 1); hl->sx = hlev.sx; hl->sy = hlev.sy; hl->ex = hlev.ex; hl->ey = hlev.ey; + hl->palette = hlev.palette; +} + +/** + * \brief mp_dvdnav_isreallyeof() get really EOF flag + * \param stream: - stream pointer + * \return 1 on really eof + */ +int mp_dvdnav_isreallyeof(stream_t *stream) { + return ((dvdnav_priv_t*) stream->priv )->status & + NAV_FLAG_EOFSTREAM; +} + +/** + * \brief mp_dvdnav_still_skip() call still skip + * \param stream: - stream pointer + * \return 0 on success + */ +int mp_dvdnav_still_skip(stream_t *stream) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + if (priv->still_length==0xff) return 1; + dvdnav_still_skip(priv->dvdnav); + return 0; +} + +/** + * \brief mp_dvdnav_wait_skip() call wait skip + * \param stream: - stream pointer + * \return 0 on success + */ +int mp_dvdnav_wait_skip(stream_t *stream) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + if (!(priv->status & NAV_FLAG_WAIT)) return 1; + priv->status &= ~NAV_FLAG_WAIT; + dvdnav_wait_skip(priv->dvdnav); + return 0; +} + +/** + * \brief mp_dvdnav_iscellchage() get cell change flag and clear this flag + * \param stream: - stream pointer + * \param clear : - if true then clear cell change flag + * \return 1 if cell change + */ +int mp_dvdnav_iscellchage(stream_t *stream, int clear) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + if (!(priv->status & NAV_FLAG_CELL_CHANGE)) return 0; + if (clear) priv->status &= ~NAV_FLAG_CELL_CHANGE; + return 1; +} + +/** + * \brief mp_dvdnav_wait_read() set wait mode + * \param stream : - stream pointer + * \param mode : - if true then suspend block read + * \param automode: - if true then vts or cell change set wait mode + */ +void mp_dvdnav_wait_read(stream_t *stream, int mode, int automode) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + if (mode==0) priv->status &= ~NAV_FLAG_WAIT_READ; + if (mode>0) priv->status |= NAV_FLAG_WAIT_READ; + if (automode==0) priv->status &= ~NAV_FLAG_WAIT_READ_AUTO; + if (automode>0) priv->status |= NAV_FLAG_WAIT_READ_AUTO; + return; +} + +// get current audio channel id +int mp_dvdnav_get_audio(stream_t *stream) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + return dvdnav_get_active_audio_stream(priv->dvdnav); +} + +audio_attr_t mp_dvdnav_audio_attr(stream_t *stream, int audio_num) { + audio_attr_t audio_attr; + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + memset(&audio_attr,0,sizeof(audio_attr_t)); + dvdnav_get_audio_attr(priv->dvdnav, audio_num, &audio_attr); + return audio_attr; +} + +// get current spu +int mp_dvdnav_get_spu(stream_t *stream) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + return dvdnav_get_active_spu_stream(priv->dvdnav); +} + +// is audio channel change? +int mp_dvdnav_is_audio_change(stream_t *stream) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + if(!priv->status & NAV_FLAG_AUDIO_CHANGE) return 0; + priv->status &= ~NAV_FLAG_AUDIO_CHANGE; + return 1; +} + +// is spu change? +int mp_dvdnav_is_spu_change(stream_t *stream) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + if(!(priv->status & NAV_FLAG_SPU_CHANGE)) return 0; + priv->status &= ~NAV_FLAG_SPU_CHANGE; + return 1; +} + +// is change title, part, audio or spu +int mp_dvdnav_is_change(stream_t *stream) { + int tit = 0, part = 0, tit_nr = 0, part_nr = 0; + audio_attr_t audio_attr; + int i,sub_id,audio_id; + uint16_t language; + + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + if(!(priv->status & NAV_FLAG_STREAM_CHANGE)) return 0; // no change + priv->status &= ~NAV_FLAG_STREAM_CHANGE; + dvdnav_current_title_info(priv->dvdnav, &tit, &part); // get curren title and part + dvdnav_get_number_of_titles(priv->dvdnav,&tit_nr); + dvdnav_get_number_of_parts(priv->dvdnav,tit,&part_nr); + priv->titles_nr = tit_nr; // update titles numbers + priv->chapters_nr = part_nr; // update chapters numbers + priv->title=tit; // update current title + priv->part=part; // update current chapter + priv->nr_of_subtitles=0; + priv->nr_of_channels=0; + if (!(priv->status & NAV_FLAG_VTS_DOMAIN)) return 1; // if no vts then no set audio and spu + for(i=0;i<32;i++) { // updates spu's + priv->subtitles[priv->nr_of_subtitles].id=-1; + if (-1==(sub_id=dvdnav_get_spu_logical_stream(priv->dvdnav,i))) continue; + language=dvdnav_spu_stream_to_lang(priv->dvdnav, sub_id); + priv->subtitles[priv->nr_of_subtitles].language=language; + priv->subtitles[priv->nr_of_subtitles].id=sub_id; + priv->nr_of_subtitles++; + } + for(i=0;i<32;i++) { // updates audio channels + priv->audio_streams[priv->nr_of_channels].id=-1; + if (-1==(sub_id=dvdnav_get_audio_logical_stream(priv->dvdnav,i))) continue; + language=dvdnav_audio_stream_to_lang(priv->dvdnav, sub_id); + audio_id = dvdnav_aid_from_audio_num(stream, sub_id); + memset(&audio_attr,0,sizeof(audio_attr_t)); + dvdnav_get_audio_attr(priv->dvdnav, i, &audio_attr); + priv->audio_streams[priv->nr_of_channels].language=language; + priv->audio_streams[priv->nr_of_channels].id=audio_id; + priv->audio_streams[priv->nr_of_channels].type=audio_attr.audio_format; + priv->audio_streams[priv->nr_of_channels].channels=audio_attr.channels; + priv->nr_of_channels++; + } + return 1; +} + +void mp_dvdnav_switch_title(stream_t *stream, int title) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + + if(title>0 && title<=priv->titles_nr) + dvdnav_title_play(priv->dvdnav, title); +} + +void mp_dvdnav_switch_chapter(stream_t *stream, int chapter) { + dvdnav_priv_t * priv=(dvdnav_priv_t*)stream->priv; + + if(chapter>=0 && chapterchapters_nr && priv->title>0) + dvdnav_part_play(priv->dvdnav, priv->title, chapter); +} + +title_prop_t* seek_title_prop(dvdnav_priv_t * priv, int title) { + int i; + + if(!priv->title_prop) + return NULL; + if (!(priv->status & NAV_FLAG_VTS_DOMAIN)) + return NULL; + for(i=0;ititle_prop_num;i++) + if(priv->title_prop[i].title==title) + return &priv->title_prop[i]; + return NULL; +} + +title_prop_t* add_title_prop(dvdnav_priv_t * priv, int title) { + title_prop_t* title_prop; + priv->title_prop_num++; + if(priv->title_prop) + priv->title_prop=realloc(priv->title_prop,priv->title_prop_num*sizeof(title_prop_t)); + else + priv->title_prop=malloc(priv->title_prop_num*sizeof(title_prop_t)); + title_prop=&priv->title_prop[priv->title_prop_num-1]; + title_prop->title=title; + title_prop->mp_aid=-1; + title_prop->nav_aid=-1; + title_prop->mp_sid=-1; + title_prop->nav_sid=-1; + return title_prop; +} + +void dvdnav_reg_mp_aid(stream_t *stream, int audio_id) { + dvdnav_priv_t* priv=(dvdnav_priv_t*)stream->priv; + title_prop_t* title_prop = seek_title_prop(priv,priv->title); + if (!(priv->status & NAV_FLAG_VTS_DOMAIN)) + return; + if(!title_prop) + title_prop=add_title_prop(priv,priv->title); + title_prop->mp_aid=audio_id; +} + +int dvdnav_reg_nav_aid(stream_t *stream, int audio_id) { + dvdnav_priv_t* priv=(dvdnav_priv_t*)stream->priv; + title_prop_t* title_prop = seek_title_prop(priv,priv->title); + if (!(priv->status & NAV_FLAG_VTS_DOMAIN)) + return audio_id; + if(!title_prop) + title_prop=add_title_prop(priv,priv->title); + if(title_prop->mp_aid==-1) + return title_prop->nav_aid=audio_id; + if(title_prop->nav_aid==-1) + title_prop->nav_aid=audio_id; + if(title_prop->nav_aid==audio_id) + return title_prop->mp_aid; + title_prop->nav_aid=audio_id; + return audio_id; +} + +void dvdnav_reg_mp_sid(stream_t *stream, int dvdsub_id) { + dvdnav_priv_t* priv=(dvdnav_priv_t*)stream->priv; + title_prop_t* title_prop = seek_title_prop(priv,priv->title); + if (!(priv->status & NAV_FLAG_VTS_DOMAIN)) + return; + if(!title_prop) + title_prop=add_title_prop(priv,priv->title); + title_prop->mp_sid=dvdsub_id; +} + +int dvdnav_reg_nav_sid(stream_t *stream, int dvdsub_id) { + dvdnav_priv_t* priv=(dvdnav_priv_t*)stream->priv; + title_prop_t* title_prop = seek_title_prop(priv,priv->title); + if (!(priv->status & NAV_FLAG_VTS_DOMAIN)) + return dvdsub_id; + if(!title_prop) + title_prop=add_title_prop(priv,priv->title); + if(title_prop->mp_sid==-1) + return title_prop->nav_sid=dvdsub_id; + if(title_prop->nav_sid==-1) + title_prop->nav_sid=dvdsub_id; + if(title_prop->nav_sid==dvdsub_id) + return title_prop->mp_sid; + title_prop->nav_sid=dvdsub_id; + return dvdsub_id; } stream_info_t stream_info_dvdnav = { --- stream/stream_dvdnav.h 2007-10-07 21:49:26.000000000 +0200 +++ stream/stream_dvdnav.h 2008-01-12 23:53:13.000000000 +0100 @@ -12,27 +12,83 @@ typedef struct { uint16_t sx, sy; uint16_t ex, ey; + + uint32_t palette; } nav_highlight_t; typedef struct { + int title; + int mp_aid; + int nav_aid; + int mp_sid; + int nav_sid; +} title_prop_t; + +/* status flags */ +#define NAV_FLAG_EOFSTREAM 0x0001 /* stream eof flag */ +#define NAV_FLAG_WAIT 0x0002 /* wait event */ +#define NAV_FLAG_WAIT_SKIP 0x0004 /* wait skip disable */ +#define NAV_FLAG_CELL_CHANGE 0x0008 /* cell change event */ +#define NAV_FLAG_WAIT_READ_AUTO 0x0010 /* wait read auto mode (if opening demuxer then off else on) */ +#define NAV_FLAG_WAIT_READ 0x0020 /* wait read flag (suspend read from dvdnav stream */ +#define NAV_FLAG_STREAM_CHANGE 0x0040 /* stream change flag: title, part, audio or SPU */ +#define NAV_FLAG_VTS_DOMAIN 0x0080 /* vts domain */ +#define NAV_FLAG_SPU_SET 0x0100 /* spu_clut is valid */ +#define NAV_FLAG_SPU_CHANGE 0x0200 /* SPU change flag */ +#define NAV_FLAG_AUDIO_CHANGE 0x0400 /* audio change flag */ + +typedef struct { dvdnav_t * dvdnav; /* handle to libdvdnav stuff */ char * filename; /* path */ unsigned int duration; /* in milliseconds */ int mousex, mousey; int title; - unsigned int spu_clut[16], spu_set; + unsigned int spu_clut[16]; dvdnav_highlight_event_t hlev; + int still_length; /* still frame duration */ + unsigned int status; + + int part; /* current chapter */ + int titles_nr; /* all titles numbers */ + int chapters_nr; /* all chapert numbers in current title */ + int nr_of_channels; /* audio channels numbers */ + stream_language_t audio_streams[32]; /* audio channels propreties */ + int nr_of_subtitles; /* spu numbers */ + stream_language_t subtitles[32]; /* spu properties */ + + int title_prop_num; + title_prop_t* title_prop; } dvdnav_priv_t; int dvdnav_number_of_subs(stream_t *stream); int dvdnav_aid_from_lang(stream_t *stream, unsigned char *language); +int dvdnav_aid_from_audio_num(stream_t *stream, int audio_num); int dvdnav_lang_from_aid(stream_t *stream, int id, unsigned char *buf); int dvdnav_sid_from_lang(stream_t *stream, unsigned char *language); int dvdnav_lang_from_sid(stream_t *stream, int sid, unsigned char *buf); -int mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button); +void mp_dvdnav_handle_input(stream_t *stream, int cmd, int *button); void mp_dvdnav_update_mouse_pos(stream_t *stream, int32_t x, int32_t y, int* button); void mp_dvdnav_get_highlight (stream_t *stream, nav_highlight_t *hl); unsigned int *mp_dvdnav_get_spu_clut(stream_t *stream); +int mp_dvdnav_isreallyeof(stream_t *stream); +int mp_dvdnav_still_skip(stream_t *stream); +int mp_dvdnav_wait_skip(stream_t *stream); +int mp_dvdnav_iscellchage(stream_t *stream, int clear); +void mp_dvdnav_wait_read(stream_t *stream, int mode, int automode); + +int mp_dvdnav_get_audio(stream_t *stream); +audio_attr_t mp_dvdnav_audio_attr(stream_t *stream, int audio_num); +int mp_dvdnav_is_audio_change(stream_t *stream); +int mp_dvdnav_get_spu(stream_t *stream); +int mp_dvdnav_is_spu_change(stream_t *stream); +int mp_dvdnav_is_change(stream_t *stream); + +void mp_dvdnav_switch_title(stream_t *stream, int title); +void mp_dvdnav_switch_chapter(stream_t *stream, int chapter); +void dvdnav_reg_mp_aid(stream_t *stream, int audio_id); +int dvdnav_reg_nav_aid(stream_t *stream, int audio_id); +void dvdnav_reg_mp_sid(stream_t *stream, int dvdsub_id); +int dvdnav_reg_nav_sid(stream_t *stream, int dvdsub_id); #endif