From 789ed99ffdeae638e9191ca99272e536f36f6934 Mon Sep 17 00:00:00 2001 From: deva Date: Tue, 29 Mar 2005 20:07:22 +0000 Subject: Added a lot of error detection stuff to the camera, player, encoder and decoder objects. --- src/camera.cc | 60 +++++++++++++++++++++++++++-------- src/camera.h | 1 + src/decoder.cc | 17 ++++++---- src/encoder.cc | 93 ++++++++++++++++++++++++++---------------------------- src/encoder.h | 5 ++- src/mainwindow.cc | 17 +++++++++- src/mainwindow.h | 1 + src/miav_config.cc | 4 --- src/network.cc | 39 ++++++++++++++++------- src/network.h | 4 ++- src/player.cc | 35 ++++++++++++++------ src/player.h | 9 +++++- src/socket.cc | 54 +++++++++++++++++++------------ src/socket.h | 7 ++-- 14 files changed, 226 insertions(+), 120 deletions(-) (limited to 'src') diff --git a/src/camera.cc b/src/camera.cc index 0ba3da9..9e9fd82 100644 --- a/src/camera.cc +++ b/src/camera.cc @@ -34,13 +34,14 @@ Camera::Camera() void Camera::connect(const char *ip, const int port) { errorstatus = new Error(); + initialized = false; pthread_mutex_init (&mutex, NULL); //mutex = PTHREAD_MUTEX_INITIALIZER; - + /* AVFormatContext *ifmtctx; AVFormatContext *ofmtctx; - + */ running = 1; int channel = 0; @@ -63,8 +64,10 @@ void Camera::connect(const char *ip, const int port) player_queue, &mutex, &running); - // ifmtctx = decoder->fc; - if(!decoder->fc) return; + if(errorstatus->hasError()) { + errorstatus->pushError("Camera initialization failed (decoder)."); + return; + } encoder = new Encoder(errorstatus, ip, port, @@ -72,17 +75,38 @@ void Camera::connect(const char *ip, const int port) encode_queue, &mutex, &running); - ofmtctx = encoder->fc; + if(errorstatus->hasError()) { + errorstatus->pushError("Camera initialization failed (encoder)."); + return; + } player = new Player(errorstatus, &running, &player_sem, player_queue, &mutex); + if(errorstatus->hasError()) { + errorstatus->pushError("Camera initialization failed (player)."); + return; + } pthread_create (&decodetid, NULL, thread_run, decoder); + if(errorstatus->hasError()) { + errorstatus->pushError("Camera initialization failed (decoder thread)."); + return; + } pthread_create (&encodetid, NULL, thread_run, encoder); + if(errorstatus->hasError()) { + errorstatus->pushError("Camera initialization failed (encoder thread)."); + return; + } pthread_create (&playertid, NULL, thread_run, player); + if(errorstatus->hasError()) { + errorstatus->pushError("Camera initialization failed (player thread)."); + return; + } + + initialized = true; } Camera::~Camera() @@ -110,36 +134,46 @@ Camera::~Camera() void Camera::setCpr(char *newcpr) { - encoder->setCpr(newcpr); + if(initialized) encoder->setCpr(newcpr); + else errorstatus->pushError("Camera not initialized."); + } void Camera::start() { - encoder->start(); + if(initialized) encoder->start(); + else errorstatus->pushError("Camera not initialized."); } void Camera::stop() { - encoder->stop(); + if(initialized) encoder->stop(); + else errorstatus->pushError("Camera not initialized."); } void Camera::freeze() { // FIXME: Ensure they freeze the same frame, i.e. the player - // shows the same frame that is actually fronzen on the server. - player->stop(); - encoder->freeze(); + // shows the same frame that is actually frozen on the server. + if(initialized) { + player->stop(); + encoder->freeze(); + } else { + errorstatus->pushError("Camera not initialized."); + } } void Camera::unfreeze() { - player->start(); + if(initialized) player->start(); + else errorstatus->pushError("Camera not initialized."); } void Camera::snapshot() { - encoder->shoot(); + if(initialized) encoder->shoot(); + else errorstatus->pushError("Camera not initialized."); } Error *Camera::errorObject() diff --git a/src/camera.h b/src/camera.h index 4f58d7e..25e1972 100644 --- a/src/camera.h +++ b/src/camera.h @@ -76,6 +76,7 @@ public: private: // Error object passed to all sub objects. Error *errorstatus; + bool initialized; pthread_t playertid; pthread_t decodetid; diff --git a/src/decoder.cc b/src/decoder.cc index dfddd87..bf9b75c 100644 --- a/src/decoder.cc +++ b/src/decoder.cc @@ -52,7 +52,8 @@ Decoder::Decoder(Error* err, if(!(iformat = av_find_input_format("dv1394"))) { errobj->pushError("Failed to get input format dv1394."); - exit(1); + fc = NULL; + return; } dvpars.device = device; /* "/dev/dv1394"; */ @@ -61,23 +62,27 @@ Decoder::Decoder(Error* err, if(av_open_input_file(&ifc, "", iformat, 0, &dvpars) < 0) { errobj->pushError("Device is in use."); - fc = NULL; return; + fc = NULL; + return; } if(av_find_stream_info(ifc) < 0) { errobj->pushError("Could not find enough parameters."); - fc = NULL; return; + fc = NULL; + return; } dump_format(ifc, 1, "", 0); if(!(dec_codec = avcodec_find_decoder(ifc->streams[0]->codec.codec_id))) { errobj->pushError("Unsupported codec for input stream."); - fc = NULL; return; + fc = NULL; + return; } if(avcodec_open(&ifc->streams[0]->codec, dec_codec) < 0) { errobj->pushError("Error while opening codec for input stream."); - fc = NULL; return; + fc = NULL; + return; } fc = ifc; @@ -126,7 +131,7 @@ void Decoder::decode() if(ret < 0) { errobj->pushError("Error while decoding stream."); - exit(1); + return; } len -= ret; diff --git a/src/encoder.cc b/src/encoder.cc index ee60a8f..fc19921 100644 --- a/src/encoder.cc +++ b/src/encoder.cc @@ -34,13 +34,10 @@ Encoder::Encoder(Error* err, { errobj = err; - sprintf(ip, gip); + strcpy(ip, gip); port = gport; memset(cpr, 0, sizeof(cpr)); - printf("[ip: %s]\n", ip); - printf("[port: %d]\n", port); - sem = gsem; queue = gqueue; mutex = gmutex; @@ -67,95 +64,93 @@ Encoder::~Encoder() } -void Encoder::setCpr(char *newcpr) -{ - sprintf(cpr, newcpr); -} - - void Encoder::encode() { DVFrame *f; + printf("0\n"); while(*running) { + printf("1\n"); sem_wait(sem); - /* + printf("2\n"); pthread_mutex_lock(mutex); - while((f = queue->pop())) delete f; + f = queue->pop(); pthread_mutex_unlock(mutex); - - while(record) { - sem_wait(sem); - */ + + printf("3\n"); + if((f && record) || + (freeze_request != freeze_value) || + (shoot_request != shoot_value)) { + n_header h; - pthread_mutex_lock(mutex); - f = queue->pop(); - pthread_mutex_unlock(mutex); + h.header_type = DATA_HEADER; + sprintf(h.header.h_data.cpr, cpr); + h.header.h_data.freeze = (freeze_request != freeze_value); + h.header.h_data.snapshot = (shoot_request != shoot_value); + h.header.h_data.record = record; + + if(freeze_request != freeze_value) freeze_value = freeze_request; + if(shoot_request != shoot_value) shoot_value = shoot_request; - if((f && record) || (freeze_request != freeze_value) || (shoot_request != shoot_value)) { - fprintf(stderr, "Rec!\n"); - n_header h; - - h.header_type = DATA_HEADER; - sprintf(h.header.h_data.cpr, cpr); - h.header.h_data.freeze = (freeze_request != freeze_value); - h.header.h_data.snapshot = (shoot_request != shoot_value); - h.header.h_data.record = record; - - if(freeze_request != freeze_value) freeze_value = freeze_request; - if(shoot_request != shoot_value) shoot_value = shoot_request; - - n->sendPackage(&h, f->frame, sizeof(f->frame)); - } - - if(f) delete f; - //} + n->sendPackage(&h, f->frame, sizeof(f->frame)); + } + + if(f) delete f; } pthread_exit(NULL); } + +void Encoder::setCpr(char *newcpr) +{ + strcpy(cpr, newcpr); +} + + void Encoder::freeze() { if(!s) { - s = new Socket(port); + s = new Socket(port, errobj); s->sconnect(ip); - n = new Network(s); + n = new Network(s, errobj); } - freeze_request = 1 - freeze_request; + if(!errobj->hasError()) freeze_request = 1 - freeze_request; } + void Encoder::shoot() { if(!s) { - s = new Socket(port); + s = new Socket(port, errobj); s->sconnect(ip); - n = new Network(s); + n = new Network(s, errobj); } - shoot_request = 1 - shoot_request; + if(!errobj->hasError()) shoot_request = 1 - shoot_request; } + void Encoder::run() { encode(); } + void Encoder::start() { - printf("GO!\n"); if(!s) { - s = new Socket(port); + s = new Socket(port, errobj); s->sconnect(ip); - n = new Network(s); + n = new Network(s, errobj); } - record = 1; + if(!errobj->hasError()) record = 1; } + void Encoder::stop() { - printf("STOP!\n"); + record = 0; if(s) { if(n) delete n; delete s; s = NULL; n = NULL; } - record = 0; } diff --git a/src/encoder.h b/src/encoder.h index 1b459b9..8a458c8 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -42,7 +42,10 @@ #define VIDEO_BUFFER_SIZE (1024*1024) - +/** + * This class contains code for sending the video stream and the snapshots + * over the network, to the MIaV server. + */ class Encoder : public Thread { public: Encoder(Error* err, diff --git a/src/mainwindow.cc b/src/mainwindow.cc index dc5b5e2..212dfe7 100644 --- a/src/mainwindow.cc +++ b/src/mainwindow.cc @@ -92,7 +92,8 @@ MainWindow::MainWindow( QWidget* parent, const char* name ) cam_error = camera->errorObject(); while(cam_error->hasError()) { - MessageBox(this, "", cam_error->popErrorString().c_str(), TYPE_OK, ICON_ERROR).exec(); + MessageBox(this, "", cam_error->popErrorString().c_str(), + TYPE_OK, ICON_ERROR).exec(); } recording = false; @@ -238,6 +239,14 @@ void MainWindow::cpr_clicked() } } +void MainWindow::checkErrors() +{ + while(cam_error->hasError()) { + MessageBox(this, "", cam_error->popErrorString().c_str(), + TYPE_OK, ICON_ERROR).exec(); + } +} + void MainWindow::rec_clicked() { recording = 1 - recording; @@ -245,10 +254,12 @@ void MainWindow::rec_clicked() img_recedge->setBackgroundColor(red); btn_rec->setPixmap(*pix_stop); camera->start(); + checkErrors(); } else { img_recedge->setBackgroundColor(QColor(160,160,160)); btn_rec->setPixmap(*pix_record); camera->stop(); + checkErrors(); } } @@ -257,6 +268,7 @@ void MainWindow::shoot_clicked() QImage image; camera->snapshot(); + checkErrors(); image = img_live->getScreenshot(); image = image.smoothScale(img_history[0]->width(), img_history[0]->height()); @@ -270,6 +282,7 @@ void MainWindow::shoot_clicked() if(frozen) { camera->unfreeze(); + checkErrors(); btn_freeze->setOn(false); frozen = false; } @@ -279,9 +292,11 @@ void MainWindow::freeze_clicked() { if(frozen) { camera->unfreeze(); + checkErrors(); frozen = false; } else { camera->freeze(); + checkErrors(); frozen = true; } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 88e924e..443ef83 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -60,6 +60,7 @@ public slots: void freeze_clicked(); private: + void checkErrors(); void createGui(); Camera *camera; diff --git a/src/miav_config.cc b/src/miav_config.cc index 05e0d06..1c2d0c6 100644 --- a/src/miav_config.cc +++ b/src/miav_config.cc @@ -75,20 +75,16 @@ _cfg *MiavConfig::addConfig(_cfg *parent, char* conf) _cfg *cfg; - printf("[%s]\n", conf); - cfg = (_cfg*) malloc(sizeof(_cfg)); if(!parent) configs = cfg; int namelen = strchr(conf, '=') - conf; char* name = (char*)calloc(namelen + 1, 1); strncpy(name, conf, namelen); - printf("name [%s]#%d - ", name, namelen); int vallen = conf + strlen(conf) - (strchr(conf, '=') + 1); char* val = (char*)calloc(vallen + 1, 1); strncpy(val, conf + strlen(conf) - vallen, vallen); - printf("val [%s]#%d\n", val, vallen); cfg->name = new string((const char*)name); free(name); diff --git a/src/network.cc b/src/network.cc index 8e99855..3c7fd7e 100644 --- a/src/network.cc +++ b/src/network.cc @@ -31,8 +31,9 @@ #include #include -Network::Network(Socket *gs) +Network::Network(Socket *gs, Error* err) { + error = err; s = gs; } @@ -43,14 +44,18 @@ Network::~Network() int Network::write(void *buf, int size) { if(!s->isConnected()) { - fprintf(stderr, "Write attempted to a socket not connected!\n"); + char errbuf[] = "Write attempted to a socket not connected!\0"; + if(error) error->pushError(errbuf); + else fprintf(stderr, errbuf); return 0; } int n = send(s->ssocket, buf, size, MSG_WAITALL); - if(n == -1) printf("An error occurred!\n"); - - // printf("Sent: %s\n", buf); + if(n == -1) { + char errbuf[] = "An error occurred!\0"; + if(error) error->pushError(errbuf); + else fprintf(stderr, errbuf); + } return n; } @@ -58,14 +63,18 @@ int Network::write(void *buf, int size) int Network::read(void *buf, int size) { if(!s->isConnected()) { - fprintf(stderr, "Read attempted from a socket not connected!\n"); + char errbuf[] = "Read attempted from a socket not connected!\0"; + if(error) error->pushError(errbuf); + else fprintf(stderr, errbuf); return 0; } int n = recv(s->ssocket, buf, size, MSG_WAITALL); - if(n == -1) printf("An error occurred!\n"); - - // printf("Recieved: %s\n", buf); + if(n == -1) { + char errbuf[] = "An error occurred!\0"; + if(error) error->pushError(errbuf); + else fprintf(stderr, errbuf); + } return n; } @@ -100,7 +109,9 @@ int Network::sendPackage(n_header *h, void* buf, int bufsz) int n = sendmsg(s->ssocket, &msg, 0); if(n < 0) { - perror("sendmsg"); + char errbuf[] = "A network error ocurred during sendPackage!\0"; + if(error) error->pushError(errbuf); + else perror(errbuf); return -1; } @@ -126,12 +137,16 @@ int Network::recvPackage(n_header *h, void* buf, int bufsz) int n = recvmsg(s->ssocket, &msg, MSG_WAITALL); if(n < 0) { - perror("recvmsg"); + char errbuf[] = "A network error ocurred during recvPackage!\0"; + if(error) error->pushError(errbuf); + else perror(errbuf); return -1; } if(msg.msg_iovlen != 2) { - fprintf(stderr, "Wrong package format!\n"); + char errbuf[] = "Wrong package format!\0"; + if(error) error->pushError(errbuf); + else perror(errbuf); return -1; } return n; diff --git a/src/network.h b/src/network.h index 72d5826..d1f68c0 100644 --- a/src/network.h +++ b/src/network.h @@ -29,10 +29,11 @@ #include "socket.h" #include "package.h" +#include "error.h" class Network { public: - Network(Socket *gs); + Network(Socket *gs, Error* err = NULL); ~Network(); // Raw communication @@ -44,6 +45,7 @@ public: int recvPackage(n_header *h, void* buf, int bufsz); private: + Error *error; Socket *s; }; diff --git a/src/player.cc b/src/player.cc index 85a961a..db5b108 100644 --- a/src/player.cc +++ b/src/player.cc @@ -31,6 +31,9 @@ Player::Player(Error *err, Queue *gqueue, pthread_mutex_t *gmutex) { + // No errors has ocurred... yet! + noErrors = true; + char errbuf[256]; errobj = err; @@ -42,28 +45,39 @@ Player::Player(Error *err, sem_init(&play_sem, 0, 1); if(SDL_Init(SDL_INIT_VIDEO) < 0) { - sprintf(errbuf, "Unable to init SDL: %s\n", SDL_GetError()); + sprintf(errbuf, "Unable to init SDL: %s.", SDL_GetError()); errobj->pushError(errbuf); + noErrors = false; return; } + screen = SDL_SetVideoMode(DISPLAYWIDTH, DISPLAYHEIGHT, - 16, - SDL_HWSURFACE|SDL_ANYFORMAT|SDL_HWACCEL); + 0, // 0 bpp means 'use current display depth' + SDL_HWSURFACE | SDL_ANYFORMAT | SDL_HWACCEL); + if(!screen) { - sprintf(errbuf, "Unable to set %dx%d video: %s\n", + sprintf(errbuf, "Unable to set %dx%d video: %s.", DISPLAYWIDTH, DISPLAYHEIGHT, SDL_GetError()); errobj->pushError(errbuf); + noErrors = false; return; } - overlay = SDL_CreateYUVOverlay(DISPLAYWIDTH, DISPLAYHEIGHT, SDL_IYUV_OVERLAY, screen); + overlay = SDL_CreateYUVOverlay(DISPLAYWIDTH, + DISPLAYHEIGHT, + SDL_IYUV_OVERLAY, screen); + if(!overlay) { + sprintf(errbuf, "Unable to create SDL overlay: %s.", SDL_GetError()); + errobj->pushError(errbuf); + noErrors = false; + return; + } } Player::~Player() { - if(overlay) - SDL_FreeYUVOverlay(overlay); + SDL_FreeYUVOverlay(overlay); SDL_Quit(); } @@ -76,8 +90,9 @@ void Player::player() int i; struct timespec ts; - // rect.x = 20; - // rect.y = 182; + if(!noErrors) return; // FIXME: Gracefully exit... + + // Setup the displayarea. rect.x = 0; rect.y = 0; rect.w = DISPLAYWIDTH; @@ -94,7 +109,7 @@ void Player::player() sem_wait(&play_sem); sem_post(&play_sem); - if(!SDL_WaitEvent(&event)) break; // FIXME: Gracefull exit... + if(!SDL_WaitEvent(&event)) break; // FIXME: Gracefully exit... switch(event.type) { case SDL_KEYDOWN: diff --git a/src/player.h b/src/player.h index 3e7efb6..2af4165 100644 --- a/src/player.h +++ b/src/player.h @@ -44,9 +44,13 @@ #include -#define DISPLAYWIDTH 720 /* FIXME: These numbers suck! */ +#define DISPLAYWIDTH 720 // FIXME: These numbers suck! #define DISPLAYHEIGHT 576 +/** + * This class contains the SDL code, for displaying the movie frames + * in the widget, using hardware overlay. + */ class Player : public Thread { public: Player(Error* err, @@ -66,6 +70,9 @@ private: void player(); + // Used to verify if errors ha ocurred previously. + bool noErrors; + volatile int *running; sem_t *sem; Queue *queue; diff --git a/src/socket.cc b/src/socket.cc index 7cee58a..851a6ea 100644 --- a/src/socket.cc +++ b/src/socket.cc @@ -26,33 +26,36 @@ #include "socket.h" -Socket::Socket() +Socket::Socket(Error* _err) { + error = _err; connected = false; err = 0; } -Socket::Socket(u_short port) +Socket::Socket(u_short port, Error* _err) { + error = _err; connected = false; err = 0; - // printf("Socket on port: %d\n", port); - // create socket - ssocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); // PF_INET: ipv4, PF_INET6: ipv6 - // tcp: IPPROTO_TCP - // upd: IPPROTO_UDP + ssocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + // PF_INET: ipv4, PF_INET6: ipv6 + // tcp: IPPROTO_TCP + // upd: IPPROTO_UDP + if (ssocket < 0) { err = 1; - perror("Socket: socket() failed"); + char errbuf[] = "Socket: socket() failed!\0"; + if(error) error->pushError(errbuf); + else perror(errbuf); } - socketaddr.sin_family = AF_INET; // Use "internet protocol" IP - socketaddr.sin_port = htons(port); // connect to that port - socketaddr.sin_addr.s_addr = INADDR_ANY;// INADDR_ANY puts your IP address automatically - - // fprintf(stderr, "Socket created\n"); + socketaddr.sin_family = AF_INET; // Use "internet protocol" IP + socketaddr.sin_port = htons(port); // connect to that port + socketaddr.sin_addr.s_addr = INADDR_ANY; + // INADDR_ANY puts your IP address automatically } @@ -69,7 +72,9 @@ Socket Socket::slisten() Socket s = Socket(); if(err) { - perror("Socket: No socket present"); + char errbuf[] = "Socket: No socket present!\0"; + if(error) error->pushError(errbuf); + else perror(errbuf); return s; } if(!connected) { @@ -81,10 +86,13 @@ Socket Socket::slisten() return s; } - // start listen for connection - kernel will accept connection requests (max 5 in queue) + // start listen for connection - kernel will accept connection + // requests (max 5 in queue) err = listen(ssocket, 5); if(err) { - perror("Socket: listen() failed"); + char errbuf[] = "Socket: listen() failed!\0"; + if(error) error->pushError(errbuf); + else perror(errbuf); return s; } } @@ -92,14 +100,18 @@ Socket Socket::slisten() // accept new connection and get its connection descriptor int csalen = sizeof(s.socketaddr); - s.ssocket = accept(ssocket, (struct sockaddr*)&s.socketaddr, (socklen_t*)&csalen); + s.ssocket = accept(ssocket, + (struct sockaddr*)&s.socketaddr, + (socklen_t*)&csalen); + if (s.ssocket < 0) { err = 1; - perror("Socket: accept() failed"); + char errbuf[] = "Socket: accept() failed!\0"; + if(error) error->pushError(errbuf); + else perror(errbuf); return s; } - fprintf(stderr, "Socket connected\n"); connected = true; s.connected = true; return s; @@ -119,7 +131,9 @@ int Socket::sconnect(char *ip) err = connect(ssocket, (struct sockaddr*)&socketaddr, sizeof(socketaddr)); if (err) { - perror("Socket: connect() failed"); + char errbuf[] = "Socket: connect() failed!\0"; + if(error) error->pushError(errbuf); + else perror(errbuf); return err; } // fprintf(stderr, "Socket connected\n"); diff --git a/src/socket.h b/src/socket.h index d0d85af..70dc7fe 100644 --- a/src/socket.h +++ b/src/socket.h @@ -36,10 +36,12 @@ #include #include +#include "error.h" + class Socket { public: - Socket(); - Socket(u_short port); + Socket(Error *_err = NULL); + Socket(u_short port, Error *_err = NULL); ~Socket(); Socket slisten(); int sconnect(char *ip); @@ -50,6 +52,7 @@ public: bool connected; private: + Error *error; int err; }; -- cgit v1.2.3