Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(802)

Unified Diff: media/filters/ffmpeg_demuxer.cc

Issue 10829470: Support for parsing encrypted WebM streams by src. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase code. Add support for audio. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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();

Powered by Google App Engine
This is Rietveld 408576698