| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2017 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/mojo/clients/mojo_demuxer_source_buffer.h" |
| 6 |
| 7 #include "base/callback_helpers.h" |
| 8 #include "media/base/data_buffer.h" |
| 9 #include "media/base/media_tracks.h" |
| 10 #include "media/mojo/common/media_type_converters.h" |
| 11 #include "media/mojo/common/mojo_data_buffer_converter.h" |
| 12 |
| 13 using base::TimeDelta; |
| 14 |
| 15 namespace media { |
| 16 |
| 17 MojoDemuxerSourceBuffer::MojoDemuxerSourceBuffer( |
| 18 int32_t id, |
| 19 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, |
| 20 const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, |
| 21 mojom::DemuxerPtr mojo_demuxer, |
| 22 mojom::SourceBufferPtr mojo_source_buffer, |
| 23 const base::Closure& open_cb, |
| 24 const Demuxer::EncryptedMediaInitDataCB& encrypted_media_init_data_cb) |
| 25 : MojoDemuxer(id, |
| 26 Demuxer::LoadType::LoadTypeMediaSource, |
| 27 nullptr, |
| 28 media_task_runner, |
| 29 std::move(mojo_demuxer), |
| 30 open_cb, |
| 31 encrypted_media_init_data_cb, |
| 32 base::Bind(&MojoDemuxerSourceBuffer::OnMediaTracksDoNothing, |
| 33 base::Unretained(this))), |
| 34 main_task_runner_(main_task_runner), |
| 35 remote_source_buffer_(std::move(mojo_source_buffer)), |
| 36 client_binding_(this), |
| 37 duration_(0), |
| 38 weak_factory_(this) { |
| 39 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 40 DCHECK(remote_source_buffer_); |
| 41 |
| 42 remote_source_buffer_.set_connection_error_handler(base::Bind( |
| 43 &MojoDemuxerSourceBuffer::OnConnectionError, weak_factory_.GetWeakPtr())); |
| 44 } |
| 45 |
| 46 MojoDemuxerSourceBuffer::~MojoDemuxerSourceBuffer() {} |
| 47 |
| 48 std::string MojoDemuxerSourceBuffer::GetDisplayName() const { |
| 49 return "MojoDemuxerSourceBuffer"; |
| 50 } |
| 51 |
| 52 void MojoDemuxerSourceBuffer::Initialize(DemuxerHost* host, |
| 53 const PipelineStatusCB& status_cb, |
| 54 bool enable_text_tracks) { |
| 55 CHECK(media_task_runner_->BelongsToCurrentThread()); |
| 56 |
| 57 MojoDemuxer::Initialize(host, status_cb, enable_text_tracks); |
| 58 |
| 59 main_task_runner_->PostTask( |
| 60 FROM_HERE, base::Bind(&MojoDemuxerSourceBuffer::InitializeInternal, |
| 61 weak_factory_.GetWeakPtr())); |
| 62 } |
| 63 |
| 64 void MojoDemuxerSourceBuffer::InitializeInternal() { |
| 65 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 66 |
| 67 mojom::SourceBufferClientAssociatedPtrInfo client_ptr_info; |
| 68 client_binding_.Bind(&client_ptr_info, |
| 69 remote_source_buffer_.associated_group()); |
| 70 |
| 71 mojo::ScopedDataPipeConsumerHandle remote_consumer_handle; |
| 72 |
| 73 // TODO(j.isorce): fix TODO in media/mojo/common/mojo_data_buffer_converter.cc |
| 74 // CreateDataPipe first and reflect the fix here. For now the following value |
| 75 // should be enough for audio + video. |
| 76 mojo_data_buffer_writer_ = MojoDataBufferWriter::Create( |
| 77 /* capacity_num_bytes */ 3 * 1024 * 1024, &remote_consumer_handle); |
| 78 remote_source_buffer_->Initialize(std::move(client_ptr_info), GetRemoteId(), |
| 79 std::move(remote_consumer_handle)); |
| 80 } |
| 81 |
| 82 SourceBuffer::Status MojoDemuxerSourceBuffer::AddId(const std::string& id, |
| 83 const std::string& type, |
| 84 const std::string& codecs) { |
| 85 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 86 |
| 87 SourceBuffer::Status status = SourceBuffer::Status::kOk; |
| 88 remote_source_buffer_->AddId(id, type, codecs, &status); |
| 89 |
| 90 return status; |
| 91 } |
| 92 |
| 93 bool MojoDemuxerSourceBuffer::AppendData(const std::string& id, |
| 94 const uint8_t* data, |
| 95 size_t length, |
| 96 base::TimeDelta append_window_start, |
| 97 base::TimeDelta append_window_end, |
| 98 base::TimeDelta* timestamp_offset) { |
| 99 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 100 |
| 101 scoped_refptr<media::DataBuffer> buffer = |
| 102 media::DataBuffer::CopyFrom(data, length); |
| 103 mojom::DataBufferPtr mojo_buffer = |
| 104 mojo_data_buffer_writer_->WriteDataBuffer(buffer); |
| 105 |
| 106 bool success = false; |
| 107 remote_source_buffer_->AppendData(id, std::move(mojo_buffer), |
| 108 append_window_start, append_window_end, |
| 109 &success, timestamp_offset); |
| 110 |
| 111 return success; |
| 112 } |
| 113 |
| 114 void MojoDemuxerSourceBuffer::SetTracksWatcher( |
| 115 const std::string& id, |
| 116 const MediaTracksUpdatedCB& tracks_updated_cb) { |
| 117 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 118 |
| 119 tracks_updated_callbacks_map_[id] = tracks_updated_cb; |
| 120 |
| 121 remote_source_buffer_->SetTracksWatcher(id); |
| 122 } |
| 123 |
| 124 void MojoDemuxerSourceBuffer::OnTracksWatcher( |
| 125 const std::string& id, |
| 126 mojom::MediaTracksPtr mojo_tracks) { |
| 127 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 128 CHECK(!tracks_updated_callbacks_map_[id].is_null()); |
| 129 |
| 130 if (!mojo_tracks) { |
| 131 media_task_runner_->PostTask( |
| 132 FROM_HERE, |
| 133 base::Bind(&MojoDemuxer::OnDemuxerError, weak_factory_.GetWeakPtr(), |
| 134 PIPELINE_ERROR_INVALID_STATE)); |
| 135 tracks_updated_callbacks_map_[id].Run(base::MakeUnique<MediaTracks>()); |
| 136 return; |
| 137 } |
| 138 |
| 139 std::unique_ptr<MediaTracks> tracks( |
| 140 mojo_tracks.To<std::unique_ptr<MediaTracks>>()); |
| 141 |
| 142 CHECK(tracks); |
| 143 tracks_updated_callbacks_map_[id].Run(std::move(tracks)); |
| 144 } |
| 145 |
| 146 void MojoDemuxerSourceBuffer::RemoveId(const std::string& id) { |
| 147 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 148 |
| 149 remote_source_buffer_->RemoveId(id); |
| 150 } |
| 151 |
| 152 Ranges<base::TimeDelta> MojoDemuxerSourceBuffer::GetBufferedRanges( |
| 153 const std::string& id) const { |
| 154 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 155 |
| 156 mojom::RangesTimeDeltaPtr mojo_ranges; |
| 157 remote_source_buffer_->GetBufferedRanges(id, &mojo_ranges); |
| 158 |
| 159 if (!mojo_ranges) { |
| 160 media_task_runner_->PostTask( |
| 161 FROM_HERE, base::Bind(&MojoDemuxer::OnDemuxerError, |
| 162 const_cast<MojoDemuxerSourceBuffer*>(this) |
| 163 ->weak_factory_.GetWeakPtr(), |
| 164 PIPELINE_ERROR_INVALID_STATE)); |
| 165 return Ranges<base::TimeDelta>(); |
| 166 } |
| 167 |
| 168 Ranges<base::TimeDelta> ranges = mojo_ranges.To<Ranges<base::TimeDelta>>(); |
| 169 return ranges; |
| 170 } |
| 171 |
| 172 base::TimeDelta MojoDemuxerSourceBuffer::GetHighestPresentationTimestamp( |
| 173 const std::string& id) const { |
| 174 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 175 |
| 176 base::TimeDelta timestamp; |
| 177 remote_source_buffer_->GetHighestPresentationTimestamp(id, ×tamp); |
| 178 return timestamp; |
| 179 } |
| 180 |
| 181 void MojoDemuxerSourceBuffer::ResetParserState( |
| 182 const std::string& id, |
| 183 base::TimeDelta append_window_start, |
| 184 base::TimeDelta append_window_end, |
| 185 base::TimeDelta* timestamp_offset) { |
| 186 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 187 DCHECK(timestamp_offset); |
| 188 remote_source_buffer_->ResetParserState(id, append_window_start, |
| 189 append_window_end, timestamp_offset); |
| 190 } |
| 191 |
| 192 void MojoDemuxerSourceBuffer::Remove(const std::string& id, |
| 193 base::TimeDelta start, |
| 194 base::TimeDelta end) { |
| 195 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 196 remote_source_buffer_->Remove(id, start, end); |
| 197 } |
| 198 |
| 199 bool MojoDemuxerSourceBuffer::EvictCodedFrames(const std::string& id, |
| 200 base::TimeDelta currentMediaTime, |
| 201 size_t newDataSize) { |
| 202 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 203 bool success = false; |
| 204 remote_source_buffer_->EvictCodedFrames(id, currentMediaTime, newDataSize, |
| 205 &success); |
| 206 return success; |
| 207 } |
| 208 |
| 209 void MojoDemuxerSourceBuffer::OnMemoryPressure( |
| 210 base::TimeDelta currentMediaTime, |
| 211 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level, |
| 212 bool force_instant_gc) { |
| 213 CHECK(media_task_runner_->BelongsToCurrentThread()); |
| 214 |
| 215 main_task_runner_->PostTask( |
| 216 FROM_HERE, base::Bind(&MojoDemuxerSourceBuffer::OnMemoryPressureInternal, |
| 217 weak_factory_.GetWeakPtr(), currentMediaTime, |
| 218 memory_pressure_level, force_instant_gc)); |
| 219 } |
| 220 |
| 221 void MojoDemuxerSourceBuffer::OnMemoryPressureInternal( |
| 222 base::TimeDelta currentMediaTime, |
| 223 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level, |
| 224 bool force_instant_gc) { |
| 225 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 226 remote_source_buffer_->OnMemoryPressure( |
| 227 currentMediaTime, memory_pressure_level, force_instant_gc); |
| 228 } |
| 229 |
| 230 double MojoDemuxerSourceBuffer::GetDuration() { |
| 231 return duration_; |
| 232 } |
| 233 |
| 234 double MojoDemuxerSourceBuffer::GetDuration_Locked() { |
| 235 return duration_; |
| 236 } |
| 237 |
| 238 void MojoDemuxerSourceBuffer::SetDuration(double duration) { |
| 239 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 240 CHECK(mojo_data_buffer_writer_); |
| 241 |
| 242 duration_ = duration; |
| 243 remote_source_buffer_->SetDuration(duration); |
| 244 } |
| 245 |
| 246 bool MojoDemuxerSourceBuffer::IsParsingMediaSegment(const std::string& id) { |
| 247 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 248 bool is_parsing = false; |
| 249 remote_source_buffer_->IsParsingMediaSegment(id, &is_parsing); |
| 250 return is_parsing; |
| 251 } |
| 252 |
| 253 void MojoDemuxerSourceBuffer::SetSequenceMode(const std::string& id, |
| 254 bool sequence_mode) { |
| 255 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 256 remote_source_buffer_->SetSequenceMode(id, sequence_mode); |
| 257 } |
| 258 |
| 259 void MojoDemuxerSourceBuffer::SetGroupStartTimestampIfInSequenceMode( |
| 260 const std::string& id, |
| 261 base::TimeDelta timestamp_offset) { |
| 262 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 263 remote_source_buffer_->SetGroupStartTimestampIfInSequenceMode( |
| 264 id, timestamp_offset); |
| 265 } |
| 266 |
| 267 void MojoDemuxerSourceBuffer::MarkEndOfStream(PipelineStatus status) { |
| 268 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 269 remote_source_buffer_->MarkEndOfStream(status); |
| 270 } |
| 271 |
| 272 void MojoDemuxerSourceBuffer::UnmarkEndOfStream() { |
| 273 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 274 remote_source_buffer_->UnmarkEndOfStream(); |
| 275 } |
| 276 |
| 277 void MojoDemuxerSourceBuffer::Shutdown() { |
| 278 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 279 remote_source_buffer_->Shutdown(); |
| 280 } |
| 281 |
| 282 void MojoDemuxerSourceBuffer::SetMemoryLimitsForTest(DemuxerStream::Type type, |
| 283 size_t memory_limit) {} |
| 284 |
| 285 Ranges<base::TimeDelta> MojoDemuxerSourceBuffer::GetBufferedRanges() const { |
| 286 return Ranges<base::TimeDelta>(); |
| 287 } |
| 288 |
| 289 void MojoDemuxerSourceBuffer::OnConnectionError() { |
| 290 CHECK(main_task_runner_->BelongsToCurrentThread()); |
| 291 |
| 292 media_task_runner_->PostTask( |
| 293 FROM_HERE, base::Bind(&MojoDemuxer::OnDemuxerError, |
| 294 weak_factory_.GetWeakPtr(), PIPELINE_ERROR_READ)); |
| 295 } |
| 296 |
| 297 void MojoDemuxerSourceBuffer::OnMediaTracksDoNothing( |
| 298 std::unique_ptr<MediaTracks> tracks) { |
| 299 // Nothing to do since it is done another way around for SourceBuffer, see |
| 300 // TrackWatcher. |
| 301 } |
| 302 |
| 303 } // namespace media |
| OLD | NEW |