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; }; |