OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/filters/ffmpeg_demuxer.h" | 5 #include "media/filters/ffmpeg_demuxer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <memory> | |
ddorwin
2016/04/21 22:54:54
This is the first non-test .cc file to have this a
| |
8 #include <utility> | 9 #include <utility> |
9 | 10 |
10 #include "base/base64.h" | 11 #include "base/base64.h" |
11 #include "base/bind.h" | 12 #include "base/bind.h" |
12 #include "base/callback_helpers.h" | 13 #include "base/callback_helpers.h" |
13 #include "base/macros.h" | 14 #include "base/macros.h" |
14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/ptr_util.h" |
15 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
16 #include "base/metrics/sparse_histogram.h" | 17 #include "base/metrics/sparse_histogram.h" |
17 #include "base/single_thread_task_runner.h" | 18 #include "base/single_thread_task_runner.h" |
18 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
19 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
20 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
21 #include "base/sys_byteorder.h" | 22 #include "base/sys_byteorder.h" |
22 #include "base/task_runner_util.h" | 23 #include "base/task_runner_util.h" |
23 #include "base/thread_task_runner_handle.h" | 24 #include "base/thread_task_runner_handle.h" |
24 #include "base/time/time.h" | 25 #include "base/time/time.h" |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
189 const std::string& key, | 190 const std::string& key, |
190 base::TimeDelta value) { | 191 base::TimeDelta value) { |
191 if (value == kInfiniteDuration()) | 192 if (value == kInfiniteDuration()) |
192 event->params.SetString(key, "kInfiniteDuration"); | 193 event->params.SetString(key, "kInfiniteDuration"); |
193 else if (value == kNoTimestamp()) | 194 else if (value == kNoTimestamp()) |
194 event->params.SetString(key, "kNoTimestamp"); | 195 event->params.SetString(key, "kNoTimestamp"); |
195 else | 196 else |
196 event->params.SetDouble(key, value.InSecondsF()); | 197 event->params.SetDouble(key, value.InSecondsF()); |
197 } | 198 } |
198 | 199 |
199 scoped_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create( | 200 std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create( |
200 FFmpegDemuxer* demuxer, | 201 FFmpegDemuxer* demuxer, |
201 AVStream* stream, | 202 AVStream* stream, |
202 const scoped_refptr<MediaLog>& media_log) { | 203 const scoped_refptr<MediaLog>& media_log) { |
203 if (!demuxer || !stream) | 204 if (!demuxer || !stream) |
204 return nullptr; | 205 return nullptr; |
205 | 206 |
206 scoped_ptr<FFmpegDemuxerStream> demuxer_stream; | 207 std::unique_ptr<FFmpegDemuxerStream> demuxer_stream; |
207 scoped_ptr<AudioDecoderConfig> audio_config; | 208 std::unique_ptr<AudioDecoderConfig> audio_config; |
208 scoped_ptr<VideoDecoderConfig> video_config; | 209 std::unique_ptr<VideoDecoderConfig> video_config; |
209 | 210 |
210 if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) { | 211 if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
211 audio_config.reset(new AudioDecoderConfig()); | 212 audio_config.reset(new AudioDecoderConfig()); |
212 | 213 |
213 // IsValidConfig() checks that the codec is supported and that the channel | 214 // IsValidConfig() checks that the codec is supported and that the channel |
214 // layout and sample format are valid. | 215 // layout and sample format are valid. |
215 // | 216 // |
216 // TODO(chcunningham): Change AVStreamToAudioDecoderConfig to check | 217 // TODO(chcunningham): Change AVStreamToAudioDecoderConfig to check |
217 // IsValidConfig internally and return a null scoped_ptr if not valid. | 218 // IsValidConfig internally and return a null scoped_ptr if not valid. |
218 if (!AVStreamToAudioDecoderConfig(stream, audio_config.get()) || | 219 if (!AVStreamToAudioDecoderConfig(stream, audio_config.get()) || |
(...skipping 17 matching lines...) Expand all Loading... | |
236 !video_config->IsValidConfig()) { | 237 !video_config->IsValidConfig()) { |
237 MEDIA_LOG(ERROR, media_log) | 238 MEDIA_LOG(ERROR, media_log) |
238 << "FFmpegDemuxer: failed creating video stream"; | 239 << "FFmpegDemuxer: failed creating video stream"; |
239 return nullptr; | 240 return nullptr; |
240 } | 241 } |
241 | 242 |
242 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created video stream, config " | 243 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created video stream, config " |
243 << video_config->AsHumanReadableString(); | 244 << video_config->AsHumanReadableString(); |
244 } | 245 } |
245 | 246 |
246 return make_scoped_ptr(new FFmpegDemuxerStream( | 247 return base::WrapUnique(new FFmpegDemuxerStream( |
247 demuxer, stream, std::move(audio_config), std::move(video_config))); | 248 demuxer, stream, std::move(audio_config), std::move(video_config))); |
248 } | 249 } |
249 | 250 |
250 // | 251 // |
251 // FFmpegDemuxerStream | 252 // FFmpegDemuxerStream |
252 // | 253 // |
253 FFmpegDemuxerStream::FFmpegDemuxerStream( | 254 FFmpegDemuxerStream::FFmpegDemuxerStream( |
254 FFmpegDemuxer* demuxer, | 255 FFmpegDemuxer* demuxer, |
255 AVStream* stream, | 256 AVStream* stream, |
256 scoped_ptr<AudioDecoderConfig> audio_config, | 257 std::unique_ptr<AudioDecoderConfig> audio_config, |
257 scoped_ptr<VideoDecoderConfig> video_config) | 258 std::unique_ptr<VideoDecoderConfig> video_config) |
258 : demuxer_(demuxer), | 259 : demuxer_(demuxer), |
259 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 260 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
260 stream_(stream), | 261 stream_(stream), |
261 audio_config_(audio_config.release()), | 262 audio_config_(audio_config.release()), |
262 video_config_(video_config.release()), | 263 video_config_(video_config.release()), |
263 type_(UNKNOWN), | 264 type_(UNKNOWN), |
264 liveness_(LIVENESS_UNKNOWN), | 265 liveness_(LIVENESS_UNKNOWN), |
265 end_of_stream_(false), | 266 end_of_stream_(false), |
266 last_packet_timestamp_(kNoTimestamp()), | 267 last_packet_timestamp_(kNoTimestamp()), |
267 last_packet_duration_(kNoTimestamp()), | 268 last_packet_duration_(kNoTimestamp()), |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 settings_data, settings_data + settings_size, | 382 settings_data, settings_data + settings_size, |
382 &side_data); | 383 &side_data); |
383 | 384 |
384 buffer = DecoderBuffer::CopyFrom(packet.get()->data, packet.get()->size, | 385 buffer = DecoderBuffer::CopyFrom(packet.get()->data, packet.get()->size, |
385 side_data.data(), side_data.size()); | 386 side_data.data(), side_data.size()); |
386 } else { | 387 } else { |
387 int side_data_size = 0; | 388 int side_data_size = 0; |
388 uint8_t* side_data = av_packet_get_side_data( | 389 uint8_t* side_data = av_packet_get_side_data( |
389 packet.get(), AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); | 390 packet.get(), AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); |
390 | 391 |
391 scoped_ptr<DecryptConfig> decrypt_config; | 392 std::unique_ptr<DecryptConfig> decrypt_config; |
392 int data_offset = 0; | 393 int data_offset = 0; |
393 if ((type() == DemuxerStream::AUDIO && audio_config_->is_encrypted()) || | 394 if ((type() == DemuxerStream::AUDIO && audio_config_->is_encrypted()) || |
394 (type() == DemuxerStream::VIDEO && video_config_->is_encrypted())) { | 395 (type() == DemuxerStream::VIDEO && video_config_->is_encrypted())) { |
395 if (!WebMCreateDecryptConfig( | 396 if (!WebMCreateDecryptConfig( |
396 packet->data, packet->size, | 397 packet->data, packet->size, |
397 reinterpret_cast<const uint8_t*>(encryption_key_id_.data()), | 398 reinterpret_cast<const uint8_t*>(encryption_key_id_.data()), |
398 encryption_key_id_.size(), &decrypt_config, &data_offset)) { | 399 encryption_key_id_.size(), &decrypt_config, &data_offset)) { |
399 LOG(ERROR) << "Creation of DecryptConfig failed."; | 400 LOG(ERROR) << "Creation of DecryptConfig failed."; |
400 } | 401 } |
401 } | 402 } |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1104 if (packet_buffer->pkt.pts != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 1105 if (packet_buffer->pkt.pts != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
1105 const base::TimeDelta packet_pts = | 1106 const base::TimeDelta packet_pts = |
1106 ConvertFromTimeBase(stream->time_base, packet_buffer->pkt.pts); | 1107 ConvertFromTimeBase(stream->time_base, packet_buffer->pkt.pts); |
1107 if (packet_pts < start_time_estimates[stream->index]) | 1108 if (packet_pts < start_time_estimates[stream->index]) |
1108 start_time_estimates[stream->index] = packet_pts; | 1109 start_time_estimates[stream->index] = packet_pts; |
1109 } | 1110 } |
1110 packet_buffer = packet_buffer->next; | 1111 packet_buffer = packet_buffer->next; |
1111 } | 1112 } |
1112 } | 1113 } |
1113 | 1114 |
1114 scoped_ptr<MediaTracks> media_tracks(new MediaTracks()); | 1115 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks()); |
1115 AVStream* audio_stream = NULL; | 1116 AVStream* audio_stream = NULL; |
1116 AudioDecoderConfig audio_config; | 1117 AudioDecoderConfig audio_config; |
1117 AVStream* video_stream = NULL; | 1118 AVStream* video_stream = NULL; |
1118 VideoDecoderConfig video_config; | 1119 VideoDecoderConfig video_config; |
1119 | 1120 |
1120 // If available, |start_time_| will be set to the lowest stream start time. | 1121 // If available, |start_time_| will be set to the lowest stream start time. |
1121 start_time_ = kInfiniteDuration(); | 1122 start_time_ = kInfiniteDuration(); |
1122 | 1123 |
1123 base::TimeDelta max_duration; | 1124 base::TimeDelta max_duration; |
1124 int detected_audio_track_count = 0; | 1125 int detected_audio_track_count = 0; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1180 if (codec_context->codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) { | 1181 if (codec_context->codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) { |
1181 continue; | 1182 continue; |
1182 } | 1183 } |
1183 } else { | 1184 } else { |
1184 continue; | 1185 continue; |
1185 } | 1186 } |
1186 | 1187 |
1187 // Attempt to create a FFmpegDemuxerStream from the AVStream. This will | 1188 // Attempt to create a FFmpegDemuxerStream from the AVStream. This will |
1188 // return nullptr if the AVStream is invalid. Validity checks will verify | 1189 // return nullptr if the AVStream is invalid. Validity checks will verify |
1189 // things like: codec, channel layout, sample/pixel format, etc... | 1190 // things like: codec, channel layout, sample/pixel format, etc... |
1190 scoped_ptr<FFmpegDemuxerStream> demuxer_stream = | 1191 std::unique_ptr<FFmpegDemuxerStream> demuxer_stream = |
1191 FFmpegDemuxerStream::Create(this, stream, media_log_); | 1192 FFmpegDemuxerStream::Create(this, stream, media_log_); |
1192 if (demuxer_stream.get()) { | 1193 if (demuxer_stream.get()) { |
1193 streams_[i] = demuxer_stream.release(); | 1194 streams_[i] = demuxer_stream.release(); |
1194 } else { | 1195 } else { |
1195 if (codec_type == AVMEDIA_TYPE_AUDIO) { | 1196 if (codec_type == AVMEDIA_TYPE_AUDIO) { |
1196 MEDIA_LOG(INFO, media_log_) | 1197 MEDIA_LOG(INFO, media_log_) |
1197 << GetDisplayName() | 1198 << GetDisplayName() |
1198 << ": skipping invalid or unsupported audio track"; | 1199 << ": skipping invalid or unsupported audio track"; |
1199 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { | 1200 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { |
1200 MEDIA_LOG(INFO, media_log_) | 1201 MEDIA_LOG(INFO, media_log_) |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1362 duration_known_ = (max_duration != kInfiniteDuration()); | 1363 duration_known_ = (max_duration != kInfiniteDuration()); |
1363 | 1364 |
1364 int64_t filesize_in_bytes = 0; | 1365 int64_t filesize_in_bytes = 0; |
1365 url_protocol_->GetSize(&filesize_in_bytes); | 1366 url_protocol_->GetSize(&filesize_in_bytes); |
1366 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); | 1367 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); |
1367 if (bitrate_ > 0) | 1368 if (bitrate_ > 0) |
1368 data_source_->SetBitrate(bitrate_); | 1369 data_source_->SetBitrate(bitrate_); |
1369 | 1370 |
1370 // Use a single MediaLogEvent to batch all parameter updates at once; this | 1371 // Use a single MediaLogEvent to batch all parameter updates at once; this |
1371 // prevents throttling of events due to the large number of updates here. | 1372 // prevents throttling of events due to the large number of updates here. |
1372 scoped_ptr<MediaLogEvent> metadata_event = | 1373 std::unique_ptr<MediaLogEvent> metadata_event = |
1373 media_log_->CreateEvent(MediaLogEvent::PROPERTY_CHANGE); | 1374 media_log_->CreateEvent(MediaLogEvent::PROPERTY_CHANGE); |
1374 | 1375 |
1375 // Audio logging. | 1376 // Audio logging. |
1376 metadata_event->params.SetBoolean("found_audio_stream", !!audio_stream); | 1377 metadata_event->params.SetBoolean("found_audio_stream", !!audio_stream); |
1377 if (audio_stream) { | 1378 if (audio_stream) { |
1378 const AVCodecContext* audio_codec = audio_stream->codec; | 1379 const AVCodecContext* audio_codec = audio_stream->codec; |
1379 metadata_event->params.SetString("audio_codec_name", | 1380 metadata_event->params.SetString("audio_codec_name", |
1380 GetCodecName(audio_codec)); | 1381 GetCodecName(audio_codec)); |
1381 metadata_event->params.SetInteger("audio_channels_count", | 1382 metadata_event->params.SetInteger("audio_channels_count", |
1382 audio_codec->channels); | 1383 audio_codec->channels); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1589 | 1590 |
1590 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1591 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
1591 DCHECK(task_runner_->BelongsToCurrentThread()); | 1592 DCHECK(task_runner_->BelongsToCurrentThread()); |
1592 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. | 1593 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. |
1593 if (stream) | 1594 if (stream) |
1594 stream->SetLiveness(liveness); | 1595 stream->SetLiveness(liveness); |
1595 } | 1596 } |
1596 } | 1597 } |
1597 | 1598 |
1598 } // namespace media | 1599 } // namespace media |
OLD | NEW |