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

Unified Diff: media/formats/mp4/mp4_stream_parser.cc

Issue 2254733006: Allow MP4 parser to handle multiple audio and video tracks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@merged-buffers-map
Patch Set: CR feedback Created 4 years, 4 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
« no previous file with comments | « media/formats/mp4/mp4_stream_parser.h ('k') | media/formats/mp4/mp4_stream_parser_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/formats/mp4/mp4_stream_parser.cc
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc
index bd95afce5790351a7f3778a66ed082af8cd04460..23f2d2401636e4634fbbe9afec29c335848f6d02 100644
--- a/media/formats/mp4/mp4_stream_parser.cc
+++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -41,12 +41,8 @@ MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types,
highest_end_offset_(0),
has_audio_(false),
has_video_(false),
- audio_track_id_(0),
- video_track_id_(0),
audio_object_types_(audio_object_types),
has_sbr_(has_sbr),
- is_audio_track_encrypted_(false),
- is_video_track_encrypted_(false),
num_top_level_box_skipped_(0) {
}
@@ -186,6 +182,9 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
moov_.reset(new Movie);
RCHECK(moov_->Parse(reader));
runs_.reset();
+ audio_track_ids_.clear();
+ video_track_ids_.clear();
+ is_track_encrypted_.clear();
has_audio_ = false;
has_video_ = false;
@@ -218,8 +217,6 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
if (track->media.handler.type == kAudio) {
detected_audio_track_count++;
- if (audio_config.IsValidConfig())
- continue; // Skip other audio tracks once we found a supported one.
RCHECK(!samp_descr.audio_entries.empty());
@@ -308,20 +305,30 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
return false;
}
- is_audio_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
- DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_;
+ uint32_t audio_track_id = track->header.track_id;
+ if (audio_track_ids_.find(audio_track_id) != audio_track_ids_.end()) {
+ MEDIA_LOG(ERROR, media_log_)
+ << "Audio track with track_id=" << audio_track_id
+ << " already present.";
+ return false;
+ }
+ bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted;
+ is_track_encrypted_[audio_track_id] = is_track_encrypted;
audio_config.Initialize(
codec, sample_format, channel_layout, sample_per_second, extra_data,
- is_audio_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted(),
+ is_track_encrypted ? AesCtrEncryptionScheme() : Unencrypted(),
base::TimeDelta(), 0);
+ DVLOG(1) << "audio_track_id=" << audio_track_id
+ << " config=" << audio_config.AsHumanReadableString();
if (!audio_config.IsValidConfig()) {
MEDIA_LOG(ERROR, media_log_) << "Invalid audio decoder config: "
<< audio_config.AsHumanReadableString();
return false;
}
has_audio_ = true;
- audio_track_id_ = track->header.track_id;
- media_tracks->AddAudioTrack(audio_config, audio_track_id_, "main",
+ audio_track_ids_.insert(audio_track_id);
+ const char* track_kind = (audio_track_ids_.size() == 1 ? "main" : "");
+ media_tracks->AddAudioTrack(audio_config, audio_track_id, track_kind,
track->media.handler.name,
track->media.header.language());
continue;
@@ -329,8 +336,6 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
if (track->media.handler.type == kVideo) {
detected_video_track_count++;
- if (video_config.IsValidConfig())
- continue; // Skip other video tracks once we found a supported one.
RCHECK(!samp_descr.video_entries.empty());
if (desc_idx >= samp_descr.video_entries.size())
@@ -361,23 +366,33 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
gfx::Size(track->header.width, track->header.height);
}
- is_video_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted;
- DVLOG(1) << "is_video_track_encrypted_: " << is_video_track_encrypted_;
+ uint32_t video_track_id = track->header.track_id;
+ if (video_track_ids_.find(video_track_id) != video_track_ids_.end()) {
+ MEDIA_LOG(ERROR, media_log_)
+ << "Video track with track_id=" << video_track_id
+ << " already present.";
+ return false;
+ }
+ bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted;
+ is_track_encrypted_[video_track_id] = is_track_encrypted;
video_config.Initialize(
entry.video_codec, entry.video_codec_profile, PIXEL_FORMAT_YV12,
COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size,
// No decoder-specific buffer needed for AVC;
// SPS/PPS are embedded in the video stream
EmptyExtraData(),
- is_video_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted());
+ is_track_encrypted ? AesCtrEncryptionScheme() : Unencrypted());
+ DVLOG(1) << "video_track_id=" << video_track_id
+ << " config=" << video_config.AsHumanReadableString();
if (!video_config.IsValidConfig()) {
MEDIA_LOG(ERROR, media_log_) << "Invalid video decoder config: "
<< video_config.AsHumanReadableString();
return false;
}
has_video_ = true;
- video_track_id_ = track->header.track_id;
- media_tracks->AddVideoTrack(video_config, video_track_id_, "main",
+ video_track_ids_.insert(video_track_id);
+ const char* track_kind = (video_track_ids_.size() == 1 ? "main" : "");
+ media_tracks->AddVideoTrack(video_config, video_track_id, track_kind,
track->media.handler.name,
track->media.header.language());
continue;
@@ -514,8 +529,10 @@ bool MP4StreamParser::EnqueueSample(BufferQueueMap* buffers, bool* err) {
queue_.Peek(&buf, &buf_size);
if (!buf_size) return false;
- bool audio = has_audio_ && audio_track_id_ == runs_->track_id();
- bool video = has_video_ && video_track_id_ == runs_->track_id();
+ bool audio =
+ audio_track_ids_.find(runs_->track_id()) != audio_track_ids_.end();
+ bool video =
+ video_track_ids_.find(runs_->track_id()) != video_track_ids_.end();
// Skip this entire track if it's not one we're interested in
if (!audio && !video) {
@@ -585,8 +602,7 @@ bool MP4StreamParser::EnqueueSample(BufferQueueMap* buffers, bool* err) {
subsamples));
}
// else, use the existing config.
- } else if ((audio && is_audio_track_encrypted_) ||
- (video && is_video_track_encrypted_)) {
+ } else if (is_track_encrypted_[runs_->track_id()]) {
// The media pipeline requires a DecryptConfig with an empty |iv|.
// TODO(ddorwin): Refactor so we do not need a fake key ID ("1");
decrypt_config.reset(
@@ -596,9 +612,6 @@ bool MP4StreamParser::EnqueueSample(BufferQueueMap* buffers, bool* err) {
StreamParserBuffer::Type buffer_type = audio ? DemuxerStream::AUDIO :
DemuxerStream::VIDEO;
- // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId
- // type and allow multiple tracks for same media type, if applicable. See
- // https://crbug.com/341581.
scoped_refptr<StreamParserBuffer> stream_buf = StreamParserBuffer::CopyFrom(
&frame_buf[0], frame_buf.size(), runs_->is_keyframe(), buffer_type,
runs_->track_id());
@@ -610,7 +623,8 @@ bool MP4StreamParser::EnqueueSample(BufferQueueMap* buffers, bool* err) {
stream_buf->set_timestamp(runs_->cts());
stream_buf->SetDecodeTimestamp(runs_->dts());
- DVLOG(3) << "Pushing frame: aud=" << audio
+ DVLOG(3) << "Emit " << (audio ? "audio" : "video") << " frame: "
+ << " track_id=" << runs_->track_id()
<< ", key=" << runs_->is_keyframe()
<< ", dur=" << runs_->duration().InMilliseconds()
<< ", dts=" << runs_->dts().InMilliseconds()
« no previous file with comments | « media/formats/mp4/mp4_stream_parser.h ('k') | media/formats/mp4/mp4_stream_parser_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698