summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2005-07-02 11:39:51 +0000
committerdeva <deva>2005-07-02 11:39:51 +0000
commit91e9b782cc9ea0252ab2b211b15e8da4a3043d5f (patch)
tree335f800ae82b1385b6eb635d34ccc4a84be0a2d9
parent55c83847016699a18006f9f728076ab9cd2d873b (diff)
Added some audiocode.
Moved libfame code out of mov_encoder
-rw-r--r--ChangeLog11
-rw-r--r--Makefile.am4
-rw-r--r--TODO8
-rw-r--r--configure.in15
-rw-r--r--etc/miav.conf3
-rw-r--r--man/miav.conf.17
-rw-r--r--man/miav.conf.57
-rw-r--r--src/Makefile.am4
-rw-r--r--src/libfame_wrapper.cc265
-rw-r--r--src/libfame_wrapper.h80
-rw-r--r--src/liblame_wrapper.cc158
-rw-r--r--src/liblame_wrapper.h77
-rw-r--r--src/miav_config.cc489
-rw-r--r--src/miav_config.h42
-rw-r--r--src/mov_encoder.cc251
-rw-r--r--src/mov_encoder.h35
-rw-r--r--src/mov_encoder_thread.cc6
17 files changed, 1061 insertions, 401 deletions
diff --git a/ChangeLog b/ChangeLog
index bf6247d..6e8cb94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,17 @@
Changelog for MIaV
=======================================
+Juli XX 2005 - MIaV version 0.2.7
+---------------------------------------
+New Features:
+ - Config file parser now reports line numbers when errors occure.
+ - Config file parser now destincts bewteen types.
+ - Man pages have been written.
+ - Added server_image_root and server_movie_root to the config file.
+ - Added 'encrypted' filenames for the image files.
+Bug Fixes:
+
+=======================================
Juni 19 2005 - MIaV version 0.2.6
---------------------------------------
New Features:
diff --git a/Makefile.am b/Makefile.am
index fae527d..3db006e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,3 @@
AUTOMAKE_OPTIONS = gnu
-SUBDIRS = pixmaps tools src etc
-DISTDIRS = pixmaps tools src etc
+SUBDIRS = pixmaps tools src etc man
+DISTDIRS = pixmaps tools src etc man
diff --git a/TODO b/TODO
index ae2ec10..365e5d2 100644
--- a/TODO
+++ b/TODO
@@ -126,7 +126,8 @@ Main:
==========================================================================
Man pages:
- [ ] - Write man page for 'miav'
+ [x] - Write man page for 'miav'
+ [x] - Write man page for 'miav.conf'
Makesystem:
[x] - "Port" to automake/autoconf
@@ -143,9 +144,10 @@ Makesystem:
MiavConfig:
[x] - Integrate file parser.
[x] - Use error object.
- [ ] - Make code for input validity test.
+ [x] - Make code for input validity test.
[x] - Initialize one global configuration object.
- [ ] - BUG: Parse error when string occur with length 1
+ [x] - BUG: Parse error when string occur with length 1
+ [x] - Test it.
ErrorObject:
[x] - Make it.
diff --git a/configure.in b/configure.in
index cf3ca88..921802d 100644
--- a/configure.in
+++ b/configure.in
@@ -1,6 +1,6 @@
# Filename: configure.in
AC_INIT(src/miav.cc)
-AM_INIT_AUTOMAKE( miav, 0.2.6 )
+AM_INIT_AUTOMAKE( miav, 0.2.7 )
AC_PROG_CXX
@@ -61,8 +61,14 @@ AC_CHECK_LIB(jpeg, jpeg_start_compress, , AC_MSG_ERROR([*** libJpeg not found!]
dnl ======================
dnl Check for Fame library
dnl ======================
-AC_CHECK_HEADER(fame.h, , AC_MSG_ERROR([*** libFame include files not found!]))
-AC_CHECK_LIB(fame, fame_init, , AC_MSG_ERROR([*** libFame not found!]))
+AC_CHECK_HEADER(fame.h, , AC_MSG_ERROR([*** libFAME include files not found!]))
+AC_CHECK_LIB(fame, fame_init, , AC_MSG_ERROR([*** libFAME not found!]))
+
+dnl ======================
+dnl Check for Lame library
+dnl ======================
+AC_CHECK_HEADER(lame/lame.h, , AC_MSG_ERROR([*** libLAME (libmp3lame) include files not found!]))
+AC_CHECK_LIB(mp3lame, lame_init, , AC_MSG_ERROR([*** libLAME (libmp3lame) not found!]))
AC_SUBST(CFLAGS)
AC_SUBST(CPPFLAGS)
@@ -74,4 +80,5 @@ AC_OUTPUT(
src/Makefile
tools/Makefile
etc/Makefile
- pixmaps/Makefile)
+ pixmaps/Makefile
+ man/Makefile)
diff --git a/etc/miav.conf b/etc/miav.conf
index 05f865e..82cf98f 100644
--- a/etc/miav.conf
+++ b/etc/miav.conf
@@ -32,7 +32,8 @@ server_user = "miav"
server_group = "miav"
# Where to store the files recieved by the server
-server_root = "/home/miav/miav_files"
+server_movie_root = "/home/miav/miav_movie_files"
+server_image_root = "/home/miav/miav_image_files"
# Video output controls. A sequence of I and P, where I is keyframes
# which is fast to create, but uses a lot of discspace.
diff --git a/man/miav.conf.1 b/man/miav.conf.1
index 1719ea6..a9d90fa 100644
--- a/man/miav.conf.1
+++ b/man/miav.conf.1
@@ -107,7 +107,12 @@ Set to 1 if client is slow ( less than 1.5 ghz )
.B Where to store the files recieved by the server
.RE
-.I server_root
+.I server_movie_root
+points to the root folder of the directory structure (Which is created
+by MIaV) to contain the movie clips.
+.I server_image_root
+points to the root folder of the directory structure (Which is created
+by MIaV) to contain the images clips.
.B Video output controls.
.RE
diff --git a/man/miav.conf.5 b/man/miav.conf.5
index 1719ea6..a9d90fa 100644
--- a/man/miav.conf.5
+++ b/man/miav.conf.5
@@ -107,7 +107,12 @@ Set to 1 if client is slow ( less than 1.5 ghz )
.B Where to store the files recieved by the server
.RE
-.I server_root
+.I server_movie_root
+points to the root folder of the directory structure (Which is created
+by MIaV) to contain the movie clips.
+.I server_image_root
+points to the root folder of the directory structure (Which is created
+by MIaV) to contain the images clips.
.B Video output controls.
.RE
diff --git a/src/Makefile.am b/src/Makefile.am
index 0afb24a..a611de5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,8 @@ miav_SOURCES = $(shell if [ $QT_CXXFLAGS ] ; then ../tools/MocList cc; fi ) \
info.cc \
info_console.cc \
info_gui.cc \
+ libfame_wrapper.cc \
+ liblame_wrapper.cc \
mainwindow.cc \
messagebox.cc \
miav.cc \
@@ -52,6 +54,8 @@ EXTRA_DIST = \
info.h \
info_console.h \
info_gui.h \
+ libfame_wrapper.h \
+ liblame_wrapper.h \
mainwindow.h \
messagebox.h \
miav.h \
diff --git a/src/libfame_wrapper.cc b/src/libfame_wrapper.cc
new file mode 100644
index 0000000..ab60b36
--- /dev/null
+++ b/src/libfame_wrapper.cc
@@ -0,0 +1,265 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * libfame_wrapper.cc
+ *
+ * Sat Jul 2 11:11:31 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.
+ */
+
+/*
+ * $Id$
+ */
+
+/*
+ * $Log$
+ * Revision 1.1 2005/07/02 11:39:51 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
+ */
+
+#include <config.h>
+#include "libfame_wrapper.h"
+
+#include <errno.h>
+
+#include "miav_config.h"
+#include "frame.h"
+
+LibFAMEWrapper::LibFAMEWrapper(Info *i)
+{
+ info = i;
+
+ // FIXME: Hmmm... should this be detected somewhere?!
+ int w = 720;
+ int h = 576;
+
+ // Initialize yuv structure.
+ yuv.w = w;
+ yuv.h = h;
+ yuv.p = w;
+ yuv.y = new unsigned char [w*h * 2];
+ yuv.u = new unsigned char [w*h];// [w*h/4]
+ yuv.v = new unsigned char [w*h];// [w*h/4]
+
+ ////////////LIBDV STUFF///////////////
+
+ dvdecoder = NULL; // Initialize in encode method
+
+ /////////LIBFAME STUFF///////////
+
+ // Allocate the output buffer.
+
+// fame_buffer = new unsigned char [FAME_BUFFER_SIZE];
+
+ /*
+ // Open output file
+ f=fopen(filename, "wb");
+ if(!f) {
+ fprintf(stderr, "Failed to open output file [%s] due to the following error: %s", filename, strerror(errno));
+ return;
+ }
+ */
+ // Open a new session of the fame library.
+ // (If initialization was successful, it returns a non-null context which
+ // can then be used for subsequent library calls.)
+ fame_context = fame_open();
+ if(!fame_context) {
+ info->error("Unable to open FAME context, due to the following error: %s", strerror(errno));
+ return;
+ }
+
+ /*
+ typedef struct _fame_parameters_ {
+ int width; // width of the video sequence
+ int height; // height of the video sequence
+ char const *coding; // coding sequence
+ int quality; // video quality
+ int slices_per_frame; // number of slices per frame
+ unsigned int frames_per_sequence; // number of frames per sequence
+ int frame_rate_num; // numerator of frames per second
+ int frame_rate_den; // denominator of frames per second
+ unsigned int shape_quality; // binary shape quality
+ unsigned int search_range; // motion estimation search range
+ unsigned char verbose; // verbosity
+ } fame_parameters_t;
+ */
+ // width and height specify the size of each frames of the video sequence.
+ // Both must be multiple of 16. width and height must be less than 4096x4096
+ fame_par.width = 720;
+ fame_par.height = 576;
+
+ // coding is a string of I, P or B characters representing the sequence of
+ // frames the encoder must produce. I frames are intra-coded frames (similar
+ // to JPEG), whereas P and B frames are motion compressed, respectively
+ // predicted from past reference (I or P) frame, or bidirectionally predicted
+ // from past and future reference frame.
+ fame_par.coding = config->readString("frame_sequence")->c_str();
+
+ // quality is a percentage, which controls compression versus quality.
+ fame_par.quality = config->readInt("frame_quality");
+
+ // Bitrate
+ fame_par.bitrate = 0; // video bitrate (0=VBR)
+
+ // slices_per_frame is the number of frame slices per frame. More slices provide
+ // better error recovery. There must be at least one slice per frame, and at most
+ // height / 16
+ fame_par.slices_per_frame = 1;//fame_par.height / 16;
+
+ // frames_per_sequence is the maximum number of frames contained in a video
+ // sequence.
+ fame_par.frames_per_sequence = 0xffffffff; // Unlimited length
+
+ // frame_rate_num/frame_rate_den specify the number of frames per second for
+ // playback.
+ fame_par.frame_rate_num = 25; // 25 / 1 fps = 25 fps
+ fame_par.frame_rate_den = 1;
+
+ // shape_quality is percentage determing the average binary shape accuracy in
+ // video with arbitrary shape.
+ fame_par.shape_quality = 100; // Original shape
+
+ // search_range specifies the motion estimation search range in pixel unit.
+ // Small search ranges work best with slow motion videos, whereas larger search
+ // ranges are rather for fast motion videos.
+ fame_par.search_range = 0; // Adaptive search range
+
+ // verbose when set to 1 outputs information on copyright, modules used and
+ // current frame on standard error.
+ fame_par.verbose = 0;
+
+ static const char profilename[] = "MIaV\0";
+ fame_par.profile = profilename; // profile name
+ fame_par.total_frames = 0; // total number of frames
+
+ if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg4") == 0) {
+
+ info->info("Using mpeg4 compression.");
+ fame_object_t *object;
+
+ object = fame_get_object(fame_context, "profile/mpeg4/simple");
+ if(object) fame_register(fame_context, "profile", object);
+
+ } else if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg1") == 0) {
+
+ info->info("Using mpeg1 compression.");
+ fame_object_t *object;
+
+ object = fame_get_object(fame_context, "profile/mpeg1");
+ if(object) fame_register(fame_context, "profile", object);
+
+ } else if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg1") == 0) {
+ } else {
+ info->info("Using default (mpeg1) compression.");
+ }
+
+ fame_init(fame_context, &fame_par, fame_buffer, FAME_BUFFER_SIZE);
+}
+
+LibFAMEWrapper::~LibFAMEWrapper()
+{
+ delete [] yuv.y;
+ delete [] yuv.u;
+ delete [] yuv.v;
+}
+
+Frame *LibFAMEWrapper::encode(Frame *dvframe)
+{
+ // if(!f) return; // The file was not opened.
+
+ // Decode DV Frame to YUV422
+ int w = 720;
+ int h = 576;
+
+ unsigned char *pixels[3];
+ int pitches[3];
+
+ if(!dvdecoder) {
+ dvdecoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE);
+ dvdecoder->quality = DV_QUALITY_BEST;
+
+ dv_parse_header(dvdecoder, dvframe->data);
+ //dv_parse_packs(decoder, frame->data); // Not needed anyway!
+
+ dvdecoder->system = e_dv_system_625_50; // PAL lines, PAL framerate
+ dvdecoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v
+ dvdecoder->std = e_dv_std_iec_61834;
+ dvdecoder->num_dif_seqs = 12;
+ }
+
+ pixels[ 0 ] = picture; // We use this as the output buffer
+ pitches[ 0 ] = w * 2;
+
+ dv_decode_full_frame(dvdecoder,
+ dvframe->data,
+ e_dv_color_yuv,
+ pixels,
+ pitches);
+
+ // Convert YUV422 to YUV420p
+ int w2 = w / 2;
+ uint8_t *y = yuv.y;
+ uint8_t *cb = yuv.u;
+ uint8_t *cr = yuv.v;
+ uint8_t *p = picture;
+
+ for ( int i = 0; i < h; i += 2 ) {
+ // process two scanlines (one from each field, interleaved)
+ for ( int j = 0; j < w2; j++ ) {
+ // packed YUV 422 is: Y[i] U[i] Y[i+1] V[i]
+ *( y++ ) = *( p++ );
+ *( cb++ ) = *( p++ );
+ *( y++ ) = *( p++ );
+ *( cr++ ) = *( p++ );
+ }
+
+ // process next two scanlines (one from each field, interleaved)
+ for ( int j = 0; j < w2; j++ ) {
+ // skip every second line for U and V
+ *( y++ ) = *( p++ );
+ p++;
+ *( y++ ) = *( p++ );
+ p++;
+ }
+ }
+
+ // Allocate a new frame for the output
+ Frame *output = new Frame(NULL, FAME_BUFFER_SIZE);
+ output->size = 0;
+ unsigned char* pt = output->data;
+
+ // Encode YUV frame and write it to disk.
+ fame_start_frame(fame_context, &yuv, 0);
+ int written;
+
+ while((written = fame_encode_slice(fame_context))) {
+ // fwrite(fame_buffer, written, 1, f);
+ memcpy(pt, fame_buffer, written);
+ pt += written;
+ output->size += written;
+ }
+ fame_end_frame(fame_context,0);
+
+ return output;
+}
+
diff --git a/src/libfame_wrapper.h b/src/libfame_wrapper.h
new file mode 100644
index 0000000..9f3e0e8
--- /dev/null
+++ b/src/libfame_wrapper.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * libfame_wrapper.h
+ *
+ * Sat Jul 2 11:11:31 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.
+ */
+
+/*
+ * $Id$
+ */
+
+/*
+ * $Log$
+ * Revision 1.1 2005/07/02 11:39:51 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
+ */
+
+#include <config.h>
+#ifndef __MIAV_LIBFAME_WRAPPER_H__
+#define __MIAV_LIBFAME_WRAPPER_H__
+
+// Use libfame
+#include <fame.h>
+
+// Use libdv
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+
+#include "frame.h"
+#include "info.h"
+
+// size specifies the length of the buffer.
+#define FAME_BUFFER_SIZE (1024*1024) // FIXME: One size fits all...
+
+class LibFAMEWrapper {
+public:
+ LibFAMEWrapper(Info *info);
+ ~LibFAMEWrapper();
+
+ Frame *encode(Frame *dvframe);
+
+private:
+ Info* info;
+
+ // libFAME encoder
+ // unsigned char *fame_buffer;
+ fame_parameters_t fame_par;
+ fame_context_t *fame_context;
+ fame_yuv_t yuv;
+ unsigned char fame_buffer[FAME_BUFFER_SIZE];
+
+ // libdv decoder
+ dv_decoder_t *dvdecoder;
+
+ unsigned char picture[FAME_BUFFER_SIZE];
+};
+
+#endif/*__MIAV_LIBFAME_WRAPPER_H__*/
diff --git a/src/liblame_wrapper.cc b/src/liblame_wrapper.cc
new file mode 100644
index 0000000..751c41b
--- /dev/null
+++ b/src/liblame_wrapper.cc
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * liblame_wrapper.cc
+ *
+ * Sat Jul 2 11:11:34 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.
+ */
+
+/*
+ * $Id$
+ */
+
+/*
+ * $Log$
+ * Revision 1.1 2005/07/02 11:39:51 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
+ */
+
+#include <config.h>
+#include "liblame_wrapper.h"
+
+LibLAMEWrapper::LibLAMEWrapper(Info *i)
+{
+ info = i;
+
+ // Init library.
+ lamegf = lame_init();
+ if(!lamegf) {
+ info->error("LAME initialization failed (due to malloc failure!)");
+ }
+
+ lame_init_params(lamegf);
+
+ decoder = NULL;
+
+ audio_buffer[0] = new int16_t[AUDIO_BUFFER_SIZE];
+ audio_buffer[1] = new int16_t[AUDIO_BUFFER_SIZE];
+
+}
+
+LibLAMEWrapper::~LibLAMEWrapper()
+{
+ delete audio_buffer[0];
+ delete audio_buffer[1];
+
+}
+
+Frame *LibLAMEWrapper::encode(Frame *dvframe)
+{
+
+ if(!decoder) {
+ decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE);
+ decoder->quality = DV_QUALITY_BEST;
+
+ dv_parse_header(decoder, dvframe->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;
+ }
+
+ // See
+ // http://www.koders.com/cpp/fidE614E999154E2B4A813DA272C4421633063C78CA.aspx
+ // line 769
+
+ /**
+ * Decode audio using libdv
+ */
+ // int n, i;
+ // int16_t* s = ( int16_t * ) sound;
+ dv_decode_full_audio( decoder, dvframe->data, audio_buffer );
+ /*
+ for ( n = 0; n < SAMPLES; ++n )
+ for ( i = 0; i < CHANNELS; i++ )
+ *s++ = audio_buffer[ i ][ n ];
+ */
+
+/*
+ * input pcm data, output (maybe) mp3 frames.
+ * This routine handles all buffering, resampling and filtering for you.
+ *
+ * The required mp3buf_size can be computed from num_samples,
+ * samplerate and encoding rate, but here is a worst case estimate:
+ *
+ * mp3buf_size in bytes = 1.25*num_samples + 7200
+ *
+ * I think a tighter bound could be: (mt, March 2000)
+ * MPEG1:
+ * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512
+ * MPEG2:
+ * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256
+ *
+ * but test first if you use that!
+ *
+ * set mp3buf_size = 0 and LAME will not check if mp3buf_size is
+ * large enough.
+ *
+ * NOTE:
+ * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels
+ * will be averaged into the L channel before encoding only the L channel
+ * This will overwrite the data in buffer_l[] and buffer_r[].
+ *
+*/
+
+ Frame* audio_frame = new Frame(NULL, (int)(1.25 * SAMPLES + 7200));
+
+ const short int *buffer_l = audio_buffer[0]; // PCM data for left channel
+ const short int *buffer_r = audio_buffer[0]; // PCM data for right channel
+ const int nsamples = SAMPLES; // number of samples per channel
+ unsigned char* mp3buf = audio_frame->data; // pointer to encoded MP3 stream
+ const int mp3buf_size = audio_frame->size; // number of valid octets in this
+
+ int val = lame_encode_buffer(lamegf, buffer_l, buffer_r, nsamples, mp3buf, mp3buf_size);
+
+ if(val < 0) {
+ switch(val) {
+ case -1: // mp3buf was too small
+ info->error("Lame encoding failed, mp3buf was too small.");
+ break;
+ case -2: // malloc() problem
+ info->error("Lame encoding failed, due to malloc() problem.");
+ break;
+ case -3: // lame_init_params() not called
+ info->error("Lame encoding failed, lame_init_params() not called.");
+ break;
+ case -4: // psycho acoustic problems
+ info->error("Lame encoding failed, due to psycho acoustic problems.");
+ break;
+ default:
+ info->error("Lame encoding failed, due to unknown error.");
+ break;
+ }
+ }
+
+ return audio_frame;
+}
diff --git a/src/liblame_wrapper.h b/src/liblame_wrapper.h
new file mode 100644
index 0000000..2d3a769
--- /dev/null
+++ b/src/liblame_wrapper.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * liblame_wrapper.h
+ *
+ * Sat Jul 2 11:11:34 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.
+ */
+
+/*
+ * $Id$
+ */
+
+/*
+ * $Log$
+ * Revision 1.1 2005/07/02 11:39:51 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
+ */
+
+#include <config.h>
+#ifndef __MIAV_LIBLAME_WRAPPER_H__
+#define __MIAV_LIBLAME_WRAPPER_H__
+
+// Use libdv
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+
+// Use liblame
+#include <lame/lame.h>
+
+#include "frame.h"
+#include "info.h"
+
+#define CHANNELS 2
+#define SAMPLES 44100
+#define AUDIO_BUFFER_SIZE SAMPLES/25*sizeof(int16_t)
+
+class LibLAMEWrapper {
+public:
+ LibLAMEWrapper(Info *info);
+ ~LibLAMEWrapper();
+
+ Frame *encode(Frame *dvframe);
+
+private:
+ Info *info;
+
+ // LAME stuff
+ lame_global_flags *lamegf;
+
+ // libdv stuff
+ dv_decoder_t *decoder;
+ int16_t *audio_buffer[2];
+
+};
+
+#endif/*__MIAV_LIBLAME_WRAPPER_H__*/
diff --git a/src/miav_config.cc b/src/miav_config.cc
index f7d56ce..f59b6b3 100644
--- a/src/miav_config.cc
+++ b/src/miav_config.cc
@@ -31,6 +31,10 @@
/*
* $Log$
+ * Revision 1.11 2005/07/02 11:39:51 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
* Revision 1.10 2005/06/14 12:29:40 deva
* Incorporated the use of the Info object everywhere... also using the log functionality.
*
@@ -65,7 +69,7 @@ MiavConfig::MiavConfig(char *file, Info *i)
return;
}
fseek(fp, 0, SEEK_END);
- int fsz = ftell(fp);
+ int fsz = ftell(fp) + 1;
fseek(fp, 0, SEEK_SET);
char *raw = (char*)calloc(fsz, 1);
@@ -73,7 +77,8 @@ MiavConfig::MiavConfig(char *file, Info *i)
fclose(fp);
- parse(raw);
+ configs = parse(raw);
+
free(raw);
}
@@ -93,173 +98,384 @@ MiavConfig::~MiavConfig()
/**
* Prints a reasonable error message when a parse error occurres.
*/
-_cfg *MiavConfig::parseError(char* msg, char* line)
+void MiavConfig::parseError(char* msg, _cfg* cfg)
{
- if(info) info->error("Error parsing file %s at line:\n\t%s\n\t%s\n", filename.c_str(), line, msg);
- else fprintf(stderr, "Error parsing file %s at line:\n\t%s\n\t%s\n", filename.c_str(), line, msg);
- return NULL;
+ if(info) info->error("Error parsing file %s at line %d:\n\t%s\n\t%s\n",
+ filename.c_str(),
+ cfg->line,
+ cfg->orig,
+ msg);
+ else fprintf(stderr, "Error parsing file %s at line %d:\n\t%s\n\t%s\n",
+ filename.c_str(),
+ cfg->line,
+ cfg->orig,
+ msg);
}
-/**
- * Adds one configuration entry, from a single zero terminated line.
- */
-_cfg *MiavConfig::addConfig(_cfg *parent, char* conf)
+_cfg* MiavConfig::readLines(char* raw)
{
- // Check for wellformed input:
- // Check for =
- if(strstr(conf, "=") == 0) return parseError("Missing '='", conf);
- /*
- if(strstr(conf, "\"")) {
- if(strstr(conf, "=") > strstr(conf, "\""))
- return parseError("Missing '=', first occurrence inside string", conf);
- }
- */
+ int line = 1;
+
+ _cfg *first = (_cfg*)calloc(1, sizeof(_cfg));
+ _cfg *current = first;
+ _cfg *next = NULL;
- // Check for nonempty left side
- if(strstr(conf, "=") == conf) return parseError("Empty left side", conf);
+ char *nl = strchr(raw, '\n');
- // Check for nonempty right side
- if(strstr(conf, "=") == conf + strlen(conf) - 1) return parseError("Empty right side.", conf);
+ while(nl != NULL) {
+ int len = nl - raw;
- // Parse this wellformed input.
- _cfg *cfg;
+ current->line = line;
- cfg = (_cfg*) malloc(sizeof(_cfg));
- if(!parent) configs = cfg;
+ current->orig = (char*) calloc(len + 1, 1);
+ strncpy(current->orig, raw, len);
- int namelen = strchr(conf, '=') - conf;
- char* name = (char*)calloc(namelen + 1, 1);
- strncpy(name, conf, namelen);
+ // Find next newline
+ raw = nl+1;
+ nl = strchr(raw, '\n');
- int vallen = conf + strlen(conf) - (strchr(conf, '=') + 1);
- char* val = (char*)calloc(vallen + 1, 1);
- strncpy(val, conf + strlen(conf) - vallen, vallen);
+ line++;
- // TODO: Check valid rightside (true, false, number or "..")
+ // Add _cfg
+ if(nl != NULL) {
+ next = (_cfg*)calloc(1, sizeof(_cfg));
+ current->next = next;
+ current = next;
+ } else {
+ current->next = NULL;
+ }
+ }
- cfg->name = new string((const char*)name);
- free(name);
+ return first;
+}
- cfg->stringval = new string((const char*)val);
- cfg->intval = atoi(val);
- cfg->floatval = atof(val);
- cfg->boolval = atoi(val) != 0;
- free(val);
+_cfg* MiavConfig::parseLines(_cfg *cfg)
+{
+ if(cfg == NULL) return NULL;
- cfg->next = NULL;
+ char *l = cfg->left = (char*)calloc(1, strlen(cfg->orig));
+ char *r = cfg->right = (char*)calloc(1, strlen(cfg->orig));
- if(parent) parent->next = cfg;
- return cfg;
-}
+ char *p = cfg->orig;
-/**
- * Main parse function, iterates the lines of the file.
- */
-int MiavConfig::parse(char* raw)
-{
- // Strip the string
- char *conf = strip(raw);
- char *conf_end = conf + strlen(conf);
- char *start = conf;
- char *p;
-
- _cfg *cfg = NULL;
-
- // Iterate the lines in the string
- for(p = conf; p < conf_end; p++) {
- if(*p == '\n') {
- *p = '\0';
- if(!(cfg = addConfig(cfg, start))) return 1;
- start = p+1;
+ // Skip leftmost whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Empty line, with whitespaces
+ if(p == cfg->orig + strlen(cfg->orig)) {
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Parse left side
+ while(p < cfg->orig + strlen(cfg->orig) && !strchr("\t ", *p)) {
+ if(strchr("#", *p)) {
+ if(l != cfg->left) parseError("Incomplete line.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ if(strchr("=", *p)) break;
+
+ if(strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_", *p)) {
+ *l = *p;
+ l++;
+ } else {
+ char buf[256];
+ sprintf(buf, "Invalid left hand side character at [%s].", p);
+ parseError(buf, cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
}
+
+ p++;
}
- // Allocated in strip
- free(conf);
- return 0;
-}
-/**
- * Strip all unwanted data from the string, initial to parsing.
- */
-char* MiavConfig::strip(char* conf)
-{
- // Freed in parse!!!
- char *stripped = (char*)calloc(strlen(conf) + 2, 1);
- char *r;
- char *w = stripped;
-
- bool instring = false;
- bool incomment = false;
-
- // Iterate over the characters in the input string.
- for(r = conf; r < conf + strlen(conf); r++) {
- if(strchr("#", *r)) incomment = true;
- if(strchr("\n", *r)) incomment = false;
-
- if(!incomment) {
- if(instring) {
- // When in a string, accept anything, except ".
- if(*r != '\"') {
- *w = *r;
- w++;
- }
- } else {
- // Only copy valid characters
- if(strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890-_,.=", *r)) {
- // Change comma into dot
- if(*r == ',') *r = '.';
- *w = *r;
- w++;
- }
- // We don't want double newlines and initial newline!
- if((*r == '\n') && (*(w-1) != '\n') && (w != stripped)) {
- *w = *r;
- w++;
- }
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ if(*p != '=') {
+ parseError("Expected '='.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+ p++; // Get past the '='
+
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Parse right hand side
+ int instring = 0;
+ while(p < cfg->orig + strlen(cfg->orig) && !(strchr("\t ", *p) && instring != 1)) {
+ if(*p == '\"') instring++;
+ if(instring > 2) {
+ parseError("Too many '\"'.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ if(instring == 1) {
+ // Accept all chars
+ *r= *p;
+ r++;
+ } else {
+ // Accept only those chars valid for the data types.
+ if(strchr("truefalseyesnoTRUEFALSEYESNO1234567890\",.-", *p)) {
+ if(*p == ',') *r= '.';
+ *r = *p;
+ r++;
+ } else if(!strchr("\n", *p)) {
+ char buf[256];
+ sprintf(buf, "Invalid right hand side character at [%s].", p);
+ parseError(buf, cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
}
+ if(*p == '#') break;
}
- if(strchr("\"", *r)) instring = !instring;
+ p++;
+ }
+
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Detect if whitespace ocurred inside righthand value.
+ if(p != cfg->orig + strlen(cfg->orig)) {
+ parseError("Invalid use of whitespace.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for instring (string not ended)
+ if(instring == 1) {
+ parseError("String not closed.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for empty line
+ if(l == cfg->left && r == cfg->right) {
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for empty left side.
+ if(l == cfg->left) {
+ parseError("Empty left side.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
}
- // If we are not ending on a newline, we better append one
- if(*(w-1) != '\n') {
- *w = '\n';
- w++;
+ // Check for empty right side.
+ if(r == cfg->right) {
+ parseError("Empty right side.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
}
- // Make sure we are nullterminated.
- *w = '\0';
+ cfg->next = parseLines(cfg->next);
+ return cfg;
+}
+
+
+_cfg *MiavConfig::createSemantics(_cfg *cfg) {
+ if(cfg == NULL) return NULL;
+
+ cfg->type = CONFIG_UNKNOWN;
+
+ // Boolean - true
+ if(strcasecmp(cfg->right, "yes") == 0 ||
+ strcasecmp(cfg->right, "true") == 0) {
+ cfg->type = CONFIG_BOOL;
+ cfg->boolval = true;
+ }
+
+ // Boolean - false
+ if(strcasecmp(cfg->right, "no") == 0 ||
+ strcasecmp(cfg->right, "false") == 0) {
+ cfg->type = CONFIG_BOOL;
+ cfg->boolval = false;
+ }
- return stripped;
+ // String
+ if(cfg->right[0] == '\"') {
+ cfg->type = CONFIG_STRING;
+ cfg->right[strlen(cfg->right) - 1] = '\0';
+ cfg->stringval = new string(cfg->right + 1);
+
+ }
+
+ // Number
+ bool number = true;
+ char *p = cfg->right;
+ while(p < cfg->right + strlen(cfg->right)) {
+ if(!strchr("01234567890.-", *p)) number = false;
+ p++;
+ }
+
+ // Integer
+ if(number && strstr(cfg->right, ".") == NULL ) {
+ cfg->type = CONFIG_INT;
+ cfg->intval = atoi(cfg->right);
+ }
+
+ // Float
+ if(number && strstr(cfg->right, ".") != NULL) {
+ cfg->type = CONFIG_FLOAT;
+ cfg->floatval = atof(cfg->right);
+ }
+
+ if(cfg->type == CONFIG_UNKNOWN) {
+ parseError("Unknown type (see 'man miav.conf' for valid right hand sides).", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return createSemantics(next);
+ }
+
+ // Create name
+ cfg->name = new string(cfg->left);
+
+ cfg->next = createSemantics(cfg->next);
+ return cfg;
+}
+
+
+_cfg* MiavConfig::parse(char* raw)
+{
+ _cfg *first = readLines(raw);
+ first = parseLines(first);
+
+ first = createSemantics(first);
+
+ /*
+ _cfg* cfg = first;
+ while(cfg) {
+ printf("Node:\n");
+ printf("\tLine: [%d]\n", cfg->line);
+ printf("\tOrig: [%s]\n", cfg->orig);
+ printf("\tLeft: [%s]\n", cfg->left);
+ printf("\tRight: [%s]\n", cfg->right);
+
+ switch(cfg->type) {
+ case CONFIG_INT:
+ printf("\tInt value: %d\n", cfg->intval);
+ break;
+ case CONFIG_BOOL:
+ printf("\tBool value: %d\n", cfg->boolval);
+ break;
+ case CONFIG_FLOAT:
+ printf("\tFloat value: %f\n", cfg->floatval);
+ break;
+ case CONFIG_STRING:
+ printf("\tString value: %s\n", cfg->stringval->c_str());
+ break;
+ case CONFIG_UNKNOWN:
+ printf("\tUnknown type: %s\n", cfg->right);
+ break;
+ }
+
+ cfg= cfg->next;
+ }
+ */
+ return first;
}
int MiavConfig::readInt(char *node)
{
_cfg* n = findNode(node);
- if(n) return n->intval;
- else return 0;
+ if(n) {
+ if(n->type == CONFIG_INT) return n->intval;
+ parseError("Expected integer.", n);
+ }
+ return 0;
}
bool MiavConfig::readBool(char *node)
{
- _cfg* n = findNode(node);
- if(n) return n->boolval;
- else return false;
+ _cfg* n = findNode(node);
+ if(n) {
+ if(n->type == CONFIG_BOOL) return n->boolval;
+ if(n->type == CONFIG_INT) return (n->intval != 0);
+ parseError("Expected boolean.", n);
+ }
+ return false;
}
string *MiavConfig::readString(char *node)
{
_cfg* n = findNode(node);
- if(n) return n->stringval;
- else return &emptyString;
+ if(n) {
+ if(n->type == CONFIG_STRING) return n->stringval;
+ parseError("Expected string.", n);
+ }
+ return &emptyString;
}
float MiavConfig::readFloat(char *node)
{
_cfg* n = findNode(node);
- if(n) return n->floatval;
- else return 0.0f;
+ if(n) {
+ if(n->type == CONFIG_FLOAT) return n->floatval;
+ if(n->type == CONFIG_INT) return (float)n->intval;
+ parseError("Expected float.", n);
+ }
+ return 0.0f;
}
_cfg *MiavConfig::findNode(char* node)
@@ -270,8 +486,31 @@ _cfg *MiavConfig::findNode(char* node)
if(!strcmp(node, cfg->name->c_str())) return cfg;
cfg = cfg->next;
}
- if(info) info->error("Request for nonexisting node \"%s\"!\n", node);
- else fprintf(stderr, "Request for nonexisting node \"%s\"!\n", node);
+ if(info) info->error("Missing line in configuration file: \"%s\"!\n", node);
+ else fprintf(stderr, "Missing line in configuration file: \"%s\"!\n", node);
return NULL;
}
+
+#ifdef __TEST_MIAV_CONFIG
+
+int main(int argc, char *argv[]) {
+ if(argc < 2) {
+ fprintf(stderr, "usage:\n\tmiav_config [filename]\n");
+ return 1;
+ }
+
+ MiavConfig cfg(argv[1]);
+ printf("Server user: [%s]\n", cfg.readString("server_user")->c_str());
+ printf("Resolution: [%f]\n", cfg.readFloat("screensize"));
+ printf("Resolution (as int): [%d]\n", cfg.readInt("screensize"));
+ printf("Width: [%d]\n", cfg.readInt("pixel_width"));
+ printf("Width (as float): [%f]\n", cfg.readFloat("pixel_width"));
+ printf("Frame quality: [%d]\n", cfg.readInt("frame_quality"));
+ printf("Skip frames: [%d]\n", cfg.readBool("player_skip_frames"));
+ printf("Skip frames (as int): [%d]\n", cfg.readInt("player_skip_frames"));
+ printf("Frame quality (as bool): [%d]\n", cfg.readBool("frame_quality"));
+
+}
+
+#endif/* __TEST_MIAV_CONFIG*/
diff --git a/src/miav_config.h b/src/miav_config.h
index 4bbcc59..a4c432a 100644
--- a/src/miav_config.h
+++ b/src/miav_config.h
@@ -31,6 +31,10 @@
/*
* $Log$
+ * Revision 1.8 2005/07/02 11:39:51 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
* Revision 1.7 2005/06/14 12:29:40 deva
* Incorporated the use of the Info object everywhere... also using the log functionality.
*
@@ -52,18 +56,36 @@ using namespace std;
// Cyclic include :(
class Info;
+typedef enum {
+ CONFIG_UNKNOWN,
+ CONFIG_INT,
+ CONFIG_BOOL,
+ CONFIG_FLOAT,
+ CONFIG_STRING
+} ConfigType;
+
+
typedef struct __cfg {
+ // For parsing
+ char* orig;
+ int line;
+ char* left;
+ char* right;
+
+ // For traversal
string *name;
- bool boolval;
+ ConfigType type;
int intval;
- string *stringval;
+ bool boolval;
float floatval;
+ string *stringval;
+
struct __cfg* next;
} _cfg;
class MiavConfig {
public:
- MiavConfig(char *file, Info *info);
+ MiavConfig(char *file, Info *info = NULL);
~MiavConfig();
int readInt(char *node);
@@ -73,13 +95,21 @@ public:
private:
Info *info;
+ string filename;
+ _cfg *createSemantics(_cfg *cfg);
+ _cfg* readLines(char* raw);
+ _cfg* parseLines(_cfg *cfg);
+ _cfg *parse(char* raw);
string emptyString;
- string filename;
+
+
+#if 0
_cfg *addConfig(_cfg *parent, char* conf);
- int parse(char* conf);
char *strip(char* conf);
- _cfg *parseError(char* msg, char* line);
+#endif
+
+ void parseError(char* msg, _cfg *cfg);
_cfg *findNode(char* node);
_cfg *configs;
};
diff --git a/src/mov_encoder.cc b/src/mov_encoder.cc
index 3aa7a49..38622c6 100644
--- a/src/mov_encoder.cc
+++ b/src/mov_encoder.cc
@@ -39,6 +39,10 @@
/*
* $Log$
+ * Revision 1.33 2005/07/02 11:39:52 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
* Revision 1.32 2005/06/19 20:04:43 deva
* ImgEncoder now uses the file class for output, through jpeg_mem_dest.
*
@@ -140,131 +144,8 @@ MovEncoder::MovEncoder(sem_t *r_sem,
info = i;
info->info("MovEncoder");
- // FIXME: Hmmm... should this be detected somewhere?!
- int w = 720;
- int h = 576;
-
- // Initialize yuv strucutre.
- yuv.w = w;
- yuv.h = h;
- yuv.p = w;
- yuv.y = new unsigned char [w*h * 2];
- yuv.u = new unsigned char [w*h];// [w*h/4]
- yuv.v = new unsigned char [w*h];// [w*h/4]
-
- ////////////LIBDV STUFF///////////////
-
- dvdecoder = NULL; // Initialize in encode method
-
- /////////LIBFAME STUFF///////////
-
- // Allocate the output buffer.
-
-// fame_buffer = new unsigned char [FAME_BUFFER_SIZE];
-
- /*
- // Open output file
- f=fopen(filename, "wb");
- if(!f) {
- fprintf(stderr, "Failed to open output file [%s] due to the following error: %s", filename, strerror(errno));
- return;
- }
- */
- // Open a new session of the fame library.
- // (If initialization was successful, it returns a non-null context which
- // can then be used for subsequent library calls.)
- fame_context = fame_open();
- if(!fame_context) {
- info->error("Unable to open FAME context, due to the following error: %s", strerror(errno));
- return;
- }
-
- /*
- typedef struct _fame_parameters_ {
- int width; // width of the video sequence
- int height; // height of the video sequence
- char const *coding; // coding sequence
- int quality; // video quality
- int slices_per_frame; // number of slices per frame
- unsigned int frames_per_sequence; // number of frames per sequence
- int frame_rate_num; // numerator of frames per second
- int frame_rate_den; // denominator of frames per second
- unsigned int shape_quality; // binary shape quality
- unsigned int search_range; // motion estimation search range
- unsigned char verbose; // verbosity
- } fame_parameters_t;
- */
- // width and height specify the size of each frames of the video sequence.
- // Both must be multiple of 16. width and height must be less than 4096x4096
- fame_par.width = 720;
- fame_par.height = 576;
-
- // coding is a string of I, P or B characters representing the sequence of
- // frames the encoder must produce. I frames are intra-coded frames (similar
- // to JPEG), whereas P and B frames are motion compressed, respectively
- // predicted from past reference (I or P) frame, or bidirectionally predicted
- // from past and future reference frame.
- fame_par.coding = config->readString("frame_sequence")->c_str();
-
- // quality is a percentage, which controls compression versus quality.
- fame_par.quality = config->readInt("frame_quality");
-
- // Bitrate
- fame_par.bitrate = 0; // video bitrate (0=VBR)
-
- // slices_per_frame is the number of frame slices per frame. More slices provide
- // better error recovery. There must be at least one slice per frame, and at most
- // height / 16
- fame_par.slices_per_frame = 1;//fame_par.height / 16;
-
- // frames_per_sequence is the maximum number of frames contained in a video
- // sequence.
- fame_par.frames_per_sequence = 0xffffffff; // Unlimited length
-
- // frame_rate_num/frame_rate_den specify the number of frames per second for
- // playback.
- fame_par.frame_rate_num = 25; // 25 / 1 fps = 25 fps
- fame_par.frame_rate_den = 1;
-
- // shape_quality is percentage determing the average binary shape accuracy in
- // video with arbitrary shape.
- fame_par.shape_quality = 100; // Original shape
-
- // search_range specifies the motion estimation search range in pixel unit.
- // Small search ranges work best with slow motion videos, whereas larger search
- // ranges are rather for fast motion videos.
- fame_par.search_range = 0; // Adaptive search range
-
- // verbose when set to 1 outputs information on copyright, modules used and
- // current frame on standard error.
- fame_par.verbose = 0;
-
- static const char profilename[] = "MIaV\0";
- fame_par.profile = profilename; // profile name
- fame_par.total_frames = 0; // total number of frames
-
- if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg4") == 0) {
-
- info->info("Using mpeg4 compression.");
- fame_object_t *object;
-
- object = fame_get_object(fame_context, "profile/mpeg4/simple");
- if(object) fame_register(fame_context, "profile", object);
-
- } else if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg1") == 0) {
-
- info->info("Using mpeg1 compression.");
- fame_object_t *object;
-
- object = fame_get_object(fame_context, "profile/mpeg1");
- if(object) fame_register(fame_context, "profile", object);
-
- } else if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg1") == 0) {
- } else {
- info->info("Using default (mpeg1) compression.");
- }
-
- fame_init(fame_context, &fame_par, fame_buffer, FAME_BUFFER_SIZE);
+ fame = new LibFAMEWrapper(info);
+ lame = new LibLAMEWrapper(info);
running = true;
@@ -283,108 +164,9 @@ MovEncoder::MovEncoder(sem_t *r_sem,
MovEncoder::~MovEncoder()
{
info->info("~MovEncoder");
- /*
- if(f) { // The file was opened.
- int written = fame_close(fame_context);
- fwrite(fame_buffer, written, 1, f);
- fclose(f);
- }
- */
- // delete [] fame_buffer;
- delete [] yuv.y;
- delete [] yuv.u;
- delete [] yuv.v;
-}
-
-Frame *MovEncoder::encode(Frame *dvframe)
-{
- return encode_video(dvframe);
- // encode_audio(dvframe);
-}
-
-Frame *MovEncoder::encode_video(Frame *dvframe)
-{
- // if(!f) return; // The file was not opened.
-
- // Decode DV Frame to YUV422
- int w = 720;
- int h = 576;
-
- unsigned char *pixels[3];
- int pitches[3];
-
- if(!dvdecoder) {
- dvdecoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE);
- dvdecoder->quality = DV_QUALITY_BEST;
-
- dv_parse_header(dvdecoder, dvframe->data);
- //dv_parse_packs(decoder, frame->data); // Not needed anyway!
-
- dvdecoder->system = e_dv_system_625_50; // PAL lines, PAL framerate
- dvdecoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v
- dvdecoder->std = e_dv_std_iec_61834;
- dvdecoder->num_dif_seqs = 12;
- }
-
- pixels[ 0 ] = picture; // We use this as the output buffer
- pitches[ 0 ] = w * 2;
-
- dv_decode_full_frame(dvdecoder,
- dvframe->data,
- e_dv_color_yuv,
- pixels,
- pitches);
-
- // Convert YUV422 to YUV420p
- int w2 = w / 2;
- uint8_t *y = yuv.y;
- uint8_t *cb = yuv.u;
- uint8_t *cr = yuv.v;
- uint8_t *p = picture;
-
- for ( int i = 0; i < h; i += 2 ) {
- // process two scanlines (one from each field, interleaved)
- for ( int j = 0; j < w2; j++ ) {
- // packed YUV 422 is: Y[i] U[i] Y[i+1] V[i]
- *( y++ ) = *( p++ );
- *( cb++ ) = *( p++ );
- *( y++ ) = *( p++ );
- *( cr++ ) = *( p++ );
- }
-
- // process next two scanlines (one from each field, interleaved)
- for ( int j = 0; j < w2; j++ ) {
- // skip every second line for U and V
- *( y++ ) = *( p++ );
- p++;
- *( y++ ) = *( p++ );
- p++;
- }
- }
-
- // Allocate a new frame for the output
- Frame *output = new Frame(NULL, FAME_BUFFER_SIZE);
- output->size = 0;
- unsigned char* pt = output->data;
-
- // Encode YUV frame and write it to disk.
- fame_start_frame(fame_context, &yuv, 0);
- int written;
- while((written = fame_encode_slice(fame_context))) {
- // fwrite(fame_buffer, written, 1, f);
- memcpy(pt, fame_buffer, written);
- pt += written;
- output->size += written;
- }
- fame_end_frame(fame_context,0);
-
- return output;
-}
-
-void MovEncoder::encode_audio(Frame *dvframe)
-{
- // TODO: Do some audio stuff here sometime!
+ delete fame;
+ delete lame;
}
// this runs in a thread
@@ -398,10 +180,10 @@ void MovEncoder::thread_main()
// Run with slightly lower priority than MovEncoderWriter
nice(1);
-
FrameVector *item;
Frame *in_frame;
- Frame *out_frame;
+ Frame *out_v_frame;
+ Frame *out_a_frame;
while(running) {
sem_wait(input_sem);
@@ -419,14 +201,21 @@ void MovEncoder::thread_main()
if(item) {
for(unsigned int cnt = 0; cnt < item->size(); cnt++) {
in_frame = item->at(cnt);
- out_frame = encode(in_frame);
- out_frame->number = in_frame->number;
+
+ // Encode video
+ out_v_frame = fame->encode(in_frame);
+ out_v_frame->number = in_frame->number+1;
+ // Encode audio
+ out_a_frame = lame->encode(in_frame);
+ out_a_frame->number = in_frame->number;
+
delete in_frame;
// Lock output mutex
pthread_mutex_lock(output_mutex);
- outputqueue->push(out_frame);
+ outputqueue->push(out_v_frame);
+ outputqueue->push(out_a_frame);
outsize = outputqueue->size();
diff --git a/src/mov_encoder.h b/src/mov_encoder.h
index 76f0c7a..a54b145 100644
--- a/src/mov_encoder.h
+++ b/src/mov_encoder.h
@@ -36,6 +36,10 @@
/*
* $Log$
+ * Revision 1.14 2005/07/02 11:39:52 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
* Revision 1.13 2005/06/16 21:54:22 deva
* *** empty log message ***
*
@@ -77,14 +81,6 @@
#include <stdlib.h>
#include <string.h>
-
-// Use libfame
-#include <fame.h>
-
-// Use libdv
-#include <libdv/dv.h>
-#include <libdv/dv_types.h>
-
#include <vector>
using namespace std;
@@ -96,8 +92,8 @@ using namespace std;
#include "info.h"
-// size specifies the length of the buffer.
-#define FAME_BUFFER_SIZE (1024*1024) // FIXME: One size fits all...
+#include "libfame_wrapper.h"
+#include "liblame_wrapper.h"
class MovEncoder : public Thread {
public:
@@ -106,13 +102,15 @@ public:
FramePriorityQueue *out, sem_t *out_sem, pthread_mutex_t *out_mutex,
Info *info);
~MovEncoder();
- Frame* encode(Frame *frame);
void thread_main();
volatile bool running;
private:
+ LibFAMEWrapper *fame;
+ LibLAMEWrapper *lame;
+
Info *info;
// Input/Output queues
@@ -127,21 +125,6 @@ private:
pthread_mutex_t *input_mutex;
pthread_mutex_t *output_mutex;
-
- Frame *encode_video(Frame *frame);
- void encode_audio(Frame *frame);
-
- // libFAME encoder
- // unsigned char *fame_buffer;
- fame_parameters_t fame_par;
- fame_context_t *fame_context;
- fame_yuv_t yuv;
- unsigned char fame_buffer[FAME_BUFFER_SIZE];
-
- // libdv decoder
- dv_decoder_t *dvdecoder;
-
- unsigned char picture[FAME_BUFFER_SIZE];
};
#endif
diff --git a/src/mov_encoder_thread.cc b/src/mov_encoder_thread.cc
index 49ba24c..d24e3f3 100644
--- a/src/mov_encoder_thread.cc
+++ b/src/mov_encoder_thread.cc
@@ -31,6 +31,10 @@
/*
* $Log$
+ * Revision 1.13 2005/07/02 11:39:52 deva
+ * Added some audiocode.
+ * Moved libfame code out of mov_encoder
+ *
* Revision 1.12 2005/06/16 21:28:57 deva
* Rewrote thread object
* Fixed bug in mov_encoder (pushed read_sem too many times, whihc lead to
@@ -203,5 +207,5 @@ void MovEncoderThread::encode(Frame* frame)
block = new FrameVector;
}
- frame_number ++;
+ frame_number += 2;
}