diff options
author | deva <deva> | 2005-09-12 15:46:52 +0000 |
---|---|---|
committer | deva <deva> | 2005-09-12 15:46:52 +0000 |
commit | 2a6d51ad49faa39af5e627df605d3365503b5cb4 (patch) | |
tree | 5b21988cf7457ca7cabc2cd945a61a41714b6001 /src/multiplexer.cc | |
parent | 701608f39c59b530f6cede66ec24e9ddda8beae6 (diff) |
*** empty log message ***
Diffstat (limited to 'src/multiplexer.cc')
-rw-r--r-- | src/multiplexer.cc | 315 |
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*/ +} |