summaryrefslogtreecommitdiff
path: root/miav/decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'miav/decoder.cc')
-rw-r--r--miav/decoder.cc286
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*/