diff options
Diffstat (limited to 'miav/decoder.cc')
-rw-r--r-- | miav/decoder.cc | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/miav/decoder.cc b/miav/decoder.cc new file mode 100644 index 0000000..0d56aca --- /dev/null +++ b/miav/decoder.cc @@ -0,0 +1,286 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * decoder.cc + * + * Sat Feb 19 17:05:43 CET 2005 + * Copyright 2005 Bent Bisballe + * deva@aasimon.org + ****************************************************************************/ + +/* + * Originally from: + * RTVideoRec Realtime video recoder and encoder for Linux + * + * Copyright (C) 2004 B. Stultiens + * Copyright (C) 2004 Koen Otter and Glenn van der Meyden + */ + +/* + * 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 <config.h> +#ifdef USE_GUI + +#include "frame_stream.h" + +#include "miav_config.h" + +#include <time.h> + +// Use libdv +#include <libdv/dv.h> +#include <libdv/dv_types.h> + +#include <SDL/SDL.h> + +#include "dv.h" +#include "dvfile.h" +#include "dv1394.h" + +#include "decoder.h" +#include "debug.h" + +Decoder::Decoder(Info *ginfo, + sem_t *gencode_sem, + sem_t *gplayer_sem, + Queue<Frame> *gencode_queue, + Queue<Frame> *gplayer_queue, + pthread_mutex_t *gmutex, + volatile int *grunning) +{ + info = ginfo; + + encode_sem = gencode_sem; + player_sem = gplayer_sem; + encode_queue = gencode_queue; + player_queue = gplayer_queue; + mutex = gmutex; + running = grunning; + + b_shoot = false; + b_freeze = false; + b_record = false; // Initially no recording is done. + + pthread_mutex_init (&shot_mutex, NULL); + shot = NULL; + + mute = false; +} + +Decoder::~Decoder() +{ + pthread_mutex_destroy(&shot_mutex); +} + +void Decoder::decode() +{ + frame_stream *dvstream; + + bool local_shoot; + int local_freeze; + bool local_record = false; + bool old_record; + + bool skip_frames = config->readInt("player_skip_frames"); + + dv1394 dv1394_stream = dv1394(info); // Use default port and channel. + dvfile dvfile_stream = dvfile(info); + if(dv1394_stream.connect()) { + // Use the dv1394 stream for input. + dvstream = &dv1394_stream; + } else { + // Use the fallback dv filereader for input. + dvstream = &dvfile_stream; + } + + while(*running) { + uint8_t *ptr; + SDL_Event user_event; + + // Read a dvframe + ptr = dvstream->readFrame(); + if(!ptr) return; // No frame read. (Due to dv read error) + + old_record = local_record; + local_shoot = b_shoot; + b_shoot = false; + local_freeze = b_freeze; + b_freeze = false; + local_record = b_record; + + if(local_shoot) { + pthread_mutex_lock(&shot_mutex); + if(!shot) shot = new Frame(ptr, DVPACKAGE_SIZE); + pthread_mutex_unlock(&shot_mutex); + } + + if(local_freeze == 1) { + pthread_mutex_lock(&shot_mutex); + if(shot) delete shot; + shot = new Frame(ptr, DVPACKAGE_SIZE); + pthread_mutex_unlock(&shot_mutex); + } + + static int showframe = 1; + if(skip_frames != 0) showframe = 1 - showframe; + if(showframe) { + Frame *pframe = new Frame(ptr, DVPACKAGE_SIZE); + + pframe->shoot = local_shoot; + pframe->freeze = local_freeze; + pframe->record = local_record; + + player_queue->push(pframe); + + // Create and send SDL event. + user_event.type = SDL_USEREVENT; + user_event.user.code = 0; + user_event.user.data1 = NULL; + user_event.user.data2 = NULL; + SDL_PushEvent(&user_event); + } + + if(local_record | (local_record != old_record) | local_shoot | local_freeze) { + Frame *eframe = new Frame(NULL, 0); + eframe->data = ptr; + eframe->size = DVPACKAGE_SIZE; + + eframe->shoot = local_shoot; + eframe->freeze = local_freeze; + eframe->record = local_record; + eframe->mute = mute; + + encode_queue->push(eframe); + + sem_post(encode_sem); + } else { + free(ptr); + } + } + + // Kick the others so they wake up with empty queues + sem_post(encode_sem); +} + +void Decoder::thread_main() { + decode(); + fprintf(stderr, "Decoder thread stopped.\n"); fflush(stderr); +} + +/* + * Set freeze bit on current frame. + */ +void Decoder::freeze() +{ + b_freeze = 1; +} + +/* + * Remove frozen frame. + */ +void Decoder::unfreeze() +{ + b_freeze = -1; + + pthread_mutex_lock(&shot_mutex); + delete shot; + shot = NULL; + pthread_mutex_unlock(&shot_mutex); +} + +/* + * Set shoot bit on current frame. + */ +void Decoder::shoot(unsigned char *rgb) +{ + struct timespec ts; + + b_shoot = true; + + // Wait for shot to be taken + while(1) { + pthread_mutex_lock(&shot_mutex); + if(shot) { + getScreenshot(shot, rgb); + delete shot; + shot = NULL; + pthread_mutex_unlock(&shot_mutex); + return; + } + pthread_mutex_unlock(&shot_mutex); + + ts.tv_sec = 0; + ts.tv_nsec = 100000000L; // 100ms + nanosleep(&ts, NULL); + } +} + +/* + * Set the record bit to true in all following frames. + */ +void Decoder::start() +{ + b_record = true; +} + +/* + * Set the record bit to false in all following frames. + */ +void Decoder::stop(n_savestate save) +{ + b_record = false; +} + +void Decoder::getScreenshot(Frame *frame, unsigned char *rgb) +{ + unsigned char *pixels[3]; + int pitches[3]; + + pixels[ 0 ] = rgb; + pixels[ 1 ] = NULL; + pixels[ 2 ] = NULL; + + pitches[ 0 ] = 720 * 4; + pitches[ 1 ] = 0; + pitches[ 2 ] = 0; + + dv_decoder_t *decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE); + decoder->quality = DV_QUALITY_BEST; + + dv_parse_header(decoder, frame->data); + + decoder->system = e_dv_system_625_50; // PAL lines, PAL framerate + decoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v + decoder->std = e_dv_std_iec_61834; + decoder->num_dif_seqs = 12; + + // libdv img decode to rgb + dv_decode_full_frame(decoder, + frame->data, + e_dv_color_bgr0, + pixels, + pitches); + + dv_decoder_free(decoder); +} + +void Decoder::setMute(bool m) +{ + mute = m; +} + +#endif /*USE_GUI*/ |