Index: libvo/osd.c =================================================================== RCS file: /cvsroot/mplayer/main/libvo/osd.c,v retrieving revision 1.21 diff -u -r1.21 osd.c --- libvo/osd.c 26 Apr 2004 10:12:40 -0000 1.21 +++ libvo/osd.c 3 May 2004 12:05:24 -0000 @@ -110,7 +110,7 @@ void vo_draw_alpha_yv12(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM - // ordered per speed fasterst first + // ordered by speed / fastest first if(gCpuCaps.hasMMX2) vo_draw_alpha_yv12_MMX2(w, h, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) @@ -140,7 +140,7 @@ void vo_draw_alpha_yuy2(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM - // ordered per speed fasterst first + // ordered by speed / fastest first if(gCpuCaps.hasMMX2) vo_draw_alpha_yuy2_MMX2(w, h, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) @@ -167,10 +167,40 @@ #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){ +#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); + else if(gCpuCaps.has3DNow) + vo_draw_alpha_uyvy_3DNow(w, h, src, srca, srcstride, dstbase, dststride); + else if(gCpuCaps.hasMMX) + vo_draw_alpha_uyvy_MMX(w, h, src, srca, srcstride, dstbase, dststride); + else + vo_draw_alpha_uyvy_X86(w, h, src, srca, srcstride, dstbase, dststride); +#else + vo_draw_alpha_uyvy_C(w, h, src, srca, srcstride, dstbase, dststride); +#endif +#else //RUNTIME_CPUDETECT +#ifdef HAVE_MMX2 + vo_draw_alpha_uyvy_MMX2(w, h, src, srca, srcstride, dstbase, dststride); +#elif defined (HAVE_3DNOW) + vo_draw_alpha_uyvy_3DNow(w, h, 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); +#else + vo_draw_alpha_uyvy_C(w, h, 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){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM - // ordered per speed fasterst first + // ordered by speed / fastest first if(gCpuCaps.hasMMX2) vo_draw_alpha_rgb24_MMX2(w, h, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) @@ -200,7 +230,7 @@ void vo_draw_alpha_rgb32(int w,int h, unsigned char* src, unsigned char *srca, int srcstride, unsigned char* dstbase,int dststride){ #ifdef RUNTIME_CPUDETECT #ifdef CAN_COMPILE_X86_ASM - // ordered per speed fasterst first + // ordered by speed / fastest first if(gCpuCaps.hasMMX2) vo_draw_alpha_rgb32_MMX2(w, h, src, srca, srcstride, dstbase, dststride); else if(gCpuCaps.has3DNow) Index: libvo/osd.h =================================================================== RCS file: /cvsroot/mplayer/main/libvo/osd.h,v retrieving revision 1.3 diff -u -r1.3 osd.h --- libvo/osd.h 10 Jun 2001 22:25:09 -0000 1.3 +++ libvo/osd.h 3 May 2004 12:05:24 -0000 @@ -9,6 +9,7 @@ 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); Index: libvo/osd_template.c =================================================================== RCS file: /cvsroot/mplayer/main/libvo/osd_template.c,v retrieving revision 1.20 diff -u -r1.20 osd_template.c --- libvo/osd_template.c 3 Aug 2003 18:33:28 -0000 1.20 +++ libvo/osd_template.c 3 May 2004 12:05:24 -0000 @@ -160,6 +160,30 @@ 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){ + int y; +#if defined(FAST_OSD) + w=w>>1; +#endif + for(y=0;y>8)+src[x]; + dstbase[2*x]=((((signed)dstbase[2*x]-128)*srca[x])>>8)+128; + } +#endif + } + src+=srcstride; + srca+=srcstride; + dstbase+=dststride; + } +} + 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){ int y; for(y=0;y Copyright (c) Nicolas Plourde - April 2004 + + YUV support Copyright (C) 2004 Romain Dolbeau MPlayer Mac OSX Quartz video out module. - todo: -YUV support. - -Redo event handling. + todo: -Redo event handling. -Choose fullscreen display device. -Fullscreen antialiasing. -resize black bar without CGContext -rootwin -non-blocking event -(add sugestion here) + + Direct YUV support is functional, and is now enabled + by default. To constrain what format should be used, + use the format=XXX video filter (i.e. -vf format=uyvy). */ //SYS @@ -22,33 +27,57 @@ //OSX #include +#include //MPLAYER #include "config.h" +#include "fastmemcpy.h" #include "video_out.h" #include "video_out_internal.h" #include "aspect.h" +#include "mp_msg.h" +#include "m_option.h" #include "../input/input.h" #include "../input/mouse.h" #include "vo_quartz.h" +#define QUARTZ_ENABLE_YUV + static vo_info_t info = { "Mac OSX (Quartz)", "quartz", - "Nicolas Plourde ", + "Nicolas Plourde , Romain Dolbeau ", "" }; LIBVO_EXTERN(quartz) -uint32_t image_width; -uint32_t image_height; -uint32_t image_depth; -uint32_t image_bytes; -uint32_t image_format; +static uint32_t image_width; +static uint32_t image_height; +static uint32_t image_depth; +static uint32_t image_format; +static uint32_t image_size; +static uint32_t image_buffer_size; + +#ifdef QUARTZ_ENABLE_YUV +static CodecType image_qtcodec; +static PlanarPixmapInfoYUV420 *P; +static struct { + ImageSequence seqId; + ImageDescriptionHandle desc; + Handle extension_colr; + Handle extension_fiel; + Handle extension_clap; + Handle extension_pasp; + MatrixRecord matrix; +} yuv_qt_stuff; +static DecompressorComponent mycodec; +static ComponentInstance myopenedcodec; +static int EnterMoviesDone = 0; +#endif char *image_data; extern int vo_ontop; @@ -64,8 +93,7 @@ GWorldPtr imgGWorld; Rect imgRect; -Rect dstRect; -Rect winRect; +Rect dstRect;Rect winRect; CGContextRef context; @@ -85,7 +113,26 @@ static void draw_alpha(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,image_data+4*(y0*imgRect.right+x0),4*imgRect.right); + 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); + break; +#ifdef QUARTZ_ENABLE_YUV + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + vo_draw_alpha_yv12(w,h,src,srca,stride, + ((char*)P) + P->componentInfoY.offset + x0 + y0 * image_width, + image_width); + break; + case IMGFMT_UYVY: + vo_draw_alpha_uyvy(w,h,src,srca,stride,((char*)P) + (x0 + y0 * image_width) * 2,image_width*2); + break; + case IMGFMT_YUY2: + vo_draw_alpha_yuy2(w,h,src,srca,stride,((char*)P) + (x0 + y0 * image_width) * 2,image_width*2); + break; +#endif + } } //default window event handler @@ -243,6 +290,7 @@ OSStatus result; GDHandle deviceHdl; Rect deviceRect; + OSErr qterr; //Get Main device info/////////////////////////////////////////////////// deviceHdl = GetMainDevice(); @@ -254,9 +302,22 @@ //misc mplayer setup///////////////////////////////////////////////////// image_width = width; image_height = height; - image_depth = IMGFMT_RGB_DEPTH(format); - image_bytes = (IMGFMT_RGB_DEPTH(format)+7)/8; - image_data = malloc(image_width*image_height*4); + switch (image_format) { + case IMGFMT_RGB32: + image_depth = IMGFMT_RGB_DEPTH(format); + break; +#ifdef QUARTZ_ENABLE_YUV + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + image_depth = 16; + case IMGFMT_UYVY: + case IMGFMT_YUY2: + image_depth = 16; + break; +#endif + } + image_size = ((image_width*image_height*image_depth)+7)/8; vo_fs = flags & VOFLAG_FULLSCREEN; @@ -268,9 +329,9 @@ aspect(&d_width,&d_height,A_NOZOOM); //Create player window////////////////////////////////////////////////// - windowAttrs = kWindowStandardDocumentAttributes + windowAttrs = kWindowStandardDocumentAttributes & ~(kWindowResizableAttribute) | kWindowStandardHandlerAttribute - | kWindowLiveResizeAttribute; + ;//| kWindowLiveResizeAttribute; SetRect(&winRect, 0, 0, d_width, d_height); SetRect(&dstRect, 0, 0, d_width, d_height); @@ -296,6 +357,229 @@ //Show window RepositionWindow(theWindow, NULL, kWindowCascadeOnMainScreen); +#ifdef QUARTZ_ENABLE_YUV + if (!(IMGFMT_IS_RGB(image_format))) { + if (!EnterMoviesDone) { + qterr = EnterMovies(); + EnterMoviesDone = 1; + } + else + qterr = 0; + mp_msg(MSGT_VO, MSGL_INFO, "\nQuartz: EnterMovies\n"); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: EnterMovies (%d)\n", qterr); + } + + +#if 0 // can be handy for developers, but useless for users + { + CodecNameSpecListPtr list; + int index; + qterr = GetCodecNameList(&list, 1); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: GetCodecNameList (%d)\n", qterr); + } + mp_msg(MSGT_VO, MSGL_ERR, "Quartz: found %d codec\n", list->count); + + for (index = 0; index < list->count; index++) { + char name[32]; + CodecInfo ci; + + memcpy(name, &(list->list[index].typeName[1]), list->list[index].typeName[0]); + name[list->list[index].typeName[0]]='\0'; + qterr = GetCodecInfo(&ci, list->list[index].cType, list->list[index].codec); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: GetCodecInfo (%d)\n", qterr); + } + mp_msg(MSGT_VO, MSGL_INFO, "Quartz: QuickTimecodec %d:\n\tname: %s\n\ttype: %.4s\n\tvendor: %.4s\n\tversion/revision: %d/%d\n\tdecompressFlags: 0x%08x\n\tcompressFlags: 0x%08x\n\tformatFlags: 0x%08x\n", index, name, &list->list[index].cType, &ci.vendor, ci.version, ci.revisionLevel, ci.decompressFlags, ci.compressFlags, ci.formatFlags); + } + } + { + Component c = NULL; + ComponentDescription cd; + cd.componentType = 'imdc'; + cd.componentSubType = image_qtcodec; + cd.componentManufacturer = 0;//'appx'; + cd.componentFlags = 0; + cd.componentFlagsMask = 0; + + while (c = FindNextComponent(c, &cd)) { + ComponentDescription cd2; + Handle h1 = NewHandleClear(4); + Handle h2 = NewHandleClear(4); + char ch1[256], ch2[256]; + cd2.componentFlagsMask = 0; + + qterr = GetComponentInfo(c, &cd2, h1, h2, NULL); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: GetComponentInfo (%d)\n", qterr); + } + memcpy(ch1, &((unsigned char*)(*h1))[1], ((unsigned char*)(*h1))[0]); + ch1[((unsigned char*)(*h1))[0]] = '\0'; + memcpy(ch2, &((unsigned char*)(*h2))[1], ((unsigned char*)(*h2))[0]); + ch2[((unsigned char*)(*h2))[0]] = '\0'; + DisposeHandle(h1); + DisposeHandle(h2); + + mp_msg(MSGT_VO, MSGL_ERR, "QuickTime: component %.4s %.4s %.4s, %s, %s, [flags: 0x%08x, mask: 0x%08x]\n", + &cd2.componentType, + &cd2.componentSubType, + &cd2.componentManufacturer, + ch1, + ch2, + cd2.componentFlags, + cd2.componentFlagsMask); + } + } +#endif + { + ComponentDescription cd2; + Handle h1 = NewHandleClear(4); + Handle h2 = NewHandleClear(4); + char ch1[256], ch2[256]; + + qterr = FindCodec(image_qtcodec, bestSpeedCodec, NULL, &mycodec); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: FindCodec (%d)\n", qterr); + } + qterr = GetComponentInfo(mycodec, &cd2, h1, h2, NULL); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: GetComponentInfo (%d)\n", qterr); + } + memcpy(ch1, &((unsigned char*)(*h1))[1], ((unsigned char*)(*h1))[0]); + ch1[((unsigned char*)(*h1))[0]] = '\0'; + memcpy(ch2, &((unsigned char*)(*h2))[1], ((unsigned char*)(*h2))[0]); + ch2[((unsigned char*)(*h2))[0]] = '\0'; + DisposeHandle(h1); + DisposeHandle(h2); + mp_msg(MSGT_VO, MSGL_INFO, "Quartz: QuickTime FindCodec reports component %.4s %.4s %.4s, %s, %s, [flags: 0x%08x, mask: 0x%08x]\n", + &cd2.componentType, + &cd2.componentSubType, + &cd2.componentManufacturer, + ch1, + ch2, + cd2.componentFlags, + cd2.componentFlagsMask); + + { + CodecInfo ci; + qterr = GetCodecInfo(&ci, 'imdc', mycodec); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: GetCodecInfo (%d)\n", qterr); + } + mp_msg(MSGT_VO, MSGL_INFO, "Quartz: CodecInfo:\n\tname: %s\n\tvendor: %.4s\n\tversion/revision: %d/%d\n\tdecompressFlags: 0x%08x\n\tcompressFlags: 0x%08x\n\tformatFlags: 0x%08x\n", ch1, &ci.vendor, ci.version, ci.revisionLevel, ci.decompressFlags, ci.compressFlags, ci.formatFlags); + } + } + yuv_qt_stuff.desc = (ImageDescriptionHandle)NewHandleClear( sizeof(ImageDescription) ); + yuv_qt_stuff.extension_colr = NewHandleClear(sizeof(NCLCColorInfoImageDescriptionExtension)); + ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->colorParamType = kVideoColorInfoImageDescriptionExtensionType; + ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->primaries = 2; + ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->transferFunction = 2; + ((NCLCColorInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_colr))->matrix = 2; + yuv_qt_stuff.extension_fiel = NewHandleClear(sizeof(FieldInfoImageDescriptionExtension)); + ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldCount = 1; + ((FieldInfoImageDescriptionExtension*)(*yuv_qt_stuff.extension_fiel))->fieldOrderings = 0; + yuv_qt_stuff.extension_clap = NewHandleClear(sizeof(CleanApertureImageDescriptionExtension)); + ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthN = image_width; + ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureWidthD = 1; + ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightN = image_height; + ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->cleanApertureHeightD = 1; + ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffN = 0; + ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->horizOffD = 1; + ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffN = 0; + ((CleanApertureImageDescriptionExtension*)(*yuv_qt_stuff.extension_clap))->vertOffD = 1; + yuv_qt_stuff.extension_pasp = NewHandleClear(sizeof(PixelAspectRatioImageDescriptionExtension)); + ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->hSpacing = 1; + ((PixelAspectRatioImageDescriptionExtension*)(*yuv_qt_stuff.extension_pasp))->vSpacing = 1; + + (*yuv_qt_stuff.desc)->idSize = sizeof(ImageDescription); + (*yuv_qt_stuff.desc)->cType = image_qtcodec; + (*yuv_qt_stuff.desc)->version = 2; + (*yuv_qt_stuff.desc)->revisionLevel = 0; + (*yuv_qt_stuff.desc)->vendor = 'mpla'; + (*yuv_qt_stuff.desc)->width = image_width; + (*yuv_qt_stuff.desc)->height = image_height; + (*yuv_qt_stuff.desc)->hRes = Long2Fix(72); + (*yuv_qt_stuff.desc)->vRes = Long2Fix(72); + (*yuv_qt_stuff.desc)->temporalQuality = 0; + (*yuv_qt_stuff.desc)->spatialQuality = codecLosslessQuality; + (*yuv_qt_stuff.desc)->frameCount = 1; + (*yuv_qt_stuff.desc)->dataSize = 0; + (*yuv_qt_stuff.desc)->depth = 24; + (*yuv_qt_stuff.desc)->clutID = -1; + + qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_colr, kColorInfoImageDescriptionExtension); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: AddImageDescriptionExtension [colr] (%d)\n", qterr); + } + qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_fiel, kFieldInfoImageDescriptionExtension); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: AddImageDescriptionExtension [fiel] (%d)\n", qterr); + } + qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_clap, kCleanApertureImageDescriptionExtension); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: AddImageDescriptionExtension [clap] (%d)\n", qterr); + } + qterr = AddImageDescriptionExtension(yuv_qt_stuff.desc, yuv_qt_stuff.extension_pasp, kCleanApertureImageDescriptionExtension); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: AddImageDescriptionExtension [pasp] (%d)\n", qterr); + } + + SetPort(GetWindowPort(theWindow)); + SetIdentityMatrix(&yuv_qt_stuff.matrix); + if ((d_width != width) || (d_height != height)) { + ScaleMatrix(&yuv_qt_stuff.matrix, + FixDiv(Long2Fix(d_width),Long2Fix(width)), + FixDiv(Long2Fix(d_height),Long2Fix(height)), + 0, + 0); + } + P = calloc(sizeof(PlanarPixmapInfoYUV420) + image_size, 1); + switch (image_format) { + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + P->componentInfoY.offset = sizeof(PlanarPixmapInfoYUV420); + P->componentInfoCb.offset = P->componentInfoY.offset + image_size / 2; + P->componentInfoCr.offset = P->componentInfoCb.offset + image_size / 4; + P->componentInfoY.rowBytes = image_width; + P->componentInfoCb.rowBytes = image_width / 2; + P->componentInfoCr.rowBytes = image_width / 2; + image_buffer_size = image_size + sizeof(PlanarPixmapInfoYUV420); + break; + case IMGFMT_UYVY: + case IMGFMT_YUY2: + image_buffer_size = image_size; + break; + } + mp_msg(MSGT_VO, MSGL_INFO, "Quartz: DecompressSequenceBeginS\n"); + mp_msg(MSGT_VO, MSGL_INFO, "Quartz: width=%d, height=%d, d_width=%d, d_height=%d\n", + width, height, d_width, d_height); + myopenedcodec = OpenComponent(mycodec); + + qterr = DecompressSequenceBeginS(&yuv_qt_stuff.seqId, + yuv_qt_stuff.desc, + P, + image_buffer_size, + GetWindowPort(theWindow), + NULL, // GDHandle + NULL, // srcRect + ((d_width != width) || (d_height != height)) ? + &yuv_qt_stuff.matrix : NULL, + srcCopy, + NULL, // mask, + 0, //codecFlagUseImageBuffer, + codecLosslessQuality, + bestSpeedCodec); + //mycodec); // some codec reported by FindCodec() won't work (?) + //myopenedcodec); // doesn't seem to help, either + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: DecompressSequenceBeginS (%d)\n", qterr); + } + mp_msg(MSGT_VO, MSGL_INFO, "Quartz: DecompressSequenceBeginS done\n"); + } +#endif /* QUARTZ_ENABLE_YUV */ + ShowWindow (theWindow); if(vo_fs) @@ -345,12 +629,15 @@ static void flip_page(void) { + switch (image_format) { + case IMGFMT_RGB32: + { OSStatus error; CGrafPtr oldPort,deskPort; GDHandle oldGDevice; OSStatus lockPixelsError; Boolean canLockPixels; - + GetGWorld (&oldPort, &oldGDevice); SetGWorld(GetWindowPort(theWindow), GetMainDevice()); @@ -380,43 +667,192 @@ } SetGWorld(oldPort, oldGDevice); + } + break; +#ifdef QUARTZ_ENABLE_YUV + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + case IMGFMT_UYVY: + case IMGFMT_YUY2: + if (EnterMoviesDone) { + OSErr qterr; + CodecFlags flags = 0; + qterr = DecompressSequenceFrameWhen(yuv_qt_stuff.seqId, + P, + image_buffer_size, + 0, //codecFlagUseImageBuffer, + &flags, + NULL, + NULL); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: DecompressSequenceFrameWhen in flip_page (%d) flags:0x%08x\n", qterr, flags); + } + } + break; +#endif + } } static uint32_t draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y) { +#ifdef QUARTZ_ENABLE_YUV + switch (image_format) { + case IMGFMT_YV12: + case IMGFMT_I420: + memcpy_pic(((char*)P) + P->componentInfoY.offset + x + image_width * y, src[0], + w, h, image_width, stride[0]); + x=x/2;y=y/2;w=w/2;h=h/2; + memcpy_pic(((char*)P) + P->componentInfoCb.offset + x + image_width / 2 * y, src[1], + w, h, image_width / 2, stride[1]); + memcpy_pic(((char*)P) + P->componentInfoCr.offset + x + image_width / 2 * y, src[2], + w, h, image_width / 2, stride[2]); + return 0; + + case IMGFMT_IYUV: + memcpy_pic(((char*)P) + P->componentInfoY.offset + x + image_width * y, src[0], + w, h, image_width, stride[0]); + x=x/2;y=y/2;w=w/2;h=h/2; + memcpy_pic(((char*)P) + P->componentInfoCr.offset + x + image_width / 2 * y, src[1], + w, h, image_width / 2, stride[1]); + memcpy_pic(((char*)P) + P->componentInfoCb.offset + x + image_width / 2 * y, src[2], + w, h, image_width / 2, stride[2]); + return 0; + } +#endif return -1; } static uint32_t draw_frame(uint8_t *src[]) { + switch (image_format) { + case IMGFMT_RGB32: image_data = src[0]; - DisposeGWorld(imgGWorld); NewGWorldFromPtr (&imgGWorld, k32ARGBPixelFormat, &imgRect, 0, 0, 0, image_data, image_width * 4); - - return 0; + return 0; +#ifdef QUARTZ_ENABLE_YUV + case IMGFMT_UYVY: + case IMGFMT_YUY2: + memcpy_pic(((char*)P), src[0], image_width * 2, image_height, image_width * 2, image_width * 2); + return 0; +#endif + } + return -1; } static uint32_t query_format(uint32_t format) { image_format = format; - //Curently supporting only rgb32 format. - if ((format == IMGFMT_RGB32)) - return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW; + if (format == IMGFMT_RGB32) + return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE | VFCAP_CSP_SUPPORTED_BY_HW; + +#ifdef QUARTZ_ENABLE_YUV + image_qtcodec = 0; + + if ((format == IMGFMT_YV12) || (format == IMGFMT_IYUV) || (format == IMGFMT_I420)) { + image_qtcodec = kMpegYUV420CodecType; //kYUV420CodecType ?; + return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE | VFCAP_ACCEPT_STRIDE; + } + + if (format == IMGFMT_YUY2) { + image_qtcodec = kComponentVideoUnsigned; + return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE; + } + + if (format == IMGFMT_UYVY) { + image_qtcodec = k422YpCbCr8CodecType; + return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_SWSCALE; + } +#endif + return 0; } static void uninit(void) { + switch (image_format) { + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + case IMGFMT_UYVY: + case IMGFMT_YUY2: + { + OSErr qterr; + if (EnterMoviesDone) { + qterr = CDSequenceEnd(yuv_qt_stuff.seqId); + if (qterr) { + mp_msg(MSGT_VO, MSGL_FATAL, "Quartz error: CDSequenceEnd (%d)\n", qterr); + } + } + } + break; + default: + break; + } ShowMenuBar(); } static uint32_t preinit(const char *arg) { - return 0; + return 0; } +#ifdef QUARTZ_ENABLE_YUV +static uint32_t draw_yuv_image(mp_image_t *mpi) { + // ATM we're only called for planar IMGFMT + // drawing is done directly in P + // and displaying is in flip_page. + return VO_TRUE; +} + +static uint32_t get_yuv_image(mp_image_t *mpi) { + if(mpi->type!=MP_IMGTYPE_EXPORT) return VO_FALSE; + + if(mpi->imgfmt!=image_format) return VO_FALSE; + + if(mpi->flags&MP_IMGFLAG_PLANAR){ + if (mpi->num_planes != 3) { + mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 3 planes allowed in get_yuv_image for planar (%d) \n", mpi->num_planes); + return VO_FALSE; + } + + mpi->planes[0]=((char*)P) + P->componentInfoY.offset; + mpi->stride[0]=image_width; + mpi->width=image_width; + + if(mpi->flags&MP_IMGFLAG_SWAPPED){ + // I420 + mpi->planes[1]=((char*)P) + P->componentInfoCb.offset; + mpi->planes[2]=((char*)P) + P->componentInfoCr.offset; + mpi->stride[1]=image_width/2; + mpi->stride[2]=image_width/2; + } else { + // YV12 + mpi->planes[1]=((char*)P) + P->componentInfoCr.offset; + mpi->planes[2]=((char*)P) + P->componentInfoCb.offset; + mpi->stride[1]=image_width/2; + mpi->stride[2]=image_width/2; + } + mpi->flags|=MP_IMGFLAG_DIRECT; + return VO_TRUE; + } else { // doesn't work yet + if (mpi->num_planes != 1) { + mp_msg(MSGT_VO, MSGL_ERR, "Quartz error: only 1 plane allowed in get_yuv_image for packed (%d) \n", mpi->num_planes); + return VO_FALSE; + } + + mpi->planes[0] = (char*)P; + mpi->stride[0] = image_width * 2; + mpi->width=image_width; + mpi->flags|=MP_IMGFLAG_DIRECT; + return VO_TRUE; + } + return VO_FALSE; +} +#endif /* QUARTZ_ENABLE_YUV */ + static uint32_t control(uint32_t request, void *data, ...) { switch (request) @@ -426,6 +862,28 @@ case VOCTRL_FULLSCREEN: window_fullscreen(); return VO_TRUE; case VOCTRL_ONTOP: window_ontop(); return VO_TRUE; case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data)); +#ifdef QUARTZ_ENABLE_YUV + case VOCTRL_GET_IMAGE: + switch (image_format) { + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + //case IMGFMT_UYVY: + //case IMGFMT_YUY2: + return get_yuv_image(data); + break; + } + case VOCTRL_DRAW_IMAGE: + switch (image_format) { + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + //case IMGFMT_UYVY: + //case IMGFMT_YUY2: + return draw_yuv_image(data); + break; + } +#endif } return VO_NOTIMPL; } @@ -467,6 +925,41 @@ CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0); CGContextFillRect(context, winBounds); CGContextFlush(context); + + + switch (image_format) { +#ifdef QUARTZ_ENABLE_YUV + case IMGFMT_YV12: + case IMGFMT_IYUV: + case IMGFMT_I420: + case IMGFMT_UYVY: + case IMGFMT_YUY2: + { + long scale_X = FixDiv(Long2Fix(dstRect.right - dstRect.left),Long2Fix(image_width)); + long scale_Y = FixDiv(Long2Fix(dstRect.bottom - dstRect.top),Long2Fix(image_height)); + + SetIdentityMatrix(&yuv_qt_stuff.matrix); + if (((dstRect.right - dstRect.left) != image_width) || + ((dstRect.bottom - dstRect.right) != image_height)) { + ScaleMatrix(&yuv_qt_stuff.matrix, + scale_X, + scale_Y, + 0, + 0); + + if (padding > 0) { + TranslateMatrix(&yuv_qt_stuff.matrix, + Long2Fix(dstRect.left), + Long2Fix(dstRect.top)); + } + } + SetDSequenceMatrix(yuv_qt_stuff.seqId, &yuv_qt_stuff.matrix); + break; + } +#endif + default: + break; + } } void window_ontop() @@ -509,7 +1002,7 @@ HideCursor(); //go fullscreen - ChangeWindowAttributes(theWindow, 0, kWindowResizableAttribute); + //ChangeWindowAttributes(theWindow, 0, kWindowResizableAttribute); MoveWindow (theWindow, 0, 0, 1); SizeWindow(theWindow, device_width, device_height,1); @@ -531,7 +1024,7 @@ ShowCursor(); //revert window to previous setting - ChangeWindowAttributes(theWindow, kWindowResizableAttribute, 0); + //ChangeWindowAttributes(theWindow, kWindowResizableAttribute, 0); SizeWindow(theWindow, oldRect.right, oldRect.bottom,1); RepositionWindow(theWindow, NULL, kWindowCascadeOnMainScreen); Index: DOCS/man/en/mplayer.1 =================================================================== RCS file: /cvsroot/mplayer/main/DOCS/man/en/mplayer.1,v retrieving revision 1.585 diff -u -r1.585 mplayer.1 --- DOCS/man/en/mplayer.1 3 May 2004 10:01:31 -0000 1.585 +++ DOCS/man/en/mplayer.1 3 May 2004 12:05:25 -0000 @@ -3655,6 +3655,7 @@ .TP .B quartz (Mac OS X only) Mac OS X Quartz output driver. +Under some circumstances, it might be more efficient to force a packed YUV output format, with e.g. -vf format=yuy2 .TP .B fbdev (Linux only) Uses the kernel framebuffer to output video.