Index: media/filters/ffmpeg_demuxer.cc |
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc |
index f1b03852d63d4cc22d1f0e46979ca5462e4aac54..75a10c2e1f5a2f2549eb1e8ec741b02ac09acd94 100644 |
--- a/media/filters/ffmpeg_demuxer.cc |
+++ b/media/filters/ffmpeg_demuxer.cc |
@@ -7,6 +7,7 @@ |
#include <algorithm> |
#include <string> |
+#include "base/base64.h" |
#include "base/bind.h" |
#include "base/callback.h" |
#include "base/callback_helpers.h" |
@@ -20,12 +21,14 @@ |
#include "media/base/audio_decoder_config.h" |
#include "media/base/bind_to_loop.h" |
#include "media/base/decoder_buffer.h" |
+#include "media/base/decrypt_config.h" |
#include "media/base/limits.h" |
#include "media/base/media_switches.h" |
#include "media/base/video_decoder_config.h" |
#include "media/ffmpeg/ffmpeg_common.h" |
#include "media/filters/ffmpeg_glue.h" |
#include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h" |
+#include "media/webm/webm_crypto_helpers.h" |
namespace media { |
@@ -49,7 +52,7 @@ FFmpegDemuxerStream::FFmpegDemuxerStream( |
switch (stream->codec->codec_type) { |
case AVMEDIA_TYPE_AUDIO: |
type_ = AUDIO; |
- AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); |
+ AVStreamToAudioDecoderConfig(stream, &audio_config_); |
break; |
case AVMEDIA_TYPE_VIDEO: |
type_ = VIDEO; |
@@ -67,6 +70,26 @@ FFmpegDemuxerStream::FFmpegDemuxerStream( |
bitstream_converter_.reset( |
new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); |
} |
+ |
+ if (audio_config_.is_encrypted() || video_config_.is_encrypted()) { |
ddorwin
2013/03/10 21:29:39
Shouldn't we only check the one for this stream ty
fgalligan1
2013/03/12 00:42:42
Done. But I think having the two configs in demuxe
ddorwin
2013/03/12 04:40:06
Agreed. Not sure what the best solution is. We can
|
+ AVDictionaryEntry *key = av_dict_get(stream->metadata, "enc_key_id", NULL, |
+ 0); |
+ if (!key || !key->value) |
ddorwin
2013/03/10 21:29:39
DCHECK too?
fgalligan1
2013/03/12 00:42:42
Done.
|
+ return; |
+ base::StringPiece base64_key_id(key->value); |
+ std::string enc_key_id; |
+ base::Base64Decode(base64_key_id, &enc_key_id); |
+ if (enc_key_id.empty()) |
+ return; |
+ |
+ if (stream_->codec->codec_id == CODEC_ID_VORBIS) { |
ddorwin
2013/03/10 21:29:39
I don't think codec matters. If we read enc_key_id
fgalligan1
2013/03/12 00:42:42
The code I added to FFmpeg is not WebM specific. I
ddorwin
2013/03/12 04:40:06
In what cases would we do the wrong thing? Matrosk
|
+ audio_encryption_key_id_.assign(enc_key_id); |
+ demuxer_->FireNeedKey(kWebMEncryptInitDataType, enc_key_id); |
+ } else if (stream_->codec->codec_id == CODEC_ID_VP8) { |
+ video_encryption_key_id_.assign(enc_key_id); |
+ demuxer_->FireNeedKey(kWebMEncryptInitDataType, enc_key_id); |
+ } |
+ } |
} |
void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { |
@@ -88,6 +111,21 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { |
// into memory we control. |
scoped_refptr<DecoderBuffer> buffer; |
buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); |
+ |
+ if (type() == DemuxerStream::AUDIO && audio_config_.is_encrypted() && |
ddorwin
2013/03/10 21:29:39
I think we can collapse this to:
if (type() == Dem
fgalligan1
2013/03/12 00:42:42
Done.
|
+ stream_->codec->codec_id == CODEC_ID_VORBIS) { |
ddorwin
2013/03/10 21:29:39
Checking codecs doesn't scale. I think we may need
fgalligan1
2013/03/12 00:42:42
I removed the checks.
|
+ buffer->SetDecryptConfig(WebMCreateDecryptConfig( |
+ packet->data, packet->size, |
+ reinterpret_cast<const uint8*>(audio_encryption_key_id_.data()), |
+ audio_encryption_key_id_.size())); |
+ } else if (type() == DemuxerStream::VIDEO && video_config_.is_encrypted() && |
+ stream_->codec->codec_id == CODEC_ID_VP8) { |
+ buffer->SetDecryptConfig(WebMCreateDecryptConfig( |
+ packet->data, packet->size, |
+ reinterpret_cast<const uint8*>(video_encryption_key_id_.data()), |
+ video_encryption_key_id_.size())); |
+ } |
+ |
buffer->SetTimestamp(ConvertStreamTimestamp( |
stream_->time_base, packet->pts)); |
buffer->SetDuration(ConvertStreamTimestamp( |
@@ -231,7 +269,8 @@ base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( |
// |
FFmpegDemuxer::FFmpegDemuxer( |
const scoped_refptr<base::MessageLoopProxy>& message_loop, |
- const scoped_refptr<DataSource>& data_source) |
+ const scoped_refptr<DataSource>& data_source, |
+ const FFmpegNeedKeyCB& need_key_cb) |
: host_(NULL), |
message_loop_(message_loop), |
blocking_thread_("FFmpegDemuxer"), |
@@ -243,7 +282,8 @@ FFmpegDemuxer::FFmpegDemuxer( |
audio_disabled_(false), |
duration_known_(false), |
url_protocol_(data_source, BindToLoop(message_loop_, base::Bind( |
- &FFmpegDemuxer::OnDataSourceError, base::Unretained(this)))) { |
+ &FFmpegDemuxer::OnDataSourceError, base::Unretained(this)))), |
+ need_key_cb_(need_key_cb) { |
DCHECK(message_loop_); |
DCHECK(data_source_); |
} |
@@ -661,6 +701,14 @@ void FFmpegDemuxer::StreamHasEnded() { |
} |
} |
+void FFmpegDemuxer::FireNeedKey(const std::string& init_data_type, |
+ const std::string& encryption_key_id) { |
+ int key_id_size = encryption_key_id.size(); |
+ scoped_array<uint8> key_id_local(new uint8[key_id_size]); |
+ memcpy(key_id_local.get(), encryption_key_id.data(), key_id_size); |
+ need_key_cb_.Run(init_data_type, key_id_local.Pass(), key_id_size); |
+} |
+ |
void FFmpegDemuxer::NotifyCapacityAvailable() { |
DCHECK(message_loop_->BelongsToCurrentThread()); |
ReadFrameIfNeeded(); |