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/webm/webm_cluster_parser.h" | 5 #include "media/formats/webm/webm_cluster_parser.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/sys_byteorder.h" | 10 #include "base/sys_byteorder.h" |
(...skipping 26 matching lines...) Expand all Loading... |
37 block_data_size_(-1), | 37 block_data_size_(-1), |
38 block_duration_(-1), | 38 block_duration_(-1), |
39 block_add_id_(-1), | 39 block_add_id_(-1), |
40 block_additional_data_size_(-1), | 40 block_additional_data_size_(-1), |
41 discard_padding_(-1), | 41 discard_padding_(-1), |
42 cluster_timecode_(-1), | 42 cluster_timecode_(-1), |
43 cluster_start_time_(kNoTimestamp()), | 43 cluster_start_time_(kNoTimestamp()), |
44 cluster_ended_(false), | 44 cluster_ended_(false), |
45 audio_(audio_track_num, false, audio_default_duration, log_cb), | 45 audio_(audio_track_num, false, audio_default_duration, log_cb), |
46 video_(video_track_num, true, video_default_duration, log_cb), | 46 video_(video_track_num, true, video_default_duration, log_cb), |
47 ready_buffer_upper_bound_(kNoTimestamp()), | 47 ready_buffer_upper_bound_(kNoDecodeTimestamp()), |
48 log_cb_(log_cb) { | 48 log_cb_(log_cb) { |
49 for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin(); | 49 for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin(); |
50 it != text_tracks.end(); | 50 it != text_tracks.end(); |
51 ++it) { | 51 ++it) { |
52 text_track_map_.insert(std::make_pair( | 52 text_track_map_.insert(std::make_pair( |
53 it->first, Track(it->first, false, kNoTimestamp(), log_cb_))); | 53 it->first, Track(it->first, false, kNoTimestamp(), log_cb_))); |
54 } | 54 } |
55 } | 55 } |
56 | 56 |
57 WebMClusterParser::~WebMClusterParser() {} | 57 WebMClusterParser::~WebMClusterParser() {} |
58 | 58 |
59 void WebMClusterParser::Reset() { | 59 void WebMClusterParser::Reset() { |
60 last_block_timecode_ = -1; | 60 last_block_timecode_ = -1; |
61 cluster_timecode_ = -1; | 61 cluster_timecode_ = -1; |
62 cluster_start_time_ = kNoTimestamp(); | 62 cluster_start_time_ = kNoTimestamp(); |
63 cluster_ended_ = false; | 63 cluster_ended_ = false; |
64 parser_.Reset(); | 64 parser_.Reset(); |
65 audio_.Reset(); | 65 audio_.Reset(); |
66 video_.Reset(); | 66 video_.Reset(); |
67 ResetTextTracks(); | 67 ResetTextTracks(); |
68 ready_buffer_upper_bound_ = kNoTimestamp(); | 68 ready_buffer_upper_bound_ = kNoDecodeTimestamp(); |
69 } | 69 } |
70 | 70 |
71 int WebMClusterParser::Parse(const uint8* buf, int size) { | 71 int WebMClusterParser::Parse(const uint8* buf, int size) { |
72 audio_.ClearReadyBuffers(); | 72 audio_.ClearReadyBuffers(); |
73 video_.ClearReadyBuffers(); | 73 video_.ClearReadyBuffers(); |
74 ClearTextTrackReadyBuffers(); | 74 ClearTextTrackReadyBuffers(); |
75 ready_buffer_upper_bound_ = kNoTimestamp(); | 75 ready_buffer_upper_bound_ = kNoDecodeTimestamp(); |
76 | 76 |
77 int result = parser_.Parse(buf, size); | 77 int result = parser_.Parse(buf, size); |
78 | 78 |
79 if (result < 0) { | 79 if (result < 0) { |
80 cluster_ended_ = false; | 80 cluster_ended_ = false; |
81 return result; | 81 return result; |
82 } | 82 } |
83 | 83 |
84 cluster_ended_ = parser_.IsParsingComplete(); | 84 cluster_ended_ = parser_.IsParsingComplete(); |
85 if (cluster_ended_) { | 85 if (cluster_ended_) { |
(...skipping 15 matching lines...) Expand all Loading... |
101 parser_.Reset(); | 101 parser_.Reset(); |
102 | 102 |
103 last_block_timecode_ = -1; | 103 last_block_timecode_ = -1; |
104 cluster_timecode_ = -1; | 104 cluster_timecode_ = -1; |
105 } | 105 } |
106 | 106 |
107 return result; | 107 return result; |
108 } | 108 } |
109 | 109 |
110 const WebMClusterParser::BufferQueue& WebMClusterParser::GetAudioBuffers() { | 110 const WebMClusterParser::BufferQueue& WebMClusterParser::GetAudioBuffers() { |
111 if (ready_buffer_upper_bound_ == kNoTimestamp()) | 111 if (ready_buffer_upper_bound_ == kNoDecodeTimestamp()) |
112 UpdateReadyBuffers(); | 112 UpdateReadyBuffers(); |
113 | 113 |
114 return audio_.ready_buffers(); | 114 return audio_.ready_buffers(); |
115 } | 115 } |
116 | 116 |
117 const WebMClusterParser::BufferQueue& WebMClusterParser::GetVideoBuffers() { | 117 const WebMClusterParser::BufferQueue& WebMClusterParser::GetVideoBuffers() { |
118 if (ready_buffer_upper_bound_ == kNoTimestamp()) | 118 if (ready_buffer_upper_bound_ == kNoDecodeTimestamp()) |
119 UpdateReadyBuffers(); | 119 UpdateReadyBuffers(); |
120 | 120 |
121 return video_.ready_buffers(); | 121 return video_.ready_buffers(); |
122 } | 122 } |
123 | 123 |
124 const WebMClusterParser::TextBufferQueueMap& | 124 const WebMClusterParser::TextBufferQueueMap& |
125 WebMClusterParser::GetTextBuffers() { | 125 WebMClusterParser::GetTextBuffers() { |
126 if (ready_buffer_upper_bound_ == kNoTimestamp()) | 126 if (ready_buffer_upper_bound_ == kNoDecodeTimestamp()) |
127 UpdateReadyBuffers(); | 127 UpdateReadyBuffers(); |
128 | 128 |
129 // Translate our |text_track_map_| into |text_buffers_map_|, inserting rows in | 129 // Translate our |text_track_map_| into |text_buffers_map_|, inserting rows in |
130 // the output only for non-empty ready_buffer() queues in |text_track_map_|. | 130 // the output only for non-empty ready_buffer() queues in |text_track_map_|. |
131 text_buffers_map_.clear(); | 131 text_buffers_map_.clear(); |
132 for (TextTrackMap::const_iterator itr = text_track_map_.begin(); | 132 for (TextTrackMap::const_iterator itr = text_track_map_.begin(); |
133 itr != text_track_map_.end(); | 133 itr != text_track_map_.end(); |
134 ++itr) { | 134 ++itr) { |
135 const BufferQueue& text_buffers = itr->second.ready_buffers(); | 135 const BufferQueue& text_buffers = itr->second.ready_buffers(); |
136 if (!text_buffers.empty()) | 136 if (!text_buffers.empty()) |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 is_video_(is_video), | 432 is_video_(is_video), |
433 default_duration_(default_duration), | 433 default_duration_(default_duration), |
434 estimated_next_frame_duration_(kNoTimestamp()), | 434 estimated_next_frame_duration_(kNoTimestamp()), |
435 log_cb_(log_cb) { | 435 log_cb_(log_cb) { |
436 DCHECK(default_duration_ == kNoTimestamp() || | 436 DCHECK(default_duration_ == kNoTimestamp() || |
437 default_duration_ > base::TimeDelta()); | 437 default_duration_ > base::TimeDelta()); |
438 } | 438 } |
439 | 439 |
440 WebMClusterParser::Track::~Track() {} | 440 WebMClusterParser::Track::~Track() {} |
441 | 441 |
442 base::TimeDelta WebMClusterParser::Track::GetReadyUpperBound() { | 442 DecodeTimestamp WebMClusterParser::Track::GetReadyUpperBound() { |
443 DCHECK(ready_buffers_.empty()); | 443 DCHECK(ready_buffers_.empty()); |
444 if (last_added_buffer_missing_duration_) | 444 if (last_added_buffer_missing_duration_) |
445 return last_added_buffer_missing_duration_->GetDecodeTimestamp(); | 445 return last_added_buffer_missing_duration_->GetDecodeTimestamp(); |
446 | 446 |
447 return kInfiniteDuration(); | 447 return DecodeTimestamp::FromPresentationTime(base::TimeDelta::Max()); |
448 } | 448 } |
449 | 449 |
450 void WebMClusterParser::Track::ExtractReadyBuffers( | 450 void WebMClusterParser::Track::ExtractReadyBuffers( |
451 const base::TimeDelta before_timestamp) { | 451 const DecodeTimestamp before_timestamp) { |
452 DCHECK(ready_buffers_.empty()); | 452 DCHECK(ready_buffers_.empty()); |
453 DCHECK(base::TimeDelta() <= before_timestamp); | 453 DCHECK(DecodeTimestamp() <= before_timestamp); |
454 DCHECK(kNoTimestamp() != before_timestamp); | 454 DCHECK(kNoDecodeTimestamp() != before_timestamp); |
455 | 455 |
456 if (buffers_.empty()) | 456 if (buffers_.empty()) |
457 return; | 457 return; |
458 | 458 |
459 if (buffers_.back()->GetDecodeTimestamp() < before_timestamp) { | 459 if (buffers_.back()->GetDecodeTimestamp() < before_timestamp) { |
460 // All of |buffers_| are ready. | 460 // All of |buffers_| are ready. |
461 ready_buffers_.swap(buffers_); | 461 ready_buffers_.swap(buffers_); |
462 DVLOG(3) << __FUNCTION__ << " : " << track_num_ << " All " | 462 DVLOG(3) << __FUNCTION__ << " : " << track_num_ << " All " |
463 << ready_buffers_.size() << " are ready: before upper bound ts " | 463 << ready_buffers_.size() << " are ready: before upper bound ts " |
464 << before_timestamp.InSecondsF(); | 464 << before_timestamp.InSecondsF(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 return true; | 572 return true; |
573 } | 573 } |
574 | 574 |
575 bool WebMClusterParser::Track::QueueBuffer( | 575 bool WebMClusterParser::Track::QueueBuffer( |
576 const scoped_refptr<StreamParserBuffer>& buffer) { | 576 const scoped_refptr<StreamParserBuffer>& buffer) { |
577 DCHECK(!last_added_buffer_missing_duration_); | 577 DCHECK(!last_added_buffer_missing_duration_); |
578 | 578 |
579 // WebMClusterParser::OnBlock() gives MEDIA_LOG and parse error on decreasing | 579 // WebMClusterParser::OnBlock() gives MEDIA_LOG and parse error on decreasing |
580 // block timecode detection within a cluster. Therefore, we should not see | 580 // block timecode detection within a cluster. Therefore, we should not see |
581 // those here. | 581 // those here. |
582 base::TimeDelta previous_buffers_timestamp = buffers_.empty() ? | 582 DecodeTimestamp previous_buffers_timestamp = buffers_.empty() ? |
583 base::TimeDelta() : buffers_.back()->GetDecodeTimestamp(); | 583 DecodeTimestamp() : buffers_.back()->GetDecodeTimestamp(); |
584 CHECK(previous_buffers_timestamp <= buffer->GetDecodeTimestamp()); | 584 CHECK(previous_buffers_timestamp <= buffer->GetDecodeTimestamp()); |
585 | 585 |
586 base::TimeDelta duration = buffer->duration(); | 586 base::TimeDelta duration = buffer->duration(); |
587 if (duration < base::TimeDelta() || duration == kNoTimestamp()) { | 587 if (duration < base::TimeDelta() || duration == kNoTimestamp()) { |
588 MEDIA_LOG(log_cb_) << "Invalid buffer duration: " << duration.InSecondsF(); | 588 MEDIA_LOG(log_cb_) << "Invalid buffer duration: " << duration.InSecondsF(); |
589 return false; | 589 return false; |
590 } | 590 } |
591 | 591 |
592 // The estimated frame duration is the minimum non-zero duration since the | 592 // The estimated frame duration is the minimum non-zero duration since the |
593 // last initialization segment. The minimum is used to ensure frame durations | 593 // last initialization segment. The minimum is used to ensure frame durations |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 void WebMClusterParser::ResetTextTracks() { | 637 void WebMClusterParser::ResetTextTracks() { |
638 ClearTextTrackReadyBuffers(); | 638 ClearTextTrackReadyBuffers(); |
639 for (TextTrackMap::iterator it = text_track_map_.begin(); | 639 for (TextTrackMap::iterator it = text_track_map_.begin(); |
640 it != text_track_map_.end(); | 640 it != text_track_map_.end(); |
641 ++it) { | 641 ++it) { |
642 it->second.Reset(); | 642 it->second.Reset(); |
643 } | 643 } |
644 } | 644 } |
645 | 645 |
646 void WebMClusterParser::UpdateReadyBuffers() { | 646 void WebMClusterParser::UpdateReadyBuffers() { |
647 DCHECK(ready_buffer_upper_bound_ == kNoTimestamp()); | 647 DCHECK(ready_buffer_upper_bound_ == kNoDecodeTimestamp()); |
648 DCHECK(text_buffers_map_.empty()); | 648 DCHECK(text_buffers_map_.empty()); |
649 | 649 |
650 if (cluster_ended_) { | 650 if (cluster_ended_) { |
651 audio_.ApplyDurationEstimateIfNeeded(); | 651 audio_.ApplyDurationEstimateIfNeeded(); |
652 video_.ApplyDurationEstimateIfNeeded(); | 652 video_.ApplyDurationEstimateIfNeeded(); |
653 // Per OnBlock(), all text buffers should already have valid durations, so | 653 // Per OnBlock(), all text buffers should already have valid durations, so |
654 // there is no need to call ApplyDurationEstimateIfNeeded() on text tracks | 654 // there is no need to call ApplyDurationEstimateIfNeeded() on text tracks |
655 // here. | 655 // here. |
656 ready_buffer_upper_bound_ = kInfiniteDuration(); | 656 ready_buffer_upper_bound_ = |
| 657 DecodeTimestamp::FromPresentationTime(base::TimeDelta::Max()); |
657 DCHECK(ready_buffer_upper_bound_ == audio_.GetReadyUpperBound()); | 658 DCHECK(ready_buffer_upper_bound_ == audio_.GetReadyUpperBound()); |
658 DCHECK(ready_buffer_upper_bound_ == video_.GetReadyUpperBound()); | 659 DCHECK(ready_buffer_upper_bound_ == video_.GetReadyUpperBound()); |
659 } else { | 660 } else { |
660 ready_buffer_upper_bound_ = std::min(audio_.GetReadyUpperBound(), | 661 ready_buffer_upper_bound_ = std::min(audio_.GetReadyUpperBound(), |
661 video_.GetReadyUpperBound()); | 662 video_.GetReadyUpperBound()); |
662 DCHECK(base::TimeDelta() <= ready_buffer_upper_bound_); | 663 DCHECK(DecodeTimestamp() <= ready_buffer_upper_bound_); |
663 DCHECK(kNoTimestamp() != ready_buffer_upper_bound_); | 664 DCHECK(kNoDecodeTimestamp() != ready_buffer_upper_bound_); |
664 } | 665 } |
665 | 666 |
666 // Prepare each track's ready buffers for retrieval. | 667 // Prepare each track's ready buffers for retrieval. |
667 audio_.ExtractReadyBuffers(ready_buffer_upper_bound_); | 668 audio_.ExtractReadyBuffers(ready_buffer_upper_bound_); |
668 video_.ExtractReadyBuffers(ready_buffer_upper_bound_); | 669 video_.ExtractReadyBuffers(ready_buffer_upper_bound_); |
669 for (TextTrackMap::iterator itr = text_track_map_.begin(); | 670 for (TextTrackMap::iterator itr = text_track_map_.begin(); |
670 itr != text_track_map_.end(); | 671 itr != text_track_map_.end(); |
671 ++itr) { | 672 ++itr) { |
672 itr->second.ExtractReadyBuffers(ready_buffer_upper_bound_); | 673 itr->second.ExtractReadyBuffers(ready_buffer_upper_bound_); |
673 } | 674 } |
674 } | 675 } |
675 | 676 |
676 WebMClusterParser::Track* | 677 WebMClusterParser::Track* |
677 WebMClusterParser::FindTextTrack(int track_num) { | 678 WebMClusterParser::FindTextTrack(int track_num) { |
678 const TextTrackMap::iterator it = text_track_map_.find(track_num); | 679 const TextTrackMap::iterator it = text_track_map_.find(track_num); |
679 | 680 |
680 if (it == text_track_map_.end()) | 681 if (it == text_track_map_.end()) |
681 return NULL; | 682 return NULL; |
682 | 683 |
683 return &it->second; | 684 return &it->second; |
684 } | 685 } |
685 | 686 |
686 } // namespace media | 687 } // namespace media |
OLD | NEW |