1 #include <fcntl.h> 2 #include <malloc.h> 3 #include <math.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <sys/uio.h> 7 #include <unistd.h> 8 9 #include <media/Buffer.h> 10 #include <media/BufferGroup.h> 11 #include <media/ParameterWeb.h> 12 #include <media/TimeSource.h> 13 14 #include <support/Autolock.h> 15 #include <support/Debug.h> 16 17 //XXX: change interface 18 #include <interface/Bitmap.h> 19 20 #include "CamDevice.h" 21 #include "CamSensor.h" 22 23 #define TOUCH(x) ((void)(x)) 24 25 #define PRINTF(a,b) \ 26 do { \ 27 if (a < 2) { \ 28 printf("VideoProducer::"); \ 29 printf b; \ 30 } \ 31 } while (0) 32 33 #include "Producer.h" 34 35 #define FIELD_RATE 30.f 36 37 int32 VideoProducer::fInstances = 0; 38 39 VideoProducer::VideoProducer( 40 BMediaAddOn *addon, CamDevice *dev, const char *name, int32 internal_id) 41 : BMediaNode(name), 42 BMediaEventLooper(), 43 BBufferProducer(B_MEDIA_RAW_VIDEO), 44 BControllable() 45 { 46 // status_t err; 47 48 fInitStatus = B_NO_INIT; 49 50 /* Only allow one instance of the node to exist at any time */ 51 if (atomic_add(&fInstances, 1) != 0) 52 return; 53 54 fInternalID = internal_id; 55 fAddOn = addon; 56 fCamDevice = dev; 57 58 fBufferGroup = NULL; 59 60 fThread = -1; 61 fFrameSync = -1; 62 fProcessingLatency = 0LL; 63 64 fRunning = false; 65 fConnected = false; 66 fEnabled = false; 67 68 fOutput.destination = media_destination::null; 69 70 AddNodeKind(B_PHYSICAL_INPUT); 71 72 fInitStatus = B_OK; 73 return; 74 } 75 76 VideoProducer::~VideoProducer() 77 { 78 if (fInitStatus == B_OK) { 79 /* Clean up after ourselves, in case the application didn't make us 80 * do so. */ 81 if (fConnected) 82 Disconnect(fOutput.source, fOutput.destination); 83 if (fRunning) 84 HandleStop(); 85 } 86 87 atomic_add(&fInstances, -1); 88 } 89 90 /* BMediaNode */ 91 92 port_id 93 VideoProducer::ControlPort() const 94 { 95 return BMediaNode::ControlPort(); 96 } 97 98 BMediaAddOn * 99 VideoProducer::AddOn(int32 *internal_id) const 100 { 101 if (internal_id) 102 *internal_id = fInternalID; 103 return fAddOn; 104 } 105 106 status_t 107 VideoProducer::HandleMessage(int32 /*message*/, const void* /*data*/, size_t /*size*/) 108 { 109 return B_ERROR; 110 } 111 112 void 113 VideoProducer::Preroll() 114 { 115 /* This hook may be called before the node is started to give the hardware 116 * a chance to start. */ 117 } 118 119 void 120 VideoProducer::SetTimeSource(BTimeSource* /*time_source*/) 121 { 122 /* Tell frame generation thread to recalculate delay value */ 123 release_sem(fFrameSync); 124 } 125 126 status_t 127 VideoProducer::RequestCompleted(const media_request_info &info) 128 { 129 return BMediaNode::RequestCompleted(info); 130 } 131 132 /* BMediaEventLooper */ 133 134 void 135 VideoProducer::NodeRegistered() 136 { 137 if (fInitStatus != B_OK) { 138 ReportError(B_NODE_IN_DISTRESS); 139 return; 140 } 141 142 int32 id = P_COLOR; 143 /* Set up the parameter web */ 144 145 //TODO: remove and put sensible stuff there 146 BParameterWeb *web = new BParameterWeb(); 147 BParameterGroup *main = web->MakeGroup(Name()); 148 BDiscreteParameter *state = main->MakeDiscreteParameter( 149 P_COLOR, B_MEDIA_RAW_VIDEO, "Color", "Color"); 150 151 id++; 152 if (fCamDevice) { 153 BParameterGroup *dev = web->MakeGroup("Device"); 154 fCamDevice->AddParameters(dev, id); 155 if (fCamDevice->Sensor()) { 156 BParameterGroup *sensor = web->MakeGroup("Sensor"); 157 fCamDevice->Sensor()->AddParameters(sensor, id); 158 } 159 } 160 state->AddItem(B_HOST_TO_LENDIAN_INT32(0x00ff0000), "Red"); 161 state->AddItem(B_HOST_TO_LENDIAN_INT32(0x0000ff00), "Green"); 162 state->AddItem(B_HOST_TO_LENDIAN_INT32(0x000000ff), "Blue"); 163 164 fColor = B_HOST_TO_LENDIAN_INT32(0x00ff0000); 165 fLastColorChange = system_time(); 166 167 /* After this call, the BControllable owns the BParameterWeb object and 168 * will delete it for you */ 169 SetParameterWeb(web); 170 171 fOutput.node = Node(); 172 fOutput.source.port = ControlPort(); 173 fOutput.source.id = 0; 174 fOutput.destination = media_destination::null; 175 strcpy(fOutput.name, Name()); 176 177 /* Tailor these for the output of your device */ 178 fOutput.format.type = B_MEDIA_RAW_VIDEO; 179 fOutput.format.u.raw_video = media_raw_video_format::wildcard; 180 fOutput.format.u.raw_video.interlace = 1; 181 fOutput.format.u.raw_video.display.format = B_RGB32; 182 fOutput.format.u.raw_video.field_rate = 29.97f; // XXX: mmu 183 184 /* Start the BMediaEventLooper control loop running */ 185 Run(); 186 } 187 188 void 189 VideoProducer::Start(bigtime_t performance_time) 190 { 191 BMediaEventLooper::Start(performance_time); 192 } 193 194 void 195 VideoProducer::Stop(bigtime_t performance_time, bool immediate) 196 { 197 BMediaEventLooper::Stop(performance_time, immediate); 198 } 199 200 void 201 VideoProducer::Seek(bigtime_t media_time, bigtime_t performance_time) 202 { 203 BMediaEventLooper::Seek(media_time, performance_time); 204 } 205 206 void 207 VideoProducer::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time) 208 { 209 BMediaEventLooper::TimeWarp(at_real_time, to_performance_time); 210 } 211 212 status_t 213 VideoProducer::AddTimer(bigtime_t at_performance_time, int32 cookie) 214 { 215 return BMediaEventLooper::AddTimer(at_performance_time, cookie); 216 } 217 218 void 219 VideoProducer::SetRunMode(run_mode mode) 220 { 221 BMediaEventLooper::SetRunMode(mode); 222 } 223 224 void 225 VideoProducer::HandleEvent(const media_timed_event *event, 226 bigtime_t lateness, bool realTimeEvent) 227 { 228 TOUCH(lateness); TOUCH(realTimeEvent); 229 230 switch(event->type) 231 { 232 case BTimedEventQueue::B_START: 233 HandleStart(event->event_time); 234 break; 235 case BTimedEventQueue::B_STOP: 236 HandleStop(); 237 break; 238 case BTimedEventQueue::B_WARP: 239 HandleTimeWarp(event->bigdata); 240 break; 241 case BTimedEventQueue::B_SEEK: 242 HandleSeek(event->bigdata); 243 break; 244 case BTimedEventQueue::B_HANDLE_BUFFER: 245 case BTimedEventQueue::B_DATA_STATUS: 246 case BTimedEventQueue::B_PARAMETER: 247 default: 248 PRINTF(-1, ("HandleEvent: Unhandled event -- %lx\n", event->type)); 249 break; 250 } 251 } 252 253 void 254 VideoProducer::CleanUpEvent(const media_timed_event *event) 255 { 256 BMediaEventLooper::CleanUpEvent(event); 257 } 258 259 bigtime_t 260 VideoProducer::OfflineTime() 261 { 262 return BMediaEventLooper::OfflineTime(); 263 } 264 265 void 266 VideoProducer::ControlLoop() 267 { 268 BMediaEventLooper::ControlLoop(); 269 } 270 271 status_t 272 VideoProducer::DeleteHook(BMediaNode * node) 273 { 274 return BMediaEventLooper::DeleteHook(node); 275 } 276 277 /* BBufferProducer */ 278 279 status_t 280 VideoProducer::FormatSuggestionRequested( 281 media_type type, int32 quality, media_format *format) 282 { 283 if (type != B_MEDIA_ENCODED_VIDEO) 284 return B_MEDIA_BAD_FORMAT; 285 286 TOUCH(quality); 287 288 *format = fOutput.format; 289 format->u.raw_video.field_rate = 29.97f; 290 return B_OK; 291 } 292 293 status_t 294 VideoProducer::FormatProposal(const media_source &output, media_format *format) 295 { 296 status_t err; 297 298 if (!format) 299 return B_BAD_VALUE; 300 301 if (output != fOutput.source) 302 return B_MEDIA_BAD_SOURCE; 303 304 err = format_is_compatible(*format, fOutput.format) ? 305 B_OK : B_MEDIA_BAD_FORMAT; 306 *format = fOutput.format; 307 return err; 308 309 } 310 311 status_t 312 VideoProducer::FormatChangeRequested(const media_source &source, 313 const media_destination &destination, media_format *io_format, 314 int32 *_deprecated_) 315 { 316 TOUCH(destination); TOUCH(io_format); TOUCH(_deprecated_); 317 if (source != fOutput.source) 318 return B_MEDIA_BAD_SOURCE; 319 320 return B_ERROR; 321 } 322 323 status_t 324 VideoProducer::GetNextOutput(int32 *cookie, media_output *out_output) 325 { 326 if (!out_output) 327 return B_BAD_VALUE; 328 329 if ((*cookie) != 0) 330 return B_BAD_INDEX; 331 332 *out_output = fOutput; 333 (*cookie)++; 334 return B_OK; 335 } 336 337 status_t 338 VideoProducer::DisposeOutputCookie(int32 cookie) 339 { 340 TOUCH(cookie); 341 342 return B_OK; 343 } 344 345 status_t 346 VideoProducer::SetBufferGroup(const media_source &for_source, 347 BBufferGroup *group) 348 { 349 TOUCH(for_source); TOUCH(group); 350 351 return B_ERROR; 352 } 353 354 status_t 355 VideoProducer::VideoClippingChanged(const media_source &for_source, 356 int16 num_shorts, int16 *clip_data, 357 const media_video_display_info &display, int32 *_deprecated_) 358 { 359 TOUCH(for_source); TOUCH(num_shorts); TOUCH(clip_data); 360 TOUCH(display); TOUCH(_deprecated_); 361 362 return B_ERROR; 363 } 364 365 status_t 366 VideoProducer::GetLatency(bigtime_t *out_latency) 367 { 368 *out_latency = EventLatency() + SchedulingLatency(); 369 return B_OK; 370 } 371 372 status_t 373 VideoProducer::PrepareToConnect(const media_source &source, 374 const media_destination &destination, media_format *format, 375 media_source *out_source, char *out_name) 376 { 377 // status_t err; 378 379 PRINTF(1, ("PrepareToConnect() %ldx%ld\n", \ 380 format->u.raw_video.display.line_width, \ 381 format->u.raw_video.display.line_count)); 382 383 if (fConnected) { 384 PRINTF(0, ("PrepareToConnect: Already connected\n")); 385 return EALREADY; 386 } 387 388 if (source != fOutput.source) 389 return B_MEDIA_BAD_SOURCE; 390 391 if (fOutput.destination != media_destination::null) 392 return B_MEDIA_ALREADY_CONNECTED; 393 394 /* The format parameter comes in with the suggested format, and may be 395 * specialized as desired by the node */ 396 if (!format_is_compatible(*format, fOutput.format)) { 397 *format = fOutput.format; 398 return B_MEDIA_BAD_FORMAT; 399 } 400 401 //XXX:FIXME 402 #if 1 403 // if (format->u.raw_video.display.line_width == 0) 404 format->u.raw_video.display.line_width = 352;//320; 405 format->u.raw_video.display.line_width = 320; 406 // if (format->u.raw_video.display.line_count == 0) 407 format->u.raw_video.display.line_count = 288;//240; 408 format->u.raw_video.display.line_count = 240; 409 #endif 410 411 if (fCamDevice) { 412 format->u.raw_video.display.line_width = fCamDevice->VideoFrame().IntegerWidth() + 1; 413 format->u.raw_video.display.line_count = fCamDevice->VideoFrame().IntegerHeight() + 1; 414 } 415 416 if (format->u.raw_video.field_rate == 0) 417 format->u.raw_video.field_rate = 29.97f; 418 419 *out_source = fOutput.source; 420 strcpy(out_name, fOutput.name); 421 422 fOutput.destination = destination; 423 424 return B_OK; 425 } 426 427 void 428 VideoProducer::Connect(status_t error, const media_source &source, 429 const media_destination &destination, const media_format &format, 430 char *io_name) 431 { 432 PRINTF(1, ("Connect() %ldx%ld\n", \ 433 format.u.raw_video.display.line_width, \ 434 format.u.raw_video.display.line_count)); 435 436 if (fConnected) { 437 PRINTF(0, ("Connect: Already connected\n")); 438 return; 439 } 440 441 BAutolock lock(fCamDevice->Locker()); 442 if (!fCamDevice->IsPlugged()) { 443 PRINTF(0, ("Connect: Device unplugged\n")); 444 return; 445 } 446 447 if ( (source != fOutput.source) || (error < B_OK) || 448 !const_cast<media_format *>(&format)->Matches(&fOutput.format)) { 449 PRINTF(1, ("Connect: Connect error\n")); 450 return; 451 } 452 453 fOutput.destination = destination; 454 strcpy(io_name, fOutput.name); 455 456 if (fOutput.format.u.raw_video.field_rate != 0.0f) { 457 fPerformanceTimeBase = fPerformanceTimeBase + 458 (bigtime_t) 459 ((fFrame - fFrameBase) * 460 (1000000 / fOutput.format.u.raw_video.field_rate)); 461 fFrameBase = fFrame; 462 } 463 464 fConnectedFormat = format.u.raw_video; 465 466 /* get the latency */ 467 bigtime_t latency = 0; 468 media_node_id tsID = 0; 469 FindLatencyFor(fOutput.destination, &latency, &tsID); 470 #define NODE_LATENCY 1000 471 SetEventLatency(latency + NODE_LATENCY); 472 473 uint32 *buffer, *p, f = 3; 474 p = buffer = (uint32 *)malloc(4 * fConnectedFormat.display.line_count * 475 fConnectedFormat.display.line_width); 476 if (!buffer) { 477 PRINTF(0, ("Connect: Out of memory\n")); 478 return; 479 } 480 bigtime_t now = system_time(); 481 for (uint32 y=0;y<fConnectedFormat.display.line_count;y++) 482 for (uint32 x=0;x<fConnectedFormat.display.line_width;x++) 483 *(p++) = ((((x+y)^0^x)+f) & 0xff) * (0x01010101 & fColor); 484 fProcessingLatency = system_time() - now; 485 free(buffer); 486 487 /* Create the buffer group */ 488 fBufferGroup = new BBufferGroup(4 * fConnectedFormat.display.line_width * 489 fConnectedFormat.display.line_count, 8); 490 if (fBufferGroup->InitCheck() < B_OK) { 491 delete fBufferGroup; 492 fBufferGroup = NULL; 493 return; 494 } 495 496 fConnected = true; 497 fEnabled = true; 498 499 /* Tell frame generation thread to recalculate delay value */ 500 release_sem(fFrameSync); 501 } 502 503 void 504 VideoProducer::Disconnect(const media_source &source, 505 const media_destination &destination) 506 { 507 PRINTF(1, ("Disconnect()\n")); 508 509 if (!fConnected) { 510 PRINTF(0, ("Disconnect: Not connected\n")); 511 return; 512 } 513 514 if ((source != fOutput.source) || (destination != fOutput.destination)) { 515 PRINTF(0, ("Disconnect: Bad source and/or destination\n")); 516 return; 517 } 518 519 #if 1 520 /* Some dumb apps don't stop nodes before disconnecting... */ 521 if (fRunning) 522 HandleStop(); 523 #endif 524 525 fEnabled = false; 526 fOutput.destination = media_destination::null; 527 528 fLock.Lock(); 529 delete fBufferGroup; 530 fBufferGroup = NULL; 531 fLock.Unlock(); 532 533 fConnected = false; 534 } 535 536 void 537 VideoProducer::LateNoticeReceived(const media_source &source, 538 bigtime_t how_much, bigtime_t performance_time) 539 { 540 TOUCH(source); TOUCH(how_much); TOUCH(performance_time); 541 } 542 543 void 544 VideoProducer::EnableOutput(const media_source &source, bool enabled, 545 int32 *_deprecated_) 546 { 547 TOUCH(_deprecated_); 548 549 if (source != fOutput.source) 550 return; 551 552 fEnabled = enabled; 553 } 554 555 status_t 556 VideoProducer::SetPlayRate(int32 numer, int32 denom) 557 { 558 TOUCH(numer); TOUCH(denom); 559 560 return B_ERROR; 561 } 562 563 void 564 VideoProducer::AdditionalBufferRequested(const media_source &source, 565 media_buffer_id prev_buffer, bigtime_t prev_time, 566 const media_seek_tag *prev_tag) 567 { 568 TOUCH(source); TOUCH(prev_buffer); TOUCH(prev_time); TOUCH(prev_tag); 569 } 570 571 void 572 VideoProducer::LatencyChanged(const media_source &source, 573 const media_destination &destination, bigtime_t new_latency, 574 uint32 flags) 575 { 576 TOUCH(source); TOUCH(destination); TOUCH(new_latency); TOUCH(flags); 577 } 578 579 /* BControllable */ 580 581 status_t 582 VideoProducer::GetParameterValue( 583 int32 id, bigtime_t *last_change, void *value, size_t *size) 584 { 585 status_t err; 586 587 if (id == P_COLOR) { 588 //return B_BAD_VALUE; 589 590 *last_change = fLastColorChange; 591 *size = sizeof(uint32); 592 *((uint32 *)value) = fColor; 593 return B_OK; 594 } 595 596 if (fCamDevice) { 597 BAutolock lock(fCamDevice->Locker()); 598 err = fCamDevice->GetParameterValue(id, last_change, value, size); 599 if (err >= B_OK) 600 return err; 601 if (fCamDevice->Sensor()) { 602 err = fCamDevice->Sensor()->GetParameterValue(id, last_change, value, size); 603 if (err >= B_OK) 604 return err; 605 } 606 } 607 608 return B_BAD_VALUE; 609 } 610 611 void 612 VideoProducer::SetParameterValue( 613 int32 id, bigtime_t when, const void *value, size_t size) 614 { 615 status_t err = B_OK; 616 617 if (id == P_COLOR) { 618 if (!value || (size != sizeof(uint32))) 619 return; 620 621 if (*(uint32 *)value == fColor) 622 return; 623 624 fColor = *(uint32 *)value; 625 fLastColorChange = when; 626 627 } else if (fCamDevice) { 628 BAutolock lock(fCamDevice->Locker()); 629 err = fCamDevice->SetParameterValue(id, when, value, size); 630 if ((err < B_OK) && (fCamDevice->Sensor())) { 631 err = fCamDevice->Sensor()->SetParameterValue(id, when, value, size); 632 } 633 } 634 635 if (err >= B_OK) 636 BroadcastNewParameterValue(when, id, (void *)value, size); 637 } 638 639 status_t 640 VideoProducer::StartControlPanel(BMessenger *out_messenger) 641 { 642 return BControllable::StartControlPanel(out_messenger); 643 } 644 645 /* VideoProducer */ 646 647 void 648 VideoProducer::HandleStart(bigtime_t performance_time) 649 { 650 /* Start producing frames, even if the output hasn't been connected yet. */ 651 652 PRINTF(1, ("HandleStart(%Ld)\n", performance_time)); 653 654 if (fRunning) { 655 PRINTF(-1, ("HandleStart: Node already started\n")); 656 return; 657 } 658 659 fFrame = 0; 660 fFrameBase = 0; 661 fPerformanceTimeBase = performance_time; 662 663 fFrameSync = create_sem(0, "frame synchronization"); 664 if (fFrameSync < B_OK) 665 goto err1; 666 667 fThread = spawn_thread(_frame_generator_, "frame generator", 668 B_NORMAL_PRIORITY, this); 669 if (fThread < B_OK) 670 goto err2; 671 672 resume_thread(fThread); 673 674 { 675 BAutolock lock(fCamDevice->Locker()); 676 fCamDevice->StartTransfer(); 677 } 678 679 fRunning = true; 680 return; 681 682 err2: 683 delete_sem(fFrameSync); 684 err1: 685 return; 686 } 687 688 void 689 VideoProducer::HandleStop(void) 690 { 691 PRINTF(1, ("HandleStop()\n")); 692 693 if (!fRunning) { 694 PRINTF(-1, ("HandleStop: Node isn't running\n")); 695 return; 696 } 697 698 delete_sem(fFrameSync); 699 wait_for_thread(fThread, &fThread); 700 701 BAutolock lock(fCamDevice->Locker()); 702 fCamDevice->StopTransfer(); 703 704 fRunning = false; 705 } 706 707 void 708 VideoProducer::HandleTimeWarp(bigtime_t performance_time) 709 { 710 fPerformanceTimeBase = performance_time; 711 fFrameBase = fFrame; 712 713 /* Tell frame generation thread to recalculate delay value */ 714 release_sem(fFrameSync); 715 } 716 717 void 718 VideoProducer::HandleSeek(bigtime_t performance_time) 719 { 720 fPerformanceTimeBase = performance_time; 721 fFrameBase = fFrame; 722 723 /* Tell frame generation thread to recalculate delay value */ 724 release_sem(fFrameSync); 725 } 726 727 /* The following functions form the thread that generates frames. You should 728 * replace this with the code that interfaces to your hardware. */ 729 int32 730 VideoProducer::FrameGenerator() 731 { 732 bigtime_t wait_until = system_time(); 733 734 while (1) { 735 PRINTF(1, ("FrameGenerator: acquire_sem_etc() until %Ldµs (in %Ldµs)\n", wait_until, wait_until - system_time())); 736 status_t err = acquire_sem_etc(fFrameSync, 1, B_ABSOLUTE_TIMEOUT, 737 wait_until); 738 739 /* The only acceptable responses are B_OK and B_TIMED_OUT. Everything 740 * else means the thread should quit. Deleting the semaphore, as in 741 * VideoProducer::HandleStop(), will trigger this behavior. */ 742 if ((err != B_OK) && (err != B_TIMED_OUT)) 743 break; 744 745 fFrame++; 746 747 /* Recalculate the time until the thread should wake up to begin 748 * processing the next frame. Subtract fProcessingLatency so that 749 * the frame is sent in time. */ 750 wait_until = TimeSource()->RealTimeFor(fPerformanceTimeBase, 0) + 751 (bigtime_t) 752 ((fFrame - fFrameBase) * 753 (1000000 / fConnectedFormat.field_rate)) - 754 fProcessingLatency; 755 756 /* Drop frame if it's at least a frame late */ 757 if (wait_until < system_time()) 758 continue; 759 760 PRINTF(1, ("FrameGenerator: wait until %Ld, %ctimed out, %crunning, %cenabled.\n", 761 wait_until, 762 (err == B_OK)?'!':' ', 763 (fRunning)?' ':'!', 764 (fEnabled)?' ':'!')); 765 766 /* If the semaphore was acquired successfully, it means something 767 * changed the timing information (see VideoProducer::Connect()) and 768 * so the thread should go back to sleep until the newly-calculated 769 * wait_until time. */ 770 if (err == B_OK) 771 continue; 772 773 /* Send buffers only if the node is running and the output has been 774 * enabled */ 775 if (!fRunning || !fEnabled) 776 continue; 777 778 BAutolock _(fLock); 779 780 /* Fetch a buffer from the buffer group */ 781 BBuffer *buffer = fBufferGroup->RequestBuffer( 782 4 * fConnectedFormat.display.line_width * 783 fConnectedFormat.display.line_count, 0LL); 784 if (!buffer) 785 continue; 786 787 /* Fill out the details about this buffer. */ 788 media_header *h = buffer->Header(); 789 h->type = B_MEDIA_RAW_VIDEO; 790 h->time_source = TimeSource()->ID(); 791 h->size_used = 4 * fConnectedFormat.display.line_width * 792 fConnectedFormat.display.line_count; 793 /* For a buffer originating from a device, you might want to calculate 794 * this based on the PerformanceTimeFor the time your buffer arrived at 795 * the hardware (plus any applicable adjustments). */ 796 /* 797 h->start_time = fPerformanceTimeBase + 798 (bigtime_t) 799 ((fFrame - fFrameBase) * 800 (1000000 / fConnectedFormat.field_rate)); 801 */ 802 h->file_pos = 0; 803 h->orig_size = 0; 804 h->data_offset = 0; 805 h->u.raw_video.field_gamma = 1.0; 806 h->u.raw_video.field_sequence = fFrame; 807 h->u.raw_video.field_number = 0; 808 h->u.raw_video.pulldown_number = 0; 809 h->u.raw_video.first_active_line = 1; 810 h->u.raw_video.line_count = fConnectedFormat.display.line_count; 811 812 // This is where we fill the video buffer. 813 814 #if 0 815 uint32 *p = (uint32 *)buffer->Data(); 816 /* Fill in a pattern */ 817 for (uint32 y=0;y<fConnectedFormat.display.line_count;y++) 818 for (uint32 x=0;x<fConnectedFormat.display.line_width;x++) 819 *(p++) = ((((x+y)^0^x)+fFrame) & 0xff) * (0x01010101 & fColor); 820 #endif 821 822 //NO! must be called without lock! 823 //BAutolock lock(fCamDevice->Locker()); 824 825 bigtime_t stamp; 826 //#ifdef UseFillFrameBuffer 827 err = fCamDevice->FillFrameBuffer(buffer, &stamp); 828 if (err < B_OK) { 829 ;//XXX handle error 830 } 831 //#endif 832 #ifdef UseGetFrameBitmap 833 BBitmap *bm; 834 err = fCamDevice->GetFrameBitmap(&bm, &stamp); 835 if (err >= B_OK) { 836 ;//XXX handle error 837 } 838 #endif 839 //PRINTF(1, ("FrameGenerator: stamp %Ld vs %Ld\n", stamp, h->start_time)); 840 //XXX: that's what we should be doing, but CodyCam drops all frames as they are late. (maybe add latency ??) 841 //h->start_time = TimeSource()->PerformanceTimeFor(stamp); 842 h->start_time = TimeSource()->PerformanceTimeFor(system_time()); 843 844 PRINTF(1, ("FrameGenerator: SendBuffer...\n")); 845 /* Send the buffer on down to the consumer */ 846 if (SendBuffer(buffer, fOutput.destination) < B_OK) { 847 PRINTF(-1, ("FrameGenerator: Error sending buffer\n")); 848 /* If there is a problem sending the buffer, return it to its 849 * buffer group. */ 850 buffer->Recycle(); 851 } 852 } 853 854 PRINTF(1, ("FrameGenerator: thread existed.\n")); 855 return B_OK; 856 } 857 858 int32 859 VideoProducer::_frame_generator_(void *data) 860 { 861 return ((VideoProducer *)data)->FrameGenerator(); 862 } 863