summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/filters/chunk_demuxer.cc40
-rw-r--r--media/filters/chunk_demuxer.h29
-rw-r--r--media/filters/chunk_demuxer_unittest.cc35
-rw-r--r--media/filters/pipeline_integration_test.cc8
-rw-r--r--webkit/media/webmediaplayer_impl.cc31
-rw-r--r--webkit/media/webmediaplayer_impl.h7
-rw-r--r--webkit/media/webmediaplayer_proxy.cc21
-rw-r--r--webkit/media/webmediaplayer_proxy.h6
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();