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 | 8 |
9 #include <limits> | 9 #include <limits> |
10 #include <memory> | 10 #include <memory> |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 } | 94 } |
95 | 95 |
96 bool MP4StreamParser::Parse(const uint8_t* buf, int size) { | 96 bool MP4StreamParser::Parse(const uint8_t* buf, int size) { |
97 DCHECK_NE(state_, kWaitingForInit); | 97 DCHECK_NE(state_, kWaitingForInit); |
98 | 98 |
99 if (state_ == kError) | 99 if (state_ == kError) |
100 return false; | 100 return false; |
101 | 101 |
102 queue_.Push(buf, size); | 102 queue_.Push(buf, size); |
103 | 103 |
104 BufferQueue audio_buffers; | 104 BufferQueueMap buffers; |
105 BufferQueue video_buffers; | |
106 | 105 |
107 bool result = false; | 106 bool result = false; |
108 bool err = false; | 107 bool err = false; |
109 | 108 |
110 do { | 109 do { |
111 switch (state_) { | 110 switch (state_) { |
112 case kWaitingForInit: | 111 case kWaitingForInit: |
113 case kError: | 112 case kError: |
114 NOTREACHED(); | 113 NOTREACHED(); |
115 return false; | 114 return false; |
116 | 115 |
117 case kParsingBoxes: | 116 case kParsingBoxes: |
118 result = ParseBox(&err); | 117 result = ParseBox(&err); |
119 break; | 118 break; |
120 | 119 |
121 case kWaitingForSampleData: | 120 case kWaitingForSampleData: |
122 result = HaveEnoughDataToEnqueueSamples(); | 121 result = HaveEnoughDataToEnqueueSamples(); |
123 if (result) | 122 if (result) |
124 ChangeState(kEmittingSamples); | 123 ChangeState(kEmittingSamples); |
125 break; | 124 break; |
126 | 125 |
127 case kEmittingSamples: | 126 case kEmittingSamples: |
128 result = EnqueueSample(&audio_buffers, &video_buffers, &err); | 127 result = EnqueueSample(&buffers, &err); |
129 if (result) { | 128 if (result) { |
130 int64_t max_clear = runs_->GetMaxClearOffset() + moof_head_; | 129 int64_t max_clear = runs_->GetMaxClearOffset() + moof_head_; |
131 err = !ReadAndDiscardMDATsUntil(max_clear); | 130 err = !ReadAndDiscardMDATsUntil(max_clear); |
132 } | 131 } |
133 break; | 132 break; |
134 } | 133 } |
135 } while (result && !err); | 134 } while (result && !err); |
136 | 135 |
137 if (!err) | 136 if (!err) |
138 err = !SendAndFlushSamples(&audio_buffers, &video_buffers); | 137 err = !SendAndFlushSamples(&buffers); |
139 | 138 |
140 if (err) { | 139 if (err) { |
141 DLOG(ERROR) << "Error while parsing MP4"; | 140 DLOG(ERROR) << "Error while parsing MP4"; |
142 moov_.reset(); | 141 moov_.reset(); |
143 Reset(); | 142 Reset(); |
144 ChangeState(kError); | 143 ChangeState(kError); |
145 return false; | 144 return false; |
146 } | 145 } |
147 | 146 |
148 return true; | 147 return true; |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 // not required to use subsample encryption, so we may need to add an entry. | 478 // not required to use subsample encryption, so we may need to add an entry. |
480 if (subsamples->empty()) { | 479 if (subsamples->empty()) { |
481 subsamples->push_back(SubsampleEntry( | 480 subsamples->push_back(SubsampleEntry( |
482 kADTSHeaderMinSize, frame_buf->size() - kADTSHeaderMinSize)); | 481 kADTSHeaderMinSize, frame_buf->size() - kADTSHeaderMinSize)); |
483 } else { | 482 } else { |
484 (*subsamples)[0].clear_bytes += kADTSHeaderMinSize; | 483 (*subsamples)[0].clear_bytes += kADTSHeaderMinSize; |
485 } | 484 } |
486 return true; | 485 return true; |
487 } | 486 } |
488 | 487 |
489 bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers, | 488 bool MP4StreamParser::EnqueueSample(BufferQueueMap* buffers, bool* err) { |
490 BufferQueue* video_buffers, | |
491 bool* err) { | |
492 DCHECK_EQ(state_, kEmittingSamples); | 489 DCHECK_EQ(state_, kEmittingSamples); |
493 | 490 |
494 if (!runs_->IsRunValid()) { | 491 if (!runs_->IsRunValid()) { |
495 // Flush any buffers we've gotten in this chunk so that buffers don't | 492 // Flush any buffers we've gotten in this chunk so that buffers don't |
496 // cross |new_segment_cb_| calls | 493 // cross |new_segment_cb_| calls |
497 *err = !SendAndFlushSamples(audio_buffers, video_buffers); | 494 *err = !SendAndFlushSamples(buffers); |
498 if (*err) | 495 if (*err) |
499 return false; | 496 return false; |
500 | 497 |
501 // Remain in kEmittingSamples state, discarding data, until the end of | 498 // Remain in kEmittingSamples state, discarding data, until the end of |
502 // the current 'mdat' box has been appended to the queue. | 499 // the current 'mdat' box has been appended to the queue. |
503 if (!queue_.Trim(mdat_tail_)) | 500 if (!queue_.Trim(mdat_tail_)) |
504 return false; | 501 return false; |
505 | 502 |
506 ChangeState(kParsingBoxes); | 503 ChangeState(kParsingBoxes); |
507 end_of_segment_cb_.Run(); | 504 end_of_segment_cb_.Run(); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 stream_buf->set_timestamp(runs_->cts()); | 613 stream_buf->set_timestamp(runs_->cts()); |
617 stream_buf->SetDecodeTimestamp(runs_->dts()); | 614 stream_buf->SetDecodeTimestamp(runs_->dts()); |
618 | 615 |
619 DVLOG(3) << "Pushing frame: aud=" << audio | 616 DVLOG(3) << "Pushing frame: aud=" << audio |
620 << ", key=" << runs_->is_keyframe() | 617 << ", key=" << runs_->is_keyframe() |
621 << ", dur=" << runs_->duration().InMilliseconds() | 618 << ", dur=" << runs_->duration().InMilliseconds() |
622 << ", dts=" << runs_->dts().InMilliseconds() | 619 << ", dts=" << runs_->dts().InMilliseconds() |
623 << ", cts=" << runs_->cts().InMilliseconds() | 620 << ", cts=" << runs_->cts().InMilliseconds() |
624 << ", size=" << runs_->sample_size(); | 621 << ", size=" << runs_->sample_size(); |
625 | 622 |
626 if (audio) { | 623 (*buffers)[runs_->track_id()].push_back(stream_buf); |
627 audio_buffers->push_back(stream_buf); | |
628 } else { | |
629 video_buffers->push_back(stream_buf); | |
630 } | |
631 | |
632 runs_->AdvanceSample(); | 624 runs_->AdvanceSample(); |
633 return true; | 625 return true; |
634 } | 626 } |
635 | 627 |
636 bool MP4StreamParser::SendAndFlushSamples(BufferQueue* audio_buffers, | 628 bool MP4StreamParser::SendAndFlushSamples(BufferQueueMap* buffers) { |
637 BufferQueue* video_buffers) { | 629 if (buffers->empty()) |
638 if (audio_buffers->empty() && video_buffers->empty()) | |
639 return true; | 630 return true; |
640 | 631 bool success = new_buffers_cb_.Run(*buffers); |
641 TextBufferQueueMap empty_text_map; | 632 buffers->clear(); |
642 bool success = new_buffers_cb_.Run(*audio_buffers, | |
643 *video_buffers, | |
644 empty_text_map); | |
645 audio_buffers->clear(); | |
646 video_buffers->clear(); | |
647 return success; | 633 return success; |
648 } | 634 } |
649 | 635 |
650 bool MP4StreamParser::ReadAndDiscardMDATsUntil(int64_t max_clear_offset) { | 636 bool MP4StreamParser::ReadAndDiscardMDATsUntil(int64_t max_clear_offset) { |
651 bool err = false; | 637 bool err = false; |
652 int64_t upper_bound = std::min(max_clear_offset, queue_.tail()); | 638 int64_t upper_bound = std::min(max_clear_offset, queue_.tail()); |
653 while (mdat_tail_ < upper_bound) { | 639 while (mdat_tail_ < upper_bound) { |
654 const uint8_t* buf = NULL; | 640 const uint8_t* buf = NULL; |
655 int size = 0; | 641 int size = 0; |
656 queue_.PeekAt(mdat_tail_, &buf, &size); | 642 queue_.PeekAt(mdat_tail_, &buf, &size); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 runs.AdvanceSample(); | 693 runs.AdvanceSample(); |
708 } | 694 } |
709 runs.AdvanceRun(); | 695 runs.AdvanceRun(); |
710 } | 696 } |
711 | 697 |
712 return true; | 698 return true; |
713 } | 699 } |
714 | 700 |
715 } // namespace mp4 | 701 } // namespace mp4 |
716 } // namespace media | 702 } // namespace media |
OLD | NEW |