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

Unified Diff: media/mp4/mp4_stream_parser.cc

Issue 10651006: Add Common Encryption support to BMFF, including subsample decryption. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fix another case issue Created 8 years, 6 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/mp4/mp4_stream_parser.cc
diff --git a/media/mp4/mp4_stream_parser.cc b/media/mp4/mp4_stream_parser.cc
index 4f4a6db12818e03483bb2cfd59f884b4d94714b2..88bf8bae62372ed0d81600d8911bf2fb188eb4a3 100644
--- a/media/mp4/mp4_stream_parser.cc
+++ b/media/mp4/mp4_stream_parser.cc
@@ -100,13 +100,14 @@ bool MP4StreamParser::Parse(const uint8* buf, int size) {
return false;
}
- if (!audio_buffers.empty() &&
- (audio_cb_.is_null() || !audio_cb_.Run(audio_buffers)))
- return false;
- if (!video_buffers.empty() &&
- (video_cb_.is_null() || !video_cb_.Run(video_buffers)))
- return false;
-
+ if (!audio_buffers.empty()) {
+ CHECK(!audio_cb_.is_null());
+ RCHECK(audio_cb_.Run(audio_buffers));
+ }
+ if (!video_buffers.empty()) {
+ CHECK(!video_cb_.is_null());
+ RCHECK(video_cb_.Run(video_buffers));
+ }
return true;
}
@@ -166,6 +167,7 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
// RCHECK(entry.format == FOURCC_MP4A ||
// (entry.format == FOURCC_ENCA &&
// entry.sinf.format.format == FOURCC_MP4A));
+ RCHECK(EmitKeyNeeded(entry.sinf.info.track_encryption));
const ChannelLayout layout =
AVC::ConvertAACChannelCountToChannelLayout(entry.channelcount);
@@ -181,6 +183,7 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
// RCHECK(entry.format == FOURCC_AVC1 ||
// (entry.format == FOURCC_ENCV &&
// entry.sinf.format.format == FOURCC_AVC1));
+ RCHECK(EmitKeyNeeded(entry.sinf.info.track_encryption));
// TODO(strobe): Recover correct crop box and pixel aspect ratio
video_config.Initialize(kCodecH264, H264PROFILE_MAIN, VideoFrame::YV12,
@@ -227,6 +230,14 @@ bool MP4StreamParser::ParseMoof(BoxReader* reader) {
return true;
}
+bool MP4StreamParser::EmitKeyNeeded(const TrackEncryption& track_encryption) {
+ if (!track_encryption.is_encrypted) return true;
+ scoped_array<uint8> kid(new uint8[track_encryption.default_kid.size()]);
+ memcpy(kid.get(), &track_encryption.default_kid[0],
+ track_encryption.default_kid.size());
+ return need_key_cb_.Run(kid.Pass(), track_encryption.default_kid.size());
+}
+
bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers,
BufferQueue* video_buffers,
bool* err) {
@@ -260,18 +271,45 @@ bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers,
// quite small compared to sample data, so this pattern is useful on
// memory-constrained devices where the source buffer consumes a substantial
// portion of the total system memory.
- if (runs_.NeedsCENC()) {
- queue_.PeekAt(runs_.cenc_offset() + moof_head_, &buf, &size);
- return runs_.CacheCENC(buf, size);
+ if (runs_.AuxInfoNeedsToBeCached()) {
+ queue_.PeekAt(runs_.aux_info_offset() + moof_head_, &buf, &size);
+ if (size < runs_.aux_info_size()) return false;
+ *err = !runs_.CacheAuxInfo(buf, size);
+ return !*err;
}
- queue_.PeekAt(runs_.offset() + moof_head_, &buf, &size);
- if (size < runs_.size()) return false;
+ queue_.PeekAt(runs_.sample_offset() + moof_head_, &buf, &size);
+ if (size < runs_.sample_size()) return false;
+
+ scoped_ptr<DecryptConfig> decrypt_config;
+ if (runs_.is_encrypted())
+ decrypt_config = runs_.GetDecryptConfig();
- std::vector<uint8> frame_buf(buf, buf + runs_.size());
+ std::vector<uint8> frame_buf(buf, buf + runs_.sample_size());
if (video) {
+ // TODO(strobe): move all this to separate method, add unittest
RCHECK(AVC::ConvertToAnnexB(size_of_nalu_length_, &frame_buf));
+
+ if (decrypt_config.get()) {
+ // XXX(strobe): decide how best to make these modifications
ddorwin 2012/07/03 21:03:47 TODO
strobe_ 2012/07/13 00:47:07 Sorry, "XXX" is personal shorthand for "resolve be
+ std::vector<SubsampleEntry>* subsamples =
+ decrypt_config->mutable_subsamples();
+
+ const int nalu_size_diff = 4 - size_of_nalu_length_;
+ size_t expected_size = runs_.sample_size() +
+ decrypt_config->subsamples().size() * nalu_size_diff;
+ RCHECK(frame_buf.size() == expected_size);
+ for (size_t i = 0; i < decrypt_config->subsamples().size(); i++)
+ (*subsamples)[i].clear_bytes += nalu_size_diff;
+ }
+
if (!parameter_sets_inserted_) {
+ if (!runs_.is_keyframe()) {
+ LOG(INFO) << "XXX skipping initial non-keyframe sample";
+ runs_.AdvanceSample();
+ return true;
+ }
+
const AVCDecoderConfigurationRecord* avc_config = NULL;
for (size_t t = 0; t < moov_->tracks.size(); t++) {
if (moov_->tracks[t].header.track_id == runs_.track_id()) {
@@ -281,7 +319,14 @@ bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers,
}
}
RCHECK(avc_config != NULL);
- RCHECK(AVC::InsertParameterSets(*avc_config, &frame_buf));
+ std::vector<uint8> param_sets;
+ RCHECK(AVC::ConvertParameterSets(*avc_config, &param_sets));
+ frame_buf.insert(frame_buf.begin(),
+ param_sets.begin(), param_sets.end());
+ if (decrypt_config.get()) {
+ (*decrypt_config->mutable_subsamples())[0].clear_bytes +=
+ param_sets.size();
+ }
parameter_sets_inserted_ = true;
}
}
@@ -290,6 +335,9 @@ bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers,
StreamParserBuffer::CopyFrom(&frame_buf[0], frame_buf.size(),
runs_.is_keyframe());
+ if (runs_.is_encrypted())
+ stream_buf->SetDecryptConfig(decrypt_config.Pass());
+
stream_buf->SetDuration(runs_.duration());
// We depend on the decoder performing frame reordering without reordering
// timestamps, and only provide the decode timestamp in the buffer.
@@ -299,7 +347,7 @@ bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers,
<< ", key=" << runs_.is_keyframe()
<< ", dur=" << runs_.duration().InMilliseconds()
<< ", dts=" << runs_.dts().InMilliseconds()
- << ", size=" << runs_.size();
+ << ", size=" << runs_.sample_size();
if (audio) {
audio_buffers->push_back(stream_buf);

Powered by Google App Engine
This is Rietveld 408576698