Refactoring: switch gui::PlaybackController to use the player service

This commit is contained in:
Fischlurch 2009-01-23 04:15:58 +01:00
parent 791b09142a
commit 6c3492396c
7 changed files with 82 additions and 103 deletions

View file

@ -23,11 +23,12 @@
** This file contains the definition of the controller object
*/
#include "playback-controller.hpp"
#ifndef CONTROLLER_HPP
#define CONTROLLER_HPP
#include "playback-controller.hpp"
namespace gui {
namespace model {

View file

@ -20,32 +20,46 @@
* *****************************************************/
#include "playback-controller.hpp"
#include "../gtk-lumiera.hpp"
#include "gui/controller/playback-controller.hpp"
#include "lib/error.hpp"
#include <nobug.h>
namespace gui {
namespace controller {
PlaybackController::PlaybackController() :
finish_playback_thread(false),
playing(false)
{
start_playback_thread();
}
playing(false),
playHandle(0)
{ }
PlaybackController::~PlaybackController()
{
mutex.lock();
finish_playback_thread = true;
mutex.unlock();
thread->join();
if (thread)
thread->join();
}
void
PlaybackController::play()
{
Glib::Mutex::Lock lock(mutex);
playing = true;
try
{
playHandle = & (proc::DummyPlayer::facade().start());
start_playback_thread();
playing = true;
}
catch (lumiera::error::State& err)
{
WARN (operate, "failed to start playback: %s" ,err.what());
lumiera_error();
playing = false;
}
}
void
@ -53,6 +67,8 @@ PlaybackController::pause()
{
Glib::Mutex::Lock lock(mutex);
playing = false;
if (playHandle)
playHandle->pause(true);
}
void
@ -60,6 +76,7 @@ PlaybackController::stop()
{
Glib::Mutex::Lock lock(mutex);
playing = false;
// TODO: stop player somehow?
}
bool
@ -97,108 +114,37 @@ PlaybackController::playback_thread()
if(is_playing())
pull_frame();
////////////////////////////////TODO: usleep
Glib::Thread::yield();
}
}
typedef unsigned char byte;
inline int
clamp(const int &val, const int &maxval, const int &minval)
{
if(val > maxval) return maxval;
if(val < minval) return minval;
return val;
}
inline void
rgb_to_yuv(int r, int g, int b, byte &y, byte &u, byte &v)
{
// This code isn't great, but it does the job
y = (byte)clamp((299 * r + 587 * g + 114 * b) / 1000, 235, 16);
v = (byte)clamp((500 * r - 419 * g - 81 * b) / 1000 + 127, 255, 0);
u = (byte)clamp((-169 * r - 331 * g + 500 * b) / 1000 + 127, 255, 0);
}
void rgb_buffer_to_yuy2(unsigned char *in, unsigned char *out)
{
for(int i = 0; i < 320*240*2; i+=4)
{
byte y0, u0, v0;
const byte r0 = *(in++);
const byte g0 = *(in++);
const byte b0 = *(in++);
rgb_to_yuv(r0, g0, b0, y0, u0, v0);
byte y1, u1, v1;
const byte r1 = *(in++);
const byte g1 = *(in++);
const byte b1 = *(in++);
rgb_to_yuv(r1, g1, b1, y1, u1, v1);
out[i] = y0;
out[i + 1] = u0;
out[i + 2] = y1;
out[i + 3] = v0;
}
}
void
PlaybackController::pull_frame()
{
static int frame = 0;
unsigned char in[320 * 240 * 3];
REQUIRE (is_playing());
REQUIRE (playHandle);
frame--;
unsigned char * newBuffer = reinterpret_cast<unsigned char*> (playHandle->getFrame());
if(frame <= 0)
frame = 200;
if(frame > 150)
{
for(int i = 0; i < 320*240*3; i+=3)
{
byte value = (byte)rand();
in[i] = value;
in[i+1] = value;
in[i+2] = value;
}
}
else
{
unsigned char row[320 * 3];
for(int x = 0; x < 320; x++)
{
byte &r = row[x*3];
byte &g = row[x*3+1];
byte &b = row[x*3+2];
if(x < 1*320/7) r = 0xC0, g = 0xC0, b = 0xC0;
else if(x < 2*320/7) r = 0xC0, g = 0xC0, b = 0x00;
else if(x < 3*320/7) r = 0x00, g = 0xC0, b = 0xC0;
else if(x < 4*320/7) r = 0x00, g = 0xC0, b = 0x00;
else if(x < 5*320/7) r = 0xC0, g = 0x00, b = 0xC0;
else if(x < 6*320/7) r = 0xC0, g = 0x00, b = 0x00;
else r = 0x00, g = 0x00, b = 0xC0;
}
for(int y = 0; y < 240; y++)
if (newBuffer != currentBuffer)
{
memcpy(in + y*320*3, row, sizeof(row));
currentBuffer = newBuffer;
dispatcher.emit();
}
else
{
TRACE (render, "frame dropped?");
}
}
rgb_buffer_to_yuy2(in, buffer);
dispatcher.emit();
}
void
PlaybackController::on_frame()
{
frame_signal.emit(buffer);
frame_signal.emit(currentBuffer);
}
} // namespace controller

View file

@ -23,16 +23,20 @@
** This file contains the definition of the playback controller object
*/
#include <sigc++/sigc++.h>
#include <glibmm.h>
#ifndef PLAYBACK_CONTROLLER_HPP
#define PLAYBACK_CONTROLLER_HPP
#include "include/dummy-player-facade.h"
#include <sigc++/sigc++.h>
#include <glibmm.h>
#include <boost/noncopyable.hpp>
namespace gui {
namespace controller {
class PlaybackController
: boost::noncopyable
{
public:
@ -72,7 +76,9 @@ private:
volatile bool playing;
unsigned char buffer[320 * 240 * 4];
proc::DummyPlayer::Process *playHandle;
unsigned char * currentBuffer;
sigc::signal<void, void*> frame_signal;
};

View file

@ -154,7 +154,14 @@ namespace proc {
return outBuff;
}
void * const
DummyImageGenerator::current()
{
if (!current_) return outFrame_A_;
else return outFrame_B_;
}

View file

@ -69,6 +69,10 @@ namespace proc {
* @return the buffer containing the new frame
*/
void * const next();
/** just re-return a pointer to the current frame
* without generating any new image data */
void * const current();
private:

View file

@ -22,6 +22,7 @@
#include "proc/play/dummy-player-service.hpp"
#include "proc/play/dummy-image-generator.hpp"
#include "lib/singleton.hpp"
extern "C" {
@ -273,6 +274,9 @@ namespace proc {
fps_ = fps;
play_ = (fps != 0);
if (play_)
imageGen_.reset(new DummyImageGenerator(fps));
}
@ -290,8 +294,12 @@ namespace proc {
ProcessImpl::getFrame()
{
REQUIRE (isActive());
ASSERT (imageGen_);
UNIMPLEMENTED ("actually deliver a frame");
if (play_)
return imageGen_->next();
else
return imageGen_->current();
}

View file

@ -43,6 +43,7 @@
#include "common/instancehandle.hpp"
#include "lib/singleton-ref.hpp"
#include <boost/scoped_ptr.hpp>
#include <string>
@ -53,6 +54,9 @@ namespace proc {
using lumiera::Subsys;
class DummyImageGenerator;
class ProcessImpl
: public DummyPlayer::Process
{
@ -60,10 +64,13 @@ namespace proc {
void* const getFrame();
uint fps_;
bool play_;
bool play_;
boost::scoped_ptr<DummyImageGenerator> imageGen_;
public:
ProcessImpl() : fps_(0), play_(false) {}
ProcessImpl() : fps_(0), play_(false), imageGen_(0) {}
/* Implementation-level API to be used By DummyPlayerService */