OLD | NEW |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |