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> | 8 #include <memory> |
9 #include <set> | 9 #include <set> |
10 #include <utility> | 10 #include <utility> |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 | 176 |
177 // Note the PRESUBMIT_IGNORE_UMA_MAX below, this silences the PRESUBMIT.py | 177 // Note the PRESUBMIT_IGNORE_UMA_MAX below, this silences the PRESUBMIT.py |
178 // check for uma enum max usage, since we're abusing | 178 // check for uma enum max usage, since we're abusing |
179 // UMA_HISTOGRAM_ENUMERATION to report a discrete value. | 179 // UMA_HISTOGRAM_ENUMERATION to report a discrete value. |
180 UMA_HISTOGRAM_ENUMERATION("Media.VideoColorRange", color_range, | 180 UMA_HISTOGRAM_ENUMERATION("Media.VideoColorRange", color_range, |
181 AVCOL_RANGE_NB); // PRESUBMIT_IGNORE_UMA_MAX | 181 AVCOL_RANGE_NB); // PRESUBMIT_IGNORE_UMA_MAX |
182 } | 182 } |
183 | 183 |
184 static const char kCodecNone[] = "none"; | 184 static const char kCodecNone[] = "none"; |
185 | 185 |
186 static const char* GetCodecName(const AVCodecContext* context) { | 186 static const char* GetCodecName(enum AVCodecID id) { |
187 if (context->codec_descriptor) | 187 const AVCodecDescriptor* codec_descriptor = avcodec_descriptor_get(id); |
188 return context->codec_descriptor->name; | |
189 const AVCodecDescriptor* codec_descriptor = | |
190 avcodec_descriptor_get(context->codec_id); | |
191 // If the codec name can't be determined, return none for tracking. | 188 // If the codec name can't be determined, return none for tracking. |
192 return codec_descriptor ? codec_descriptor->name : kCodecNone; | 189 return codec_descriptor ? codec_descriptor->name : kCodecNone; |
193 } | 190 } |
194 | 191 |
195 static void SetTimeProperty(MediaLogEvent* event, | 192 static void SetTimeProperty(MediaLogEvent* event, |
196 const std::string& key, | 193 const std::string& key, |
197 base::TimeDelta value) { | 194 base::TimeDelta value) { |
198 if (value == kInfiniteDuration) | 195 if (value == kInfiniteDuration) |
199 event->params.SetString(key, "kInfiniteDuration"); | 196 event->params.SetString(key, "kInfiniteDuration"); |
200 else if (value == kNoTimestamp) | 197 else if (value == kNoTimestamp) |
201 event->params.SetString(key, "kNoTimestamp"); | 198 event->params.SetString(key, "kNoTimestamp"); |
202 else | 199 else |
203 event->params.SetDouble(key, value.InSecondsF()); | 200 event->params.SetDouble(key, value.InSecondsF()); |
204 } | 201 } |
205 | 202 |
206 std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create( | 203 std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create( |
207 FFmpegDemuxer* demuxer, | 204 FFmpegDemuxer* demuxer, |
208 AVStream* stream, | 205 AVStream* stream, |
209 const scoped_refptr<MediaLog>& media_log) { | 206 const scoped_refptr<MediaLog>& media_log) { |
210 if (!demuxer || !stream) | 207 if (!demuxer || !stream) |
211 return nullptr; | 208 return nullptr; |
212 | 209 |
213 std::unique_ptr<FFmpegDemuxerStream> demuxer_stream; | 210 std::unique_ptr<FFmpegDemuxerStream> demuxer_stream; |
214 std::unique_ptr<AudioDecoderConfig> audio_config; | 211 std::unique_ptr<AudioDecoderConfig> audio_config; |
215 std::unique_ptr<VideoDecoderConfig> video_config; | 212 std::unique_ptr<VideoDecoderConfig> video_config; |
216 | 213 |
217 if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) { | 214 if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
218 audio_config.reset(new AudioDecoderConfig()); | 215 audio_config.reset(new AudioDecoderConfig()); |
219 | 216 |
220 // IsValidConfig() checks that the codec is supported and that the channel | 217 // IsValidConfig() checks that the codec is supported and that the channel |
221 // layout and sample format are valid. | 218 // layout and sample format are valid. |
222 // | 219 // |
223 // TODO(chcunningham): Change AVStreamToAudioDecoderConfig to check | 220 // TODO(chcunningham): Change AVStreamToAudioDecoderConfig to check |
224 // IsValidConfig internally and return a null scoped_ptr if not valid. | 221 // IsValidConfig internally and return a null scoped_ptr if not valid. |
225 if (!AVStreamToAudioDecoderConfig(stream, audio_config.get()) || | 222 if (!AVStreamToAudioDecoderConfig(stream, audio_config.get()) || |
226 !audio_config->IsValidConfig()) { | 223 !audio_config->IsValidConfig()) { |
227 MEDIA_LOG(ERROR, media_log) | 224 MEDIA_LOG(ERROR, media_log) |
228 << "FFmpegDemuxer: failed creating audio stream"; | 225 << "FFmpegDemuxer: failed creating audio stream"; |
229 return nullptr; | 226 return nullptr; |
230 } | 227 } |
231 | 228 |
232 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created audio stream, config " | 229 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created audio stream, config " |
233 << audio_config->AsHumanReadableString(); | 230 << audio_config->AsHumanReadableString(); |
234 } else if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) { | 231 } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { |
235 video_config.reset(new VideoDecoderConfig()); | 232 video_config.reset(new VideoDecoderConfig()); |
236 | 233 |
237 // IsValidConfig() checks that the codec is supported and that the channel | 234 // IsValidConfig() checks that the codec is supported and that the channel |
238 // layout and sample format are valid. | 235 // layout and sample format are valid. |
239 // | 236 // |
240 // TODO(chcunningham): Change AVStreamToVideoDecoderConfig to check | 237 // TODO(chcunningham): Change AVStreamToVideoDecoderConfig to check |
241 // IsValidConfig internally and return a null scoped_ptr if not valid. | 238 // IsValidConfig internally and return a null scoped_ptr if not valid. |
242 if (!AVStreamToVideoDecoderConfig(stream, video_config.get()) || | 239 if (!AVStreamToVideoDecoderConfig(stream, video_config.get()) || |
243 !video_config->IsValidConfig()) { | 240 !video_config->IsValidConfig()) { |
244 MEDIA_LOG(ERROR, media_log) | 241 MEDIA_LOG(ERROR, media_log) |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 is_enabled_(true), | 278 is_enabled_(true), |
282 waiting_for_keyframe_(false), | 279 waiting_for_keyframe_(false), |
283 fixup_negative_timestamps_(false) { | 280 fixup_negative_timestamps_(false) { |
284 DCHECK(demuxer_); | 281 DCHECK(demuxer_); |
285 | 282 |
286 bool is_encrypted = false; | 283 bool is_encrypted = false; |
287 int rotation = 0; | 284 int rotation = 0; |
288 AVDictionaryEntry* rotation_entry = NULL; | 285 AVDictionaryEntry* rotation_entry = NULL; |
289 | 286 |
290 // Determine our media format. | 287 // Determine our media format. |
291 switch (stream->codec->codec_type) { | 288 switch (stream->codecpar->codec_type) { |
292 case AVMEDIA_TYPE_AUDIO: | 289 case AVMEDIA_TYPE_AUDIO: |
293 DCHECK(audio_config_.get() && !video_config_.get()); | 290 DCHECK(audio_config_.get() && !video_config_.get()); |
294 type_ = AUDIO; | 291 type_ = AUDIO; |
295 is_encrypted = audio_config_->is_encrypted(); | 292 is_encrypted = audio_config_->is_encrypted(); |
296 break; | 293 break; |
297 case AVMEDIA_TYPE_VIDEO: | 294 case AVMEDIA_TYPE_VIDEO: |
298 DCHECK(video_config_.get() && !audio_config_.get()); | 295 DCHECK(video_config_.get() && !audio_config_.get()); |
299 type_ = VIDEO; | 296 type_ = VIDEO; |
300 is_encrypted = video_config_->is_encrypted(); | 297 is_encrypted = video_config_->is_encrypted(); |
301 | 298 |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 if (start_time > base::TimeDelta()) | 493 if (start_time > base::TimeDelta()) |
497 start_time = base::TimeDelta(); | 494 start_time = base::TimeDelta(); |
498 | 495 |
499 buffer->set_timestamp(stream_timestamp - start_time); | 496 buffer->set_timestamp(stream_timestamp - start_time); |
500 | 497 |
501 // If enabled, and no codec delay is present, mark audio packets with | 498 // If enabled, and no codec delay is present, mark audio packets with |
502 // negative timestamps for post-decode discard. | 499 // negative timestamps for post-decode discard. |
503 if (fixup_negative_timestamps_ && is_audio && | 500 if (fixup_negative_timestamps_ && is_audio && |
504 stream_timestamp < base::TimeDelta() && | 501 stream_timestamp < base::TimeDelta() && |
505 buffer->duration() != kNoTimestamp) { | 502 buffer->duration() != kNoTimestamp) { |
506 if (!stream_->codec->delay) { | 503 if (!audio_decoder_config().codec_delay()) { |
507 DCHECK_EQ(buffer->discard_padding().first, base::TimeDelta()); | 504 DCHECK_EQ(buffer->discard_padding().first, base::TimeDelta()); |
508 | 505 |
509 if (stream_timestamp + buffer->duration() < base::TimeDelta()) { | 506 if (stream_timestamp + buffer->duration() < base::TimeDelta()) { |
510 DCHECK_EQ(buffer->discard_padding().second, base::TimeDelta()); | 507 DCHECK_EQ(buffer->discard_padding().second, base::TimeDelta()); |
511 | 508 |
512 // Discard the entire packet if it's entirely before zero. | 509 // Discard the entire packet if it's entirely before zero. |
513 buffer->set_discard_padding( | 510 buffer->set_discard_padding( |
514 std::make_pair(kInfiniteDuration, base::TimeDelta())); | 511 std::make_pair(kInfiniteDuration, base::TimeDelta())); |
515 } else { | 512 } else { |
516 // Only discard part of the frame if it overlaps zero. | 513 // Only discard part of the frame if it overlaps zero. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
661 | 658 |
662 void FFmpegDemuxerStream::ResetBitstreamConverter() { | 659 void FFmpegDemuxerStream::ResetBitstreamConverter() { |
663 #if defined(USE_PROPRIETARY_CODECS) | 660 #if defined(USE_PROPRIETARY_CODECS) |
664 if (bitstream_converter_) | 661 if (bitstream_converter_) |
665 InitBitstreamConverter(); | 662 InitBitstreamConverter(); |
666 #endif // defined(USE_PROPRIETARY_CODECS) | 663 #endif // defined(USE_PROPRIETARY_CODECS) |
667 } | 664 } |
668 | 665 |
669 void FFmpegDemuxerStream::InitBitstreamConverter() { | 666 void FFmpegDemuxerStream::InitBitstreamConverter() { |
670 #if defined(USE_PROPRIETARY_CODECS) | 667 #if defined(USE_PROPRIETARY_CODECS) |
671 switch (stream_->codec->codec_id) { | 668 switch (stream_->codecpar->codec_id) { |
672 case AV_CODEC_ID_H264: | 669 case AV_CODEC_ID_H264: |
673 // Clear |extra_data| so that future (fallback) decoders will know that | 670 // Clear |extra_data| so that future (fallback) decoders will know that |
674 // conversion is forcibly enabled on this stream. | 671 // conversion is forcibly enabled on this stream. |
675 // | 672 // |
676 // TODO(sandersd): Ideally we would convert |extra_data| to concatenated | 673 // TODO(sandersd): Ideally we would convert |extra_data| to concatenated |
677 // SPS/PPS data, but it's too late to be useful because Initialize() was | 674 // SPS/PPS data, but it's too late to be useful because Initialize() was |
678 // already called on GpuVideoDecoder, which is the only path that would | 675 // already called on GpuVideoDecoder, which is the only path that would |
679 // consume that data. | 676 // consume that data. |
680 if (video_config_) | 677 if (video_config_) |
681 video_config_->SetExtraData(std::vector<uint8_t>()); | 678 video_config_->SetExtraData(std::vector<uint8_t>()); |
682 bitstream_converter_.reset( | 679 bitstream_converter_.reset( |
683 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); | 680 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codecpar)); |
684 break; | 681 break; |
685 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 682 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
686 case AV_CODEC_ID_HEVC: | 683 case AV_CODEC_ID_HEVC: |
687 bitstream_converter_.reset( | 684 bitstream_converter_.reset( |
688 new FFmpegH265ToAnnexBBitstreamConverter(stream_->codec)); | 685 new FFmpegH265ToAnnexBBitstreamConverter(stream_->codecpar)); |
689 break; | 686 break; |
690 #endif | 687 #endif |
691 case AV_CODEC_ID_AAC: | 688 case AV_CODEC_ID_AAC: |
692 bitstream_converter_.reset( | 689 bitstream_converter_.reset( |
693 new FFmpegAACBitstreamConverter(stream_->codec)); | 690 new FFmpegAACBitstreamConverter(stream_->codecpar)); |
694 break; | 691 break; |
695 default: | 692 default: |
696 break; | 693 break; |
697 } | 694 } |
698 #endif // defined(USE_PROPRIETARY_CODECS) | 695 #endif // defined(USE_PROPRIETARY_CODECS) |
699 } | 696 } |
700 | 697 |
701 bool FFmpegDemuxerStream::SupportsConfigChanges() { return false; } | 698 bool FFmpegDemuxerStream::SupportsConfigChanges() { return false; } |
702 | 699 |
703 AudioDecoderConfig FFmpegDemuxerStream::audio_decoder_config() { | 700 AudioDecoderConfig FFmpegDemuxerStream::audio_decoder_config() { |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 static int CalculateBitrate(AVFormatContext* format_context, | 1105 static int CalculateBitrate(AVFormatContext* format_context, |
1109 const base::TimeDelta& duration, | 1106 const base::TimeDelta& duration, |
1110 int64_t filesize_in_bytes) { | 1107 int64_t filesize_in_bytes) { |
1111 // If there is a bitrate set on the container, use it. | 1108 // If there is a bitrate set on the container, use it. |
1112 if (format_context->bit_rate > 0) | 1109 if (format_context->bit_rate > 0) |
1113 return format_context->bit_rate; | 1110 return format_context->bit_rate; |
1114 | 1111 |
1115 // Then try to sum the bitrates individually per stream. | 1112 // Then try to sum the bitrates individually per stream. |
1116 int bitrate = 0; | 1113 int bitrate = 0; |
1117 for (size_t i = 0; i < format_context->nb_streams; ++i) { | 1114 for (size_t i = 0; i < format_context->nb_streams; ++i) { |
1118 AVCodecContext* codec_context = format_context->streams[i]->codec; | 1115 AVCodecParameters* codec_parameters = format_context->streams[i]->codecpar; |
1119 bitrate += codec_context->bit_rate; | 1116 bitrate += codec_parameters->bit_rate; |
1120 } | 1117 } |
1121 if (bitrate > 0) | 1118 if (bitrate > 0) |
1122 return bitrate; | 1119 return bitrate; |
1123 | 1120 |
1124 // See if we can approximate the bitrate as long as we have a filesize and | 1121 // See if we can approximate the bitrate as long as we have a filesize and |
1125 // valid duration. | 1122 // valid duration. |
1126 if (duration.InMicroseconds() <= 0 || duration == kInfiniteDuration || | 1123 if (duration.InMicroseconds() <= 0 || duration == kInfiniteDuration || |
1127 filesize_in_bytes == 0) { | 1124 filesize_in_bytes == 0) { |
1128 return 0; | 1125 return 0; |
1129 } | 1126 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1220 | 1217 |
1221 // If available, |start_time_| will be set to the lowest stream start time. | 1218 // If available, |start_time_| will be set to the lowest stream start time. |
1222 start_time_ = kInfiniteDuration; | 1219 start_time_ = kInfiniteDuration; |
1223 | 1220 |
1224 base::TimeDelta max_duration; | 1221 base::TimeDelta max_duration; |
1225 int detected_audio_track_count = 0; | 1222 int detected_audio_track_count = 0; |
1226 int detected_video_track_count = 0; | 1223 int detected_video_track_count = 0; |
1227 int detected_text_track_count = 0; | 1224 int detected_text_track_count = 0; |
1228 for (size_t i = 0; i < format_context->nb_streams; ++i) { | 1225 for (size_t i = 0; i < format_context->nb_streams; ++i) { |
1229 AVStream* stream = format_context->streams[i]; | 1226 AVStream* stream = format_context->streams[i]; |
1230 const AVCodecContext* codec_context = stream->codec; | 1227 const AVCodecParameters* codec_parameters = stream->codecpar; |
1231 const AVMediaType codec_type = codec_context->codec_type; | 1228 const AVMediaType codec_type = codec_parameters->codec_type; |
| 1229 const AVCodecID codec_id = codec_parameters->codec_id; |
1232 | 1230 |
1233 if (codec_type == AVMEDIA_TYPE_AUDIO) { | 1231 if (codec_type == AVMEDIA_TYPE_AUDIO) { |
1234 // Log the codec detected, whether it is supported or not, and whether or | 1232 // Log the codec detected, whether it is supported or not, and whether or |
1235 // not we have already detected a supported codec in another stream. | 1233 // not we have already detected a supported codec in another stream. |
1236 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedAudioCodecHash", | 1234 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedAudioCodecHash", |
1237 HashCodecName(GetCodecName(codec_context))); | 1235 HashCodecName(GetCodecName(codec_id))); |
1238 detected_audio_track_count++; | 1236 detected_audio_track_count++; |
1239 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { | 1237 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { |
1240 // Log the codec detected, whether it is supported or not, and whether or | 1238 // Log the codec detected, whether it is supported or not, and whether or |
1241 // not we have already detected a supported codec in another stream. | 1239 // not we have already detected a supported codec in another stream. |
1242 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedVideoCodecHash", | 1240 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedVideoCodecHash", |
1243 HashCodecName(GetCodecName(codec_context))); | 1241 HashCodecName(GetCodecName(codec_id))); |
1244 detected_video_track_count++; | 1242 detected_video_track_count++; |
1245 | 1243 |
1246 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 1244 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
1247 if (stream->codec->codec_id == AV_CODEC_ID_HEVC) { | 1245 if (codec_id == AV_CODEC_ID_HEVC) { |
1248 // If ffmpeg is built without HEVC parser/decoder support, it will be | 1246 // If ffmpeg is built without HEVC parser/decoder support, it will be |
1249 // able to demux HEVC based solely on container-provided information, | 1247 // able to demux HEVC based solely on container-provided information, |
1250 // but unable to get some of the parameters without parsing the stream | 1248 // but unable to get some of the parameters without parsing the stream |
1251 // (e.g. coded size needs to be read from SPS, pixel format is typically | 1249 // (e.g. coded size needs to be read from SPS, pixel format is typically |
1252 // deduced from decoder config in hvcC box). These are not really needed | 1250 // deduced from decoder config in hvcC box). These are not really needed |
1253 // when using external decoder (e.g. hardware decoder), so override them | 1251 // when using external decoder (e.g. hardware decoder), so override them |
1254 // here, to make sure this translates into a valid VideoDecoderConfig. | 1252 // to make sure this translates into a valid VideoDecoderConfig. Coded |
1255 if (stream->codec->coded_width == 0 && | 1253 // size is overridden in AVStreamToVideoDecoderConfig(). |
1256 stream->codec->coded_height == 0) { | 1254 if (stream->codecpar->format == AV_PIX_FMT_NONE) |
1257 DCHECK(stream->codec->width > 0); | 1255 stream->codecpar->format = AV_PIX_FMT_YUV420P; |
1258 DCHECK(stream->codec->height > 0); | |
1259 stream->codec->coded_width = stream->codec->width; | |
1260 stream->codec->coded_height = stream->codec->height; | |
1261 } | |
1262 if (stream->codec->pix_fmt == AV_PIX_FMT_NONE) { | |
1263 stream->codec->pix_fmt = AV_PIX_FMT_YUV420P; | |
1264 } | |
1265 } | 1256 } |
1266 #endif | 1257 #endif |
1267 } else if (codec_type == AVMEDIA_TYPE_SUBTITLE) { | 1258 } else if (codec_type == AVMEDIA_TYPE_SUBTITLE) { |
1268 detected_text_track_count++; | 1259 detected_text_track_count++; |
1269 if (codec_context->codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) { | 1260 if (codec_id != AV_CODEC_ID_WEBVTT || !text_enabled_) { |
1270 continue; | 1261 continue; |
1271 } | 1262 } |
1272 } else { | 1263 } else { |
1273 continue; | 1264 continue; |
1274 } | 1265 } |
1275 | 1266 |
1276 // Attempt to create a FFmpegDemuxerStream from the AVStream. This will | 1267 // Attempt to create a FFmpegDemuxerStream from the AVStream. This will |
1277 // return nullptr if the AVStream is invalid. Validity checks will verify | 1268 // return nullptr if the AVStream is invalid. Validity checks will verify |
1278 // things like: codec, channel layout, sample/pixel format, etc... | 1269 // things like: codec, channel layout, sample/pixel format, etc... |
1279 std::unique_ptr<FFmpegDemuxerStream> demuxer_stream = | 1270 std::unique_ptr<FFmpegDemuxerStream> demuxer_stream = |
1280 FFmpegDemuxerStream::Create(this, stream, media_log_); | 1271 FFmpegDemuxerStream::Create(this, stream, media_log_); |
1281 if (demuxer_stream.get()) { | 1272 if (demuxer_stream.get()) { |
1282 streams_[i] = std::move(demuxer_stream); | 1273 streams_[i] = std::move(demuxer_stream); |
1283 } else { | 1274 } else { |
1284 if (codec_type == AVMEDIA_TYPE_AUDIO) { | 1275 if (codec_type == AVMEDIA_TYPE_AUDIO) { |
1285 MEDIA_LOG(INFO, media_log_) | 1276 MEDIA_LOG(INFO, media_log_) |
1286 << GetDisplayName() | 1277 << GetDisplayName() |
1287 << ": skipping invalid or unsupported audio track"; | 1278 << ": skipping invalid or unsupported audio track"; |
1288 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { | 1279 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { |
1289 MEDIA_LOG(INFO, media_log_) | 1280 MEDIA_LOG(INFO, media_log_) |
1290 << GetDisplayName() | 1281 << GetDisplayName() |
1291 << ": skipping invalid or unsupported video track"; | 1282 << ": skipping invalid or unsupported video track"; |
1292 } | 1283 } |
1293 | 1284 |
1294 // This AVStream does not successfully convert. | 1285 // This AVStream does not successfully convert. |
1295 continue; | 1286 continue; |
1296 } | 1287 } |
1297 | 1288 |
1298 StreamParser::TrackId track_id = stream->id; | 1289 StreamParser::TrackId track_id = stream->id; |
1299 | |
1300 if ((codec_type == AVMEDIA_TYPE_AUDIO && | |
1301 media_tracks->getAudioConfig(track_id).IsValidConfig()) || | |
1302 (codec_type == AVMEDIA_TYPE_VIDEO && | |
1303 media_tracks->getVideoConfig(track_id).IsValidConfig())) { | |
1304 MEDIA_LOG(INFO, media_log_) | |
1305 << GetDisplayName() | |
1306 << ": skipping duplicate media stream id=" << track_id; | |
1307 continue; | |
1308 } | |
1309 | |
1310 std::string track_label = streams_[i]->GetMetadata("handler_name"); | 1290 std::string track_label = streams_[i]->GetMetadata("handler_name"); |
1311 std::string track_language = streams_[i]->GetMetadata("language"); | 1291 std::string track_language = streams_[i]->GetMetadata("language"); |
1312 | 1292 |
1313 // Some metadata is named differently in FFmpeg for webm files. | 1293 // Some metadata is named differently in FFmpeg for webm files. |
1314 if (strstr(format_context->iformat->name, "webm") || | 1294 if (strstr(format_context->iformat->name, "webm") || |
1315 strstr(format_context->iformat->name, "matroska")) { | 1295 strstr(format_context->iformat->name, "matroska")) { |
1316 // TODO(servolk): FFmpeg doesn't set stream->id correctly for webm files. | 1296 // TODO(servolk): FFmpeg doesn't set stream->id correctly for webm files. |
1317 // Need to fix that and use it as track id. crbug.com/323183 | 1297 // Need to fix that and use it as track id. crbug.com/323183 |
1318 track_id = | 1298 track_id = |
1319 static_cast<StreamParser::TrackId>(media_tracks->tracks().size() + 1); | 1299 static_cast<StreamParser::TrackId>(media_tracks->tracks().size() + 1); |
1320 track_label = streams_[i]->GetMetadata("title"); | 1300 track_label = streams_[i]->GetMetadata("title"); |
1321 } | 1301 } |
1322 | 1302 |
| 1303 if ((codec_type == AVMEDIA_TYPE_AUDIO && |
| 1304 media_tracks->getAudioConfig(track_id).IsValidConfig()) || |
| 1305 (codec_type == AVMEDIA_TYPE_VIDEO && |
| 1306 media_tracks->getVideoConfig(track_id).IsValidConfig())) { |
| 1307 MEDIA_LOG(INFO, media_log_) |
| 1308 << GetDisplayName() |
| 1309 << ": skipping duplicate media stream id=" << track_id; |
| 1310 continue; |
| 1311 } |
| 1312 |
1323 // Note when we find our audio/video stream (we only want one of each) and | 1313 // Note when we find our audio/video stream (we only want one of each) and |
1324 // record src= playback UMA stats for the stream's decoder config. | 1314 // record src= playback UMA stats for the stream's decoder config. |
1325 MediaTrack* media_track = nullptr; | 1315 MediaTrack* media_track = nullptr; |
1326 if (codec_type == AVMEDIA_TYPE_AUDIO) { | 1316 if (codec_type == AVMEDIA_TYPE_AUDIO) { |
1327 AudioDecoderConfig audio_config = streams_[i]->audio_decoder_config(); | 1317 AudioDecoderConfig audio_config = streams_[i]->audio_decoder_config(); |
1328 RecordAudioCodecStats(audio_config); | 1318 RecordAudioCodecStats(audio_config); |
1329 | 1319 |
1330 media_track = media_tracks->AddAudioTrack(audio_config, track_id, "main", | 1320 media_track = media_tracks->AddAudioTrack(audio_config, track_id, "main", |
1331 track_label, track_language); | 1321 track_label, track_language); |
1332 media_track->set_id(base::UintToString(track_id)); | 1322 media_track->set_id(base::UintToString(track_id)); |
1333 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == | 1323 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == |
1334 track_id_to_demux_stream_map_.end()); | 1324 track_id_to_demux_stream_map_.end()); |
1335 track_id_to_demux_stream_map_[media_track->id()] = streams_[i].get(); | 1325 track_id_to_demux_stream_map_[media_track->id()] = streams_[i].get(); |
1336 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { | 1326 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { |
1337 VideoDecoderConfig video_config = streams_[i]->video_decoder_config(); | 1327 VideoDecoderConfig video_config = streams_[i]->video_decoder_config(); |
1338 | 1328 |
1339 RecordVideoCodecStats(video_config, stream->codec->color_range, | 1329 RecordVideoCodecStats(video_config, stream->codecpar->color_range, |
1340 media_log_.get()); | 1330 media_log_.get()); |
1341 | 1331 |
1342 media_track = media_tracks->AddVideoTrack(video_config, track_id, "main", | 1332 media_track = media_tracks->AddVideoTrack(video_config, track_id, "main", |
1343 track_label, track_language); | 1333 track_label, track_language); |
1344 media_track->set_id(base::UintToString(track_id)); | 1334 media_track->set_id(base::UintToString(track_id)); |
1345 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == | 1335 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == |
1346 track_id_to_demux_stream_map_.end()); | 1336 track_id_to_demux_stream_map_.end()); |
1347 track_id_to_demux_stream_map_[media_track->id()] = streams_[i].get(); | 1337 track_id_to_demux_stream_map_[media_track->id()] = streams_[i].get(); |
1348 } | 1338 } |
1349 | 1339 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1402 // http://xiph.org/vorbis/doc/Vorbis_I_spec.html | 1392 // http://xiph.org/vorbis/doc/Vorbis_I_spec.html |
1403 // | 1393 // |
1404 // FFmpeg's use of negative timestamps for opus pre-skip is nonstandard, but | 1394 // FFmpeg's use of negative timestamps for opus pre-skip is nonstandard, but |
1405 // for more information on pre-skip see section 4.2 of the Ogg Opus spec: | 1395 // for more information on pre-skip see section 4.2 of the Ogg Opus spec: |
1406 // https://tools.ietf.org/html/draft-ietf-codec-oggopus-08#section-4.2 | 1396 // https://tools.ietf.org/html/draft-ietf-codec-oggopus-08#section-4.2 |
1407 for (const auto& stream : streams_) { | 1397 for (const auto& stream : streams_) { |
1408 if (!stream || stream->type() != DemuxerStream::AUDIO) | 1398 if (!stream || stream->type() != DemuxerStream::AUDIO) |
1409 continue; | 1399 continue; |
1410 const AVStream* audio_stream = stream->av_stream(); | 1400 const AVStream* audio_stream = stream->av_stream(); |
1411 DCHECK(audio_stream); | 1401 DCHECK(audio_stream); |
1412 if (audio_stream->codec->codec_id == AV_CODEC_ID_OPUS || | 1402 if (audio_stream->codecpar->codec_id == AV_CODEC_ID_OPUS || |
1413 (strcmp(format_context->iformat->name, "ogg") == 0 && | 1403 (strcmp(format_context->iformat->name, "ogg") == 0 && |
1414 audio_stream->codec->codec_id == AV_CODEC_ID_VORBIS)) { | 1404 audio_stream->codecpar->codec_id == AV_CODEC_ID_VORBIS)) { |
1415 for (size_t i = 0; i < streams_.size(); ++i) { | 1405 for (size_t i = 0; i < streams_.size(); ++i) { |
1416 if (!streams_[i]) | 1406 if (!streams_[i]) |
1417 continue; | 1407 continue; |
1418 streams_[i]->enable_negative_timestamp_fixups(); | 1408 streams_[i]->enable_negative_timestamp_fixups(); |
1419 | 1409 |
1420 // Fixup the seeking information to avoid selecting the audio stream | 1410 // Fixup the seeking information to avoid selecting the audio stream |
1421 // simply because it has a lower starting time. | 1411 // simply because it has a lower starting time. |
1422 if (streams_[i]->av_stream() == audio_stream && | 1412 if (streams_[i]->av_stream() == audio_stream && |
1423 streams_[i]->start_time() < base::TimeDelta()) { | 1413 streams_[i]->start_time() < base::TimeDelta()) { |
1424 streams_[i]->set_start_time(base::TimeDelta()); | 1414 streams_[i]->set_start_time(base::TimeDelta()); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1484 int video_track_count = 0; | 1474 int video_track_count = 0; |
1485 for (size_t i = 0; i < streams_.size(); ++i) { | 1475 for (size_t i = 0; i < streams_.size(); ++i) { |
1486 FFmpegDemuxerStream* stream = streams_[i].get(); | 1476 FFmpegDemuxerStream* stream = streams_[i].get(); |
1487 if (!stream) | 1477 if (!stream) |
1488 continue; | 1478 continue; |
1489 if (stream->type() == DemuxerStream::AUDIO) { | 1479 if (stream->type() == DemuxerStream::AUDIO) { |
1490 ++audio_track_count; | 1480 ++audio_track_count; |
1491 std::string suffix = ""; | 1481 std::string suffix = ""; |
1492 if (audio_track_count > 1) | 1482 if (audio_track_count > 1) |
1493 suffix = "_track" + base::IntToString(audio_track_count); | 1483 suffix = "_track" + base::IntToString(audio_track_count); |
1494 const AVCodecContext* audio_codec = avctx->streams[i]->codec; | 1484 const AVCodecParameters* audio_parameters = avctx->streams[i]->codecpar; |
1495 const AudioDecoderConfig& audio_config = stream->audio_decoder_config(); | 1485 const AudioDecoderConfig& audio_config = stream->audio_decoder_config(); |
1496 params.SetString("audio_codec_name" + suffix, GetCodecName(audio_codec)); | 1486 params.SetString("audio_codec_name" + suffix, |
1497 params.SetInteger("audio_channels_count" + suffix, audio_codec->channels); | 1487 GetCodecName(audio_parameters->codec_id)); |
| 1488 params.SetInteger("audio_channels_count" + suffix, |
| 1489 audio_parameters->channels); |
1498 params.SetString("audio_sample_format" + suffix, | 1490 params.SetString("audio_sample_format" + suffix, |
1499 SampleFormatToString(audio_config.sample_format())); | 1491 SampleFormatToString(audio_config.sample_format())); |
1500 params.SetInteger("audio_samples_per_second" + suffix, | 1492 params.SetInteger("audio_samples_per_second" + suffix, |
1501 audio_config.samples_per_second()); | 1493 audio_config.samples_per_second()); |
1502 } else if (stream->type() == DemuxerStream::VIDEO) { | 1494 } else if (stream->type() == DemuxerStream::VIDEO) { |
1503 ++video_track_count; | 1495 ++video_track_count; |
1504 std::string suffix = ""; | 1496 std::string suffix = ""; |
1505 if (video_track_count > 1) | 1497 if (video_track_count > 1) |
1506 suffix = "_track" + base::IntToString(video_track_count); | 1498 suffix = "_track" + base::IntToString(video_track_count); |
1507 const AVCodecContext* video_codec = avctx->streams[i]->codec; | 1499 const AVStream* video_av_stream = avctx->streams[i]; |
| 1500 const AVCodecParameters* video_parameters = video_av_stream->codecpar; |
1508 const VideoDecoderConfig& video_config = stream->video_decoder_config(); | 1501 const VideoDecoderConfig& video_config = stream->video_decoder_config(); |
1509 params.SetString("video_codec_name" + suffix, GetCodecName(video_codec)); | 1502 params.SetString("video_codec_name" + suffix, |
1510 params.SetInteger("width" + suffix, video_codec->width); | 1503 GetCodecName(video_parameters->codec_id)); |
1511 params.SetInteger("height" + suffix, video_codec->height); | 1504 params.SetInteger("width" + suffix, video_parameters->width); |
1512 params.SetInteger("coded_width" + suffix, video_codec->coded_width); | 1505 params.SetInteger("height" + suffix, video_parameters->height); |
1513 params.SetInteger("coded_height" + suffix, video_codec->coded_height); | 1506 |
1514 params.SetString("time_base" + suffix, | 1507 // AVCodecParameters has no coded size fields. We gather this information |
1515 base::StringPrintf("%d/%d", video_codec->time_base.num, | 1508 // during video FFmpegDemuxerStream's VideoDecoderConfig setup. |
1516 video_codec->time_base.den)); | 1509 params.SetInteger("coded_width" + suffix, |
| 1510 video_config.coded_size().width()); |
| 1511 params.SetInteger("coded_height" + suffix, |
| 1512 video_config.coded_size().height()); |
| 1513 |
| 1514 // AVCodecParameters has no time_base field. We use the one from AVStream |
| 1515 // here. |
| 1516 params.SetString( |
| 1517 "time_base" + suffix, |
| 1518 base::StringPrintf("%d/%d", video_av_stream->time_base.num, |
| 1519 video_av_stream->time_base.den)); |
| 1520 |
1517 params.SetString("video_format" + suffix, | 1521 params.SetString("video_format" + suffix, |
1518 VideoPixelFormatToString(video_config.format())); | 1522 VideoPixelFormatToString(video_config.format())); |
1519 params.SetBoolean("video_is_encrypted" + suffix, | 1523 params.SetBoolean("video_is_encrypted" + suffix, |
1520 video_config.is_encrypted()); | 1524 video_config.is_encrypted()); |
1521 } | 1525 } |
1522 } | 1526 } |
1523 params.SetBoolean("found_audio_stream", (audio_track_count > 0)); | 1527 params.SetBoolean("found_audio_stream", (audio_track_count > 0)); |
1524 params.SetBoolean("found_video_stream", (video_track_count > 0)); | 1528 params.SetBoolean("found_video_stream", (video_track_count > 0)); |
1525 SetTimeProperty(metadata_event.get(), "max_duration", max_duration); | 1529 SetTimeProperty(metadata_event.get(), "max_duration", max_duration); |
1526 SetTimeProperty(metadata_event.get(), "start_time", start_time_); | 1530 SetTimeProperty(metadata_event.get(), "start_time", start_time_); |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1788 | 1792 |
1789 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1793 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
1790 DCHECK(task_runner_->BelongsToCurrentThread()); | 1794 DCHECK(task_runner_->BelongsToCurrentThread()); |
1791 for (const auto& stream : streams_) { | 1795 for (const auto& stream : streams_) { |
1792 if (stream) | 1796 if (stream) |
1793 stream->SetLiveness(liveness); | 1797 stream->SetLiveness(liveness); |
1794 } | 1798 } |
1795 } | 1799 } |
1796 | 1800 |
1797 } // namespace media | 1801 } // namespace media |
OLD | NEW |