summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordeva <deva>2005-09-12 15:34:25 +0000
committerdeva <deva>2005-09-12 15:34:25 +0000
commit701608f39c59b530f6cede66ec24e9ddda8beae6 (patch)
treee974077734a45e0e6bb5b487b230922656834bed /src
parent84e9873f846478476487d5cd2587e5879a0be8ea (diff)
*** empty log message ***
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am5
-rw-r--r--src/frame.h4
-rw-r--r--src/iso11172-1.h110
-rw-r--r--src/iso11172-2.h73
-rw-r--r--src/iso11172-3.h85
-rw-r--r--src/libfame_wrapper.cc29
-rw-r--r--src/libfame_wrapper.h2
-rw-r--r--src/liblame_wrapper.cc6
-rw-r--r--src/mov_encoder.cc69
-rw-r--r--src/mov_encoder.h14
-rw-r--r--src/mov_encoder_thread.cc51
-rw-r--r--src/mov_encoder_thread.h9
-rw-r--r--src/mov_encoder_writer.cc195
-rw-r--r--src/mov_encoder_writer.h29
-rw-r--r--src/thread.cc5
-rw-r--r--src/thread.h3
16 files changed, 557 insertions, 132 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 2382214..8494cf1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ miav_SOURCES = $(shell if [ $QT_CXXFLAGS ] ; then ../tools/MocList cc; fi ) \
mov_encoder.cc \
mov_encoder_thread.cc \
mov_encoder_writer.cc \
+ multiplexer.cc \
network.cc \
player.cc \
server.cc \
@@ -60,6 +61,9 @@ EXTRA_DIST = \
info.h \
info_console.h \
info_gui.h \
+ iso11172-1.h \
+ iso11172-2.h \
+ iso11172-3.h \
jpeg_mem_dest.h \
libfame_wrapper.h \
liblame_wrapper.h \
@@ -71,6 +75,7 @@ EXTRA_DIST = \
mov_encoder.h \
mov_encoder_thread.h \
mov_encoder_writer.h \
+ multiplexer.h \
network.h \
package.h \
player.h \
diff --git a/src/frame.h b/src/frame.h
index e6faacd..18425ab 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -40,10 +40,12 @@ public:
~Frame();
unsigned char *data;
- int size;
+ unsigned int size;
unsigned int number;
+ unsigned int bitrate;
+
bool shoot;
int freeze; // 1 is freeze, -1 is unfreeze
bool record;
diff --git a/src/iso11172-1.h b/src/iso11172-1.h
new file mode 100644
index 0000000..f284410
--- /dev/null
+++ b/src/iso11172-1.h
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * iso11172-1.h
+ *
+ * Wed Aug 31 13:48:30 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.
+ */
+
+/*
+ * This file contains symbols used to create an ISO11172-1 compatible multiplexed
+ * MPEG stream.
+ */
+
+#include "config.h"
+#ifndef __MIAV_ISO11172_1_H__
+#define __MIAV_ISO11172_1_H__
+
+#define CLOCK_90KHZ 90000
+
+namespace ISO11172_1 {
+ ////////////////////////////////////////////////////
+ // Constants
+ ////////////////////////////////////////////////////
+ const char pack_start_code[] = "\x00\x00\x01\xBA";
+ const char system_header_start_code[] = "\x00\x00\x01\xBB";
+ const char packet_start_code_prefix[] = "\x00\x00\x01";
+ const char stream_id_video1[] = "\xE3";
+ const char stream_id_video2[] = "\xE4";
+ const char stream_id_video3[] = "\xE5";
+ const char stream_id_video4[] = "\xE6";
+ const char stream_id_video5[] = "\xE7";
+ const char stream_id_video6[] = "\xE8";
+ const char stream_id_video7[] = "\xE9";
+ const char stream_id_video8[] = "\xEA";
+ const char stream_id_audio1[] = "\xC0";
+ const char stream_id_audio2[] = "\xC1";
+ const char stream_id_audio3[] = "\xC2";
+ const char stream_id_audio4[] = "\xC3";
+ const char stream_id_audio5[] = "\xC4";
+ const char stream_id_audio6[] = "\xC5";
+ const char stream_id_audio7[] = "\xC6";
+ const char stream_id_audio8[] = "\xC7";
+ const char stream_id_padding[] = "\xBE";
+ const char end_code[] = "\x00\x00\x01\xB9";
+
+ ////////////////////////////////////////////////////
+ // Methods
+ ////////////////////////////////////////////////////
+ /**
+ * SCR stands for System Clock Reference
+ */
+ inline unsigned int SCR(unsigned int previous_SCR,
+ unsigned int pack_header_size,
+ unsigned int packets_per_pack,
+ unsigned int packet_data_size,
+ unsigned int Rmux)
+ {
+ // To prevent a crash when doing division.
+ if(Rmux == 0) Rmux = 1;
+ return previous_SCR + (unsigned int)((double)(pack_header_size +
+ (packets_per_pack * packet_data_size)) *
+ (double)CLOCK_90KHZ / (double)Rmux);
+ }
+
+ /**
+ * Calculates Rmux according to subclause A.5.4
+ * mux stands for multiplexing and R for Rate,
+ * so Rmux is the rate of the multiplexing.
+ */
+ inline unsigned int Rmux(unsigned int video_data_rate,
+ unsigned int audio_data_rate,
+ unsigned int packet_header_size,
+ unsigned int pack_header_size,
+ unsigned int packets_per_pack,
+ unsigned int packet_data_size)
+ {
+ // To prevent a crash when doing division.
+ if(packets_per_pack == 0) packets_per_pack = 1;
+ if(packet_data_size == 0) packet_data_size = 1;
+
+ return (unsigned int)(
+ ((double)video_data_rate + (double)audio_data_rate) *
+ (1.0 + ((double)packet_header_size + (double)pack_header_size / (double)packets_per_pack)
+ / (double)packet_data_size)
+ );
+ }
+
+
+};
+
+#endif/*__MIAV_ISO11172_1_H__*/
diff --git a/src/iso11172-2.h b/src/iso11172-2.h
new file mode 100644
index 0000000..f2e2fa3
--- /dev/null
+++ b/src/iso11172-2.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * iso11172-2.h
+ *
+ * Tue Sep 6 13:31:04 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_ISO11172_2_H__
+#define __MIAV_ISO11172_2_H__
+
+namespace ISO11172_2 {
+ ////////////////////////////////////////////////////
+ // Types
+ ////////////////////////////////////////////////////
+ typedef struct {
+ unsigned long int picture_rate:4;
+ unsigned long int pel_aspect_ratio:4;
+ unsigned long int vertical_size:12;
+ unsigned long int horizontal_size:12;
+ } sequence_header_1;
+
+ typedef struct {
+ unsigned long int load_non_intra_quantizer_flag:1;
+ unsigned long int load_intra_quantizer_flag:1;
+ unsigned long int constrained_parameter_flag:1;
+ unsigned long int vbv_buffer_size:10;
+ unsigned long int marker_bit:1;
+ unsigned long int bitrate:18;
+ } sequence_header_2;
+
+ ////////////////////////////////////////////////////
+ // Constants
+ ////////////////////////////////////////////////////
+ const char picture_start_code[] = "\x00\x00\x01\x00";
+ const char slice_start_code_prefix[] ="\x00\x00\x01";
+ // const char _code = "\x00\x00\x01\xB0"; //Reserved
+ // const char _code = "\x00\x00\x01\xB1"; //Reserved
+ const char user_data_start_code[] = "\x00\x00\x01\xB2";
+ const char sequence_header_code[] = "\x00\x00\x01\xB3";
+ const char sequence_error_code[] = "\x00\x00\x01\xB4";
+ const char sequence_start_code[] = "\x00\x00\x01\xB5";
+ // const char _code = "\x00\x00\x01\xB6"; //Reserved
+ const char sequence_end_code[] = "\x00\x00\x01\xB7";
+ const char group_start_code[] = "\x00\x00\x01\xB8";
+ const char system_start_code_prefix[] = "\x00\x00\x01";
+
+ ////////////////////////////////////////////////////
+ // Methods
+ ////////////////////////////////////////////////////
+
+};
+
+#endif/*__MIAV_ISO11172_2_H__*/
diff --git a/src/iso11172-3.h b/src/iso11172-3.h
new file mode 100644
index 0000000..d3eda79
--- /dev/null
+++ b/src/iso11172-3.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * iso11172-3.h
+ *
+ * Tue Sep 6 13:10:48 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_ISO11172_3_H__
+#define __MIAV_ISO11172_3_H__
+
+namespace ISO11172_3 {
+ ////////////////////////////////////////////////////
+ // Types
+ ////////////////////////////////////////////////////
+ typedef struct {
+ unsigned long int emphasis:2;
+ unsigned long int original_home:1;
+ unsigned long int copyright:1;
+ unsigned long int mode_extension:2;
+ unsigned long int mode:2;
+ unsigned long int private_bit:1;
+ unsigned long int padding_bit:1;
+ unsigned long int sampling_frequency:2;
+ unsigned long int bitrate_index:4;
+ unsigned long int protection_bit:1;
+ unsigned long int layer:2;
+ unsigned long int ID:1;
+ unsigned long int syncword:12;
+ } header;
+
+ ////////////////////////////////////////////////////
+ // Constants
+ ////////////////////////////////////////////////////
+
+ typedef enum {
+ ID_RESERVED = 0,
+ ID_MPEG = 1
+ } IDs;
+
+ typedef enum {
+ LAYER_RESERVED = 0x00,
+ LAYER_III = 0x01,
+ LAYER_II = 0x10,
+ LAYER_I = 0x11
+ } layers;
+
+ typedef enum {
+ CRC_ON = 0,
+ CRC_OFF = 1
+ } crcs;
+
+ typedef enum {
+ MODE_STEREO = 0x00,
+ MODE_JOINT_STEREO = 0x01,
+ MODE_DUAL_CHANNEL = 0x10,
+ MODE_SINGLE_CHANNEL = 0x11,
+ } modes;
+
+ ////////////////////////////////////////////////////
+ // Methods
+ ////////////////////////////////////////////////////
+
+};
+
+#endif/*__MIAV_ISO11172_3_H__*/
diff --git a/src/libfame_wrapper.cc b/src/libfame_wrapper.cc
index e17ed68..94989f1 100644
--- a/src/libfame_wrapper.cc
+++ b/src/libfame_wrapper.cc
@@ -47,7 +47,9 @@ LibFAMEWrapper::LibFAMEWrapper(Info *i)
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]
-
+
+ calc_bitrate = 0;
+
////////////LIBDV STUFF///////////////
dvdecoder = NULL; // Initialize in encode method
@@ -224,6 +226,8 @@ Frame *LibFAMEWrapper::encode(Frame *dvframe)
// Allocate a new frame for the output
Frame *output = new Frame(NULL, FAME_BUFFER_SIZE);
+ fame_frame_statistics_t stats;
+
// Init frame params
dv_get_timestamp(dvdecoder, output->timecode); // Set timecode
output->size = 0; // Init size (incremented as we read)
@@ -238,7 +242,28 @@ Frame *LibFAMEWrapper::encode(Frame *dvframe)
pt += written;
output->size += written;
}
- fame_end_frame(fame_context,0);
+ fame_end_frame(fame_context, &stats);
+ /*
+ info->info("frame_number: %d, coding: %c, target_bits: %d, actual_bits: %d, spatial_activity: %d, quant_scale: %f",
+ stats.frame_number,
+ stats.coding,
+ stats.target_bits,
+ stats.actual_bits,
+ stats.spatial_activity,
+ stats.quant_scale);
+ */
+ /*
+ fame_frame_statistics_t_ {
+ unsigned int frame_number;
+ char coding;
+ signed int target_bits;
+ unsigned int actual_bits;
+ unsigned int spatial_activity;
+ float quant_scale;
+ }
+ */
+ calc_bitrate += stats.actual_bits;
+ output->bitrate = (unsigned int)(((double)calc_bitrate / (double)(stats.frame_number+1)) * 25.0);
return output;
}
diff --git a/src/libfame_wrapper.h b/src/libfame_wrapper.h
index c4b5344..6a6b569 100644
--- a/src/libfame_wrapper.h
+++ b/src/libfame_wrapper.h
@@ -49,6 +49,8 @@ public:
Frame *encode(Frame *dvframe);
private:
+ unsigned long long calc_bitrate;
+
Info* info;
// libFAME encoder
diff --git a/src/liblame_wrapper.cc b/src/liblame_wrapper.cc
index 5868c86..6d78380 100644
--- a/src/liblame_wrapper.cc
+++ b/src/liblame_wrapper.cc
@@ -48,7 +48,7 @@ LibLAMEWrapper::LibLAMEWrapper(Info *i)
lame_set_mode(gfp, STEREO);
lame_set_brate(gfp, config->readInt("mp3_bitrate"));
- lame_set_strict_ISO(gfp, 0);
+ lame_set_strict_ISO(gfp, 1);
// 1 = write a Xing VBR header frame.
lame_set_bWriteVbrTag(gfp, 0);
@@ -189,11 +189,15 @@ Frame *LibLAMEWrapper::encode(Frame *dvframe)
*
* return code = number of bytes output to mp3buf. Can be 0
*/
+
int flush_sz = lame_encode_flush_nogap(gfp, // global context handle
mp3buf + val, // pointer to encoded MP3 stream
mp3buf_size - val); // number of valid octets in this stream
audio_frame->size = val + flush_sz;
+ // Bits pr. second
+ audio_frame->bitrate = config->readInt("mp3_bitrate") * 1000;
+
return audio_frame;
}
diff --git a/src/mov_encoder.cc b/src/mov_encoder.cc
index 1073b35..a9a2ca2 100644
--- a/src/mov_encoder.cc
+++ b/src/mov_encoder.cc
@@ -44,8 +44,9 @@
#include "debug.h"
MovEncoder::MovEncoder(sem_t *r_sem,
- FrameVectorQueue *in, sem_t *in_sem, pthread_mutex_t *in_mutex,
- FramePriorityQueue *out, sem_t *out_sem, pthread_mutex_t *out_mutex,
+ FrameVectorQueue *in, sem_t *in_sem, pthread_mutex_t *in_mutex,
+ FramePriorityQueue *v_out, pthread_mutex_t *v_out_mutex, sem_t *v_out_sem,
+ FramePriorityQueue *a_out, pthread_mutex_t *a_out_mutex, sem_t *a_out_sem,
Info *i)
{
info = i;
@@ -53,16 +54,21 @@ MovEncoder::MovEncoder(sem_t *r_sem,
running = true;
+ // Queues
inputqueue = in;
- outputqueue = out;
+ video_outputqueue = v_out;
+ audio_outputqueue = a_out;
+
+ // Queue mutexes
+ input_mutex = in_mutex;
+ video_output_mutex = v_out_mutex;
+ audio_output_mutex = a_out_mutex;
input_sem = in_sem;
- output_sem = out_sem;
+ video_output_sem = v_out_sem;
+ audio_output_sem = a_out_sem;
read_sem = r_sem;
-
- input_mutex = in_mutex;
- output_mutex = out_mutex;
}
MovEncoder::~MovEncoder()
@@ -71,14 +77,13 @@ MovEncoder::~MovEncoder()
}
-//#define COPY_DV 1
-
// this runs in a thread
void MovEncoder::thread_main()
{
info->info("MovEncoder thread is running.");
static volatile int test = 0;
- int outsize = 0;
+ int v_outsize = 0;
+ int a_outsize = 0;
int insize = 0;
// Run with slightly lower priority than MovEncoderWriter
@@ -113,49 +118,47 @@ void MovEncoder::thread_main()
for(unsigned int cnt = 0; cnt < item->size(); cnt++) {
in_frame = item->at(cnt);
-#ifdef COPY_DV
-
// Encode video
out_v_frame = new Frame(in_frame->data, in_frame->size);
out_v_frame->number = in_frame->number;
-
- // Encode audio
- out_a_frame = new Frame(in_frame->data, in_frame->size);
- out_a_frame->number = in_frame->number + 1;
-
-#else /*COPY_DV*/
-
- // Encode video
out_v_frame = fame.encode(in_frame);
out_v_frame->number = in_frame->number;
// Encode audio
+ out_a_frame = new Frame(in_frame->data, in_frame->size);
+ out_a_frame->number = in_frame->number;
out_a_frame = lame.encode(in_frame);
- out_a_frame->number = in_frame->number + 1;
+ out_a_frame->number = in_frame->number;
-#endif /*COPY_DV*/
delete in_frame;
// Lock output mutex
- pthread_mutex_lock(output_mutex);
-
- outputqueue->push(out_v_frame);
-
- outputqueue->push(out_a_frame);
+ pthread_mutex_lock(video_output_mutex);
+ video_outputqueue->push(out_v_frame);
+ v_outsize = video_outputqueue->size();
+ pthread_mutex_unlock(video_output_mutex);
+ // Unlock output mutex
- outsize = outputqueue->size();
+ // Kick multiplexer (video)
+ sem_post(video_output_sem);
- pthread_mutex_unlock(output_mutex);
+ // Lock output mutex
+ pthread_mutex_lock(audio_output_mutex);
+ audio_outputqueue->push(out_a_frame);
+ a_outsize = audio_outputqueue->size();
+ pthread_mutex_unlock(audio_output_mutex);
// Unlock output mutex
+
+ // Kick multiplexer (audio)
+ sem_post(audio_output_sem);
}
delete item;
test++;
- if(test % (25 * 24) == 0) info->info("Input pool size: %d, output pool size: %d", insize, outsize);
-
- // Kick frame writer
- sem_post(output_sem);
+ if(test % (25 * 24) == 0)
+ info->info("Input pool size: %d, video output pool size: %d, audio output pool size: %d",
+ insize, v_outsize, a_outsize);
// Kick reader
sem_post(read_sem);
diff --git a/src/mov_encoder.h b/src/mov_encoder.h
index cb233e5..6862c84 100644
--- a/src/mov_encoder.h
+++ b/src/mov_encoder.h
@@ -55,7 +55,8 @@ class MovEncoder : public Thread {
public:
MovEncoder(sem_t *r_sem,
FrameVectorQueue *in, sem_t *in_sem, pthread_mutex_t *in_mutex,
- FramePriorityQueue *out, sem_t *out_sem, pthread_mutex_t *out_mutex,
+ FramePriorityQueue *v_out, pthread_mutex_t *v_out_mutex, sem_t *v_out_sem,
+ FramePriorityQueue *a_out, pthread_mutex_t *a_out_mutex, sem_t *a_out_sem,
Info *info);
~MovEncoder();
@@ -71,16 +72,19 @@ private:
// Input/Output queues
FrameVectorQueue *inputqueue;
- FramePriorityQueue *outputqueue;
+ FramePriorityQueue *video_outputqueue;
+ FramePriorityQueue *audio_outputqueue;
+ pthread_mutex_t *input_mutex;
+ pthread_mutex_t *video_output_mutex;
+ pthread_mutex_t *audio_output_mutex;
//thread stuff
sem_t *input_sem;
- sem_t *output_sem;
+ sem_t *video_output_sem;
+ sem_t *audio_output_sem;
sem_t *read_sem;
- pthread_mutex_t *input_mutex;
- pthread_mutex_t *output_mutex;
};
#endif
diff --git a/src/mov_encoder_thread.cc b/src/mov_encoder_thread.cc
index cfa6071..dc3581d 100644
--- a/src/mov_encoder_thread.cc
+++ b/src/mov_encoder_thread.cc
@@ -34,8 +34,16 @@ MovEncoderThread::MovEncoderThread(const char *cpr, Info *i)
info = i;
info->info("MovEncoderThread");
- outputqueue = new FramePriorityQueue();
+ // Queues
inputqueue = new FrameVectorQueue();
+ video_outputqueue = new FramePriorityQueue();
+ audio_outputqueue = new FramePriorityQueue();
+
+ // Queue mutexes
+ pthread_mutex_init (&input_mutex, NULL);
+ pthread_mutex_init (&video_output_mutex, NULL);
+ pthread_mutex_init (&audio_output_mutex, NULL);
+
block = new FrameVector();
num_frames_in_block = config->readString("frame_sequence")->length();
@@ -46,28 +54,26 @@ MovEncoderThread::MovEncoderThread(const char *cpr, Info *i)
// Thread stuff
sem_init(&in_sem, 0, 0);
- sem_init(&out_sem, 0, 0);
+ sem_init(&video_out_sem, 0, 0);
+ sem_init(&audio_out_sem, 0, 0);
sem_init(&read_sem, 0, 0);
for(int cnt = 0; cnt < threads; cnt++) sem_post(&read_sem);
- pthread_mutex_init (&input_mutex, NULL);
- pthread_mutex_init (&output_mutex, NULL);
-
- writer = new MovEncoderWriter(cpr, outputqueue, &out_sem, &output_mutex, info);
+ writer = new MovEncoderWriter(cpr,
+ video_outputqueue, &video_output_mutex, &video_out_sem,
+ audio_outputqueue, &audio_output_mutex, &audio_out_sem,
+ info);
writer->run();
- // writer_tid = new pthread_t;
- //pthread_create (writer_tid, NULL, thread_run, writer);
for(int cnt = 0; cnt < threads; cnt++) {
MovEncoder *movenc = new MovEncoder(&read_sem,
inputqueue, &in_sem, &input_mutex,
- outputqueue, &out_sem, &output_mutex,
+ video_outputqueue, &video_output_mutex, &video_out_sem,
+ audio_outputqueue, &audio_output_mutex, &audio_out_sem,
info);
movenc->run();
encs.push_back(movenc);
- // tids.push_back(new pthread_t);
- // pthread_create (tids[cnt], NULL, thread_run, encs[cnt]);
}
frame_number = 0;
@@ -80,9 +86,10 @@ MovEncoderThread::~MovEncoderThread()
// These should not be deleted here... its done elsewhere.
// inputqueue = NULL;
- sem_post(&out_sem);
+ sem_post(&video_out_sem);
+ sem_post(&audio_out_sem);
- // Stop the encoding threads.
+ // Tell the encoding threads to stop.
for(int cnt = 0; cnt < threads; cnt++) {
encs[cnt]->running = false;
}
@@ -94,27 +101,29 @@ MovEncoderThread::~MovEncoderThread()
// They should be exited now, so we can delete them.
for(int cnt = 0; cnt < threads; cnt++) {
- // pthread_join(*tids[cnt], NULL);
+ // Wait for it to stop
+ encs[cnt]->wait_stop();
+ // Delete it
delete encs[cnt];
- // delete tids[cnt];
}
// Tell the writer to stop
writer->running = false;
// Kick it to make it stop.
- sem_post(&out_sem);
+ sem_post(&video_out_sem);
+ sem_post(&audio_out_sem);
- // Destroy the thread
- // pthread_join(*writer_tid, NULL);
- // delete writer_tid;
+ // Wait for it to stop.
+ writer->wait_stop();
// delete the writer (end thereby close the file)
delete writer;
// Destroy the semaphores.
sem_destroy(&in_sem);
- sem_destroy(&out_sem);
+ sem_destroy(&video_out_sem);
+ sem_destroy(&audio_out_sem);
sem_destroy(&read_sem);
}
@@ -157,5 +166,5 @@ void MovEncoderThread::encode(Frame* frame)
block = new FrameVector;
}
- frame_number += 2;
+ frame_number ++;
}
diff --git a/src/mov_encoder_thread.h b/src/mov_encoder_thread.h
index 5d38d3b..5684edf 100644
--- a/src/mov_encoder_thread.h
+++ b/src/mov_encoder_thread.h
@@ -52,17 +52,20 @@ private:
Info *info;
FrameVectorQueue *inputqueue;
- FramePriorityQueue *outputqueue;
+ FramePriorityQueue *video_outputqueue;
+ FramePriorityQueue *audio_outputqueue;
FrameVector *block;
//thread stuff
sem_t in_sem;
- sem_t out_sem;
+ sem_t video_out_sem;
+ sem_t audio_out_sem;
sem_t read_sem;
pthread_mutex_t input_mutex;
- pthread_mutex_t output_mutex;
+ pthread_mutex_t video_output_mutex;
+ pthread_mutex_t audio_output_mutex;
// Used for encoder switching
unsigned int frame_number;
diff --git a/src/mov_encoder_writer.cc b/src/mov_encoder_writer.cc
index f408417..bc9302a 100644
--- a/src/mov_encoder_writer.cc
+++ b/src/mov_encoder_writer.cc
@@ -44,10 +44,11 @@ using namespace std;
#include <time.h>
+#include "multiplexer.h"
+
MovEncoderWriter::MovEncoderWriter(const char* cpr,
- FramePriorityQueue *q,
- sem_t *s,
- pthread_mutex_t *m,
+ FramePriorityQueue *v_q, pthread_mutex_t *v_m, sem_t *v_s,
+ FramePriorityQueue *a_q, pthread_mutex_t *a_m, sem_t *a_s,
Info *i)
{
info = i;
@@ -80,12 +81,21 @@ MovEncoderWriter::MovEncoderWriter(const char* cpr,
file = new File(fname, "mpg", info);
- sem = s;
- queue = q;
- frame_number = 0;
- mutex = m;
+ video_queue = v_q;
+ video_sem = v_s;
+ video_mutex = v_m;
+
+ audio_queue = a_q;
+ audio_sem = a_s;
+ audio_mutex = a_m;
+
+ video_frame_number = 0;
+ audio_frame_number = 0;
running = true;
+
+ // empty_timecode_struc(&SCR);
+ // timestamp = 0.0;
}
MovEncoderWriter::~MovEncoderWriter()
@@ -94,74 +104,128 @@ MovEncoderWriter::~MovEncoderWriter()
delete file;
}
-//#define WRITE_DV 1
void MovEncoderWriter::thread_main()
{
info->info("MovEncoderWriter::run");
- Frame *frame;
+ Multiplexer multiplexer(file, info, &running,
+ video_queue, video_mutex, video_sem,
+ audio_queue, audio_mutex, audio_sem);
+ multiplexer.multiplex();
-#ifndef WRITE_DV
-
- write_header();
-
-#endif/*WRITE_DV*/
-
- while(running) {
- sem_wait(sem);
+#if 0
+ int wrote = 0;
+ while(running ) {
+ sem_wait(audio_sem);
// Lock output mutex
- pthread_mutex_lock(mutex);
- frame = queue->top();
- if(frame && frame->number == frame_number) queue->pop();
- // poolsize = queue->size();
- pthread_mutex_unlock(mutex);
+ pthread_mutex_lock(audio_mutex);
+ audio_frame = audio_queue->top();
+ if(audio_frame && audio_frame->number == audio_frame_number) audio_queue->pop();
+ pthread_mutex_unlock(audio_mutex);
// Unlock output mutex
- int wrote = 0;
- while(frame && (frame->number == frame_number)) {
+ while(audio_frame && (audio_frame->number == audio_frame_number)) {
+ if(file->Write(audio_frame->data, audio_frame->size) == -1) {
+ info->error("File write returned -1.");
+ return;
+ }
- int ret = 0;
+ delete audio_frame;
+ audio_frame = NULL;
+
+ wrote ++;
+ audio_frame_number++;
+
+ // Lock output mutex
+ pthread_mutex_lock(audio_mutex);
+ audio_frame = audio_queue->top();
+ if(audio_frame && audio_frame->number == audio_frame_number) audio_queue->pop();
+ pthread_mutex_unlock(audio_mutex);
+ // Unlock output mutex
+ }
+ }
+#endif/*0*/
+
+ // info->info("Wrote %d mpeg packets.", wrote);
+ info->info("MovEncoderWriter::stop");
+}
+
-#ifndef WRITE_DV
- if(frame->number%2 == 1) write_audio_header((unsigned short int)frame->size);
- else write_video_header((unsigned short int)frame->size);
- ret = file->Write(frame->data, frame->size);
-#else/*WRITE_DV*/
- if(frame->number%2 == 0) ret = file->Write(frame->data, frame->size);
-#endif/*WRITE_DV*/
- frame_number++;
- wrote ++;
- delete frame;
- if(ret == -1) {
- info->error("File write returned -1.");
- return;
- }
- // Lock output mutex
- pthread_mutex_lock(mutex);
- frame = queue->top();
- if(frame && frame->number == frame_number) queue->pop();
- // poolsize = queue->size();
- pthread_mutex_unlock(mutex);
- // Unlock output mutex
- }
- }
- info->info("MovEncoderWriter::stop");
-}
-void MovEncoderWriter::write_header()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+void MovEncoderWriter::write_system_header(unsigned int audio_size, unsigned int video_size)
{
+ /*
+ Sys_header_struc sys_header;
+
+ unsigned int mux_rate = (audio_size + video_size) * 25;
+
+ create_sys_header(&sys_header,
+ mux_rate, //unsigned int rate_bound,
+ 1, //unsigned char audio_bound,
+ 1, //unsigned char fixed,
+ 1, //unsigned char CSPS,
+ 1, //unsigned char audio_lock,
+ 1, //unsigned char video_lock,
+ 1, //unsigned char video_bound,
+
+ AUDIO_STR_0, //unsigned char stream1,
+ 0, //unsigned char buffer1_scale,
+ audio_size, //unsigned int buffer1_size,
+ // audio_size/128, //unsigned int buffer1_size,
+
+ VIDEO_STR_0, //unsigned char stream2,
+ 1, //unsigned char buffer2_scale,
+ // video_size/1024, //unsigned int buffer2_size,
+ video_size, //unsigned int buffer2_size,
+
+ // We both have audio *and* video
+ STREAMS_BOTH);//unsigned int which_streams
+
+// create_sys_header (sys_header, mux_rate, 1, 1, 1, 1, 1, 1,
+// AUDIO_STR_0, 0, audio_size/128,
+// VIDEO_STR_0, 1, video_size/1024, STREAMS_BOTH );
+
+ file->Write(sys_header.buf, sizeof(sys_header.buf));
+*/
+ /**
+ * My shot at a valid system header
+ */
+ /*
// PACK
char pack_start_code[] = {
0x00, 0x00, 0x01, 0xBA,
@@ -177,6 +241,7 @@ void MovEncoderWriter::write_header()
};
file->Write(pack_data, sizeof(pack_data));
+ */
/*
// SYSTEM
char system_header_start_code[] = {
@@ -216,6 +281,28 @@ void MovEncoderWriter::write_header()
*/
}
+void MovEncoderWriter::write_packet_header(unsigned int audio_size, unsigned int video_size)
+{
+ /*
+ Pack_struc pack;
+ timestamp += 1.0;
+ make_timecode(timestamp, &SCR);
+ // Timecode_struc SCR;
+ unsigned int mux_rate = (audio_size + video_size) * 25;
+ // SCR.
+
+ create_pack(&pack, mux_rate, &SCR);
+
+ file->Write(pack.buf, sizeof(pack.buf));
+
+ unsigned char timestampbuf[32];
+ unsigned char *i = timestampbuf;
+ buffer_timecode (&SCR, MARKER_JUST_PTS, &i);
+
+ file->Write(timestampbuf, (int)i - (int)timestampbuf);
+ */
+}
+
void MovEncoderWriter::write_video_header(unsigned short int psize)
{
// PES Header startcode
@@ -283,10 +370,7 @@ void MovEncoderWriter::write_audio_header(unsigned short int psize)
file->Write(streamID, sizeof(streamID));
- psize +=
- sizeof(stuffing_bytes) +
- sizeof(std_buffer) +
- sizeof(PTS);
+ psize += sizeof(stuffing_bytes) + sizeof(std_buffer) + sizeof(PTS);
packetsize[0] = ((char*)&psize)[1];
packetsize[1] = ((char*)&psize)[0];
file->Write(packetsize, sizeof(packetsize));
@@ -299,3 +383,4 @@ void MovEncoderWriter::write_audio_header(unsigned short int psize)
}
+#endif /*0*/
diff --git a/src/mov_encoder_writer.h b/src/mov_encoder_writer.h
index f74dc51..e653223 100644
--- a/src/mov_encoder_writer.h
+++ b/src/mov_encoder_writer.h
@@ -36,12 +36,14 @@
#include <string>
using namespace std;
+#define AUDIO_FRAME(x) x->number%2==1
+#define VIDEO_FRAME(x) x->number%2==0
+
class MovEncoderWriter : public Thread {
public:
MovEncoderWriter(const char* cpr,
- FramePriorityQueue *q,
- sem_t *s,
- pthread_mutex_t *m,
+ FramePriorityQueue *video_queue, pthread_mutex_t *video_mutex, sem_t *video_sem,
+ FramePriorityQueue *audio_queue, pthread_mutex_t *audio_mutex, sem_t *audio_sem,
Info *info);
~MovEncoderWriter();
@@ -54,16 +56,23 @@ private:
File *file;
- FramePriorityQueue *queue;
- pthread_mutex_t *mutex;
+ FramePriorityQueue *video_queue;
+ FramePriorityQueue *audio_queue;
+ pthread_mutex_t *video_mutex;
+ pthread_mutex_t *audio_mutex;
+ sem_t *video_sem;
+ sem_t *audio_sem;
- sem_t *sem;
+ unsigned int video_frame_number;
+ unsigned int audio_frame_number;
- unsigned int frame_number;
+ // Timecode_struc SCR;
+ // double timestamp;
- void write_audio_header(unsigned short int packetsize);
- void write_video_header(unsigned short int packetsize);
- void write_header();
+// void write_audio_header(unsigned short int packetsize);
+// void write_video_header(unsigned short int packetsize);
+// void write_system_header(unsigned int audio_size, unsigned int video_size);
+// void write_packet_header(unsigned int audio_size, unsigned int video_size);
};
diff --git a/src/thread.cc b/src/thread.cc
index 23b142a..2791c53 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -45,3 +45,8 @@ void Thread::run()
{
pthread_create (&tid, NULL, thread_run, this);
}
+
+void Thread::wait_stop()
+{
+ pthread_join (tid, NULL);
+}
diff --git a/src/thread.h b/src/thread.h
index 3ed3c93..6b7a52a 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -37,9 +37,10 @@ public:
virtual ~Thread();
void run();
+ void wait_stop();
virtual void thread_main() = 0;
-
+
private:
pthread_t tid;
};