diff options
author | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-12 01:04:33 +0000 |
---|---|---|
committer | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-12 01:04:33 +0000 |
commit | 37141711d11b09cef8405c4c2384549dad316fe9 (patch) | |
tree | 82c6e743cb9b011d5e600069ebb42e4098b1ec81 /media/webm | |
parent | 8f92ac14a5a83d336f97317a7292394f187d5c16 (diff) | |
download | chromium_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.cc | 42 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser.h | 2 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser_unittest.cc | 7 | ||||
-rw-r--r-- | media/webm/webm_stream_parser.cc | 38 | ||||
-rw-r--r-- | media/webm/webm_stream_parser.h | 3 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.cc | 42 | ||||
-rw-r--r-- | media/webm/webm_tracks_parser.h | 13 |
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); }; |