/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * player.cc * * Mon Mar 6 20:14:25 CET 2006 * Copyright 2006 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of MIaV. * * MIaV is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MIaV is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MIaV; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "player.h" #define WIDTH 720 #define HEIGHT 576 static unsigned char yuv_buf[WIDTH*HEIGHT*3]; static int num = 0; static bool first = true; Player::Player(VideoWidget *w, Decoder *d) { widget = w; decoder = d; render.init(widget, WIDTH, HEIGHT);//widget->getWidth(), widget->getHeight() connect(this, SIGNAL(timeout()), this, SLOT(show_frame())); /* for(int x = 1; x < 720; x++) for(int y = 1; y < 576; y++) { yuv[x + y * 576 * 1] = x % 720 * 255; yuv[x + y * 576 * 2] = y % 576 * 255; yuv[x + y * 576 * 3] = (unsigned char)x % y; } */ dvdecoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE); dvdecoder->quality = DV_QUALITY_BEST; // reader.connect(); } Player::~Player() { render.end(); } void Player::show_frame() { uint8_t *frame; fprintf(stderr, "Frame!%d\n", num++); frame = decoder->getFrame(); if(!frame) return; if(first) { #ifdef COLORSPACE_YV12 yuv[0] = yuv_buf; yuv[1] = (unsigned char*)yuv[0] + (WIDTH * HEIGHT); yuv[2] = (unsigned char*)yuv[1] + (WIDTH * HEIGHT / 4); pitches[0] = WIDTH; pitches[1] = WIDTH / 2; pitches[2] = WIDTH / 2; #else yuv[0] = yuv_buf; pitches[0] = WIDTH * 2; #endif dv_parse_header(dvdecoder, frame); //dv_parse_packs(decoder, frame->data); // Not needed anyway! dvdecoder->system = e_dv_system_625_50; // PAL lines, PAL framerate dvdecoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v dvdecoder->std = e_dv_std_iec_61834; dvdecoder->num_dif_seqs = 12; first = false; } dv_decode_full_frame(dvdecoder, frame, e_dv_color_yuv, yuv, pitches); render.width = widget->getWidth(); render.height = widget->getHeight(); render.display(yuv_buf, WIDTH, HEIGHT);//widget->width(), widget->height()); } #if 0 #define DBG(x) fprintf(stderr, x) #include "info.h" #include #define DV_FOURCC_YV12 0x32315659 /* 4:2:0 Planar mode: Y + V + U (3 planes) */ #define DV_FOURCC_YUY2 0x32595559 /* 4:2:2 Packed mode: Y0+U0+Y1+V0 (1 plane) */ #include #include extern "C" { //extern int XShmQueryExtension(Display*); //extern int XShmGetEventBase(Display*); extern XvImage *XvShmCreateImage(Display*, XvPortID, int, char*, int, int, XShmSegmentInfo*); } Player::Player(VideoWidget *w) { widget = w; // dpy = XOpenDisplay(NULL); // Get the deafult display display = widget->x11Info().display(); drawable = widget->winId(); fprintf(stderr, "XCreateGC\n"); gc = XCreateGC(display, drawable, 0, &values); /* switch(gc) { case BadAlloc: MIaV::info->error("The server failed to allocate the requested resource or server memory."); break; case BadDrawable: MIaV::info->error("A value for a Drawable argument does not name a defined Window or Pixmap."); break; case BadFont: MIaV::info->error("A value for a Font or GContext argument does not name a defined Font."); break; case BadMatch: MIaV::info->error("An InputOnly window is used as a Drawable."); break; case BadMatch: MIaV::info->error("Some argument or pair of arguments has the correct type and range but fails to match in some other way required by the request."); break; case BadPixmap: MIaV::info->error("A value for a Pixmap argument does not name a defined Pixmap."); break; case BadValue: MIaV::info->error("Some numeric value falls outside the range of values accepted by the request. Unless a \ specific range is specified for an argument, the full range defined by the argument's type is \ accepted. Any argument defined as a set of alternatives can generate this error."); break; } */ // // Check version // unsigned int version, release; unsigned int request_base, event_base, error_base; fprintf(stderr, "XvQueryExtension\n"); switch(XvQueryExtension(display, &version, &release, &request_base, &event_base, &error_base)) { case Success:DBG("[-]Returned if XvQueryExtension(3X) completed successfully.");break; case XvBadExtension:DBG("[E]Returned if the Xv video extension is not available for the named display.");break; case XvBadAlloc:DBG("[E]Returned if XvQueryExtension(3X) failed to allocate memory to process the request.");break; } // // Find port // unsigned int adaptors; XvAdaptorInfo *ai; fprintf(stderr, "XvQueryAdaptors\n"); switch(XvQueryAdaptors(display, drawable, &adaptors, &ai)) { case Success:DBG("[-]Returned if XvQueryAdaptors(3X) completed successfully.");break; case XvBadExtension:DBG("[E]Returned if the Xv video extension is not available for the named display.");break; case XvBadAlloc:DBG("[E]Returned if XvQueryAdaptors(3X) failed to allocate memory to process the request.");break; } /* typedef struct { XvPortID base_id; unsigned long num_ports; char type; char *name; unsigned long num_formats; XvFormat *formats; unsigned long num_adaptors; } XvAdaptorInfo; */ if(adaptors == 0) { MIaV::info->error("Unable to find any adapters."); return; } /* check adaptors */ port = 0; for (unsigned int i = 0; i < adaptors; i++) { if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask) && (ai[i].type & XvOutputMask) && (port == 0)) { port = ai[i].base_id; } } fprintf(stderr, "XvGrabPort\n"); if(port == 0) { MIaV::info->error("Unable to find suitable port."); return; } else { MIaV::info->info("Using port %d.", port); } fprintf(stderr, "Using XVideo port: %d\n", port); port=62; switch(XvGrabPort(display, port, CurrentTime)) { case Success:DBG("[-]Returned if XvGrabPort(3X) completed successfully.");break; case XvInvalidTime:DBG("[E]Returned if requested time is older than the current port time.");break; case XvAlreadyGrabbed:DBG("[E]Returned if the port is already grabbed by another client.");break; case XvBadExtension:DBG("[E]Returned if the Xv extension is unavailable.");break; case XvBadAlloc:DBG("[E]Returned if XvGrabPort(3X) failed to allocate memory to process the request.");break; } } Player::~Player() { fprintf(stderr, "XFreeGC\n"); XvUngrabPort(display, port, CurrentTime); XFreeGC(display, gc); //XCloseDisplay(dpy); // Close the Display } //extern XvImage *XvShmCreateImage(Display*, XvPortID, int, char*, int, int, XShmSegmentInfo*); void Player::run() { while(1) { XShmSegmentInfo yuv_shminfo; static char pixels[720*576*4][4]; XvImage* xv_image = XvShmCreateImage(display, port, DV_FOURCC_YV12, //DV_FOURCC_YUY2 pixels[0], widget->getWidth(), widget->getHeight(),// dv_dpy->width, dv_dpy->height, &yuv_shminfo); XvShmPutImage(display, port, drawable, gc, xv_image, 0, 0, widget->getWidth(), widget->getHeight(), widget->getX(), widget->getY(), widget->getWidth(), widget->getHeight(), True); // XFlush(display); sleep(1); } /* int cnt = 100; while(cnt--) { sleep(1); fprintf(stderr, "XvPutStill(%d,%d,%d,%d)\n",widget->getX(),widget->getY(),widget->getWidth(), widget->getHeight()); switch(XvPutStill(display, port, drawable, gc, widget->getX(),widget->getY(),widget->getWidth(), widget->getHeight(), widget->getX(),widget->getY(),widget->getWidth(), widget->getHeight())) { // case Success: // Yeah! //break; case XvBadExtension: MIaV::info->error("Returned if the Xv extension is unavailable."); break; case XvBadAlloc: MIaV::info->error("Returned if XvGetStill(3X) failed to allocate memory to process the request."); break; case XvBadPort: MIaV::info->error("Generated if the requested port does not exist."); break; case BadDrawable: MIaV::info->error("Generated if the requested drawable does not exist."); break; case BadGC: MIaV::info->error("Generated if the requested graphics context does not exist."); break; case BadAlloc: MIaV::info->error("Generated if there were insufficient resources to process the request."); break; } // fprintf(stderr, "XFlush\n"); XFlush(display); } */ } /* #include #include #include #include #include #include #include #include */ /* XvImage* ximage=XCreateImage(display, visual, 32, ZPixmap, 0, xw->virtualscreen, xw->width, xw->height, 32, xw->width*xw->pixelsize); XShmSegmentInfo yuv_shminfo; yuv_shminfo.shmid = shmget(IPC_PRIVATE, 720*576*4, //yuv_image->data_size, IPC_CREAT | 0777); // yuv_shminfo.shmaddr = shmat(yuv_shminfo.shmid, 0, 0); yuv_shminfo.readOnly = False; char pixels[720*576*4][4]; XvImage* xv_image = XvShmCreateImage(display, port, DV_FOURCC_YUY2, // DV_FOURCC_YV12 pixels[0], 720, 576,// dv_dpy->width, dv_dpy->height, &yuv_shminfo); int swidth = 720; int sheight = 576; int lxoff = 0; int lyoff = 0; int lwidth = swidth; int lheight = sheight; XvShmPutImage(display, port, drawable, gc, xv_image, 0, 0, swidth, sheight, lxoff, lyoff, lwidth, lheight, True); */ // From: // http://cvs.sourceforge.net/viewcvs.py/libmpeg2/MSSG/display_x11.c?rev=1.2 //#if 0 #ifdef HAVE_XV xv_port = 0; if (Success == XvQueryExtension(mydisplay,&ver,&rel,&req,&ev,&err)) { /* check for Xvideo support */ if (Success != XvQueryAdaptors(mydisplay,DefaultRootWindow(mydisplay), &adaptors,&ai)) { fprintf(stderr,"Xv: XvQueryAdaptors failed"); exit(1); } /* check adaptors */ for (i = 0; i < adaptors; i++) { if ((ai[i].type & XvInputMask) && (ai[i].type & XvImageMask) && (xv_port == 0)) { xv_port = ai[i].base_id; } } /* check image formats */ if (xv_port != 0) { fo = XvListImageFormats(mydisplay, xv_port, (int*)&formats); for(i = 0; i < formats; i++) { fprintf(stderr, "Xvideo image format: 0x%x (%4.4s) %s\n", fo[i].id, (char*)&fo[i].id, (fo[i].format == XvPacked) ? "packed" : "planar"); if (0x32315659 == fo[i].id) { xv_format = fo[i].id; break; } } if (i == formats) /* no matching image format not */ xv_port = 0; } if (xv_port != 0) { fprintf(stderr,"using Xvideo port %d for hw scaling\n", xv_port); /* allocate XvImages. FIXME: no error checking, without * mit-shm this will bomb... */ xvimage1 = XvShmCreateImage(mydisplay, xv_port, xv_format, 0, image_width, image_height, &Shminfo1); Shminfo1.shmid = shmget(IPC_PRIVATE, xvimage1->data_size, IPC_CREAT | 0777); Shminfo1.shmaddr = (char *) shmat(Shminfo1.shmid, 0, 0); Shminfo1.readOnly = False; xvimage1->data = Shminfo1.shmaddr; XShmAttach(mydisplay, &Shminfo1); XSync(mydisplay, False); shmctl(Shminfo1.shmid, IPC_RMID, 0); /* so we can do grayscale while testing... */ memset(xvimage1->data,128,xvimage1->data_size); /* catch window resizes */ XSelectInput(mydisplay, mywindow, StructureNotifyMask); win_width = image_width; win_height = image_height; /* all done (I hope...) */ X_already_started++; return; } } #endif/* HAVE_XV */ #endif/* 0 */