summaryrefslogtreecommitdiffstats
path: root/media/webm
diff options
context:
space:
mode:
authorxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-12 01:04:33 +0000
committerxhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-12 01:04:33 +0000
commit37141711d11b09cef8405c4c2384549dad316fe9 (patch)
tree82c6e743cb9b011d5e600069ebb42e4098b1ec81 /media/webm
parent8f92ac14a5a83d336f97317a7292394f187d5c16 (diff)
downloadchromium_src-37141711d11b09cef8405c4c2384549dad316fe9.zip
chromium_src-37141711d11b09cef8405c4c2384549dad316fe9.tar.gz
chromium_src-37141711d11b09cef8405c4c2384549dad316fe9.tar.bz2
Support encrypted audio stream in demuxer.
BUG=123421 TEST=updated media_unittest Review URL: https://chromiumcodereview.appspot.com/11088047 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@161465 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/webm')
-rw-r--r--media/webm/webm_cluster_parser.cc42
-rw-r--r--media/webm/webm_cluster_parser.h2
-rw-r--r--media/webm/webm_cluster_parser_unittest.cc7
-rw-r--r--media/webm/webm_stream_parser.cc38
-rw-r--r--media/webm/webm_stream_parser.h3
-rw-r--r--media/webm/webm_tracks_parser.cc42
-rw-r--r--media/webm/webm_tracks_parser.h13
7 files changed, 88 insertions, 59 deletions
diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc
index a6867bc0..fb1c69b 100644
--- a/media/webm/webm_cluster_parser.cc
+++ b/media/webm/webm_cluster_parser.cc
@@ -26,8 +26,10 @@ static std::string GenerateCounterBlock(uint64 iv) {
WebMClusterParser::WebMClusterParser(int64 timecode_scale,
int audio_track_num,
int video_track_num,
+ const std::string& audio_encryption_key_id,
const std::string& video_encryption_key_id)
: timecode_multiplier_(timecode_scale / 1000.0),
+ audio_encryption_key_id_(audio_encryption_key_id),
video_encryption_key_id_(video_encryption_key_id),
parser_(kWebMIdCluster, this),
last_block_timecode_(-1),
@@ -198,24 +200,34 @@ bool WebMClusterParser::OnBlock(int track_num, int timecode,
return false;
}
+ Track* track = NULL;
+ std::string encryption_key_id;
+ if (track_num == audio_.track_num()) {
+ track = &audio_;
+ encryption_key_id = audio_encryption_key_id_;
+ } else if (track_num == video_.track_num()) {
+ track = &video_;
+ encryption_key_id = video_encryption_key_id_;
+ } else {
+ DVLOG(1) << "Unexpected track number " << track_num;
+ return false;
+ }
+
last_block_timecode_ = timecode;
base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
(cluster_timecode_ + timecode) * timecode_multiplier_);
- // Every encrypted Block has a signal byte and IV prepended to it. Current
- // encrypted WebM request for comments specification is here
- // http://wiki.webmproject.org/encryption/webm-encryption-rfc
- bool is_track_encrypted =
- track_num == video_.track_num() && !video_encryption_key_id_.empty();
-
// The first bit of the flags is set when the block contains only keyframes.
// http://www.matroska.org/technical/specs/index.html
bool is_keyframe = (flags & 0x80) != 0;
scoped_refptr<StreamParserBuffer> buffer =
StreamParserBuffer::CopyFrom(data, size, is_keyframe);
- if (is_track_encrypted) {
+ // Every encrypted Block has a signal byte and IV prepended to it. Current
+ // encrypted WebM request for comments specification is here
+ // http://wiki.webmproject.org/encryption/webm-encryption-rfc
+ if (!encryption_key_id.empty()) {
uint8 signal_byte = data[0];
int data_offset = sizeof(signal_byte);
@@ -227,9 +239,8 @@ bool WebMClusterParser::OnBlock(int track_num, int timecode,
if (signal_byte & kWebMFlagEncryptedFrame) {
uint64 network_iv;
memcpy(&network_iv, data + data_offset, sizeof(network_iv));
- const uint64 iv = base::NetToHost64(network_iv);
- counter_block = GenerateCounterBlock(iv);
- data_offset += sizeof(iv);
+ data_offset += sizeof(network_iv);
+ counter_block = GenerateCounterBlock(base::NetToHost64(network_iv));
}
// TODO(fgalligan): Revisit if DecryptConfig needs to be set on unencrypted
@@ -237,7 +248,7 @@ bool WebMClusterParser::OnBlock(int track_num, int timecode,
// Unencrypted frames of potentially encrypted streams currently set
// DecryptConfig.
buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig(
- video_encryption_key_id_,
+ encryption_key_id,
counter_block,
data_offset,
std::vector<SubsampleEntry>())));
@@ -252,14 +263,7 @@ bool WebMClusterParser::OnBlock(int track_num, int timecode,
block_duration * timecode_multiplier_));
}
- if (track_num == audio_.track_num()) {
- return audio_.AddBuffer(buffer);
- } else if (track_num == video_.track_num()) {
- return video_.AddBuffer(buffer);
- }
-
- DVLOG(1) << "Unexpected track number " << track_num;
- return false;
+ return track->AddBuffer(buffer);
}
WebMClusterParser::Track::Track(int track_num)
diff --git a/media/webm/webm_cluster_parser.h b/media/webm/webm_cluster_parser.h
index 988f224..6748a28 100644
--- a/media/webm/webm_cluster_parser.h
+++ b/media/webm/webm_cluster_parser.h
@@ -22,6 +22,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
WebMClusterParser(int64 timecode_scale,
int audio_track_num,
int video_track_num,
+ const std::string& audio_encryption_key_id,
const std::string& video_encryption_key_id);
virtual ~WebMClusterParser();
@@ -74,6 +75,7 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
double timecode_multiplier_; // Multiplier used to convert timecodes into
// microseconds.
+ std::string audio_encryption_key_id_;
std::string video_encryption_key_id_;
WebMListParser parser_;
diff --git a/media/webm/webm_cluster_parser_unittest.cc b/media/webm/webm_cluster_parser_unittest.cc
index 3737e38..d12979f 100644
--- a/media/webm/webm_cluster_parser_unittest.cc
+++ b/media/webm/webm_cluster_parser_unittest.cc
@@ -121,13 +121,12 @@ static void AppendToEnd(const WebMClusterParser::BufferQueue& src,
}
}
-class WebMClusterParserTest : public testing::Test {
+class WebMClusterParserTest : public testing::Test {
public:
WebMClusterParserTest()
: parser_(new WebMClusterParser(kTimecodeScale,
- kAudioTrackNum,
- kVideoTrackNum,
- std::string())) {
+ kAudioTrackNum, kVideoTrackNum,
+ "", "")) {
}
protected:
diff --git a/media/webm/webm_stream_parser.cc b/media/webm/webm_stream_parser.cc
index b0a18e3..2e34ed9 100644
--- a/media/webm/webm_stream_parser.cc
+++ b/media/webm/webm_stream_parser.cc
@@ -351,6 +351,25 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
return -1;
}
+ bool is_audio_encrypted = !tracks_parser.audio_encryption_key_id().empty();
+ AudioDecoderConfig audio_config;
+ if (is_audio_encrypted) {
+ const AudioDecoderConfig& original_audio_config =
+ config_helper.audio_config();
+
+ audio_config.Initialize(original_audio_config.codec(),
+ original_audio_config.bits_per_channel(),
+ original_audio_config.channel_layout(),
+ original_audio_config.samples_per_second(),
+ original_audio_config.extra_data(),
+ original_audio_config.extra_data_size(),
+ is_audio_encrypted, false);
+
+ FireNeedKey(tracks_parser.audio_encryption_key_id());
+ } else {
+ audio_config.CopyFrom(config_helper.audio_config());
+ }
+
// TODO(xhwang): Support decryption of audio (see http://crbug.com/123421).
bool is_video_encrypted = !tracks_parser.video_encryption_key_id().empty();
@@ -368,18 +387,12 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
original_video_config.extra_data_size(),
is_video_encrypted, false);
- // Fire needkey event.
- std::string key_id = tracks_parser.video_encryption_key_id();
- int key_id_size = key_id.size();
- DCHECK_GT(key_id_size, 0);
- scoped_array<uint8> key_id_array(new uint8[key_id_size]);
- memcpy(key_id_array.get(), key_id.data(), key_id_size);
- need_key_cb_.Run(key_id_array.Pass(), key_id_size);
+ FireNeedKey(tracks_parser.video_encryption_key_id());
} else {
video_config.CopyFrom(config_helper.video_config());
}
- if (!config_cb_.Run(config_helper.audio_config(), video_config)) {
+ if (!config_cb_.Run(audio_config, video_config)) {
DVLOG(1) << "New config data isn't allowed.";
return -1;
}
@@ -388,6 +401,7 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
info_parser.timecode_scale(),
tracks_parser.audio_track_num(),
tracks_parser.video_track_num(),
+ tracks_parser.audio_encryption_key_id(),
tracks_parser.video_encryption_key_id()));
ChangeState(kParsingClusters);
@@ -455,4 +469,12 @@ int WebMStreamParser::ParseCluster(const uint8* data, int size) {
return bytes_parsed;
}
+void WebMStreamParser::FireNeedKey(const std::string& key_id) {
+ int key_id_size = key_id.size();
+ DCHECK_GT(key_id_size, 0);
+ scoped_array<uint8> key_id_array(new uint8[key_id_size]);
+ memcpy(key_id_array.get(), key_id.data(), key_id_size);
+ need_key_cb_.Run(key_id_array.Pass(), key_id_size);
+}
+
} // namespace media
diff --git a/media/webm/webm_stream_parser.h b/media/webm/webm_stream_parser.h
index c5d06d5..3640151 100644
--- a/media/webm/webm_stream_parser.h
+++ b/media/webm/webm_stream_parser.h
@@ -60,6 +60,9 @@ class WebMStreamParser : public StreamParser {
// Returning > 0 indicates success & the number of bytes parsed.
int ParseCluster(const uint8* data, int size);
+ // Fire needkey event through the |need_key_cb_|.
+ void FireNeedKey(const std::string& key_id);
+
State state_;
InitCB init_cb_;
NewConfigCB config_cb_;
diff --git a/media/webm/webm_tracks_parser.cc b/media/webm/webm_tracks_parser.cc
index bf039bf..7232285 100644
--- a/media/webm/webm_tracks_parser.cc
+++ b/media/webm/webm_tracks_parser.cc
@@ -25,15 +25,6 @@ WebMTracksParser::WebMTracksParser()
WebMTracksParser::~WebMTracksParser() {}
-const std::string& WebMTracksParser::video_encryption_key_id() const {
- if (!video_content_encodings_client_.get())
- return EmptyString();
-
- DCHECK(!video_content_encodings_client_->content_encodings().empty());
- return video_content_encodings_client_->content_encodings()[0]->
- encryption_key_id();
-}
-
int WebMTracksParser::Parse(const uint8* buf, int size) {
track_type_ =-1;
track_num_ = -1;
@@ -50,7 +41,6 @@ int WebMTracksParser::Parse(const uint8* buf, int size) {
return parser.IsParsingComplete() ? result : 0;
}
-
WebMParserClient* WebMTracksParser::OnListStart(int id) {
if (id == kWebMIdContentEncodings) {
DCHECK(!track_content_encodings_client_.get());
@@ -81,23 +71,29 @@ bool WebMTracksParser::OnListEnd(int id) {
return false;
}
- if (track_type_ == kWebMTrackTypeVideo) {
- video_track_num_ = track_num_;
- if (track_content_encodings_client_.get()) {
- video_content_encodings_client_ =
- track_content_encodings_client_.Pass();
- }
- } else if (track_type_ == kWebMTrackTypeAudio) {
- audio_track_num_ = track_num_;
- if (track_content_encodings_client_.get()) {
- audio_content_encodings_client_ =
- track_content_encodings_client_.Pass();
- }
- } else {
+ if (track_type_ != kWebMTrackTypeAudio &&
+ track_type_ != kWebMTrackTypeVideo) {
DVLOG(1) << "Unexpected TrackType " << track_type_;
return false;
}
+ std::string encryption_key_id;
+ if (track_content_encodings_client_.get()) {
+ DCHECK(!track_content_encodings_client_->content_encodings().empty());
+ // If we have multiple ContentEncoding in one track. Always choose the
+ // key id in the first ContentEncoding as the key id of the track.
+ encryption_key_id = track_content_encodings_client_->
+ content_encodings()[0]->encryption_key_id();
+ }
+
+ if (track_type_ == kWebMTrackTypeAudio) {
+ audio_track_num_ = track_num_;
+ audio_encryption_key_id_ = encryption_key_id;
+ } else if (track_type_ == kWebMTrackTypeVideo) {
+ video_track_num_ = track_num_;
+ video_encryption_key_id_ = encryption_key_id;
+ }
+
track_type_ = -1;
track_num_ = -1;
track_content_encodings_client_.reset();
diff --git a/media/webm/webm_tracks_parser.h b/media/webm/webm_tracks_parser.h
index 24211ed..02d43d6 100644
--- a/media/webm/webm_tracks_parser.h
+++ b/media/webm/webm_tracks_parser.h
@@ -29,8 +29,12 @@ class WebMTracksParser : public WebMParserClient {
int64 audio_track_num() const { return audio_track_num_; }
int64 video_track_num() const { return video_track_num_; }
-
- const std::string& video_encryption_key_id() const;
+ const std::string& audio_encryption_key_id() const {
+ return audio_encryption_key_id_;
+ }
+ const std::string& video_encryption_key_id() const {
+ return video_encryption_key_id_;
+ }
private:
// WebMParserClient methods
@@ -46,10 +50,9 @@ class WebMTracksParser : public WebMParserClient {
scoped_ptr<WebMContentEncodingsClient> track_content_encodings_client_;
int64 audio_track_num_;
- scoped_ptr<WebMContentEncodingsClient> audio_content_encodings_client_;
-
int64 video_track_num_;
- scoped_ptr<WebMContentEncodingsClient> video_content_encodings_client_;
+ std::string audio_encryption_key_id_;
+ std::string video_encryption_key_id_;
DISALLOW_COPY_AND_ASSIGN(WebMTracksParser);
};