From 2f10a73cbbe4333e2a41e87a94eda7fb3d442dc5 Mon Sep 17 00:00:00 2001 From: deva Date: Mon, 17 Mar 2008 09:10:42 +0000 Subject: Major code changes... FFMPEG introduced. Project splitup into subfolders. --- miav/player.cc | 322 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 miav/player.cc (limited to 'miav/player.cc') diff --git a/miav/player.cc b/miav/player.cc new file mode 100644 index 0000000..8d97426 --- /dev/null +++ b/miav/player.cc @@ -0,0 +1,322 @@ +/* -*- 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. + */ +#include +#ifdef USE_GUI + +#include "player.h" + +// Use libdv +#include +#include + +#include + +// For sleep +#include + +Player::Player(Info *ginfo, + int w, int h, + volatile int *grunning, + sem_t *gsem, + Queue *gqueue, + pthread_mutex_t *gmutex) +{ + // No errors has ocurred... yet! + noErrors = true; + + yuv_draw = new YUVDraw(); + + width = w; + height = h; + + info = ginfo; + + running = grunning; + sem = gsem; + queue = gqueue; + mutex = gmutex; + + sem_init(&play_sem, 0, 1); + + initSDL(); + + bypass = false; + + // Do not show the text + showtext = false; + recording = false; + recording_prev = !recording; + cprchanged = false; + + muted = false; + muted_prev = !muted; +} + +Player::~Player() +{ + deinitSDL(); + if(yuv_draw) delete yuv_draw; +} + +void Player::reinitSDL() +{ + deinitSDL(); + initSDL(); +} + +void Player::deinitSDL() +{ + SDL_FreeYUVOverlay(overlay); + SDL_Quit(); +} + +void Player::initSDL() +{ + if(SDL_Init(SDL_INIT_VIDEO) < 0) { + info->error("Unable to init SDL: %s.", SDL_GetError()); + noErrors = false; + printf("failed!\n"); + return; + } + + screen = SDL_SetVideoMode(width, + height, + 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.", + 720, 576, SDL_GetError()); + noErrors = false; + printf("failed!\n"); + return; + } + + overlay = SDL_CreateYUVOverlay(720, + 576, + SDL_YUY2_OVERLAY, // Match for the libdv decoder output + screen); + if(!overlay) { + info->error("Unable to create SDL overlay: %s.", SDL_GetError()); + noErrors = false; + printf("failed!\n"); + return; + } + + // Setup the displayarea. + rect.x = 0; + rect.y = 0; + rect.w = width; + rect.h = height; + + yuv_draw->setOverlay(overlay); +} + +void Player::player() +{ + SDL_Event event; + Frame *frame; + + int pitches[3]; + + if(!noErrors) return; // FIXME: Gracefully exit... + + 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(bypass) continue; + + 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] = 0; + pitches[2] = overlay->pitches[2] = 0; + + 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; + } + + if(SDL_LockYUVOverlay(overlay) == -1) info->error("SDL_LockYUVOverlay failed."); + + // libdv img decode to yuv + dv_decode_full_frame(decoder, + frame->data, + e_dv_color_yuv, + overlay->pixels, + pitches); + + // Set status text + // if(muted != muted_prev) { + yuv_draw->mute(muted); + // muted_prev = muted; + // } + if(recording != recording_prev) { + if(recording) yuv_draw->setTopText(TEXT_RECORDING); + else yuv_draw->setTopText(TEXT_STOPPED); + recording_prev = recording; + } + + // Draw overlaytext (if enabled) + if(showtext) { + if(cprchanged) { + yuv_draw->setBottomText(cpr); + cprchanged = false; + } + yuv_draw->draw(); + } + + 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); + + struct timespec ts; + + /* 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::thread_main() +{ + player(); + fprintf(stderr, "Player thread stopped.\n"); fflush(stderr); +} + +void Player::start() +{ + sem_post(&play_sem); +} + +void Player::stop() +{ + sem_wait(&play_sem); +} + +// FIXME: Worst case genario: the loop takes more than 1 second +// to stop displaying => crash, due to deinitialization +// of SDL, while calling it.! +void Player::resize(int w, int h, bool s) +{ + // Tell loop to stop + bypass = true; + + // Wait to ensure the current frame is done being displayed + sleep(1); + + // Deinitialize SDL + deinitSDL(); + + // Set new size + width = w; + height = h; + + // Initialize SDL + initSDL(); + + // Tell loop to go on. + bypass = false; + + showtext = s; +} + +void Player::setCpr(char *newcpr, char* name) +{ + sprintf(cpr, "ID: %s - %s", newcpr, name); + cprchanged = true; +} + +void Player::startrecord() +{ + recording = true; +} + +void Player::stoprecord() +{ + recording = false; +} + +void Player::setMute(bool m) +{ + muted = m; +} + +#endif /* USE_GUI */ -- cgit v1.2.3