2 * Copyright 2004-2008, François Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
14 #include <media/Buffer.h>
15 #include <media/BufferGroup.h>
16 #include <media/ParameterWeb.h>
17 #include <media/TimeSource.h>
19 #include <support/Autolock.h>
20 #include <support/Debug.h>
22 //XXX: change interface
23 #include <interface/Bitmap.h>
25 #include "CamDevice.h"
26 #include "CamSensor.h"
28 // don't separate parameters from addon, device and sensor
29 #define SINGLE_PARAMETER_GROUP 1
31 // CodyCam and eXposer prefer 320x240
32 #define FORCE_320_240 1
33 //#define FORCE_160_120 1
34 //#define FORCE_MAX_FRAME 1
36 #define TOUCH(x) ((void)(x))
41 printf("VideoProducer::"); \
48 //#define FIELD_RATE 30.f
49 //#define FIELD_RATE 29.97f
50 #define FIELD_RATE 5.f
53 int32
VideoProducer::fInstances
= 0;
56 VideoProducer::VideoProducer(
57 BMediaAddOn
*addon
, CamDevice
*dev
, const char *name
, int32 internal_id
)
60 BBufferProducer(B_MEDIA_RAW_VIDEO
),
65 fInitStatus
= B_NO_INIT
;
67 /* Only allow one instance of the node to exist at any time */
68 if (atomic_add(&fInstances
, 1) != 0)
71 fInternalID
= internal_id
;
79 fProcessingLatency
= 0LL;
85 fOutput
.destination
= media_destination::null
;
87 AddNodeKind(B_PHYSICAL_INPUT
);
94 VideoProducer::~VideoProducer()
96 if (fInitStatus
== B_OK
) {
97 /* Clean up after ourselves, in case the application didn't make us
100 Disconnect(fOutput
.source
, fOutput
.destination
);
105 atomic_add(&fInstances
, -1);
111 VideoProducer::ControlPort() const
113 return BMediaNode::ControlPort();
118 VideoProducer::AddOn(int32
*internal_id
) const
121 *internal_id
= fInternalID
;
127 VideoProducer::HandleMessage(int32
/*message*/, const void* /*data*/, size_t /*size*/)
134 VideoProducer::Preroll()
136 /* This hook may be called before the node is started to give the hardware
137 * a chance to start. */
142 VideoProducer::SetTimeSource(BTimeSource
* /*time_source*/)
144 /* Tell frame generation thread to recalculate delay value */
145 release_sem(fFrameSync
);
150 VideoProducer::RequestCompleted(const media_request_info
&info
)
152 return BMediaNode::RequestCompleted(info
);
156 /* BMediaEventLooper */
160 VideoProducer::NodeRegistered()
162 if (fInitStatus
!= B_OK
) {
163 ReportError(B_NODE_IN_DISTRESS
);
167 /* Set up the parameter web */
169 //TODO: remove and put sensible stuff there
170 BParameterWeb
*web
= new BParameterWeb();
171 BParameterGroup
*main
= web
->MakeGroup(Name());
175 g = main->MakeGroup("Color");
176 BDiscreteParameter *state = g->MakeDiscreteParameter(
177 P_COLOR, B_MEDIA_RAW_VIDEO, "Color", "Color");
178 state->AddItem(B_HOST_TO_LENDIAN_INT32(0x00ff0000), "Red");
179 state->AddItem(B_HOST_TO_LENDIAN_INT32(0x0000ff00), "Green");
180 state->AddItem(B_HOST_TO_LENDIAN_INT32(0x000000ff), "Blue");
184 g
= main
->MakeGroup("Info");
185 p
= g
->MakeTextParameter(
186 P_INFO
, B_MEDIA_RAW_VIDEO
, "", "Info", 256);
190 #ifndef SINGLE_PARAMETER_GROUP
191 main
= web
->MakeGroup("Device");
193 fCamDevice
->AddParameters(main
, id
);
194 if (fCamDevice
->Sensor()) {
195 #ifndef SINGLE_PARAMETER_GROUP
196 main
= web
->MakeGroup("Sensor");
198 fCamDevice
->Sensor()->AddParameters(main
, id
);
202 fColor
= B_HOST_TO_LENDIAN_INT32(0x00ff0000);
203 fLastColorChange
= system_time();
205 /* After this call, the BControllable owns the BParameterWeb object and
206 * will delete it for you */
207 SetParameterWeb(web
);
209 fOutput
.node
= Node();
210 fOutput
.source
.port
= ControlPort();
211 fOutput
.source
.id
= 0;
212 fOutput
.destination
= media_destination::null
;
213 strcpy(fOutput
.name
, Name());
215 /* Tailor these for the output of your device */
216 fOutput
.format
.type
= B_MEDIA_RAW_VIDEO
;
217 fOutput
.format
.u
.raw_video
= media_raw_video_format::wildcard
;
218 fOutput
.format
.u
.raw_video
.interlace
= 1;
219 fOutput
.format
.u
.raw_video
.display
.format
= B_RGB32
;
220 fOutput
.format
.u
.raw_video
.field_rate
= FIELD_RATE
; // XXX: mmu
222 /* Start the BMediaEventLooper control loop running */
228 VideoProducer::Start(bigtime_t performance_time
)
230 BMediaEventLooper::Start(performance_time
);
235 VideoProducer::Stop(bigtime_t performance_time
, bool immediate
)
237 BMediaEventLooper::Stop(performance_time
, immediate
);
242 VideoProducer::Seek(bigtime_t media_time
, bigtime_t performance_time
)
244 BMediaEventLooper::Seek(media_time
, performance_time
);
249 VideoProducer::TimeWarp(bigtime_t at_real_time
, bigtime_t to_performance_time
)
251 BMediaEventLooper::TimeWarp(at_real_time
, to_performance_time
);
256 VideoProducer::AddTimer(bigtime_t at_performance_time
, int32 cookie
)
258 return BMediaEventLooper::AddTimer(at_performance_time
, cookie
);
263 VideoProducer::SetRunMode(run_mode mode
)
265 BMediaEventLooper::SetRunMode(mode
);
270 VideoProducer::HandleEvent(const media_timed_event
*event
,
271 bigtime_t lateness
, bool realTimeEvent
)
273 TOUCH(lateness
); TOUCH(realTimeEvent
);
275 switch(event
->type
) {
276 case BTimedEventQueue::B_START
:
277 HandleStart(event
->event_time
);
279 case BTimedEventQueue::B_STOP
:
282 case BTimedEventQueue::B_WARP
:
283 HandleTimeWarp(event
->bigdata
);
285 case BTimedEventQueue::B_SEEK
:
286 HandleSeek(event
->bigdata
);
288 case BTimedEventQueue::B_HANDLE_BUFFER
:
289 case BTimedEventQueue::B_DATA_STATUS
:
290 case BTimedEventQueue::B_PARAMETER
:
292 PRINTF(-1, ("HandleEvent: Unhandled event -- %lx\n", event
->type
));
299 VideoProducer::CleanUpEvent(const media_timed_event
*event
)
301 BMediaEventLooper::CleanUpEvent(event
);
306 VideoProducer::OfflineTime()
308 return BMediaEventLooper::OfflineTime();
313 VideoProducer::ControlLoop()
315 BMediaEventLooper::ControlLoop();
320 VideoProducer::DeleteHook(BMediaNode
* node
)
322 return BMediaEventLooper::DeleteHook(node
);
326 /* BBufferProducer */
330 VideoProducer::FormatSuggestionRequested(
331 media_type type
, int32 quality
, media_format
*format
)
333 if (type
!= B_MEDIA_ENCODED_VIDEO
)
334 return B_MEDIA_BAD_FORMAT
;
338 PRINTF(1, ("FormatSuggestionRequested() %ldx%ld\n", \
339 format
->u
.raw_video
.display
.line_width
, \
340 format
->u
.raw_video
.display
.line_count
));
342 *format
= fOutput
.format
;
343 uint32 width
, height
;
344 if (fCamDevice
&& fCamDevice
->SuggestVideoFrame(width
, height
) == B_OK
) {
345 format
->u
.raw_video
.display
.line_width
= width
;
346 format
->u
.raw_video
.display
.line_count
= height
;
348 format
->u
.raw_video
.field_rate
= FIELD_RATE
;
354 VideoProducer::FormatProposal(const media_source
&output
, media_format
*format
)
361 if (output
!= fOutput
.source
)
362 return B_MEDIA_BAD_SOURCE
;
364 PRINTF(1, ("FormatProposal() %ldx%ld\n", \
365 format
->u
.raw_video
.display
.line_width
, \
366 format
->u
.raw_video
.display
.line_count
));
368 err
= format_is_compatible(*format
, fOutput
.format
) ?
369 B_OK
: B_MEDIA_BAD_FORMAT
;
371 uint32 width
= format
->u
.raw_video
.display
.line_width
;
372 uint32 height
= format
->u
.raw_video
.display
.line_count
;
374 *format
= fOutput
.format
;
376 if (err
== B_OK
&& fCamDevice
) {
377 err
= fCamDevice
->AcceptVideoFrame(width
, height
);
379 format
->u
.raw_video
.display
.line_width
= width
;
380 format
->u
.raw_video
.display
.line_count
= height
;
384 PRINTF(1, ("FormatProposal: %ldx%ld\n", \
385 format
->u
.raw_video
.display
.line_width
, \
386 format
->u
.raw_video
.display
.line_count
));
394 VideoProducer::FormatChangeRequested(const media_source
&source
,
395 const media_destination
&destination
, media_format
*io_format
,
398 TOUCH(destination
); TOUCH(io_format
); TOUCH(_deprecated_
);
399 if (source
!= fOutput
.source
)
400 return B_MEDIA_BAD_SOURCE
;
407 VideoProducer::GetNextOutput(int32
*cookie
, media_output
*out_output
)
415 *out_output
= fOutput
;
422 VideoProducer::DisposeOutputCookie(int32 cookie
)
431 VideoProducer::SetBufferGroup(const media_source
&for_source
,
434 TOUCH(for_source
); TOUCH(group
);
441 VideoProducer::VideoClippingChanged(const media_source
&for_source
,
442 int16 num_shorts
, int16
*clip_data
,
443 const media_video_display_info
&display
, int32
*_deprecated_
)
445 TOUCH(for_source
); TOUCH(num_shorts
); TOUCH(clip_data
);
446 TOUCH(display
); TOUCH(_deprecated_
);
453 VideoProducer::GetLatency(bigtime_t
*out_latency
)
455 *out_latency
= EventLatency() + SchedulingLatency();
461 VideoProducer::PrepareToConnect(const media_source
&source
,
462 const media_destination
&destination
, media_format
*format
,
463 media_source
*out_source
, char *out_name
)
467 PRINTF(1, ("PrepareToConnect() %ldx%ld\n", \
468 format
->u
.raw_video
.display
.line_width
, \
469 format
->u
.raw_video
.display
.line_count
));
472 PRINTF(0, ("PrepareToConnect: Already connected\n"));
476 if (source
!= fOutput
.source
)
477 return B_MEDIA_BAD_SOURCE
;
479 if (fOutput
.destination
!= media_destination::null
)
480 return B_MEDIA_ALREADY_CONNECTED
;
482 /* The format parameter comes in with the suggested format, and may be
483 * specialized as desired by the node */
484 if (!format_is_compatible(*format
, fOutput
.format
)) {
485 *format
= fOutput
.format
;
486 return B_MEDIA_BAD_FORMAT
;
491 // if (format->u.raw_video.display.line_width == 0)
492 format
->u
.raw_video
.display
.line_width
= 352;//320;
493 format
->u
.raw_video
.display
.line_width
= 320;
494 // if (format->u.raw_video.display.line_count == 0)
495 format
->u
.raw_video
.display
.line_count
= 288;//240;
496 format
->u
.raw_video
.display
.line_count
= 240;
501 format
->u
.raw_video
.display
.line_width
= 320;
502 format
->u
.raw_video
.display
.line_count
= 240;
507 format
->u
.raw_video
.display
.line_width
= 160;
508 format
->u
.raw_video
.display
.line_count
= 120;
511 #ifdef FORCE_MAX_FRAME
513 format
->u
.raw_video
.display
.line_width
= 0;
514 format
->u
.raw_video
.display
.line_count
= 0;
518 err
= fCamDevice
->AcceptVideoFrame(
519 format
->u
.raw_video
.display
.line_width
,
520 format
->u
.raw_video
.display
.line_count
);
525 if (format
->u
.raw_video
.field_rate
== 0)
526 format
->u
.raw_video
.field_rate
= FIELD_RATE
;
528 *out_source
= fOutput
.source
;
529 strcpy(out_name
, fOutput
.name
);
531 fOutput
.destination
= destination
;
538 VideoProducer::Connect(status_t error
, const media_source
&source
,
539 const media_destination
&destination
, const media_format
&format
,
542 PRINTF(1, ("Connect() %ldx%ld\n", \
543 format
.u
.raw_video
.display
.line_width
, \
544 format
.u
.raw_video
.display
.line_count
));
547 PRINTF(0, ("Connect: Already connected\n"));
551 BAutolock
lock(fCamDevice
->Locker());
552 if (!fCamDevice
->IsPlugged()) {
553 PRINTF(0, ("Connect: Device unplugged\n"));
557 if (source
!= fOutput
.source
|| error
< B_OK
558 || !const_cast<media_format
*>(&format
)->Matches(&fOutput
.format
)) {
559 PRINTF(1, ("Connect: Connect error\n"));
563 fOutput
.destination
= destination
;
564 strcpy(io_name
, fOutput
.name
);
566 if (fOutput
.format
.u
.raw_video
.field_rate
!= 0.0f
) {
567 fPerformanceTimeBase
= fPerformanceTimeBase
+
569 ((fFrame
- fFrameBase
) *
570 (1000000 / fOutput
.format
.u
.raw_video
.field_rate
));
574 fConnectedFormat
= format
.u
.raw_video
;
576 /* get the latency */
577 bigtime_t latency
= 0;
578 media_node_id tsID
= 0;
579 FindLatencyFor(fOutput
.destination
, &latency
, &tsID
);
580 #define NODE_LATENCY 1000
581 SetEventLatency(latency
+ NODE_LATENCY
);
583 uint32
*buffer
, *p
, f
= 3;
584 p
= buffer
= (uint32
*)malloc(4 * fConnectedFormat
.display
.line_count
*
585 fConnectedFormat
.display
.line_width
);
587 PRINTF(0, ("Connect: Out of memory\n"));
590 bigtime_t now
= system_time();
591 for (uint32 y
=0;y
<fConnectedFormat
.display
.line_count
;y
++)
592 for (uint32 x
=0;x
<fConnectedFormat
.display
.line_width
;x
++)
593 *(p
++) = ((((x
+y
)^0^x
)+f
) & 0xff) * (0x01010101 & fColor
);
594 fProcessingLatency
= system_time() - now
;
597 /* Create the buffer group */
598 fBufferGroup
= new BBufferGroup(4 * fConnectedFormat
.display
.line_width
*
599 fConnectedFormat
.display
.line_count
, 8);
600 if (fBufferGroup
->InitCheck() < B_OK
) {
609 /* Tell frame generation thread to recalculate delay value */
610 release_sem(fFrameSync
);
614 VideoProducer::Disconnect(const media_source
&source
,
615 const media_destination
&destination
)
617 PRINTF(1, ("Disconnect()\n"));
620 PRINTF(0, ("Disconnect: Not connected\n"));
624 if ((source
!= fOutput
.source
) || (destination
!= fOutput
.destination
)) {
625 PRINTF(0, ("Disconnect: Bad source and/or destination\n"));
630 /* Some dumb apps don't stop nodes before disconnecting... */
636 fOutput
.destination
= media_destination::null
;
648 VideoProducer::LateNoticeReceived(const media_source
&source
,
649 bigtime_t how_much
, bigtime_t performance_time
)
651 TOUCH(source
); TOUCH(how_much
); TOUCH(performance_time
);
656 VideoProducer::EnableOutput(const media_source
&source
, bool enabled
,
661 if (source
!= fOutput
.source
)
669 VideoProducer::SetPlayRate(int32 numer
, int32 denom
)
671 TOUCH(numer
); TOUCH(denom
);
678 VideoProducer::AdditionalBufferRequested(const media_source
&source
,
679 media_buffer_id prev_buffer
, bigtime_t prev_time
,
680 const media_seek_tag
*prev_tag
)
682 TOUCH(source
); TOUCH(prev_buffer
); TOUCH(prev_time
); TOUCH(prev_tag
);
687 VideoProducer::LatencyChanged(const media_source
&source
,
688 const media_destination
&destination
, bigtime_t new_latency
,
691 TOUCH(source
); TOUCH(destination
); TOUCH(new_latency
); TOUCH(flags
);
699 VideoProducer::GetParameterValue(
700 int32 id
, bigtime_t
*last_change
, void *value
, size_t *size
)
706 //return B_BAD_VALUE;
708 *last_change
= fLastColorChange
;
709 *size
= sizeof(uint32
);
710 *((uint32
*)value
) = fColor
;
713 if (*size
< fInfoString
.Length() + 1)
715 *last_change
= fLastColorChange
;
716 *size
= fInfoString
.Length() + 1;
717 memcpy(value
, fInfoString
.String(), *size
);
722 BAutolock
lock(fCamDevice
->Locker());
723 err
= fCamDevice
->GetParameterValue(id
, last_change
, value
, size
);
726 if (fCamDevice
->Sensor()) {
727 err
= fCamDevice
->Sensor()->GetParameterValue(id
, last_change
, value
, size
);
738 VideoProducer::SetParameterValue(
739 int32 id
, bigtime_t when
, const void *value
, size_t size
)
745 if (!value
|| (size
!= sizeof(uint32
)))
748 if (*(uint32
*)value
== fColor
)
751 fColor
= *(uint32
*)value
;
752 fLastColorChange
= when
;
758 if (fCamDevice
== NULL
)
761 BAutolock
lock(fCamDevice
->Locker());
762 err
= fCamDevice
->SetParameterValue(id
, when
, value
, size
);
763 if ((err
< B_OK
) && (fCamDevice
->Sensor())) {
764 err
= fCamDevice
->Sensor()->SetParameterValue(id
, when
, value
, size
);
769 BroadcastNewParameterValue(when
, id
, (void *)value
, size
);
774 VideoProducer::StartControlPanel(BMessenger
*out_messenger
)
776 return BControllable::StartControlPanel(out_messenger
);
784 VideoProducer::HandleStart(bigtime_t performance_time
)
786 /* Start producing frames, even if the output hasn't been connected yet. */
788 PRINTF(1, ("HandleStart(%Ld)\n", performance_time
));
791 PRINTF(-1, ("HandleStart: Node already started\n"));
797 fPerformanceTimeBase
= performance_time
;
799 fFrameSync
= create_sem(0, "frame synchronization");
800 if (fFrameSync
< B_OK
)
803 fThread
= spawn_thread(_frame_generator_
, "frame generator",
804 B_NORMAL_PRIORITY
, this);
808 resume_thread(fThread
);
811 BAutolock
lock(fCamDevice
->Locker());
812 fCamDevice
->StartTransfer();
819 delete_sem(fFrameSync
);
826 VideoProducer::HandleStop(void)
828 PRINTF(1, ("HandleStop()\n"));
831 PRINTF(-1, ("HandleStop: Node isn't running\n"));
835 delete_sem(fFrameSync
);
836 wait_for_thread(fThread
, &fThread
);
838 BAutolock
lock(fCamDevice
->Locker());
839 fCamDevice
->StopTransfer();
846 VideoProducer::HandleTimeWarp(bigtime_t performance_time
)
848 fPerformanceTimeBase
= performance_time
;
851 /* Tell frame generation thread to recalculate delay value */
852 release_sem(fFrameSync
);
857 VideoProducer::HandleSeek(bigtime_t performance_time
)
859 fPerformanceTimeBase
= performance_time
;
862 /* Tell frame generation thread to recalculate delay value */
863 release_sem(fFrameSync
);
868 VideoProducer::_UpdateStats()
870 float fps
= (fStats
[0].frames
- fStats
[1].frames
) * 1000000LL
871 / (double)(fStats
[0].stamp
- fStats
[1].stamp
);
872 float rfps
= (fStats
[0].actual
- fStats
[1].actual
) * 1000000LL
873 / (double)(fStats
[0].stamp
- fStats
[1].stamp
);
874 fInfoString
= "FPS: ";
875 fInfoString
<< fps
<< " virt, "
876 << rfps
<< " real, missed: " << fStats
[0].missed
;
877 memcpy(&fStats
[1], &fStats
[0], sizeof(fStats
[0]));
878 fLastColorChange
= system_time();
879 BroadcastNewParameterValue(fLastColorChange
, P_INFO
,
880 (void *)fInfoString
.String(), fInfoString
.Length()+1);
884 /* The following functions form the thread that generates frames. You should
885 * replace this with the code that interfaces to your hardware. */
887 VideoProducer::FrameGenerator()
889 bigtime_t wait_until
= system_time();
892 PRINTF(1, ("FrameGenerator: acquire_sem_etc() until %Ldµs (in %Ldµs)\n", wait_until
, wait_until
- system_time()));
893 status_t err
= acquire_sem_etc(fFrameSync
, 1, B_ABSOLUTE_TIMEOUT
,
896 /* The only acceptable responses are B_OK and B_TIMED_OUT. Everything
897 * else means the thread should quit. Deleting the semaphore, as in
898 * VideoProducer::HandleStop(), will trigger this behavior. */
899 if ((err
!= B_OK
) && (err
!= B_TIMED_OUT
))
904 /* Recalculate the time until the thread should wake up to begin
905 * processing the next frame. Subtract fProcessingLatency so that
906 * the frame is sent in time. */
907 wait_until
= TimeSource()->RealTimeFor(fPerformanceTimeBase
, 0) +
909 ((fFrame
- fFrameBase
) *
910 (1000000 / fConnectedFormat
.field_rate
)) -
912 PRINT(("PS: %Ld\n", fProcessingLatency
));
914 /* Drop frame if it's at least a frame late */
915 if (wait_until
< system_time())
918 PRINTF(1, ("FrameGenerator: wait until %Ld, %ctimed out, %crunning, %cenabled.\n",
920 (err
== B_OK
)?'!':' ',
922 (fEnabled
)?' ':'!'));
924 /* If the semaphore was acquired successfully, it means something
925 * changed the timing information (see VideoProducer::Connect()) and
926 * so the thread should go back to sleep until the newly-calculated
927 * wait_until time. */
931 /* Send buffers only if the node is running and the output has been
933 if (!fRunning
|| !fEnabled
)
938 /* Fetch a buffer from the buffer group */
939 BBuffer
*buffer
= fBufferGroup
->RequestBuffer(
940 4 * fConnectedFormat
.display
.line_width
*
941 fConnectedFormat
.display
.line_count
, 0LL);
945 /* Fill out the details about this buffer. */
946 media_header
*h
= buffer
->Header();
947 h
->type
= B_MEDIA_RAW_VIDEO
;
948 h
->time_source
= TimeSource()->ID();
949 h
->size_used
= 4 * fConnectedFormat
.display
.line_width
*
950 fConnectedFormat
.display
.line_count
;
951 /* For a buffer originating from a device, you might want to calculate
952 * this based on the PerformanceTimeFor the time your buffer arrived at
953 * the hardware (plus any applicable adjustments). */
955 h->start_time = fPerformanceTimeBase +
957 ((fFrame - fFrameBase) *
958 (1000000 / fConnectedFormat.field_rate));
963 h
->u
.raw_video
.field_gamma
= 1.0;
964 h
->u
.raw_video
.field_sequence
= fFrame
;
965 h
->u
.raw_video
.field_number
= 0;
966 h
->u
.raw_video
.pulldown_number
= 0;
967 h
->u
.raw_video
.first_active_line
= 1;
968 h
->u
.raw_video
.line_count
= fConnectedFormat
.display
.line_count
;
970 // This is where we fill the video buffer.
973 uint32
*p
= (uint32
*)buffer
->Data();
974 /* Fill in a pattern */
975 for (uint32 y
=0;y
<fConnectedFormat
.display
.line_count
;y
++)
976 for (uint32 x
=0;x
<fConnectedFormat
.display
.line_width
;x
++)
977 *(p
++) = ((((x
+y
)^0^x
)+fFrame
) & 0xff) * (0x01010101 & fColor
);
980 //NO! must be called without lock!
981 //BAutolock lock(fCamDevice->Locker());
983 bigtime_t now
= system_time();
985 //#ifdef UseFillFrameBuffer
986 err
= fCamDevice
->FillFrameBuffer(buffer
, &stamp
);
992 #ifdef UseGetFrameBitmap
994 err
= fCamDevice
->GetFrameBitmap(&bm
, &stamp
);
1000 fStats
[0].frames
= fFrame
;
1001 fStats
[0].actual
++;;
1002 fStats
[0].stamp
= system_time();
1004 //PRINTF(1, ("FrameGenerator: stamp %Ld vs %Ld\n", stamp, h->start_time));
1005 //XXX: that's what we should be doing, but CodyCam drops all frames as they are late. (maybe add latency ??)
1006 //h->start_time = TimeSource()->PerformanceTimeFor(stamp);
1007 h
->start_time
= TimeSource()->PerformanceTimeFor(system_time());
1010 // update processing latency
1012 fProcessingLatency
= system_time() - now
;
1013 fProcessingLatency
/= 10;
1015 PRINTF(1, ("FrameGenerator: SendBuffer...\n"));
1016 /* Send the buffer on down to the consumer */
1017 if (SendBuffer(buffer
, fOutput
.source
, fOutput
.destination
) < B_OK
) {
1018 PRINTF(-1, ("FrameGenerator: Error sending buffer\n"));
1019 /* If there is a problem sending the buffer, return it to its
1027 PRINTF(1, ("FrameGenerator: thread existed.\n"));
1033 VideoProducer::_frame_generator_(void *data
)
1035 return ((VideoProducer
*)data
)->FrameGenerator();