Home | History | Annotate | Download | only in filters
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/filters/chunk_demuxer.h"
      6 
      7 #include <algorithm>
      8 #include <limits>
      9 #include <list>
     10 
     11 #include "base/bind.h"
     12 #include "base/callback_helpers.h"
     13 #include "base/location.h"
     14 #include "base/message_loop/message_loop_proxy.h"
     15 #include "base/stl_util.h"
     16 #include "media/base/audio_decoder_config.h"
     17 #include "media/base/bind_to_current_loop.h"
     18 #include "media/base/stream_parser_buffer.h"
     19 #include "media/base/video_decoder_config.h"
     20 #include "media/filters/frame_processor.h"
     21 #include "media/filters/stream_parser_factory.h"
     22 
     23 using base::TimeDelta;
     24 
     25 namespace media {
     26 
     27 static TimeDelta EndTimestamp(const StreamParser::BufferQueue& queue) {
     28   return queue.back()->timestamp() + queue.back()->duration();
     29 }
     30 
     31 // List of time ranges for each SourceBuffer.
     32 typedef std::list<Ranges<TimeDelta> > RangesList;
     33 static Ranges<TimeDelta> ComputeIntersection(const RangesList& activeRanges,
     34                                              bool ended) {
     35   // Implementation of HTMLMediaElement.buffered algorithm in MSE spec.
     36   // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#dom-htmlmediaelement.buffered
     37 
     38   // Step 1: If activeSourceBuffers.length equals 0 then return an empty
     39   //  TimeRanges object and abort these steps.
     40   if (activeRanges.empty())
     41     return Ranges<TimeDelta>();
     42 
     43   // Step 2: Let active ranges be the ranges returned by buffered for each
     44   //  SourceBuffer object in activeSourceBuffers.
     45   // Step 3: Let highest end time be the largest range end time in the active
     46   //  ranges.
     47   TimeDelta highest_end_time;
     48   for (RangesList::const_iterator itr = activeRanges.begin();
     49        itr != activeRanges.end(); ++itr) {
     50     if (!itr->size())
     51       continue;
     52 
     53     highest_end_time = std::max(highest_end_time, itr->end(itr->size() - 1));
     54   }
     55 
     56   // Step 4: Let intersection ranges equal a TimeRange object containing a
     57   //  single range from 0 to highest end time.
     58   Ranges<TimeDelta> intersection_ranges;
     59   intersection_ranges.Add(TimeDelta(), highest_end_time);
     60 
     61   // Step 5: For each SourceBuffer object in activeSourceBuffers run the
     62   //  following steps:
     63   for (RangesList::const_iterator itr = activeRanges.begin();
     64        itr != activeRanges.end(); ++itr) {
     65     // Step 5.1: Let source ranges equal the ranges returned by the buffered
     66     //  attribute on the current SourceBuffer.
     67     Ranges<TimeDelta> source_ranges = *itr;
     68 
     69     // Step 5.2: If readyState is "ended", then set the end time on the last
     70     //  range in source ranges to highest end time.
     71     if (ended && source_ranges.size() > 0u) {
     72       source_ranges.Add(source_ranges.start(source_ranges.size() - 1),
     73                         highest_end_time);
     74     }
     75 
     76     // Step 5.3: Let new intersection ranges equal the intersection between
     77     // the intersection ranges and the source ranges.
     78     // Step 5.4: Replace the ranges in intersection ranges with the new
     79     // intersection ranges.
     80     intersection_ranges = intersection_ranges.IntersectionWith(source_ranges);
     81   }
     82 
     83   return intersection_ranges;
     84 }
     85 
     86 // Contains state belonging to a source id.
     87 class SourceState {
     88  public:
     89   // Callback signature used to create ChunkDemuxerStreams.
     90   typedef base::Callback<ChunkDemuxerStream*(
     91       DemuxerStream::Type)> CreateDemuxerStreamCB;
     92 
     93   typedef base::Callback<void(
     94       ChunkDemuxerStream*, const TextTrackConfig&)> NewTextTrackCB;
     95 
     96   SourceState(
     97       scoped_ptr<StreamParser> stream_parser,
     98       scoped_ptr<FrameProcessor> frame_processor, const LogCB& log_cb,
     99       const CreateDemuxerStreamCB& create_demuxer_stream_cb);
    100 
    101   ~SourceState();
    102 
    103   void Init(const StreamParser::InitCB& init_cb,
    104             bool allow_audio,
    105             bool allow_video,
    106             const StreamParser::NeedKeyCB& need_key_cb,
    107             const NewTextTrackCB& new_text_track_cb);
    108 
    109   // Appends new data to the StreamParser.
    110   // Returns true if the data was successfully appended. Returns false if an
    111   // error occurred. |*timestamp_offset| is used and possibly updated by the
    112   // append. |append_window_start| and |append_window_end| correspond to the MSE
    113   // spec's similarly named source buffer attributes that are used in coded
    114   // frame processing.
    115   bool Append(const uint8* data, size_t length,
    116               TimeDelta append_window_start,
    117               TimeDelta append_window_end,
    118               TimeDelta* timestamp_offset);
    119 
    120   // Aborts the current append sequence and resets the parser.
    121   void Abort(TimeDelta append_window_start,
    122              TimeDelta append_window_end,
    123              TimeDelta* timestamp_offset);
    124 
    125   // Calls Remove(|start|, |end|, |duration|) on all
    126   // ChunkDemuxerStreams managed by this object.
    127   void Remove(TimeDelta start, TimeDelta end, TimeDelta duration);
    128 
    129   // Returns true if currently parsing a media segment, or false otherwise.
    130   bool parsing_media_segment() const { return parsing_media_segment_; }
    131 
    132   // Sets |frame_processor_|'s sequence mode to |sequence_mode|.
    133   void SetSequenceMode(bool sequence_mode);
    134 
    135   // Signals the coded frame processor to update its group start timestamp to be
    136   // |timestamp_offset| if it is in sequence append mode.
    137   void SetGroupStartTimestampIfInSequenceMode(base::TimeDelta timestamp_offset);
    138 
    139   // Returns the range of buffered data in this source, capped at |duration|.
    140   // |ended| - Set to true if end of stream has been signaled and the special
    141   // end of stream range logic needs to be executed.
    142   Ranges<TimeDelta> GetBufferedRanges(TimeDelta duration, bool ended) const;
    143 
    144   // Returns the highest buffered duration across all streams managed
    145   // by this object.
    146   // Returns TimeDelta() if none of the streams contain buffered data.
    147   TimeDelta GetMaxBufferedDuration() const;
    148 
    149   // Helper methods that call methods with similar names on all the
    150   // ChunkDemuxerStreams managed by this object.
    151   void StartReturningData();
    152   void AbortReads();
    153   void Seek(TimeDelta seek_time);
    154   void CompletePendingReadIfPossible();
    155   void OnSetDuration(TimeDelta duration);
    156   void MarkEndOfStream();
    157   void UnmarkEndOfStream();
    158   void Shutdown();
    159   // Sets the memory limit on each stream. |memory_limit| is the
    160   // maximum number of bytes each stream is allowed to hold in its buffer.
    161   void SetMemoryLimitsForTesting(int memory_limit);
    162   bool IsSeekWaitingForData() const;
    163 
    164  private:
    165   // Called by the |stream_parser_| when a new initialization segment is
    166   // encountered.
    167   // Returns true on a successful call. Returns false if an error occurred while
    168   // processing decoder configurations.
    169   bool OnNewConfigs(bool allow_audio, bool allow_video,
    170                     const AudioDecoderConfig& audio_config,
    171                     const VideoDecoderConfig& video_config,
    172                     const StreamParser::TextTrackConfigMap& text_configs);
    173 
    174   // Called by the |stream_parser_| at the beginning of a new media segment.
    175   void OnNewMediaSegment();
    176 
    177   // Called by the |stream_parser_| at the end of a media segment.
    178   void OnEndOfMediaSegment();
    179 
    180   // Called by the |stream_parser_| when new buffers have been parsed.
    181   // It processes the new buffers using |frame_processor_|, which includes
    182   // appending the processed frames to associated demuxer streams for each
    183   // frame's track.
    184   // Returns true on a successful call. Returns false if an error occurred while
    185   // processing the buffers.
    186   bool OnNewBuffers(const StreamParser::BufferQueue& audio_buffers,
    187                     const StreamParser::BufferQueue& video_buffers,
    188                     const StreamParser::TextBufferQueueMap& text_map);
    189 
    190   void OnSourceInitDone(bool success,
    191                         const StreamParser::InitParameters& params);
    192 
    193   CreateDemuxerStreamCB create_demuxer_stream_cb_;
    194   NewTextTrackCB new_text_track_cb_;
    195 
    196   // During Append(), if OnNewBuffers() coded frame processing updates the
    197   // timestamp offset then |*timestamp_offset_during_append_| is also updated
    198   // so Append()'s caller can know the new offset. This pointer is only non-NULL
    199   // during the lifetime of an Append() call.
    200   TimeDelta* timestamp_offset_during_append_;
    201 
    202   // During Append(), coded frame processing triggered by OnNewBuffers()
    203   // requires these two attributes. These are only valid during the lifetime of
    204   // an Append() call.
    205   TimeDelta append_window_start_during_append_;
    206   TimeDelta append_window_end_during_append_;
    207 
    208   // Set to true if the next buffers appended within the append window
    209   // represent the start of a new media segment. This flag being set
    210   // triggers a call to |new_segment_cb_| when the new buffers are
    211   // appended. The flag is set on actual media segment boundaries and
    212   // when the "append window" filtering causes discontinuities in the
    213   // appended data.
    214   // TODO(wolenetz/acolwell): Investigate if we need this, or if coded frame
    215   // processing's discontinuity logic is enough. See http://crbug.com/351489.
    216   bool new_media_segment_;
    217 
    218   // Keeps track of whether a media segment is being parsed.
    219   bool parsing_media_segment_;
    220 
    221   // The object used to parse appended data.
    222   scoped_ptr<StreamParser> stream_parser_;
    223 
    224   ChunkDemuxerStream* audio_;  // Not owned by |this|.
    225   ChunkDemuxerStream* video_;  // Not owned by |this|.
    226 
    227   typedef std::map<StreamParser::TrackId, ChunkDemuxerStream*> TextStreamMap;
    228   TextStreamMap text_stream_map_;  // |this| owns the map's stream pointers.
    229 
    230   scoped_ptr<FrameProcessor> frame_processor_;
    231   LogCB log_cb_;
    232   StreamParser::InitCB init_cb_;
    233 
    234   // Indicates that timestampOffset should be updated automatically during
    235   // OnNewBuffers() based on the earliest end timestamp of the buffers provided.
    236   // TODO(wolenetz): Refactor this function while integrating April 29, 2014
    237   // changes to MSE spec. See http://crbug.com/371499.
    238   bool auto_update_timestamp_offset_;
    239 
    240   DISALLOW_COPY_AND_ASSIGN(SourceState);
    241 };
    242 
    243 SourceState::SourceState(scoped_ptr<StreamParser> stream_parser,
    244                          scoped_ptr<FrameProcessor> frame_processor,
    245                          const LogCB& log_cb,
    246                          const CreateDemuxerStreamCB& create_demuxer_stream_cb)
    247     : create_demuxer_stream_cb_(create_demuxer_stream_cb),
    248       timestamp_offset_during_append_(NULL),
    249       new_media_segment_(false),
    250       parsing_media_segment_(false),
    251       stream_parser_(stream_parser.release()),
    252       audio_(NULL),
    253       video_(NULL),
    254       frame_processor_(frame_processor.release()),
    255       log_cb_(log_cb),
    256       auto_update_timestamp_offset_(false) {
    257   DCHECK(!create_demuxer_stream_cb_.is_null());
    258   DCHECK(frame_processor_);
    259 }
    260 
    261 SourceState::~SourceState() {
    262   Shutdown();
    263 
    264   STLDeleteValues(&text_stream_map_);
    265 }
    266 
    267 void SourceState::Init(const StreamParser::InitCB& init_cb,
    268                        bool allow_audio,
    269                        bool allow_video,
    270                        const StreamParser::NeedKeyCB& need_key_cb,
    271                        const NewTextTrackCB& new_text_track_cb) {
    272   new_text_track_cb_ = new_text_track_cb;
    273   init_cb_ = init_cb;
    274 
    275   stream_parser_->Init(
    276       base::Bind(&SourceState::OnSourceInitDone, base::Unretained(this)),
    277       base::Bind(&SourceState::OnNewConfigs,
    278                  base::Unretained(this),
    279                  allow_audio,
    280                  allow_video),
    281       base::Bind(&SourceState::OnNewBuffers, base::Unretained(this)),
    282       new_text_track_cb_.is_null(),
    283       need_key_cb,
    284       base::Bind(&SourceState::OnNewMediaSegment, base::Unretained(this)),
    285       base::Bind(&SourceState::OnEndOfMediaSegment, base::Unretained(this)),
    286       log_cb_);
    287 }
    288 
    289 void SourceState::SetSequenceMode(bool sequence_mode) {
    290   DCHECK(!parsing_media_segment_);
    291 
    292   frame_processor_->SetSequenceMode(sequence_mode);
    293 }
    294 
    295 void SourceState::SetGroupStartTimestampIfInSequenceMode(
    296     base::TimeDelta timestamp_offset) {
    297   DCHECK(!parsing_media_segment_);
    298 
    299   frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset);
    300 }
    301 
    302 bool SourceState::Append(const uint8* data, size_t length,
    303                          TimeDelta append_window_start,
    304                          TimeDelta append_window_end,
    305                          TimeDelta* timestamp_offset) {
    306   DCHECK(timestamp_offset);
    307   DCHECK(!timestamp_offset_during_append_);
    308   append_window_start_during_append_ = append_window_start;
    309   append_window_end_during_append_ = append_window_end;
    310   timestamp_offset_during_append_ = timestamp_offset;
    311 
    312   // TODO(wolenetz/acolwell): Curry and pass a NewBuffersCB here bound with
    313   // append window and timestamp offset pointer. See http://crbug.com/351454.
    314   bool err = stream_parser_->Parse(data, length);
    315   timestamp_offset_during_append_ = NULL;
    316   return err;
    317 }
    318 
    319 void SourceState::Abort(TimeDelta append_window_start,
    320                         TimeDelta append_window_end,
    321                         base::TimeDelta* timestamp_offset) {
    322   DCHECK(timestamp_offset);
    323   DCHECK(!timestamp_offset_during_append_);
    324   timestamp_offset_during_append_ = timestamp_offset;
    325   append_window_start_during_append_ = append_window_start;
    326   append_window_end_during_append_ = append_window_end;
    327 
    328   stream_parser_->Flush();
    329   timestamp_offset_during_append_ = NULL;
    330 
    331   frame_processor_->Reset();
    332   parsing_media_segment_ = false;
    333 }
    334 
    335 void SourceState::Remove(TimeDelta start, TimeDelta end, TimeDelta duration) {
    336   if (audio_)
    337     audio_->Remove(start, end, duration);
    338 
    339   if (video_)
    340     video_->Remove(start, end, duration);
    341 
    342   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    343        itr != text_stream_map_.end(); ++itr) {
    344     itr->second->Remove(start, end, duration);
    345   }
    346 }
    347 
    348 Ranges<TimeDelta> SourceState::GetBufferedRanges(TimeDelta duration,
    349                                                  bool ended) const {
    350   // TODO(acolwell): When we start allowing disabled tracks we'll need to update
    351   // this code to only add ranges from active tracks.
    352   RangesList ranges_list;
    353   if (audio_)
    354     ranges_list.push_back(audio_->GetBufferedRanges(duration));
    355 
    356   if (video_)
    357     ranges_list.push_back(video_->GetBufferedRanges(duration));
    358 
    359   for (TextStreamMap::const_iterator itr = text_stream_map_.begin();
    360        itr != text_stream_map_.end(); ++itr) {
    361     ranges_list.push_back(itr->second->GetBufferedRanges(duration));
    362   }
    363 
    364   return ComputeIntersection(ranges_list, ended);
    365 }
    366 
    367 TimeDelta SourceState::GetMaxBufferedDuration() const {
    368   TimeDelta max_duration;
    369 
    370   if (audio_)
    371     max_duration = std::max(max_duration, audio_->GetBufferedDuration());
    372 
    373   if (video_)
    374     max_duration = std::max(max_duration, video_->GetBufferedDuration());
    375 
    376   for (TextStreamMap::const_iterator itr = text_stream_map_.begin();
    377        itr != text_stream_map_.end(); ++itr) {
    378     max_duration = std::max(max_duration, itr->second->GetBufferedDuration());
    379   }
    380 
    381   return max_duration;
    382 }
    383 
    384 void SourceState::StartReturningData() {
    385   if (audio_)
    386     audio_->StartReturningData();
    387 
    388   if (video_)
    389     video_->StartReturningData();
    390 
    391   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    392        itr != text_stream_map_.end(); ++itr) {
    393     itr->second->StartReturningData();
    394   }
    395 }
    396 
    397 void SourceState::AbortReads() {
    398   if (audio_)
    399     audio_->AbortReads();
    400 
    401   if (video_)
    402     video_->AbortReads();
    403 
    404   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    405        itr != text_stream_map_.end(); ++itr) {
    406     itr->second->AbortReads();
    407   }
    408 }
    409 
    410 void SourceState::Seek(TimeDelta seek_time) {
    411   if (audio_)
    412     audio_->Seek(seek_time);
    413 
    414   if (video_)
    415     video_->Seek(seek_time);
    416 
    417   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    418        itr != text_stream_map_.end(); ++itr) {
    419     itr->second->Seek(seek_time);
    420   }
    421 }
    422 
    423 void SourceState::CompletePendingReadIfPossible() {
    424   if (audio_)
    425     audio_->CompletePendingReadIfPossible();
    426 
    427   if (video_)
    428     video_->CompletePendingReadIfPossible();
    429 
    430   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    431        itr != text_stream_map_.end(); ++itr) {
    432     itr->second->CompletePendingReadIfPossible();
    433   }
    434 }
    435 
    436 void SourceState::OnSetDuration(TimeDelta duration) {
    437   if (audio_)
    438     audio_->OnSetDuration(duration);
    439 
    440   if (video_)
    441     video_->OnSetDuration(duration);
    442 
    443   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    444        itr != text_stream_map_.end(); ++itr) {
    445     itr->second->OnSetDuration(duration);
    446   }
    447 }
    448 
    449 void SourceState::MarkEndOfStream() {
    450   if (audio_)
    451     audio_->MarkEndOfStream();
    452 
    453   if (video_)
    454     video_->MarkEndOfStream();
    455 
    456   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    457        itr != text_stream_map_.end(); ++itr) {
    458     itr->second->MarkEndOfStream();
    459   }
    460 }
    461 
    462 void SourceState::UnmarkEndOfStream() {
    463   if (audio_)
    464     audio_->UnmarkEndOfStream();
    465 
    466   if (video_)
    467     video_->UnmarkEndOfStream();
    468 
    469   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    470        itr != text_stream_map_.end(); ++itr) {
    471     itr->second->UnmarkEndOfStream();
    472   }
    473 }
    474 
    475 void SourceState::Shutdown() {
    476   if (audio_)
    477     audio_->Shutdown();
    478 
    479   if (video_)
    480     video_->Shutdown();
    481 
    482   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    483        itr != text_stream_map_.end(); ++itr) {
    484     itr->second->Shutdown();
    485   }
    486 }
    487 
    488 void SourceState::SetMemoryLimitsForTesting(int memory_limit) {
    489   if (audio_)
    490     audio_->set_memory_limit_for_testing(memory_limit);
    491 
    492   if (video_)
    493     video_->set_memory_limit_for_testing(memory_limit);
    494 
    495   for (TextStreamMap::iterator itr = text_stream_map_.begin();
    496        itr != text_stream_map_.end(); ++itr) {
    497     itr->second->set_memory_limit_for_testing(memory_limit);
    498   }
    499 }
    500 
    501 bool SourceState::IsSeekWaitingForData() const {
    502   if (audio_ && audio_->IsSeekWaitingForData())
    503     return true;
    504 
    505   if (video_ && video_->IsSeekWaitingForData())
    506     return true;
    507 
    508   // NOTE: We are intentionally not checking the text tracks
    509   // because text tracks are discontinuous and may not have data
    510   // for the seek position. This is ok and playback should not be
    511   // stalled because we don't have cues. If cues, with timestamps after
    512   // the seek time, eventually arrive they will be delivered properly
    513   // in response to ChunkDemuxerStream::Read() calls.
    514 
    515   return false;
    516 }
    517 
    518 bool SourceState::OnNewConfigs(
    519     bool allow_audio, bool allow_video,
    520     const AudioDecoderConfig& audio_config,
    521     const VideoDecoderConfig& video_config,
    522     const StreamParser::TextTrackConfigMap& text_configs) {
    523   DVLOG(1) << "OnNewConfigs(" << allow_audio << ", " << allow_video
    524            << ", " << audio_config.IsValidConfig()
    525            << ", " << video_config.IsValidConfig() << ")";
    526 
    527   if (!audio_config.IsValidConfig() && !video_config.IsValidConfig()) {
    528     DVLOG(1) << "OnNewConfigs() : Audio & video config are not valid!";
    529     return false;
    530   }
    531 
    532   // Signal an error if we get configuration info for stream types that weren't
    533   // specified in AddId() or more configs after a stream is initialized.
    534   if (allow_audio != audio_config.IsValidConfig()) {
    535     MEDIA_LOG(log_cb_)
    536         << "Initialization segment"
    537         << (audio_config.IsValidConfig() ? " has" : " does not have")
    538         << " an audio track, but the mimetype"
    539         << (allow_audio ? " specifies" : " does not specify")
    540         << " an audio codec.";
    541     return false;
    542   }
    543 
    544   if (allow_video != video_config.IsValidConfig()) {
    545     MEDIA_LOG(log_cb_)
    546         << "Initialization segment"
    547         << (video_config.IsValidConfig() ? " has" : " does not have")
    548         << " a video track, but the mimetype"
    549         << (allow_video ? " specifies" : " does not specify")
    550         << " a video codec.";
    551     return false;
    552   }
    553 
    554   bool success = true;
    555   if (audio_config.IsValidConfig()) {
    556     if (!audio_) {
    557       audio_ = create_demuxer_stream_cb_.Run(DemuxerStream::AUDIO);
    558 
    559       if (!audio_) {
    560         DVLOG(1) << "Failed to create an audio stream.";
    561         return false;
    562       }
    563 
    564       if (!frame_processor_->AddTrack(FrameProcessorBase::kAudioTrackId,
    565                                       audio_)) {
    566         DVLOG(1) << "Failed to add audio track to frame processor.";
    567         return false;
    568       }
    569     }
    570 
    571     frame_processor_->OnPossibleAudioConfigUpdate(audio_config);
    572     success &= audio_->UpdateAudioConfig(audio_config, log_cb_);
    573   }
    574 
    575   if (video_config.IsValidConfig()) {
    576     if (!video_) {
    577       video_ = create_demuxer_stream_cb_.Run(DemuxerStream::VIDEO);
    578 
    579       if (!video_) {
    580         DVLOG(1) << "Failed to create a video stream.";
    581         return false;
    582       }
    583 
    584       if (!frame_processor_->AddTrack(FrameProcessorBase::kVideoTrackId,
    585                                       video_)) {
    586         DVLOG(1) << "Failed to add video track to frame processor.";
    587         return false;
    588       }
    589     }
    590 
    591     success &= video_->UpdateVideoConfig(video_config, log_cb_);
    592   }
    593 
    594   typedef StreamParser::TextTrackConfigMap::const_iterator TextConfigItr;
    595   if (text_stream_map_.empty()) {
    596     for (TextConfigItr itr = text_configs.begin();
    597          itr != text_configs.end(); ++itr) {
    598       ChunkDemuxerStream* const text_stream =
    599           create_demuxer_stream_cb_.Run(DemuxerStream::TEXT);
    600       if (!frame_processor_->AddTrack(itr->first, text_stream)) {
    601         success &= false;
    602         MEDIA_LOG(log_cb_) << "Failed to add text track ID " << itr->first
    603                            << " to frame processor.";
    604         break;
    605       }
    606       text_stream->UpdateTextConfig(itr->second, log_cb_);
    607       text_stream_map_[itr->first] = text_stream;
    608       new_text_track_cb_.Run(text_stream, itr->second);
    609     }
    610   } else {
    611     const size_t text_count = text_stream_map_.size();
    612     if (text_configs.size() != text_count) {
    613       success &= false;
    614       MEDIA_LOG(log_cb_) << "The number of text track configs changed.";
    615     } else if (text_count == 1) {
    616       TextConfigItr config_itr = text_configs.begin();
    617       const TextTrackConfig& new_config = config_itr->second;
    618       TextStreamMap::iterator stream_itr = text_stream_map_.begin();
    619       ChunkDemuxerStream* text_stream = stream_itr->second;
    620       TextTrackConfig old_config = text_stream->text_track_config();
    621       if (!new_config.Matches(old_config)) {
    622         success &= false;
    623         MEDIA_LOG(log_cb_) << "New text track config does not match old one.";
    624       } else {
    625         StreamParser::TrackId old_id = stream_itr->first;
    626         StreamParser::TrackId new_id = config_itr->first;
    627         if (new_id != old_id) {
    628           if (frame_processor_->UpdateTrack(old_id, new_id)) {
    629             text_stream_map_.clear();
    630             text_stream_map_[config_itr->first] = text_stream;
    631           } else {
    632             success &= false;
    633             MEDIA_LOG(log_cb_) << "Error remapping single text track number";
    634           }
    635         }
    636       }
    637     } else {
    638       for (TextConfigItr config_itr = text_configs.begin();
    639            config_itr != text_configs.end(); ++config_itr) {
    640         TextStreamMap::iterator stream_itr =
    641             text_stream_map_.find(config_itr->first);
    642         if (stream_itr == text_stream_map_.end()) {
    643           success &= false;
    644           MEDIA_LOG(log_cb_) << "Unexpected text track configuration "
    645                                 "for track ID "
    646                              << config_itr->first;
    647           break;
    648         }
    649 
    650         const TextTrackConfig& new_config = config_itr->second;
    651         ChunkDemuxerStream* stream = stream_itr->second;
    652         TextTrackConfig old_config = stream->text_track_config();
    653         if (!new_config.Matches(old_config)) {
    654           success &= false;
    655           MEDIA_LOG(log_cb_) << "New text track config for track ID "
    656                              << config_itr->first
    657                              << " does not match old one.";
    658           break;
    659         }
    660       }
    661     }
    662   }
    663 
    664   frame_processor_->SetAllTrackBuffersNeedRandomAccessPoint();
    665 
    666   DVLOG(1) << "OnNewConfigs() : " << (success ? "success" : "failed");
    667   return success;
    668 }
    669 
    670 void SourceState::OnNewMediaSegment() {
    671   DVLOG(2) << "OnNewMediaSegment()";
    672   parsing_media_segment_ = true;
    673   new_media_segment_ = true;
    674 }
    675 
    676 void SourceState::OnEndOfMediaSegment() {
    677   DVLOG(2) << "OnEndOfMediaSegment()";
    678   parsing_media_segment_ = false;
    679   new_media_segment_ = false;
    680 }
    681 
    682 bool SourceState::OnNewBuffers(
    683     const StreamParser::BufferQueue& audio_buffers,
    684     const StreamParser::BufferQueue& video_buffers,
    685     const StreamParser::TextBufferQueueMap& text_map) {
    686   DVLOG(2) << "OnNewBuffers()";
    687   DCHECK(timestamp_offset_during_append_);
    688   DCHECK(parsing_media_segment_);
    689 
    690   const TimeDelta timestamp_offset_before_processing =
    691       *timestamp_offset_during_append_;
    692 
    693   // Calculate the new timestamp offset for audio/video tracks if the stream
    694   // parser has requested automatic updates.
    695   TimeDelta new_timestamp_offset = timestamp_offset_before_processing;
    696   if (auto_update_timestamp_offset_) {
    697     const bool have_audio_buffers = !audio_buffers.empty();
    698     const bool have_video_buffers = !video_buffers.empty();
    699     if (have_audio_buffers && have_video_buffers) {
    700       new_timestamp_offset +=
    701           std::min(EndTimestamp(audio_buffers), EndTimestamp(video_buffers));
    702     } else if (have_audio_buffers) {
    703       new_timestamp_offset += EndTimestamp(audio_buffers);
    704     } else if (have_video_buffers) {
    705       new_timestamp_offset += EndTimestamp(video_buffers);
    706     }
    707   }
    708 
    709   if (!frame_processor_->ProcessFrames(audio_buffers,
    710                                        video_buffers,
    711                                        text_map,
    712                                        append_window_start_during_append_,
    713                                        append_window_end_during_append_,
    714                                        &new_media_segment_,
    715                                        timestamp_offset_during_append_)) {
    716     return false;
    717   }
    718 
    719   // Only update the timestamp offset if the frame processor hasn't already.
    720   if (auto_update_timestamp_offset_ &&
    721       timestamp_offset_before_processing == *timestamp_offset_during_append_) {
    722     *timestamp_offset_during_append_ = new_timestamp_offset;
    723   }
    724 
    725   return true;
    726 }
    727 
    728 void SourceState::OnSourceInitDone(bool success,
    729                                    const StreamParser::InitParameters& params) {
    730   auto_update_timestamp_offset_ = params.auto_update_timestamp_offset;
    731   base::ResetAndReturn(&init_cb_).Run(success, params);
    732 }
    733 
    734 ChunkDemuxerStream::ChunkDemuxerStream(Type type, bool splice_frames_enabled)
    735     : type_(type),
    736       state_(UNINITIALIZED),
    737       splice_frames_enabled_(splice_frames_enabled),
    738       partial_append_window_trimming_enabled_(false) {
    739 }
    740 
    741 void ChunkDemuxerStream::StartReturningData() {
    742   DVLOG(1) << "ChunkDemuxerStream::StartReturningData()";
    743   base::AutoLock auto_lock(lock_);
    744   DCHECK(read_cb_.is_null());
    745   ChangeState_Locked(RETURNING_DATA_FOR_READS);
    746 }
    747 
    748 void ChunkDemuxerStream::AbortReads() {
    749   DVLOG(1) << "ChunkDemuxerStream::AbortReads()";
    750   base::AutoLock auto_lock(lock_);
    751   ChangeState_Locked(RETURNING_ABORT_FOR_READS);
    752   if (!read_cb_.is_null())
    753     base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
    754 }
    755 
    756 void ChunkDemuxerStream::CompletePendingReadIfPossible() {
    757   base::AutoLock auto_lock(lock_);
    758   if (read_cb_.is_null())
    759     return;
    760 
    761   CompletePendingReadIfPossible_Locked();
    762 }
    763 
    764 void ChunkDemuxerStream::Shutdown() {
    765   DVLOG(1) << "ChunkDemuxerStream::Shutdown()";
    766   base::AutoLock auto_lock(lock_);
    767   ChangeState_Locked(SHUTDOWN);
    768 
    769   // Pass an end of stream buffer to the pending callback to signal that no more
    770   // data will be sent.
    771   if (!read_cb_.is_null()) {
    772     base::ResetAndReturn(&read_cb_).Run(DemuxerStream::kOk,
    773                                         StreamParserBuffer::CreateEOSBuffer());
    774   }
    775 }
    776 
    777 bool ChunkDemuxerStream::IsSeekWaitingForData() const {
    778   base::AutoLock auto_lock(lock_);
    779 
    780   // This method should not be called for text tracks. See the note in
    781   // SourceState::IsSeekWaitingForData().
    782   DCHECK_NE(type_, DemuxerStream::TEXT);
    783 
    784   return stream_->IsSeekPending();
    785 }
    786 
    787 void ChunkDemuxerStream::Seek(TimeDelta time) {
    788   DVLOG(1) << "ChunkDemuxerStream::Seek(" << time.InSecondsF() << ")";
    789   base::AutoLock auto_lock(lock_);
    790   DCHECK(read_cb_.is_null());
    791   DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS)
    792       << state_;
    793 
    794   stream_->Seek(time);
    795 }
    796 
    797 bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers) {
    798   if (buffers.empty())
    799     return false;
    800 
    801   base::AutoLock auto_lock(lock_);
    802   DCHECK_NE(state_, SHUTDOWN);
    803   if (!stream_->Append(buffers)) {
    804     DVLOG(1) << "ChunkDemuxerStream::Append() : stream append failed";
    805     return false;
    806   }
    807 
    808   if (!read_cb_.is_null())
    809     CompletePendingReadIfPossible_Locked();
    810 
    811   return true;
    812 }
    813 
    814 void ChunkDemuxerStream::Remove(TimeDelta start, TimeDelta end,
    815                                 TimeDelta duration) {
    816   base::AutoLock auto_lock(lock_);
    817   stream_->Remove(start, end, duration);
    818 }
    819 
    820 void ChunkDemuxerStream::OnSetDuration(TimeDelta duration) {
    821   base::AutoLock auto_lock(lock_);
    822   stream_->OnSetDuration(duration);
    823 }
    824 
    825 Ranges<TimeDelta> ChunkDemuxerStream::GetBufferedRanges(
    826     TimeDelta duration) const {
    827   base::AutoLock auto_lock(lock_);
    828 
    829   if (type_ == TEXT) {
    830     // Since text tracks are discontinuous and the lack of cues should not block
    831     // playback, report the buffered range for text tracks as [0, |duration|) so
    832     // that intesections with audio & video tracks are computed correctly when
    833     // no cues are present.
    834     Ranges<TimeDelta> text_range;
    835     text_range.Add(TimeDelta(), duration);
    836     return text_range;
    837   }
    838 
    839   Ranges<TimeDelta> range = stream_->GetBufferedTime();
    840 
    841   if (range.size() == 0u)
    842     return range;
    843 
    844   // Clamp the end of the stream's buffered ranges to fit within the duration.
    845   // This can be done by intersecting the stream's range with the valid time
    846   // range.
    847   Ranges<TimeDelta> valid_time_range;
    848   valid_time_range.Add(range.start(0), duration);
    849   return range.IntersectionWith(valid_time_range);
    850 }
    851 
    852 TimeDelta ChunkDemuxerStream::GetBufferedDuration() const {
    853   return stream_->GetBufferedDuration();
    854 }
    855 
    856 void ChunkDemuxerStream::OnNewMediaSegment(TimeDelta start_timestamp) {
    857   DVLOG(2) << "ChunkDemuxerStream::OnNewMediaSegment("
    858            << start_timestamp.InSecondsF() << ")";
    859   base::AutoLock auto_lock(lock_);
    860   stream_->OnNewMediaSegment(start_timestamp);
    861 }
    862 
    863 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config,
    864                                            const LogCB& log_cb) {
    865   DCHECK(config.IsValidConfig());
    866   DCHECK_EQ(type_, AUDIO);
    867   base::AutoLock auto_lock(lock_);
    868   if (!stream_) {
    869     DCHECK_EQ(state_, UNINITIALIZED);
    870 
    871     // On platforms which support splice frames, enable splice frames and
    872     // partial append window support for most codecs (notably: not opus).
    873     const bool codec_supported = config.codec() == kCodecMP3 ||
    874                                  config.codec() == kCodecAAC ||
    875                                  config.codec() == kCodecVorbis;
    876     splice_frames_enabled_ = splice_frames_enabled_ && codec_supported;
    877     partial_append_window_trimming_enabled_ =
    878         splice_frames_enabled_ && codec_supported;
    879 
    880     stream_.reset(
    881         new SourceBufferStream(config, log_cb, splice_frames_enabled_));
    882     return true;
    883   }
    884 
    885   return stream_->UpdateAudioConfig(config);
    886 }
    887 
    888 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config,
    889                                            const LogCB& log_cb) {
    890   DCHECK(config.IsValidConfig());
    891   DCHECK_EQ(type_, VIDEO);
    892   base::AutoLock auto_lock(lock_);
    893 
    894   if (!stream_) {
    895     DCHECK_EQ(state_, UNINITIALIZED);
    896     stream_.reset(
    897         new SourceBufferStream(config, log_cb, splice_frames_enabled_));
    898     return true;
    899   }
    900 
    901   return stream_->UpdateVideoConfig(config);
    902 }
    903 
    904 void ChunkDemuxerStream::UpdateTextConfig(const TextTrackConfig& config,
    905                                           const LogCB& log_cb) {
    906   DCHECK_EQ(type_, TEXT);
    907   base::AutoLock auto_lock(lock_);
    908   DCHECK(!stream_);
    909   DCHECK_EQ(state_, UNINITIALIZED);
    910   stream_.reset(new SourceBufferStream(config, log_cb, splice_frames_enabled_));
    911 }
    912 
    913 void ChunkDemuxerStream::MarkEndOfStream() {
    914   base::AutoLock auto_lock(lock_);
    915   stream_->MarkEndOfStream();
    916 }
    917 
    918 void ChunkDemuxerStream::UnmarkEndOfStream() {
    919   base::AutoLock auto_lock(lock_);
    920   stream_->UnmarkEndOfStream();
    921 }
    922 
    923 // DemuxerStream methods.
    924 void ChunkDemuxerStream::Read(const ReadCB& read_cb) {
    925   base::AutoLock auto_lock(lock_);
    926   DCHECK_NE(state_, UNINITIALIZED);
    927   DCHECK(read_cb_.is_null());
    928 
    929   read_cb_ = BindToCurrentLoop(read_cb);
    930   CompletePendingReadIfPossible_Locked();
    931 }
    932 
    933 DemuxerStream::Type ChunkDemuxerStream::type() { return type_; }
    934 
    935 void ChunkDemuxerStream::EnableBitstreamConverter() {}
    936 
    937 AudioDecoderConfig ChunkDemuxerStream::audio_decoder_config() {
    938   CHECK_EQ(type_, AUDIO);
    939   base::AutoLock auto_lock(lock_);
    940   return stream_->GetCurrentAudioDecoderConfig();
    941 }
    942 
    943 VideoDecoderConfig ChunkDemuxerStream::video_decoder_config() {
    944   CHECK_EQ(type_, VIDEO);
    945   base::AutoLock auto_lock(lock_);
    946   return stream_->GetCurrentVideoDecoderConfig();
    947 }
    948 
    949 bool ChunkDemuxerStream::SupportsConfigChanges() { return true; }
    950 
    951 TextTrackConfig ChunkDemuxerStream::text_track_config() {
    952   CHECK_EQ(type_, TEXT);
    953   base::AutoLock auto_lock(lock_);
    954   return stream_->GetCurrentTextTrackConfig();
    955 }
    956 
    957 void ChunkDemuxerStream::ChangeState_Locked(State state) {
    958   lock_.AssertAcquired();
    959   DVLOG(1) << "ChunkDemuxerStream::ChangeState_Locked() : "
    960            << "type " << type_
    961            << " - " << state_ << " -> " << state;
    962   state_ = state;
    963 }
    964 
    965 ChunkDemuxerStream::~ChunkDemuxerStream() {}
    966 
    967 void ChunkDemuxerStream::CompletePendingReadIfPossible_Locked() {
    968   lock_.AssertAcquired();
    969   DCHECK(!read_cb_.is_null());
    970 
    971   DemuxerStream::Status status;
    972   scoped_refptr<StreamParserBuffer> buffer;
    973 
    974   switch (state_) {
    975     case UNINITIALIZED:
    976       NOTREACHED();
    977       return;
    978     case RETURNING_DATA_FOR_READS:
    979       switch (stream_->GetNextBuffer(&buffer)) {
    980         case SourceBufferStream::kSuccess:
    981           status = DemuxerStream::kOk;
    982           break;
    983         case SourceBufferStream::kNeedBuffer:
    984           // Return early without calling |read_cb_| since we don't have
    985           // any data to return yet.
    986           return;
    987         case SourceBufferStream::kEndOfStream:
    988           status = DemuxerStream::kOk;
    989           buffer = StreamParserBuffer::CreateEOSBuffer();
    990           break;
    991         case SourceBufferStream::kConfigChange:
    992           DVLOG(2) << "Config change reported to ChunkDemuxerStream.";
    993           status = kConfigChanged;
    994           buffer = NULL;
    995           break;
    996       }
    997       break;
    998     case RETURNING_ABORT_FOR_READS:
    999       // Null buffers should be returned in this state since we are waiting
   1000       // for a seek. Any buffers in the SourceBuffer should NOT be returned
   1001       // because they are associated with the seek.
   1002       status = DemuxerStream::kAborted;
   1003       buffer = NULL;
   1004       break;
   1005     case SHUTDOWN:
   1006       status = DemuxerStream::kOk;
   1007       buffer = StreamParserBuffer::CreateEOSBuffer();
   1008       break;
   1009   }
   1010 
   1011   base::ResetAndReturn(&read_cb_).Run(status, buffer);
   1012 }
   1013 
   1014 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb,
   1015                            const NeedKeyCB& need_key_cb,
   1016                            const LogCB& log_cb,
   1017                            bool splice_frames_enabled)
   1018     : state_(WAITING_FOR_INIT),
   1019       cancel_next_seek_(false),
   1020       host_(NULL),
   1021       open_cb_(open_cb),
   1022       need_key_cb_(need_key_cb),
   1023       enable_text_(false),
   1024       log_cb_(log_cb),
   1025       duration_(kNoTimestamp()),
   1026       user_specified_duration_(-1),
   1027       liveness_(LIVENESS_UNKNOWN),
   1028       splice_frames_enabled_(splice_frames_enabled) {
   1029   DCHECK(!open_cb_.is_null());
   1030   DCHECK(!need_key_cb_.is_null());
   1031 }
   1032 
   1033 void ChunkDemuxer::Initialize(
   1034     DemuxerHost* host,
   1035     const PipelineStatusCB& cb,
   1036     bool enable_text_tracks) {
   1037   DVLOG(1) << "Init()";
   1038 
   1039   base::AutoLock auto_lock(lock_);
   1040 
   1041   init_cb_ = BindToCurrentLoop(cb);
   1042   if (state_ == SHUTDOWN) {
   1043     base::ResetAndReturn(&init_cb_).Run(DEMUXER_ERROR_COULD_NOT_OPEN);
   1044     return;
   1045   }
   1046   DCHECK_EQ(state_, WAITING_FOR_INIT);
   1047   host_ = host;
   1048   enable_text_ = enable_text_tracks;
   1049 
   1050   ChangeState_Locked(INITIALIZING);
   1051 
   1052   base::ResetAndReturn(&open_cb_).Run();
   1053 }
   1054 
   1055 void ChunkDemuxer::Stop(const base::Closure& callback) {
   1056   DVLOG(1) << "Stop()";
   1057   Shutdown();
   1058   callback.Run();
   1059 }
   1060 
   1061 void ChunkDemuxer::Seek(TimeDelta time, const PipelineStatusCB& cb) {
   1062   DVLOG(1) << "Seek(" << time.InSecondsF() << ")";
   1063   DCHECK(time >= TimeDelta());
   1064 
   1065   base::AutoLock auto_lock(lock_);
   1066   DCHECK(seek_cb_.is_null());
   1067 
   1068   seek_cb_ = BindToCurrentLoop(cb);
   1069   if (state_ != INITIALIZED && state_ != ENDED) {
   1070     base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_INVALID_STATE);
   1071     return;
   1072   }
   1073 
   1074   if (cancel_next_seek_) {
   1075     cancel_next_seek_ = false;
   1076     base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
   1077     return;
   1078   }
   1079 
   1080   SeekAllSources(time);
   1081   StartReturningData();
   1082 
   1083   if (IsSeekWaitingForData_Locked()) {
   1084     DVLOG(1) << "Seek() : waiting for more data to arrive.";
   1085     return;
   1086   }
   1087 
   1088   base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
   1089 }
   1090 
   1091 // Demuxer implementation.
   1092 DemuxerStream* ChunkDemuxer::GetStream(DemuxerStream::Type type) {
   1093   DCHECK_NE(type, DemuxerStream::TEXT);
   1094   base::AutoLock auto_lock(lock_);
   1095   if (type == DemuxerStream::VIDEO)
   1096     return video_.get();
   1097 
   1098   if (type == DemuxerStream::AUDIO)
   1099     return audio_.get();
   1100 
   1101   return NULL;
   1102 }
   1103 
   1104 TimeDelta ChunkDemuxer::GetStartTime() const {
   1105   return TimeDelta();
   1106 }
   1107 
   1108 base::Time ChunkDemuxer::GetTimelineOffset() const {
   1109   return timeline_offset_;
   1110 }
   1111 
   1112 Demuxer::Liveness ChunkDemuxer::GetLiveness() const {
   1113   return liveness_;
   1114 }
   1115 
   1116 void ChunkDemuxer::StartWaitingForSeek(TimeDelta seek_time) {
   1117   DVLOG(1) << "StartWaitingForSeek()";
   1118   base::AutoLock auto_lock(lock_);
   1119   DCHECK(state_ == INITIALIZED || state_ == ENDED || state_ == SHUTDOWN ||
   1120          state_ == PARSE_ERROR) << state_;
   1121   DCHECK(seek_cb_.is_null());
   1122 
   1123   if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
   1124     return;
   1125 
   1126   AbortPendingReads();
   1127   SeekAllSources(seek_time);
   1128 
   1129   // Cancel state set in CancelPendingSeek() since we want to
   1130   // accept the next Seek().
   1131   cancel_next_seek_ = false;
   1132 }
   1133 
   1134 void ChunkDemuxer::CancelPendingSeek(TimeDelta seek_time) {
   1135   base::AutoLock auto_lock(lock_);
   1136   DCHECK_NE(state_, INITIALIZING);
   1137   DCHECK(seek_cb_.is_null() || IsSeekWaitingForData_Locked());
   1138 
   1139   if (cancel_next_seek_)
   1140     return;
   1141 
   1142   AbortPendingReads();
   1143   SeekAllSources(seek_time);
   1144 
   1145   if (seek_cb_.is_null()) {
   1146     cancel_next_seek_ = true;
   1147     return;
   1148   }
   1149 
   1150   base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
   1151 }
   1152 
   1153 ChunkDemuxer::Status ChunkDemuxer::AddId(const std::string& id,
   1154                                          const std::string& type,
   1155                                          std::vector<std::string>& codecs) {
   1156   base::AutoLock auto_lock(lock_);
   1157 
   1158   if ((state_ != WAITING_FOR_INIT && state_ != INITIALIZING) || IsValidId(id))
   1159     return kReachedIdLimit;
   1160 
   1161   bool has_audio = false;
   1162   bool has_video = false;
   1163   scoped_ptr<media::StreamParser> stream_parser(
   1164       StreamParserFactory::Create(type, codecs, log_cb_,
   1165                                   &has_audio, &has_video));
   1166 
   1167   if (!stream_parser)
   1168     return ChunkDemuxer::kNotSupported;
   1169 
   1170   if ((has_audio && !source_id_audio_.empty()) ||
   1171       (has_video && !source_id_video_.empty()))
   1172     return kReachedIdLimit;
   1173 
   1174   if (has_audio)
   1175     source_id_audio_ = id;
   1176 
   1177   if (has_video)
   1178     source_id_video_ = id;
   1179 
   1180   scoped_ptr<FrameProcessor> frame_processor(
   1181       new FrameProcessor(base::Bind(&ChunkDemuxer::IncreaseDurationIfNecessary,
   1182                          base::Unretained(this))));
   1183 
   1184   scoped_ptr<SourceState> source_state(
   1185       new SourceState(stream_parser.Pass(),
   1186                       frame_processor.Pass(), log_cb_,
   1187                       base::Bind(&ChunkDemuxer::CreateDemuxerStream,
   1188                                  base::Unretained(this))));
   1189 
   1190   SourceState::NewTextTrackCB new_text_track_cb;
   1191 
   1192   if (enable_text_) {
   1193     new_text_track_cb = base::Bind(&ChunkDemuxer::OnNewTextTrack,
   1194                                    base::Unretained(this));
   1195   }
   1196 
   1197   source_state->Init(
   1198       base::Bind(&ChunkDemuxer::OnSourceInitDone, base::Unretained(this)),
   1199       has_audio,
   1200       has_video,
   1201       need_key_cb_,
   1202       new_text_track_cb);
   1203 
   1204   source_state_map_[id] = source_state.release();
   1205   return kOk;
   1206 }
   1207 
   1208 void ChunkDemuxer::RemoveId(const std::string& id) {
   1209   base::AutoLock auto_lock(lock_);
   1210   CHECK(IsValidId(id));
   1211 
   1212   delete source_state_map_[id];
   1213   source_state_map_.erase(id);
   1214 
   1215   if (source_id_audio_ == id)
   1216     source_id_audio_.clear();
   1217 
   1218   if (source_id_video_ == id)
   1219     source_id_video_.clear();
   1220 }
   1221 
   1222 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges(const std::string& id) const {
   1223   base::AutoLock auto_lock(lock_);
   1224   DCHECK(!id.empty());
   1225 
   1226   SourceStateMap::const_iterator itr = source_state_map_.find(id);
   1227 
   1228   DCHECK(itr != source_state_map_.end());
   1229   return itr->second->GetBufferedRanges(duration_, state_ == ENDED);
   1230 }
   1231 
   1232 void ChunkDemuxer::AppendData(const std::string& id,
   1233                               const uint8* data, size_t length,
   1234                               TimeDelta append_window_start,
   1235                               TimeDelta append_window_end,
   1236                               TimeDelta* timestamp_offset) {
   1237   DVLOG(1) << "AppendData(" << id << ", " << length << ")";
   1238 
   1239   DCHECK(!id.empty());
   1240   DCHECK(timestamp_offset);
   1241 
   1242   Ranges<TimeDelta> ranges;
   1243 
   1244   {
   1245     base::AutoLock auto_lock(lock_);
   1246     DCHECK_NE(state_, ENDED);
   1247 
   1248     // Capture if any of the SourceBuffers are waiting for data before we start
   1249     // parsing.
   1250     bool old_waiting_for_data = IsSeekWaitingForData_Locked();
   1251 
   1252     if (length == 0u)
   1253       return;
   1254 
   1255     DCHECK(data);
   1256 
   1257     switch (state_) {
   1258       case INITIALIZING:
   1259         DCHECK(IsValidId(id));
   1260         if (!source_state_map_[id]->Append(data, length,
   1261                                            append_window_start,
   1262                                            append_window_end,
   1263                                            timestamp_offset)) {
   1264           ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
   1265           return;
   1266         }
   1267         break;
   1268 
   1269       case INITIALIZED: {
   1270         DCHECK(IsValidId(id));
   1271         if (!source_state_map_[id]->Append(data, length,
   1272                                            append_window_start,
   1273                                            append_window_end,
   1274                                            timestamp_offset)) {
   1275           ReportError_Locked(PIPELINE_ERROR_DECODE);
   1276           return;
   1277         }
   1278       } break;
   1279 
   1280       case PARSE_ERROR:
   1281         DVLOG(1) << "AppendData(): Ignoring data after a parse error.";
   1282         return;
   1283 
   1284       case WAITING_FOR_INIT:
   1285       case ENDED:
   1286       case SHUTDOWN:
   1287         DVLOG(1) << "AppendData(): called in unexpected state " << state_;
   1288         return;
   1289     }
   1290 
   1291     // Check to see if data was appended at the pending seek point. This
   1292     // indicates we have parsed enough data to complete the seek.
   1293     if (old_waiting_for_data && !IsSeekWaitingForData_Locked() &&
   1294         !seek_cb_.is_null()) {
   1295       base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
   1296     }
   1297 
   1298     ranges = GetBufferedRanges_Locked();
   1299   }
   1300 
   1301   for (size_t i = 0; i < ranges.size(); ++i)
   1302     host_->AddBufferedTimeRange(ranges.start(i), ranges.end(i));
   1303 }
   1304 
   1305 void ChunkDemuxer::Abort(const std::string& id,
   1306                          TimeDelta append_window_start,
   1307                          TimeDelta append_window_end,
   1308                          TimeDelta* timestamp_offset) {
   1309   DVLOG(1) << "Abort(" << id << ")";
   1310   base::AutoLock auto_lock(lock_);
   1311   DCHECK(!id.empty());
   1312   CHECK(IsValidId(id));
   1313   source_state_map_[id]->Abort(append_window_start,
   1314                                append_window_end,
   1315                                timestamp_offset);
   1316 }
   1317 
   1318 void ChunkDemuxer::Remove(const std::string& id, TimeDelta start,
   1319                           TimeDelta end) {
   1320   DVLOG(1) << "Remove(" << id << ", " << start.InSecondsF()
   1321            << ", " << end.InSecondsF() << ")";
   1322   base::AutoLock auto_lock(lock_);
   1323 
   1324   DCHECK(!id.empty());
   1325   CHECK(IsValidId(id));
   1326   DCHECK(start >= base::TimeDelta()) << start.InSecondsF();
   1327   DCHECK(start < end) << "start " << start.InSecondsF()
   1328                       << " end " << end.InSecondsF();
   1329   DCHECK(duration_ != kNoTimestamp());
   1330   DCHECK(start <= duration_) << "start " << start.InSecondsF()
   1331                              << " duration " << duration_.InSecondsF();
   1332 
   1333   if (start == duration_)
   1334     return;
   1335 
   1336   source_state_map_[id]->Remove(start, end, duration_);
   1337 }
   1338 
   1339 double ChunkDemuxer::GetDuration() {
   1340   base::AutoLock auto_lock(lock_);
   1341   return GetDuration_Locked();
   1342 }
   1343 
   1344 double ChunkDemuxer::GetDuration_Locked() {
   1345   lock_.AssertAcquired();
   1346   if (duration_ == kNoTimestamp())
   1347     return std::numeric_limits<double>::quiet_NaN();
   1348 
   1349   // Return positive infinity if the resource is unbounded.
   1350   // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
   1351   if (duration_ == kInfiniteDuration())
   1352     return std::numeric_limits<double>::infinity();
   1353 
   1354   if (user_specified_duration_ >= 0)
   1355     return user_specified_duration_;
   1356 
   1357   return duration_.InSecondsF();
   1358 }
   1359 
   1360 void ChunkDemuxer::SetDuration(double duration) {
   1361   base::AutoLock auto_lock(lock_);
   1362   DVLOG(1) << "SetDuration(" << duration << ")";
   1363   DCHECK_GE(duration, 0);
   1364 
   1365   if (duration == GetDuration_Locked())
   1366     return;
   1367 
   1368   // Compute & bounds check the TimeDelta representation of duration.
   1369   // This can be different if the value of |duration| doesn't fit the range or
   1370   // precision of TimeDelta.
   1371   TimeDelta min_duration = TimeDelta::FromInternalValue(1);
   1372   // Don't use TimeDelta::Max() here, as we want the largest finite time delta.
   1373   TimeDelta max_duration = TimeDelta::FromInternalValue(kint64max - 1);
   1374   double min_duration_in_seconds = min_duration.InSecondsF();
   1375   double max_duration_in_seconds = max_duration.InSecondsF();
   1376 
   1377   TimeDelta duration_td;
   1378   if (duration == std::numeric_limits<double>::infinity()) {
   1379     duration_td = media::kInfiniteDuration();
   1380   } else if (duration < min_duration_in_seconds) {
   1381     duration_td = min_duration;
   1382   } else if (duration > max_duration_in_seconds) {
   1383     duration_td = max_duration;
   1384   } else {
   1385     duration_td = TimeDelta::FromMicroseconds(
   1386         duration * base::Time::kMicrosecondsPerSecond);
   1387   }
   1388 
   1389   DCHECK(duration_td > TimeDelta());
   1390 
   1391   user_specified_duration_ = duration;
   1392   duration_ = duration_td;
   1393   host_->SetDuration(duration_);
   1394 
   1395   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1396        itr != source_state_map_.end(); ++itr) {
   1397     itr->second->OnSetDuration(duration_);
   1398   }
   1399 }
   1400 
   1401 bool ChunkDemuxer::IsParsingMediaSegment(const std::string& id) {
   1402   base::AutoLock auto_lock(lock_);
   1403   DVLOG(1) << "IsParsingMediaSegment(" << id << ")";
   1404   CHECK(IsValidId(id));
   1405 
   1406   return source_state_map_[id]->parsing_media_segment();
   1407 }
   1408 
   1409 void ChunkDemuxer::SetSequenceMode(const std::string& id,
   1410                                    bool sequence_mode) {
   1411   base::AutoLock auto_lock(lock_);
   1412   DVLOG(1) << "SetSequenceMode(" << id << ", " << sequence_mode << ")";
   1413   CHECK(IsValidId(id));
   1414   DCHECK_NE(state_, ENDED);
   1415 
   1416   source_state_map_[id]->SetSequenceMode(sequence_mode);
   1417 }
   1418 
   1419 void ChunkDemuxer::SetGroupStartTimestampIfInSequenceMode(
   1420     const std::string& id,
   1421     base::TimeDelta timestamp_offset) {
   1422   base::AutoLock auto_lock(lock_);
   1423   DVLOG(1) << "SetGroupStartTimestampIfInSequenceMode(" << id << ", "
   1424            << timestamp_offset.InSecondsF() << ")";
   1425   CHECK(IsValidId(id));
   1426   DCHECK_NE(state_, ENDED);
   1427 
   1428   source_state_map_[id]->SetGroupStartTimestampIfInSequenceMode(
   1429       timestamp_offset);
   1430 }
   1431 
   1432 
   1433 void ChunkDemuxer::MarkEndOfStream(PipelineStatus status) {
   1434   DVLOG(1) << "MarkEndOfStream(" << status << ")";
   1435   base::AutoLock auto_lock(lock_);
   1436   DCHECK_NE(state_, WAITING_FOR_INIT);
   1437   DCHECK_NE(state_, ENDED);
   1438 
   1439   if (state_ == SHUTDOWN || state_ == PARSE_ERROR)
   1440     return;
   1441 
   1442   if (state_ == INITIALIZING) {
   1443     ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
   1444     return;
   1445   }
   1446 
   1447   bool old_waiting_for_data = IsSeekWaitingForData_Locked();
   1448   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1449        itr != source_state_map_.end(); ++itr) {
   1450     itr->second->MarkEndOfStream();
   1451   }
   1452 
   1453   CompletePendingReadsIfPossible();
   1454 
   1455   // Give a chance to resume the pending seek process.
   1456   if (status != PIPELINE_OK) {
   1457     ReportError_Locked(status);
   1458     return;
   1459   }
   1460 
   1461   ChangeState_Locked(ENDED);
   1462   DecreaseDurationIfNecessary();
   1463 
   1464   if (old_waiting_for_data && !IsSeekWaitingForData_Locked() &&
   1465       !seek_cb_.is_null()) {
   1466     base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
   1467   }
   1468 }
   1469 
   1470 void ChunkDemuxer::UnmarkEndOfStream() {
   1471   DVLOG(1) << "UnmarkEndOfStream()";
   1472   base::AutoLock auto_lock(lock_);
   1473   DCHECK_EQ(state_, ENDED);
   1474 
   1475   ChangeState_Locked(INITIALIZED);
   1476 
   1477   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1478        itr != source_state_map_.end(); ++itr) {
   1479     itr->second->UnmarkEndOfStream();
   1480   }
   1481 }
   1482 
   1483 void ChunkDemuxer::Shutdown() {
   1484   DVLOG(1) << "Shutdown()";
   1485   base::AutoLock auto_lock(lock_);
   1486 
   1487   if (state_ == SHUTDOWN)
   1488     return;
   1489 
   1490   ShutdownAllStreams();
   1491 
   1492   ChangeState_Locked(SHUTDOWN);
   1493 
   1494   if(!seek_cb_.is_null())
   1495     base::ResetAndReturn(&seek_cb_).Run(PIPELINE_ERROR_ABORT);
   1496 }
   1497 
   1498 void ChunkDemuxer::SetMemoryLimitsForTesting(int memory_limit) {
   1499   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1500        itr != source_state_map_.end(); ++itr) {
   1501     itr->second->SetMemoryLimitsForTesting(memory_limit);
   1502   }
   1503 }
   1504 
   1505 void ChunkDemuxer::ChangeState_Locked(State new_state) {
   1506   lock_.AssertAcquired();
   1507   DVLOG(1) << "ChunkDemuxer::ChangeState_Locked() : "
   1508            << state_ << " -> " << new_state;
   1509   state_ = new_state;
   1510 }
   1511 
   1512 ChunkDemuxer::~ChunkDemuxer() {
   1513   DCHECK_NE(state_, INITIALIZED);
   1514 
   1515   STLDeleteValues(&source_state_map_);
   1516 }
   1517 
   1518 void ChunkDemuxer::ReportError_Locked(PipelineStatus error) {
   1519   DVLOG(1) << "ReportError_Locked(" << error << ")";
   1520   lock_.AssertAcquired();
   1521   DCHECK_NE(error, PIPELINE_OK);
   1522 
   1523   ChangeState_Locked(PARSE_ERROR);
   1524 
   1525   PipelineStatusCB cb;
   1526 
   1527   if (!init_cb_.is_null()) {
   1528     std::swap(cb, init_cb_);
   1529   } else {
   1530     if (!seek_cb_.is_null())
   1531       std::swap(cb, seek_cb_);
   1532 
   1533     ShutdownAllStreams();
   1534   }
   1535 
   1536   if (!cb.is_null()) {
   1537     cb.Run(error);
   1538     return;
   1539   }
   1540 
   1541   base::AutoUnlock auto_unlock(lock_);
   1542   host_->OnDemuxerError(error);
   1543 }
   1544 
   1545 bool ChunkDemuxer::IsSeekWaitingForData_Locked() const {
   1546   lock_.AssertAcquired();
   1547   for (SourceStateMap::const_iterator itr = source_state_map_.begin();
   1548        itr != source_state_map_.end(); ++itr) {
   1549     if (itr->second->IsSeekWaitingForData())
   1550       return true;
   1551   }
   1552 
   1553   return false;
   1554 }
   1555 
   1556 void ChunkDemuxer::OnSourceInitDone(
   1557     bool success,
   1558     const StreamParser::InitParameters& params) {
   1559   DVLOG(1) << "OnSourceInitDone(" << success << ", "
   1560            << params.duration.InSecondsF() << ")";
   1561   lock_.AssertAcquired();
   1562   DCHECK_EQ(state_, INITIALIZING);
   1563   if (!success || (!audio_ && !video_)) {
   1564     ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
   1565     return;
   1566   }
   1567 
   1568   if (params.duration != TimeDelta() && duration_ == kNoTimestamp())
   1569     UpdateDuration(params.duration);
   1570 
   1571   if (!params.timeline_offset.is_null()) {
   1572     if (!timeline_offset_.is_null() &&
   1573         params.timeline_offset != timeline_offset_) {
   1574       MEDIA_LOG(log_cb_)
   1575           << "Timeline offset is not the same across all SourceBuffers.";
   1576       ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
   1577       return;
   1578     }
   1579 
   1580     timeline_offset_ = params.timeline_offset;
   1581   }
   1582 
   1583   if (params.liveness != LIVENESS_UNKNOWN) {
   1584     if (liveness_ != LIVENESS_UNKNOWN && params.liveness != liveness_) {
   1585       MEDIA_LOG(log_cb_)
   1586           << "Liveness is not the same across all SourceBuffers.";
   1587       ReportError_Locked(DEMUXER_ERROR_COULD_NOT_OPEN);
   1588       return;
   1589     }
   1590 
   1591     liveness_ = params.liveness;
   1592   }
   1593 
   1594   // Wait until all streams have initialized.
   1595   if ((!source_id_audio_.empty() && !audio_) ||
   1596       (!source_id_video_.empty() && !video_)) {
   1597     return;
   1598   }
   1599 
   1600   SeekAllSources(GetStartTime());
   1601   StartReturningData();
   1602 
   1603   if (duration_ == kNoTimestamp())
   1604     duration_ = kInfiniteDuration();
   1605 
   1606   // The demuxer is now initialized after the |start_timestamp_| was set.
   1607   ChangeState_Locked(INITIALIZED);
   1608   base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
   1609 }
   1610 
   1611 ChunkDemuxerStream*
   1612 ChunkDemuxer::CreateDemuxerStream(DemuxerStream::Type type) {
   1613   switch (type) {
   1614     case DemuxerStream::AUDIO:
   1615       if (audio_)
   1616         return NULL;
   1617       audio_.reset(
   1618           new ChunkDemuxerStream(DemuxerStream::AUDIO, splice_frames_enabled_));
   1619       return audio_.get();
   1620       break;
   1621     case DemuxerStream::VIDEO:
   1622       if (video_)
   1623         return NULL;
   1624       video_.reset(
   1625           new ChunkDemuxerStream(DemuxerStream::VIDEO, splice_frames_enabled_));
   1626       return video_.get();
   1627       break;
   1628     case DemuxerStream::TEXT: {
   1629       return new ChunkDemuxerStream(DemuxerStream::TEXT,
   1630                                     splice_frames_enabled_);
   1631       break;
   1632     }
   1633     case DemuxerStream::UNKNOWN:
   1634     case DemuxerStream::NUM_TYPES:
   1635       NOTREACHED();
   1636       return NULL;
   1637   }
   1638   NOTREACHED();
   1639   return NULL;
   1640 }
   1641 
   1642 void ChunkDemuxer::OnNewTextTrack(ChunkDemuxerStream* text_stream,
   1643                                   const TextTrackConfig& config) {
   1644   lock_.AssertAcquired();
   1645   DCHECK_NE(state_, SHUTDOWN);
   1646   host_->AddTextStream(text_stream, config);
   1647 }
   1648 
   1649 bool ChunkDemuxer::IsValidId(const std::string& source_id) const {
   1650   lock_.AssertAcquired();
   1651   return source_state_map_.count(source_id) > 0u;
   1652 }
   1653 
   1654 void ChunkDemuxer::UpdateDuration(TimeDelta new_duration) {
   1655   DCHECK(duration_ != new_duration);
   1656   user_specified_duration_ = -1;
   1657   duration_ = new_duration;
   1658   host_->SetDuration(new_duration);
   1659 }
   1660 
   1661 void ChunkDemuxer::IncreaseDurationIfNecessary(TimeDelta new_duration) {
   1662   DCHECK(new_duration != kNoTimestamp());
   1663   DCHECK(new_duration != kInfiniteDuration());
   1664 
   1665   // Per April 1, 2014 MSE spec editor's draft:
   1666   // https://dvcs.w3.org/hg/html-media/raw-file/d471a4412040/media-source/
   1667   //     media-source.html#sourcebuffer-coded-frame-processing
   1668   // 5. If the media segment contains data beyond the current duration, then run
   1669   //    the duration change algorithm with new duration set to the maximum of
   1670   //    the current duration and the group end timestamp.
   1671 
   1672   if (new_duration <= duration_)
   1673     return;
   1674 
   1675   DVLOG(2) << __FUNCTION__ << ": Increasing duration: "
   1676            << duration_.InSecondsF() << " -> " << new_duration.InSecondsF();
   1677 
   1678   UpdateDuration(new_duration);
   1679 }
   1680 
   1681 void ChunkDemuxer::DecreaseDurationIfNecessary() {
   1682   lock_.AssertAcquired();
   1683 
   1684   TimeDelta max_duration;
   1685 
   1686   for (SourceStateMap::const_iterator itr = source_state_map_.begin();
   1687        itr != source_state_map_.end(); ++itr) {
   1688     max_duration = std::max(max_duration,
   1689                             itr->second->GetMaxBufferedDuration());
   1690   }
   1691 
   1692   if (max_duration == TimeDelta())
   1693     return;
   1694 
   1695   if (max_duration < duration_)
   1696     UpdateDuration(max_duration);
   1697 }
   1698 
   1699 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges() const {
   1700   base::AutoLock auto_lock(lock_);
   1701   return GetBufferedRanges_Locked();
   1702 }
   1703 
   1704 Ranges<TimeDelta> ChunkDemuxer::GetBufferedRanges_Locked() const {
   1705   lock_.AssertAcquired();
   1706 
   1707   bool ended = state_ == ENDED;
   1708   // TODO(acolwell): When we start allowing SourceBuffers that are not active,
   1709   // we'll need to update this loop to only add ranges from active sources.
   1710   RangesList ranges_list;
   1711   for (SourceStateMap::const_iterator itr = source_state_map_.begin();
   1712        itr != source_state_map_.end(); ++itr) {
   1713     ranges_list.push_back(itr->second->GetBufferedRanges(duration_, ended));
   1714   }
   1715 
   1716   return ComputeIntersection(ranges_list, ended);
   1717 }
   1718 
   1719 void ChunkDemuxer::StartReturningData() {
   1720   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1721        itr != source_state_map_.end(); ++itr) {
   1722     itr->second->StartReturningData();
   1723   }
   1724 }
   1725 
   1726 void ChunkDemuxer::AbortPendingReads() {
   1727   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1728        itr != source_state_map_.end(); ++itr) {
   1729     itr->second->AbortReads();
   1730   }
   1731 }
   1732 
   1733 void ChunkDemuxer::SeekAllSources(TimeDelta seek_time) {
   1734   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1735        itr != source_state_map_.end(); ++itr) {
   1736     itr->second->Seek(seek_time);
   1737   }
   1738 }
   1739 
   1740 void ChunkDemuxer::CompletePendingReadsIfPossible() {
   1741   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1742        itr != source_state_map_.end(); ++itr) {
   1743     itr->second->CompletePendingReadIfPossible();
   1744   }
   1745 }
   1746 
   1747 void ChunkDemuxer::ShutdownAllStreams() {
   1748   for (SourceStateMap::iterator itr = source_state_map_.begin();
   1749        itr != source_state_map_.end(); ++itr) {
   1750     itr->second->Shutdown();
   1751   }
   1752 }
   1753 
   1754 }  // namespace media
   1755