diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.am | 5 | ||||
| -rw-r--r-- | src/frame.h | 4 | ||||
| -rw-r--r-- | src/iso11172-1.h | 110 | ||||
| -rw-r--r-- | src/iso11172-2.h | 73 | ||||
| -rw-r--r-- | src/iso11172-3.h | 85 | ||||
| -rw-r--r-- | src/libfame_wrapper.cc | 29 | ||||
| -rw-r--r-- | src/libfame_wrapper.h | 2 | ||||
| -rw-r--r-- | src/liblame_wrapper.cc | 6 | ||||
| -rw-r--r-- | src/mov_encoder.cc | 69 | ||||
| -rw-r--r-- | src/mov_encoder.h | 14 | ||||
| -rw-r--r-- | src/mov_encoder_thread.cc | 51 | ||||
| -rw-r--r-- | src/mov_encoder_thread.h | 9 | ||||
| -rw-r--r-- | src/mov_encoder_writer.cc | 195 | ||||
| -rw-r--r-- | src/mov_encoder_writer.h | 29 | ||||
| -rw-r--r-- | src/thread.cc | 5 | ||||
| -rw-r--r-- | src/thread.h | 3 | 
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;  };  | 
