/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * mov_encoder_writer.cc * * Sun May 22 12:51:36 CEST 2005 * Copyright 2005 Bent Bisballe * 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 #include "mov_encoder_writer.h" #include #include #include #include #include #include #include #include using namespace std; #include "miav_config.h" #include #include "multiplexer.h" MovEncoderWriter::MovEncoderWriter(const char* cpr, 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; info->info("MovEncoderWriter"); // Create path and filename char fname[256]; string *server_root; char birthmonth[3]; char date[32]; // Get server root server_root = config->readString("server_movie_root"); // Copy the bytes representing the birth month from the cpr // [dd][mm][yy]-[nn][nn] strncpy(birthmonth, &cpr[2], 2); birthmonth[2] = 0; // Create date (today) in [yyyy][mm][dd] struct tm *ltime; time_t t = time(NULL); ltime = localtime(&t); sprintf(date, "%.4d%.2d%.2d", ltime->tm_year + 1900, ltime->tm_mon, ltime->tm_mday); sprintf(fname, "%s/%s/%s/%s-%s-", server_root->c_str(), birthmonth, cpr, cpr, date); file = new File(fname, "mpg", info); 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() { info->info("~MovEncoderWriter"); delete file; } void MovEncoderWriter::thread_main() { info->info("MovEncoderWriter::run"); Multiplexer multiplexer(file, info, &running, video_queue, video_mutex, video_sem, audio_queue, audio_mutex, audio_sem); multiplexer.multiplex(); #if 0 int wrote = 0; while(running ) { sem_wait(audio_sem); // 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 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; } 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"); } #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, }; file->Write(pack_start_code, sizeof(pack_start_code)); char pack_data[] = { 0x21, // SCR-32 thru 30, marker bit 0x00, 0x01, // SCR-29 thru 15, marker bit 0x80, 0xF5, // SCR-14 thru 0, marker bit 0x80, 0x1B, 0x83 // Marker bit, mux_rate, marker_bit }; file->Write(pack_data, sizeof(pack_data)); */ /* // SYSTEM char system_header_start_code[] = { 0x00, 0x00, 0x01, 0xBB, }; file->Write(system_header_start_code, sizeof(system_header_start_code)); char system_data[] = { 0x00, 0x0C, // Header length 0x80, 0x1B, 0x83, // Marker bit, rate_bound,marker_bit 0x07, // Audio bound, fixed_flag, CSPS_flag 0xA1, // system_audio_lock_flag, system_video_lock_flag 0xFF, // Reserved byte 0xC0, // Stream id (audio) // 0xC0, 0x20, // '11', STD_buffer_bound_scale, STD_buffer_size_bound 0xFF, 0xFF, // '11', STD_buffer_bound_scale, STD_buffer_size_bound 0xE0, // Stream id (video) // 0xE0, 0x2E // '11', STD_buffer_bound_scale, STD_buffer_size_bound 0xFF, 0xFF // '11', STD_buffer_bound_scale, STD_buffer_size_bound }; file->Write(system_data, sizeof(system_data)); char padding_header_start_code[] = { 0x00, 0x00, 0x01, 0xBE }; file->Write(padding_header_start_code, sizeof(padding_header_start_code)); char padding_data[] = { 0x00, 0x04, // Padding length 0x0F, 0xFF, 0xFF, 0xFF // Padding }; file->Write(padding_data, sizeof(padding_data)); */ } 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 char startcode[] = { 0x00, 0x00, 0x01 }; // Video stream, index = 0 char streamID[] = { 0xE0 }; char packetsize[] = { 0x00, 0x00 }; char stuffing_bytes[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F }; file->Write(startcode, sizeof(startcode)); file->Write(streamID, sizeof(streamID)); psize += sizeof(stuffing_bytes); packetsize[0] = ((char*)&psize)[1]; packetsize[1] = ((char*)&psize)[0]; file->Write(packetsize, sizeof(packetsize)); file->Write(stuffing_bytes, sizeof(stuffing_bytes)); } void MovEncoderWriter::write_audio_header(unsigned short int psize) { // PES Header startcode char startcode[] = { 0x00, 0x00, 0x01 }; // Audio stream, index = 0 char streamID[] = { 0xC0 }; char packetsize[] = { 0x00, 0x00 }; char stuffing_bytes[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; char std_buffer[] = { 0x40, // STD_buffer_scale 0x20 // STD_buffer_size }; char PTS[] = { 0x21, // SCR-32 thru 30, marker bit 0x00, 0x01, // SCR-29 thru 15, marker bit 0xCE, 0x37 // SCR-14 thru 0, marker bit }; file->Write(startcode, sizeof(startcode)); file->Write(streamID, sizeof(streamID)); psize += sizeof(stuffing_bytes) + sizeof(std_buffer) + sizeof(PTS); packetsize[0] = ((char*)&psize)[1]; packetsize[1] = ((char*)&psize)[0]; file->Write(packetsize, sizeof(packetsize)); file->Write(stuffing_bytes, sizeof(stuffing_bytes)); file->Write(std_buffer, sizeof(std_buffer)); file->Write(PTS, sizeof(PTS)); } #endif /*0*/