2 * This file is a part of BeOS USBVision driver project.
3 * Copyright (c) 2003 by Siarzuk Zharski <imker@gmx.li>
5 * This file may be used under the terms of the BSD License
7 * Skeletal part of this code was inherired from original BeOS sample code,
8 * that is distributed under the terms of the Be Sample Code License.
20 #include <media/Buffer.h>
21 #include <media/BufferGroup.h>
22 #include <media/ParameterWeb.h>
23 #include <media/TimeSource.h>
25 #include <support/Autolock.h>
26 #include <support/Debug.h>
28 #define TOUCH(x) ((void)(x))
33 printf("VideoProducer::"); \
40 #define FIELD_RATE 30.f
42 const float kUSBBandWidthMin
= 0.5f
;
43 const float kUSBBandWidthMax
= 7.5f
;
44 const float kUSBBandWidthStep
= 0.5f
;
46 const float kVScreenOffsetMin
= 0.f
;
47 const float kVScreenOffsetMax
= 4.f
;
48 const float kVScreenOffsetStep
= 1.f
;
49 const float kHScreenOffsetMin
= 0.f
;
50 const float kHScreenOffsetMax
= 4.f
;
51 const float kHScreenOffsetStep
= 1.f
;
53 const float kEffectMin
= 0.f
;
54 const float kEffectMax
= 31.f
;
55 const float kEffectStep
= 1.f
;
57 const float kBrightnessMin
= kEffectMin
;
58 const float kBrightnessMax
= kEffectMax
;
59 const float kBrightnessStep
= kEffectStep
;
61 const float kContrastMin
= kEffectMin
;
62 const float kContrastMax
= kEffectMax
;
63 const float kContrastStep
= kEffectStep
;
65 const float kHueMin
= kEffectMin
;
66 const float kHueMax
= kEffectMax
;
67 const float kHueStep
= kEffectStep
;
69 const float kSaturationMin
= kEffectMin
;
70 const float kSaturationMax
= kEffectMax
;
71 const float kSaturationStep
= kEffectStep
;
73 const uint32 kDefChannel
= 0;
74 //const VideoInput kDefVideoInput = P_VI_TUNER;
75 const uint32 kDefAudioInput
= 0;
76 const uint32 kDefBrightness
= 20;
77 const uint32 kDefContrast
= 22;
78 const uint32 kDefSaturation
= 15;
79 const uint32 kDefHue
= 20;
80 const uint32 kDefCaptureSize
= 0;
81 const uint32 kDefCaptureFormat
= 0;
82 //const VideoStandard kDefStandard = P_VF_PAL_BDGHI;
83 const float kDefBandwidth
= 7.0;
84 const uint32 kDefLocale
= 0;
85 const uint32 kDefVertOffset
= 1;
86 const uint32 kDefHorzOffset
= 2;
88 int32
VideoProducer::fInstances
= 0;
90 VideoProducer::VideoProducer(
91 BMediaAddOn
*addon
, const char *name
, int32 internal_id
)
94 BBufferProducer(B_MEDIA_RAW_VIDEO
),
99 fInitStatus
= B_NO_INIT
;
101 /* Only allow one instance of the node to exist at any time */
102 if (atomic_add(&fInstances
, 1) != 0)
105 fInternalID
= internal_id
;
112 fProcessingLatency
= 0LL;
118 fOutput
.destination
= media_destination::null
;
120 AddNodeKind(B_PHYSICAL_INPUT
);
126 status_t status
= Locale::TunerLocale::LoadLocales(fLocales
);
128 printf("LoadLocales:%08x\n", status
);
130 fChannel
= kDefChannel
;
131 fVideoInput
= P_VI_TUNER
;
132 fAudioInput
= kDefAudioInput
;
133 fBrightness
= kDefBrightness
;
134 fContrast
= kDefContrast
;
135 fSaturation
= kDefSaturation
;
137 fCaptureSize
= kDefCaptureSize
;
138 fCaptureFormat
= kDefCaptureFormat
;
139 fStandard
= P_VF_PAL_BDGHI
;
140 fLocale
= kDefLocale
;
141 fBandwidth
= kDefBandwidth
;
142 fVertOffset
= kDefVertOffset
;
143 fHorzOffset
= kDefHorzOffset
;
144 fColor
= B_HOST_TO_LENDIAN_INT32(0x00ff0000);
147 fLastVideoInputChange
=
148 fLastAudioInputChange
=
149 fLastBrightnessChange
=
150 fLastContrastChange
=
151 fLastSaturationChange
=
153 fLastCaptureSizeChange
=
154 fLastCaptureFormatChange
=
155 fLastStandardChange
=
157 fLastBandwidthChange
=
158 fLastVertOffsetChange
=
159 fLastHorzOffsetChange
=
160 fLastColorChange
= system_time();
165 VideoProducer::~VideoProducer()
167 if (fInitStatus
== B_OK
) {
168 /* Clean up after ourselves, in case the application didn't make us
171 Disconnect(fOutput
.source
, fOutput
.destination
);
176 atomic_add(&fInstances
, -1);
178 Locale::TunerLocale::ReleaseLocales(fLocales
);
184 VideoProducer::ControlPort() const
186 return BMediaNode::ControlPort();
190 VideoProducer::AddOn(int32
*internal_id
) const
193 *internal_id
= fInternalID
;
198 VideoProducer::HandleMessage(int32 message
, const void *data
, size_t size
)
204 VideoProducer::Preroll()
206 /* This hook may be called before the node is started to give the hardware
207 * a chance to start. */
211 VideoProducer::SetTimeSource(BTimeSource
*time_source
)
213 /* Tell frame generation thread to recalculate delay value */
214 release_sem(fFrameSync
);
218 VideoProducer::RequestCompleted(const media_request_info
&info
)
220 return BMediaNode::RequestCompleted(info
);
223 /* BMediaEventLooper */
226 VideoProducer::NodeRegistered()
228 if (fInitStatus
!= B_OK
) {
229 ReportError(B_NODE_IN_DISTRESS
);
233 /* After this call, the BControllable owns the BParameterWeb object and
234 * will delete it for you */
235 SetParameterWeb(CreateParameterWeb());
237 fOutput
.node
= Node();
238 fOutput
.source
.port
= ControlPort();
239 fOutput
.source
.id
= 0;
240 fOutput
.destination
= media_destination::null
;
241 strcpy(fOutput
.name
, Name());
243 /* Tailor these for the output of your device */
244 fOutput
.format
.type
= B_MEDIA_RAW_VIDEO
;
245 fOutput
.format
.u
.raw_video
= media_raw_video_format::wildcard
;
246 fOutput
.format
.u
.raw_video
.interlace
= 1;
247 fOutput
.format
.u
.raw_video
.display
.format
= B_RGB32
;
249 /* Start the BMediaEventLooper control loop running */
253 BParameterWeb
*VideoProducer::CreateParameterWeb()
255 /* Set up the parameter web */
256 BParameterWeb
*web
= new BParameterWeb();
258 BParameterGroup
*controls
= web
->MakeGroup("Controls");
259 BParameterGroup
*group
= controls
->MakeGroup("Main Controls");
260 BDiscreteParameter
*parameter
= group
->MakeDiscreteParameter(
261 P_CHANNEL
, B_MEDIA_NO_TYPE
, "Channel:", B_GENERIC
);
262 for(int i
= 0; i
< fLocales
[fLocale
]->ChannelsCount(); i
++){
263 parameter
->AddItem(i
, (fLocales
[fLocale
]->GetChannel(i
)).Name().c_str());
266 parameter
= group
->MakeDiscreteParameter(
267 P_VIDEO_INPUT
, B_MEDIA_NO_TYPE
, "Video Input:", B_INPUT_MUX
);
268 parameter
->AddItem(P_VI_TUNER
, "Tuner");
269 parameter
->AddItem(P_VI_COMPOSITE
, "Composite");
270 parameter
->AddItem(P_VI_SVIDEO
, "SVideo");
272 parameter
= group
->MakeDiscreteParameter(
273 P_AUDIO_INPUT
, B_MEDIA_NO_TYPE
, "Audio Input:", B_INPUT_MUX
);
274 parameter
->AddItem(1, "TODO");
275 parameter
->AddItem(2, "TODO");
276 parameter
->AddItem(3, "TODO");
278 group
= controls
->MakeGroup("Effect Controls");
279 group
->MakeContinuousParameter(
280 P_BRIGHTNESS
, B_MEDIA_NO_TYPE
, "Brightness", B_LEVEL
,
281 "", kBrightnessMin
, kBrightnessMax
, kBrightnessStep
);
283 group
->MakeContinuousParameter(
284 P_CONTRAST
, B_MEDIA_NO_TYPE
, "Contrast", B_LEVEL
,
285 "", kContrastMin
, kContrastMax
, kContrastStep
);
287 group
= controls
->MakeGroup("Adv. Effect Controls");
288 group
->MakeContinuousParameter(
289 P_SATURATION
, B_MEDIA_NO_TYPE
, "Saturation", B_LEVEL
,
290 "", kSaturationMin
, kSaturationMax
, kSaturationStep
);
292 group
->MakeContinuousParameter(
293 P_HUE
, B_MEDIA_NO_TYPE
, "Hue", B_LEVEL
,
294 "", kHueMin
, kHueMax
, kHueStep
);
296 BParameterGroup
*options
= web
->MakeGroup("Options");
297 group
= options
->MakeGroup("Capture Option");
298 parameter
= group
->MakeDiscreteParameter(
299 P_CAPTURE_SIZE
, B_MEDIA_NO_TYPE
, "Capture Size:", B_RESOLUTION
);
300 parameter
->AddItem(1, "TODO");
301 parameter
->AddItem(2, "TODO");
303 parameter
= group
->MakeDiscreteParameter(
304 P_CAPTURE_FORMAT
, B_MEDIA_NO_TYPE
, "Capture Format:", B_COLOR_SPACE
);
305 parameter
->AddItem(1, "TODO");
306 parameter
->AddItem(2, "TODO");
308 BParameterGroup
*hardware
= web
->MakeGroup("Hardware Setup");
309 group
= hardware
->MakeGroup("Format");
310 parameter
= group
->MakeDiscreteParameter(
311 P_STANDART
, B_MEDIA_NO_TYPE
, "Video Format:", B_VIDEO_FORMAT
);
312 parameter
->AddItem(P_VF_NTSC_M
, "NTSC M");
313 parameter
->AddItem(P_VF_NTSC_MJ
, "NTSC MJ");
314 parameter
->AddItem(P_VF_PAL_BDGHI
, "PAL BDGHI");
315 parameter
->AddItem(P_VF_PAL_M
, "PAL M");
316 parameter
->AddItem(P_VF_PAL_N
, "PAL N");
317 parameter
->AddItem(P_VF_SECAM
, "SECAM");
319 parameter
= group
->MakeDiscreteParameter(
320 P_LOCALE
, B_MEDIA_NO_TYPE
, "Tuner Locale:", B_GENERIC
);
321 for(int i
= 0; i
< fLocales
.size(); i
++)
322 parameter
->AddItem(i
, fLocales
[i
]->Name().c_str());
324 group
= hardware
->MakeGroup("Format");
326 group
->MakeContinuousParameter(
327 P_BANDWIDTH
, B_MEDIA_NO_TYPE
, "Max.Bandwidth", B_LEVEL
,
328 "", kUSBBandWidthMin
, kUSBBandWidthMax
, kUSBBandWidthStep
);
330 group
= hardware
->MakeGroup("Offsets");
332 group
->MakeContinuousParameter(
333 P_VERT_OFFSET
, B_MEDIA_NO_TYPE
, "Vertical Offset", B_LEVEL
,
334 "", kVScreenOffsetMin
, kVScreenOffsetMax
, kVScreenOffsetStep
);
336 group
->MakeContinuousParameter(
337 P_HORZ_OFFSET
, B_MEDIA_NO_TYPE
, "Horizontal Offset", B_LEVEL
,
338 "", kHScreenOffsetMin
, kHScreenOffsetMax
, kHScreenOffsetStep
);
340 BParameterGroup
*main
= web
->MakeGroup(Name());
341 BDiscreteParameter
*state
= main
->MakeDiscreteParameter(
342 P_COLOR
, B_MEDIA_RAW_VIDEO
, "Color", "Color");
343 state
->AddItem(B_HOST_TO_LENDIAN_INT32(0x00ff0000), "Red");
344 state
->AddItem(B_HOST_TO_LENDIAN_INT32(0x0000ff00), "Green");
345 state
->AddItem(B_HOST_TO_LENDIAN_INT32(0x000000ff), "Blue");
351 VideoProducer::Start(bigtime_t performance_time
)
353 BMediaEventLooper::Start(performance_time
);
357 VideoProducer::Stop(bigtime_t performance_time
, bool immediate
)
359 BMediaEventLooper::Stop(performance_time
, immediate
);
363 VideoProducer::Seek(bigtime_t media_time
, bigtime_t performance_time
)
365 BMediaEventLooper::Seek(media_time
, performance_time
);
369 VideoProducer::TimeWarp(bigtime_t at_real_time
, bigtime_t to_performance_time
)
371 BMediaEventLooper::TimeWarp(at_real_time
, to_performance_time
);
375 VideoProducer::AddTimer(bigtime_t at_performance_time
, int32 cookie
)
377 return BMediaEventLooper::AddTimer(at_performance_time
, cookie
);
381 VideoProducer::SetRunMode(run_mode mode
)
383 BMediaEventLooper::SetRunMode(mode
);
387 VideoProducer::HandleEvent(const media_timed_event
*event
,
388 bigtime_t lateness
, bool realTimeEvent
)
390 TOUCH(lateness
); TOUCH(realTimeEvent
);
394 case BTimedEventQueue::B_START
:
395 HandleStart(event
->event_time
);
397 case BTimedEventQueue::B_STOP
:
400 case BTimedEventQueue::B_WARP
:
401 HandleTimeWarp(event
->bigdata
);
403 case BTimedEventQueue::B_SEEK
:
404 HandleSeek(event
->bigdata
);
406 case BTimedEventQueue::B_PARAMETER
:
407 HandleParameter(event
->data
);
409 case BTimedEventQueue::B_HANDLE_BUFFER
:
410 case BTimedEventQueue::B_DATA_STATUS
:
412 PRINTF(-1, ("HandleEvent: Unhandled event -- %lx\n", event
->type
));
418 VideoProducer::CleanUpEvent(const media_timed_event
*event
)
420 BMediaEventLooper::CleanUpEvent(event
);
424 VideoProducer::OfflineTime()
426 return BMediaEventLooper::OfflineTime();
430 VideoProducer::ControlLoop()
432 BMediaEventLooper::ControlLoop();
436 VideoProducer::DeleteHook(BMediaNode
* node
)
438 return BMediaEventLooper::DeleteHook(node
);
441 /* BBufferProducer */
444 VideoProducer::FormatSuggestionRequested(
445 media_type type
, int32 quality
, media_format
*format
)
447 if (type
!= B_MEDIA_ENCODED_VIDEO
)
448 return B_MEDIA_BAD_FORMAT
;
452 *format
= fOutput
.format
;
457 VideoProducer::FormatProposal(const media_source
&output
, media_format
*format
)
464 if (output
!= fOutput
.source
)
465 return B_MEDIA_BAD_SOURCE
;
467 err
= format_is_compatible(*format
, fOutput
.format
) ?
468 B_OK
: B_MEDIA_BAD_FORMAT
;
469 *format
= fOutput
.format
;
475 VideoProducer::FormatChangeRequested(const media_source
&source
,
476 const media_destination
&destination
, media_format
*io_format
,
479 TOUCH(destination
); TOUCH(io_format
); TOUCH(_deprecated_
);
480 if (source
!= fOutput
.source
)
481 return B_MEDIA_BAD_SOURCE
;
487 VideoProducer::GetNextOutput(int32
*cookie
, media_output
*out_output
)
495 *out_output
= fOutput
;
501 VideoProducer::DisposeOutputCookie(int32 cookie
)
509 VideoProducer::SetBufferGroup(const media_source
&for_source
,
512 TOUCH(for_source
); TOUCH(group
);
518 VideoProducer::VideoClippingChanged(const media_source
&for_source
,
519 int16 num_shorts
, int16
*clip_data
,
520 const media_video_display_info
&display
, int32
*_deprecated_
)
522 TOUCH(for_source
); TOUCH(num_shorts
); TOUCH(clip_data
);
523 TOUCH(display
); TOUCH(_deprecated_
);
529 VideoProducer::GetLatency(bigtime_t
*out_latency
)
531 *out_latency
= EventLatency() + SchedulingLatency();
536 VideoProducer::PrepareToConnect(const media_source
&source
,
537 const media_destination
&destination
, media_format
*format
,
538 media_source
*out_source
, char *out_name
)
542 PRINTF(1, ("PrepareToConnect() %ldx%ld\n", \
543 format
->u
.raw_video
.display
.line_width
, \
544 format
->u
.raw_video
.display
.line_count
));
547 PRINTF(0, ("PrepareToConnect: Already connected\n"));
551 if (source
!= fOutput
.source
)
552 return B_MEDIA_BAD_SOURCE
;
554 if (fOutput
.destination
!= media_destination::null
)
555 return B_MEDIA_ALREADY_CONNECTED
;
557 /* The format parameter comes in with the suggested format, and may be
558 * specialized as desired by the node */
559 if (!format_is_compatible(*format
, fOutput
.format
)) {
560 *format
= fOutput
.format
;
561 return B_MEDIA_BAD_FORMAT
;
564 if (format
->u
.raw_video
.display
.line_width
== 0)
565 format
->u
.raw_video
.display
.line_width
= 320;
566 if (format
->u
.raw_video
.display
.line_count
== 0)
567 format
->u
.raw_video
.display
.line_count
= 240;
568 if (format
->u
.raw_video
.field_rate
== 0)
569 format
->u
.raw_video
.field_rate
= 29.97f
;
571 *out_source
= fOutput
.source
;
572 strcpy(out_name
, fOutput
.name
);
574 fOutput
.destination
= destination
;
580 VideoProducer::Connect(status_t error
, const media_source
&source
,
581 const media_destination
&destination
, const media_format
&format
,
584 PRINTF(1, ("Connect() %ldx%ld\n", \
585 format
.u
.raw_video
.display
.line_width
, \
586 format
.u
.raw_video
.display
.line_count
));
589 PRINTF(0, ("Connect: Already connected\n"));
593 if ( (source
!= fOutput
.source
) || (error
< B_OK
) ||
594 !const_cast<media_format
*>(&format
)->Matches(&fOutput
.format
)) {
595 PRINTF(1, ("Connect: Connect error\n"));
599 fOutput
.destination
= destination
;
600 strcpy(io_name
, fOutput
.name
);
602 if (fOutput
.format
.u
.raw_video
.field_rate
!= 0.0f
) {
603 fPerformanceTimeBase
= fPerformanceTimeBase
+
605 ((fFrame
- fFrameBase
) *
606 (1000000 / fOutput
.format
.u
.raw_video
.field_rate
));
610 fConnectedFormat
= format
.u
.raw_video
;
612 /* get the latency */
613 bigtime_t latency
= 0;
614 media_node_id tsID
= 0;
615 FindLatencyFor(fOutput
.destination
, &latency
, &tsID
);
616 #define NODE_LATENCY 1000
617 SetEventLatency(latency
+ NODE_LATENCY
);
619 uint32
*buffer
, *p
, f
= 3;
620 p
= buffer
= (uint32
*)malloc(4 * fConnectedFormat
.display
.line_count
*
621 fConnectedFormat
.display
.line_width
);
623 PRINTF(0, ("Connect: Out of memory\n"));
626 bigtime_t now
= system_time();
627 for (int y
=0;y
<fConnectedFormat
.display
.line_count
;y
++)
628 for (int x
=0;x
<fConnectedFormat
.display
.line_width
;x
++)
629 *(p
++) = ((((x
+y
)^0^x
)+f
) & 0xff) * (0x01010101 & fColor
);
630 fProcessingLatency
= system_time() - now
;
633 /* Create the buffer group */
634 fBufferGroup
= new BBufferGroup(4 * fConnectedFormat
.display
.line_width
*
635 fConnectedFormat
.display
.line_count
, 8);
636 if (fBufferGroup
->InitCheck() < B_OK
) {
645 /* Tell frame generation thread to recalculate delay value */
646 release_sem(fFrameSync
);
650 VideoProducer::Disconnect(const media_source
&source
,
651 const media_destination
&destination
)
653 PRINTF(1, ("Disconnect()\n"));
656 PRINTF(0, ("Disconnect: Not connected\n"));
660 if ((source
!= fOutput
.source
) || (destination
!= fOutput
.destination
)) {
661 PRINTF(0, ("Disconnect: Bad source and/or destination\n"));
666 fOutput
.destination
= media_destination::null
;
677 VideoProducer::LateNoticeReceived(const media_source
&source
,
678 bigtime_t how_much
, bigtime_t performance_time
)
680 TOUCH(source
); TOUCH(how_much
); TOUCH(performance_time
);
684 VideoProducer::EnableOutput(const media_source
&source
, bool enabled
,
689 if (source
!= fOutput
.source
)
696 VideoProducer::SetPlayRate(int32 numer
, int32 denom
)
698 TOUCH(numer
); TOUCH(denom
);
704 VideoProducer::AdditionalBufferRequested(const media_source
&source
,
705 media_buffer_id prev_buffer
, bigtime_t prev_time
,
706 const media_seek_tag
*prev_tag
)
708 TOUCH(source
); TOUCH(prev_buffer
); TOUCH(prev_time
); TOUCH(prev_tag
);
712 VideoProducer::LatencyChanged(const media_source
&source
,
713 const media_destination
&destination
, bigtime_t new_latency
,
716 TOUCH(source
); TOUCH(destination
); TOUCH(new_latency
); TOUCH(flags
);
722 VideoProducer::GetParameterValue(
723 int32 id
, bigtime_t
*last_change
, void *value
, size_t *size
)
727 *last_change
= fLastChannelChange
;
728 *size
= sizeof(uint32
);
729 *((uint32
*)value
) = fChannel
;
732 *last_change
= fLastVideoInputChange
;
733 *size
= sizeof(uint32
);
734 *((uint32
*)value
) = fVideoInput
;
737 *last_change
= fLastAudioInputChange
;
738 *size
= sizeof(uint32
);
739 *((uint32
*)value
) = fAudioInput
;
742 *last_change
= fLastBrightnessChange
;
743 *size
= sizeof(float);
744 *((float *)value
) = fBrightness
;
747 *last_change
= fLastContrastChange
;
748 *size
= sizeof(float);
749 *((float*)value
) = fContrast
;
752 *last_change
= fLastSaturationChange
;
753 *size
= sizeof(float);
754 *((float*)value
) = fSaturation
;
757 *last_change
= fLastHueChange
;
758 *size
= sizeof(float);
759 *((float*)value
) = fHue
;
762 *last_change
= fLastCaptureSizeChange
;
763 *size
= sizeof(uint32
);
764 *((uint32
*)value
) = fCaptureSize
;
766 case P_CAPTURE_FORMAT
:
767 *last_change
= fLastCaptureFormatChange
;
768 *size
= sizeof(uint32
);
769 *((uint32
*)value
) = fCaptureFormat
;
772 *last_change
= fLastStandardChange
;
773 *size
= sizeof(uint32
);
774 *((uint32
*)value
) = fStandard
;
777 *last_change
= fLastBandwidthChange
;
778 *size
= sizeof(float);
779 *((float *)value
) = fBandwidth
;
782 *last_change
= fLastLocaleChange
;
783 *size
= sizeof(uint32
);
784 *((uint32
*)value
) = fLocale
;
787 *last_change
= fLastVertOffsetChange
;
788 *size
= sizeof(float);
789 *((float*)value
) = fVertOffset
;
792 *last_change
= fLastHorzOffsetChange
;
793 *size
= sizeof(float);
794 *((float*)value
) = fHorzOffset
;
797 *last_change
= fLastColorChange
;
798 *size
= sizeof(uint32
);
799 *((uint32
*)value
) = fColor
;
808 VideoProducer::SetParameterValue(
809 int32 id
, bigtime_t when
, const void *value
, size_t size
)
813 if (*(uint32
*)value
!= fChannel
){
814 fChannel
= *(uint32
*)value
;
815 fLastChannelChange
= when
;
816 BroadcastNewParameterValue(
817 fLastChannelChange
, P_CHANNEL
, &fChannel
, sizeof(fChannel
));
821 if (*(uint32
*)value
!= fVideoInput
){
822 fVideoInput
= *(uint32
*)value
;
823 fLastVideoInputChange
= when
;
824 BroadcastNewParameterValue(
825 fLastVideoInputChange
, P_VIDEO_INPUT
, &fVideoInput
, sizeof(fVideoInput
));
829 if (*(uint32
*)value
!= fAudioInput
){
830 fAudioInput
= *(uint32
*)value
;
831 fLastAudioInputChange
= when
;
832 BroadcastNewParameterValue(
833 fLastAudioInputChange
, P_AUDIO_INPUT
, &fAudioInput
, sizeof(fAudioInput
));
837 if (*(float *)value
!= fBrightness
){
838 fBrightness
= *(float *)value
;
839 fLastBrightnessChange
= when
;
840 BroadcastNewParameterValue(
841 fLastBrightnessChange
, P_BRIGHTNESS
, &fBrightness
, sizeof(fBrightness
));
845 if (*(float *)value
!= fContrast
){
846 fContrast
= *(float *)value
;
847 fLastContrastChange
= when
;
848 BroadcastNewParameterValue(
849 fLastContrastChange
, P_CONTRAST
, &fContrast
, sizeof(fContrast
));
853 if (*(float *)value
!= fSaturation
){
854 fSaturation
= *(float *)value
;
855 fLastSaturationChange
= when
;
856 BroadcastNewParameterValue(
857 fLastSaturationChange
, P_SATURATION
, &fSaturation
, sizeof(fSaturation
));
861 if (*(float *)value
!= fHue
){
862 fHue
= *(float *)value
;
863 fLastHueChange
= when
;
864 BroadcastNewParameterValue(
865 fLastHueChange
, P_HUE
, &fHue
, sizeof(fHue
));
869 if (*(uint32
*)value
!= fCaptureSize
){
870 fCaptureSize
= *(uint32
*)value
;
871 fLastCaptureSizeChange
= when
;
872 BroadcastNewParameterValue(
873 fLastCaptureSizeChange
, P_CAPTURE_SIZE
, &fCaptureSize
, sizeof(fCaptureSize
));
876 case P_CAPTURE_FORMAT
:
877 if (*(uint32
*)value
!= fCaptureFormat
){
878 fCaptureFormat
= *(uint32
*)value
;
879 fLastCaptureFormatChange
= when
;
880 BroadcastNewParameterValue(
881 fLastCaptureFormatChange
, P_CAPTURE_FORMAT
, &fCaptureFormat
, sizeof(fCaptureFormat
));
885 if (*(uint32
*)value
!= fStandard
){
886 fStandard
= *(uint32
*)value
;
887 fLastStandardChange
= when
;
888 BroadcastNewParameterValue(
889 fLastStandardChange
, P_STANDART
, &fStandard
, sizeof(fStandard
));
893 if (*(float *)value
!= fBandwidth
){
894 fBandwidth
= *(float *)value
;
895 fLastBandwidthChange
= when
;
896 BroadcastNewParameterValue(
897 fLastBandwidthChange
, P_BANDWIDTH
, &fBandwidth
, sizeof(fBandwidth
));
901 if (*(uint32
*)value
!= fLocale
){
902 fLocale
= *(uint32
*)value
;
903 fLastLocaleChange
= when
;
904 BroadcastNewParameterValue(
905 fLastLocaleChange
, P_LOCALE
, &fLocale
, sizeof(fLocale
));
909 if (*(float*)value
!= fVertOffset
){
910 fVertOffset
= *(float *)value
;
911 fLastVertOffsetChange
= when
;
912 BroadcastNewParameterValue(
913 fLastVertOffsetChange
, P_VERT_OFFSET
, &fVertOffset
, sizeof(fVertOffset
));
917 if (*(float*)value
!= fHorzOffset
){
918 fHorzOffset
= *(float *)value
;
919 fLastHorzOffsetChange
= when
;
920 BroadcastNewParameterValue(
921 fLastHorzOffsetChange
, P_HORZ_OFFSET
, &fHorzOffset
, sizeof(fHorzOffset
));
925 if (*(int32
*)value
!= fColor
){
926 fColor
= *(uint32
*)value
;
927 fLastColorChange
= when
;
928 BroadcastNewParameterValue(
929 fLastColorChange
, P_COLOR
, &fColor
, sizeof(fColor
));
934 EventQueue()->AddEvent(media_timed_event(when
,
935 BTimedEventQueue::B_PARAMETER
, NULL
,
936 BTimedEventQueue::B_NO_CLEANUP
, id
, 0, NULL
, 0));
941 VideoProducer::StartControlPanel(BMessenger
*out_messenger
)
943 return BControllable::StartControlPanel(out_messenger
);
949 VideoProducer::HandleStart(bigtime_t performance_time
)
951 /* Start producing frames, even if the output hasn't been connected yet. */
953 PRINTF(1, ("HandleStart(%Ld)\n", performance_time
));
956 PRINTF(-1, ("HandleStart: Node already started\n"));
962 fPerformanceTimeBase
= performance_time
;
964 fFrameSync
= create_sem(0, "frame synchronization");
965 if (fFrameSync
< B_OK
)
968 fThread
= spawn_thread(_frame_generator_
, "frame generator",
969 B_NORMAL_PRIORITY
, this);
973 resume_thread(fThread
);
979 delete_sem(fFrameSync
);
985 VideoProducer::HandleStop(void)
987 PRINTF(1, ("HandleStop()\n"));
990 PRINTF(-1, ("HandleStop: Node isn't running\n"));
994 delete_sem(fFrameSync
);
995 wait_for_thread(fThread
, &fThread
);
1001 VideoProducer::HandleTimeWarp(bigtime_t performance_time
)
1003 fPerformanceTimeBase
= performance_time
;
1004 fFrameBase
= fFrame
;
1006 /* Tell frame generation thread to recalculate delay value */
1007 release_sem(fFrameSync
);
1011 VideoProducer::HandleSeek(bigtime_t performance_time
)
1013 fPerformanceTimeBase
= performance_time
;
1014 fFrameBase
= fFrame
;
1016 /* Tell frame generation thread to recalculate delay value */
1017 release_sem(fFrameSync
);
1021 VideoProducer::HandleParameter(uint32 parameter
)
1038 case P_CAPTURE_SIZE
:
1040 case P_CAPTURE_FORMAT
:
1049 BParameterWeb
*web
= Web();
1050 int nCount
= web
->CountParameters();
1051 for(int idx
= 0; idx
< nCount
; idx
++){
1052 BParameter
*parameter
= web
->ParameterAt(idx
);
1053 if(parameter
&& parameter
->Type() == BParameter::B_DISCRETE_PARAMETER
&&
1054 parameter
->ID() == P_CHANNEL
){
1055 BDiscreteParameter
* d_parameter
= dynamic_cast<BDiscreteParameter
*>(parameter
);
1056 d_parameter
->MakeEmpty();
1057 for(int i
= 0; i
< fLocales
[fLocale
]->ChannelsCount(); i
++){
1058 d_parameter
->AddItem(i
, (fLocales
[fLocale
]->GetChannel(i
)).Name().c_str());
1060 /*status_t st = BroadcastChangedParameter(P_CHANNEL);
1075 /* The following functions form the thread that generates frames. You should
1076 * replace this with the code that interfaces to your hardware. */
1078 VideoProducer::FrameGenerator()
1080 bigtime_t wait_until
= system_time();
1083 status_t err
= acquire_sem_etc(fFrameSync
, 1, B_ABSOLUTE_TIMEOUT
,
1086 /* The only acceptable responses are B_OK and B_TIMED_OUT. Everything
1087 * else means the thread should quit. Deleting the semaphore, as in
1088 * VideoProducer::HandleStop(), will trigger this behavior. */
1089 if ((err
!= B_OK
) && (err
!= B_TIMED_OUT
))
1094 /* Recalculate the time until the thread should wake up to begin
1095 * processing the next frame. Subtract fProcessingLatency so that
1096 * the frame is sent in time. */
1097 wait_until
= TimeSource()->RealTimeFor(fPerformanceTimeBase
+
1099 ((fFrame
- fFrameBase
) *
1100 (1000000 / fConnectedFormat
.field_rate
)), 0) -
1103 /* Drop frame if it's at least a frame late */
1104 if (wait_until
< system_time())
1107 /* If the semaphore was acquired successfully, it means something
1108 * changed the timing information (see VideoProducer::Connect()) and
1109 * so the thread should go back to sleep until the newly-calculated
1110 * wait_until time. */
1114 /* Send buffers only if the node is running and the output has been
1116 if (!fRunning
|| !fEnabled
)
1121 /* Fetch a buffer from the buffer group */
1122 BBuffer
*buffer
= fBufferGroup
->RequestBuffer(
1123 4 * fConnectedFormat
.display
.line_width
*
1124 fConnectedFormat
.display
.line_count
, 0LL);
1128 /* Fill out the details about this buffer. */
1129 media_header
*h
= buffer
->Header();
1130 h
->type
= B_MEDIA_RAW_VIDEO
;
1131 h
->time_source
= TimeSource()->ID();
1132 h
->size_used
= 4 * fConnectedFormat
.display
.line_width
*
1133 fConnectedFormat
.display
.line_count
;
1134 /* For a buffer originating from a device, you might want to calculate
1135 * this based on the PerformanceTimeFor the time your buffer arrived at
1136 * the hardware (plus any applicable adjustments). */
1137 h
->start_time
= fPerformanceTimeBase
+
1139 ((fFrame
- fFrameBase
) *
1140 (1000000 / fConnectedFormat
.field_rate
));
1144 h
->u
.raw_video
.field_gamma
= 1.0;
1145 h
->u
.raw_video
.field_sequence
= fFrame
;
1146 h
->u
.raw_video
.field_number
= 0;
1147 h
->u
.raw_video
.pulldown_number
= 0;
1148 h
->u
.raw_video
.first_active_line
= 1;
1149 h
->u
.raw_video
.line_count
= fConnectedFormat
.display
.line_count
;
1151 /* Fill in a pattern */
1152 uint32
*p
= (uint32
*)buffer
->Data();
1153 for (int y
=0;y
<fConnectedFormat
.display
.line_count
;y
++)
1154 for (int x
=0;x
<fConnectedFormat
.display
.line_width
;x
++)
1155 *(p
++) = ((((x
+y
)^0^x
)+fFrame
) & 0xff) * (0x01010101 & fColor
);
1157 /* Send the buffer on down to the consumer */
1158 if (SendBuffer(buffer
, fOutput
.destination
) < B_OK
) {
1159 PRINTF(-1, ("FrameGenerator: Error sending buffer\n"));
1160 /* If there is a problem sending the buffer, return it to its
1170 VideoProducer::_frame_generator_(void *data
)
1172 return ((VideoProducer
*)data
)->FrameGenerator();