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

Side by Side Diff: media/formats/mp4/mp4_stream_parser_unittest.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, 3 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
« no previous file with comments | « media/formats/mp4/mp4_stream_parser.cc ('k') | media/test/data/README » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 bool NewConfigF(std::unique_ptr<MediaTracks> tracks, 118 bool NewConfigF(std::unique_ptr<MediaTracks> tracks,
119 const StreamParser::TextTrackConfigMap& tc) { 119 const StreamParser::TextTrackConfigMap& tc) {
120 configs_received_ = true; 120 configs_received_ = true;
121 CHECK(tracks.get()); 121 CHECK(tracks.get());
122 DVLOG(1) << "NewConfigF: got " << tracks->tracks().size() << " tracks"; 122 DVLOG(1) << "NewConfigF: got " << tracks->tracks().size() << " tracks";
123 for (const auto& track : tracks->tracks()) { 123 for (const auto& track : tracks->tracks()) {
124 const auto& track_id = track->bytestream_track_id(); 124 const auto& track_id = track->bytestream_track_id();
125 if (track->type() == MediaTrack::Audio) { 125 if (track->type() == MediaTrack::Audio) {
126 audio_track_id_ = track_id; 126 audio_track_id_ = track_id;
127 audio_decoder_config_ = tracks->getAudioConfig(track_id); 127 audio_decoder_config_ = tracks->getAudioConfig(track_id);
128 DVLOG(1) << "Audio track " << track_id << " config=" 128 DVLOG(1) << "track_id=" << track_id << " audio config="
129 << (audio_decoder_config_.IsValidConfig() 129 << (audio_decoder_config_.IsValidConfig()
130 ? audio_decoder_config_.AsHumanReadableString() 130 ? audio_decoder_config_.AsHumanReadableString()
131 : "INVALID"); 131 : "INVALID");
132 } else if (track->type() == MediaTrack::Video) { 132 } else if (track->type() == MediaTrack::Video) {
133 video_track_id_ = track_id; 133 video_track_id_ = track_id;
134 video_decoder_config_ = tracks->getVideoConfig(track_id); 134 video_decoder_config_ = tracks->getVideoConfig(track_id);
135 DVLOG(1) << "Video track " << track_id << " config=" 135 DVLOG(1) << "track_id=" << track_id << " video config="
136 << (video_decoder_config_.IsValidConfig() 136 << (video_decoder_config_.IsValidConfig()
137 ? video_decoder_config_.AsHumanReadableString() 137 ? video_decoder_config_.AsHumanReadableString()
138 : "INVALID"); 138 : "INVALID");
139 } 139 }
140 } 140 }
141 media_tracks_ = std::move(tracks); 141 media_tracks_ = std::move(tracks);
142 return true; 142 return true;
143 } 143 }
144 144
145 bool NewBuffersF(const StreamParser::BufferQueueMap& buffer_queue_map) { 145 bool NewBuffersF(const StreamParser::BufferQueueMap& buffer_queue_map) {
146 // Ensure that track ids are properly assigned on all emitted buffers. 146 DecodeTimestamp lowest_end_dts = kNoDecodeTimestamp();
147 for (const auto& it : buffer_queue_map) { 147 for (const auto& it : buffer_queue_map) {
148 DVLOG(3) << "Buffers for track_id=" << it.first; 148 DVLOG(3) << "Buffers for track_id=" << it.first;
149 DCHECK(!it.second.empty());
150
151 if (lowest_end_dts == kNoDecodeTimestamp() ||
152 lowest_end_dts > it.second.back()->GetDecodeTimestamp())
153 lowest_end_dts = it.second.back()->GetDecodeTimestamp();
154
149 for (const auto& buf : it.second) { 155 for (const auto& buf : it.second) {
150 DVLOG(3) << " track_id=" << buf->track_id() 156 DVLOG(3) << " track_id=" << buf->track_id()
151 << ", size=" << buf->data_size() 157 << ", size=" << buf->data_size()
152 << ", pts=" << buf->timestamp().InSecondsF() 158 << ", pts=" << buf->timestamp().InSecondsF()
153 << ", dts=" << buf->GetDecodeTimestamp().InSecondsF() 159 << ", dts=" << buf->GetDecodeTimestamp().InSecondsF()
154 << ", dur=" << buf->duration().InSecondsF(); 160 << ", dur=" << buf->duration().InSecondsF();
161 // Ensure that track ids are properly assigned on all emitted buffers.
155 EXPECT_EQ(it.first, buf->track_id()); 162 EXPECT_EQ(it.first, buf->track_id());
156 } 163 }
157 } 164 }
158 165
159 const StreamParser::BufferQueue empty_buffers; 166 EXPECT_NE(lowest_end_dts, kNoDecodeTimestamp());
160 const auto& itr_audio = buffer_queue_map.find(audio_track_id_);
161 const StreamParser::BufferQueue& audio_buffers =
162 (itr_audio == buffer_queue_map.end()) ? empty_buffers
163 : itr_audio->second;
164 167
165 const auto& itr_video = buffer_queue_map.find(video_track_id_); 168 if (lower_bound_ != kNoDecodeTimestamp() && lowest_end_dts < lower_bound_) {
166 const StreamParser::BufferQueue& video_buffers =
167 (itr_video == buffer_queue_map.end()) ? empty_buffers
168 : itr_video->second;
169
170 // Find the second highest timestamp so that we know what the
171 // timestamps on the next set of buffers must be >= than.
172 DecodeTimestamp audio = !audio_buffers.empty() ?
173 audio_buffers.back()->GetDecodeTimestamp() : kNoDecodeTimestamp();
174 DecodeTimestamp video = !video_buffers.empty() ?
175 video_buffers.back()->GetDecodeTimestamp() : kNoDecodeTimestamp();
176 DecodeTimestamp second_highest_timestamp =
177 (audio == kNoDecodeTimestamp() ||
178 (video != kNoDecodeTimestamp() && audio > video)) ? video : audio;
179
180 EXPECT_NE(second_highest_timestamp, kNoDecodeTimestamp());
181
182 if (lower_bound_ != kNoDecodeTimestamp() &&
183 second_highest_timestamp < lower_bound_) {
184 return false; 169 return false;
185 } 170 }
186 171
187 lower_bound_ = second_highest_timestamp; 172 lower_bound_ = lowest_end_dts;
188 return true; 173 return true;
189 } 174 }
190 175
191 void KeyNeededF(EmeInitDataType type, const std::vector<uint8_t>& init_data) { 176 void KeyNeededF(EmeInitDataType type, const std::vector<uint8_t>& init_data) {
192 DVLOG(1) << "KeyNeededF: " << init_data.size(); 177 DVLOG(1) << "KeyNeededF: " << init_data.size();
193 EXPECT_EQ(EmeInitDataType::CENC, type); 178 EXPECT_EQ(EmeInitDataType::CENC, type);
194 EXPECT_FALSE(init_data.empty()); 179 EXPECT_FALSE(init_data.empty());
195 } 180 }
196 181
197 void NewSegmentF() { 182 void NewSegmentF() {
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 InitializeParserWithInitParametersExpectations(params); 522 InitializeParserWithInitParametersExpectations(params);
538 523
539 scoped_refptr<DecoderBuffer> buffer = 524 scoped_refptr<DecoderBuffer> buffer =
540 ReadTestDataFile("bear-1280x720-avt_subt_frag.mp4"); 525 ReadTestDataFile("bear-1280x720-avt_subt_frag.mp4");
541 526
542 EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2")); 527 EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2"));
543 EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F")); 528 EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64001F"));
544 EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512)); 529 EXPECT_TRUE(AppendDataInPieces(buffer->data(), buffer->data_size(), 512));
545 } 530 }
546 531
532 TEST_F(MP4StreamParserTest, MultiTrackFile) {
533 auto params = GetDefaultInitParametersExpectations();
534 params.duration = base::TimeDelta::FromMilliseconds(4248);
535 params.liveness = DemuxerStream::LIVENESS_RECORDED;
536 params.detected_audio_track_count = 2;
537 params.detected_video_track_count = 2;
538 InitializeParserWithInitParametersExpectations(params);
539 EXPECT_MEDIA_LOG(VideoCodecLog("avc1.64000D")).Times(2);
540 EXPECT_MEDIA_LOG(AudioCodecLog("mp4a.40.2")).Times(2);
541 ParseMP4File("bbb-320x240-2video-2audio.mp4", 4096);
542
543 EXPECT_EQ(media_tracks_->tracks().size(), 4u);
544
545 const MediaTrack& video_track1 = *(media_tracks_->tracks()[0]);
546 EXPECT_EQ(video_track1.type(), MediaTrack::Video);
547 EXPECT_EQ(video_track1.bytestream_track_id(), 1);
548 EXPECT_EQ(video_track1.kind(), "main");
549 EXPECT_EQ(video_track1.label(), "VideoHandler");
550 EXPECT_EQ(video_track1.language(), "und");
551
552 const MediaTrack& audio_track1 = *(media_tracks_->tracks()[1]);
553 EXPECT_EQ(audio_track1.type(), MediaTrack::Audio);
554 EXPECT_EQ(audio_track1.bytestream_track_id(), 2);
555 EXPECT_EQ(audio_track1.kind(), "main");
556 EXPECT_EQ(audio_track1.label(), "SoundHandler");
557 EXPECT_EQ(audio_track1.language(), "und");
558
559 const MediaTrack& video_track2 = *(media_tracks_->tracks()[2]);
560 EXPECT_EQ(video_track2.type(), MediaTrack::Video);
561 EXPECT_EQ(video_track2.bytestream_track_id(), 3);
562 EXPECT_EQ(video_track2.kind(), "");
563 EXPECT_EQ(video_track2.label(), "VideoHandler");
564 EXPECT_EQ(video_track2.language(), "und");
565
566 const MediaTrack& audio_track2 = *(media_tracks_->tracks()[3]);
567 EXPECT_EQ(audio_track2.type(), MediaTrack::Audio);
568 EXPECT_EQ(audio_track2.bytestream_track_id(), 4);
569 EXPECT_EQ(audio_track2.kind(), "");
570 EXPECT_EQ(audio_track2.label(), "SoundHandler");
571 EXPECT_EQ(audio_track2.language(), "und");
572 }
573
547 } // namespace mp4 574 } // namespace mp4
548 } // namespace media 575 } // namespace media
OLDNEW
« no previous file with comments | « media/formats/mp4/mp4_stream_parser.cc ('k') | media/test/data/README » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698