Chromium Code Reviews| 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()); | |
|
philipj_slow
2016/03/29 11:59:21
Looks like you could put this in the initializer l
servolk
2016/03/29 17:30:34
Yeah, I wanted to check (via ASSERT) that we have
| |
| 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) |
| 134 ASSERT(isRemoved()); | 141 ASSERT(isRemoved()); |
| (...skipping 86 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. | 228 // 6. If the mode attribute equals "sequence", then set the group start time stamp to new timestamp offset. |
| 222 if (!m_webSourceBuffer->setTimestampOffset(offset)) { | 229 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'."); | 230 MediaSource::logAndThrowDOMException(exceptionState, InvalidStateError, "The timestamp offset may not be set while the SourceBuffer's append state is 'P ARSING_MEDIA_SEGMENT'."); |
| 224 return; | 231 return; |
| 225 } | 232 } |
| 226 | 233 |
| 227 // 7. Update the attribute to new timestamp offset. | 234 // 7. Update the attribute to new timestamp offset. |
| 228 m_timestampOffset = offset; | 235 m_timestampOffset = offset; |
| 229 } | 236 } |
| 230 | 237 |
| 238 AudioTrackList& SourceBuffer::audioTracks() | |
| 239 { | |
| 240 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); | |
| 241 return *m_audioTracks; | |
| 242 } | |
| 243 | |
| 244 VideoTrackList& SourceBuffer::videoTracks() | |
| 245 { | |
| 246 ASSERT(RuntimeEnabledFeatures::audioVideoTracksEnabled()); | |
| 247 return *m_videoTracks; | |
| 248 } | |
| 249 | |
| 231 double SourceBuffer::appendWindowStart() const | 250 double SourceBuffer::appendWindowStart() const |
| 232 { | 251 { |
| 233 return m_appendWindowStart; | 252 return m_appendWindowStart; |
| 234 } | 253 } |
| 235 | 254 |
| 236 void SourceBuffer::setAppendWindowStart(double start, ExceptionState& exceptionS tate) | 255 void SourceBuffer::setAppendWindowStart(double start, ExceptionState& exceptionS tate) |
| 237 { | 256 { |
| 238 WTF_LOG(Media, "SourceBuffer::setAppendWindowStart %p start=%f", this, start ); | 257 WTF_LOG(Media, "SourceBuffer::setAppendWindowStart %p start=%f", this, start ); |
| 239 // Section 3.1 appendWindowStart attribute setter steps. | 258 // 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 | 259 // 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 | 483 |
| 465 WTF_LOG(Media, "SourceBuffer(%p)::removedFromMediaSource", this); | 484 WTF_LOG(Media, "SourceBuffer(%p)::removedFromMediaSource", this); |
| 466 abortIfUpdating(); | 485 abortIfUpdating(); |
| 467 | 486 |
| 468 m_webSourceBuffer->removedFromMediaSource(); | 487 m_webSourceBuffer->removedFromMediaSource(); |
| 469 m_webSourceBuffer.clear(); | 488 m_webSourceBuffer.clear(); |
| 470 m_source = nullptr; | 489 m_source = nullptr; |
| 471 m_asyncEventQueue = nullptr; | 490 m_asyncEventQueue = nullptr; |
| 472 } | 491 } |
| 473 | 492 |
| 474 void SourceBuffer::initializationSegmentReceived() | 493 template<class T> |
| 494 T* findTrackById(const TrackListBase<T>& trackList, const WebString& id) | |
| 475 { | 495 { |
| 476 WTF_LOG(Media, "SourceBuffer::initializationSegmentReceived %p", this); | 496 // According to MSE specification (https://www.w3.org/TR/media-source/#sourc ebuffer-init-segment-received) step 3.1: |
| 497 // > 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. | |
| 498 // I.e. we only need to search by TrackID if there is more than one track, o therwise we can assume that the only | |
|
philipj_slow
2016/03/29 11:59:21
Is this an optimization, or is it expected to ever
servolk
2016/03/29 17:30:34
wolenetz@ mentioned that MSE spec allows bytestrea
| |
| 499 // track of the given type is the same one that we had in previous init segm ents. | |
| 500 if (trackList.length() == 1) | |
| 501 return trackList.anonymousIndexedGetter(0); | |
| 502 return trackList.getTrackById(id); | |
| 503 } | |
| 504 | |
| 505 std::vector<WebMediaPlayer::TrackId> SourceBuffer::initializationSegmentReceived (const std::vector<MediaTrackInfo>& newTracks) | |
| 506 { | |
| 507 WTF_LOG(Media, "SourceBuffer::initializationSegmentReceived2 %p tracks=%zu", this, newTracks.size()); | |
| 477 ASSERT(m_source); | 508 ASSERT(m_source); |
| 509 ASSERT(m_source->mediaElement()); | |
| 478 ASSERT(m_updating); | 510 ASSERT(m_updating); |
| 479 | 511 |
| 480 // https://dvcs.w3.org/hg/html-media/raw-file/tip/media-source/media-source. html#sourcebuffer-init-segment-received | 512 // TODO(servolk): Implement proper 'initialization segment received' algorit hm according to MSE spec: |
| 481 // FIXME: Make steps 1-7 synchronous with this call. | 513 // https://www.w3.org/TR/media-source/#sourcebuffer-init-segment-received |
|
philipj_slow
2016/03/29 11:59:21
https://w3c.github.io/media-source/#sourcebuffer-i
servolk
2016/03/29 17:30:34
Done.
| |
| 482 // FIXME: Augment the interface to this method to implement compliant steps 4-7 here. | 514 std::vector<WebMediaPlayer::TrackId> result; |
| 483 // Step 3 (if the first initialization segment received flag is true) is | 515 for (const auto& trackInfo : newTracks) { |
| 484 // implemented by caller. | 516 const auto& trackType = std::get<0>(trackInfo); |
| 517 const auto& id = std::get<1>(trackInfo); | |
| 518 const auto& kind = std::get<2>(trackInfo); | |
| 519 const auto& label = std::get<3>(trackInfo); | |
| 520 const auto& language = std::get<4>(trackInfo); | |
| 521 | |
| 522 const TrackBase* trackBase = nullptr; | |
| 523 if (trackType == WebMediaPlayer::AudioTrack) { | |
| 524 AudioTrack* audioTrack = nullptr; | |
| 525 if (!m_firstInitializationSegmentReceived) { | |
| 526 audioTrack = AudioTrack::create(id, kind, label, language, false ); | |
| 527 audioTracks().add(audioTrack); | |
| 528 m_source->mediaElement()->audioTracks().add(audioTrack); | |
| 529 } else { | |
| 530 audioTrack = findTrackById(audioTracks(), id); | |
|
philipj_slow
2016/03/29 11:59:21
How about making it part of the API that if(m_firs
servolk
2016/03/29 17:30:34
No, see the comments above for findExistingTrackBy
| |
| 531 ASSERT(audioTrack); | |
| 532 } | |
| 533 trackBase = audioTrack; | |
| 534 result.push_back(audioTrack->trackId()); | |
| 535 } else if (trackType == WebMediaPlayer::VideoTrack) { | |
| 536 VideoTrack* videoTrack = nullptr; | |
| 537 if (!m_firstInitializationSegmentReceived) { | |
| 538 videoTrack = VideoTrack::create(id, kind, label, language, false ); | |
| 539 videoTracks().add(videoTrack); | |
| 540 m_source->mediaElement()->videoTracks().add(videoTrack); | |
| 541 } else { | |
| 542 videoTrack = findTrackById(videoTracks(), id); | |
| 543 ASSERT(videoTrack); | |
| 544 } | |
| 545 trackBase = videoTrack; | |
| 546 result.push_back(videoTrack->trackId()); | |
| 547 } else { | |
| 548 NOTREACHED(); | |
| 549 } | |
| 550 const char* logActionStr = m_firstInitializationSegmentReceived ? "using existing" : "added"; | |
|
philipj_slow
2016/03/29 11:59:21
The trackBase variable is only for logging it seem
servolk
2016/03/29 17:30:34
Well, actually one important thing that we want to
| |
| 551 const char* logTrackTypeStr = (trackType == WebMediaPlayer::AudioTrack) ? "audio" : "video"; | |
| 552 (void)logActionStr; | |
| 553 (void)logTrackTypeStr; | |
| 554 (void)trackBase; | |
| 555 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()); | |
| 556 } | |
| 485 | 557 |
| 486 if (!m_firstInitializationSegmentReceived) { | 558 if (!m_firstInitializationSegmentReceived) { |
| 487 // 5. If active track flag equals true, then run the following steps: | 559 // 5. If active track flag equals true, then run the following steps: |
| 488 // 5.1. Add this SourceBuffer to activeSourceBuffers. | 560 // 5.1. Add this SourceBuffer to activeSourceBuffers. |
| 489 // 5.2. Queue a task to fire a simple event named addsourcebuffer at | 561 // 5.2. Queue a task to fire a simple event named addsourcebuffer at |
| 490 // activesourcebuffers. | 562 // activesourcebuffers. |
| 491 m_source->setSourceBufferActive(this); | 563 m_source->setSourceBufferActive(this); |
| 492 | 564 |
| 493 // 6. Set first initialization segment received flag to true. | 565 // 6. Set first initialization segment received flag to true. |
| 494 m_firstInitializationSegmentReceived = true; | 566 m_firstInitializationSegmentReceived = true; |
| 495 } | 567 } |
| 568 | |
| 569 return result; | |
| 496 } | 570 } |
| 497 | 571 |
| 498 bool SourceBuffer::hasPendingActivity() const | 572 bool SourceBuffer::hasPendingActivity() const |
| 499 { | 573 { |
| 500 return m_source; | 574 return m_source; |
| 501 } | 575 } |
| 502 | 576 |
| 503 void SourceBuffer::suspend() | 577 void SourceBuffer::suspend() |
| 504 { | 578 { |
| 505 m_appendBufferAsyncPartRunner->suspend(); | 579 m_appendBufferAsyncPartRunner->suspend(); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 866 | 940 |
| 867 DEFINE_TRACE(SourceBuffer) | 941 DEFINE_TRACE(SourceBuffer) |
| 868 { | 942 { |
| 869 visitor->trace(m_source); | 943 visitor->trace(m_source); |
| 870 visitor->trace(m_trackDefaults); | 944 visitor->trace(m_trackDefaults); |
| 871 visitor->trace(m_asyncEventQueue); | 945 visitor->trace(m_asyncEventQueue); |
| 872 visitor->trace(m_appendBufferAsyncPartRunner); | 946 visitor->trace(m_appendBufferAsyncPartRunner); |
| 873 visitor->trace(m_removeAsyncPartRunner); | 947 visitor->trace(m_removeAsyncPartRunner); |
| 874 visitor->trace(m_appendStreamAsyncPartRunner); | 948 visitor->trace(m_appendStreamAsyncPartRunner); |
| 875 visitor->trace(m_stream); | 949 visitor->trace(m_stream); |
| 950 visitor->trace(m_audioTracks); | |
| 951 visitor->trace(m_videoTracks); | |
| 876 RefCountedGarbageCollectedEventTargetWithInlineData<SourceBuffer>::trace(vis itor); | 952 RefCountedGarbageCollectedEventTargetWithInlineData<SourceBuffer>::trace(vis itor); |
| 877 ActiveDOMObject::trace(visitor); | 953 ActiveDOMObject::trace(visitor); |
| 878 } | 954 } |
| 879 | 955 |
| 880 } // namespace blink | 956 } // namespace blink |
| OLD | NEW |