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); | |
chcunningham1
2016/08/23 01:54:32
whats the bbb stand for?
wolenetz
2016/08/23 22:51:42
Big Buck Bunny, I presume :) See the README update
servolk
2016/08/24 00:53:49
Yep, it's Big Buck Bunny. Btw, I just took a look
| |
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(), "main"); | |
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(), "main"); | |
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 |