Chromium Code Reviews| 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(); |