Chromium Code Reviews| 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..f955ec6b3dd5474e2ec069f38a7d62910af292b9 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()); |
|
ddorwin
2012/06/26 23:16:20
For ISO, the initData is supposed to be the PSSH.
strobe_
2012/06/27 02:01:21
Oh, duh, that makes a lot more sense! Where's that
ddorwin
2012/07/03 21:03:46
This is based on discussions with others, though t
strobe_
2012/07/13 00:47:07
OK, comment added.
|
| +} |
| + |
| bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers, |
| BufferQueue* video_buffers, |
| bool* err) { |
| @@ -260,18 +271,41 @@ 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_.AuxInfoRequired()) { |
| + 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; |
| + scoped_ptr<DecryptConfig> decrypt_config; |
| + if (runs_.is_encrypted()) |
| + decrypt_config = runs_.GetDecryptConfig(); |
| + |
| std::vector<uint8> frame_buf(buf, buf + runs_.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()) { |
| + const int nalu_size_diff = 4 - size_of_nalu_length_; |
| + size_t expected_size = runs_.size() + |
|
ddorwin
2012/06/26 06:09:19
expected size of what?
what is runs_.size()? It se
strobe_
2012/06/27 02:01:21
size() is the size of the current sample; IV and s
|
| + decrypt_config->subsample_count() * nalu_size_diff; |
| + RCHECK(frame_buf.size() == expected_size); |
| + for (int i = 0; i < decrypt_config->subsample_count(); i++) |
| + decrypt_config->mutable_subsamples()[i].clear_bytes += nalu_size_diff; |
|
ddorwin
2012/06/26 06:09:19
Rather than mutable_subsamples, you could have an
strobe_
2012/06/27 02:01:21
Two reasons we need to mutate:
1. To convert each
ddorwin
2012/07/03 21:03:46
Since we are just passing the DecryptConfig to som
strobe_
2012/07/13 00:47:07
Done.
|
| + } |
| + |
| 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 +315,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, ¶m_sets)); |
| + frame_buf.insert(frame_buf.begin(), |
| + param_sets.begin(), param_sets.end()); |
| + if (decrypt_config.get()) { |
| + decrypt_config->mutable_subsamples()[0].clear_bytes += |
|
ddorwin
2012/06/26 06:09:19
Hmm, another mutable use. I guess it's not as simp
strobe_
2012/06/27 02:01:21
see above
|
| + param_sets.size(); |
| + } |
| parameter_sets_inserted_ = true; |
| } |
| } |
| @@ -290,6 +331,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. |