15fc19323SFrançois Revol#include <fcntl.h>
25fc19323SFrançois Revol#include <malloc.h>
35fc19323SFrançois Revol#include <math.h>
45fc19323SFrançois Revol#include <stdio.h>
55fc19323SFrançois Revol#include <string.h>
65fc19323SFrançois Revol#include <sys/uio.h>
75fc19323SFrançois Revol#include <unistd.h>
85fc19323SFrançois Revol
95fc19323SFrançois Revol#include <media/Buffer.h>
105fc19323SFrançois Revol#include <media/BufferGroup.h>
115fc19323SFrançois Revol#include <media/ParameterWeb.h>
125fc19323SFrançois Revol#include <media/TimeSource.h>
135fc19323SFrançois Revol
145fc19323SFrançois Revol#include <support/Autolock.h>
155fc19323SFrançois Revol#include <support/Debug.h>
165fc19323SFrançois Revol
175fc19323SFrançois Revol#define TOUCH(x) ((void)(x))
185fc19323SFrançois Revol
195fc19323SFrançois Revol#define PRINTF(a,b) \
205fc19323SFrançois Revol		do { \
215fc19323SFrançois Revol			if (a < 2) { \
225fc19323SFrançois Revol				printf("FinePixProducer::"); \
235fc19323SFrançois Revol				printf b; \
245fc19323SFrançois Revol			} \
255fc19323SFrançois Revol		} while (0)
265fc19323SFrançois Revol
275fc19323SFrançois Revol#include "Producer.h"
285fc19323SFrançois Revol
295fc19323SFrançois Revol#define FIELD_RATE 30.f
305fc19323SFrançois Revol
315fc19323SFrançois Revol#define MAX_FRAME_SIZE 50000 // bytes (jpeg)
325fc19323SFrançois Revol#define FPIX_RGB24_WIDTH 320
335fc19323SFrançois Revol#define FPIX_RGB24_HEIGHT 240
345fc19323SFrançois Revol#define FPIX_RGB24_FRAME_SIZE FPIX_RGB24_WIDTH * FPIX_RGB24_HEIGHT * 3
355fc19323SFrançois Revol
365fc19323SFrançois Revolint32 FinePixProducer::fInstances = 0;
375fc19323SFrançois Revol
385fc19323SFrançois RevolFinePixProducer::FinePixProducer(
395fc19323SFrançois Revol		BMediaAddOn *addon, const char *name, int32 internal_id)
405fc19323SFrançois Revol  :	BMediaNode(name),
415fc19323SFrançois Revol	BMediaEventLooper(),
425fc19323SFrançois Revol	BBufferProducer(B_MEDIA_ENCODED_VIDEO),
435fc19323SFrançois Revol	BControllable()
445fc19323SFrançois Revol{
455fc19323SFrançois Revol	//status_t err;
465fc19323SFrançois Revol
475fc19323SFrançois Revol	fInitStatus = B_NO_INIT;
485fc19323SFrançois Revol
495fc19323SFrançois Revol	/* Only allow one instance of the node to exist at any time */
505fc19323SFrançois Revol	if (atomic_add(&fInstances, 1) != 0)
515fc19323SFrançois Revol		return;
525fc19323SFrançois Revol
535fc19323SFrançois Revol	fInternalID = internal_id;
545fc19323SFrançois Revol	fAddOn = addon;
555fc19323SFrançois Revol
565fc19323SFrançois Revol	fBufferGroup = NULL;
575fc19323SFrançois Revol
585fc19323SFrançois Revol	fThread = -1;
595fc19323SFrançois Revol	fFrameSync = -1;
605fc19323SFrançois Revol	fProcessingLatency = 0LL;
615fc19323SFrançois Revol
625fc19323SFrançois Revol	fRunning = false;
635fc19323SFrançois Revol	fConnected = false;
645fc19323SFrançois Revol	fEnabled = false;
655fc19323SFrançois Revol
665fc19323SFrançois Revol	fOutput.destination = media_destination::null;
675fc19323SFrançois Revol
685fc19323SFrançois Revol	AddNodeKind(B_PHYSICAL_INPUT);
695fc19323SFrançois Revol
705fc19323SFrançois Revol	fDeltaBuffer = NULL; //��yvind
715fc19323SFrançois Revol	fCam = new FinePix();
725fc19323SFrançois Revol
735fc19323SFrançois Revol	fInitStatus = B_OK;
745fc19323SFrançois Revol	return;
755fc19323SFrançois Revol}
765fc19323SFrançois Revol
775fc19323SFrançois RevolFinePixProducer::~FinePixProducer()
785fc19323SFrançois Revol{
795fc19323SFrançois Revol	if (fInitStatus == B_OK) {
805fc19323SFrançois Revol		/* Clean up after ourselves, in case the application didn't make us
815fc19323SFrançois Revol		 * do so. */
825fc19323SFrançois Revol		if (fConnected)
835fc19323SFrançois Revol			Disconnect(fOutput.source, fOutput.destination);
845fc19323SFrançois Revol		if (fRunning)
855fc19323SFrançois Revol			HandleStop();
865fc19323SFrançois Revol	}
875fc19323SFrançois Revol
885fc19323SFrançois Revol	if( fCam ) //��yvind
895fc19323SFrançois Revol	{
905fc19323SFrançois Revol		delete fCam;
915fc19323SFrançois Revol	}
925fc19323SFrançois Revol
935fc19323SFrançois Revol	atomic_add(&fInstances, -1);
945fc19323SFrançois Revol}
955fc19323SFrançois Revol
965fc19323SFrançois Revol/* BMediaNode */
975fc19323SFrançois Revol
985fc19323SFrançois Revolport_id
995fc19323SFrançois RevolFinePixProducer::ControlPort() const
1005fc19323SFrançois Revol{
1015fc19323SFrançois Revol	return BMediaNode::ControlPort();
1025fc19323SFrançois Revol}
1035fc19323SFrançois Revol
1045fc19323SFrançois RevolBMediaAddOn *
1055fc19323SFrançois RevolFinePixProducer::AddOn(int32 *internal_id) const
1065fc19323SFrançois Revol{
1075fc19323SFrançois Revol	if (internal_id)
1085fc19323SFrançois Revol		*internal_id = fInternalID;
1095fc19323SFrançois Revol	return fAddOn;
1105fc19323SFrançois Revol}
1115fc19323SFrançois Revol
1125fc19323SFrançois Revolstatus_t
1135fc19323SFrançois RevolFinePixProducer::HandleMessage(int32 message, const void *data, size_t size)
1145fc19323SFrançois Revol{
1155fc19323SFrançois Revol	return B_ERROR;
1165fc19323SFrançois Revol}
1175fc19323SFrançois Revol
1185fc19323SFrançois Revolvoid
1195fc19323SFrançois RevolFinePixProducer::Preroll()
1205fc19323SFrançois Revol{
1215fc19323SFrançois Revol	/* This hook may be called before the node is started to give the hardware
1225fc19323SFrançois Revol	 * a chance to start. */
1235fc19323SFrançois Revol}
1245fc19323SFrançois Revol
1255fc19323SFrançois Revolvoid
1265fc19323SFrançois RevolFinePixProducer::SetTimeSource(BTimeSource *time_source)
1275fc19323SFrançois Revol{
1285fc19323SFrançois Revol	/* Tell frame generation thread to recalculate delay value */
1295fc19323SFrançois Revol	release_sem(fFrameSync);
1305fc19323SFrançois Revol}
1315fc19323SFrançois Revol
1325fc19323SFrançois Revolstatus_t
1335fc19323SFrançois RevolFinePixProducer::RequestCompleted(const media_request_info &info)
1345fc19323SFrançois Revol{
1355fc19323SFrançois Revol	return BMediaNode::RequestCompleted(info);
1365fc19323SFrançois Revol}
1375fc19323SFrançois Revol
1385fc19323SFrançois Revol/* BMediaEventLooper */
1395fc19323SFrançois Revol
1405fc19323SFrançois Revolvoid
1415fc19323SFrançois RevolFinePixProducer::NodeRegistered()
1425fc19323SFrançois Revol{
1435fc19323SFrançois Revol	if (fInitStatus != B_OK) {
1445fc19323SFrançois Revol		ReportError(B_NODE_IN_DISTRESS);
1455fc19323SFrançois Revol		return;
1465fc19323SFrançois Revol	}
1475fc19323SFrançois Revol
1485fc19323SFrançois Revol	fOutput.node = Node();
1495fc19323SFrançois Revol	fOutput.source.port = ControlPort();
1505fc19323SFrançois Revol	fOutput.source.id = 0;
1515fc19323SFrançois Revol	fOutput.destination = media_destination::null;
1525fc19323SFrançois Revol	strcpy(fOutput.name, Name());
1535fc19323SFrançois Revol
1545fc19323SFrançois Revol	/* Tailor these for the output of your device */
1555fc19323SFrançois Revol	fOutput.format.type = B_MEDIA_RAW_VIDEO;
1565fc19323SFrançois Revol	fOutput.format.u.raw_video = media_raw_video_format::wildcard;
1575fc19323SFrançois Revol	fOutput.format.u.raw_video.interlace = 1;
1585fc19323SFrançois Revol	fOutput.format.u.raw_video.display.format = B_RGB32;
1595fc19323SFrançois Revol
1605fc19323SFrançois Revol	/* Start the BMediaEventLooper control loop running */
1615fc19323SFrançois Revol	Run();
1625fc19323SFrançois Revol}
1635fc19323SFrançois Revol
1645fc19323SFrançois Revolvoid
1655fc19323SFrançois RevolFinePixProducer::Start(bigtime_t performance_time)
1665fc19323SFrançois Revol{
1675fc19323SFrançois Revol	BMediaEventLooper::Start(performance_time);
1685fc19323SFrançois Revol}
1695fc19323SFrançois Revol
1705fc19323SFrançois Revolvoid
1715fc19323SFrançois RevolFinePixProducer::Stop(bigtime_t performance_time, bool immediate)
1725fc19323SFrançois Revol{
1735fc19323SFrançois Revol	BMediaEventLooper::Stop(performance_time, immediate);
1745fc19323SFrançois Revol}
1755fc19323SFrançois Revol
1765fc19323SFrançois Revolvoid
1775fc19323SFrançois RevolFinePixProducer::Seek(bigtime_t media_time, bigtime_t performance_time)
1785fc19323SFrançois Revol{
1795fc19323SFrançois Revol	BMediaEventLooper::Seek(media_time, performance_time);
1805fc19323SFrançois Revol}
1815fc19323SFrançois Revol
1825fc19323SFrançois Revolvoid
1835fc19323SFrançois RevolFinePixProducer::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time)
1845fc19323SFrançois Revol{
1855fc19323SFrançois Revol	BMediaEventLooper::TimeWarp(at_real_time, to_performance_time);
1865fc19323SFrançois Revol}
1875fc19323SFrançois Revol
1885fc19323SFrançois Revolstatus_t
1895fc19323SFrançois RevolFinePixProducer::AddTimer(bigtime_t at_performance_time, int32 cookie)
1905fc19323SFrançois Revol{
1915fc19323SFrançois Revol	return BMediaEventLooper::AddTimer(at_performance_time, cookie);
1925fc19323SFrançois Revol}
1935fc19323SFrançois Revol
1945fc19323SFrançois Revolvoid
1955fc19323SFrançois RevolFinePixProducer::SetRunMode(run_mode mode)
1965fc19323SFrançois Revol{
1975fc19323SFrançois Revol	BMediaEventLooper::SetRunMode(mode);
1985fc19323SFrançois Revol}
1995fc19323SFrançois Revol
2005fc19323SFrançois Revolvoid
2015fc19323SFrançois RevolFinePixProducer::HandleEvent(const media_timed_event *event,
2025fc19323SFrançois Revol		bigtime_t lateness, bool realTimeEvent)
2035fc19323SFrançois Revol{
2045fc19323SFrançois Revol	TOUCH(lateness); TOUCH(realTimeEvent);
2055fc19323SFrançois Revol
2065fc19323SFrançois Revol	switch(event->type)
2075fc19323SFrançois Revol	{
2085fc19323SFrançois Revol		case BTimedEventQueue::B_START:
2095fc19323SFrançois Revol			HandleStart(event->event_time);
2105fc19323SFrançois Revol			break;
2115fc19323SFrançois Revol		case BTimedEventQueue::B_STOP:
2125fc19323SFrançois Revol			HandleStop();
2135fc19323SFrançois Revol			break;
2145fc19323SFrançois Revol		case BTimedEventQueue::B_WARP:
2155fc19323SFrançois Revol			HandleTimeWarp(event->bigdata);
2165fc19323SFrançois Revol			break;
2175fc19323SFrançois Revol		case BTimedEventQueue::B_SEEK:
2185fc19323SFrançois Revol			HandleSeek(event->bigdata);
2195fc19323SFrançois Revol			break;
2205fc19323SFrançois Revol		case BTimedEventQueue::B_HANDLE_BUFFER:
2215fc19323SFrançois Revol		case BTimedEventQueue::B_DATA_STATUS:
2225fc19323SFrançois Revol		case BTimedEventQueue::B_PARAMETER:
2235fc19323SFrançois Revol		default:
2245fc19323SFrançois Revol			PRINTF(-1, ("HandleEvent: Unhandled event -- %lx\n", event->type));
2255fc19323SFrançois Revol			break;
2265fc19323SFrançois Revol	}
2275fc19323SFrançois Revol}
2285fc19323SFrançois Revol
2295fc19323SFrançois Revolvoid
2305fc19323SFrançois RevolFinePixProducer::CleanUpEvent(const media_timed_event *event)
2315fc19323SFrançois Revol{
2325fc19323SFrançois Revol	BMediaEventLooper::CleanUpEvent(event);
2335fc19323SFrançois Revol}
2345fc19323SFrançois Revol
2355fc19323SFrançois Revolbigtime_t
2365fc19323SFrançois RevolFinePixProducer::OfflineTime()
2375fc19323SFrançois Revol{
2385fc19323SFrançois Revol	return BMediaEventLooper::OfflineTime();
2395fc19323SFrançois Revol}
2405fc19323SFrançois Revol
2415fc19323SFrançois Revolvoid
2425fc19323SFrançois RevolFinePixProducer::ControlLoop()
2435fc19323SFrançois Revol{
2445fc19323SFrançois Revol	BMediaEventLooper::ControlLoop();
2455fc19323SFrançois Revol}
2465fc19323SFrançois Revol
2475fc19323SFrançois Revolstatus_t
2485fc19323SFrançois RevolFinePixProducer::DeleteHook(BMediaNode * node)
2495fc19323SFrançois Revol{
2505fc19323SFrançois Revol	return BMediaEventLooper::DeleteHook(node);
2515fc19323SFrançois Revol}
2525fc19323SFrançois Revol
253