| Index: media/filters/ffmpeg_demuxer.cc
|
| diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
|
| index f1b03852d63d4cc22d1f0e46979ca5462e4aac54..ee899f0de0a0f9193514865b0834bf7fb38acef2 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 {
|
|
|
| @@ -45,15 +48,19 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(
|
| bitstream_converter_enabled_(false) {
|
| DCHECK(demuxer_);
|
|
|
| + bool is_encrypted = false;
|
| +
|
| // Determine our media format.
|
| switch (stream->codec->codec_type) {
|
| case AVMEDIA_TYPE_AUDIO:
|
| type_ = AUDIO;
|
| - AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_);
|
| + AVStreamToAudioDecoderConfig(stream, &audio_config_);
|
| + is_encrypted = audio_config_.is_encrypted();
|
| break;
|
| case AVMEDIA_TYPE_VIDEO:
|
| type_ = VIDEO;
|
| AVStreamToVideoDecoderConfig(stream, &video_config_);
|
| + is_encrypted = video_config_.is_encrypted();
|
| break;
|
| default:
|
| NOTREACHED();
|
| @@ -67,6 +74,24 @@ FFmpegDemuxerStream::FFmpegDemuxerStream(
|
| bitstream_converter_.reset(
|
| new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec));
|
| }
|
| +
|
| + if (is_encrypted) {
|
| + AVDictionaryEntry* key = av_dict_get(stream->metadata, "enc_key_id", NULL,
|
| + 0);
|
| + DCHECK(key);
|
| + DCHECK(key->value);
|
| + if (!key || !key->value)
|
| + return;
|
| + base::StringPiece base64_key_id(key->value);
|
| + std::string enc_key_id;
|
| + base::Base64Decode(base64_key_id, &enc_key_id);
|
| + DCHECK(!enc_key_id.empty());
|
| + if (enc_key_id.empty())
|
| + return;
|
| +
|
| + encryption_key_id_.assign(enc_key_id);
|
| + demuxer_->FireNeedKey(kWebMEncryptInitDataType, enc_key_id);
|
| + }
|
| }
|
|
|
| void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
|
| @@ -88,6 +113,18 @@ 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()) ||
|
| + (type() == DemuxerStream::VIDEO && video_config_.is_encrypted())) {
|
| + scoped_ptr<DecryptConfig> config(WebMCreateDecryptConfig(
|
| + packet->data, packet->size,
|
| + reinterpret_cast<const uint8*>(encryption_key_id_.data()),
|
| + encryption_key_id_.size()));
|
| + if (!config)
|
| + LOG(ERROR) << "Creation of DecryptConfig failed.";
|
| + buffer->SetDecryptConfig(config.Pass());
|
| + }
|
| +
|
| buffer->SetTimestamp(ConvertStreamTimestamp(
|
| stream_->time_base, packet->pts));
|
| buffer->SetDuration(ConvertStreamTimestamp(
|
| @@ -231,7 +268,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 +281,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 +700,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();
|
|
|