/* -*- 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. */ /* * $Id$ */ /* * $Log$ * Revision 1.11 2005/06/14 18:58:35 deva * *** empty log message *** * * Revision 1.10 2005/06/14 12:29:40 deva * Incorporated the use of the Info object everywhere... also using the log functionality. * * Revision 1.9 2005/05/26 12:48:36 deva * *** empty log message *** * * Revision 1.8 2005/05/23 17:59:49 deva * Fixed delete of NULL input queue * * Revision 1.7 2005/05/22 15:49:22 deva * Added multithreaded encoding support. * * Revision 1.6 2005/05/19 14:10:22 deva * Multithreading rulez? * * Revision 1.5 2005/05/19 10:55:49 deva * Test for block encoding of length strlen("IPIPP"). * * Revision 1.4 2005/05/17 19:16:26 deva * Made new mpeg writer work, with proper file permissions. * * Revision 1.3 2005/05/17 15:13:15 deva * *** empty log message *** * * Revision 1.2 2005/05/17 15:12:51 deva * Fixed file rights (All read on files and directories, and all execute on directories). * * Revision 1.1 2005/05/17 14:30:56 deva * Added code, preparing threaded encoding. */ #include #include "mov_encoder_thread.h" #include #include "miav_config.h" MovEncoderThread::MovEncoderThread(const char *cpr, Info *i) { info = i; info->info("MovEncoderThread"); outputqueue = new FramePriorityQueue(); inputqueue = new FrameVectorQueue(); 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(&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_tid = new pthread_t; pthread_create (writer_tid, NULL, thread_run, writer); for(int cnt = 0; cnt < threads; cnt++) { encs.push_back(new MovEncoder(&read_sem, inputqueue, &in_sem, &input_mutex, outputqueue, &out_sem, &output_mutex, info)); tids.push_back(new pthread_t); pthread_create (tids[cnt], NULL, thread_run, encs[cnt]); } current_frame = 0; frame_number = 0; } MovEncoderThread::~MovEncoderThread() { info->info("~MovEncoderThread"); // These should not be deleted here... its done elsewhere. // inputqueue = NULL; sem_post(&out_sem); // Stop the encoding threads. 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++) { pthread_join(*tids[cnt], NULL); delete encs[cnt]; delete tids[cnt]; } // Tell the writer to stop writer->running = false; // Kick it to make it stop. sem_post(&out_sem); // Destroy the thread pthread_join(*writer_tid, NULL); delete writer_tid; // delete the writer (end thereby close the file) delete writer; // Destroy the semaphores. sem_destroy(&in_sem); sem_destroy(&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 current_frame = 0; block = new FrameVector; } frame_number ++; }