/* -*- 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 MovEncoderWriter::MovEncoderWriter(const char* cpr, FramePriorityQueue *q, sem_t *s, pthread_mutex_t *m, 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); sem = s; queue = q; frame_number = 0; mutex = m; running = true; } MovEncoderWriter::~MovEncoderWriter() { info->info("~MovEncoderWriter"); delete file; } //#define WRITE_DV 1 void MovEncoderWriter::thread_main() { info->info("MovEncoderWriter::run"); Frame *frame; #ifndef WRITE_DV write_header(); #endif/*WRITE_DV*/ while(running) { sem_wait(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); // Unlock output mutex int wrote = 0; while(frame && (frame->number == frame_number)) { int ret = 0; #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() { // 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_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)); }