OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 #include "core/html/HTMLMediaSource.h" | 47 #include "core/html/HTMLMediaSource.h" |
48 #include "core/html/HTMLSourceElement.h" | 48 #include "core/html/HTMLSourceElement.h" |
49 #include "core/html/HTMLTrackElement.h" | 49 #include "core/html/HTMLTrackElement.h" |
50 #include "core/html/MediaController.h" | 50 #include "core/html/MediaController.h" |
51 #include "core/html/MediaError.h" | 51 #include "core/html/MediaError.h" |
52 #include "core/html/MediaFragmentURIParser.h" | 52 #include "core/html/MediaFragmentURIParser.h" |
53 #include "core/html/MediaKeyError.h" | 53 #include "core/html/MediaKeyError.h" |
54 #include "core/html/MediaKeyEvent.h" | 54 #include "core/html/MediaKeyEvent.h" |
55 #include "core/html/TimeRanges.h" | 55 #include "core/html/TimeRanges.h" |
56 #include "core/html/shadow/MediaControls.h" | 56 #include "core/html/shadow/MediaControls.h" |
| 57 #include "core/html/track/AudioTrack.h" |
| 58 #include "core/html/track/AudioTrackList.h" |
57 #include "core/html/track/InbandTextTrack.h" | 59 #include "core/html/track/InbandTextTrack.h" |
58 #include "core/html/track/TextTrackCueList.h" | 60 #include "core/html/track/TextTrackCueList.h" |
59 #include "core/html/track/TextTrackList.h" | 61 #include "core/html/track/TextTrackList.h" |
| 62 #include "core/html/track/VideoTrack.h" |
| 63 #include "core/html/track/VideoTrackList.h" |
60 #include "core/loader/FrameLoader.h" | 64 #include "core/loader/FrameLoader.h" |
61 #include "core/rendering/RenderLayerCompositor.h" | 65 #include "core/rendering/RenderLayerCompositor.h" |
62 #include "core/rendering/RenderVideo.h" | 66 #include "core/rendering/RenderVideo.h" |
63 #include "core/rendering/RenderView.h" | 67 #include "core/rendering/RenderView.h" |
64 // FIXME: Remove dependency on modules/encryptedmedia (http://crbug.com/242754). | 68 // FIXME: Remove dependency on modules/encryptedmedia (http://crbug.com/242754). |
65 #include "modules/encryptedmedia/MediaKeyNeededEvent.h" | 69 #include "modules/encryptedmedia/MediaKeyNeededEvent.h" |
66 #include "modules/encryptedmedia/MediaKeys.h" | 70 #include "modules/encryptedmedia/MediaKeys.h" |
67 #include "platform/ContentType.h" | 71 #include "platform/ContentType.h" |
68 #include "platform/Language.h" | 72 #include "platform/Language.h" |
69 #include "platform/Logging.h" | 73 #include "platform/Logging.h" |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 , m_sentStalledEvent(false) | 299 , m_sentStalledEvent(false) |
296 , m_sentEndEvent(false) | 300 , m_sentEndEvent(false) |
297 , m_pausedInternal(false) | 301 , m_pausedInternal(false) |
298 , m_closedCaptionsVisible(false) | 302 , m_closedCaptionsVisible(false) |
299 , m_completelyLoaded(false) | 303 , m_completelyLoaded(false) |
300 , m_havePreparedToPlay(false) | 304 , m_havePreparedToPlay(false) |
301 , m_tracksAreReady(true) | 305 , m_tracksAreReady(true) |
302 , m_haveVisibleTextTrack(false) | 306 , m_haveVisibleTextTrack(false) |
303 , m_processingPreferenceChange(false) | 307 , m_processingPreferenceChange(false) |
304 , m_lastTextTrackUpdateTime(-1) | 308 , m_lastTextTrackUpdateTime(-1) |
| 309 , m_audioTracks(nullptr) |
| 310 , m_videoTracks(nullptr) |
305 , m_textTracks(nullptr) | 311 , m_textTracks(nullptr) |
306 , m_ignoreTrackDisplayUpdate(0) | 312 , m_ignoreTrackDisplayUpdate(0) |
307 #if ENABLE(WEB_AUDIO) | 313 #if ENABLE(WEB_AUDIO) |
308 , m_audioSourceNode(0) | 314 , m_audioSourceNode(0) |
309 #endif | 315 #endif |
310 , m_emeMode(EmeModeNotSelected) | 316 , m_emeMode(EmeModeNotSelected) |
311 { | 317 { |
312 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); | 318 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); |
313 | 319 |
314 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement"); | 320 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement"); |
(...skipping 13 matching lines...) Expand all Loading... |
328 addElementToDocumentMap(this, &document); | 334 addElementToDocumentMap(this, &document); |
329 } | 335 } |
330 | 336 |
331 HTMLMediaElement::~HTMLMediaElement() | 337 HTMLMediaElement::~HTMLMediaElement() |
332 { | 338 { |
333 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement"); | 339 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement"); |
334 | 340 |
335 m_asyncEventQueue->close(); | 341 m_asyncEventQueue->close(); |
336 | 342 |
337 setShouldDelayLoadEvent(false); | 343 setShouldDelayLoadEvent(false); |
| 344 if (m_audioTracks) |
| 345 m_audioTracks->clearOwner(); |
| 346 if (m_videoTracks) |
| 347 m_videoTracks->clearOwner(); |
338 if (m_textTracks) | 348 if (m_textTracks) |
339 m_textTracks->clearOwner(); | 349 m_textTracks->clearOwnerAndClients(); |
340 if (m_textTracks) { | |
341 for (unsigned i = 0; i < m_textTracks->length(); ++i) | |
342 m_textTracks->item(i)->clearClient(); | |
343 } | |
344 | 350 |
345 if (m_mediaController) { | 351 if (m_mediaController) { |
346 m_mediaController->removeMediaElement(this); | 352 m_mediaController->removeMediaElement(this); |
347 m_mediaController = nullptr; | 353 m_mediaController = nullptr; |
348 } | 354 } |
349 | 355 |
350 closeMediaSource(); | 356 closeMediaSource(); |
351 | 357 |
352 setMediaKeysInternal(0); | 358 setMediaKeysInternal(0); |
353 | 359 |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 // a task to fire a simple event named abort at the media element. | 662 // a task to fire a simple event named abort at the media element. |
657 if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE) | 663 if (m_networkState == NETWORK_LOADING || m_networkState == NETWORK_IDLE) |
658 scheduleEvent(EventTypeNames::abort); | 664 scheduleEvent(EventTypeNames::abort); |
659 | 665 |
660 closeMediaSource(); | 666 closeMediaSource(); |
661 | 667 |
662 createMediaPlayer(); | 668 createMediaPlayer(); |
663 | 669 |
664 // 4 - If the media element's networkState is not set to NETWORK_EMPTY, then
run these substeps | 670 // 4 - If the media element's networkState is not set to NETWORK_EMPTY, then
run these substeps |
665 if (m_networkState != NETWORK_EMPTY) { | 671 if (m_networkState != NETWORK_EMPTY) { |
| 672 // 4.1 - Queue a task to fire a simple event named emptied at the media
element. |
| 673 scheduleEvent(EventTypeNames::emptied); |
| 674 |
| 675 // 4.2 - If a fetching process is in progress for the media element, the
user agent should stop it. |
666 m_networkState = NETWORK_EMPTY; | 676 m_networkState = NETWORK_EMPTY; |
| 677 |
| 678 // 4.3 - Forget the media element's media-resource-specific tracks. |
| 679 forgetResourceSpecificTracks(); |
| 680 |
| 681 // 4.4 - If readyState is not set to HAVE_NOTHING, then set it to that s
tate. |
667 m_readyState = HAVE_NOTHING; | 682 m_readyState = HAVE_NOTHING; |
668 m_readyStateMaximum = HAVE_NOTHING; | 683 m_readyStateMaximum = HAVE_NOTHING; |
| 684 |
| 685 // 4.5 - If the paused attribute is false, then set it to true. |
| 686 m_paused = true; |
| 687 |
| 688 // 4.6 - If seeking is true, set it to false. |
| 689 m_seeking = false; |
| 690 |
| 691 // 4.7 - Set the current playback position to 0. |
| 692 // Set the official playback position to 0. |
| 693 // If this changed the official playback position, then queue a ta
sk to fire a simple event named timeupdate at the media element. |
| 694 |
| 695 // 4.8 - Set the initial playback position to 0. |
| 696 // FIXME: Make this less subtle. The position only becomes 0 because of
the createMediaPlayer() call |
| 697 // above. |
669 refreshCachedTime(); | 698 refreshCachedTime(); |
670 m_paused = true; | |
671 m_seeking = false; | |
672 invalidateCachedTime(); | 699 invalidateCachedTime(); |
673 scheduleEvent(EventTypeNames::emptied); | 700 |
| 701 // 4.9 - Set the timeline offset to Not-a-Number (NaN). |
| 702 // 4.10 - Update the duration attribute to Not-a-Number (NaN). |
| 703 |
674 updateMediaController(); | 704 updateMediaController(); |
675 if (RuntimeEnabledFeatures::videoTrackEnabled()) | 705 if (RuntimeEnabledFeatures::videoTrackEnabled()) |
676 updateActiveTextTrackCues(0); | 706 updateActiveTextTrackCues(0); |
677 } | 707 } |
678 | 708 |
679 // 5 - Set the playbackRate attribute to the value of the defaultPlaybackRat
e attribute. | 709 // 5 - Set the playbackRate attribute to the value of the defaultPlaybackRat
e attribute. |
680 setPlaybackRate(defaultPlaybackRate()); | 710 setPlaybackRate(defaultPlaybackRate()); |
681 | 711 |
682 // 6 - Set the error attribute to null and the autoplaying flag to true. | 712 // 6 - Set the error attribute to null and the autoplaying flag to true. |
683 m_error = nullptr; | 713 m_error = nullptr; |
684 m_autoplaying = true; | 714 m_autoplaying = true; |
685 | 715 |
686 // 7 - Invoke the media element's resource selection algorithm. | 716 // 7 - Invoke the media element's resource selection algorithm. |
687 | 717 |
688 // 8 - Note: Playback of any previously playing media resource for this elem
ent stops. | 718 // 8 - Note: Playback of any previously playing media resource for this elem
ent stops. |
689 | 719 |
690 // The resource selection algorithm | 720 // The resource selection algorithm |
691 // 1 - Set the networkState to NETWORK_NO_SOURCE | 721 // 1 - Set the networkState to NETWORK_NO_SOURCE |
692 m_networkState = NETWORK_NO_SOURCE; | 722 m_networkState = NETWORK_NO_SOURCE; |
693 | 723 |
694 // 2 - Asynchronously await a stable state. | 724 // 2 - Asynchronously await a stable state. |
695 | 725 |
696 m_playedTimeRanges = TimeRanges::create(); | 726 m_playedTimeRanges = TimeRanges::create(); |
| 727 |
| 728 // FIXME: Investigate whether these can be moved into m_networkState != NETW
ORK_EMPTY block above |
| 729 // so they are closer to the relevant spec steps. |
697 m_lastSeekTime = 0; | 730 m_lastSeekTime = 0; |
698 m_duration = numeric_limits<double>::quiet_NaN(); | 731 m_duration = numeric_limits<double>::quiet_NaN(); |
699 | 732 |
700 // The spec doesn't say to block the load event until we actually run the as
ynchronous section | 733 // The spec doesn't say to block the load event until we actually run the as
ynchronous section |
701 // algorithm, but do it now because we won't start that until after the time
r fires and the | 734 // algorithm, but do it now because we won't start that until after the time
r fires and the |
702 // event may have already fired by then. | 735 // event may have already fired by then. |
703 setShouldDelayLoadEvent(true); | 736 setShouldDelayLoadEvent(true); |
704 | 737 |
705 configureMediaControls(); | 738 configureMediaControls(); |
706 } | 739 } |
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1357 | 1390 |
1358 // 4.8.10.5 | 1391 // 4.8.10.5 |
1359 // 6 - Reaching this step indicates that the media resource failed to load o
r that the given | 1392 // 6 - Reaching this step indicates that the media resource failed to load o
r that the given |
1360 // URL could not be resolved. In one atomic operation, run the following ste
ps: | 1393 // URL could not be resolved. In one atomic operation, run the following ste
ps: |
1361 | 1394 |
1362 // 6.1 - Set the error attribute to a new MediaError object whose code attri
bute is set to | 1395 // 6.1 - Set the error attribute to a new MediaError object whose code attri
bute is set to |
1363 // MEDIA_ERR_SRC_NOT_SUPPORTED. | 1396 // MEDIA_ERR_SRC_NOT_SUPPORTED. |
1364 m_error = MediaError::create(MediaError::MEDIA_ERR_SRC_NOT_SUPPORTED); | 1397 m_error = MediaError::create(MediaError::MEDIA_ERR_SRC_NOT_SUPPORTED); |
1365 | 1398 |
1366 // 6.2 - Forget the media element's media-resource-specific text tracks. | 1399 // 6.2 - Forget the media element's media-resource-specific text tracks. |
| 1400 forgetResourceSpecificTracks(); |
1367 | 1401 |
1368 // 6.3 - Set the element's networkState attribute to the NETWORK_NO_SOURCE v
alue. | 1402 // 6.3 - Set the element's networkState attribute to the NETWORK_NO_SOURCE v
alue. |
1369 m_networkState = NETWORK_NO_SOURCE; | 1403 m_networkState = NETWORK_NO_SOURCE; |
1370 | 1404 |
1371 // 7 - Queue a task to fire a simple event named error at the media element. | 1405 // 7 - Queue a task to fire a simple event named error at the media element. |
1372 scheduleEvent(EventTypeNames::error); | 1406 scheduleEvent(EventTypeNames::error); |
1373 | 1407 |
1374 closeMediaSource(); | 1408 closeMediaSource(); |
1375 | 1409 |
1376 // 8 - Set the element's delaying-the-load-event flag to false. This stops d
elaying the load event. | 1410 // 8 - Set the element's delaying-the-load-event flag to false. This stops d
elaying the load event. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1430 setNetworkState(m_player->networkState()); | 1464 setNetworkState(m_player->networkState()); |
1431 } | 1465 } |
1432 | 1466 |
1433 void HTMLMediaElement::mediaLoadingFailed(MediaPlayer::NetworkState error) | 1467 void HTMLMediaElement::mediaLoadingFailed(MediaPlayer::NetworkState error) |
1434 { | 1468 { |
1435 stopPeriodicTimers(); | 1469 stopPeriodicTimers(); |
1436 | 1470 |
1437 // If we failed while trying to load a <source> element, the movie was never
parsed, and there are more | 1471 // If we failed while trying to load a <source> element, the movie was never
parsed, and there are more |
1438 // <source> children, schedule the next one | 1472 // <source> children, schedule the next one |
1439 if (m_readyState < HAVE_METADATA && m_loadState == LoadingFromSourceElement)
{ | 1473 if (m_readyState < HAVE_METADATA && m_loadState == LoadingFromSourceElement)
{ |
1440 | 1474 // resource selection algorithm |
| 1475 // Step 9.Otherwise.9 - Failed with elements: Queue a task, using the DO
M manipulation task source, to fire a simple event named error at the candidate
element. |
1441 if (m_currentSourceNode) | 1476 if (m_currentSourceNode) |
1442 m_currentSourceNode->scheduleErrorEvent(); | 1477 m_currentSourceNode->scheduleErrorEvent(); |
1443 else | 1478 else |
1444 WTF_LOG(Media, "HTMLMediaElement::setNetworkState - error event not
sent, <source> was removed"); | 1479 WTF_LOG(Media, "HTMLMediaElement::setNetworkState - error event not
sent, <source> was removed"); |
1445 | 1480 |
| 1481 // 9.Otherwise.10 - Asynchronously await a stable state. The synchronous
section consists of all the remaining steps of this algorithm until the algorit
hm says the synchronous section has ended. (Steps in synchronous sections are ma
rked with ⌛.) |
| 1482 |
| 1483 // 9.Otherwise.11 Forget the media element's media-resource-specific tra
cks. |
| 1484 forgetResourceSpecificTracks(); |
| 1485 |
1446 if (havePotentialSourceChild()) { | 1486 if (havePotentialSourceChild()) { |
1447 WTF_LOG(Media, "HTMLMediaElement::setNetworkState - scheduling next
<source>"); | 1487 WTF_LOG(Media, "HTMLMediaElement::setNetworkState - scheduling next
<source>"); |
1448 scheduleNextSourceChild(); | 1488 scheduleNextSourceChild(); |
1449 } else { | 1489 } else { |
1450 WTF_LOG(Media, "HTMLMediaElement::setNetworkState - no more <source>
elements, waiting"); | 1490 WTF_LOG(Media, "HTMLMediaElement::setNetworkState - no more <source>
elements, waiting"); |
1451 waitForSourceChange(); | 1491 waitForSourceChange(); |
1452 } | 1492 } |
1453 | 1493 |
1454 return; | 1494 return; |
1455 } | 1495 } |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1567 finishSeek(); | 1607 finishSeek(); |
1568 } else { | 1608 } else { |
1569 if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) { | 1609 if (wasPotentiallyPlaying && m_readyState < HAVE_FUTURE_DATA) { |
1570 // 4.8.10.8 | 1610 // 4.8.10.8 |
1571 scheduleTimeupdateEvent(false); | 1611 scheduleTimeupdateEvent(false); |
1572 scheduleEvent(EventTypeNames::waiting); | 1612 scheduleEvent(EventTypeNames::waiting); |
1573 } | 1613 } |
1574 } | 1614 } |
1575 | 1615 |
1576 if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { | 1616 if (m_readyState >= HAVE_METADATA && oldState < HAVE_METADATA) { |
| 1617 createPlaceholderTracksIfNecessary(); |
| 1618 |
1577 prepareMediaFragmentURI(); | 1619 prepareMediaFragmentURI(); |
| 1620 |
| 1621 selectInitialTracksIfNecessary(); |
| 1622 |
1578 scheduleEvent(EventTypeNames::durationchange); | 1623 scheduleEvent(EventTypeNames::durationchange); |
1579 if (isVideo()) | 1624 if (isVideo()) |
1580 scheduleEvent(EventTypeNames::resize); | 1625 scheduleEvent(EventTypeNames::resize); |
1581 scheduleEvent(EventTypeNames::loadedmetadata); | 1626 scheduleEvent(EventTypeNames::loadedmetadata); |
1582 if (hasMediaControls()) | 1627 if (hasMediaControls()) |
1583 mediaControls()->reset(); | 1628 mediaControls()->reset(); |
1584 if (renderer()) | 1629 if (renderer()) |
1585 renderer()->updateFromElement(); | 1630 renderer()->updateFromElement(); |
1586 } | 1631 } |
1587 | 1632 |
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2445 m_lastTimeUpdateEventWallTime = now; | 2490 m_lastTimeUpdateEventWallTime = now; |
2446 m_lastTimeUpdateEventMovieTime = movieTime; | 2491 m_lastTimeUpdateEventMovieTime = movieTime; |
2447 } | 2492 } |
2448 } | 2493 } |
2449 | 2494 |
2450 bool HTMLMediaElement::canPlay() const | 2495 bool HTMLMediaElement::canPlay() const |
2451 { | 2496 { |
2452 return paused() || ended() || m_readyState < HAVE_METADATA; | 2497 return paused() || ended() || m_readyState < HAVE_METADATA; |
2453 } | 2498 } |
2454 | 2499 |
2455 void HTMLMediaElement::mediaPlayerDidAddTrack(WebInbandTextTrack* webTrack) | 2500 AudioTrackList* HTMLMediaElement::audioTracks() |
| 2501 { |
| 2502 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 2503 |
| 2504 if (!m_audioTracks) |
| 2505 m_audioTracks = AudioTrackList::create(this); |
| 2506 |
| 2507 return m_audioTracks.get(); |
| 2508 } |
| 2509 |
| 2510 void HTMLMediaElement::didEnabledAudioTrackChange(const AtomicString& audioTrack
ID, bool enabled) |
| 2511 { |
| 2512 WTF_LOG(Media, "HTMLMediaElement::didEnabledAudioTrackChange('%s', %d)", aud
ioTrackID.ascii().data(), enabled); |
| 2513 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 2514 ASSERT(!audioTrackID.isEmpty()); |
| 2515 |
| 2516 if (webMediaPlayer()) |
| 2517 webMediaPlayer()->enabledAudioTrackChange(audioTrackID, enabled); |
| 2518 } |
| 2519 |
| 2520 VideoTrackList* HTMLMediaElement::videoTracks() |
| 2521 { |
| 2522 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 2523 |
| 2524 if (!m_videoTracks) |
| 2525 m_videoTracks = VideoTrackList::create(this); |
| 2526 |
| 2527 return m_videoTracks.get(); |
| 2528 } |
| 2529 |
| 2530 void HTMLMediaElement::didSelectedVideoTrackChange(const AtomicString& unselecte
dTrackID, const AtomicString& selectedTrackID) |
| 2531 { |
| 2532 WTF_LOG(Media, "HTMLMediaElement::didSelectedVideoTrackChange('%s', '%s')",
unselectedTrackID.ascii().data(), selectedTrackID.ascii().data()); |
| 2533 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 2534 ASSERT(!unselectedTrackID.isEmpty() || !selectedTrackID.isEmpty()); |
| 2535 |
| 2536 if (webMediaPlayer()) |
| 2537 webMediaPlayer()->selectedVideoTrackChange(unselectedTrackID, selectedTr
ackID); |
| 2538 } |
| 2539 |
| 2540 void HTMLMediaElement::mediaPlayerDidAddVideoTrack(const AtomicString& id, const
AtomicString& kind, const AtomicString& label, const AtomicString& language, bo
ol selected) |
| 2541 { |
| 2542 WTF_LOG(Media, "HTMLMediaElement::mediaPlayerDidAddVideoTrack('%s', '%s', '%
s', '%s', %d)", |
| 2543 id.ascii().data(), kind.ascii().data(), label.ascii().data(), language.a
scii().data(), selected); |
| 2544 ASSERT(!id.isEmpty()); |
| 2545 |
| 2546 RefPtr<VideoTrack> videoTrack = VideoTrack::create(videoTracks(), id, kind,
label, language); |
| 2547 videoTracks()->add(videoTrack.get()); |
| 2548 |
| 2549 if (selected) |
| 2550 videoTrack->setSelected(true); |
| 2551 } |
| 2552 |
| 2553 void HTMLMediaElement::mediaPlayerDidRemoveVideoTrack(const AtomicString& id) |
| 2554 { |
| 2555 WTF_LOG(Media, "HTMLMediaElement::mediaPlayerDidRevmoeVideoTrack('%s')", id.
ascii().data()); |
| 2556 ASSERT(!id.isEmpty()); |
| 2557 |
| 2558 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 2559 return; |
| 2560 |
| 2561 videoTracks()->remove(id); |
| 2562 } |
| 2563 |
| 2564 void HTMLMediaElement::mediaPlayerDidAddAudioTrack(const AtomicString& id, const
AtomicString& kind, const AtomicString& label, const AtomicString& language, bo
ol enabled) |
| 2565 { |
| 2566 WTF_LOG(Media, "HTMLMediaElement::mediaPlayerDidAddAudioTrack('%s', '%s', '%
s', '%s', %d)", |
| 2567 id.ascii().data(), kind.ascii().data(), label.ascii().data(), language.a
scii().data(), enabled); |
| 2568 ASSERT(!id.isEmpty()); |
| 2569 |
| 2570 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 2571 return; |
| 2572 |
| 2573 AtomicString kindString; |
| 2574 RefPtr<AudioTrack> audioTrack = AudioTrack::create(audioTracks(), id, kind,
label, language); |
| 2575 audioTracks()->add(audioTrack.get()); |
| 2576 |
| 2577 if (enabled) |
| 2578 audioTrack->setEnabled(true); |
| 2579 } |
| 2580 |
| 2581 void HTMLMediaElement::mediaPlayerDidRemoveAudioTrack(const AtomicString& id) |
| 2582 { |
| 2583 WTF_LOG(Media, "HTMLMediaElement::mediaPlayerDidRevmoeAudioTrack('%s')", id.
ascii().data()); |
| 2584 ASSERT(!id.isEmpty()); |
| 2585 |
| 2586 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 2587 return; |
| 2588 |
| 2589 audioTracks()->remove(id); |
| 2590 } |
| 2591 |
| 2592 void HTMLMediaElement::mediaPlayerDidAddTextTrack(WebInbandTextTrack* webTrack) |
2456 { | 2593 { |
2457 if (!RuntimeEnabledFeatures::videoTrackEnabled()) | 2594 if (!RuntimeEnabledFeatures::videoTrackEnabled()) |
2458 return; | 2595 return; |
2459 | 2596 |
2460 // 4.8.10.12.2 Sourcing in-band text tracks | 2597 // 4.8.10.12.2 Sourcing in-band text tracks |
2461 // 1. Associate the relevant data with a new text track and its correspondin
g new TextTrack object. | 2598 // 1. Associate the relevant data with a new text track and its correspondin
g new TextTrack object. |
2462 RefPtr<InbandTextTrack> textTrack = InbandTextTrack::create(document(), this
, webTrack); | 2599 RefPtr<InbandTextTrack> textTrack = InbandTextTrack::create(document(), this
, webTrack); |
2463 | 2600 |
2464 // 2. Set the new text track's kind, label, and language based on the semant
ics of the relevant data, | 2601 // 2. Set the new text track's kind, label, and language based on the semant
ics of the relevant data, |
2465 // as defined by the relevant specification. If there is no label in that da
ta, then the label must | 2602 // as defined by the relevant specification. If there is no label in that da
ta, then the label must |
(...skipping 11 matching lines...) Expand all Loading... |
2477 | 2614 |
2478 // 7. Set the new text track's mode to the mode consistent with the user's p
references and the requirements of | 2615 // 7. Set the new text track's mode to the mode consistent with the user's p
references and the requirements of |
2479 // the relevant specification for the data. | 2616 // the relevant specification for the data. |
2480 // - This will happen in configureTextTracks() | 2617 // - This will happen in configureTextTracks() |
2481 scheduleDelayedAction(LoadTextTrackResource); | 2618 scheduleDelayedAction(LoadTextTrackResource); |
2482 | 2619 |
2483 // 8. Add the new text track to the media element's list of text tracks. | 2620 // 8. Add the new text track to the media element's list of text tracks. |
2484 // 9. Fire an event with the name addtrack, that does not bubble and is not
cancelable, and that uses the TrackEvent | 2621 // 9. Fire an event with the name addtrack, that does not bubble and is not
cancelable, and that uses the TrackEvent |
2485 // interface, with the track attribute initialized to the text track's TextT
rack object, at the media element's | 2622 // interface, with the track attribute initialized to the text track's TextT
rack object, at the media element's |
2486 // textTracks attribute's TextTrackList object. | 2623 // textTracks attribute's TextTrackList object. |
2487 addTrack(textTrack.get()); | 2624 addTextTrack(textTrack.get()); |
2488 } | 2625 } |
2489 | 2626 |
2490 void HTMLMediaElement::mediaPlayerDidRemoveTrack(WebInbandTextTrack* webTrack) | 2627 void HTMLMediaElement::mediaPlayerDidRemoveTextTrack(WebInbandTextTrack* webTrac
k) |
2491 { | 2628 { |
2492 if (!RuntimeEnabledFeatures::videoTrackEnabled()) | 2629 if (!RuntimeEnabledFeatures::videoTrackEnabled()) |
2493 return; | 2630 return; |
2494 | 2631 |
2495 if (!m_textTracks) | 2632 if (!m_textTracks) |
2496 return; | 2633 return; |
2497 | 2634 |
2498 // This cast is safe because we created the InbandTextTrack with the WebInba
ndTextTrack | 2635 // This cast is safe because we created the InbandTextTrack with the WebInba
ndTextTrack |
2499 // passed to mediaPlayerDidAddTrack. | 2636 // passed to mediaPlayerDidAddTrack. |
2500 RefPtr<InbandTextTrack> textTrack = static_cast<InbandTextTrack*>(webTrack->
client()); | 2637 RefPtr<InbandTextTrack> textTrack = static_cast<InbandTextTrack*>(webTrack->
client()); |
2501 if (!textTrack) | 2638 if (!textTrack) |
2502 return; | 2639 return; |
2503 | 2640 |
2504 removeTrack(textTrack.get()); | 2641 removeTextTrack(textTrack.get(), true); |
2505 } | 2642 } |
2506 | 2643 |
2507 void HTMLMediaElement::closeCaptionTracksChanged() | 2644 void HTMLMediaElement::closeCaptionTracksChanged() |
2508 { | 2645 { |
2509 if (hasMediaControls()) | 2646 if (hasMediaControls()) |
2510 mediaControls()->closedCaptionTracksChanged(); | 2647 mediaControls()->closedCaptionTracksChanged(); |
2511 } | 2648 } |
2512 | 2649 |
2513 void HTMLMediaElement::addTrack(TextTrack* track) | 2650 void HTMLMediaElement::addTextTrack(TextTrack* track) |
2514 { | 2651 { |
2515 textTracks()->append(track); | 2652 textTracks()->append(track); |
2516 | 2653 |
2517 closeCaptionTracksChanged(); | 2654 closeCaptionTracksChanged(); |
2518 } | 2655 } |
2519 | 2656 |
2520 void HTMLMediaElement::removeTrack(TextTrack* track) | 2657 void HTMLMediaElement::removeTextTrack(TextTrack* track, bool fireRemoveTrackEve
nt) |
2521 { | 2658 { |
2522 TrackDisplayUpdateScope scope(this); | 2659 TrackDisplayUpdateScope scope(this); |
2523 TextTrackCueList* cues = track->cues(); | 2660 TextTrackCueList* cues = track->cues(); |
2524 if (cues) | 2661 if (cues) |
2525 textTrackRemoveCues(track, cues); | 2662 textTrackRemoveCues(track, cues); |
2526 m_textTracks->remove(track); | 2663 m_textTracks->remove(track, fireRemoveTrackEvent); |
2527 | 2664 |
2528 closeCaptionTracksChanged(); | 2665 closeCaptionTracksChanged(); |
2529 } | 2666 } |
2530 | 2667 |
2531 void HTMLMediaElement::removeAllInbandTracks() | 2668 void HTMLMediaElement::forgetResourceSpecificTracks() |
2532 { | 2669 { |
2533 if (!m_textTracks) | 2670 // Implements the "forget the media element's media-resource-specific tracks
" algorithm. |
2534 return; | 2671 // The order is explicitly specified as text, then audio, and finally video.
Also |
| 2672 // 'removetrack' events should not be fired. |
| 2673 if (m_textTracks) { |
| 2674 TrackDisplayUpdateScope scope(this); |
| 2675 for (int i = m_textTracks->length() - 1; i >= 0; --i) { |
| 2676 TextTrack* track = m_textTracks->item(i); |
2535 | 2677 |
2536 TrackDisplayUpdateScope scope(this); | 2678 if (track->trackType() == TextTrack::InBand) |
2537 for (int i = m_textTracks->length() - 1; i >= 0; --i) { | 2679 removeTextTrack(track, false); |
2538 TextTrack* track = m_textTracks->item(i); | 2680 } |
| 2681 } |
2539 | 2682 |
2540 if (track->trackType() == TextTrack::InBand) | 2683 if (m_audioTracks) |
2541 removeTrack(track); | 2684 m_audioTracks->removeAll(); |
2542 } | 2685 |
| 2686 if (m_videoTracks) |
| 2687 m_videoTracks->removeAll(); |
2543 } | 2688 } |
2544 | 2689 |
2545 PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const AtomicString& kind, c
onst AtomicString& label, const AtomicString& language, ExceptionState& exceptio
nState) | 2690 PassRefPtr<TextTrack> HTMLMediaElement::addTextTrack(const AtomicString& kind, c
onst AtomicString& label, const AtomicString& language, ExceptionState& exceptio
nState) |
2546 { | 2691 { |
2547 ASSERT(RuntimeEnabledFeatures::videoTrackEnabled()); | 2692 ASSERT(RuntimeEnabledFeatures::videoTrackEnabled()); |
2548 | 2693 |
2549 // 4.8.10.12.4 Text track API | 2694 // 4.8.10.12.4 Text track API |
2550 // The addTextTrack(kind, label, language) method of media elements, when in
voked, must run the following steps: | 2695 // The addTextTrack(kind, label, language) method of media elements, when in
voked, must run the following steps: |
2551 | 2696 |
2552 // 1. If kind is not one of the following strings, then throw a SyntaxError
exception and abort these steps | 2697 // 1. If kind is not one of the following strings, then throw a SyntaxError
exception and abort these steps |
2553 if (!TextTrack::isValidKindKeyword(kind)) { | 2698 if (!TextTrack::isValidKindKeyword(kind)) { |
2554 exceptionState.throwDOMException(SyntaxError, "The 'kind' provided ('" +
kind + "') is invalid."); | 2699 exceptionState.throwDOMException(SyntaxError, "The 'kind' provided ('" +
kind + "') is invalid."); |
2555 return nullptr; | 2700 return nullptr; |
2556 } | 2701 } |
2557 | 2702 |
2558 // 2. If the label argument was omitted, let label be the empty string. | 2703 // 2. If the label argument was omitted, let label be the empty string. |
2559 // 3. If the language argument was omitted, let language be the empty string
. | 2704 // 3. If the language argument was omitted, let language be the empty string
. |
2560 // 4. Create a new TextTrack object. | 2705 // 4. Create a new TextTrack object. |
2561 | 2706 |
2562 // 5. Create a new text track corresponding to the new object, and set its t
ext track kind to kind, its text | 2707 // 5. Create a new text track corresponding to the new object, and set its t
ext track kind to kind, its text |
2563 // track label to label, its text track language to language... | 2708 // track label to label, its text track language to language... |
2564 RefPtr<TextTrack> textTrack = TextTrack::create(document(), this, kind, labe
l, language); | 2709 RefPtr<TextTrack> textTrack = TextTrack::create(document(), this, kind, labe
l, language); |
2565 | 2710 |
2566 // Note, due to side effects when changing track parameters, we have to | 2711 // Note, due to side effects when changing track parameters, we have to |
2567 // first append the track to the text track list. | 2712 // first append the track to the text track list. |
2568 | 2713 |
2569 // 6. Add the new text track to the media element's list of text tracks. | 2714 // 6. Add the new text track to the media element's list of text tracks. |
2570 addTrack(textTrack.get()); | 2715 addTextTrack(textTrack.get()); |
2571 | 2716 |
2572 // ... its text track readiness state to the text track loaded state ... | 2717 // ... its text track readiness state to the text track loaded state ... |
2573 textTrack->setReadinessState(TextTrack::Loaded); | 2718 textTrack->setReadinessState(TextTrack::Loaded); |
2574 | 2719 |
2575 // ... its text track mode to the text track hidden mode, and its text track
list of cues to an empty list ... | 2720 // ... its text track mode to the text track hidden mode, and its text track
list of cues to an empty list ... |
2576 textTrack->setMode(TextTrack::hiddenKeyword()); | 2721 textTrack->setMode(TextTrack::hiddenKeyword()); |
2577 | 2722 |
2578 return textTrack.release(); | 2723 return textTrack.release(); |
2579 } | 2724 } |
2580 | 2725 |
(...skipping 15 matching lines...) Expand all Loading... |
2596 return; | 2741 return; |
2597 | 2742 |
2598 // 4.8.10.12.3 Sourcing out-of-band text tracks | 2743 // 4.8.10.12.3 Sourcing out-of-band text tracks |
2599 // When a track element's parent element changes and the new parent is a med
ia element, | 2744 // When a track element's parent element changes and the new parent is a med
ia element, |
2600 // then the user agent must add the track element's corresponding text track
to the | 2745 // then the user agent must add the track element's corresponding text track
to the |
2601 // media element's list of text tracks ... [continues in TextTrackList::appe
nd] | 2746 // media element's list of text tracks ... [continues in TextTrackList::appe
nd] |
2602 RefPtr<TextTrack> textTrack = trackElement->track(); | 2747 RefPtr<TextTrack> textTrack = trackElement->track(); |
2603 if (!textTrack) | 2748 if (!textTrack) |
2604 return; | 2749 return; |
2605 | 2750 |
2606 addTrack(textTrack.get()); | 2751 addTextTrack(textTrack.get()); |
2607 | 2752 |
2608 // Do not schedule the track loading until parsing finishes so we don't star
t before all tracks | 2753 // Do not schedule the track loading until parsing finishes so we don't star
t before all tracks |
2609 // in the markup have been added. | 2754 // in the markup have been added. |
2610 if (isFinishedParsingChildren()) | 2755 if (isFinishedParsingChildren()) |
2611 scheduleDelayedAction(LoadTextTrackResource); | 2756 scheduleDelayedAction(LoadTextTrackResource); |
2612 | 2757 |
2613 if (hasMediaControls()) | 2758 if (hasMediaControls()) |
2614 mediaControls()->closedCaptionTracksChanged(); | 2759 mediaControls()->closedCaptionTracksChanged(); |
2615 } | 2760 } |
2616 | 2761 |
(...skipping 17 matching lines...) Expand all Loading... |
2634 | 2779 |
2635 textTrack->setHasBeenConfigured(false); | 2780 textTrack->setHasBeenConfigured(false); |
2636 | 2781 |
2637 if (!m_textTracks) | 2782 if (!m_textTracks) |
2638 return; | 2783 return; |
2639 | 2784 |
2640 // 4.8.10.12.3 Sourcing out-of-band text tracks | 2785 // 4.8.10.12.3 Sourcing out-of-band text tracks |
2641 // When a track element's parent element changes and the old parent was a me
dia element, | 2786 // When a track element's parent element changes and the old parent was a me
dia element, |
2642 // then the user agent must remove the track element's corresponding text tr
ack from the | 2787 // then the user agent must remove the track element's corresponding text tr
ack from the |
2643 // media element's list of text tracks. | 2788 // media element's list of text tracks. |
2644 removeTrack(textTrack.get()); | 2789 removeTextTrack(textTrack.get(), true); |
2645 | 2790 |
2646 size_t index = m_textTracksWhenResourceSelectionBegan.find(textTrack.get()); | 2791 size_t index = m_textTracksWhenResourceSelectionBegan.find(textTrack.get()); |
2647 if (index != kNotFound) | 2792 if (index != kNotFound) |
2648 m_textTracksWhenResourceSelectionBegan.remove(index); | 2793 m_textTracksWhenResourceSelectionBegan.remove(index); |
2649 } | 2794 } |
2650 | 2795 |
2651 static int textTrackLanguageSelectionScore(const TextTrack& track) | 2796 static int textTrackLanguageSelectionScore(const TextTrack& track) |
2652 { | 2797 { |
2653 if (track.language().isEmpty()) | 2798 if (track.language().isEmpty()) |
2654 return 0; | 2799 return 0; |
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3387 m_player.clear(); | 3532 m_player.clear(); |
3388 | 3533 |
3389 #if ENABLE(WEB_AUDIO) | 3534 #if ENABLE(WEB_AUDIO) |
3390 if (m_audioSourceNode) | 3535 if (m_audioSourceNode) |
3391 m_audioSourceNode->unlock(); | 3536 m_audioSourceNode->unlock(); |
3392 #endif | 3537 #endif |
3393 } | 3538 } |
3394 | 3539 |
3395 void HTMLMediaElement::clearMediaPlayer(int flags) | 3540 void HTMLMediaElement::clearMediaPlayer(int flags) |
3396 { | 3541 { |
3397 removeAllInbandTracks(); | 3542 forgetResourceSpecificTracks(); |
3398 | 3543 |
3399 closeMediaSource(); | 3544 closeMediaSource(); |
3400 | 3545 |
3401 setMediaKeysInternal(0); | 3546 setMediaKeysInternal(0); |
3402 | 3547 |
3403 clearMediaPlayerAndAudioSourceProviderClient(); | 3548 clearMediaPlayerAndAudioSourceProviderClient(); |
3404 | 3549 |
3405 stopPeriodicTimers(); | 3550 stopPeriodicTimers(); |
3406 m_loadTimer.stop(); | 3551 m_loadTimer.stop(); |
3407 | 3552 |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3854 m_fragmentStartTime = MediaPlayer::invalidTime(); | 3999 m_fragmentStartTime = MediaPlayer::invalidTime(); |
3855 | 4000 |
3856 double end = fragmentParser.endTime(); | 4001 double end = fragmentParser.endTime(); |
3857 if (end != MediaFragmentURIParser::invalidTimeValue() && end > 0 && end > m_
fragmentStartTime) { | 4002 if (end != MediaFragmentURIParser::invalidTimeValue() && end > 0 && end > m_
fragmentStartTime) { |
3858 m_fragmentEndTime = end; | 4003 m_fragmentEndTime = end; |
3859 if (m_fragmentEndTime > dur) | 4004 if (m_fragmentEndTime > dur) |
3860 m_fragmentEndTime = dur; | 4005 m_fragmentEndTime = dur; |
3861 } else | 4006 } else |
3862 m_fragmentEndTime = MediaPlayer::invalidTime(); | 4007 m_fragmentEndTime = MediaPlayer::invalidTime(); |
3863 | 4008 |
| 4009 // FIXME: Add support for selecting tracks by ID with the Media Fragments tr
ack dimension. |
| 4010 |
3864 if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE
_FUTURE_DATA) | 4011 if (m_fragmentStartTime != MediaPlayer::invalidTime() && m_readyState < HAVE
_FUTURE_DATA) |
3865 prepareToPlay(); | 4012 prepareToPlay(); |
3866 } | 4013 } |
3867 | 4014 |
3868 void HTMLMediaElement::applyMediaFragmentURI() | 4015 void HTMLMediaElement::applyMediaFragmentURI() |
3869 { | 4016 { |
3870 if (m_fragmentStartTime != MediaPlayer::invalidTime()) { | 4017 if (m_fragmentStartTime != MediaPlayer::invalidTime()) { |
3871 m_sentEndEvent = false; | 4018 m_sentEndEvent = false; |
3872 seek(m_fragmentStartTime, IGNORE_EXCEPTION); | 4019 seek(m_fragmentStartTime, IGNORE_EXCEPTION); |
3873 } | 4020 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3916 void HTMLMediaElement::mediaPlayerMediaSourceOpened(blink::WebMediaSource* webMe
diaSource) | 4063 void HTMLMediaElement::mediaPlayerMediaSourceOpened(blink::WebMediaSource* webMe
diaSource) |
3917 { | 4064 { |
3918 m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource)); | 4065 m_mediaSource->setWebMediaSourceAndOpen(adoptPtr(webMediaSource)); |
3919 } | 4066 } |
3920 | 4067 |
3921 bool HTMLMediaElement::isInteractiveContent() const | 4068 bool HTMLMediaElement::isInteractiveContent() const |
3922 { | 4069 { |
3923 return fastHasAttribute(controlsAttr); | 4070 return fastHasAttribute(controlsAttr); |
3924 } | 4071 } |
3925 | 4072 |
| 4073 void HTMLMediaElement::createPlaceholderTracksIfNecessary() |
| 4074 { |
| 4075 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 4076 return; |
| 4077 |
| 4078 // Create a placeholder audio track if |m_player| says it has audio but it d
idn't explicitly announce the tracks. |
| 4079 if (m_player->hasAudio() && !audioTracks()->length()) |
| 4080 mediaPlayerDidAddAudioTrack("audio", AudioTrack::mainKeyword(), "Audio T
rack", "", true); |
| 4081 |
| 4082 // Create a placeholder video track if |m_player| says it has video but it d
idn't explicitly announce the tracks. |
| 4083 if (m_player->hasVideo() && !videoTracks()->length()) |
| 4084 mediaPlayerDidAddVideoTrack("video", VideoTrack::mainKeyword(), "Video T
rack", "", true); |
3926 } | 4085 } |
| 4086 |
| 4087 void HTMLMediaElement::selectInitialTracksIfNecessary() |
| 4088 { |
| 4089 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
| 4090 return; |
| 4091 |
| 4092 // Enable the first audio track if an audio track hasn't been enabled yet. |
| 4093 if (audioTracks()->length() > 0 && !audioTracks()->hasEnabledTrack()) |
| 4094 audioTracks()->anonymousIndexedGetter(0)->setEnabled(true); |
| 4095 |
| 4096 // Select the first video track if a video track hasn't been selected yet. |
| 4097 if (videoTracks()->length() > 0 && videoTracks()->selectedIndex() == -1) |
| 4098 videoTracks()->anonymousIndexedGetter(0)->setSelected(true); |
| 4099 } |
| 4100 |
| 4101 } |
OLD | NEW |