summaryrefslogtreecommitdiff
path: root/src/multiplexer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/multiplexer.cc')
-rw-r--r--src/multiplexer.cc315
1 files changed, 315 insertions, 0 deletions
diff --git a/src/multiplexer.cc b/src/multiplexer.cc
new file mode 100644
index 0000000..3d764dd
--- /dev/null
+++ b/src/multiplexer.cc
@@ -0,0 +1,315 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multiplexer.cc
+ *
+ * Wed Aug 31 13:05:18 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 "multiplexer.h"
+
+#include <netinet/in.h>
+#include <math.h>
+
+#define SIZEOF(x) (sizeof(x)-1)
+
+// Audio index lists
+/*
+static unsigned int frequency_index[4] = {44100, 48000, 32000, 0};
+//static unsigned int slots [4] = {12, 144, 0, 0};
+//static unsigned int slot_index [4] = {144, 144, 144, 0};
+//static unsigned int sample_index [4] = {384, 1152, 0, 0};
+static unsigned int bitrate_index [4][16] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0}, // Reserved
+ {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0}, // Layer III
+ {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0}, // Layer II
+ {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0} // Layer I
+};
+static char layer_index[4][12] = { "Reserved", "Layer III", "Layer II", "Layer I" };
+static char mode_index[4][32] = { "Stereo", "Joint Stereo", "Dual Channel", "Single Channel"};
+static char protection_index[2][32] = { "CRC check enabled", "CRC check disabled" };
+*/
+//static unsigned short int syncword = 0xFFF;
+
+// Video index lists
+/*
+#define FORBIDDEN -1.0
+#define RESERVED -2.0
+static double picture_rate_index[16] = {
+ FORBIDDEN, 23.976, 24.0, 25.0, 29.97, 30.0, 50.0, 59.94, 60,
+ RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED
+};
+*/
+
+Multiplexer::Multiplexer(File *f, Info *i, volatile bool *r,
+ FramePriorityQueue *v_q, pthread_mutex_t *v_m, sem_t *v_s,
+ FramePriorityQueue *a_q, pthread_mutex_t *a_m, sem_t *a_s)
+{
+ running = r;
+ file = f;
+ info = i;
+
+ queue[TYPE_VIDEO] = v_q;
+ queue[TYPE_AUDIO] = a_q;
+
+ sem[TYPE_VIDEO] = v_s;
+ sem[TYPE_AUDIO] = a_s;
+
+ mutex[TYPE_VIDEO] = v_m;
+ mutex[TYPE_AUDIO] = a_m;
+
+ frame[TYPE_VIDEO] = NULL;
+ frame[TYPE_AUDIO] = NULL;
+
+ frame_number[TYPE_VIDEO] = 0;
+ frame_number[TYPE_AUDIO] = 0;
+
+ write_system_header = 0;
+ write_audio_packet = 0;
+
+ audio_header_read = false;
+
+ written[TYPE_VIDEO] = 0.0;
+ written[TYPE_AUDIO] = 0.0;
+}
+
+Multiplexer::~Multiplexer()
+{
+}
+
+
+int Multiplexer::read_stream(char *buf, unsigned int size, StreamType type)
+{
+ Frame *tmpframe;
+ unsigned int copied = 0;
+
+ while(copied < size && (*running) ) {
+
+ // If we read the entire frame, prepare to get a new one
+ if(frame[type] && read[type] == frame[type]->size) {
+ delete frame[type];
+ frame[type] = NULL;
+ }
+
+ // If no frame is in the buffer, get one from the queue
+ while( frame[type] == NULL && (*running) ) {
+ sem_wait(sem[type]);
+
+ // Lock output mutex
+ pthread_mutex_lock( mutex[type] );
+ tmpframe = queue[type]->top();
+ if(tmpframe && tmpframe->number == frame_number[type] ) {
+ queue[type]->pop();
+ frame[type] = tmpframe;
+ frame_number[type]++;
+ read[type] = 0;
+ }
+ pthread_mutex_unlock( mutex[type] );
+ // Unlock output mutex
+ }
+
+ // If a frame exists in the buffer copy it to the output buffer
+ // (No frame ocurres when *running is set to false)
+ if( frame[type] ) {
+ unsigned int doread = (size - copied) < (frame[type]->size - read[type]) ?
+ size - copied : (frame[type]->size - read[type]);
+
+ //info->info("Requested: %d. Read: %d. Doread: %d. In buffer %d", size, (*read), doread, (*frame)->size);
+
+ memcpy(buf + copied, frame[type]->data + read[type], doread);
+ read[type] += doread;
+ copied += doread;
+ }
+ }
+
+ return copied;
+}
+
+void Multiplexer::packet(StreamType type)
+{
+ char buf[1000000];
+
+ file->Write((void*)ISO11172_1::packet_start_code_prefix, SIZEOF(ISO11172_1::packet_start_code_prefix));
+ switch(type) {
+ case TYPE_VIDEO:
+ file->Write((void*)ISO11172_1::stream_id_video1, SIZEOF(ISO11172_1::stream_id_video1));
+ break;
+ case TYPE_AUDIO:
+ file->Write((void*)ISO11172_1::stream_id_audio1, SIZEOF(ISO11172_1::stream_id_audio1));
+ break;
+ }
+
+ // Write data
+ info->info("\t\t[%sPacket]", type==TYPE_AUDIO?"Audio\0":"Video\0");
+
+ unsigned short int hton_framesize = PACKET_SIZE + 1;
+ hton_framesize = htons(hton_framesize);
+ file->Write((char*)&hton_framesize, sizeof(hton_framesize));
+
+ char dims[] = "\x0F";
+ file->Write(dims, 1);
+
+ file->Write(buf, read_stream(buf, PACKET_SIZE, type));
+
+ written[type] += (double)PACKET_SIZE / (double)frame[type]->bitrate;
+}
+
+/**
+ * Create and write a packet
+ */
+void Multiplexer::packet()
+{
+ info->info("\t\tWritten[A]: %f, Written[V]: %f", written[TYPE_AUDIO], written[TYPE_VIDEO]);
+
+ // New switching mechanism
+ if(written[TYPE_AUDIO] < written[TYPE_VIDEO]) {
+ packet(TYPE_AUDIO);
+ } else {
+ packet(TYPE_VIDEO);
+ }
+
+
+ // Count this up here, we want audio packets in packet 4, 9, ... NOT 0, 3, ...
+ /*
+ write_audio_packet++;
+ if(write_audio_packet % AUDIO_PACKET_FREQUENCY == 0) {
+ packet(TYPE_AUDIO);
+ } else {
+ packet(TYPE_VIDEO);
+ }
+ */
+}
+
+/**
+ * Create and write the system header
+ */
+void Multiplexer::system_header()
+{
+ info->info("\t\t[System Header]");
+
+ // system_header_start_code (32 bits)
+ file->Write((void*)ISO11172_1::system_header_start_code, SIZEOF(ISO11172_1::system_header_start_code));
+
+ // header_length (16 bits)
+ char system_header_length[] = "\x00\x0C";
+ file->Write(system_header_length, SIZEOF(system_header_length));
+
+ // marker_bit (1 bit) \.
+ // rate_bound (22 bits) ) (24 bits)
+ // marker_bit (1 bit) /
+ char rate_bound[] = "\x80\x1B\x83";
+ file->Write(rate_bound, SIZEOF(rate_bound));
+
+ // audio_bound (6 bits) \.
+ // fixed_flag (1 bit) ) (8 bits)
+ // CSPS_flag (1 bit) /
+ char audio_bound[] = "\x06"; // One audio stream, fixed bitrate and not iso costraint compliant
+ file->Write(audio_bound, SIZEOF(audio_bound));
+
+ // system_audio_lock_flag (1 bit) \.
+ // system_video_lock_flag (1 bit) \.
+ // marker_bit (1 bit) ) (8 bits)
+ // video_bound (5 bits) _/
+ char video_bound[] = "\xE1"; // Audio and Video are locked and there are only one video stream
+ file->Write(video_bound, SIZEOF(video_bound));
+
+ // reserved_byte (8 bit)
+ char reserved_byte[] = "\xFF";
+ file->Write(reserved_byte, SIZEOF(reserved_byte));
+
+ { // Audio
+ // stream_id (8 bit)
+ char stream_id[] = "\xC0";
+ file->Write(stream_id, SIZEOF(stream_id));
+
+ // '11' (2 bits) \.
+ // STD_buffer_bound_scale (1 bit) ) (24 bits)
+ // STD_buffer_size_bound (13 bits) /
+ char reserved_byte[] = "\xC0\x20";
+ file->Write(reserved_byte, SIZEOF(reserved_byte));
+ }
+
+ { // Video
+ // stream_id (8 bit)
+ char stream_id[] = "\xE3";
+ file->Write(stream_id, SIZEOF(stream_id));
+
+ // '11' (2 bits) \.
+ // STD_buffer_bound_scale (1 bit) ) (24 bits)
+ // STD_buffer_size_bound (13 bits) /
+ char reserved_byte[] = "\xE0\x2E";
+ file->Write(reserved_byte, SIZEOF(reserved_byte));
+ }
+}
+
+/**
+ * Create and write a pack
+ */
+void Multiplexer::pack()
+{
+ info->info("\t[Pack");
+
+ file->Write((void*)ISO11172_1::pack_start_code, SIZEOF(ISO11172_1::pack_start_code));
+
+ // Stuff! FIXME: Change this
+ char stuff[] = "\x21\x00\x01\x1E\x81\x80\x1B\x83";
+ file->Write(stuff, SIZEOF(stuff));
+
+ if(write_system_header % SYSTEM_HEADER_FREQUENCY == 0) system_header();
+ // Count this up here, we want a system header in pack 0, 5, ... NOT 4, 9, ...
+ write_system_header++;
+
+ for(int cnt = 0; cnt < NUMBER_OF_PACKETS_IN_A_PACK; cnt++) packet();
+ info->info("\t]");
+}
+
+/**
+ *
+ */
+void Multiplexer::iso11172_stream()
+{
+ info->info("[iso11172_stream");
+ while(*running) {
+ pack();
+ }
+ info->info("]");
+ info->info("[iso11172_end_code]");
+ file->Write((void*)ISO11172_1::end_code, SIZEOF(ISO11172_1::end_code));
+}
+
+//#define BYPASS TYPE_VIDEO
+//#define BYPASS TYPE_AUDIO
+void Multiplexer::multiplex()
+{
+#ifdef BYPASS
+
+ char buf[1024];
+ while(*running) file->Write(buf, read_stream(buf, sizeof(buf), BYPASS));
+ return;
+
+#else/*BYPASS*/
+
+ iso11172_stream();
+
+#endif/*BYPASS*/
+}