diff options
-rw-r--r-- | media/filters/chunk_demuxer.cc | 40 | ||||
-rw-r--r-- | media/filters/chunk_demuxer.h | 29 | ||||
-rw-r--r-- | media/filters/chunk_demuxer_unittest.cc | 35 | ||||
-rw-r--r-- | media/filters/pipeline_integration_test.cc | 8 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_impl.cc | 31 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_impl.h | 7 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_proxy.cc | 21 | ||||
-rw-r--r-- | webkit/media/webmediaplayer_proxy.h | 6 |
8 files changed, 154 insertions, 23 deletions
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc index d3f532c..25bc0bc 100644 --- a/media/filters/chunk_demuxer.cc +++ b/media/filters/chunk_demuxer.cc @@ -15,6 +15,9 @@ namespace media { +// TODO(acolwell): Remove this when fixing http://crbug.com/122909 . +const char* kDefaultSourceType = "video/webm; codecs=\"vp8, vorbis\""; + // Create an "end of stream" buffer. static Buffer* CreateEOSBuffer() { return new DataBuffer(0); @@ -455,11 +458,40 @@ void ChunkDemuxer::FlushData() { ChangeState_Locked(INITIALIZED); } -bool ChunkDemuxer::AppendData(const uint8* data, size_t length) { - DVLOG(1) << "AppendData(" << length << ")"; +ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id, + const std::string& type) { + // TODO(acolwell): Proper mimetype decoding and support for more than one ID + // will be added as part of http://crbug.com/122909 + if (type != kDefaultSourceType) + return kNotSupported; - if (!data || length == 0u) - return false; + if (!source_id_.empty()) + return kReachedIdLimit; + + source_id_ = id; + return kOk; +} + +void ChunkDemuxer::RemoveId(const std::string& id) { + CHECK(!source_id_.empty()); + CHECK_EQ(source_id_, id); + source_id_ = ""; +} + +bool ChunkDemuxer::AppendData(const std::string& id, + const uint8* data, + size_t length) { + DVLOG(1) << "AppendData(" << id << ", " << length << ")"; + + // TODO(acolwell): Remove when http://webk.it/83788 fix lands. + if (source_id_.empty()) + AddId(id, kDefaultSourceType); + + DCHECK(!source_id_.empty()); + DCHECK_EQ(source_id_, id); + DCHECK(!id.empty()); + DCHECK(data); + DCHECK_GT(length, 0u); int64 buffered_bytes = 0; base::TimeDelta buffered_ts = base::TimeDelta::FromSeconds(-1); diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h index ae690b9..3942b23 100644 --- a/media/filters/chunk_demuxer.h +++ b/media/filters/chunk_demuxer.h @@ -6,6 +6,7 @@ #define MEDIA_FILTERS_CHUNK_DEMUXER_H_ #include <list> +#include <string> #include "base/synchronization/lock.h" #include "media/base/byte_queue.h" @@ -22,6 +23,12 @@ class FFmpegURLProtocol; // from JavaScript to the media stack. class MEDIA_EXPORT ChunkDemuxer : public Demuxer, public StreamParserHost { public: + enum Status { + kOk, // ID added w/o error. + kNotSupported, // Type specified is not supported. + kReachedIdLimit, // Reached ID limit. We can't handle any more IDs. + }; + explicit ChunkDemuxer(ChunkDemuxerClient* client); virtual ~ChunkDemuxer(); @@ -41,9 +48,22 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer, public StreamParserHost { // Methods used by an external object to control this demuxer. void FlushData(); - // Appends media data to the stream. Returns false if this method - // is called in an invalid state. - bool AppendData(const uint8* data, size_t length); + // Registers a new |id| to use for AppendData() calls. |type| indicates + // the MIME type for the data that we intend to append for this ID. + // kOk is returned if the demuxer has enough resources to support another ID + // and supports the format indicated by |type|. + // kNotSupported is returned if |type| is not a supported format. + // kReachedIdLimit is returned if the demuxer cannot handle another ID right + // now. + Status AddId(const std::string& id, const std::string& type); + + // Removed an ID & associated resources that were previously added with + // AddId(). + void RemoveId(const std::string& id); + + // Appends media data to the source buffer associated with |id|. Returns + // false if this method is called in an invalid state. + bool AppendData(const std::string& id, const uint8* data, size_t length); void EndOfStream(PipelineStatus status); bool HasEnded(); void Shutdown(); @@ -95,6 +115,9 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer, public StreamParserHost { ByteQueue byte_queue_; + // TODO(acolwell): Remove this when fixing http://crbug.com/122909 + std::string source_id_; + DISALLOW_COPY_AND_ASSIGN(ChunkDemuxer); }; diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc index 5bbc817..00669f2 100644 --- a/media/filters/chunk_demuxer_unittest.cc +++ b/media/filters/chunk_demuxer_unittest.cc @@ -38,6 +38,9 @@ static const int kVideoTrackEntryHeaderSize = kVideoTrackSizeOffset + static const int kVideoTrackNum = 1; static const int kAudioTrackNum = 2; +static const char* kSourceId = "SourceId"; +static const char* kDefaultSourceType = "video/webm; codecs=\"vp8, vorbis\""; + base::TimeDelta kDefaultDuration() { return base::TimeDelta::FromMilliseconds(201224); } @@ -164,7 +167,7 @@ class ChunkDemuxerTest : public testing::Test { EXPECT_CALL(host_, SetBufferedTime(_)).Times(AnyNumber()); EXPECT_CALL(host_, SetNetworkActivity(true)) .Times(AnyNumber()); - return demuxer_->AppendData(data, length); + return demuxer_->AppendData(kSourceId, data, length); } bool AppendDataInPieces(const uint8* data, size_t length) { @@ -219,6 +222,9 @@ class ChunkDemuxerTest : public testing::Test { demuxer_->Initialize( &host_, CreateInitDoneCB(kDefaultDuration(), expected_status)); + if (demuxer_->AddId(kSourceId, kDefaultSourceType) != ChunkDemuxer::kOk) + return false; + return AppendInfoTracks(has_audio, has_video, video_content_encoded); } @@ -272,6 +278,9 @@ class ChunkDemuxerTest : public testing::Test { demuxer_->Initialize( &host_, CreateInitDoneCB(duration, PIPELINE_OK)); + if (demuxer_->AddId(kSourceId, kDefaultSourceType) != ChunkDemuxer::kOk) + return false; + // Read a WebM file into memory and send the data to the demuxer. ReadTestDataFile(filename, &buffer, &buffer_size); if (!AppendDataInPieces(buffer.get(), buffer_size, 512)) @@ -460,7 +469,8 @@ TEST_F(ChunkDemuxerTest, TestAppendDataBeforeInit) { int info_tracks_size = 0; CreateInfoTracks(true, true, false, &info_tracks, &info_tracks_size); - EXPECT_FALSE(demuxer_->AppendData(info_tracks.get(), info_tracks_size)); + EXPECT_FALSE(demuxer_->AppendData(kSourceId, info_tracks.get(), + info_tracks_size)); } // Make sure Read() callbacks are dispatched with the proper data. @@ -527,7 +537,8 @@ TEST_F(ChunkDemuxerTest, TestOutOfOrderClusters) { AddSimpleBlock(&cb, kAudioTrackNum, 45); AddSimpleBlock(&cb, kVideoTrackNum, 45); scoped_ptr<Cluster> cluster_c(cb.Finish()); - EXPECT_FALSE(demuxer_->AppendData(cluster_c->data(), cluster_c->size())); + EXPECT_FALSE(demuxer_->AppendData(kSourceId, cluster_c->data(), + cluster_c->size())); } TEST_F(ChunkDemuxerTest, TestNonMonotonicButAboveClusterTimecode) { @@ -552,7 +563,8 @@ TEST_F(ChunkDemuxerTest, TestNonMonotonicButAboveClusterTimecode) { AddSimpleBlock(&cb, kAudioTrackNum, 20); AddSimpleBlock(&cb, kVideoTrackNum, 20); scoped_ptr<Cluster> cluster_b(cb.Finish()); - EXPECT_FALSE(demuxer_->AppendData(cluster_b->data(), cluster_b->size())); + EXPECT_FALSE(demuxer_->AppendData(kSourceId, cluster_b->data(), + cluster_b->size())); } TEST_F(ChunkDemuxerTest, TestBackwardsAndBeforeClusterTimecode) { @@ -577,7 +589,8 @@ TEST_F(ChunkDemuxerTest, TestBackwardsAndBeforeClusterTimecode) { AddSimpleBlock(&cb, kAudioTrackNum, 6); AddSimpleBlock(&cb, kVideoTrackNum, 6); scoped_ptr<Cluster> cluster_b(cb.Finish()); - EXPECT_FALSE(demuxer_->AppendData(cluster_b->data(), cluster_b->size())); + EXPECT_FALSE(demuxer_->AppendData(kSourceId, cluster_b->data(), + cluster_b->size())); } @@ -626,7 +639,8 @@ TEST_F(ChunkDemuxerTest, TestMonotonicallyIncreasingTimestampsAcrossClusters) { AddSimpleBlock(&cb, kAudioTrackNum, 10); AddSimpleBlock(&cb, kVideoTrackNum, 10); scoped_ptr<Cluster> cluster_c(cb.Finish()); - EXPECT_FALSE(demuxer_->AppendData(cluster_c->data(), cluster_c->size())); + EXPECT_FALSE(demuxer_->AppendData(kSourceId, cluster_c->data(), + cluster_c->size())); } // Test the case where a cluster is passed to AppendData() before @@ -636,6 +650,8 @@ TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) { demuxer_->Initialize( &host_, NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); + ASSERT_EQ(demuxer_->AddId(kSourceId, kDefaultSourceType), ChunkDemuxer::kOk); + ClusterBuilder cb; cb.SetClusterTimecode(0); AddSimpleBlock(&cb, kVideoTrackNum, 0); @@ -835,6 +851,8 @@ TEST_F(ChunkDemuxerTest, TestAppendingInPieces) { demuxer_->Initialize( &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK)); + ASSERT_EQ(demuxer_->AddId(kSourceId, kDefaultSourceType), ChunkDemuxer::kOk); + scoped_array<uint8> info_tracks; int info_tracks_size = 0; CreateInfoTracks(true, true, false, &info_tracks, &info_tracks_size); @@ -1033,10 +1051,13 @@ TEST_F(ChunkDemuxerTest, TestParseErrorDuringInit) { EXPECT_CALL(*client_, DemuxerOpened(_)); demuxer_->Initialize( &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK)); + + ASSERT_EQ(demuxer_->AddId(kSourceId, kDefaultSourceType), ChunkDemuxer::kOk); + ASSERT_TRUE(AppendInfoTracks(true, true, false)); uint8 tmp = 0; - ASSERT_TRUE(demuxer_->AppendData(&tmp, 1)); + ASSERT_TRUE(demuxer_->AppendData(kSourceId, &tmp, 1)); } } // namespace media diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc index cfcbf87..8be0aff 100644 --- a/media/filters/pipeline_integration_test.cc +++ b/media/filters/pipeline_integration_test.cc @@ -14,6 +14,9 @@ namespace media { static const unsigned char kKeyId[] = "\x11\xa5\x18\x37\xc4\x73\x84\x03\xe5\xe6\x57\xed\x8e\x06\xd9\x7c"; +static const char* kSourceId = "SourceId"; +static const char* kDefaultSourceType = "video/webm; codecs=\"vp8, vorbis\""; + // Helper class that emulates calls made on the ChunkDemuxer by the // Media Source API. class MockMediaSource : public ChunkDemuxerClient { @@ -46,7 +49,9 @@ class MockMediaSource : public ChunkDemuxerClient { DCHECK(chunk_demuxer_.get()); DCHECK_LT(current_position_, file_data_size_); DCHECK_LE(current_position_ + size, file_data_size_); - chunk_demuxer_->AppendData(file_data_.get() + current_position_, size); + CHECK(chunk_demuxer_->AppendData(kSourceId, + file_data_.get() + current_position_, + size)); current_position_ += size; } @@ -63,6 +68,7 @@ class MockMediaSource : public ChunkDemuxerClient { // ChunkDemuxerClient methods. virtual void DemuxerOpened(ChunkDemuxer* demuxer) { chunk_demuxer_ = demuxer; + chunk_demuxer_->AddId(kSourceId, kDefaultSourceType); AppendData(initial_append_size_); } diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc index 1c236fb8..77b86c2 100644 --- a/webkit/media/webmediaplayer_impl.cc +++ b/webkit/media/webmediaplayer_impl.cc @@ -645,10 +645,39 @@ void WebMediaPlayerImpl::putCurrentFrame( } } +#define COMPILE_ASSERT_MATCHING_STATUS_ENUM(webkit_name, chromium_name) \ + COMPILE_ASSERT(static_cast<int>(WebKit::WebMediaPlayer::webkit_name) == \ + static_cast<int>(media::ChunkDemuxer::chromium_name), \ + mismatching_status_enums) +COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddIdStatusOk, kOk); +COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddIdStatusNotSupported, kNotSupported); +COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddIdStatusReachedIdLimit, kReachedIdLimit); + +WebKit::WebMediaPlayer::AddIdStatus WebMediaPlayerImpl::sourceAddId( + const WebKit::WebString& id, + const WebKit::WebString& type) { + DCHECK_EQ(main_loop_, MessageLoop::current()); + return static_cast<WebKit::WebMediaPlayer::AddIdStatus>( + proxy_->DemuxerAddId(id.utf8().data(), type.utf8().data())); +} + +bool WebMediaPlayerImpl::sourceRemoveId(const WebKit::WebString& id) { + DCHECK(!id.isEmpty()); + proxy_->DemuxerRemoveId(id.utf8().data()); + return true; +} + bool WebMediaPlayerImpl::sourceAppend(const unsigned char* data, unsigned length) { + return sourceAppend(WebKit::WebString::fromUTF8("DefaultSourceId"), + data, length); +} + +bool WebMediaPlayerImpl::sourceAppend(const WebKit::WebString& id, + const unsigned char* data, + unsigned length) { DCHECK_EQ(main_loop_, MessageLoop::current()); - return proxy_->DemuxerAppend(data, length); + return proxy_->DemuxerAppend(id.utf8().data(), data, length); } void WebMediaPlayerImpl::sourceEndOfStream( diff --git a/webkit/media/webmediaplayer_impl.h b/webkit/media/webmediaplayer_impl.h index ae1e889..83c2c0d 100644 --- a/webkit/media/webmediaplayer_impl.h +++ b/webkit/media/webmediaplayer_impl.h @@ -181,7 +181,14 @@ class WebMediaPlayerImpl virtual WebKit::WebAudioSourceProvider* audioSourceProvider(); + virtual AddIdStatus sourceAddId(const WebKit::WebString& id, + const WebKit::WebString& type); + virtual bool sourceRemoveId(const WebKit::WebString& id); + // TODO(acolwell): Remove non-id version when http://webk.it/83788 fix lands. virtual bool sourceAppend(const unsigned char* data, unsigned length); + virtual bool sourceAppend(const WebKit::WebString& id, + const unsigned char* data, + unsigned length); virtual void sourceEndOfStream(EndOfStreamStatus status); virtual MediaKeyException generateKeyRequest( diff --git a/webkit/media/webmediaplayer_proxy.cc b/webkit/media/webmediaplayer_proxy.cc index f6984f0..54661d9 100644 --- a/webkit/media/webmediaplayer_proxy.cc +++ b/webkit/media/webmediaplayer_proxy.cc @@ -187,15 +187,24 @@ void WebMediaPlayerProxy::DemuxerFlush() { chunk_demuxer_->FlushData(); } -bool WebMediaPlayerProxy::DemuxerAppend(const uint8* data, size_t length) { - if (chunk_demuxer_.get()) - return chunk_demuxer_->AppendData(data, length); - return false; +media::ChunkDemuxer::Status WebMediaPlayerProxy::DemuxerAddId( + const std::string& id, + const std::string& type) { + return chunk_demuxer_->AddId(id, type); +} + +void WebMediaPlayerProxy::DemuxerRemoveId(const std::string& id) { + chunk_demuxer_->RemoveId(id); +} + +bool WebMediaPlayerProxy::DemuxerAppend(const std::string& id, + const uint8* data, + size_t length) { + return chunk_demuxer_->AppendData(id, data, length); } void WebMediaPlayerProxy::DemuxerEndOfStream(media::PipelineStatus status) { - if (chunk_demuxer_.get()) - chunk_demuxer_->EndOfStream(status); + chunk_demuxer_->EndOfStream(status); } void WebMediaPlayerProxy::DemuxerShutdown() { diff --git a/webkit/media/webmediaplayer_proxy.h b/webkit/media/webmediaplayer_proxy.h index 83fab2f..cc07306 100644 --- a/webkit/media/webmediaplayer_proxy.h +++ b/webkit/media/webmediaplayer_proxy.h @@ -10,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "media/base/pipeline.h" +#include "media/filters/chunk_demuxer.h" #include "media/filters/chunk_demuxer_client.h" #include "media/filters/ffmpeg_video_decoder.h" #include "webkit/media/buffered_data_source.h" @@ -88,7 +89,10 @@ class WebMediaPlayerProxy // Methods for Demuxer communication. void DemuxerFlush(); - bool DemuxerAppend(const uint8* data, size_t length); + media::ChunkDemuxer::Status DemuxerAddId(const std::string& id, + const std::string& type); + void DemuxerRemoveId(const std::string& id); + bool DemuxerAppend(const std::string& id, const uint8* data, size_t length); void DemuxerEndOfStream(media::PipelineStatus status); void DemuxerShutdown(); |