diff options
Diffstat (limited to 'client/encoder.cc')
-rw-r--r-- | client/encoder.cc | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/client/encoder.cc b/client/encoder.cc new file mode 100644 index 0000000..e7b79bf --- /dev/null +++ b/client/encoder.cc @@ -0,0 +1,273 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * encoder.cc + * + * Tue Apr 19 12:10:34 CEST 2005 + * Copyright 2005 Bent Bisballe + * deva@aasimon.org + ****************************************************************************/ + +/* + * Originally from: + * RTVideoRec Realtime video recoder and encoder for Linux + * + * Copyright (C) 2004 B. Stultiens + * Copyright (C) 2004 Koen Otter and Glenn van der Meyden + */ + +/* + * 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 <config.h> +#ifdef USE_GUI + +#include "util.h" +#include "encoder.h" + +Encoder::Encoder(Info *ginfo, + const char *gip, + const int gport, + sem_t *gsem, + Queue<Frame> *gqueue, + pthread_mutex_t *gmutex, + volatile int *grunning) +{ + info = ginfo; + + strcpy(ip, gip); + port = gport; + memset(cpr, 0, sizeof(cpr)); + + sem = gsem; + queue = gqueue; + mutex = gmutex; + running = grunning; + + // record = 0; + + sem_init(&record_sem, 0, 0); + + s = NULL; + n = NULL; + + frozen = false; + + savestate_sent = false; + savestate = NO_CHANGE; + + // shoot_request = 0; + // shoot_value = 0; + // freeze_request = 0; + // freeze_value = 0; +} + + +Encoder::~Encoder() +{ + // If a hanging connection exists, we better close it. + /* // Already deleted in thread_main + if(s) { + if(n) delete n; + delete s; + s = NULL; + n = NULL; + } + */ +} + + +void Encoder::encode() +{ + Frame *frame; + + while(*running) { + sem_wait(sem); + + frame = queue->pop(); + + if(frame) { + if(frame->freeze == 1) frozen = true; + if(frame->freeze == -1) frozen = false; + if(frame->shoot) frozen = false; + + if(frame->record || + (frame->freeze == 1) || + frame->shoot) { + + // If no connection is present, make a new one + if(!s) { + s = new Socket(port, info); + s->sconnect(ip); + n = new Network(s, info); + } + + n_header h; + + if(savestate != NO_CHANGE) savestate_sent = true; + + h.header_type = DATA_HEADER; + sprintf(h.header.h_data.cpr, cpr); + h.header.h_data.freeze = frame->freeze; + h.header.h_data.snapshot = frame->shoot; + h.header.h_data.record = frame->record; + h.header.h_data.savestate = savestate;//NO_CHANGE; + h.header.h_data.mute = frame->mute; + + savestate = NO_CHANGE; // only transmit once! + + // if(freeze_request != freeze_value) freeze_value = freeze_request; + // if(shoot_request != shoot_value) shoot_value = shoot_request; + + n->sendPackage(&h, frame->data, frame->size); + } else { + // When frozen we need to preserve the connection in order to + // remember the frozen frame on the server side. + if(!frozen) { + // No data is to be sent, if we have a connection, destroy it. + if(s) { + if(n) delete n; + delete s; + s = NULL; + n = NULL; + } + } + } + + if(frame->shoot && !frozen && !frame->record) { + // FIXME: This is ugly! + // Bugfix... connection not cleared, when an 'unfrozen' snapshot is taken, + // and no recording is done. + if(s) { + if(n) delete n; + delete s; + s = NULL; + n = NULL; + } + } + + if(frame) delete frame; + } + } +} + + +void Encoder::setCpr(char *newcpr) +{ + strcpy(cpr, newcpr); +} + + +void Encoder::freeze() +{ + /* + if(!s) { + s = new Socket(port, errobj); + s->sconnect(ip); + n = new Network(s, errobj); + } + */ + // if(!errobj->hasError()) freeze_request = 1 - freeze_request; +} + + +/* + * shoot + * Set the shoot bit in the network header on the current frame. + * return the decodet (rgba) version af that frame, for thumbnail show. + */ +void Encoder::shoot() +{ + /* + if(!s) { + s = new Socket(port, errobj); + s->sconnect(ip); + n = new Network(s, errobj); + } + */ + // if(!errobj->hasError()) shoot_request = 1 - shoot_request; + // getScreenshot(rgb); +} + + +void Encoder::thread_main() +{ + encode(); + if(s) { + if(n) delete n; + delete s; + s = NULL; + n = NULL; + } + fprintf(stderr, "Encoder thread stopped.\n"); fflush(stderr); +} + + +void Encoder::start() +{ + savestate = NO_CHANGE; + savestate_sent = false; + /* + if(!s) { + s = new Socket(port, errobj); + s->sconnect(ip); + n = new Network(s, errobj); + } + */ + // if(!errobj->hasError()) record = 1; +} + + +void Encoder::stop(n_savestate save) +{ + savestate = save; + // Don't return until we are sure the savestate has been sent. + while(savestate_sent == false) { + // Just wait a while (in a while!) + sleep_0_2_frame(); + } +/* + struct timespec ts; + // TODO: set save state in package header. + + // Lock the queue and wait until all elements are sent on the network. + queue->lock(); + fprintf(stderr, "Emptying queue"); fflush(stderr); + while(queue->peek()) { + // Remove any late buffer + // We don't care, the encoder finishes them all + ts.tv_sec = 0; + ts.tv_nsec = 500000000L; // 100ms + fprintf(stderr, "."); fflush(stderr); + nanosleep(&ts, NULL); + } + fprintf(stderr, "done!\n"); fflush(stderr); + + record = 0; + + queue->unlock(); +*/ +/* + if(s) { + if(n) delete n; + delete s; + s = NULL; + n = NULL; + } +*/ +} + +#endif /*USE_GUI*/ |