/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * mov_encoder_thread.cc * * Tue May 17 16:00:01 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_thread.h" #include #include "miav_config.h" MovEncoderThread::MovEncoderThread(const char *cpr, Info *i) { info = i; info->info("MovEncoderThread"); // 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(); info->info("Frame sequence length %d", num_frames_in_block); threads = config->readInt("encoding_threads"); // Thread stuff sem_init(&in_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); writer = new MovEncoderWriter(cpr, video_outputqueue, &video_output_mutex, &video_out_sem, audio_outputqueue, &audio_output_mutex, &audio_out_sem, info); writer->run(); for(int cnt = 0; cnt < threads; cnt++) { MovEncoder *movenc = new MovEncoder(&read_sem, inputqueue, &in_sem, &input_mutex, video_outputqueue, &video_output_mutex, &video_out_sem, audio_outputqueue, &audio_output_mutex, &audio_out_sem, info); movenc->run(); encs.push_back(movenc); } frame_number = 0; } MovEncoderThread::~MovEncoderThread() { info->info("~MovEncoderThread"); // These should not be deleted here... its done elsewhere. // inputqueue = NULL; sem_post(&video_out_sem); sem_post(&audio_out_sem); // Tell the encoding threads to stop. for(int cnt = 0; cnt < threads; cnt++) { encs[cnt]->running = false; } // Kick them to initiate the exit. for(int cnt = 0; cnt < threads; cnt++) { sem_post(&in_sem); } // They should be exited now, so we can delete them. for(int cnt = 0; cnt < threads; cnt++) { // Wait for it to stop encs[cnt]->wait_stop(); // Delete it delete encs[cnt]; } // Tell the writer to stop writer->running = false; // Kick it to make it stop. sem_post(&video_out_sem); sem_post(&audio_out_sem); // 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(&video_out_sem); sem_destroy(&audio_out_sem); sem_destroy(&read_sem); } void MovEncoderThread::encode(Frame* frame) { if(frame == NULL) { info->info("MovEncoderThread::encode - NULL frame detected."); // Terminate return; } frame->number = frame_number; block->push_back(frame); // Switch frame if(block->size() == num_frames_in_block) { // Wait until a free encoder. /* int val; sem_getvalue(&read_sem, &val); fprintf(stderr, "Sem Value: %d\n", val); fflush(stderr); */ sem_wait(&read_sem); // Lock input mutex pthread_mutex_lock(&input_mutex); inputqueue->push(block); pthread_mutex_unlock(&input_mutex); // Unlock input mutex // fprintf(stderr, "Frame vector [%d-%d] pushed\n", // block->at(0)->number, // block->at(block->size() - 1)->number); fflush(stderr); // Kick encoders sem_post(&in_sem); // Start new block block = new FrameVector; } frame_number ++; }