From 0ef298aa78a315f64a6a686407f8f10694f0ea5d Mon Sep 17 00:00:00 2001 From: deva Date: Thu, 15 Sep 2005 19:31:16 +0000 Subject: *** empty log message *** --- src/iso11172-1.h | 17 ++++++ src/libfame_wrapper.cc | 17 +++--- src/libfame_wrapper.h | 1 + src/liblame_wrapper.cc | 44 ++++++++++++++- src/liblame_wrapper.h | 3 + src/mov_encoder.cc | 6 ++ src/multiplexer.cc | 148 ++++++++++++++++++++++++++++++++++++++++--------- src/multiplexer.h | 12 ++-- 8 files changed, 208 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/iso11172-1.h b/src/iso11172-1.h index f284410..e01b45b 100644 --- a/src/iso11172-1.h +++ b/src/iso11172-1.h @@ -37,6 +37,23 @@ #define CLOCK_90KHZ 90000 namespace ISO11172_1 { + //////////////////////////////////////////////////// + // Types + //////////////////////////////////////////////////// + // 64 bits (8 bytes) + typedef struct { + unsigned long long int marker_bit5:1; + unsigned long long int mux_rate:22; + unsigned long long int marker_bit4:1; + unsigned long long int marker_bit3:1; + unsigned long long int system_clock_reference3:15; + unsigned long long int marker_bit2:1; + unsigned long long int system_clock_reference2:15; + unsigned long long int marker_bit1:1; + unsigned long long int system_clock_reference1:3; + unsigned long long int padding:4; + } pack_header; + //////////////////////////////////////////////////// // Constants //////////////////////////////////////////////////// diff --git a/src/libfame_wrapper.cc b/src/libfame_wrapper.cc index 94989f1..5c71154 100644 --- a/src/libfame_wrapper.cc +++ b/src/libfame_wrapper.cc @@ -49,7 +49,8 @@ LibFAMEWrapper::LibFAMEWrapper(Info *i) yuv.v = new unsigned char [w*h];// [w*h/4] calc_bitrate = 0; - + frame_number = 0; + ////////////LIBDV STUFF/////////////// dvdecoder = NULL; // Initialize in encode method @@ -99,7 +100,7 @@ LibFAMEWrapper::LibFAMEWrapper(Info *i) fame_par.quality = config->readInt("frame_quality"); // Bitrate - fame_par.bitrate = 0; // video bitrate (0=VBR) + fame_par.bitrate = 150000; // video bitrate in bytes pr second (0=VBR) // slices_per_frame is the number of frame slices per frame. More slices provide // better error recovery. There must be at least one slice per frame, and at most @@ -226,8 +227,6 @@ 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) @@ -242,7 +241,10 @@ Frame *LibFAMEWrapper::encode(Frame *dvframe) pt += written; output->size += written; } - fame_end_frame(fame_context, &stats); + + // fame_frame_statistics_t stats; + + // 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, @@ -262,8 +264,9 @@ Frame *LibFAMEWrapper::encode(Frame *dvframe) float quant_scale; } */ - calc_bitrate += stats.actual_bits; - output->bitrate = (unsigned int)(((double)calc_bitrate / (double)(stats.frame_number+1)) * 25.0); + frame_number++; + calc_bitrate += output->size; //stats.actual_bits; + output->bitrate = (unsigned int)((double)calc_bitrate / (double)frame_number) * 25; return output; } diff --git a/src/libfame_wrapper.h b/src/libfame_wrapper.h index 6a6b569..bf9e7b9 100644 --- a/src/libfame_wrapper.h +++ b/src/libfame_wrapper.h @@ -50,6 +50,7 @@ public: private: unsigned long long calc_bitrate; + unsigned int frame_number; Info* info; diff --git a/src/liblame_wrapper.cc b/src/liblame_wrapper.cc index 6d78380..08765b7 100644 --- a/src/liblame_wrapper.cc +++ b/src/liblame_wrapper.cc @@ -42,7 +42,8 @@ LibLAMEWrapper::LibLAMEWrapper(Info *i) lame_set_out_samplerate(gfp, OUTPUT_SAMPLE_RATE); lame_set_num_channels(gfp, CHANNELS); - lame_set_num_samples(gfp, SAMPLES); + lame_set_num_samples(gfp, 1152); + // lame_set_num_samples(gfp, SAMPLES); lame_set_quality(gfp, config->readInt("mp3_quality")); lame_set_mode(gfp, STEREO); @@ -79,6 +80,9 @@ LibLAMEWrapper::LibLAMEWrapper(Info *i) // And now for the dv decoder! decoder = NULL; + + calc_bitrate = 0; + frame_number = 0; } LibLAMEWrapper::~LibLAMEWrapper() @@ -195,9 +199,43 @@ Frame *LibLAMEWrapper::encode(Frame *dvframe) mp3buf_size - val); // number of valid octets in this stream audio_frame->size = val + flush_sz; + /* + + int bitrate_kbps[14]; + // lame_bitrate_kbps(gfp, bitrate_kbps); + lame_bitrate_hist(gfp, bitrate_kbps); + // 32 40 48 56 64 80 96 112 128 160 192 224 256 320 + info->info("%d %d %d %d %d %d %d %d %d %d %d %d %d %d", + bitrate_kbps[0], + bitrate_kbps[1], + bitrate_kbps[2], + bitrate_kbps[3], + bitrate_kbps[4], + bitrate_kbps[5], + bitrate_kbps[6], + bitrate_kbps[7], + bitrate_kbps[8], + bitrate_kbps[9], + bitrate_kbps[10], + bitrate_kbps[11], + bitrate_kbps[12], + bitrate_kbps[13]); + */ + // while(frame_number != lame_get_frameNum(gfp)) { + + calc_bitrate += audio_frame->size;//lame_get_framesize(gfp); + frame_number ++;//= 1;//lame_get_frameNum(gfp); + + // info->info("lame_get_frameNum(gfp) %d ?= frame_number %d", lame_get_frameNum(gfp), frame_number); + // } // Bits pr. second - audio_frame->bitrate = config->readInt("mp3_bitrate") * 1000; - + // 25 * 7 frames pr.second (it seems!) + audio_frame->bitrate = (unsigned int)((double)calc_bitrate / (double)(frame_number)) * 25; + /* + info->info("Audio size: %d, bitrate: %.4f", + audio_frame->bitrate, + (float)(config->readInt("mp3_bitrate") * 1000)/(float)(audio_frame->bitrate)); + */ return audio_frame; } diff --git a/src/liblame_wrapper.h b/src/liblame_wrapper.h index 75f3b3d..b2851bf 100644 --- a/src/liblame_wrapper.h +++ b/src/liblame_wrapper.h @@ -54,6 +54,9 @@ public: Frame *encode(Frame *dvframe); private: + unsigned long long calc_bitrate; + int frame_number; + Info *info; // LAME stuff diff --git a/src/mov_encoder.cc b/src/mov_encoder.cc index a9a2ca2..4e8189c 100644 --- a/src/mov_encoder.cc +++ b/src/mov_encoder.cc @@ -165,5 +165,11 @@ void MovEncoder::thread_main() } } + // Kick multiplexer (audio) + sem_post(audio_output_sem); + + // Kick multiplexer (video) + sem_post(video_output_sem); + info->info("MovEncoder thread has stopped."); } diff --git a/src/multiplexer.cc b/src/multiplexer.cc index 3d764dd..d479627 100644 --- a/src/multiplexer.cc +++ b/src/multiplexer.cc @@ -91,6 +91,9 @@ Multiplexer::Multiplexer(File *f, Info *i, volatile bool *r, written[TYPE_VIDEO] = 0.0; written[TYPE_AUDIO] = 0.0; + + SCR = 3904;//0x40010003LL;//0x1E80; + } Multiplexer::~Multiplexer() @@ -103,7 +106,7 @@ int Multiplexer::read_stream(char *buf, unsigned int size, StreamType type) Frame *tmpframe; unsigned int copied = 0; - while(copied < size && (*running) ) { + while( copied < size ) { // If we read the entire frame, prepare to get a new one if(frame[type] && read[type] == frame[type]->size) { @@ -112,8 +115,12 @@ int Multiplexer::read_stream(char *buf, unsigned int size, StreamType type) } // If no frame is in the buffer, get one from the queue - while( frame[type] == NULL && (*running) ) { - sem_wait(sem[type]); + while( frame[type] == NULL ) { + + // if(!*running) info->warn("Halt detected!"); + + // If we are not running anymore, just process the last frames as fast as possible! + if(*running) sem_wait(sem[type]); // Lock output mutex pthread_mutex_lock( mutex[type] ); @@ -124,6 +131,11 @@ int Multiplexer::read_stream(char *buf, unsigned int size, StreamType type) frame_number[type]++; read[type] = 0; } + if(*running == false && frame[type] == NULL) { + pthread_mutex_unlock( mutex[type] ); + //info->info("Bailed out early %d!", copied); + return copied; + } pthread_mutex_unlock( mutex[type] ); // Unlock output mutex } @@ -145,9 +157,14 @@ int Multiplexer::read_stream(char *buf, unsigned int size, StreamType type) return copied; } -void Multiplexer::packet(StreamType type) +bool Multiplexer::packet(StreamType type) { - char buf[1000000]; + char buf[PACKET_SIZE]; + + // Write data + info->info("\t\t[%sPacket]", type==TYPE_AUDIO?"Audio\0":"Video\0"); + + unsigned short int framesize = read_stream(buf, PACKET_SIZE, type); file->Write((void*)ISO11172_1::packet_start_code_prefix, SIZEOF(ISO11172_1::packet_start_code_prefix)); switch(type) { @@ -159,38 +176,50 @@ void Multiplexer::packet(StreamType type) break; } - // Write data - info->info("\t\t[%sPacket]", type==TYPE_AUDIO?"Audio\0":"Video\0"); - - unsigned short int hton_framesize = PACKET_SIZE + 1; + unsigned short int hton_framesize = framesize + 1; // Need space for dims too! 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)); + file->Write(buf, framesize); + + if(framesize != PACKET_SIZE) return false; written[type] += (double)PACKET_SIZE / (double)frame[type]->bitrate; + + return true; } /** * Create and write a packet */ -void Multiplexer::packet() +bool Multiplexer::packet() { - info->info("\t\tWritten[A]: %f, Written[V]: %f", written[TYPE_AUDIO], written[TYPE_VIDEO]); + //info->info("\t\tWritten[A]: %f, Written[V]: %f", written[TYPE_AUDIO], written[TYPE_VIDEO]); + + StreamType type; // New switching mechanism if(written[TYPE_AUDIO] < written[TYPE_VIDEO]) { - packet(TYPE_AUDIO); + type = TYPE_AUDIO; } else { - packet(TYPE_VIDEO); + type = TYPE_VIDEO; } - - // Count this up here, we want audio packets in packet 4, 9, ... NOT 0, 3, ... + if(!packet(type)) { + // Flush the other stream too... + if(type == TYPE_AUDIO) type = TYPE_VIDEO; + else type = TYPE_AUDIO; + while(packet(type)); + return false; + } + return true; + /* + // 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); @@ -230,7 +259,7 @@ void Multiplexer::system_header() // 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 + char video_bound[] = "\x21"; // Audio and Video are not locked and there are only one video stream file->Write(video_bound, SIZEOF(video_bound)); // reserved_byte (8 bit) @@ -262,25 +291,88 @@ void Multiplexer::system_header() } } +#define MASK3 0x7 +#define MASK15 0x7FFF +#define TIMECODE32_30(x) ((x >> 30) & MASK3 ) +#define TIMECODE29_15(x) ((x >> 15) & MASK15) +#define TIMECODE14_0(x) ((x >> 0) & MASK15) + /** * Create and write a pack */ -void Multiplexer::pack() +bool 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)); + ISO11172_1::pack_header header; + // Set marker bits to 1 + header.marker_bit1 = + header.marker_bit2 = + header.marker_bit3 = + header.marker_bit4 = + header.marker_bit5 = 1; + + header.padding = 0x2; + + unsigned int video_data_rate; + unsigned int audio_data_rate; + + if(frame[TYPE_AUDIO]) audio_data_rate = frame[TYPE_AUDIO]->bitrate; + else audio_data_rate = 112000; + + if(frame[TYPE_VIDEO]) video_data_rate = frame[TYPE_VIDEO]->bitrate; + else video_data_rate = 1100000; + + unsigned int Rmux = ISO11172_1::Rmux(video_data_rate, + audio_data_rate, + 20, // packet_header_size, + 12, // pack_header_size, + PACKETS_PER_PACK, // packets_per_pack, + PACKET_SIZE);// packet_data_size) + + header.mux_rate = Rmux; + //0x1B82; + + SCR = ISO11172_1::SCR(SCR, + 12, //pack_header_size, + PACKETS_PER_PACK, //packets_per_pack, + PACKET_SIZE, //packet_data_size, + Rmux); + + // SCR = 0x40010003LL; + + header.system_clock_reference1 = TIMECODE32_30(SCR); + header.system_clock_reference2 = TIMECODE29_15(SCR); + header.system_clock_reference3 = TIMECODE14_0(SCR); + /* + info->info("timecode All: %lld, 1: %lld, 2: %lld, 3: %lld", + SCR, + (unsigned long long int)header.system_clock_reference1, + (unsigned long long int)header.system_clock_reference2, + (unsigned long long int)header.system_clock_reference3 + ); + */ + unsigned int *hton_header_u = (unsigned int *)&header; + unsigned int *hton_header_l = (unsigned int *)((char*)&header + sizeof(unsigned int)); + + *hton_header_u = htonl(*hton_header_u); + *hton_header_l = htonl(*hton_header_l); + + file->Write((char*)hton_header_u, sizeof(*hton_header_u)); + file->Write((char*)hton_header_l, sizeof(*hton_header_l)); 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(); + for(int cnt = 0; cnt < PACKETS_PER_PACK; cnt++) + if(!packet()) return false; + info->info("\t]"); + + return true; } /** @@ -289,12 +381,18 @@ void Multiplexer::pack() void Multiplexer::iso11172_stream() { info->info("[iso11172_stream"); - while(*running) { - pack(); - } + + while(pack()); + info->info("]"); info->info("[iso11172_end_code]"); file->Write((void*)ISO11172_1::end_code, SIZEOF(ISO11172_1::end_code)); + + /* + info->info("false && false = %d", false && false); + info->info("true && false = %d", true && false); + info->info("true && true = %d", true && true); + */ } //#define BYPASS TYPE_VIDEO diff --git a/src/multiplexer.h b/src/multiplexer.h index 25c89e0..c0ac663 100644 --- a/src/multiplexer.h +++ b/src/multiplexer.h @@ -40,7 +40,7 @@ * Multiplexer configuration */ // How many packets should we put in one pack -#define NUMBER_OF_PACKETS_IN_A_PACK 3 +#define PACKETS_PER_PACK 3 // How many packets bewteen audio packs #define AUDIO_PACKET_FREQUENCY 10 @@ -49,7 +49,7 @@ #define SYSTEM_HEADER_FREQUENCY 5 // Size of video or audio data pr. packet -#define PACKET_SIZE 2048 +#define PACKET_SIZE 2028 /** * Other stuff @@ -74,13 +74,15 @@ public: void multiplex(); private: + unsigned long long int SCR; + double written[NUM_TYPES]; void iso11172_stream(); - void pack(); + bool pack(); void system_header(); - void packet(); - void packet(StreamType type); + bool packet(); + bool packet(StreamType type); /* void audio_packet(); void video_packet(); -- cgit v1.2.3