Home | History | Annotate | Download | only in base
      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/base/stream_parser_buffer.h"
      6 
      7 #include "base/logging.h"
      8 #include "media/base/buffers.h"
      9 
     10 namespace media {
     11 
     12 static scoped_refptr<StreamParserBuffer> CopyBuffer(
     13     const StreamParserBuffer& buffer) {
     14   if (buffer.end_of_stream())
     15     return StreamParserBuffer::CreateEOSBuffer();
     16 
     17   scoped_refptr<StreamParserBuffer> copied_buffer =
     18       StreamParserBuffer::CopyFrom(buffer.data(),
     19                                    buffer.data_size(),
     20                                    buffer.side_data(),
     21                                    buffer.side_data_size(),
     22                                    buffer.IsKeyframe(),
     23                                    buffer.type(),
     24                                    buffer.track_id());
     25   copied_buffer->SetDecodeTimestamp(buffer.GetDecodeTimestamp());
     26   copied_buffer->SetConfigId(buffer.GetConfigId());
     27   copied_buffer->set_timestamp(buffer.timestamp());
     28   copied_buffer->set_duration(buffer.duration());
     29   copied_buffer->set_discard_padding(buffer.discard_padding());
     30   copied_buffer->set_splice_timestamp(buffer.splice_timestamp());
     31   const DecryptConfig* decrypt_config = buffer.decrypt_config();
     32   if (decrypt_config) {
     33     copied_buffer->set_decrypt_config(
     34         make_scoped_ptr(new DecryptConfig(decrypt_config->key_id(),
     35                                           decrypt_config->iv(),
     36                                           decrypt_config->subsamples())));
     37   }
     38 
     39   return copied_buffer;
     40 }
     41 
     42 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer() {
     43   return make_scoped_refptr(new StreamParserBuffer(NULL, 0, NULL, 0, false,
     44                                                    DemuxerStream::UNKNOWN, 0));
     45 }
     46 
     47 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom(
     48     const uint8* data, int data_size, bool is_keyframe, Type type,
     49     TrackId track_id) {
     50   return make_scoped_refptr(
     51       new StreamParserBuffer(data, data_size, NULL, 0, is_keyframe, type,
     52                              track_id));
     53 }
     54 
     55 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CopyFrom(
     56     const uint8* data, int data_size,
     57     const uint8* side_data, int side_data_size,
     58     bool is_keyframe, Type type, TrackId track_id) {
     59   return make_scoped_refptr(
     60       new StreamParserBuffer(data, data_size, side_data, side_data_size,
     61                              is_keyframe, type, track_id));
     62 }
     63 
     64 DecodeTimestamp StreamParserBuffer::GetDecodeTimestamp() const {
     65   if (decode_timestamp_ == kNoDecodeTimestamp())
     66     return DecodeTimestamp::FromPresentationTime(timestamp());
     67   return decode_timestamp_;
     68 }
     69 
     70 void StreamParserBuffer::SetDecodeTimestamp(DecodeTimestamp timestamp) {
     71   decode_timestamp_ = timestamp;
     72   if (preroll_buffer_.get())
     73     preroll_buffer_->SetDecodeTimestamp(timestamp);
     74 }
     75 
     76 StreamParserBuffer::StreamParserBuffer(const uint8* data, int data_size,
     77                                        const uint8* side_data,
     78                                        int side_data_size, bool is_keyframe,
     79                                        Type type, TrackId track_id)
     80     : DecoderBuffer(data, data_size, side_data, side_data_size),
     81       is_keyframe_(is_keyframe),
     82       decode_timestamp_(kNoDecodeTimestamp()),
     83       config_id_(kInvalidConfigId),
     84       type_(type),
     85       track_id_(track_id) {
     86   // TODO(scherkus): Should DataBuffer constructor accept a timestamp and
     87   // duration to force clients to set them? Today they end up being zero which
     88   // is both a common and valid value and could lead to bugs.
     89   if (data) {
     90     set_duration(kNoTimestamp());
     91   }
     92 }
     93 
     94 StreamParserBuffer::~StreamParserBuffer() {}
     95 
     96 int StreamParserBuffer::GetConfigId() const {
     97   return config_id_;
     98 }
     99 
    100 void StreamParserBuffer::SetConfigId(int config_id) {
    101   config_id_ = config_id;
    102   if (preroll_buffer_.get())
    103     preroll_buffer_->SetConfigId(config_id);
    104 }
    105 
    106 int StreamParserBuffer::GetSpliceBufferConfigId(size_t index) const {
    107   return index < splice_buffers().size()
    108       ? splice_buffers_[index]->GetConfigId()
    109       : GetConfigId();
    110 }
    111 
    112 void StreamParserBuffer::ConvertToSpliceBuffer(
    113     const BufferQueue& pre_splice_buffers) {
    114   DCHECK(splice_buffers_.empty());
    115   DCHECK(duration() > base::TimeDelta())
    116       << "Only buffers with a valid duration can convert to a splice buffer."
    117       << " pts " << timestamp().InSecondsF()
    118       << " dts " << GetDecodeTimestamp().InSecondsF()
    119       << " dur " << duration().InSecondsF();
    120   DCHECK(!end_of_stream());
    121 
    122   // Make a copy of this first, before making any changes.
    123   scoped_refptr<StreamParserBuffer> overlapping_buffer = CopyBuffer(*this);
    124   overlapping_buffer->set_splice_timestamp(kNoTimestamp());
    125 
    126   const scoped_refptr<StreamParserBuffer>& first_splice_buffer =
    127       pre_splice_buffers.front();
    128 
    129   // Ensure the given buffers are actually before the splice point.
    130   DCHECK(first_splice_buffer->timestamp() <= overlapping_buffer->timestamp());
    131 
    132   // TODO(dalecurtis): We should also clear |data| and |side_data|, but since
    133   // that implies EOS care must be taken to ensure there are no clients relying
    134   // on that behavior.
    135 
    136   // Move over any preroll from this buffer.
    137   if (preroll_buffer_.get()) {
    138     DCHECK(!overlapping_buffer->preroll_buffer_.get());
    139     overlapping_buffer->preroll_buffer_.swap(preroll_buffer_);
    140   }
    141 
    142   // Rewrite |this| buffer as a splice buffer.
    143   SetDecodeTimestamp(first_splice_buffer->GetDecodeTimestamp());
    144   SetConfigId(first_splice_buffer->GetConfigId());
    145   set_timestamp(first_splice_buffer->timestamp());
    146   is_keyframe_ = first_splice_buffer->IsKeyframe();
    147   type_ = first_splice_buffer->type();
    148   track_id_ = first_splice_buffer->track_id();
    149   set_splice_timestamp(overlapping_buffer->timestamp());
    150 
    151   // The splice duration is the duration of all buffers before the splice plus
    152   // the highest ending timestamp after the splice point.
    153   DCHECK(overlapping_buffer->duration() > base::TimeDelta());
    154   DCHECK(pre_splice_buffers.back()->duration() > base::TimeDelta());
    155   set_duration(
    156       std::max(overlapping_buffer->timestamp() + overlapping_buffer->duration(),
    157                pre_splice_buffers.back()->timestamp() +
    158                    pre_splice_buffers.back()->duration()) -
    159       first_splice_buffer->timestamp());
    160 
    161   // Copy all pre splice buffers into our wrapper buffer.
    162   for (BufferQueue::const_iterator it = pre_splice_buffers.begin();
    163        it != pre_splice_buffers.end();
    164        ++it) {
    165     const scoped_refptr<StreamParserBuffer>& buffer = *it;
    166     DCHECK(!buffer->end_of_stream());
    167     DCHECK(!buffer->preroll_buffer().get());
    168     DCHECK(buffer->splice_buffers().empty());
    169     splice_buffers_.push_back(CopyBuffer(*buffer.get()));
    170     splice_buffers_.back()->set_splice_timestamp(splice_timestamp());
    171   }
    172 
    173   splice_buffers_.push_back(overlapping_buffer);
    174 }
    175 
    176 void StreamParserBuffer::SetPrerollBuffer(
    177     const scoped_refptr<StreamParserBuffer>& preroll_buffer) {
    178   DCHECK(!preroll_buffer_.get());
    179   DCHECK(!end_of_stream());
    180   DCHECK(!preroll_buffer->end_of_stream());
    181   DCHECK(!preroll_buffer->preroll_buffer_.get());
    182   DCHECK(preroll_buffer->splice_timestamp() == kNoTimestamp());
    183   DCHECK(preroll_buffer->splice_buffers().empty());
    184   DCHECK(preroll_buffer->timestamp() <= timestamp());
    185   DCHECK(preroll_buffer->discard_padding() == DecoderBuffer::DiscardPadding());
    186   DCHECK_EQ(preroll_buffer->type(), type());
    187   DCHECK_EQ(preroll_buffer->track_id(), track_id());
    188 
    189   preroll_buffer_ = preroll_buffer;
    190   preroll_buffer_->set_timestamp(timestamp());
    191   preroll_buffer_->SetDecodeTimestamp(GetDecodeTimestamp());
    192 
    193   // Mark the entire buffer for discard.
    194   preroll_buffer_->set_discard_padding(
    195       std::make_pair(kInfiniteDuration(), base::TimeDelta()));
    196 }
    197 
    198 void StreamParserBuffer::set_timestamp(base::TimeDelta timestamp) {
    199   DecoderBuffer::set_timestamp(timestamp);
    200   if (preroll_buffer_.get())
    201     preroll_buffer_->set_timestamp(timestamp);
    202 }
    203 
    204 }  // namespace media
    205