summaryrefslogtreecommitdiff
path: root/miav/encoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'miav/encoder.cc')
-rw-r--r--miav/encoder.cc283
1 files changed, 283 insertions, 0 deletions
diff --git a/miav/encoder.cc b/miav/encoder.cc
new file mode 100644
index 0000000..61ec2d0
--- /dev/null
+++ b/miav/encoder.cc
@@ -0,0 +1,283 @@
+/* -*- 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;
+
+ if(n->sendPackage(&h, frame->data, frame->size) == -1) {
+ // An error on the network!
+ if(n) delete n;
+ delete s;
+ s = NULL;
+ n = NULL;
+
+ while( (frame = queue->pop()) ) delete frame; // Remove all frames
+ frame = NULL;
+ }
+ } 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*/