summaryrefslogtreecommitdiff
path: root/miavd
diff options
context:
space:
mode:
authordeva <deva>2008-03-17 09:10:42 +0000
committerdeva <deva>2008-03-17 09:10:42 +0000
commit2f10a73cbbe4333e2a41e87a94eda7fb3d442dc5 (patch)
treecc023927be890bb4880d6c97ddaf055041c512ea /miavd
parent6ae128fc80dd8a32ec6f062c7767ced32e9ba495 (diff)
Major code changes... FFMPEG introduced. Project splitup into subfolders.
Diffstat (limited to 'miavd')
-rw-r--r--miavd/Makefile.am26
-rw-r--r--miavd/daemon.cc118
-rw-r--r--miavd/daemon.h45
-rw-r--r--miavd/error.cc73
-rw-r--r--miavd/error.h32
-rw-r--r--miavd/ffframe.h64
-rw-r--r--miavd/ffmpeg_encoder.cc204
-rw-r--r--miavd/ffmpeg_encoder.h81
-rw-r--r--miavd/ffoutput.cc400
-rw-r--r--miavd/ffoutput.h78
-rw-r--r--miavd/format.h48
-rw-r--r--miavd/img_encoder.cc232
-rw-r--r--miavd/img_encoder.h62
-rw-r--r--miavd/info_console.cc101
-rw-r--r--miavd/info_console.h52
-rw-r--r--miavd/miav_daemon.cc109
-rw-r--r--miavd/miav_daemon.h42
-rw-r--r--miavd/miavd.cc47
-rw-r--r--miavd/multicast_configuration.cc141
-rw-r--r--miavd/multicast_configuration.h56
-rw-r--r--miavd/server.cc137
-rw-r--r--miavd/server.h37
-rw-r--r--miavd/stream.h61
23 files changed, 2246 insertions, 0 deletions
diff --git a/miavd/Makefile.am b/miavd/Makefile.am
new file mode 100644
index 0000000..2170717
--- /dev/null
+++ b/miavd/Makefile.am
@@ -0,0 +1,26 @@
+bin_PROGRAMS = miavd
+
+miavd_LDADD = ../libmiav/libmiav.la
+
+miavd_SOURCES = \
+ miavd.cc \
+ daemon.cc \
+ error.cc \
+ ffoutput.cc \
+ ffmpeg_encoder.cc \
+ img_encoder.cc \
+ info_console.cc \
+ miav_daemon.cc \
+ multicast_configuration.cc \
+ server.cc
+
+EXTRA_DIST = \
+ miavd.h \
+ daemon.h \
+ ffoutput.h \
+ ffmpeg_encoder.h \
+ img_encoder.h \
+ info_console.h \
+ miav_daemon.h \
+ multicast_configuration.h \
+ server.h
diff --git a/miavd/daemon.cc b/miavd/daemon.cc
new file mode 100644
index 0000000..6e46bd5
--- /dev/null
+++ b/miavd/daemon.cc
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * daemon.cc
+ *
+ * Thu Jun 9 10:27:59 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "daemon.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+
+// For getgrent and getgrent
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+
+// For strcmp
+#include <string.h>
+
+Daemon::Daemon()
+{}
+
+Daemon::~Daemon()
+{}
+
+int Daemon::run(const char *user, const char* group)
+{
+ int f;
+ int fd;
+
+ // Fetch user id
+ int uid = -1;
+ struct passwd *p = getpwent();
+ while(p) {
+ if(strcmp(p->pw_name, user) == 0) uid = p->pw_uid;
+ p = getpwent();
+ }
+ if(uid == -1) {
+ fprintf(stderr, "Could not find user \"%s\" in /etc/passwd file.\n", user);
+ }
+
+ // Fetch group id
+ int gid = -1;
+ struct group *g = getgrent();
+ while(g) {
+ if(strcmp(g->gr_name, group) == 0) gid = g->gr_gid;
+ g = getgrent();
+ }
+ if(gid == -1) {
+ fprintf(stderr, "Could not find group \"%s\" in /etc/group file.\n", group);
+ }
+
+ chdir("/");
+ umask(0);
+
+ f = fork();
+ switch(f) {
+ case -1: // Fork error
+ perror("Fork in daemon.cc");
+ return 1;
+
+ case 0: // Forked child
+ // Switch to given group
+ if(setgid(gid) != 0) {
+ fprintf(stderr, "Failed to change to group \"%s\" (gid: %d), quitting.\n", group, gid);
+ perror("");
+ fprintf(stderr, "Runnning daemon as current group\n");
+ }
+
+ // Switch to given user
+ if(setuid(uid) != 0) {
+ fprintf(stderr, "Failed to change to user \"%s\" (uid: %d), quitting.\n", user, uid);
+ perror("");
+ fprintf(stderr, "Runnning daemon as current user\n");
+ }
+
+ // Redirect stdin, stdout and stderr to /dev/null
+ fd = open("/dev/null", O_NOCTTY | O_RDWR, 0666);
+
+ dup2(0, fd);
+ dup2(1, fd);
+ dup2(2, fd);
+
+ setsid();
+
+ signal (SIGTERM, SIG_IGN);
+ signal (SIGINT, SIG_IGN);
+ signal (SIGHUP, SIG_IGN);
+
+ return daemon_main();
+
+ default: // Parent
+ // exit(0);
+ return 0;
+ }
+}
diff --git a/miavd/daemon.h b/miavd/daemon.h
new file mode 100644
index 0000000..1bd663e
--- /dev/null
+++ b/miavd/daemon.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * daemon.h
+ *
+ * Thu Jun 9 10:27:59 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This program 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.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DAEMON_H__
+#define __DAEMON_H__
+
+#include <sys/types.h>
+
+class Daemon {
+public:
+ Daemon();
+ virtual ~Daemon();
+
+ /**
+ * Use NOBODY_GROUP and NOBODY_USER if no privileges are needed to run.
+ */
+ int run(const char* user, const char* group);
+
+private:
+ virtual int daemon_main() = 0;
+};
+
+#endif/*__DAEMON_H__*/
diff --git a/miavd/error.cc b/miavd/error.cc
new file mode 100644
index 0000000..02843e3
--- /dev/null
+++ b/miavd/error.cc
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * error.cc
+ *
+ * Fri Dec 28 18:49:20 CET 2007
+ * Copyright 2007 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of FFMpegPP.
+ *
+ * FFMpegPP 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.
+ *
+ * FFMpegPP 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 FFMpegPP; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "error.h"
+extern "C" {
+#include <ffmpeg/avcodec.h>
+}
+#include <stdio.h>
+#include <errno.h>
+
+void error(int errval, char *where)
+{
+ printf("Error: ");
+
+ switch(-errval) {
+ case AVERROR_IO:
+ printf("I/O error");
+ break;
+
+ case AVERROR_NUMEXPECTED:
+ printf("Number syntax expected in filename.");
+ break;
+
+ case AVERROR_INVALIDDATA:
+ printf("Invalid data found.");
+ break;
+
+ case AVERROR_NOMEM:
+ printf("Not enough memory.");
+ break;
+
+ case AVERROR_NOFMT:
+ printf("Unknown format.");
+ break;
+
+ case AVERROR_NOTSUPP:
+ printf("Operation not supported.");
+ break;
+
+ case AVERROR_NOENT:
+ printf("No such file or directory.");
+ break;
+
+ default:
+ printf("Unknown error");
+ break;
+ }
+
+ printf(" in %s\n", where);
+}
diff --git a/miavd/error.h b/miavd/error.h
new file mode 100644
index 0000000..1c72862
--- /dev/null
+++ b/miavd/error.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * error.h
+ *
+ * Fri Dec 28 18:49:20 CET 2007
+ * Copyright 2007 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of FFMpegPP.
+ *
+ * FFMpegPP 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.
+ *
+ * FFMpegPP 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 FFMpegPP; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __FFMPEGPP_ERROR_H__
+#define __FFMPEGPP_ERROR_H__
+
+void error(int errval, char *where);
+
+#endif/*__FFMPEGPP_ERROR_H__*/
diff --git a/miavd/ffframe.h b/miavd/ffframe.h
new file mode 100644
index 0000000..fec820d
--- /dev/null
+++ b/miavd/ffframe.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * frame.h
+ *
+ * Fri Dec 28 18:09:04 CET 2007
+ * Copyright 2007 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of FFMpegPP.
+ *
+ * FFMpegPP 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.
+ *
+ * FFMpegPP 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 FFMpegPP; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __FFMPEGPP_FRAME_H__
+#define __FFMPEGPP_FRAME_H__
+
+extern "C" {
+#include <ffmpeg/avformat.h>
+#include <ffmpeg/avcodec.h>
+}
+
+#include "stream.h"
+
+class FFFrame {
+public:
+ FFFrame() {
+ avframe = NULL;
+ stream = NULL;
+ codec_context = NULL;
+ pts = 0;
+ dts = 0;
+ }
+
+ // The actual frame data.
+ AVFrame *avframe;
+
+ Stream *stream;
+
+ AVCodecContext *codec_context;
+
+ // Audio data
+ int16_t *pcmdata;
+ int pcmdatasize;
+
+ // Timecode
+ int64_t pts;
+ int64_t dts;
+
+};
+
+#endif/*__FFMPEGPP_FRAME_H__*/
diff --git a/miavd/ffmpeg_encoder.cc b/miavd/ffmpeg_encoder.cc
new file mode 100644
index 0000000..2f73c4c
--- /dev/null
+++ b/miavd/ffmpeg_encoder.cc
@@ -0,0 +1,204 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mov_encoder_thread.cc
+ *
+ * Tue May 17 16:00:01 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * 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 <config.h>
+#include "ffmpeg_encoder.h"
+#include <errno.h>
+#include "miav_config.h"
+#include <math.h>
+
+#include <ffmpeg/avcodec.h>
+#include <ffmpeg/avformat.h>
+
+#define AUDIO_BUFFER_SIZE DV_AUDIO_MAX_SAMPLES
+//(DV_AUDIO_MAX_SAMPLES * sizeof(int16_t))
+
+FFMpegEncoder::FFMpegEncoder(const char *clientip, const char *cpr)
+{
+ MIaV::info->info("FFMpegEncoder");
+
+ // init encoder
+ output = new FFOutput(cpr, clientip);
+
+ // Init DV decoder
+ avcodec_init();
+
+ // Video
+ dvvcodec = avcodec_find_decoder(CODEC_ID_DVVIDEO);
+ if(!dvvcodec) MIaV::info->error("Could not find DV Video codec.");
+
+ dvvcontext = avcodec_alloc_context();
+ if(avcodec_open(dvvcontext, dvvcodec) < 0) MIaV::info->error("Could not open DV Video codec.");
+
+ // Audio
+ dvacodec = avcodec_find_decoder(CODEC_ID_PCM_S16LE);
+ if(!dvacodec) MIaV::info->error("Could not find DV Audio codec.");
+
+ dvacontext = avcodec_alloc_context();
+ if(avcodec_open(dvacontext, dvacodec) < 0) MIaV::info->error("Could not open DV Audio codec.");
+
+ frame_number = 0;
+
+ audio_buffer[0] = (int16_t*)calloc(AUDIO_BUFFER_SIZE, sizeof(int16_t));
+ audio_buffer[1] = (int16_t*)calloc(AUDIO_BUFFER_SIZE, sizeof(int16_t));
+
+ sin_cnt = 0;
+ decoder = NULL;
+
+ // CBuffer init
+ cbufferdatasize = 0;
+ cbuffer_size = AUDIO_BUFFER_SIZE * 4; // Buffer max, 2 frames * 2 channels.
+ cbuffer = (int16_t *)malloc(cbuffer_size * sizeof(int16_t));
+ pbegin = 0;
+}
+
+//#include <unistd.h>
+FFMpegEncoder::~FFMpegEncoder()
+{
+ MIaV::info->info("~FFMpegEncoder...");
+
+ delete output;
+
+ free(audio_buffer[0]);
+ free(audio_buffer[1]);
+
+ free(cbuffer);
+ dv_decoder_free(decoder);
+
+ MIaV::info->info("~FFMpegEncoder::done");
+}
+
+void FFMpegEncoder::encode(Frame* frame)
+{
+ if(frame_number % 250 == 0)
+ MIaV::info->info("Got frame %d ...", frame_number);
+
+ if(frame == NULL) {
+ MIaV::info->info("FFMpegEncoder::encode - NULL frame detected.");
+ // Terminate
+ return;
+ }
+
+ if(frame->endOfFrameStream) {
+ // MIaV::info->info("endOfStream");
+ return;
+ }
+
+ frame->number = frame_number;
+
+#if 0
+ // Use to half the framerate.
+ if(frame_number % 2 == 0) {
+ frame_number ++;
+ return;
+ }
+#endif
+
+ //
+ // VIDEO
+ //
+ FFFrame *vfrm = new FFFrame();
+ vfrm->avframe = avcodec_alloc_frame();
+ vfrm->codec_context = dvvcontext;
+ int got_picture;
+ int pos = avcodec_decode_video(dvvcontext, vfrm->avframe, &got_picture, frame->data, frame->size);
+ if(!got_picture)
+ MIaV::info->warn("Decoding did not result in a picture!");
+ output->writeFrame(vfrm);
+
+ //
+ // AUDIO
+ //
+ FFFrame *afrm = new FFFrame();
+ afrm->pcmdatasize = output->audio_st->codec->frame_size * 2 * sizeof(int16_t);
+ afrm->pcmdata = (int16_t*)malloc(afrm->pcmdatasize);
+ //afrm->avframe = avcodec_alloc_frame();
+ afrm->codec_context = dvacontext;
+
+ if(frame->mute) {
+ // Overwrite audiobuffer with dummy data
+ double volume = 1000; // Min:= 0 - Max := 32000
+ double frequency = 440; // in Hz
+
+ for(int cnt = 0; cnt < 48000/25; cnt++) {
+ sin_cnt++;
+ double sin_val = (((double)sin_cnt / (double)48000) * (double)M_PI) * frequency;
+ audio_buffer[0][cnt] = audio_buffer[1][cnt] = (short int)(sin(sin_val) * volume);
+ }
+ } else {
+ // Decode audio from dv frame
+ if(!decoder) {
+ decoder = dv_decoder_new(FALSE, FALSE, FALSE);
+ decoder->quality = DV_QUALITY_BEST;
+
+ dv_parse_header(decoder, frame->data);
+
+ decoder->system = e_dv_system_625_50; // PAL lines, PAL framerate
+ decoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v
+ decoder->std = e_dv_std_iec_61834;
+ decoder->num_dif_seqs = 12;
+ }
+
+ // Decode audio using libdv
+ int frames = dv_decode_full_audio( decoder, frame->data, audio_buffer );
+
+ }
+
+ // Write new data to cbuffer
+ int pend = pbegin + cbufferdatasize;
+ for(int i = 0; i < (48000/25)*2; i++) {
+ cbuffer[(pend + i) % cbuffer_size] = audio_buffer[i%2][i/2];
+ }
+ cbufferdatasize += (48000/25)*2;
+
+ // Read out full ffmpeg frames from cbuffer.
+ while(cbufferdatasize >= output->audio_st->codec->frame_size * 2) {
+ for(int i = 0; i < output->audio_st->codec->frame_size * 2; i++) {
+ afrm->pcmdata[i] = cbuffer[(pbegin + i) % cbuffer_size];
+ }
+
+ cbufferdatasize -= output->audio_st->codec->frame_size * 2;
+ pbegin += output->audio_st->codec->frame_size * 2;
+
+ output->writeFrame(afrm);
+ }
+
+
+ frame_number ++;
+
+ av_free(vfrm->avframe);
+ delete vfrm;
+
+ free(afrm->pcmdata);
+ delete afrm;
+
+ delete frame;
+}
+
+void FFMpegEncoder::setSaveState(n_savestate savestate)
+{
+ output->setSaveState(savestate);
+}
diff --git a/miavd/ffmpeg_encoder.h b/miavd/ffmpeg_encoder.h
new file mode 100644
index 0000000..8a70521
--- /dev/null
+++ b/miavd/ffmpeg_encoder.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mov_encoder_thread.h
+ *
+ * Tue May 17 16:00:01 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * 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 "config.h"
+#ifndef __MIAV_FFMPEG_ENCODER_H__
+#define __MIAV_FFMPEG_ENCODER_H__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <vector>
+using namespace std;
+
+#include "frame.h"
+
+#include "ffoutput.h"
+
+#include "info.h"
+
+// For savestate_n
+#include "package.h"
+
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+
+class FFMpegEncoder {
+public:
+ FFMpegEncoder(const char *clientip, const char *cpr);
+ ~FFMpegEncoder();
+
+ void encode(Frame* frame);
+
+ void setSaveState(n_savestate savestate);
+
+private:
+ FFOutput *output;
+
+ AVCodec *dvvcodec;
+ AVCodecContext *dvvcontext;
+
+ AVCodec *dvacodec;
+ AVCodecContext *dvacontext;
+ int16_t *audio_buffer[2];
+
+ // Audio vars
+ int sin_cnt;
+ dv_decoder_t *decoder; // DV Audio Decoder
+ int cbufferdatasize;
+ int cbuffer_size;
+ int16_t *cbuffer;
+ int pbegin;
+
+ unsigned int frame_number;
+};
+
+#endif/*__MIAV_FFMPEG_ENCODER_H__*/
diff --git a/miavd/ffoutput.cc b/miavd/ffoutput.cc
new file mode 100644
index 0000000..963e694
--- /dev/null
+++ b/miavd/ffoutput.cc
@@ -0,0 +1,400 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * ffoutput.cc
+ *
+ * Fri Dec 28 18:09:18 CET 2007
+ * Copyright 2007 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 "ffoutput.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "miav_config.h"
+
+#define INDEX_PACKET_HEADER_SIZE 8192
+
+/*
+ * add a video output stream
+ */
+AVStream *FFOutput::add_video_stream(AVFormatContext *oc, CodecID codec_id)
+{
+ AVCodecContext *c;
+ AVStream *st;
+
+ int stream_id = 0;//av_find_default_stream_index(oc);
+ st = av_new_stream(oc, stream_id);
+ if (!st) {
+ MIaV::info->error("Could not alloc video stream");
+ }
+
+ AVCodec *codec = avcodec_find_encoder(codec_id);
+ if(!codec) {
+ MIaV::info->error("Could not find video encoder codec.");
+ }
+
+ AVFormatParameters parms;
+ parms.mpeg2ts_raw = 1;
+ parms.mpeg2ts_compute_pcr = 1;
+ if (av_set_parameters(oc, NULL) < 0) {
+ MIaV::info->error("Invalid output format parameters.");
+ }
+
+ // Get config values
+ int bitrate = config->readInt("video_bitrate");
+ int num_threads = config->readInt("encoding_threads");
+
+
+ c = st->codec;
+ c->codec_id = codec_id;
+ c->bit_rate = bitrate * 1000;
+ // c->width = 480; c->height = 320;
+ c->width = 720; c->height = 576;
+ c->time_base= (AVRational){1,25};
+ //c->time_base= (AVRational){2,25};
+ c->gop_size = 12; // Emit one intra frame every twelve frames at most.
+ c->pix_fmt = PIX_FMT_YUV420P; //NONE
+ c->codec_type = CODEC_TYPE_VIDEO;
+ c->max_b_frames = 0;
+ // c->flags2 |= CODEC_FLAG2_8X8DCT;
+ c->strict_std_compliance = FF_COMPLIANCE_VERY_STRICT;
+
+ c->debug = 0;
+ c->debug_mv = 0;
+
+ c->rtp_payload_size = 1500;
+ c->rtp_mode = 1;
+
+ c->thread_count = num_threads;
+
+ if(avcodec_open(c, codec) < 0) {
+ MIaV::info->error("Could not open video encoder codec.");
+ }
+
+ if(c->thread_count > 1) avcodec_thread_init(c, c->thread_count);
+
+ /* // Later version of ffmpeg
+ AVProgram *p = av_new_program(oc, stream_id);
+ p->provider_name = "Aasimon.org";
+ p->name = "MIaV";
+ */
+
+
+ snprintf(oc->title, 512, "MIaV");
+ snprintf(oc->author, 512, "Aasimon.org");
+ /*
+ char copyright[512];
+ char comment[512];
+ char album[512];
+ int year;
+ int track;
+ char genre[32];
+*/
+ return st;
+}
+
+
+/*
+ * add an audio output stream
+ */
+AVStream *FFOutput::add_audio_stream(AVFormatContext *oc, CodecID codec_id)
+{
+ AVCodecContext *c;
+ AVStream *st;
+
+ int stream_id = 0;//av_find_default_stream_index(oc);
+ st = av_new_stream(oc, stream_id + 1);
+ if (!st) {
+ MIaV::info->error("Could not alloc audio stream");
+ }
+
+ AVCodec *codec = avcodec_find_encoder(codec_id);
+ if(!codec) {
+ MIaV::info->error("Could not find audio encoder codec.");
+ }
+
+ // Get config values
+ int bitrate = config->readInt("audio_bitrate");
+
+ c = st->codec;
+ c->codec_id = codec_id;
+ c->codec_type = CODEC_TYPE_AUDIO;
+ c->bit_rate = bitrate * 1000;
+ c->sample_rate = 48000;
+ c->channels = 2;
+ c->sample_fmt = SAMPLE_FMT_S16;
+
+ c->debug = 0;
+
+ c->rtp_payload_size = 1500;
+ c->rtp_mode = 1;
+
+ if(avcodec_open(st->codec, codec) < 0) {
+ MIaV::info->error("Could not open audio encoder codec.");
+ }
+
+ return st;
+}
+
+FFOutput::FFOutput(const char *cpr, const char *clientip)
+{
+ avcodec_init();
+ av_register_all();
+
+ // Get filename
+ // Create path and filename
+ char fname[256];
+ string *server_root;
+ char birthmonth[3];
+ char date[32];
+
+ // Get server root
+ server_root = config->readString("server_movie_root");
+
+ // Copy the bytes representing the birth month from the cpr
+ // [dd][mm][yy]-[nn][nn]
+ strncpy(birthmonth, &cpr[2], 2);
+ birthmonth[2] = 0;
+
+ // Create date (today) in [yyyy][mm][dd]
+ struct tm *ltime;
+ time_t t = time(NULL);
+ ltime = localtime(&t);
+ sprintf(date, "%.4d%.2d%.2d",
+ ltime->tm_year + 1900,
+ ltime->tm_mon + 1, // Ranging from 0 to 11
+ ltime->tm_mday);
+
+ sprintf(fname, "%s/%s/%s/%s-%s-", server_root->c_str(), birthmonth, cpr, cpr, date);
+
+ file = new File(fname, "avi", MIaV::info);
+
+ open();
+
+ maxfilesize = -1;//10000000;
+}
+
+FFOutput::~FFOutput()
+{
+ MIaV::info->info("~FFOutput...");
+
+ close();
+
+ if(video_st->codec->thread_count > 1) avcodec_thread_free(video_st->codec);
+ if(net_video_st->codec->thread_count > 1) avcodec_thread_free(net_video_st->codec);
+
+ delete file;
+
+ MIaV::info->info("~FFOutput...done");
+}
+
+void FFOutput::open()
+{
+ enum CodecID vcodecid = CODEC_ID_H264;
+ enum CodecID acodecid = CODEC_ID_MP3;
+
+ //
+ // Output file
+ //
+
+ filename = file->Open();
+
+ oc = av_alloc_format_context();
+
+ oc->oformat = guess_format(NULL, filename.c_str(), NULL);
+ if (!oc->oformat) {
+ MIaV::info->error("guess_format failed on %s", filename.c_str());
+ }
+
+ video_st = add_video_stream(oc, vcodecid);
+ audio_st = add_audio_stream(oc, acodecid);
+
+ oc->flags |= AVFMT_FLAG_GENPTS;
+
+ // some formats want stream headers to be seperate
+ if(!strcmp(oc->oformat->name, "mp4")) {
+ // || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))
+ video_st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ }
+
+ // dump_format(oc, 0, filename.c_str(), 1);
+
+ // open the output file, if needed
+ if (!(oc->oformat->flags & AVFMT_NOFILE)) {
+ if (url_fopen(&(oc->pb), filename.c_str(), URL_WRONLY) < 0) {
+ MIaV::info->error("Could not open '%s': %s", filename.c_str(), strerror(errno));
+ }
+ }
+
+ av_write_header(oc);
+ keyframes = 0;
+ if(maxfilesize != -1) maxfilesize = maxfilesize - oc->pb.pos;
+
+
+ //
+ // RTSP
+ //
+
+ stream_oc = av_alloc_format_context();
+
+ char streamformat[] = "mpegts";//mpegts";//"m4v"; // "mpegts"; "rm";
+ stream_oc->oformat = guess_stream_format(streamformat, NULL, NULL);
+ if (!stream_oc->oformat) {
+ MIaV::info->error("guess_format failed on %s", streamformat);
+ }
+
+ net_video_st = add_video_stream(stream_oc, vcodecid);
+ net_audio_st = add_audio_stream(stream_oc, acodecid);
+
+ stream_oc->flags |= AVFMT_FLAG_GENPTS;
+
+ // open the output file, if needed
+ if (!(stream_oc->oformat->flags & AVFMT_NOFILE)) {
+ char streamname[] = "rtp://224.0.0.1:1234";
+ if (url_fopen(&(stream_oc->pb), streamname, URL_WRONLY) < 0) {
+ MIaV::info->error("Could not open '%s': %s", streamname, strerror(errno));
+ }
+ }
+ av_write_header(stream_oc);
+
+
+}
+
+void FFOutput::close()
+{
+ av_write_trailer(oc);
+ if (!(oc->oformat->flags & AVFMT_NOFILE)) {
+ url_fclose(&(oc->pb));
+ }
+
+ avcodec_close(audio_st->codec);
+ avcodec_close(video_st->codec);
+ av_free(oc);
+
+ av_write_trailer(stream_oc);
+ if (!(stream_oc->oformat->flags & AVFMT_NOFILE)) {
+ url_fclose(&(stream_oc->pb));
+ }
+
+ avcodec_close(net_audio_st->codec);
+ avcodec_close(net_video_st->codec);
+ av_free(stream_oc);
+}
+
+#ifndef INT64_C
+#define INT64_C(c) (c ## LL)
+#endif
+
+void FFOutput::writeFrame(FFFrame *frame)
+{
+ // return;
+ bit_buffer_size = 720*576*4;//video_st->codec->bit_rate * 1024 * 10;
+ bit_buffer = (uint8_t*)malloc(bit_buffer_size);
+
+ if( maxfilesize != -1 &&
+ oc->pb.pos + (keyframes * 170) + INDEX_PACKET_HEADER_SIZE > maxfilesize) { // Too big?
+ close();
+ open();
+ }
+
+ if(frame == NULL) return;
+ int ret = 0;
+ int stream_index = -1;
+ int64_t pts;
+ int64_t dts;
+ int pos = 0;
+
+
+ // printf("Now: %lld\n", av_gettime());
+ if(frame->pts == AV_NOPTS_VALUE) frame->pts = av_gettime();
+ if(frame->pts == 0) frame->pts = av_gettime();
+
+ switch(frame->codec_context->codec->type) {
+ case CODEC_TYPE_VIDEO:
+ stream_index = 0;
+ ret = avcodec_encode_video(net_video_st->codec,
+ bit_buffer,
+ bit_buffer_size,
+ frame->avframe);
+ pts = net_video_st->codec->coded_frame->pts;
+ //pts = vpts;
+ //vpts++;
+ break;
+
+ case CODEC_TYPE_AUDIO:
+ stream_index = 1;
+ ret = avcodec_encode_audio(net_audio_st->codec,
+ bit_buffer,
+ bit_buffer_size,
+ frame->pcmdata);
+ pts = net_audio_st->codec->coded_frame->pts;
+ // apts += 48000/25;
+ break;
+
+ default:
+ ret = 0;
+ break;
+ }
+
+ // printf("Now: %lld\n", av_gettime());
+ if(pts == AV_NOPTS_VALUE) pts = av_gettime();
+ if(pts == 0) pts = av_gettime();
+
+ if(ret > 0){
+ AVPacket *pkt = (AVPacket*)malloc(sizeof(AVPacket));
+ av_init_packet(pkt);
+
+ // dts = pts;
+ // dts++;
+
+ pkt->pts = pts;
+ pkt->dts = 0;//AV_NOPTS_VALUE;
+ pkt->stream_index = stream_index;
+ if(stream_index == 1) pkt->flags |= PKT_FLAG_KEY;
+
+ pkt->data = bit_buffer;
+ pkt->size = ret;
+
+ if(video_st->codec->coded_frame && video_st->codec->coded_frame->key_frame) {
+ pkt->flags |= PKT_FLAG_KEY;
+ keyframes++;
+ }
+
+ if (!(oc->oformat->flags & AVFMT_NOFILE)) {
+ av_interleaved_write_frame(oc, pkt);
+ //av_write_frame(oc, pkt);
+ }
+ if (!(stream_oc->oformat->flags & AVFMT_NOFILE)) {
+ av_interleaved_write_frame(stream_oc, pkt);
+ //av_write_frame(oc, pkt);
+ }
+ free(pkt->data);
+ free(pkt);
+ }
+}
+
+void FFOutput::setSaveState(n_savestate savestate)
+{
+ file->setSaveState(savestate);
+}
diff --git a/miavd/ffoutput.h b/miavd/ffoutput.h
new file mode 100644
index 0000000..ce4f83f
--- /dev/null
+++ b/miavd/ffoutput.h
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * ffoutput.h
+ *
+ * Fri Dec 28 18:09:17 CET 2007
+ * Copyright 2007 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.
+ */
+#ifndef __MIAV_FFOUTPUT_H__
+#define __MIAV_FFOUTPUT_H__
+
+extern "C" {
+#include <ffmpeg/avformat.h>
+#include <ffmpeg/avcodec.h>
+}
+
+#include "ffframe.h"
+#include "format.h"
+
+#include <string>
+#include <file.h>
+
+// For n_savestate
+#include "package.h"
+
+class FFOutput {
+public:
+ FFOutput(const char *cpr, const char *clientip);
+ ~FFOutput();
+
+ void writeFrame(FFFrame *frame);
+ void setSaveState(n_savestate savestate);
+
+ AVStream *audio_st;
+
+private:
+ void open();
+ void close();
+
+ std::string filename;
+ File *file;
+
+ AVStream *add_video_stream(AVFormatContext *oc, CodecID codec_id);
+ AVStream *add_audio_stream(AVFormatContext *oc, CodecID codec_id);
+
+ long long int maxfilesize;
+ unsigned int keyframes;
+
+ AVFormatContext *stream_oc;
+ AVFormatContext *oc;
+ AVStream *video_st;
+ // AVStream *audio_st;
+ AVStream *net_video_st;
+ AVStream *net_audio_st;
+
+ size_t bit_buffer_size;
+ uint8_t *bit_buffer;
+};
+
+#endif/*__MIAV_FFOUTPUT_H__*/
diff --git a/miavd/format.h b/miavd/format.h
new file mode 100644
index 0000000..722b6b7
--- /dev/null
+++ b/miavd/format.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * format.h
+ *
+ * Sat Dec 29 12:59:16 CET 2007
+ * Copyright 2007 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of FFMpegPP.
+ *
+ * FFMpegPP 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.
+ *
+ * FFMpegPP 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 FFMpegPP; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __FFMPEGPP_FORMAT_H__
+#define __FFMPEGPP_FORMAT_H__
+
+typedef enum {
+ FMT_MPEG4,
+ FMT_MPEG2,
+ FMT_MPEG1,
+ FMT_MJPEG,
+ FMT_H264
+} VFormat;
+
+typedef enum {
+ FMT_AAC,
+ FMT_MP3,
+ FMT_MP2,
+ FMT_PCM,
+ FMT_VORBIS,
+ FMT_AC3
+} AFormat;
+
+
+#endif/*__FFMPEGPP_FORMAT_H__*/
diff --git a/miavd/img_encoder.cc b/miavd/img_encoder.cc
new file mode 100644
index 0000000..b326749
--- /dev/null
+++ b/miavd/img_encoder.cc
@@ -0,0 +1,232 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * img_encoder.cc
+ *
+ * Mon Nov 15 19:45:07 CET 2004
+ * Copyright 2004 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 "img_encoder.h"
+#include <stdio.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <info.h>
+
+#include "debug.h"
+
+extern "C" {
+#include <jpeglib.h>
+}
+
+#include "jpeg_mem_dest.h"
+
+// Use libdv
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+
+ImgEncoder::ImgEncoder(const char* cpr)
+{
+ // Create path and filename
+ char filename[256];
+ string *server_root;
+ char birthmonth[3];
+ char date[32];
+ char encrypted_cpr[32];
+
+ // Get server root
+ server_root = config->readString("server_image_root");
+
+ // Copy the bytes representing the birth month from the cpr
+ // [dd][mm][yy]-[nn][nn]
+ strncpy(birthmonth, &cpr[2], 2);
+ birthmonth[2] = 0;
+
+ // Create date (today) in [yyyy][mm][dd]
+ struct tm *ltime;
+ time_t t = time(NULL);
+ ltime = localtime(&t);
+ sprintf(date, "%.4d%.2d%.2d",
+ ltime->tm_year + 1900,
+ ltime->tm_mon,
+ ltime->tm_mday);
+
+ // Create 'encrypted' cpr, reverse numbers, skip month, and subtract from 9
+ // [d1][d2][m1][m2][y1][y2]-[n1][n2][n3][n4]
+ // =>
+ // [9-n4][9-n3][9-n2][9-n1][9-y2][9-y1][9-d2][9-d1]
+ memset(encrypted_cpr, 0, sizeof(encrypted_cpr));
+ int p = strlen(cpr) - 1;
+ int cnt = 0;
+ while(p) {
+ encrypted_cpr[cnt] = cpr[p];
+ p--;
+ if(p == 2) p--;
+ if(cpr[p] == '-' || p == 3) p--;
+ cnt++;
+ }
+
+ sprintf(filename, "%s/%s/%s/%s-%s-", server_root->c_str(), birthmonth, encrypted_cpr, cpr, date);
+ char extension[] = "jpg";
+
+ //
+ // Open unique file.
+ //
+ fd = -1;
+ int num = 0;
+ char buf[512];
+
+ while(fd == -1 && num < 999) {
+ sprintf(buf, "%s%.3d.%s", filename, num, extension);
+
+ // Try to open exclusively, fails if file already exists.
+ fd = open(buf, O_CREAT | O_WRONLY | O_ASYNC | O_EXCL, //| O_LARGEFILE
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ if(fd == -1) {
+ switch(errno) {
+ case EEXIST:
+ num ++;
+ break;
+ default:
+ MIaV::info->error("Something is wrong with the path [%s] - %s!", filename, strerror(errno));
+ return;
+ }
+ }
+ }
+
+ MIaV::info->info("Writing screenshot to file: %s", buf);
+
+}
+
+
+ImgEncoder::~ImgEncoder()
+{
+ if(fd != -1) close(fd);
+}
+
+
+void ImgEncoder::encode(Frame *dvframe, int quality)
+{
+ unsigned char rgb[720*576*4];
+
+ getRGB(dvframe, rgb);
+ writeJPEGFile(quality, rgb, 720, 576);
+}
+
+
+void ImgEncoder::writeJPEGFile(int quality, unsigned char *rgb, int image_width, int image_height)
+{
+ JSAMPLE *image_buffer = (JSAMPLE*)rgb;
+
+ size_t buffersize = (image_width * image_height * 3) + JPEG_HEADER_PAD;
+ char *jpeg_output_buffer = new char [buffersize];
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
+ int row_stride; // physical row width in image buffer
+
+ // Allocate and initialize JPEG compression object
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ // Specify data destination (see jpeg_mem_dest)
+ jpeg_mem_dest(&cinfo, jpeg_output_buffer, &buffersize);
+
+ // Set compression parameters
+ cinfo.image_width = image_width; // image width and height, in pixels
+ cinfo.image_height = image_height;
+ cinfo.input_components = 3; // # of color components per pixel
+ cinfo.in_color_space = JCS_RGB; // colorspace of input image
+
+ jpeg_set_defaults(&cinfo);
+
+ jpeg_set_quality(&cinfo, quality, TRUE); // limit to baseline-JPEG values
+
+ // Start compressor
+ jpeg_start_compress(&cinfo, TRUE);
+
+ // While (scan lines remain to be written)
+ row_stride = image_width * 3; // JSAMPLEs per row in image_buffer
+
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+ (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+ // Finish compression
+ jpeg_finish_compress(&cinfo);
+
+ // Release JPEG compression object
+ jpeg_destroy_compress(&cinfo);
+
+ // MIaV::info->info("JPEG buffersize: %d", buffersize);
+
+ if(fd != -1) write(fd, jpeg_output_buffer, buffersize);
+
+ delete jpeg_output_buffer;
+}
+
+void ImgEncoder::getRGB(Frame *frame, unsigned char *rgb)
+{
+ unsigned char *pixels[3];
+ int pitches[3];
+
+ pixels[ 0 ] = rgb;
+ pixels[ 1 ] = NULL;
+ pixels[ 2 ] = NULL;
+
+ pitches[ 0 ] = 720 * 3;
+ pitches[ 1 ] = 0;
+ pitches[ 2 ] = 0;
+
+ dv_decoder_t *decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE);
+ decoder->quality = DV_QUALITY_BEST;
+
+ dv_parse_header(decoder, frame->data);
+
+ decoder->system = e_dv_system_625_50; // PAL lines, PAL framerate
+ decoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v
+ decoder->std = e_dv_std_iec_61834;
+ decoder->num_dif_seqs = 12;
+
+ // libdv img decode to rgb
+ dv_decode_full_frame(decoder,
+ frame->data,
+ e_dv_color_rgb,
+ pixels,
+ pitches);
+
+ dv_decoder_free(decoder);
+}
diff --git a/miavd/img_encoder.h b/miavd/img_encoder.h
new file mode 100644
index 0000000..9f722f4
--- /dev/null
+++ b/miavd/img_encoder.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * img_encoder.h
+ *
+ * Mon Nov 15 19:45:07 CET 2004
+ * Copyright 2004 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * Originally from:
+ * RTVideoRec Realtime video recoder and encoder for Linux
+ *
+ * Copyright (C) 2004 B. Stultiens
+ */
+
+/*
+ * 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"
+#ifndef __RTVIDEOREC_IMGENCODER_H
+#define __RTVIDEOREC_IMGENCODER_H
+
+#include <stdio.h>
+
+#include "frame.h"
+#include "util.h"
+
+#define VIDEO_BUFFER_SIZE (1024*1024) // FIXME: One size fits all...
+#define JPEG_HEADER_PAD 500
+
+class ImgEncoder {
+public:
+ ImgEncoder(const char* cpr);
+ ~ImgEncoder();
+ void encode(Frame *frame, int quality);
+ void writeJPEGFile(int quality,
+ unsigned char *image_buffer, // Points to large array of R,G,B-order data
+ int image_width, // Number of columns in image
+ int image_height); // Number of rows in image
+
+private:
+ int fd;
+ void getRGB(Frame *frame, unsigned char *rgb);
+};
+
+#endif /*__RTVIDEOREC_IMGENCODER_H*/
+
diff --git a/miavd/info_console.cc b/miavd/info_console.cc
new file mode 100644
index 0000000..ce406fb
--- /dev/null
+++ b/miavd/info_console.cc
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * info_console.cc
+ *
+ * Tue May 3 09:35:03 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * 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 <config.h>
+#include "info_console.h"
+
+#include "miav_config.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+InfoConsole::InfoConsole(MiavConfig *c): Info()
+{
+ this->config = c;
+ log_filename = *(this->config->readString("server_log_file"));
+}
+
+InfoConsole::~InfoConsole()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+void InfoConsole::error(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ // fprintf(stderr, "Error: ["); vfprintf(stderr, fmt, argp); fprintf(stderr, "]\n"); fflush(stderr);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ log("Error: %s", buf);
+}
+
+void InfoConsole::warn(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ // fprintf(stderr, "Warning: ["); vfprintf(stderr, fmt, argp); fprintf(stderr, "]\n"); fflush(stderr);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ log("Warning: %s", buf);
+}
+
+void InfoConsole::info(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ // fprintf(stderr, "Info: ["); vfprintf(stderr, fmt, argp); fprintf(stderr, "]\n"); fflush(stderr);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ log("Info: %s", buf);
+}
diff --git a/miavd/info_console.h b/miavd/info_console.h
new file mode 100644
index 0000000..43bb435
--- /dev/null
+++ b/miavd/info_console.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * info_console.h
+ *
+ * Tue May 3 09:35:03 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * 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 "config.h"
+#ifndef __MIAV_INFO_CONSOLE_H__
+#define __MIAV_INFO_CONSOLE_H__
+
+#include "info.h"
+
+#include "miav_config.h"
+
+#include <pthread.h>
+#include <semaphore.h>
+
+#include <string>
+using namespace std;
+
+class InfoConsole: public Info {
+public:
+ InfoConsole(MiavConfig *config);
+ ~InfoConsole();
+
+ void error(char* fmt, ...);
+ void warn(char* fmt, ...);
+ void info(char* fmt, ...);
+
+};
+
+#endif/*__MIAV_INFO_CONSOLE_H__*/
diff --git a/miavd/miav_daemon.cc b/miavd/miav_daemon.cc
new file mode 100644
index 0000000..7f32436
--- /dev/null
+++ b/miavd/miav_daemon.cc
@@ -0,0 +1,109 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * miav_daemon.cc
+ *
+ * Thu Jun 9 11:14:19 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * 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 <config.h>
+#include "miav_daemon.h"
+
+#include "info_console.h"
+#include "miav_config.h"
+
+#include "server.h"
+#include "socket.h"
+
+#include <signal.h>
+#include <errno.h>
+
+MiavDaemon::MiavDaemon()
+{}
+
+MiavDaemon::~MiavDaemon()
+{}
+
+int MiavDaemon::daemon_main()
+{
+ MiavConfig cfg(ETC"/miav.conf", NULL);
+ InfoConsole info(&cfg);
+ MIaV::setInfo(&info);
+ config = new MiavConfig(ETC"/miav.conf", &info);
+
+ int port = config->readInt("server_port");
+ pid_t childpid; // variable to store the child's pid
+
+ signal(SIGCLD, SIG_IGN); // Ved SIGCHILD til IGNORE maa wait/waitpid ikke kaldes
+ // (ellers kommer der kernel-brok)
+
+ info.info("Starting MIaV server v. %s", VERSION);
+ info.info("Listening on port %d", port);
+ Socket *socket = new Socket(port, &info);
+
+ if(socket->hasError()) {
+ info.error("Listening socket has errors, quitting.");
+ delete socket;
+ return 1;
+ }
+
+ while(1) {
+ Socket *csocket = new Socket(socket->slisten());
+
+ if(socket->hasError()) {
+ info.error("Server socket has errors, quitting.");
+ delete csocket;
+ break;
+ }
+
+ if(csocket->hasError()) {
+ info.error("Child socket has errors, quitting.");
+ delete csocket;
+ break;
+ }
+
+ if(!csocket->isConnected()) {
+ info.error("Child socket is not connected, quitting.");
+ delete csocket;
+ break;
+ }
+
+ childpid = fork();
+
+ switch(childpid) {
+ case -1: // fork() returns -1 on failure
+ info.log("Fork error: %s", strerror(errno));
+ exit(1);
+ case 0: // fork() returns 0 to the child process
+ delete socket; // Close listen socket.
+ newConnection(csocket);
+ delete csocket; // Close communication socket.
+ exit(0);
+
+ default: // fork() returns new pid to the parent process
+ break;
+ }
+ }
+
+ delete socket;
+ return 0;
+}
+
diff --git a/miavd/miav_daemon.h b/miavd/miav_daemon.h
new file mode 100644
index 0000000..6ab469e
--- /dev/null
+++ b/miavd/miav_daemon.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * miav_daemon.h
+ *
+ * Thu Jun 9 11:14:19 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * 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 "config.h"
+#ifndef __MIAV_MIAV_DAEMON_H__
+#define __MIAV_MIAV_DAEMON_H__
+
+#include "daemon.h"
+
+class MiavDaemon: public Daemon {
+public:
+ MiavDaemon();
+ ~MiavDaemon();
+
+private:
+ int daemon_main();
+};
+
+#endif/*__MIAV_MIAV_DAEMON_H__*/
diff --git a/miavd/miavd.cc b/miavd/miavd.cc
new file mode 100644
index 0000000..29c02f2
--- /dev/null
+++ b/miavd/miavd.cc
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * miav.cc
+ *
+ * Sat Aug 21 17:32:24 2004
+ * Copyright 2004 deva
+ * 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 <config.h>
+
+#include "miav_daemon.h"
+
+#include "miav_config.h"
+
+#include "info_console.h"
+
+#include <stdio.h>
+
+int main(int argc, char *argv[])
+{
+ MiavDaemon daemon;
+
+ MiavConfig cfg(ETC"/miav.conf", NULL);
+
+ string *user = cfg.readString("server_user");
+ string *group = cfg.readString("server_group");
+
+ return daemon.run(user->c_str(), group->c_str());
+}
diff --git a/miavd/multicast_configuration.cc b/miavd/multicast_configuration.cc
new file mode 100644
index 0000000..969faca
--- /dev/null
+++ b/miavd/multicast_configuration.cc
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multicast_configuration.cc
+ *
+ * Wed Oct 12 10:12:11 CEST 2005
+ * Copyright 2005 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 "config.h"
+#include "multicast_configuration.h"
+
+MulticastConfiguration::MulticastConfiguration(Info *info, char *file)
+ : MiavConfig(file, info)
+{
+ mcastconf_t conf;
+
+ // Create the default values.
+ global_conf.addr = "224.0.0.1";
+ global_conf.port = 1234;
+ global_conf.enabled = false;
+ global_conf.with_audio = false;
+
+ bool global = true;
+
+ _cfg *cfg = configs;
+
+ // Build the client list
+ while(cfg) {
+ if(strcmp(cfg->name->c_str(), "client") == 0) {
+ if(!global) confs.push_back(conf);
+
+ // Reset the configuration to the defaults
+ conf.client = *(cfg->stringval);
+ conf.addr = global_conf.addr;
+ conf.port = global_conf.port;
+ conf.enabled = global_conf.enabled;
+ conf.with_audio = global_conf.with_audio;
+
+ global = false;
+ }
+ if(strcmp(cfg->name->c_str(), "address") == 0) {
+ if(global) global_conf.addr = *(cfg->stringval);
+ else conf.addr = *(cfg->stringval);
+ }
+ if(strcmp(cfg->name->c_str(), "port") == 0) {
+ if(global) global_conf.port = cfg->intval;
+ else conf.port = cfg->intval;
+ }
+ if(strcmp(cfg->name->c_str(), "enabled") == 0) {
+ if(global) global_conf.enabled = cfg->boolval;
+ else conf.enabled = cfg->boolval;
+ }
+ if(strcmp(cfg->name->c_str(), "with_audio") == 0) {
+ if(global) global_conf.with_audio = cfg->boolval;
+ else conf.with_audio = cfg->boolval;
+ }
+ cfg = cfg->next;
+ }
+ if(!global) confs.push_back(conf);
+
+ // Show the configuration in the log file .
+ info->info("Global - Enabled: %s - Addr: %s - Port: %d - WithAudio: %s",
+ global_conf.enabled?"Yes\0":"No\0",
+ global_conf.addr.c_str(),
+ global_conf.port,
+ global_conf.with_audio?"Yes\0":"No\0");
+
+ for(unsigned int cnt = 0; cnt < confs.size(); cnt++) {
+ info->info("Client: %s - Enabled: %s - Addr: %s - Port: %d - WithAudio: %s",
+ confs[cnt].client.c_str(),
+ confs[cnt].enabled?"Yes\0":"No\0",
+ confs[cnt].addr.c_str(),
+ confs[cnt].port,
+ confs[cnt].with_audio?"Yes\0":"No\0");
+ }
+
+ info->info("Chosing:");
+}
+
+MulticastConfiguration::~MulticastConfiguration()
+{
+}
+
+mcastconf_t &MulticastConfiguration::getConf(char *client)
+{
+ for(unsigned int cnt = 0; cnt < confs.size(); cnt++) {
+ if(strcmp(confs[cnt].client.c_str(), client) == 0)
+ return confs[cnt];
+ }
+
+ return global_conf;
+}
+
+#ifdef __TEST_MULTICAST_CONFIGURATION
+#include "info_simple.h"
+
+int main(int argc, char *argv[]) {
+ if(argc < 2) {
+ fprintf(stderr, "usage:\n\t%s [filename]\n", argv[0]);
+ return 1;
+ }
+
+ InfoSimple info;
+ MulticastConfiguration conf(&info, argv[1]);
+
+ mcastconf_t mcconf = conf.getConf("192.168.0.11");
+
+ info.warn("Client: %s - Enabled: %s - Addr: %s - Port: %d",
+ mcconf.client.c_str(),
+ mcconf.enabled?"Yes\0":"No\0",
+ mcconf.addr.c_str(),
+ mcconf.port);
+
+ mcconf = conf.getConf("192.168.0.0");
+
+ info.warn("Client: %s - Enabled: %s - Addr: %s - Port: %d",
+ mcconf.client.c_str(),
+ mcconf.enabled?"Yes\0":"No\0",
+ mcconf.addr.c_str(),
+ mcconf.port);
+}
+
+#endif/* __TEST_MULTICAST_CONFIGURATION*/
diff --git a/miavd/multicast_configuration.h b/miavd/multicast_configuration.h
new file mode 100644
index 0000000..3fa7ef1
--- /dev/null
+++ b/miavd/multicast_configuration.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multicast_configuration.h
+ *
+ * Wed Oct 12 10:12:11 CEST 2005
+ * Copyright 2005 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 "config.h"
+#ifndef __MIAV_MULTICAST_CONFIGURATION_H__
+#define __MIAV_MULTICAST_CONFIGURATION_H__
+
+#include "miav_config.h"
+
+#include <vector>
+#include <string>
+
+typedef struct {
+ std::string client;
+ std::string addr;
+ bool enabled;
+ int port;
+ bool with_audio;
+} mcastconf_t;
+
+class MulticastConfiguration : private MiavConfig {
+public:
+ MulticastConfiguration(Info *info, char *file);
+ ~MulticastConfiguration();
+
+ mcastconf_t &getConf(char *client);
+
+private:
+ std::vector<mcastconf_t> confs;
+ mcastconf_t global_conf;
+};
+
+#endif/*__MIAV_MULTICAST_CONFIGURATION_H__*/
diff --git a/miavd/server.cc b/miavd/server.cc
new file mode 100644
index 0000000..9180c3d
--- /dev/null
+++ b/miavd/server.cc
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * server.cc
+ *
+ * Mon Nov 8 11:35:01 CET 2004
+ * Copyright 2004 Bent Bisballe
+ * 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 "server.h"
+#include "miav.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+// For mkdir
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// For unlink
+#include <unistd.h>
+
+// For errno
+#include <errno.h>
+
+// For inet_ntoa
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "miav_config.h"
+
+#include "img_encoder.h"
+
+#include "server_status.h"
+
+#include "ffmpeg_encoder.h"
+
+#include "dv.h"
+
+void newConnection(Socket *socket)
+{
+ char cpr[256];
+ char clientip[64];
+ bool hasCpr = false;
+ ServerStatus status(MIaV::info);
+
+ n_savestate savestate = LATER;
+ n_header h;
+ Frame *frame;
+ Frame *freeze_frame = NULL;
+ FFMpegEncoder *enc = NULL;
+
+ frame = new Frame(NULL, DVPACKAGE_SIZE);
+
+ MIaV::info->info("CONNECTION OPENED");
+ MIaV::info->info("New connection (%s)", inet_ntoa(socket->socketaddr.sin_addr));
+
+ sprintf(clientip, "%s", inet_ntoa(socket->socketaddr.sin_addr));
+
+ Network network = Network(socket, MIaV::info);
+ while(int ret = network.recvPackage(&h, frame->data, frame->size)) {
+ status.checkPoint();
+
+ if(ret == -1) {
+ MIaV::info->error("A network error ocurred, terminating session");
+ break;
+ }
+
+ frame->mute = h.header.h_data.mute;
+
+ if(!hasCpr) {
+ sprintf(cpr, h.header.h_data.cpr);
+ hasCpr = true;
+ }
+
+ if(h.header.h_data.snapshot) {
+ if(freeze_frame) {
+ ImgEncoder(cpr).encode(freeze_frame, 100);
+ delete freeze_frame;
+ freeze_frame = NULL;
+ } else {
+ ImgEncoder(cpr).encode(frame, 100);
+ }
+ }
+
+ if(h.header.h_data.savestate != NO_CHANGE) {
+ savestate = h.header.h_data.savestate;
+ MIaV::info->info("GOT SAVESTATE FROM NETWORK: %d", savestate );
+ }
+
+ if(h.header.h_data.freeze) {
+ if(freeze_frame) delete freeze_frame;
+ // copy the frame into another temporary one.
+ freeze_frame = new Frame(frame->data, frame->size);
+ }
+
+ // This one must be last!
+ if(h.header.h_data.record) {
+ if(!enc) enc = new FFMpegEncoder(clientip, cpr);
+ enc->encode(frame);
+ }
+
+ frame = new Frame(NULL, DVPACKAGE_SIZE);
+ }
+
+ MIaV::info->info("Closing connection...");
+
+ // No encoder exists, if this is a pure snapshot (image) connection.
+ if(enc) {
+ enc->setSaveState(savestate);
+ // Send end of stream frame.
+ frame->endOfFrameStream = true;
+ enc->encode(frame);
+
+ delete enc;
+ }
+
+ MIaV::info->info("CONNECTION CLOSED");
+}
diff --git a/miavd/server.h b/miavd/server.h
new file mode 100644
index 0000000..38015ba
--- /dev/null
+++ b/miavd/server.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * server.h
+ *
+ * Mon Nov 8 11:35:01 CET 2004
+ * Copyright 2004 Bent Bisballe
+ * 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.
+ */
+#ifndef __SERVER_H__
+#define __SERVER_H__
+
+#include "socket.h"
+
+#include "info.h"
+
+void newConnection(Socket *s);
+
+
+#endif/*__SERVER_H__*/
diff --git a/miavd/stream.h b/miavd/stream.h
new file mode 100644
index 0000000..a929243
--- /dev/null
+++ b/miavd/stream.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * stream.h
+ *
+ * Sun Dec 30 10:37:31 CET 2007
+ * Copyright 2007 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of FFMpegPP.
+ *
+ * FFMpegPP 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.
+ *
+ * FFMpegPP 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 FFMpegPP; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __FFMPEGPP_STREAM_H__
+#define __FFMPEGPP_STREAM_H__
+
+extern "C" {
+#include <ffmpeg/avformat.h>
+#include <ffmpeg/avcodec.h>
+}
+
+#include <map>
+
+class Stream {
+public:
+ Stream() {
+ stream = NULL;
+ codec_context = NULL;
+ codec = NULL;
+ index = -1;
+ unknown_stream = true;
+ }
+
+ // Information about the stream.
+ AVStream *stream;
+ int index;
+
+ bool unknown_stream;
+
+ // The codec context and its codec, needed to decode this stream.
+ AVCodecContext *codec_context;
+ AVCodec *codec;
+};
+
+typedef std::map< int, Stream* > Streams;
+
+
+#endif/*__FFMPEGPP_STREAM_H__*/