Chromium Code Reviews| 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 |