diff options
| -rw-r--r-- | src/multiplexer.cc | 315 | ||||
| -rw-r--r-- | src/multiplexer.h | 118 | 
2 files changed, 433 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*/ +} diff --git a/src/multiplexer.h b/src/multiplexer.h new file mode 100644 index 0000000..25c89e0 --- /dev/null +++ b/src/multiplexer.h @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            multiplexer.h + * + *  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" +#ifndef __MIAV_MULTIPLEXER_H__ +#define __MIAV_MULTIPLEXER_H__ + +#include "iso11172-1.h" +#include "iso11172-2.h" +#include "iso11172-3.h" + +#include "file.h" +#include "info.h" +#include "frame.h" + +/** + * Multiplexer configuration + */ +// How many packets should we put in one pack +#define NUMBER_OF_PACKETS_IN_A_PACK 3 + +// How many packets bewteen audio packs +#define AUDIO_PACKET_FREQUENCY 10 + +// How many packs bewteen system headers +#define SYSTEM_HEADER_FREQUENCY 5 + +// Size of video or audio data pr. packet +#define PACKET_SIZE 2048 + +/** + * Other stuff + */ +// The number of streamtypes. +#define NUM_TYPES 2 + +// Enum of the streamtypes. +typedef enum { +  TYPE_VIDEO, +  TYPE_AUDIO +} StreamType; + + +class Multiplexer { +public: +  Multiplexer(File *file, Info *info, volatile bool *running, +              FramePriorityQueue *v_q, pthread_mutex_t *v_m, sem_t *v_s,  +              FramePriorityQueue *a_q, pthread_mutex_t *a_m, sem_t *a_s); +  ~Multiplexer(); + +  void multiplex(); + +private: +  double written[NUM_TYPES]; + +  void iso11172_stream(); +  void pack(); +  void system_header(); +  void packet(); +  void packet(StreamType type); +  /* +  void audio_packet(); +  void video_packet(); + +  void audio_data(ISO11172_3::header *header); +  void audio_data_layer_I(ISO11172_3::header *header); +  void audio_data_layer_II(ISO11172_3::header *header); +  void audio_data_layer_III(ISO11172_3::header *header); + +  void video_data(ISO11172_2::sequence_header_1 *header1, +                  ISO11172_2::sequence_header_2 *header2); +  */ +  // Frequency variables +  unsigned int write_system_header; +  unsigned int write_audio_packet; + +  int read_stream(char *buf, unsigned int size, StreamType type); + +  FramePriorityQueue *queue[NUM_TYPES]; +  pthread_mutex_t *mutex[NUM_TYPES]; +  sem_t *sem[NUM_TYPES]; + +  Frame *frame[NUM_TYPES]; +  unsigned int frame_number[NUM_TYPES]; +  unsigned int read[NUM_TYPES]; + +  File *file; +  Info *info; +  volatile bool *running; + +  // Audio Header + bool audio_header_read; +}; + +#endif/*__MIAV_MULTIPLEXER_H__*/ | 
