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

Side by Side Diff: media/formats/mp4/mp4_stream_parser.cc

Issue 1826583003: MSE: Record counts of detected MSE audio, video and text tracks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/formats/mp4/mp4_stream_parser.h" 5 #include "media/formats/mp4/mp4_stream_parser.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <limits> 8 #include <limits>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 moov_.reset(new Movie); 185 moov_.reset(new Movie);
186 RCHECK(moov_->Parse(reader)); 186 RCHECK(moov_->Parse(reader));
187 runs_.reset(); 187 runs_.reset();
188 188
189 has_audio_ = false; 189 has_audio_ = false;
190 has_video_ = false; 190 has_video_ = false;
191 191
192 scoped_ptr<MediaTracks> media_tracks(new MediaTracks()); 192 scoped_ptr<MediaTracks> media_tracks(new MediaTracks());
193 AudioDecoderConfig audio_config; 193 AudioDecoderConfig audio_config;
194 VideoDecoderConfig video_config; 194 VideoDecoderConfig video_config;
195 int detected_audio_track_count = 0;
196 int detected_video_track_count = 0;
197 int detected_text_track_count = 0;
195 198
196 for (std::vector<Track>::const_iterator track = moov_->tracks.begin(); 199 for (std::vector<Track>::const_iterator track = moov_->tracks.begin();
197 track != moov_->tracks.end(); ++track) { 200 track != moov_->tracks.end(); ++track) {
198 // TODO(strobe): Only the first audio and video track present in a file are 201 // TODO(strobe): Only the first audio and video track present in a file are
199 // used. (Track selection is better accomplished via Source IDs, though, so 202 // used. (Track selection is better accomplished via Source IDs, though, so
200 // adding support for track selection within a stream is low-priority.) 203 // adding support for track selection within a stream is low-priority.)
201 const SampleDescription& samp_descr = 204 const SampleDescription& samp_descr =
202 track->media.information.sample_table.description; 205 track->media.information.sample_table.description;
203 206
204 // TODO(strobe): When codec reconfigurations are supported, detect and send 207 // TODO(strobe): When codec reconfigurations are supported, detect and send
205 // a codec reconfiguration for fragments using a sample description index 208 // a codec reconfiguration for fragments using a sample description index
206 // different from the previous one 209 // different from the previous one
207 size_t desc_idx = 0; 210 size_t desc_idx = 0;
208 for (size_t t = 0; t < moov_->extends.tracks.size(); t++) { 211 for (size_t t = 0; t < moov_->extends.tracks.size(); t++) {
209 const TrackExtends& trex = moov_->extends.tracks[t]; 212 const TrackExtends& trex = moov_->extends.tracks[t];
210 if (trex.track_id == track->header.track_id) { 213 if (trex.track_id == track->header.track_id) {
211 desc_idx = trex.default_sample_description_index; 214 desc_idx = trex.default_sample_description_index;
212 break; 215 break;
213 } 216 }
214 } 217 }
215 RCHECK(desc_idx > 0); 218 RCHECK(desc_idx > 0);
216 desc_idx -= 1; // BMFF descriptor index is one-based 219 desc_idx -= 1; // BMFF descriptor index is one-based
217 220
218 if (track->media.handler.type == kAudio && !audio_config.IsValidConfig()) { 221 if (track->media.handler.type == kAudio) {
222 detected_audio_track_count++;
223 if (audio_config.IsValidConfig())
224 continue; // Skip other audio tracks once we found a supported one.
225
219 RCHECK(!samp_descr.audio_entries.empty()); 226 RCHECK(!samp_descr.audio_entries.empty());
220 227
221 // It is not uncommon to find otherwise-valid files with incorrect sample 228 // It is not uncommon to find otherwise-valid files with incorrect sample
222 // description indices, so we fail gracefully in that case. 229 // description indices, so we fail gracefully in that case.
223 if (desc_idx >= samp_descr.audio_entries.size()) 230 if (desc_idx >= samp_descr.audio_entries.size())
224 desc_idx = 0; 231 desc_idx = 0;
225 const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx]; 232 const AudioSampleEntry& entry = samp_descr.audio_entries[desc_idx];
226 const AAC& aac = entry.esds.aac; 233 const AAC& aac = entry.esds.aac;
227 234
228 // For encrypted audio streams entry.format is FOURCC_ENCA and actual 235 // For encrypted audio streams entry.format is FOURCC_ENCA and actual
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_; 314 DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_;
308 audio_config.Initialize( 315 audio_config.Initialize(
309 codec, sample_format, channel_layout, sample_per_second, extra_data, 316 codec, sample_format, channel_layout, sample_per_second, extra_data,
310 is_audio_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted(), 317 is_audio_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted(),
311 base::TimeDelta(), 0); 318 base::TimeDelta(), 0);
312 has_audio_ = true; 319 has_audio_ = true;
313 audio_track_id_ = track->header.track_id; 320 audio_track_id_ = track->header.track_id;
314 media_tracks->AddAudioTrack( 321 media_tracks->AddAudioTrack(
315 audio_config, base::UintToString(audio_track_id_), "main", 322 audio_config, base::UintToString(audio_track_id_), "main",
316 track->media.handler.name, track->media.header.language()); 323 track->media.handler.name, track->media.header.language());
324 continue;
317 } 325 }
318 if (track->media.handler.type == kVideo && !video_config.IsValidConfig()) { 326
327 if (track->media.handler.type == kVideo) {
328 detected_video_track_count++;
329 if (video_config.IsValidConfig())
330 continue; // Skip other video tracks once we found a supported one.
331
319 RCHECK(!samp_descr.video_entries.empty()); 332 RCHECK(!samp_descr.video_entries.empty());
320 if (desc_idx >= samp_descr.video_entries.size()) 333 if (desc_idx >= samp_descr.video_entries.size())
321 desc_idx = 0; 334 desc_idx = 0;
322 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx]; 335 const VideoSampleEntry& entry = samp_descr.video_entries[desc_idx];
323 336
324 if (!entry.IsFormatValid()) { 337 if (!entry.IsFormatValid()) {
325 MEDIA_LOG(ERROR, media_log_) << "Unsupported video format 0x" 338 MEDIA_LOG(ERROR, media_log_) << "Unsupported video format 0x"
326 << std::hex << entry.format 339 << std::hex << entry.format
327 << " in stsd box."; 340 << " in stsd box.";
328 return false; 341 return false;
(...skipping 23 matching lines...) Expand all
352 COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size, 365 COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size,
353 // No decoder-specific buffer needed for AVC; 366 // No decoder-specific buffer needed for AVC;
354 // SPS/PPS are embedded in the video stream 367 // SPS/PPS are embedded in the video stream
355 EmptyExtraData(), 368 EmptyExtraData(),
356 is_video_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted()); 369 is_video_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted());
357 has_video_ = true; 370 has_video_ = true;
358 video_track_id_ = track->header.track_id; 371 video_track_id_ = track->header.track_id;
359 media_tracks->AddVideoTrack( 372 media_tracks->AddVideoTrack(
360 video_config, base::UintToString(video_track_id_), "main", 373 video_config, base::UintToString(video_track_id_), "main",
361 track->media.handler.name, track->media.header.language()); 374 track->media.handler.name, track->media.header.language());
375 continue;
362 } 376 }
377
378 // TODO(wolenetz): Investigate support in MSE and Chrome MSE for CEA 608/708
379 // embedded caption data in video track. At time of init segment parsing, we
380 // don't have this data (unless maybe by SourceBuffer's mimetype).
381 // See https://crbug.com/597073
382 if (track->media.handler.type == kText)
383 detected_text_track_count++;
363 } 384 }
364 385
365 if (!moov_->pssh.empty()) 386 if (!moov_->pssh.empty())
366 OnEncryptedMediaInitData(moov_->pssh); 387 OnEncryptedMediaInitData(moov_->pssh);
367 388
368 RCHECK(config_cb_.Run(std::move(media_tracks), TextTrackConfigMap())); 389 RCHECK(config_cb_.Run(std::move(media_tracks), TextTrackConfigMap()));
369 390
370 StreamParser::InitParameters params(kInfiniteDuration()); 391 StreamParser::InitParameters params(kInfiniteDuration());
371 if (moov_->extends.header.fragment_duration > 0) { 392 if (moov_->extends.header.fragment_duration > 0) {
372 params.duration = TimeDeltaFromRational( 393 params.duration = TimeDeltaFromRational(
373 moov_->extends.header.fragment_duration, moov_->header.timescale); 394 moov_->extends.header.fragment_duration, moov_->header.timescale);
374 params.liveness = DemuxerStream::LIVENESS_RECORDED; 395 params.liveness = DemuxerStream::LIVENESS_RECORDED;
375 } else if (moov_->header.duration > 0 && 396 } else if (moov_->header.duration > 0 &&
376 moov_->header.duration != std::numeric_limits<uint64_t>::max()) { 397 moov_->header.duration != std::numeric_limits<uint64_t>::max()) {
377 params.duration = 398 params.duration =
378 TimeDeltaFromRational(moov_->header.duration, moov_->header.timescale); 399 TimeDeltaFromRational(moov_->header.duration, moov_->header.timescale);
379 params.liveness = DemuxerStream::LIVENESS_RECORDED; 400 params.liveness = DemuxerStream::LIVENESS_RECORDED;
380 } else { 401 } else {
381 // In ISO/IEC 14496-12:2005(E), 8.30.2: ".. If an MP4 file is created in 402 // In ISO/IEC 14496-12:2005(E), 8.30.2: ".. If an MP4 file is created in
382 // real-time, such as used in live streaming, it is not likely that the 403 // real-time, such as used in live streaming, it is not likely that the
383 // fragment_duration is known in advance and this (mehd) box may be 404 // fragment_duration is known in advance and this (mehd) box may be
384 // omitted." 405 // omitted."
385 // TODO(wolenetz): Investigate gating liveness detection on timeline_offset 406 // TODO(wolenetz): Investigate gating liveness detection on timeline_offset
386 // when it's populated. See http://crbug.com/312699 407 // when it's populated. See http://crbug.com/312699
387 params.liveness = DemuxerStream::LIVENESS_LIVE; 408 params.liveness = DemuxerStream::LIVENESS_LIVE;
388 } 409 }
389 410
390 DVLOG(1) << "liveness: " << params.liveness; 411 DVLOG(1) << "liveness: " << params.liveness;
391 412
392 if (!init_cb_.is_null()) 413 if (!init_cb_.is_null()) {
414 params.detected_audio_track_count = detected_audio_track_count;
415 params.detected_video_track_count = detected_video_track_count;
416 params.detected_text_track_count = detected_text_track_count;
chcunningham 2016/03/23 23:05:56 Might be good to add a test for these to mp4_strea
wolenetz 2016/03/25 23:25:08 Yup. I thought you might ask :) Verification added
wolenetz 2016/03/29 00:14:42 Done.
393 base::ResetAndReturn(&init_cb_).Run(params); 417 base::ResetAndReturn(&init_cb_).Run(params);
418 }
394 419
395 return true; 420 return true;
396 } 421 }
397 422
398 bool MP4StreamParser::ParseMoof(BoxReader* reader) { 423 bool MP4StreamParser::ParseMoof(BoxReader* reader) {
399 RCHECK(moov_.get()); // Must already have initialization segment 424 RCHECK(moov_.get()); // Must already have initialization segment
400 MovieFragment moof; 425 MovieFragment moof;
401 RCHECK(moof.Parse(reader)); 426 RCHECK(moof.Parse(reader));
402 if (!runs_) 427 if (!runs_)
403 runs_.reset(new TrackRunIterator(moov_.get(), media_log_)); 428 runs_.reset(new TrackRunIterator(moov_.get(), media_log_));
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
668 runs.AdvanceSample(); 693 runs.AdvanceSample();
669 } 694 }
670 runs.AdvanceRun(); 695 runs.AdvanceRun();
671 } 696 }
672 697
673 return true; 698 return true;
674 } 699 }
675 700
676 } // namespace mp4 701 } // namespace mp4
677 } // namespace media 702 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698