OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google 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 are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 24 matching lines...) Expand all Loading... |
35 #include "core/dom/DOMArrayBuffer.h" | 35 #include "core/dom/DOMArrayBuffer.h" |
36 #include "core/dom/DOMArrayBufferView.h" | 36 #include "core/dom/DOMArrayBufferView.h" |
37 #include "core/dom/ExceptionCode.h" | 37 #include "core/dom/ExceptionCode.h" |
38 #include "core/dom/ExecutionContext.h" | 38 #include "core/dom/ExecutionContext.h" |
39 #include "core/events/Event.h" | 39 #include "core/events/Event.h" |
40 #include "core/events/GenericEventQueue.h" | 40 #include "core/events/GenericEventQueue.h" |
41 #include "core/fileapi/FileReaderLoader.h" | 41 #include "core/fileapi/FileReaderLoader.h" |
42 #include "core/html/HTMLMediaElement.h" | 42 #include "core/html/HTMLMediaElement.h" |
43 #include "core/html/MediaError.h" | 43 #include "core/html/MediaError.h" |
44 #include "core/html/TimeRanges.h" | 44 #include "core/html/TimeRanges.h" |
| 45 #include "core/html/track/AudioTrack.h" |
| 46 #include "core/html/track/AudioTrackList.h" |
| 47 #include "core/html/track/VideoTrack.h" |
| 48 #include "core/html/track/VideoTrackList.h" |
45 #include "core/streams/Stream.h" | 49 #include "core/streams/Stream.h" |
46 #include "modules/mediasource/MediaSource.h" | 50 #include "modules/mediasource/MediaSource.h" |
47 #include "platform/Logging.h" | 51 #include "platform/Logging.h" |
48 #include "platform/TraceEvent.h" | 52 #include "platform/TraceEvent.h" |
49 #include "public/platform/WebSourceBuffer.h" | 53 #include "public/platform/WebSourceBuffer.h" |
50 #include "wtf/MathExtras.h" | 54 #include "wtf/MathExtras.h" |
51 | 55 |
52 #include <limits> | 56 #include <limits> |
53 #include <sstream> | 57 #include <sstream> |
54 | 58 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 , m_appendBufferAsyncPartRunner(AsyncMethodRunner<SourceBuffer>::create(this
, &SourceBuffer::appendBufferAsyncPart)) | 119 , m_appendBufferAsyncPartRunner(AsyncMethodRunner<SourceBuffer>::create(this
, &SourceBuffer::appendBufferAsyncPart)) |
116 , m_pendingRemoveStart(-1) | 120 , m_pendingRemoveStart(-1) |
117 , m_pendingRemoveEnd(-1) | 121 , m_pendingRemoveEnd(-1) |
118 , m_removeAsyncPartRunner(AsyncMethodRunner<SourceBuffer>::create(this, &Sou
rceBuffer::removeAsyncPart)) | 122 , m_removeAsyncPartRunner(AsyncMethodRunner<SourceBuffer>::create(this, &Sou
rceBuffer::removeAsyncPart)) |
119 , m_streamMaxSizeValid(false) | 123 , m_streamMaxSizeValid(false) |
120 , m_streamMaxSize(0) | 124 , m_streamMaxSize(0) |
121 , m_appendStreamAsyncPartRunner(AsyncMethodRunner<SourceBuffer>::create(this
, &SourceBuffer::appendStreamAsyncPart)) | 125 , m_appendStreamAsyncPartRunner(AsyncMethodRunner<SourceBuffer>::create(this
, &SourceBuffer::appendStreamAsyncPart)) |
122 { | 126 { |
123 ASSERT(m_webSourceBuffer); | 127 ASSERT(m_webSourceBuffer); |
124 ASSERT(m_source); | 128 ASSERT(m_source); |
| 129 ASSERT(m_source->mediaElement()); |
| 130 m_audioTracks = AudioTrackList::create(*m_source->mediaElement()); |
| 131 m_videoTracks = VideoTrackList::create(*m_source->mediaElement()); |
125 m_webSourceBuffer->setClient(this); | 132 m_webSourceBuffer->setClient(this); |
126 } | 133 } |
127 | 134 |
128 SourceBuffer::~SourceBuffer() | 135 SourceBuffer::~SourceBuffer() |
129 { | 136 { |
130 // Oilpan: a SourceBuffer might be finalized without having been | 137 // Oilpan: a SourceBuffer might be finalized without having been |
131 // explicitly removed first, hence the asserts below will not | 138 // explicitly removed first, hence the asserts below will not |
132 // hold. | 139 // hold. |
133 #if !ENABLE(OILPAN) | 140 #if !ENABLE(OILPAN) |
| 141 m_audioTracks->shutdown(); |
| 142 m_videoTracks->shutdown(); |
134 ASSERT(isRemoved()); | 143 ASSERT(isRemoved()); |
135 ASSERT(!m_loader); | 144 ASSERT(!m_loader); |
136 ASSERT(!m_stream); | 145 ASSERT(!m_stream); |
137 ASSERT(!m_webSourceBuffer); | 146 ASSERT(!m_webSourceBuffer); |
138 #endif | 147 #endif |
139 WTF_LOG(Media, "SourceBuffer(%p)::~SourceBuffer", this); | 148 WTF_LOG(Media, "SourceBuffer(%p)::~SourceBuffer", this); |
140 } | 149 } |
141 | 150 |
142 const AtomicString& SourceBuffer::segmentsKeyword() | 151 const AtomicString& SourceBuffer::segmentsKeyword() |
143 { | 152 { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 // 6. If the mode attribute equals "sequence", then set the group start time
stamp to new timestamp offset. | 230 // 6. If the mode attribute equals "sequence", then set the group start time
stamp to new timestamp offset. |
222 if (!m_webSourceBuffer->setTimestampOffset(offset)) { | 231 if (!m_webSourceBuffer->setTimestampOffset(offset)) { |
223 MediaSource::logAndThrowDOMException(exceptionState, InvalidStateError,
"The timestamp offset may not be set while the SourceBuffer's append state is 'P
ARSING_MEDIA_SEGMENT'."); | 232 MediaSource::logAndThrowDOMException(exceptionState, InvalidStateError,
"The timestamp offset may not be set while the SourceBuffer's append state is 'P
ARSING_MEDIA_SEGMENT'."); |
224 return; | 233 return; |
225 } | 234 } |
226 | 235 |
227 // 7. Update the attribute to new timestamp offset. | 236 // 7. Update the attribute to new timestamp offset. |
228 m_timestampOffset = offset; | 237 m_timestampOffset = offset; |
229 } | 238 } |
230 | 239 |
| 240 AudioTrackList& SourceBuffer::audioTracks() |
| 241 { |
| 242 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 243 return *m_audioTracks; |
| 244 } |
| 245 |
| 246 VideoTrackList& SourceBuffer::videoTracks() |
| 247 { |
| 248 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); |
| 249 return *m_videoTracks; |
| 250 } |
| 251 |
231 double SourceBuffer::appendWindowStart() const | 252 double SourceBuffer::appendWindowStart() const |
232 { | 253 { |
233 return m_appendWindowStart; | 254 return m_appendWindowStart; |
234 } | 255 } |
235 | 256 |
236 void SourceBuffer::setAppendWindowStart(double start, ExceptionState& exceptionS
tate) | 257 void SourceBuffer::setAppendWindowStart(double start, ExceptionState& exceptionS
tate) |
237 { | 258 { |
238 WTF_LOG(Media, "SourceBuffer::setAppendWindowStart %p start=%f", this, start
); | 259 WTF_LOG(Media, "SourceBuffer::setAppendWindowStart %p start=%f", this, start
); |
239 // Section 3.1 appendWindowStart attribute setter steps. | 260 // Section 3.1 appendWindowStart attribute setter steps. |
240 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.
html#widl-SourceBuffer-appendWindowStart | 261 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.
html#widl-SourceBuffer-appendWindowStart |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 | 485 |
465 WTF_LOG(Media, "SourceBuffer(%p)::removedFromMediaSource", this); | 486 WTF_LOG(Media, "SourceBuffer(%p)::removedFromMediaSource", this); |
466 abortIfUpdating(); | 487 abortIfUpdating(); |
467 | 488 |
468 m_webSourceBuffer->removedFromMediaSource(); | 489 m_webSourceBuffer->removedFromMediaSource(); |
469 m_webSourceBuffer.clear(); | 490 m_webSourceBuffer.clear(); |
470 m_source = nullptr; | 491 m_source = nullptr; |
471 m_asyncEventQueue = nullptr; | 492 m_asyncEventQueue = nullptr; |
472 } | 493 } |
473 | 494 |
474 void SourceBuffer::initializationSegmentReceived() | 495 template<class T> |
| 496 T* findExistingTrackById(const TrackListBase<T>& trackList, const String& id) |
475 { | 497 { |
476 WTF_LOG(Media, "SourceBuffer::initializationSegmentReceived %p", this); | 498 // According to MSE specification (https://w3c.github.io/media-source/#sourc
ebuffer-init-segment-received) step 3.1: |
| 499 // > If more than one track for a single type are present (ie 2 audio tracks
), then the Track IDs match the ones in the first initialization segment. |
| 500 // I.e. we only need to search by TrackID if there is more than one track, o
therwise we can assume that the only |
| 501 // track of the given type is the same one that we had in previous init segm
ents. |
| 502 if (trackList.length() == 1) |
| 503 return trackList.anonymousIndexedGetter(0); |
| 504 return trackList.getTrackById(id); |
| 505 } |
| 506 |
| 507 std::vector<WebMediaPlayer::TrackId> SourceBuffer::initializationSegmentReceived
(const std::vector<MediaTrackInfo>& newTracks) |
| 508 { |
| 509 WTF_LOG(Media, "SourceBuffer::initializationSegmentReceived %p tracks=%zu",
this, newTracks.size()); |
477 ASSERT(m_source); | 510 ASSERT(m_source); |
| 511 ASSERT(m_source->mediaElement()); |
478 ASSERT(m_updating); | 512 ASSERT(m_updating); |
479 | 513 |
480 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source.
html#sourcebuffer-init-segment-received | 514 // TODO(servolk): Implement proper 'initialization segment received' algorit
hm according to MSE spec: |
481 // FIXME: Make steps 1-7 synchronous with this call. | 515 // https://w3c.github.io/media-source/#sourcebuffer-init-segment-received |
482 // FIXME: Augment the interface to this method to implement compliant steps
4-7 here. | 516 std::vector<WebMediaPlayer::TrackId> result; |
483 // Step 3 (if the first initialization segment received flag is true) is | 517 for (const auto& trackInfo : newTracks) { |
484 // implemented by caller. | 518 const auto& trackType = std::get<0>(trackInfo); |
| 519 const auto& id = std::get<1>(trackInfo); |
| 520 const auto& kind = std::get<2>(trackInfo); |
| 521 const auto& label = std::get<3>(trackInfo); |
| 522 const auto& language = std::get<4>(trackInfo); |
| 523 |
| 524 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) { |
| 525 static WebMediaPlayer::TrackId nextTrackId = 0; |
| 526 result.push_back(++nextTrackId); |
| 527 continue; |
| 528 } |
| 529 |
| 530 const TrackBase* trackBase = nullptr; |
| 531 if (trackType == WebMediaPlayer::AudioTrack) { |
| 532 AudioTrack* audioTrack = nullptr; |
| 533 if (!m_firstInitializationSegmentReceived) { |
| 534 audioTrack = AudioTrack::create(id, kind, label, language, false
); |
| 535 audioTracks().add(audioTrack); |
| 536 m_source->mediaElement()->audioTracks().add(audioTrack); |
| 537 } else { |
| 538 audioTrack = findExistingTrackById(audioTracks(), id); |
| 539 ASSERT(audioTrack); |
| 540 } |
| 541 trackBase = audioTrack; |
| 542 result.push_back(audioTrack->trackId()); |
| 543 } else if (trackType == WebMediaPlayer::VideoTrack) { |
| 544 VideoTrack* videoTrack = nullptr; |
| 545 if (!m_firstInitializationSegmentReceived) { |
| 546 videoTrack = VideoTrack::create(id, kind, label, language, false
); |
| 547 videoTracks().add(videoTrack); |
| 548 m_source->mediaElement()->videoTracks().add(videoTrack); |
| 549 } else { |
| 550 videoTrack = findExistingTrackById(videoTracks(), id); |
| 551 ASSERT(videoTrack); |
| 552 } |
| 553 trackBase = videoTrack; |
| 554 result.push_back(videoTrack->trackId()); |
| 555 } else { |
| 556 NOTREACHED(); |
| 557 } |
| 558 (void)trackBase; |
| 559 #if !LOG_DISABLED |
| 560 const char* logActionStr = m_firstInitializationSegmentReceived ? "using
existing" : "added"; |
| 561 const char* logTrackTypeStr = (trackType == WebMediaPlayer::AudioTrack)
? "audio" : "video"; |
| 562 WTF_LOG(Media, "Tracks (sb=%p): %s %sTrack %p trackId=%d id=%s label=%s
lang=%s", this, logActionStr, logTrackTypeStr, trackBase, trackBase->trackId(),
trackBase->id().utf8().data(), trackBase->label().utf8().data(), trackBase->lang
uage().utf8().data()); |
| 563 #endif |
| 564 } |
485 | 565 |
486 if (!m_firstInitializationSegmentReceived) { | 566 if (!m_firstInitializationSegmentReceived) { |
487 // 5. If active track flag equals true, then run the following steps: | 567 // 5. If active track flag equals true, then run the following steps: |
488 // 5.1. Add this SourceBuffer to activeSourceBuffers. | 568 // 5.1. Add this SourceBuffer to activeSourceBuffers. |
489 // 5.2. Queue a task to fire a simple event named addsourcebuffer at | 569 // 5.2. Queue a task to fire a simple event named addsourcebuffer at |
490 // activesourcebuffers. | 570 // activesourcebuffers. |
491 m_source->setSourceBufferActive(this); | 571 m_source->setSourceBufferActive(this); |
492 | 572 |
493 // 6. Set first initialization segment received flag to true. | 573 // 6. Set first initialization segment received flag to true. |
494 m_firstInitializationSegmentReceived = true; | 574 m_firstInitializationSegmentReceived = true; |
495 } | 575 } |
| 576 |
| 577 return result; |
496 } | 578 } |
497 | 579 |
498 bool SourceBuffer::hasPendingActivity() const | 580 bool SourceBuffer::hasPendingActivity() const |
499 { | 581 { |
500 return m_source; | 582 return m_source; |
501 } | 583 } |
502 | 584 |
503 void SourceBuffer::suspend() | 585 void SourceBuffer::suspend() |
504 { | 586 { |
505 m_appendBufferAsyncPartRunner->suspend(); | 587 m_appendBufferAsyncPartRunner->suspend(); |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 | 948 |
867 DEFINE_TRACE(SourceBuffer) | 949 DEFINE_TRACE(SourceBuffer) |
868 { | 950 { |
869 visitor->trace(m_source); | 951 visitor->trace(m_source); |
870 visitor->trace(m_trackDefaults); | 952 visitor->trace(m_trackDefaults); |
871 visitor->trace(m_asyncEventQueue); | 953 visitor->trace(m_asyncEventQueue); |
872 visitor->trace(m_appendBufferAsyncPartRunner); | 954 visitor->trace(m_appendBufferAsyncPartRunner); |
873 visitor->trace(m_removeAsyncPartRunner); | 955 visitor->trace(m_removeAsyncPartRunner); |
874 visitor->trace(m_appendStreamAsyncPartRunner); | 956 visitor->trace(m_appendStreamAsyncPartRunner); |
875 visitor->trace(m_stream); | 957 visitor->trace(m_stream); |
| 958 visitor->trace(m_audioTracks); |
| 959 visitor->trace(m_videoTracks); |
876 RefCountedGarbageCollectedEventTargetWithInlineData<SourceBuffer>::trace(vis
itor); | 960 RefCountedGarbageCollectedEventTargetWithInlineData<SourceBuffer>::trace(vis
itor); |
877 ActiveDOMObject::trace(visitor); | 961 ActiveDOMObject::trace(visitor); |
878 } | 962 } |
879 | 963 |
880 } // namespace blink | 964 } // namespace blink |
OLD | NEW |