Chromium Code Reviews| 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 |