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 <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/base64.h" | 10 #include "base/base64.h" |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 template <class T> // T has int width() & height() methods. | 107 template <class T> // T has int width() & height() methods. |
108 static void UmaHistogramAspectRatio(const char* name, const T& size) { | 108 static void UmaHistogramAspectRatio(const char* name, const T& size) { |
109 UMA_HISTOGRAM_CUSTOM_ENUMERATION( | 109 UMA_HISTOGRAM_CUSTOM_ENUMERATION( |
110 name, | 110 name, |
111 // Intentionally use integer division to truncate the result. | 111 // Intentionally use integer division to truncate the result. |
112 size.height() ? (size.width() * 100) / size.height() : kInfiniteRatio, | 112 size.height() ? (size.width() * 100) / size.height() : kInfiniteRatio, |
113 base::CustomHistogram::ArrayToCustomRanges( | 113 base::CustomHistogram::ArrayToCustomRanges( |
114 kCommonAspectRatios100, arraysize(kCommonAspectRatios100))); | 114 kCommonAspectRatios100, arraysize(kCommonAspectRatios100))); |
115 } | 115 } |
116 | 116 |
| 117 // Record detected track counts by type corresponding to a src= playback. |
| 118 // Counts are split into 50 buckets, capped into [0,100] range. |
| 119 static void RecordDetectedTrackTypeStats(int audio_count, |
| 120 int video_count, |
| 121 int text_count) { |
| 122 UMA_HISTOGRAM_COUNTS_100("Media.DetectedTrackCount.Audio", audio_count); |
| 123 UMA_HISTOGRAM_COUNTS_100("Media.DetectedTrackCount.Video", video_count); |
| 124 UMA_HISTOGRAM_COUNTS_100("Media.DetectedTrackCount.Text", text_count); |
| 125 } |
| 126 |
117 // Record audio decoder config UMA stats corresponding to a src= playback. | 127 // Record audio decoder config UMA stats corresponding to a src= playback. |
118 static void RecordAudioCodecStats(const AudioDecoderConfig& audio_config) { | 128 static void RecordAudioCodecStats(const AudioDecoderConfig& audio_config) { |
119 UMA_HISTOGRAM_ENUMERATION("Media.AudioCodec", audio_config.codec(), | 129 UMA_HISTOGRAM_ENUMERATION("Media.AudioCodec", audio_config.codec(), |
120 kAudioCodecMax + 1); | 130 kAudioCodecMax + 1); |
121 UMA_HISTOGRAM_ENUMERATION("Media.AudioSampleFormat", | 131 UMA_HISTOGRAM_ENUMERATION("Media.AudioSampleFormat", |
122 audio_config.sample_format(), kSampleFormatMax + 1); | 132 audio_config.sample_format(), kSampleFormatMax + 1); |
123 UMA_HISTOGRAM_ENUMERATION("Media.AudioChannelLayout", | 133 UMA_HISTOGRAM_ENUMERATION("Media.AudioChannelLayout", |
124 audio_config.channel_layout(), | 134 audio_config.channel_layout(), |
125 CHANNEL_LAYOUT_MAX + 1); | 135 CHANNEL_LAYOUT_MAX + 1); |
126 AudioSampleRate asr; | 136 AudioSampleRate asr; |
(...skipping 966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 scoped_ptr<MediaTracks> media_tracks(new MediaTracks()); | 1103 scoped_ptr<MediaTracks> media_tracks(new MediaTracks()); |
1094 AVStream* audio_stream = NULL; | 1104 AVStream* audio_stream = NULL; |
1095 AudioDecoderConfig audio_config; | 1105 AudioDecoderConfig audio_config; |
1096 AVStream* video_stream = NULL; | 1106 AVStream* video_stream = NULL; |
1097 VideoDecoderConfig video_config; | 1107 VideoDecoderConfig video_config; |
1098 | 1108 |
1099 // If available, |start_time_| will be set to the lowest stream start time. | 1109 // If available, |start_time_| will be set to the lowest stream start time. |
1100 start_time_ = kInfiniteDuration(); | 1110 start_time_ = kInfiniteDuration(); |
1101 | 1111 |
1102 base::TimeDelta max_duration; | 1112 base::TimeDelta max_duration; |
| 1113 int detected_audio_track_count = 0; |
| 1114 int detected_video_track_count = 0; |
| 1115 int detected_text_track_count = 0; |
1103 for (size_t i = 0; i < format_context->nb_streams; ++i) { | 1116 for (size_t i = 0; i < format_context->nb_streams; ++i) { |
1104 AVStream* stream = format_context->streams[i]; | 1117 AVStream* stream = format_context->streams[i]; |
1105 const AVCodecContext* codec_context = stream->codec; | 1118 const AVCodecContext* codec_context = stream->codec; |
1106 const AVMediaType codec_type = codec_context->codec_type; | 1119 const AVMediaType codec_type = codec_context->codec_type; |
1107 | 1120 |
1108 if (codec_type == AVMEDIA_TYPE_AUDIO) { | 1121 if (codec_type == AVMEDIA_TYPE_AUDIO) { |
| 1122 // Log the codec detected, whether it is supported or not, and whether or |
| 1123 // not we have already detected a supported codec in another stream. |
| 1124 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedAudioCodecHash", |
| 1125 HashCodecName(GetCodecName(codec_context))); |
| 1126 detected_audio_track_count++; |
| 1127 |
1109 if (audio_stream) | 1128 if (audio_stream) |
1110 continue; | 1129 continue; |
| 1130 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { |
| 1131 // Log the codec detected, whether it is supported or not, and whether or |
| 1132 // not we have already detected a supported codec in another stream. |
| 1133 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedVideoCodecHash", |
| 1134 HashCodecName(GetCodecName(codec_context))); |
| 1135 detected_video_track_count++; |
1111 | 1136 |
1112 // Log the codec detected, whether it is supported or not. | |
1113 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedAudioCodecHash", | |
1114 HashCodecName(GetCodecName(codec_context))); | |
1115 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { | |
1116 if (video_stream) | 1137 if (video_stream) |
1117 continue; | 1138 continue; |
1118 | 1139 |
1119 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 1140 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
1120 if (stream->codec->codec_id == AV_CODEC_ID_HEVC) { | 1141 if (stream->codec->codec_id == AV_CODEC_ID_HEVC) { |
1121 // If ffmpeg is built without HEVC parser/decoder support, it will be | 1142 // If ffmpeg is built without HEVC parser/decoder support, it will be |
1122 // able to demux HEVC based solely on container-provided information, | 1143 // able to demux HEVC based solely on container-provided information, |
1123 // but unable to get some of the parameters without parsing the stream | 1144 // but unable to get some of the parameters without parsing the stream |
1124 // (e.g. coded size needs to be read from SPS, pixel format is typically | 1145 // (e.g. coded size needs to be read from SPS, pixel format is typically |
1125 // deduced from decoder config in hvcC box). These are not really needed | 1146 // deduced from decoder config in hvcC box). These are not really needed |
1126 // when using external decoder (e.g. hardware decoder), so override them | 1147 // when using external decoder (e.g. hardware decoder), so override them |
1127 // here, to make sure this translates into a valid VideoDecoderConfig. | 1148 // here, to make sure this translates into a valid VideoDecoderConfig. |
1128 if (stream->codec->coded_width == 0 && | 1149 if (stream->codec->coded_width == 0 && |
1129 stream->codec->coded_height == 0) { | 1150 stream->codec->coded_height == 0) { |
1130 DCHECK(stream->codec->width > 0); | 1151 DCHECK(stream->codec->width > 0); |
1131 DCHECK(stream->codec->height > 0); | 1152 DCHECK(stream->codec->height > 0); |
1132 stream->codec->coded_width = stream->codec->width; | 1153 stream->codec->coded_width = stream->codec->width; |
1133 stream->codec->coded_height = stream->codec->height; | 1154 stream->codec->coded_height = stream->codec->height; |
1134 } | 1155 } |
1135 if (stream->codec->pix_fmt == AV_PIX_FMT_NONE) { | 1156 if (stream->codec->pix_fmt == AV_PIX_FMT_NONE) { |
1136 stream->codec->pix_fmt = AV_PIX_FMT_YUV420P; | 1157 stream->codec->pix_fmt = AV_PIX_FMT_YUV420P; |
1137 } | 1158 } |
1138 } | 1159 } |
1139 #endif | 1160 #endif |
1140 // Log the codec detected, whether it is supported or not. | |
1141 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedVideoCodecHash", | |
1142 HashCodecName(GetCodecName(codec_context))); | |
1143 } else if (codec_type == AVMEDIA_TYPE_SUBTITLE) { | 1161 } else if (codec_type == AVMEDIA_TYPE_SUBTITLE) { |
| 1162 detected_text_track_count++; |
1144 if (codec_context->codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) { | 1163 if (codec_context->codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) { |
1145 continue; | 1164 continue; |
1146 } | 1165 } |
1147 } else { | 1166 } else { |
1148 continue; | 1167 continue; |
1149 } | 1168 } |
1150 | 1169 |
1151 // Attempt to create a FFmpegDemuxerStream from the AVStream. This will | 1170 // Attempt to create a FFmpegDemuxerStream from the AVStream. This will |
1152 // return nullptr if the AVStream is invalid. Validity checks will verify | 1171 // return nullptr if the AVStream is invalid. Validity checks will verify |
1153 // things like: codec, channel layout, sample/pixel format, etc... | 1172 // things like: codec, channel layout, sample/pixel format, etc... |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 | 1230 |
1212 if (start_time < start_time_) { | 1231 if (start_time < start_time_) { |
1213 start_time_ = start_time; | 1232 start_time_ = start_time; |
1214 | 1233 |
1215 // Choose the stream with the lowest starting time as the fallback stream | 1234 // Choose the stream with the lowest starting time as the fallback stream |
1216 // for seeking. Video should always be preferred. | 1235 // for seeking. Video should always be preferred. |
1217 fallback_stream_for_seeking_ = StreamSeekInfo(i, start_time); | 1236 fallback_stream_for_seeking_ = StreamSeekInfo(i, start_time); |
1218 } | 1237 } |
1219 } | 1238 } |
1220 | 1239 |
| 1240 RecordDetectedTrackTypeStats(detected_audio_track_count, |
| 1241 detected_video_track_count, |
| 1242 detected_text_track_count); |
| 1243 |
1221 if (!audio_stream && !video_stream) { | 1244 if (!audio_stream && !video_stream) { |
1222 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() | 1245 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() |
1223 << ": no supported streams"; | 1246 << ": no supported streams"; |
1224 status_cb.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); | 1247 status_cb.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); |
1225 return; | 1248 return; |
1226 } | 1249 } |
1227 | 1250 |
1228 if (text_enabled_) | 1251 if (text_enabled_) |
1229 AddTextStreams(); | 1252 AddTextStreams(); |
1230 | 1253 |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1538 | 1561 |
1539 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1562 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
1540 DCHECK(task_runner_->BelongsToCurrentThread()); | 1563 DCHECK(task_runner_->BelongsToCurrentThread()); |
1541 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. | 1564 for (const auto& stream : streams_) { // |stream| is a ref to a pointer. |
1542 if (stream) | 1565 if (stream) |
1543 stream->SetLiveness(liveness); | 1566 stream->SetLiveness(liveness); |
1544 } | 1567 } |
1545 } | 1568 } |
1546 | 1569 |
1547 } // namespace media | 1570 } // namespace media |
OLD | NEW |