/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * plsyer.cc * * Wed Nov 3 21:23:14 CET 2004 * Copyright 2004 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. */ /* * $Id$ */ /* * $Log$ * Revision 1.24 2005/06/09 11:00:03 deva * Added daemon code, and cleaned up using -Wall and -Werror * * Revision 1.23 2005/05/03 08:31:59 deva * Removed the error object, and replaced it with a more generic info object. * * Revision 1.22 2005/05/01 09:56:26 deva * Added Id and Log tags to all files */ #include #ifdef USE_GUI #include "player.h" // Use libdv #include #include #include Player::Player(Info *ginfo, volatile int *grunning, sem_t *gsem, Queue *gqueue, pthread_mutex_t *gmutex) { // No errors has ocurred... yet! noErrors = true; info = ginfo; running = grunning; sem = gsem; queue = gqueue; mutex = gmutex; sem_init(&play_sem, 0, 1); if(SDL_Init(SDL_INIT_VIDEO) < 0) { info->error("Unable to init SDL: %s.", SDL_GetError()); noErrors = false; return; } screen = SDL_SetVideoMode(DISPLAYWIDTH, DISPLAYHEIGHT, 0, // 0 bpp means 'use current display depth' SDL_HWSURFACE | SDL_ANYFORMAT | SDL_HWACCEL); if(!screen) { info->error("Unable to set %dx%d video: %s.", DISPLAYWIDTH, DISPLAYHEIGHT, SDL_GetError()); noErrors = false; return; } overlay = SDL_CreateYUVOverlay(DISPLAYWIDTH, DISPLAYHEIGHT, SDL_YUY2_OVERLAY, // Match for the libdv decoder output screen); if(!overlay) { info->error("Unable to create SDL overlay: %s.", SDL_GetError()); noErrors = false; return; } } Player::~Player() { SDL_FreeYUVOverlay(overlay); SDL_Quit(); } void Player::player() { SDL_Event event; SDL_Rect rect; Frame *frame; int pitches[3]; struct timespec ts; if(!noErrors) return; // FIXME: Gracefully exit... // Setup the displayarea. rect.x = 0; rect.y = 0; rect.w = DISPLAYWIDTH; rect.h = DISPLAYHEIGHT; bool first = true; dv_decoder_t *decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE); decoder->quality = DV_QUALITY_BEST; while(*running) { // Wait for the semaphore to be free... then run sem_wait(&play_sem); sem_post(&play_sem); if(!SDL_WaitEvent(&event)) break; // FIXME: Gracefully exit... switch(event.type) { case SDL_KEYDOWN: switch(event.key.keysym.sym) { case SDLK_q: case SDLK_ESCAPE: goto quitit; default: break; } break; case SDL_USEREVENT: frame = queue->pop(); if(!frame) break; if(first) { pitches[0] = overlay->pitches[0]; pitches[1] = overlay->pitches[1]; pitches[2] = overlay->pitches[2]; dv_parse_header(decoder, frame->data); //dv_parse_packs(decoder, frame->data); // Not needed anyway! 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; first = false; } SDL_LockYUVOverlay(overlay); // libdv img decode to yuv dv_decode_full_frame(decoder, frame->data, e_dv_color_yuv, overlay->pixels, pitches); SDL_UnlockYUVOverlay(overlay); SDL_DisplayYUVOverlay(overlay, &rect); delete frame; break; case SDL_QUIT: quitit: *running = 0; break; default: break; } } if(decoder) dv_decoder_free(decoder); /* Remove any late buffer */ /* We don't care, the encoder finishes them all */ ts.tv_sec = 0; ts.tv_nsec = 100000000L; // 100ms nanosleep(&ts, NULL); frame = queue->pop(); if(frame) delete frame; } void Player::run() { player(); fprintf(stderr, "Player thread stopped.\n"); fflush(stderr); } void Player::start() { sem_post(&play_sem); } void Player::stop() { sem_wait(&play_sem); } #endif /* USE_GUI */