From 582bcd19d6a58c266f5453961c87acf72fae5353 Mon Sep 17 00:00:00 2001 From: deva Date: Mon, 10 Apr 2006 13:04:31 +0000 Subject: *** empty log message *** --- client/decoder.cc | 39 ++++- client/decoder.h | 13 +- client/mainwindow.h | 2 +- client/miav_client.cc | 2 +- client/player.cc | 373 ++-------------------------------------------- client/player.h | 15 +- client/xvaccelrenderer.cc | 23 +-- client/xvaccelrenderer.h | 12 +- lib/Makefile.am | 2 + lib/frame.cc | 3 + lib/frame.h | 7 +- 11 files changed, 98 insertions(+), 393 deletions(-) diff --git a/client/decoder.cc b/client/decoder.cc index e181516..fd2464b 100644 --- a/client/decoder.cc +++ b/client/decoder.cc @@ -28,13 +28,23 @@ #include "info.h" +#define READ_DV_FROM_FILE + #include "dv.h" -//#include "dvfile.h" +#ifdef READ_DV_FROM_FILE +#include "dvfile.h" +#else/* READ_DV_FROM_FILE*/ #include "dv1394.h" +#endif/* READ_DV_FROM_FILE*/ + +#include +#include -Decoder::Decoder() +Decoder::Decoder(): semaphore(1) { frame = NULL; + running = true; + qApp->installEventFilter(this); } Decoder::~Decoder() @@ -42,16 +52,33 @@ Decoder::~Decoder() void Decoder::run() { - dv1394 reader; + semaphore.acquire(); // Lock the shutdown process +#ifdef READ_DV_FROM_FILE + dvfile reader; +#else/* READ_DV_FROM_FILE*/ + dv1394 reader; reader.connect(); +#endif/* READ_DV_FROM_FILE*/ - while(1) { - frame = reader.readFrame(); + while(running) { + frame = new Frame(reader.readFrame()); } + semaphore.release(); // Unlock the shutdown process } -unsigned char *Decoder::getFrame() +Frame *Decoder::getFrame() { return frame; } + +bool Decoder::eventFilter(QObject *o, QEvent *e) +{ + if (e->type() == QEvent::Close) { + running = false; // Tell the thread to stop. + semaphore.acquire(); // Wait for the thread to stop. + } + + // standard event processing + return false; +} diff --git a/client/decoder.h b/client/decoder.h index ca684ed..3a1b30f 100644 --- a/client/decoder.h +++ b/client/decoder.h @@ -28,19 +28,28 @@ #define __MIAV_DECODER_H__ #include +#include +#include "frame.h" class Decoder : public QThread { +Q_OBJECT public: Decoder(); ~Decoder(); - unsigned char *getFrame(); + Frame *getFrame(); void run(); +protected: + bool eventFilter(QObject *o, QEvent *e); + private: - unsigned char *frame; + volatile bool running; + volatile bool stopped; + Frame *frame; + QSemaphore semaphore; }; #endif/*__MIAV_DECODER_H__*/ diff --git a/client/mainwindow.h b/client/mainwindow.h index 58edb3c..4698a2c 100644 --- a/client/mainwindow.h +++ b/client/mainwindow.h @@ -59,7 +59,7 @@ public: MainWindow(); ~MainWindow(); - VideoWidget *getVideo() { return video; } + QWidget *getVideoWidget() { return video; } void moveEvent(QMoveEvent *event); diff --git a/client/miav_client.cc b/client/miav_client.cc index 376a27e..6122093 100644 --- a/client/miav_client.cc +++ b/client/miav_client.cc @@ -48,7 +48,7 @@ int main(int argc, char *argv[]) MainWindow mainwindow; Decoder decoder; - Player player(mainwindow.getVideo(), &decoder); + Player player(mainwindow.getVideoWidget(), &decoder); NetworkSender sender; decoder.start(); diff --git a/client/player.cc b/client/player.cc index 1edf2cb..1f789b9 100644 --- a/client/player.cc +++ b/client/player.cc @@ -29,32 +29,23 @@ #define WIDTH 720 #define HEIGHT 576 -static unsigned char yuv_buf[WIDTH*HEIGHT*3]; +//#define COLORSPACE_YV12 + static int num = 0; static bool first = true; -Player::Player(VideoWidget *w, Decoder *d) +Player::Player(QWidget *w, Decoder *d) { widget = w; decoder = d; - render.init(widget, WIDTH, HEIGHT);//widget->getWidth(), widget->getHeight() + render.init(widget, WIDTH, HEIGHT); 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(); + dv_set_quality(dvdecoder, DV_QUALITY_COLOR | DV_QUALITY_AC_1); + //dv_set_quality(dvdecoder, DV_QUALITY_BEST); } Player::~Player() @@ -64,26 +55,26 @@ Player::~Player() void Player::show_frame() { - uint8_t *frame; + Frame *frame; fprintf(stderr, "Frame!%d\n", num++); frame = decoder->getFrame(); - if(!frame) return; + if(first) { #ifdef COLORSPACE_YV12 - yuv[0] = yuv_buf; + yuv[0] = (unsigned char*)render.xvimage->data; 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; + yuv[0] = (unsigned char*)render.getDisplayData(); // Decode directly to the XVideo buffer pitches[0] = WIDTH * 2; #endif - dv_parse_header(dvdecoder, frame); + dv_parse_header(dvdecoder, frame->data); //dv_parse_packs(decoder, frame->data); // Not needed anyway! dvdecoder->system = e_dv_system_625_50; // PAL lines, PAL framerate @@ -94,347 +85,13 @@ void Player::show_frame() } dv_decode_full_frame(dvdecoder, - frame, + frame->data, 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; - } + render.width = widget->width(); + render.height = widget->height(); + render.display(WIDTH, HEIGHT); - /* 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 */ diff --git a/client/player.h b/client/player.h index d3db533..824e2c0 100644 --- a/client/player.h +++ b/client/player.h @@ -37,6 +37,7 @@ #include #include +//#include "libdv_wrapper.h" // Use libdv #include #include @@ -47,29 +48,23 @@ class Player : public QTimer { Q_OBJECT public: - Player(VideoWidget *widget, Decoder *decoder); + Player(QWidget *widget, Decoder *decoder); ~Player(); public slots: void show_frame(); private: - // dv1394 reader; - int pitches[3]; unsigned char* yuv[3]; + // LibDVWrapper dvdecoder; dv_decoder_t *dvdecoder; + Decoder *decoder; - VideoWidget *widget; + QWidget *widget; XvAccelRender render; - - Display *display; - Drawable drawable; - GC gc; - XvPortID port; - XGCValues values; }; #endif/*__MIAV_PLAYER_H__*/ diff --git a/client/xvaccelrenderer.cc b/client/xvaccelrenderer.cc index f030642..7de4510 100644 --- a/client/xvaccelrenderer.cc +++ b/client/xvaccelrenderer.cc @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** gui_xv.cpp - description ------------------- @@ -28,10 +29,6 @@ // Use this define for verbose output #define VERBOSE_XV - -//static uint8_t GUI_XvSync(void); - - //________________Wrapper around Xv_______________ XvAccelRender::XvAccelRender( void ) { @@ -57,14 +54,19 @@ uint8_t XvAccelRender::end(void) return 1; } -uint8_t XvAccelRender::display(uint8_t *ptr, uint32_t w, uint32_t h) +char *XvAccelRender::getDisplayData() +{ + if(xvimage) return xvimage->data; + else return NULL; +} + +uint8_t XvAccelRender::display(uint32_t w, uint32_t h) { - return GUI_XvDisplay(ptr, w, h); + return GUI_XvDisplay(w, h); } //________________Wrapper around Xv_______________ -//static uint8_t GUI_XvExpose( void ); // // Free all ressources allocated by xv // @@ -92,7 +94,7 @@ void XvAccelRender::GUI_XvEnd( void ) } //------------------------------------ -uint8_t XvAccelRender::GUI_XvDisplay(uint8_t * src, uint32_t w, uint32_t h) +uint8_t XvAccelRender::GUI_XvDisplay(uint32_t w, uint32_t h) { if (xvimage) @@ -102,7 +104,10 @@ uint8_t XvAccelRender::GUI_XvDisplay(uint8_t * src, uint32_t w, uint32_t h) // for YV12, 4 bits for Y 4 bits for u, 4 bits for v // total 1.5* - memcpy(xvimage->data, src, (w*h*3)>>1); + + // memcpy(xvimage->data, src, (w*h*3)>>1); + //memcpy(xvimage->data, src, (w*h*4)>>1); // We decodee directly to the buffer, so we don't need to copy it. + XLockDisplay (xv_display); // And display it ! #if 1 diff --git a/client/xvaccelrenderer.h b/client/xvaccelrenderer.h index 69745d6..3d70e91 100644 --- a/client/xvaccelrenderer.h +++ b/client/xvaccelrenderer.h @@ -1,4 +1,4 @@ -/* -*- mode: c++ -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ #ifndef __XVACCELRENDERER_H__ #define __XVACCELRENDERER_H__ @@ -31,16 +31,18 @@ public: XvAccelRender(); uint8_t init(QWidget *window, uint32_t w, uint32_t h); uint8_t end(void); - uint8_t display(uint8_t *ptr, uint32_t w, uint32_t h); + uint8_t display(uint32_t w, uint32_t h); unsigned int width, height; + char *getDisplayData(); + private: unsigned int xv_port; uint32_t xv_format; Display *xv_display; - XvImage *xvimage; - GC xv_gc; + XvImage *xvimage; + GC xv_gc; XGCValues xv_xgc; Window xv_win; XShmSegmentInfo Shminfo; @@ -48,7 +50,7 @@ private: uint8_t GUI_XvList(Display *dis, uint32_t port, uint32_t * fmt); uint8_t GUI_XvInit(QWidget *window, uint32_t w, uint32_t h); void GUI_XvEnd(); - uint8_t GUI_XvDisplay(uint8_t * src, uint32_t w, uint32_t h); + uint8_t GUI_XvDisplay(uint32_t w, uint32_t h); }; #endif/*__XVACCELRENDERER_H__*/ diff --git a/lib/Makefile.am b/lib/Makefile.am index f2293d1..6f01ef1 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -10,6 +10,7 @@ libmiav_la_SOURCES = \ info.cc \ info_simple.cc \ jpeg_mem_dest.cc \ + libdv_wrapper.cc \ miav_config.cc \ mutex.cc \ network.cc \ @@ -32,6 +33,7 @@ EXTRA_DIST = \ info.h \ info_simple.h \ jpeg_mem_dest.h \ + libdv_wrapper.h \ miav_config.h \ mutex.h \ network.h \ diff --git a/lib/frame.cc b/lib/frame.cc index 568c46b..caab521 100644 --- a/lib/frame.cc +++ b/lib/frame.cc @@ -34,11 +34,14 @@ Frame::Frame(unsigned char *d, int sz) { if(sz) data = new unsigned char[sz]; if(sz && d) memcpy(data, d, sz); + if(sz == 0 && d) data = d; size = sz; number = 0; memset(timecode, 0, sizeof(timecode)); endOfFrameStream = false; + + usage = 0; } Frame::~Frame() diff --git a/lib/frame.h b/lib/frame.h index 988f460..66c2ce7 100644 --- a/lib/frame.h +++ b/lib/frame.h @@ -28,12 +28,15 @@ #ifndef __FRAME_H__ #define __FRAME_H__ +#define START_USE_FRAME(x) x->usage++ +#define STOP_USE_FRAME(x) if(--x->usage == 0) delete x; x = NULL + // Definition of vector #include class Frame { public: - Frame(unsigned char *d, int sz); + Frame(unsigned char *d, int sz = 0); ~Frame(); unsigned char *data; @@ -51,6 +54,8 @@ public: char timecode[12]; bool endOfFrameStream; + + int usage; }; typedef std::vector< Frame* > FrameVector; -- cgit v1.2.3