OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 cr.define('options', function() { | 5 cr.define('options', function() { |
6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; | 6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; |
7 /** @const */ var Grid = cr.ui.Grid; | 7 /** @const */ var Grid = cr.ui.Grid; |
8 /** @const */ var GridItem = cr.ui.GridItem; | 8 /** @const */ var GridItem = cr.ui.GridItem; |
9 /** @const */ var GridSelectionController = cr.ui.GridSelectionController; | 9 /** @const */ var GridSelectionController = cr.ui.GridSelectionController; |
10 /** @const */ var ListSingleSelectionModel = cr.ui.ListSingleSelectionModel; | 10 /** @const */ var ListSingleSelectionModel = cr.ui.ListSingleSelectionModel; |
11 | 11 |
| 12 /** |
| 13 * Number of frames recorded by takeVideo(). |
| 14 * @const |
| 15 */ |
| 16 var RECORD_FRAMES = 48; |
| 17 |
| 18 /** |
| 19 * FPS at which camera stream is recorded. |
| 20 * @const |
| 21 */ |
| 22 var RECORD_FPS = 16; |
| 23 |
12 /** | 24 /** |
13 * Dimensions for camera capture. | 25 * Dimensions for camera capture. |
14 * @const | 26 * @const |
15 */ | 27 */ |
16 var CAPTURE_SIZE = { | 28 var CAPTURE_SIZE = { |
17 height: 480, | 29 height: 480, |
18 width: 480 | 30 width: 480 |
19 }; | 31 }; |
20 | 32 |
21 /** | 33 /** |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 this.cameraImage = previewImg.src; | 484 this.cameraImage = previewImg.src; |
473 }.bind(this)); | 485 }.bind(this)); |
474 previewImg.src = canvas.toDataURL('image/png'); | 486 previewImg.src = canvas.toDataURL('image/png'); |
475 var e = new Event('phototaken'); | 487 var e = new Event('phototaken'); |
476 e.dataURL = this.flipPhoto ? this.flipFrame_(canvas) : previewImg.src; | 488 e.dataURL = this.flipPhoto ? this.flipFrame_(canvas) : previewImg.src; |
477 this.dispatchEvent(e); | 489 this.dispatchEvent(e); |
478 return true; | 490 return true; |
479 }, | 491 }, |
480 | 492 |
481 /** | 493 /** |
| 494 * Performs video capture from the live camera stream. |
| 495 * @param {function=} opt_callback Callback that receives taken video as |
| 496 * data URL of a vertically stacked PNG sprite. |
| 497 */ |
| 498 takeVideo: function(opt_callback) { |
| 499 var canvas = document.createElement('canvas'); |
| 500 canvas.width = CAPTURE_SIZE.width; |
| 501 canvas.height = CAPTURE_SIZE.height * RECORD_FRAMES; |
| 502 var ctx = canvas.getContext('2d'); |
| 503 // Force canvas initialization to prevent FPS lag on the first frame. |
| 504 ctx.fillRect(0, 0, 1, 1); |
| 505 var captureData = { |
| 506 callback: opt_callback, |
| 507 canvas: canvas, |
| 508 ctx: ctx, |
| 509 frameNo: 0, |
| 510 lastTimestamp: new Date().getTime() |
| 511 }; |
| 512 captureData.timer = window.setInterval( |
| 513 this.captureVideoFrame_.bind(this, captureData), 1000 / RECORD_FPS); |
| 514 }, |
| 515 |
| 516 /** |
482 * Discard current photo and return to the live camera stream. | 517 * Discard current photo and return to the live camera stream. |
483 */ | 518 */ |
484 discardPhoto: function() { | 519 discardPhoto: function() { |
485 this.cameraTitle_ = this.placeholderTitle_; | 520 this.cameraTitle_ = this.placeholderTitle_; |
486 this.cameraImage = null; | 521 this.cameraImage = null; |
487 }, | 522 }, |
488 | 523 |
489 /** | 524 /** |
490 * Capture a single still frame from a <video> element, placing it at the | 525 * Capture a single still frame from a <video> element, placing it at the |
491 * current drawing origin of a canvas context. | 526 * current drawing origin of a canvas context. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 canvas.width = CAPTURE_SIZE.width; | 563 canvas.width = CAPTURE_SIZE.width; |
529 canvas.height = CAPTURE_SIZE.height; | 564 canvas.height = CAPTURE_SIZE.height; |
530 var ctx = canvas.getContext('2d'); | 565 var ctx = canvas.getContext('2d'); |
531 ctx.translate(CAPTURE_SIZE.width, 0); | 566 ctx.translate(CAPTURE_SIZE.width, 0); |
532 ctx.scale(-1.0, 1.0); | 567 ctx.scale(-1.0, 1.0); |
533 ctx.drawImage(source, 0, 0); | 568 ctx.drawImage(source, 0, 0); |
534 return canvas.toDataURL('image/png'); | 569 return canvas.toDataURL('image/png'); |
535 }, | 570 }, |
536 | 571 |
537 /** | 572 /** |
| 573 * Capture next frame of the video being recorded after a takeVideo() call. |
| 574 * @param {Object} data Property bag with the recorder details. |
| 575 * @private |
| 576 */ |
| 577 captureVideoFrame_: function(data) { |
| 578 var lastTimestamp = new Date().getTime(); |
| 579 var delayMs = lastTimestamp - data.lastTimestamp; |
| 580 console.error('Delay: ' + delayMs + ' (' + (1000 / delayMs + ' FPS)')); |
| 581 data.lastTimestamp = lastTimestamp; |
| 582 |
| 583 this.captureFrame_(this.cameraVideo_, data.ctx, CAPTURE_SIZE); |
| 584 data.ctx.translate(0, CAPTURE_SIZE.height); |
| 585 |
| 586 if (++data.frameNo == RECORD_FRAMES) { |
| 587 window.clearTimeout(data.timer); |
| 588 if (data.callback && typeof data.callback == 'function') |
| 589 data.callback(data.canvas.toDataURL('image/png')); |
| 590 } |
| 591 }, |
| 592 |
| 593 /** |
538 * Adds new image to the user image grid. | 594 * Adds new image to the user image grid. |
539 * @param {string} src Image URL. | 595 * @param {string} src Image URL. |
540 * @param {string=} opt_title Image tooltip. | 596 * @param {string=} opt_title Image tooltip. |
541 * @param {function=} opt_clickHandler Image click handler. | 597 * @param {function=} opt_clickHandler Image click handler. |
542 * @param {number=} opt_position If given, inserts new image into | 598 * @param {number=} opt_position If given, inserts new image into |
543 * that position (0-based) in image list. | 599 * that position (0-based) in image list. |
544 * @param {function=} opt_decorateFn Function called with the list element | 600 * @param {function=} opt_decorateFn Function called with the list element |
545 * as argument to do any final decoration. | 601 * as argument to do any final decoration. |
546 * @return {!Object} Image data inserted into the data model. | 602 * @return {!Object} Image data inserted into the data model. |
547 */ | 603 */ |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 UserImagesGrid.ButtonImages = { | 694 UserImagesGrid.ButtonImages = { |
639 TAKE_PHOTO: 'chrome://theme/IDR_BUTTON_USER_IMAGE_TAKE_PHOTO', | 695 TAKE_PHOTO: 'chrome://theme/IDR_BUTTON_USER_IMAGE_TAKE_PHOTO', |
640 CHOOSE_FILE: 'chrome://theme/IDR_BUTTON_USER_IMAGE_CHOOSE_FILE', | 696 CHOOSE_FILE: 'chrome://theme/IDR_BUTTON_USER_IMAGE_CHOOSE_FILE', |
641 PROFILE_PICTURE: 'chrome://theme/IDR_PROFILE_PICTURE_LOADING' | 697 PROFILE_PICTURE: 'chrome://theme/IDR_PROFILE_PICTURE_LOADING' |
642 }; | 698 }; |
643 | 699 |
644 return { | 700 return { |
645 UserImagesGrid: UserImagesGrid | 701 UserImagesGrid: UserImagesGrid |
646 }; | 702 }; |
647 }); | 703 }); |
OLD | NEW |