summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/base/stream_parser.h11
-rw-r--r--media/filters/chunk_demuxer.cc9
-rw-r--r--media/filters/chunk_demuxer.h1
-rw-r--r--media/filters/chunk_demuxer_client.h9
-rw-r--r--media/filters/chunk_demuxer_unittest.cc11
-rw-r--r--media/filters/pipeline_integration_test.cc24
-rw-r--r--media/webm/webm_stream_parser.cc14
-rw-r--r--media/webm/webm_stream_parser.h4
-rw-r--r--webkit/media/webmediaplayer_impl.cc7
-rw-r--r--webkit/media/webmediaplayer_impl.h1
-rw-r--r--webkit/media/webmediaplayer_proxy.cc14
-rw-r--r--webkit/media/webmediaplayer_proxy.h3
12 files changed, 100 insertions, 8 deletions
diff --git a/media/base/stream_parser.h b/media/base/stream_parser.h
index 2d71573..ef859dc 100644
--- a/media/base/stream_parser.h
+++ b/media/base/stream_parser.h
@@ -9,6 +9,7 @@
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time.h"
#include "media/base/media_export.h"
@@ -52,6 +53,13 @@ class MEDIA_EXPORT StreamParser {
// error should be signalled.
typedef base::Callback<bool(const BufferQueue&)> NewBuffersCB;
+ // A new potentially encrypted stream has been parsed.
+ // First parameter - The initialization data associated with the stream.
+ // Second parameter - Number of bytes of the initialization data.
+ // Return value - True indicates that the initialization data is accepted.
+ // False if something was wrong with the initialization data
+ // and a parsing error should be signalled.
+ typedef base::Callback<bool(scoped_array<uint8>, int)> KeyNeededCB;
// Initialize the parser with necessary callbacks. Must be called before any
// data is passed to Parse(). |init_cb| will be called once enough data has
@@ -60,7 +68,8 @@ class MEDIA_EXPORT StreamParser {
virtual void Init(const InitCB& init_cb,
const NewConfigCB& config_cb,
const NewBuffersCB& audio_cb,
- const NewBuffersCB& video_cb) = 0;
+ const NewBuffersCB& video_cb,
+ const KeyNeededCB& key_needed_cb) = 0;
// Called when a seek occurs. This flushes the current parser state
// and puts the parser in a state where it can receive data for the new seek
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc
index 9c1a6cb..f92a79e 100644
--- a/media/filters/chunk_demuxer.cc
+++ b/media/filters/chunk_demuxer.cc
@@ -363,7 +363,8 @@ void ChunkDemuxer::Initialize(DemuxerHost* host,
base::Bind(&ChunkDemuxer::OnStreamParserInitDone, this),
base::Bind(&ChunkDemuxer::OnNewConfigs, base::Unretained(this)),
base::Bind(&ChunkDemuxer::OnAudioBuffers, base::Unretained(this)),
- base::Bind(&ChunkDemuxer::OnVideoBuffers, base::Unretained(this)));
+ base::Bind(&ChunkDemuxer::OnVideoBuffers, base::Unretained(this)),
+ base::Bind(&ChunkDemuxer::OnKeyNeeded, base::Unretained(this)));
}
client_->DemuxerOpened(this);
@@ -736,4 +737,10 @@ bool ChunkDemuxer::OnVideoBuffers(const StreamParser::BufferQueue& buffers) {
return true;
}
+bool ChunkDemuxer::OnKeyNeeded(scoped_array<uint8> init_data,
+ int init_data_size) {
+ client_->KeyNeeded(init_data.Pass(), init_data_size);
+ return true;
+}
+
} // namespace media
diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h
index 0a14d48..725e9ee 100644
--- a/media/filters/chunk_demuxer.h
+++ b/media/filters/chunk_demuxer.h
@@ -91,6 +91,7 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
const VideoDecoderConfig& video_config);
bool OnAudioBuffers(const StreamParser::BufferQueue& buffer);
bool OnVideoBuffers(const StreamParser::BufferQueue& buffer);
+ bool OnKeyNeeded(scoped_array<uint8> init_data, int init_data_size);
base::Lock lock_;
State state_;
diff --git a/media/filters/chunk_demuxer_client.h b/media/filters/chunk_demuxer_client.h
index 691f81e..3fbe6e3 100644
--- a/media/filters/chunk_demuxer_client.h
+++ b/media/filters/chunk_demuxer_client.h
@@ -1,10 +1,12 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_FILTERS_CHUNK_DEMUXER_CLIENT_H_
#define MEDIA_FILTERS_CHUNK_DEMUXER_CLIENT_H_
+#include "base/memory/scoped_ptr.h"
+
namespace media {
class ChunkDemuxer;
@@ -19,6 +21,11 @@ class ChunkDemuxerClient {
// The ChunkDemuxer passed via last DemuxerOpened() call is now
// closed. Any further calls on the demuxer will result in an error.
virtual void DemuxerClosed() = 0;
+
+ // A decryption key associated with |init_data| may be needed to decrypt the
+ // media being demuxed before decoding. Note that the demuxing itself does not
+ // need decryption.
+ virtual void KeyNeeded(scoped_array<uint8> init_data, int init_data_size) = 0;
};
} // namespace media
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc
index 00669f2..0e062c3 100644
--- a/media/filters/chunk_demuxer_unittest.cc
+++ b/media/filters/chunk_demuxer_unittest.cc
@@ -14,6 +14,7 @@
using ::testing::AnyNumber;
using ::testing::InSequence;
+using ::testing::NotNull;
using ::testing::Return;
using ::testing::SetArgumentPointee;
using ::testing::_;
@@ -77,6 +78,13 @@ class MockChunkDemuxerClient : public ChunkDemuxerClient {
MOCK_METHOD1(DemuxerOpened, void(ChunkDemuxer* demuxer));
MOCK_METHOD0(DemuxerClosed, void());
+ // TODO(xhwang): This is a workaround of the issue that move-only parameters
+ // are not supported in mocked methods. Remove this when the issue is fixed.
+ // See http://code.google.com/p/googletest/issues/detail?id=395
+ MOCK_METHOD2(KeyNeededMock, void(const uint8* init_data, int init_data_size));
+ void KeyNeeded(scoped_array<uint8> init_data, int init_data_size) {
+ KeyNeededMock(init_data.get(), init_data_size);
+ }
private:
DISALLOW_COPY_AND_ASSIGN(MockChunkDemuxerClient);
@@ -346,6 +354,9 @@ TEST_F(ChunkDemuxerTest, TestInit) {
client_.reset(new MockChunkDemuxerClient());
demuxer_ = new ChunkDemuxer(client_.get());
+ if (has_video && video_content_encoded)
+ EXPECT_CALL(*client_, KeyNeededMock(NotNull(), 16));
+
ASSERT_TRUE(InitDemuxer(has_audio, has_video, video_content_encoded));
scoped_refptr<DemuxerStream> audio_stream =
diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc
index 8be0aff..5a8ec0f 100644
--- a/media/filters/pipeline_integration_test.cc
+++ b/media/filters/pipeline_integration_test.cc
@@ -33,7 +33,14 @@ class MockMediaSource : public ChunkDemuxerClient {
virtual ~MockMediaSource() {}
- const std::string& url() { return url_; }
+ void set_decryptor(AesDecryptor* decryptor) {
+ decryptor_ = decryptor;
+ }
+ AesDecryptor* decryptor() const {
+ return decryptor_;
+ }
+
+ const std::string& url() const { return url_; }
void Seek(int new_position, int seek_append_size) {
chunk_demuxer_->FlushData();
@@ -76,6 +83,16 @@ class MockMediaSource : public ChunkDemuxerClient {
chunk_demuxer_ = NULL;
}
+ virtual void KeyNeeded(scoped_array<uint8> init_data, int init_data_size) {
+ DCHECK(init_data.get());
+ DCHECK_EQ(init_data_size, 16);
+ DCHECK(decryptor());
+ // In test file bear-320x240-encrypted.webm, the decryption key is equal to
+ // |init_data|.
+ decryptor()->AddKey(init_data.get(), init_data_size,
+ init_data.get(), init_data_size);
+ }
+
private:
std::string url_;
scoped_array<uint8> file_data_;
@@ -83,6 +100,7 @@ class MockMediaSource : public ChunkDemuxerClient {
int current_position_;
int initial_append_size_;
scoped_refptr<ChunkDemuxer> chunk_demuxer_;
+ AesDecryptor* decryptor_;
};
class PipelineIntegrationTest
@@ -96,8 +114,8 @@ class PipelineIntegrationTest
base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
NetworkEventCB(), QuitOnStatusCB(PIPELINE_OK));
- decoder_->decryptor()->AddKey(kKeyId, arraysize(kKeyId) - 1,
- kKeyId, arraysize(kKeyId) - 1);
+ ASSERT_TRUE(decoder_.get());
+ source.set_decryptor(decoder_->decryptor());
message_loop_.Run();
}
diff --git a/media/webm/webm_stream_parser.cc b/media/webm/webm_stream_parser.cc
index 94e3256..8596368 100644
--- a/media/webm/webm_stream_parser.cc
+++ b/media/webm/webm_stream_parser.cc
@@ -189,18 +189,21 @@ WebMStreamParser::~WebMStreamParser() {}
void WebMStreamParser::Init(const InitCB& init_cb,
const NewConfigCB& config_cb,
const NewBuffersCB& audio_cb,
- const NewBuffersCB& video_cb) {
+ const NewBuffersCB& video_cb,
+ const KeyNeededCB& key_needed_cb) {
DCHECK_EQ(state_, kWaitingForInit);
DCHECK(init_cb_.is_null());
DCHECK(!init_cb.is_null());
DCHECK(!config_cb.is_null());
DCHECK(!audio_cb.is_null() || !video_cb.is_null());
+ DCHECK(!key_needed_cb.is_null());
ChangeState(kParsingHeaders);
init_cb_ = init_cb;
config_cb_ = config_cb;
audio_cb_ = audio_cb;
video_cb_ = video_cb;
+ key_needed_cb_ = key_needed_cb;
}
void WebMStreamParser::Flush() {
@@ -334,6 +337,15 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
config_cb_.Run(config_helper.audio_config(),config_helper.video_config());
+ // TODO(xhwang): Support decryption of audio (see http://crbug.com/123421).
+ if (tracks_parser.video_encryption_key_id()) {
+ int key_id_size = tracks_parser.video_encryption_key_id_size();
+ CHECK_GT(key_id_size, 0);
+ scoped_array<uint8> key_id(new uint8[key_id_size]);
+ memcpy(key_id.get(), tracks_parser.video_encryption_key_id(), key_id_size);
+ key_needed_cb_.Run(key_id.Pass(), key_id_size);
+ }
+
cluster_parser_.reset(new WebMClusterParser(
info_parser.timecode_scale(),
tracks_parser.audio_track_num(),
diff --git a/media/webm/webm_stream_parser.h b/media/webm/webm_stream_parser.h
index 0311297..0d37992 100644
--- a/media/webm/webm_stream_parser.h
+++ b/media/webm/webm_stream_parser.h
@@ -24,7 +24,8 @@ class WebMStreamParser : public StreamParser {
// StreamParser implementation.
virtual void Init(const InitCB& init_cb, const NewConfigCB& config_cb,
const NewBuffersCB& audio_cb,
- const NewBuffersCB& video_cb) OVERRIDE;
+ const NewBuffersCB& video_cb,
+ const KeyNeededCB& key_needed_cb) OVERRIDE;
virtual void Flush() OVERRIDE;
virtual bool Parse(const uint8* buf, int size) OVERRIDE;
@@ -62,6 +63,7 @@ class WebMStreamParser : public StreamParser {
NewConfigCB config_cb_;
NewBuffersCB audio_cb_;
NewBuffersCB video_cb_;
+ KeyNeededCB key_needed_cb_;
scoped_ptr<WebMClusterParser> cluster_parser_;
ByteQueue byte_queue_;
diff --git a/webkit/media/webmediaplayer_impl.cc b/webkit/media/webmediaplayer_impl.cc
index 2f2e22b..6ebb548 100644
--- a/webkit/media/webmediaplayer_impl.cc
+++ b/webkit/media/webmediaplayer_impl.cc
@@ -936,6 +936,13 @@ void WebMediaPlayerImpl::OnDemuxerOpened() {
GetClient()->sourceOpened();
}
+void WebMediaPlayerImpl::OnKeyNeeded(scoped_array<uint8> init_data,
+ int init_data_size) {
+ DCHECK_EQ(main_loop_, MessageLoop::current());
+
+ GetClient()->keyNeeded("", "", init_data.get(), init_data_size);
+}
+
void WebMediaPlayerImpl::SetOpaque(bool opaque) {
DCHECK_EQ(main_loop_, MessageLoop::current());
diff --git a/webkit/media/webmediaplayer_impl.h b/webkit/media/webmediaplayer_impl.h
index 83c2c0d..36a35c3 100644
--- a/webkit/media/webmediaplayer_impl.h
+++ b/webkit/media/webmediaplayer_impl.h
@@ -222,6 +222,7 @@ class WebMediaPlayerImpl
void OnPipelineError(media::PipelineStatus error);
void OnNetworkEvent(media::NetworkEvent type);
void OnDemuxerOpened();
+ void OnKeyNeeded(scoped_array<uint8> init_data, int init_data_size);
void SetOpaque(bool);
private:
diff --git a/webkit/media/webmediaplayer_proxy.cc b/webkit/media/webmediaplayer_proxy.cc
index 54661d9..81636d2 100644
--- a/webkit/media/webmediaplayer_proxy.cc
+++ b/webkit/media/webmediaplayer_proxy.cc
@@ -182,6 +182,13 @@ void WebMediaPlayerProxy::DemuxerClosed() {
&WebMediaPlayerProxy::DemuxerClosedTask, this));
}
+void WebMediaPlayerProxy::KeyNeeded(scoped_array<uint8> init_data,
+ int init_data_size) {
+ render_loop_->PostTask(FROM_HERE, base::Bind(
+ &WebMediaPlayerProxy::KeyNeededTask, this,
+ base::Passed(&init_data), init_data_size));
+}
+
void WebMediaPlayerProxy::DemuxerFlush() {
if (chunk_demuxer_.get())
chunk_demuxer_->FlushData();
@@ -224,4 +231,11 @@ void WebMediaPlayerProxy::DemuxerClosedTask() {
chunk_demuxer_ = NULL;
}
+void WebMediaPlayerProxy::KeyNeededTask(scoped_array<uint8> init_data,
+ int init_data_size) {
+ DCHECK(render_loop_->BelongsToCurrentThread());
+ if (webmediaplayer_)
+ webmediaplayer_->OnKeyNeeded(init_data.Pass(), init_data_size);
+}
+
} // namespace webkit_media
diff --git a/webkit/media/webmediaplayer_proxy.h b/webkit/media/webmediaplayer_proxy.h
index cc07306..ab1527e 100644
--- a/webkit/media/webmediaplayer_proxy.h
+++ b/webkit/media/webmediaplayer_proxy.h
@@ -86,6 +86,8 @@ class WebMediaPlayerProxy
// ChunkDemuxerClient implementation.
virtual void DemuxerOpened(media::ChunkDemuxer* demuxer) OVERRIDE;
virtual void DemuxerClosed() OVERRIDE;
+ virtual void KeyNeeded(scoped_array<uint8> init_data,
+ int init_data_size) OVERRIDE;
// Methods for Demuxer communication.
void DemuxerFlush();
@@ -98,6 +100,7 @@ class WebMediaPlayerProxy
void DemuxerOpenedTask(const scoped_refptr<media::ChunkDemuxer>& demuxer);
void DemuxerClosedTask();
+ void KeyNeededTask(scoped_array<uint8> init_data, int init_data_size);
private:
friend class base::RefCountedThreadSafe<WebMediaPlayerProxy>;