/**
 *  GraphTFT plugin for the Video Disk Recorder 
 * 
 *  player.c - A plugin for the Video Disk Recorder
 *
 *  (c) 2004 Lars Tegeler, Sascha Volkenandt  
 *
 * This code is distributed under the terms and conditions of the
 * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
 *
 * $Id: player.c,v 1.5 2007/12/03 19:57:53 root Exp $
 *
 **/

#include "common.h"
#include "player.h"
#include "setup.h"

static  pthread_mutex_t dvb_mutex = PTHREAD_MUTEX_INITIALIZER;

cGraphTFTPlayer::cGraphTFTPlayer()
#if VDRVERSNUM >= 10300
		: cThread("GraphTFT dvbrenderer player")
#endif
{
	_active = false;
	_showImage = false;
}

cGraphTFTPlayer::~cGraphTFTPlayer() 
{
	tell(4, "player.c: ~graphTFTPlayer()\n");
   cPlayer::Detach();
}

void cGraphTFTPlayer::Activate(bool On) 
{
	tell(4, "player.c: Activate()\n");

   if (On)
		Start();
   else if (_active) 
   {
		_active = false;
		Cancel(3);
	}
}

void cGraphTFTPlayer::setPlayMode(bool Video)
{
	tell(4, "player.c: setPlayMode()\n");
	if (Video)
		_showImage = false;
	else
		_showImage = true;
	DeviceClear();
	_doUpdate.Broadcast();
}

void cGraphTFTPlayer::setIFrame( mpeg_frame iframe )
{
	tell(4, "player.c: setIFrame\n");
	pthread_mutex_lock(&dvb_mutex);
	_iframe = iframe;
	pthread_mutex_unlock(&dvb_mutex);
	_doUpdate.Broadcast();
}

void cGraphTFTPlayer::send_pes_packet(unsigned char *data, int len, int timestamp)
{
#define PES_MAX_SIZE 2048
    int ptslen = timestamp ? 5 : 1;
    static unsigned char pes_header[PES_MAX_SIZE];

    pes_header[0] = pes_header[1] = 0;
    pes_header[2] = 1;
    pes_header[3] = 0xe0;

    while(len > 0)
	{
	    int payload_size = len;
	    if(6 + ptslen + payload_size > PES_MAX_SIZE)
		payload_size = PES_MAX_SIZE - (6 + ptslen);

	    pes_header[4] = (ptslen + payload_size) >> 8;
	    pes_header[5] = (ptslen + payload_size) & 255;

	    if(ptslen == 5)
		{
		    int x;
		    x = (0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1;
		    pes_header[8] = x;
		    x = ((((timestamp >> 15) & 0x7fff) << 1) | 1);
		    pes_header[7] = x >> 8;
		    pes_header[8] = x & 255;
		    x = ((((timestamp) & 0x7fff) < 1) | 1);
		    pes_header[9] = x >> 8;
		    pes_header[10] = x & 255;
	    } else
		{
		    pes_header[6] = 0x0f;
		}

	    fast_memcpy(&pes_header[6 + ptslen], data, payload_size);
	    PlayPes(pes_header, 6 + ptslen + payload_size);

	    len -= payload_size;
	    data += payload_size;
	    ptslen = 1;
	}
}

void cGraphTFTPlayer::Action(void) {
	
#if VDRVERSNUM < 10300
 	dsyslog("graphTFT: dvbrenderer player thread started (pid=%d)", getpid());
#endif
	_active = true;

	while (_active)
	{
		tell(5, "player.c: Action(): in loop\n");

		while(_showImage && _active)
		{
			if (GraphTFTSetup.UseStillPicture)
			{
				tell(6, "player.c: Action(): view stillpicture\n");
				pthread_mutex_lock(&dvb_mutex);
				if (_iframe.size)
				   DeviceStillPicture(_iframe.data, _iframe.size);
				pthread_mutex_unlock(&dvb_mutex);

			}else{
				tell(6, "player.c: Action(): view picture with send_pes_packet\n");
				pthread_mutex_lock(&dvb_mutex);
				 
				// for (int i = 1; i <= 25; i++)
				if (_iframe.size)
				   send_pes_packet(_iframe.data, _iframe.size, 0);

				pthread_mutex_unlock(&dvb_mutex);
			}
			cMutexLock lock(&_mutex);
			_doUpdate.TimedWait(_mutex, GraphTFTSetup.DvbRefresh);			
		}
		cMutexLock lock(&_mutex);
		_doUpdate.Wait(_mutex);
	}
#if VDRVERSNUM < 10300
	dsyslog("graphTFT: player thread ended (pid=%d)", getpid());
#endif
}
