1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/ffmpeg_demuxer.h"
12 #include "base/base64.h"
13 #include "base/bind.h"
14 #include "base/callback_helpers.h"
15 #include "base/feature_list.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_functions.h"
18 #include "base/metrics/histogram_macros.h"
19 #include "base/numerics/safe_conversions.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_util.h"
22 #include "base/sys_byteorder.h"
23 #include "base/task/sequenced_task_runner.h"
24 #include "base/task/task_runner_util.h"
25 #include "base/task/thread_pool.h"
26 #include "base/threading/thread_task_runner_handle.h"
27 #include "base/time/time.h"
28 #include "base/trace_event/trace_event.h"
29 #include "build/build_config.h"
30 #include "media/base/bind_to_current_loop.h"
31 #include "media/base/decrypt_config.h"
32 #include "media/base/demuxer_memory_limit.h"
33 #include "media/base/limits.h"
34 #include "media/base/media_switches.h"
35 #include "media/base/media_tracks.h"
36 #include "media/base/media_types.h"
37 #include "media/base/sample_rates.h"
38 #include "media/base/supported_types.h"
39 #include "media/base/timestamp_constants.h"
40 #include "media/base/video_codecs.h"
41 #include "media/base/webvtt_util.h"
42 #include "media/ffmpeg/ffmpeg_common.h"
43 #include "media/filters/ffmpeg_aac_bitstream_converter.h"
44 #include "media/filters/ffmpeg_bitstream_converter.h"
45 #include "media/filters/ffmpeg_glue.h"
46 #include "media/filters/ffmpeg_h264_to_annex_b_bitstream_converter.h"
47 #include "media/formats/mpeg/mpeg1_audio_stream_parser.h"
48 #include "media/formats/webm/webm_crypto_helpers.h"
49 #include "media/media_buildflags.h"
50 #include "third_party/ffmpeg/ffmpeg_features.h"
51 #include "third_party/ffmpeg/libavcodec/packet.h"
53 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
54 #include "media/filters/ffmpeg_h265_to_annex_b_bitstream_converter.h"
61 constexpr int64_t kInvalidPTSMarker = static_cast<int64_t>(0x8000000000000000);
63 void SetAVStreamDiscard(AVStream* stream, AVDiscard discard) {
65 stream->discard = discard;
70 static base::Time ExtractTimelineOffset(
71 container_names::MediaContainerName container,
72 const AVFormatContext* format_context) {
73 if (container == container_names::CONTAINER_WEBM) {
74 const AVDictionaryEntry* entry =
75 av_dict_get(format_context->metadata, "creation_time", nullptr, 0);
77 base::Time timeline_offset;
79 // FFmpegDemuxerTests assume base::Time::FromUTCString() is used here.
80 if (entry != nullptr && entry->value != nullptr &&
81 base::Time::FromUTCString(entry->value, &timeline_offset)) {
82 return timeline_offset;
89 static base::TimeDelta FramesToTimeDelta(int frames, double sample_rate) {
90 return base::Microseconds(frames * base::Time::kMicrosecondsPerSecond /
94 static base::TimeDelta ExtractStartTime(AVStream* stream) {
95 // The default start time is zero.
96 base::TimeDelta start_time;
98 // First try to use the |start_time| value as is.
99 if (stream->start_time != kNoFFmpegTimestamp)
100 start_time = ConvertFromTimeBase(stream->time_base, stream->start_time);
102 // Next try to use the first DTS value, for codecs where we know PTS == DTS
103 // (excludes all H26x codecs). The start time must be returned in PTS.
104 if (av_stream_get_first_dts(stream) != kNoFFmpegTimestamp &&
105 stream->codecpar->codec_id != AV_CODEC_ID_HEVC &&
106 stream->codecpar->codec_id != AV_CODEC_ID_H264 &&
107 stream->codecpar->codec_id != AV_CODEC_ID_MPEG4) {
108 const base::TimeDelta first_pts =
109 ConvertFromTimeBase(stream->time_base, av_stream_get_first_dts(stream));
110 if (first_pts < start_time)
111 start_time = first_pts;
117 // Record audio decoder config UMA stats corresponding to a src= playback.
118 static void RecordAudioCodecStats(const AudioDecoderConfig& audio_config) {
119 base::UmaHistogramEnumeration("Media.AudioCodec", audio_config.codec());
122 // Record video decoder config UMA stats corresponding to a src= playback.
123 static void RecordVideoCodecStats(container_names::MediaContainerName container,
124 const VideoDecoderConfig& video_config,
125 AVColorRange color_range,
126 MediaLog* media_log) {
127 // TODO(xhwang): Fix these misleading metric names. They should be something
128 // like "Media.SRC.Xxxx". See http://crbug.com/716183.
129 base::UmaHistogramEnumeration("Media.VideoCodec", video_config.codec());
130 if (container == container_names::CONTAINER_MOV) {
131 base::UmaHistogramEnumeration("Media.SRC.VideoCodec.MP4",
132 video_config.codec());
133 } else if (container == container_names::CONTAINER_WEBM) {
134 base::UmaHistogramEnumeration("Media.SRC.VideoCodec.WebM",
135 video_config.codec());
139 static const char kCodecNone[] = "none";
141 static const char* GetCodecName(enum AVCodecID id) {
142 const AVCodecDescriptor* codec_descriptor = avcodec_descriptor_get(id);
143 // If the codec name can't be determined, return none for tracking.
144 return codec_descriptor ? codec_descriptor->name : kCodecNone;
147 static base::Value GetTimeValue(base::TimeDelta value) {
148 if (value == kInfiniteDuration)
149 return base::Value("kInfiniteDuration");
150 if (value == kNoTimestamp)
151 return base::Value("kNoTimestamp");
152 return base::Value(value.InSecondsF());
156 struct MediaLogPropertyTypeSupport<MediaLogProperty::kMaxDuration,
158 static base::Value Convert(base::TimeDelta t) { return GetTimeValue(t); }
162 struct MediaLogPropertyTypeSupport<MediaLogProperty::kStartTime,
164 static base::Value Convert(base::TimeDelta t) { return GetTimeValue(t); }
167 static int ReadFrameAndDiscardEmpty(AVFormatContext* context,
169 // Skip empty packets in a tight loop to avoid timing out fuzzers.
173 result = av_read_frame(context, packet);
174 drop_packet = (!packet->data || !packet->size) && result >= 0;
176 av_packet_unref(packet);
177 DLOG(WARNING) << "Dropping empty packet, size: " << packet->size
178 << ", data: " << static_cast<void*>(packet->data);
180 } while (drop_packet);
185 std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create(
186 FFmpegDemuxer* demuxer,
188 MediaLog* media_log) {
189 if (!demuxer || !stream)
192 std::unique_ptr<FFmpegDemuxerStream> demuxer_stream;
193 std::unique_ptr<AudioDecoderConfig> audio_config;
194 std::unique_ptr<VideoDecoderConfig> video_config;
196 #if BUILDFLAG(IS_CHROMEOS)
197 if (base::FeatureList::IsEnabled(kDeprecateLowUsageCodecs)) {
198 const auto codec_id = stream->codecpar->codec_id;
199 if (codec_id == AV_CODEC_ID_AMR_NB || codec_id == AV_CODEC_ID_AMR_WB ||
200 codec_id == AV_CODEC_ID_GSM_MS) {
201 MEDIA_LOG(ERROR, media_log) << "AMR and GSM are deprecated on ChromeOS.";
207 if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
208 audio_config = std::make_unique<AudioDecoderConfig>();
210 // TODO(chcunningham): Change AVStreamToAudioDecoderConfig to check
211 // IsValidConfig internally and return a null scoped_ptr if not valid.
212 if (!AVStreamToAudioDecoderConfig(stream, audio_config.get()) ||
213 !audio_config->IsValidConfig() ||
214 !IsSupportedAudioType(AudioType::FromDecoderConfig(*audio_config))) {
215 MEDIA_LOG(DEBUG, media_log) << "Warning, FFmpegDemuxer failed to create "
216 "a valid/supported audio decoder "
217 "configuration from muxed stream, config:"
218 << audio_config->AsHumanReadableString();
222 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created audio stream, config "
223 << audio_config->AsHumanReadableString();
224 } else if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
225 video_config = std::make_unique<VideoDecoderConfig>();
227 // TODO(chcunningham): Change AVStreamToVideoDecoderConfig to check
228 // IsValidConfig internally and return a null scoped_ptr if not valid.
229 if (!AVStreamToVideoDecoderConfig(stream, video_config.get()) ||
230 !video_config->IsValidConfig() ||
231 !IsSupportedVideoType(VideoType::FromDecoderConfig(*video_config))) {
232 MEDIA_LOG(DEBUG, media_log) << "Warning, FFmpegDemuxer failed to create "
233 "a valid/supported video decoder "
234 "configuration from muxed stream, config:"
235 << video_config->AsHumanReadableString();
239 MEDIA_LOG(INFO, media_log) << "FFmpegDemuxer: created video stream, config "
240 << video_config->AsHumanReadableString();
243 return base::WrapUnique(
244 new FFmpegDemuxerStream(demuxer, stream, std::move(audio_config),
245 std::move(video_config), media_log));
248 static void UnmarkEndOfStreamAndClearError(AVFormatContext* format_context) {
249 format_context->pb->eof_reached = 0;
250 format_context->pb->error = 0;
254 // FFmpegDemuxerStream
256 FFmpegDemuxerStream::FFmpegDemuxerStream(
257 FFmpegDemuxer* demuxer,
259 std::unique_ptr<AudioDecoderConfig> audio_config,
260 std::unique_ptr<VideoDecoderConfig> video_config,
263 task_runner_(base::ThreadTaskRunnerHandle::Get()),
265 start_time_(kNoTimestamp),
266 audio_config_(audio_config.release()),
267 video_config_(video_config.release()),
268 media_log_(media_log),
269 end_of_stream_(false),
270 last_packet_timestamp_(kNoTimestamp),
271 last_packet_duration_(kNoTimestamp),
273 waiting_for_keyframe_(false),
275 fixup_negative_timestamps_(false),
276 fixup_chained_ogg_(false),
277 num_discarded_packet_warnings_(0),
278 last_packet_pos_(AV_NOPTS_VALUE),
279 last_packet_dts_(AV_NOPTS_VALUE) {
282 bool is_encrypted = false;
284 // Determine our media format.
285 switch (stream->codecpar->codec_type) {
286 case AVMEDIA_TYPE_AUDIO:
287 DCHECK(audio_config_.get() && !video_config_.get());
289 is_encrypted = audio_config_->is_encrypted();
291 case AVMEDIA_TYPE_VIDEO:
292 DCHECK(video_config_.get() && !audio_config_.get());
294 is_encrypted = video_config_->is_encrypted();
296 case AVMEDIA_TYPE_SUBTITLE:
297 DCHECK(!video_config_.get() && !audio_config_.get());
305 // Calculate the duration.
306 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration);
309 AVDictionaryEntry* key =
310 av_dict_get(stream->metadata, "enc_key_id", nullptr, 0);
313 if (!key || !key->value)
315 base::StringPiece base64_key_id(key->value);
316 std::string enc_key_id;
317 base::Base64Decode(base64_key_id, &enc_key_id);
318 DCHECK(!enc_key_id.empty());
319 if (enc_key_id.empty())
322 encryption_key_id_.assign(enc_key_id);
323 demuxer_->OnEncryptedMediaInitData(EmeInitDataType::WEBM, enc_key_id);
327 FFmpegDemuxerStream::~FFmpegDemuxerStream() {
330 DCHECK(buffer_queue_.IsEmpty());
333 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
334 DCHECK(task_runner_->RunsTasksInCurrentSequence());
335 DCHECK(packet->size);
336 DCHECK(packet->data);
338 const bool is_audio = type() == AUDIO;
340 // dts == pts when dts is not present.
342 packet->dts == AV_NOPTS_VALUE ? packet->pts : packet->dts;
344 // Chained ogg files have non-monotonically increasing position and time stamp
345 // values, which prevents us from using them to determine if a packet should
346 // be dropped. Since chained ogg is only allowed on single track audio only
347 // opus/vorbis media, and dropping packets is only necessary for multi-track
348 // video-and-audio streams, we can just disable dropping when we detect
350 // For similar reasons, we only want to allow packet drops for audio streams;
351 // video frame dropping is handled by the renderer when correcting for a/v
353 if (is_audio && !fixup_chained_ogg_ && last_packet_pos_ != AV_NOPTS_VALUE) {
354 // Some containers have unknown position...
355 if (packet->pos == -1)
356 packet->pos = last_packet_pos_;
358 if (packet->pos < last_packet_pos_) {
359 DVLOG(3) << "Dropped packet with out of order position (" << packet->pos
360 << " < " << last_packet_pos_ << ")";
363 if (last_packet_dts_ != AV_NOPTS_VALUE && packet->pos == last_packet_pos_ &&
364 packet_dts <= last_packet_dts_) {
365 DVLOG(3) << "Dropped packet with out of order display timestamp ("
366 << packet_dts << " < " << last_packet_dts_ << ")";
371 if (!demuxer_ || end_of_stream_) {
372 NOTREACHED() << "Attempted to enqueue packet on a stopped stream";
376 last_packet_pos_ = packet->pos;
377 last_packet_dts_ = packet_dts;
379 if (waiting_for_keyframe_) {
380 if (packet->flags & AV_PKT_FLAG_KEY) {
381 waiting_for_keyframe_ = false;
383 DVLOG(1) << "Dropped non-keyframe pts=" << packet->pts;
388 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
389 // Convert the packet if there is a bitstream filter.
390 if (bitstream_converter_ &&
391 !bitstream_converter_->ConvertPacket(packet.get())) {
392 DVLOG(1) << "Format conversion failed.";
396 scoped_refptr<DecoderBuffer> buffer;
398 if (type() == DemuxerStream::TEXT) {
400 uint8_t* id_data = av_packet_get_side_data(
401 packet.get(), AV_PKT_DATA_WEBVTT_IDENTIFIER, &id_size);
403 size_t settings_size = 0;
404 uint8_t* settings_data = av_packet_get_side_data(
405 packet.get(), AV_PKT_DATA_WEBVTT_SETTINGS, &settings_size);
407 std::vector<uint8_t> side_data;
408 MakeSideData(id_data, id_data + id_size,
409 settings_data, settings_data + settings_size,
412 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size,
413 side_data.data(), side_data.size());
415 size_t side_data_size = 0;
416 uint8_t* side_data = av_packet_get_side_data(
417 packet.get(), AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size);
419 std::unique_ptr<DecryptConfig> decrypt_config;
421 if ((type() == DemuxerStream::AUDIO && audio_config_->is_encrypted()) ||
422 (type() == DemuxerStream::VIDEO && video_config_->is_encrypted())) {
423 if (!WebMCreateDecryptConfig(
424 packet->data, packet->size,
425 reinterpret_cast<const uint8_t*>(encryption_key_id_.data()),
426 encryption_key_id_.size(), &decrypt_config, &data_offset)) {
427 MEDIA_LOG(ERROR, media_log_) << "Creation of DecryptConfig failed.";
431 // FFmpeg may return garbage packets for MP3 stream containers, so we need
432 // to drop these to avoid decoder errors. The ffmpeg team maintains that
433 // this behavior isn't ideal, but have asked for a significant refactoring
434 // of the AVParser infrastructure to fix this, which is overkill for now.
435 // See http://crbug.com/794782.
437 // This behavior may also occur with ADTS streams, but is rarer in practice
438 // because ffmpeg's ADTS demuxer does more validation on the packets, so
439 // when invalid data is received, av_read_frame() fails and playback ends.
440 if (is_audio && demuxer_->container() == container_names::CONTAINER_MP3) {
441 DCHECK(!data_offset); // Only set for containers supporting encryption...
443 // MP3 packets may be zero-padded according to ffmpeg, so trim until we
444 // have the packet; adjust |data_offset| too so this work isn't repeated.
445 uint8_t* packet_end = packet->data + packet->size;
446 uint8_t* header_start = packet->data;
447 while (header_start < packet_end && !*header_start) {
452 if (packet_end - header_start < MPEG1AudioStreamParser::kHeaderSize ||
453 !MPEG1AudioStreamParser::ParseHeader(nullptr, nullptr, header_start,
455 LIMITED_MEDIA_LOG(INFO, media_log_, num_discarded_packet_warnings_, 5)
456 << "Discarding invalid MP3 packet, ts: "
457 << ConvertStreamTimestamp(stream_->time_base, packet->pts)
459 << ConvertStreamTimestamp(stream_->time_base, packet->duration);
464 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will
465 // reference inner memory of FFmpeg. As such we should transfer the packet
466 // into memory we control.
467 if (side_data_size > 0) {
468 buffer = DecoderBuffer::CopyFrom(packet->data + data_offset,
469 packet->size - data_offset, side_data,
472 buffer = DecoderBuffer::CopyFrom(packet->data + data_offset,
473 packet->size - data_offset);
476 size_t skip_samples_size = 0;
477 const uint32_t* skip_samples_ptr =
478 reinterpret_cast<const uint32_t*>(av_packet_get_side_data(
479 packet.get(), AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size));
480 const int kSkipSamplesValidSize = 10;
481 const int kSkipEndSamplesOffset = 1;
482 if (skip_samples_size >= kSkipSamplesValidSize) {
483 // Because FFmpeg rolls codec delay and skip samples into one we can only
484 // allow front discard padding on the first buffer. Otherwise the discard
485 // helper can't figure out which data to discard. See AudioDiscardHelper.
486 int discard_front_samples = base::ByteSwapToLE32(*skip_samples_ptr);
487 if (last_packet_timestamp_ != kNoTimestamp && discard_front_samples) {
488 DLOG(ERROR) << "Skip samples are only allowed for the first packet.";
489 discard_front_samples = 0;
492 if (discard_front_samples < 0) {
493 // See https://crbug.com/1189939 and https://trac.ffmpeg.org/ticket/9622
494 DLOG(ERROR) << "Negative skip samples are not allowed.";
495 discard_front_samples = 0;
498 const int discard_end_samples =
499 base::ByteSwapToLE32(*(skip_samples_ptr + kSkipEndSamplesOffset));
501 if (discard_front_samples || discard_end_samples) {
503 const int samples_per_second =
504 audio_decoder_config().samples_per_second();
505 buffer->set_discard_padding(std::make_pair(
506 FramesToTimeDelta(discard_front_samples, samples_per_second),
507 FramesToTimeDelta(discard_end_samples, samples_per_second)));
512 buffer->set_decrypt_config(std::move(decrypt_config));
515 if (packet->duration >= 0) {
516 buffer->set_duration(
517 ConvertStreamTimestamp(stream_->time_base, packet->duration));
519 // TODO(wolenetz): Remove when FFmpeg stops returning negative durations.
520 // https://crbug.com/394418
521 DVLOG(1) << "FFmpeg returned a buffer with a negative duration! "
523 buffer->set_duration(kNoTimestamp);
526 // Note: If pts is kNoFFmpegTimestamp, stream_timestamp will be kNoTimestamp.
527 const base::TimeDelta stream_timestamp =
528 ConvertStreamTimestamp(stream_->time_base, packet->pts);
530 if (stream_timestamp == kNoTimestamp ||
531 stream_timestamp == kInfiniteDuration) {
532 MEDIA_LOG(ERROR, media_log_) << "FFmpegDemuxer: PTS is not defined";
533 demuxer_->NotifyDemuxerError(DEMUXER_ERROR_COULD_NOT_PARSE);
537 // If this file has negative timestamps don't rebase any other stream types
538 // against the negative starting time.
539 base::TimeDelta start_time = demuxer_->start_time();
540 if (fixup_negative_timestamps_ && !is_audio && start_time.is_negative()) {
541 start_time = base::TimeDelta();
544 // Don't rebase timestamps for positive start times, the HTML Media Spec
545 // details this in section "4.8.10.6 Offsets into the media resource." We
546 // will still need to rebase timestamps before seeking with FFmpeg though.
547 if (start_time.is_positive())
548 start_time = base::TimeDelta();
550 buffer->set_timestamp(stream_timestamp - start_time);
552 // If the packet is marked for complete discard and it doesn't already have
553 // any discard padding set, mark the DecoderBuffer for complete discard. We
554 // don't want to overwrite any existing discard padding since the discard
555 // padding may refer to frames beyond this packet.
556 if (packet->flags & AV_PKT_FLAG_DISCARD &&
557 buffer->discard_padding() == DecoderBuffer::DiscardPadding()) {
558 buffer->set_discard_padding(
559 std::make_pair(kInfiniteDuration, base::TimeDelta()));
560 // These timestamps should never be used, but to ensure they are dropped
561 // correctly give them unique timestamps.
562 buffer->set_timestamp(last_packet_timestamp_ == kNoTimestamp
564 : last_packet_timestamp_ + base::Microseconds(1));
567 // Fixup negative timestamps where the before-zero portion is completely
568 // discarded after decoding.
569 if (buffer->timestamp().is_negative()) {
570 // Discard padding may also remove samples after zero.
571 auto fixed_ts = buffer->discard_padding().first + buffer->timestamp();
573 // Allow for rounding error in the discard padding calculations.
574 if (fixed_ts == base::Microseconds(-1))
575 fixed_ts = base::TimeDelta();
577 if (fixed_ts >= base::TimeDelta())
578 buffer->set_timestamp(fixed_ts);
581 // Only allow negative timestamps past if we know they'll be fixed up by the
582 // code paths below; otherwise they should be treated as a parse error.
583 if ((!fixup_chained_ogg_ || last_packet_timestamp_ == kNoTimestamp) &&
584 buffer->timestamp().is_negative()) {
585 MEDIA_LOG(ERROR, media_log_)
586 << "FFmpegDemuxer: unfixable negative timestamp.";
587 demuxer_->NotifyDemuxerError(DEMUXER_ERROR_COULD_NOT_PARSE);
591 // If enabled, and no codec delay is present, mark audio packets with negative
592 // timestamps for post-decode discard. If codec delay is present, discard is
593 // handled by the decoder using that value.
594 if (fixup_negative_timestamps_ && is_audio &&
595 stream_timestamp.is_negative() && buffer->duration() != kNoTimestamp &&
596 !audio_decoder_config().codec_delay()) {
597 if ((stream_timestamp + buffer->duration()).is_negative()) {
598 DCHECK_EQ(buffer->discard_padding().second, base::TimeDelta());
600 // Discard the entire packet if it's entirely before zero, but don't
601 // override the discard padding if it refers to frames beyond this packet.
602 if (buffer->discard_padding().first <= buffer->duration()) {
603 buffer->set_discard_padding(
604 std::make_pair(kInfiniteDuration, base::TimeDelta()));
607 // Only discard part of the frame if it overlaps zero.
608 buffer->set_discard_padding(std::make_pair(
609 std::max(-stream_timestamp, buffer->discard_padding().first),
610 buffer->discard_padding().second));
614 if (last_packet_timestamp_ != kNoTimestamp) {
615 // FFmpeg doesn't support chained ogg correctly. Instead of guaranteeing
616 // continuity across links in the chain it uses the timestamp information
617 // from each link directly. Doing so can lead to timestamps which appear to
618 // go backwards in time.
620 // If the new link starts with a negative timestamp or a timestamp less than
621 // the original (positive) |start_time|, we will get a negative timestamp
624 // Fixing chained ogg is non-trivial, so for now just reuse the last good
625 // timestamp. The decoder will rewrite the timestamps to be sample accurate
626 // later. See http://crbug.com/396864.
628 // Note: This will not work with codecs that have out of order frames like
629 // H.264 with b-frames, but luckily you can't put those in ogg files...
630 if (fixup_chained_ogg_ && buffer->timestamp() < last_packet_timestamp_) {
631 buffer->set_timestamp(last_packet_timestamp_ +
632 (last_packet_duration_ != kNoTimestamp
633 ? last_packet_duration_
634 : base::Microseconds(1)));
637 // The demuxer should always output positive timestamps.
638 DCHECK_GE(buffer->timestamp(), base::TimeDelta());
640 if (last_packet_timestamp_ < buffer->timestamp()) {
641 buffered_ranges_.Add(last_packet_timestamp_, buffer->timestamp());
642 demuxer_->NotifyBufferingChanged();
646 if (packet->flags & AV_PKT_FLAG_KEY)
647 buffer->set_is_key_frame(true);
649 // One last sanity check on the packet timestamps in case any of the above
650 // calculations have pushed the values to the limits.
651 if (buffer->timestamp() == kNoTimestamp ||
652 buffer->timestamp() == kInfiniteDuration) {
653 MEDIA_LOG(ERROR, media_log_) << "FFmpegDemuxer: PTS is not defined";
654 demuxer_->NotifyDemuxerError(DEMUXER_ERROR_COULD_NOT_PARSE);
658 last_packet_timestamp_ = buffer->timestamp();
659 last_packet_duration_ = buffer->duration();
661 const base::TimeDelta new_duration = last_packet_timestamp_;
662 if (new_duration > duration_ || duration_ == kNoTimestamp)
663 duration_ = new_duration;
665 buffer_queue_.Push(std::move(buffer));
666 SatisfyPendingRead();
669 void FFmpegDemuxerStream::SetEndOfStream() {
670 DCHECK(task_runner_->RunsTasksInCurrentSequence());
671 end_of_stream_ = true;
672 SatisfyPendingRead();
675 void FFmpegDemuxerStream::FlushBuffers(bool preserve_packet_position) {
676 DCHECK(task_runner_->RunsTasksInCurrentSequence());
677 DCHECK(preserve_packet_position || !read_cb_)
678 << "There should be no pending read";
680 // H264 and AAC require that we resend the header after flush.
681 // Reset bitstream for converter to do so.
682 // This is related to chromium issue 140371 (http://crbug.com/140371).
683 ResetBitstreamConverter();
685 if (!preserve_packet_position) {
686 last_packet_pos_ = AV_NOPTS_VALUE;
687 last_packet_dts_ = AV_NOPTS_VALUE;
690 buffer_queue_.Clear();
691 end_of_stream_ = false;
692 last_packet_timestamp_ = kNoTimestamp;
693 last_packet_duration_ = kNoTimestamp;
697 void FFmpegDemuxerStream::Abort() {
700 std::move(read_cb_).Run(DemuxerStream::kAborted, nullptr);
703 void FFmpegDemuxerStream::Stop() {
704 DCHECK(task_runner_->RunsTasksInCurrentSequence());
705 buffer_queue_.Clear();
708 end_of_stream_ = true;
710 std::move(read_cb_).Run(DemuxerStream::kOk,
711 DecoderBuffer::CreateEOSBuffer());
715 DemuxerStream::Type FFmpegDemuxerStream::type() const {
716 DCHECK(task_runner_->RunsTasksInCurrentSequence());
720 StreamLiveness FFmpegDemuxerStream::liveness() const {
721 DCHECK(task_runner_->RunsTasksInCurrentSequence());
725 void FFmpegDemuxerStream::Read(ReadCB read_cb) {
726 DCHECK(task_runner_->RunsTasksInCurrentSequence());
727 CHECK(!read_cb_) << "Overlapping reads are not supported";
728 read_cb_ = BindToCurrentLoop(std::move(read_cb));
730 // Don't accept any additional reads if we've been told to stop.
731 // The |demuxer_| may have been destroyed in the pipeline thread.
733 // TODO(scherkus): it would be cleaner to reply with an error message.
735 std::move(read_cb_).Run(DemuxerStream::kOk,
736 DecoderBuffer::CreateEOSBuffer());
741 DVLOG(1) << "Read from disabled stream, returning EOS";
742 std::move(read_cb_).Run(kOk, DecoderBuffer::CreateEOSBuffer());
747 std::move(read_cb_).Run(kAborted, nullptr);
751 SatisfyPendingRead();
754 void FFmpegDemuxerStream::EnableBitstreamConverter() {
755 DCHECK(task_runner_->RunsTasksInCurrentSequence());
757 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
758 InitBitstreamConverter();
760 DLOG(ERROR) << "Proprietary codecs not enabled and stream requires bitstream "
761 "conversion. Playback will likely fail.";
765 void FFmpegDemuxerStream::ResetBitstreamConverter() {
766 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
767 if (bitstream_converter_)
768 InitBitstreamConverter();
769 #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
772 void FFmpegDemuxerStream::InitBitstreamConverter() {
773 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
774 switch (stream_->codecpar->codec_id) {
775 case AV_CODEC_ID_H264:
776 // Clear |extra_data| so that future (fallback) decoders will know that
777 // conversion is forcibly enabled on this stream.
779 // TODO(sandersd): Ideally we would convert |extra_data| to concatenated
780 // SPS/PPS data, but it's too late to be useful because Initialize() was
781 // already called on GpuVideoDecoder, which is the only path that would
782 // consume that data.
784 video_config_->SetExtraData(std::vector<uint8_t>());
785 bitstream_converter_ =
786 std::make_unique<FFmpegH264ToAnnexBBitstreamConverter>(
789 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
790 case AV_CODEC_ID_HEVC:
791 bitstream_converter_.reset(
792 new FFmpegH265ToAnnexBBitstreamConverter(stream_->codecpar));
795 case AV_CODEC_ID_AAC:
796 // FFmpeg doesn't understand xHE-AAC profiles yet, which can't be put in
797 // ADTS anyways, so skip bitstream conversion when the profile is
799 if (audio_config_->profile() != AudioCodecProfile::kXHE_AAC) {
800 bitstream_converter_ =
801 std::make_unique<FFmpegAACBitstreamConverter>(stream_->codecpar);
807 #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
810 bool FFmpegDemuxerStream::SupportsConfigChanges() { return false; }
812 AudioDecoderConfig FFmpegDemuxerStream::audio_decoder_config() {
813 DCHECK(task_runner_->RunsTasksInCurrentSequence());
814 DCHECK_EQ(type_, AUDIO);
815 DCHECK(audio_config_.get());
816 return *audio_config_;
819 VideoDecoderConfig FFmpegDemuxerStream::video_decoder_config() {
820 DCHECK(task_runner_->RunsTasksInCurrentSequence());
821 DCHECK_EQ(type_, VIDEO);
822 DCHECK(video_config_.get());
823 return *video_config_;
826 bool FFmpegDemuxerStream::IsEnabled() const {
827 DCHECK(task_runner_->RunsTasksInCurrentSequence());
831 void FFmpegDemuxerStream::SetEnabled(bool enabled, base::TimeDelta timestamp) {
832 DCHECK(task_runner_->RunsTasksInCurrentSequence());
834 DCHECK(demuxer_->ffmpeg_task_runner());
835 if (enabled == is_enabled_)
838 is_enabled_ = enabled;
839 demuxer_->ffmpeg_task_runner()->PostTask(
840 FROM_HERE, base::BindOnce(&SetAVStreamDiscard, av_stream(),
841 enabled ? AVDISCARD_DEFAULT : AVDISCARD_ALL));
843 waiting_for_keyframe_ = true;
845 if (!is_enabled_ && read_cb_) {
846 DVLOG(1) << "Read from disabled stream, returning EOS";
847 std::move(read_cb_).Run(kOk, DecoderBuffer::CreateEOSBuffer());
851 void FFmpegDemuxerStream::SetLiveness(StreamLiveness liveness) {
852 DCHECK(task_runner_->RunsTasksInCurrentSequence());
853 DCHECK_EQ(liveness_, StreamLiveness::kUnknown);
854 liveness_ = liveness;
857 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const {
858 return buffered_ranges_;
861 void FFmpegDemuxerStream::SatisfyPendingRead() {
862 DCHECK(task_runner_->RunsTasksInCurrentSequence());
864 if (!buffer_queue_.IsEmpty()) {
865 std::move(read_cb_).Run(DemuxerStream::kOk, buffer_queue_.Pop());
866 } else if (end_of_stream_) {
867 std::move(read_cb_).Run(DemuxerStream::kOk,
868 DecoderBuffer::CreateEOSBuffer());
872 // Have capacity? Ask for more!
873 if (HasAvailableCapacity() && !end_of_stream_) {
874 demuxer_->NotifyCapacityAvailable();
878 bool FFmpegDemuxerStream::HasAvailableCapacity() {
879 // Try to have two second's worth of encoded data per stream.
880 const base::TimeDelta kCapacity = base::Seconds(2);
881 return buffer_queue_.IsEmpty() || buffer_queue_.Duration() < kCapacity;
884 size_t FFmpegDemuxerStream::MemoryUsage() const {
885 return buffer_queue_.data_size();
888 std::string FFmpegDemuxerStream::GetMetadata(const char* key) const {
889 const AVDictionaryEntry* entry =
890 av_dict_get(stream_->metadata, key, nullptr, 0);
891 return (entry == nullptr || entry->value == nullptr) ? "" : entry->value;
895 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp(
896 const AVRational& time_base,
898 if (timestamp == kNoFFmpegTimestamp)
901 return ConvertFromTimeBase(time_base, timestamp);
907 FFmpegDemuxer::FFmpegDemuxer(
908 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
909 DataSource* data_source,
910 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb,
911 MediaTracksUpdatedCB media_tracks_updated_cb,
914 : task_runner_(task_runner),
915 // FFmpeg has no asynchronous API, so we use base::WaitableEvents inside
916 // the BlockingUrlProtocol to handle hops to the render thread for network
918 blocking_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
919 {base::MayBlock(), base::TaskPriority::USER_BLOCKING})),
920 data_source_(data_source),
921 media_log_(media_log),
922 encrypted_media_init_data_cb_(encrypted_media_init_data_cb),
923 media_tracks_updated_cb_(std::move(media_tracks_updated_cb)),
924 is_local_file_(is_local_file) {
925 DCHECK(task_runner_.get());
926 DCHECK(data_source_);
927 DCHECK(media_tracks_updated_cb_);
930 FFmpegDemuxer::~FFmpegDemuxer() {
932 DCHECK(!pending_seek_cb_);
934 // NOTE: This class is not destroyed on |task_runner|, so we must ensure that
935 // there are no outstanding WeakPtrs by the time we reach here.
936 DCHECK(!weak_factory_.HasWeakPtrs());
938 // There may be outstanding tasks in the blocking pool which are trying to use
939 // these members, so release them in sequence with any outstanding calls. The
940 // earlier call to Abort() on |data_source_| prevents further access to it.
941 blocking_task_runner_->DeleteSoon(FROM_HERE, url_protocol_.release());
942 blocking_task_runner_->DeleteSoon(FROM_HERE, glue_.release());
945 std::string FFmpegDemuxer::GetDisplayName() const {
946 return "FFmpegDemuxer";
949 void FFmpegDemuxer::Initialize(DemuxerHost* host,
950 PipelineStatusCallback init_cb) {
951 DCHECK(task_runner_->RunsTasksInCurrentSequence());
953 weak_this_ = cancel_pending_seek_factory_.GetWeakPtr();
954 init_cb_ = std::move(init_cb);
956 // Give a WeakPtr to BlockingUrlProtocol since we'll need to release it on the
957 // blocking thread pool.
958 url_protocol_ = std::make_unique<BlockingUrlProtocol>(
959 data_source_, BindToCurrentLoop(base::BindRepeating(
960 &FFmpegDemuxer::OnDataSourceError, weak_this_)));
961 glue_ = std::make_unique<FFmpegGlue>(url_protocol_.get());
962 AVFormatContext* format_context = glue_->format_context();
964 // Disable ID3v1 tag reading to avoid costly seeks to end of file for data we
965 // don't use. FFmpeg will only read ID3v1 tags if no other metadata is
966 // available, so add a metadata entry to ensure some is always present.
967 av_dict_set(&format_context->metadata, "skip_id3v1_tags", "", 0);
969 // Ensure ffmpeg doesn't give up too early while looking for stream params;
970 // this does not increase the amount of data downloaded. The default value
971 // is 5 AV_TIME_BASE units (1 second each), which prevents some oddly muxed
972 // streams from being detected properly; this value was chosen arbitrarily.
973 format_context->max_analyze_duration = 60 * AV_TIME_BASE;
975 // Open the AVFormatContext using our glue layer.
976 base::PostTaskAndReplyWithResult(
977 blocking_task_runner_.get(), FROM_HERE,
978 base::BindOnce(&FFmpegGlue::OpenContext, base::Unretained(glue_.get()),
980 base::BindOnce(&FFmpegDemuxer::OnOpenContextDone,
981 weak_factory_.GetWeakPtr()));
984 void FFmpegDemuxer::AbortPendingReads() {
985 DCHECK(task_runner_->RunsTasksInCurrentSequence());
987 // If Stop() has been called, then drop this call.
991 // This should only be called after the demuxer has been initialized.
992 DCHECK_GT(streams_.size(), 0u);
994 // Abort all outstanding reads.
995 for (const auto& stream : streams_) {
1000 // It's important to invalidate read/seek completion callbacks to avoid any
1001 // errors that occur because of the data source abort.
1002 weak_factory_.InvalidateWeakPtrs();
1003 data_source_->Abort();
1005 // Aborting the read may cause EOF to be marked, undo this.
1006 blocking_task_runner_->PostTask(
1008 base::BindOnce(&UnmarkEndOfStreamAndClearError, glue_->format_context()));
1009 pending_read_ = false;
1011 // TODO(dalecurtis): We probably should report PIPELINE_ERROR_ABORT here
1012 // instead to avoid any preroll work that may be started upon return, but
1013 // currently the PipelineImpl does not know how to handle this.
1014 if (pending_seek_cb_)
1015 RunPendingSeekCB(PIPELINE_OK);
1018 void FFmpegDemuxer::Stop() {
1019 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1022 RunInitCB(PIPELINE_ERROR_ABORT);
1023 if (pending_seek_cb_)
1024 RunPendingSeekCB(PIPELINE_ERROR_ABORT);
1026 // The order of Stop() and Abort() is important here. If Abort() is called
1027 // first, control may pass into FFmpeg where it can destruct buffers that are
1028 // in the process of being fulfilled by the DataSource.
1029 data_source_->Stop();
1030 url_protocol_->Abort();
1032 for (const auto& stream : streams_) {
1037 data_source_ = nullptr;
1039 // Invalidate WeakPtrs on |task_runner_|, destruction may happen on another
1040 // thread. We don't need to wait for any outstanding tasks since they will all
1041 // fail to return after invalidating WeakPtrs.
1043 weak_factory_.InvalidateWeakPtrs();
1044 cancel_pending_seek_factory_.InvalidateWeakPtrs();
1047 void FFmpegDemuxer::StartWaitingForSeek(base::TimeDelta seek_time) {}
1049 void FFmpegDemuxer::CancelPendingSeek(base::TimeDelta seek_time) {
1050 if (task_runner_->RunsTasksInCurrentSequence()) {
1051 AbortPendingReads();
1053 // Don't use GetWeakPtr() here since we are on the wrong thread.
1054 task_runner_->PostTask(
1056 base::BindOnce(&FFmpegDemuxer::AbortPendingReads, weak_this_));
1060 void FFmpegDemuxer::Seek(base::TimeDelta time, PipelineStatusCallback cb) {
1061 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1062 DCHECK(!pending_seek_cb_);
1063 TRACE_EVENT_ASYNC_BEGIN0("media", "FFmpegDemuxer::Seek", this);
1064 pending_seek_cb_ = std::move(cb);
1065 SeekInternal(time, base::BindOnce(&FFmpegDemuxer::OnSeekFrameSuccess,
1066 weak_factory_.GetWeakPtr()));
1069 void FFmpegDemuxer::SeekInternal(base::TimeDelta time,
1070 base::OnceClosure seek_cb) {
1071 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1073 // FFmpeg requires seeks to be adjusted according to the lowest starting time.
1074 // Since EnqueuePacket() rebased negative timestamps by the start time, we
1075 // must correct the shift here.
1077 // Additionally, to workaround limitations in how we expose seekable ranges to
1078 // Blink (http://crbug.com/137275), we also want to clamp seeks before the
1079 // start time to the start time.
1080 base::TimeDelta seek_time;
1081 if (start_time_.is_negative()) {
1082 seek_time = time + start_time_;
1084 seek_time = std::max(start_time_, time);
1087 // When seeking in an opus stream we need to ensure we deliver enough data to
1088 // satisfy the seek preroll; otherwise the audio at the actual seek time will
1089 // not be entirely accurate.
1090 FFmpegDemuxerStream* audio_stream =
1091 GetFirstEnabledFFmpegStream(DemuxerStream::AUDIO);
1093 const AudioDecoderConfig& config = audio_stream->audio_decoder_config();
1094 if (config.codec() == AudioCodec::kOpus)
1095 seek_time = std::max(start_time_, seek_time - config.seek_preroll());
1098 // Choose the seeking stream based on whether it contains the seek time, if
1099 // no match can be found prefer the preferred stream.
1101 // TODO(dalecurtis): Currently FFmpeg does not ensure that all streams in a
1102 // given container will demux all packets after the seek point. Instead it
1103 // only guarantees that all packets after the file position of the seek will
1104 // be demuxed. It's an open question whether FFmpeg should fix this:
1105 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html
1106 // Tracked by http://crbug.com/387996.
1107 FFmpegDemuxerStream* demux_stream = FindPreferredStreamForSeeking(seek_time);
1108 DCHECK(demux_stream);
1109 const AVStream* seeking_stream = demux_stream->av_stream();
1110 DCHECK(seeking_stream);
1112 blocking_task_runner_->PostTaskAndReply(
1114 base::BindOnce(base::IgnoreResult(&av_seek_frame),
1115 glue_->format_context(), seeking_stream->index,
1116 ConvertToTimeBase(seeking_stream->time_base, seek_time),
1117 // Always seek to a timestamp <= to the desired timestamp.
1118 AVSEEK_FLAG_BACKWARD),
1119 std::move(seek_cb));
1122 base::Time FFmpegDemuxer::GetTimelineOffset() const {
1123 return timeline_offset_;
1126 std::vector<DemuxerStream*> FFmpegDemuxer::GetAllStreams() {
1127 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1128 std::vector<DemuxerStream*> result;
1129 // Put enabled streams at the beginning of the list so that
1130 // MediaResource::GetFirstStream returns the enabled stream if there is one.
1131 // TODO(servolk): Revisit this after media track switching is supported.
1132 for (const auto& stream : streams_) {
1133 if (stream && stream->IsEnabled())
1134 result.push_back(stream.get());
1136 // And include disabled streams at the end of the list.
1137 for (const auto& stream : streams_) {
1138 if (stream && !stream->IsEnabled())
1139 result.push_back(stream.get());
1144 FFmpegDemuxerStream* FFmpegDemuxer::GetFirstEnabledFFmpegStream(
1145 DemuxerStream::Type type) const {
1146 for (const auto& stream : streams_) {
1147 if (stream && stream->type() == type && stream->IsEnabled()) {
1148 return stream.get();
1154 base::TimeDelta FFmpegDemuxer::GetStartTime() const {
1155 return std::max(start_time_, base::TimeDelta());
1158 int64_t FFmpegDemuxer::GetMemoryUsage() const {
1159 int64_t allocation_size = 0;
1160 for (const auto& stream : streams_) {
1162 allocation_size += stream->MemoryUsage();
1164 return allocation_size;
1167 absl::optional<container_names::MediaContainerName>
1168 FFmpegDemuxer::GetContainerForMetrics() const {
1172 void FFmpegDemuxer::OnEncryptedMediaInitData(
1173 EmeInitDataType init_data_type,
1174 const std::string& encryption_key_id) {
1175 std::vector<uint8_t> key_id_local(encryption_key_id.begin(),
1176 encryption_key_id.end());
1177 encrypted_media_init_data_cb_.Run(init_data_type, key_id_local);
1180 void FFmpegDemuxer::NotifyCapacityAvailable() {
1181 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1182 ReadFrameIfNeeded();
1185 void FFmpegDemuxer::NotifyBufferingChanged() {
1186 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1187 Ranges<base::TimeDelta> buffered;
1188 bool initialized_buffered_ranges = false;
1189 for (const auto& stream : streams_) {
1192 if (initialized_buffered_ranges) {
1193 buffered = buffered.IntersectionWith(stream->GetBufferedRanges());
1195 buffered = stream->GetBufferedRanges();
1196 initialized_buffered_ranges = true;
1199 host_->OnBufferedTimeRangesChanged(buffered);
1202 // Helper for calculating the bitrate of the media based on information stored
1203 // in |format_context| or failing that the size and duration of the media.
1205 // Returns 0 if a bitrate could not be determined.
1206 static int CalculateBitrate(AVFormatContext* format_context,
1207 const base::TimeDelta& duration,
1208 int64_t filesize_in_bytes) {
1209 // If there is a bitrate set on the container, use it.
1210 if (format_context->bit_rate > 0)
1211 return format_context->bit_rate;
1213 // Then try to sum the bitrates individually per stream.
1215 for (size_t i = 0; i < format_context->nb_streams; ++i) {
1216 AVCodecParameters* codec_parameters = format_context->streams[i]->codecpar;
1217 bitrate += codec_parameters->bit_rate;
1222 // See if we can approximate the bitrate as long as we have a filesize and
1224 if (duration <= base::TimeDelta() || duration == kInfiniteDuration ||
1228 // Don't multiply by 8 first; it will overflow if (filesize_in_bytes >= 2^60).
1229 return base::ClampRound(filesize_in_bytes * duration.ToHz() * 8);
1232 void FFmpegDemuxer::OnOpenContextDone(bool result) {
1233 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1235 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1236 RunInitCB(PIPELINE_ERROR_ABORT);
1240 #if BUILDFLAG(IS_ANDROID)
1241 if (glue_->detected_hls()) {
1242 MEDIA_LOG(INFO, media_log_)
1243 << GetDisplayName() << ": detected HLS manifest";
1244 RunInitCB(DEMUXER_ERROR_DETECTED_HLS);
1250 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": open context failed";
1251 RunInitCB(DEMUXER_ERROR_COULD_NOT_OPEN);
1255 // Fully initialize AVFormatContext by parsing the stream a little.
1256 base::PostTaskAndReplyWithResult(
1257 blocking_task_runner_.get(), FROM_HERE,
1258 base::BindOnce(&avformat_find_stream_info, glue_->format_context(),
1259 static_cast<AVDictionary**>(nullptr)),
1260 base::BindOnce(&FFmpegDemuxer::OnFindStreamInfoDone,
1261 weak_factory_.GetWeakPtr()));
1264 void FFmpegDemuxer::OnFindStreamInfoDone(int result) {
1265 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1266 if (stopped_ || !data_source_) {
1267 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1268 RunInitCB(PIPELINE_ERROR_ABORT);
1273 MEDIA_LOG(ERROR, media_log_) << GetDisplayName()
1274 << ": find stream info failed";
1275 RunInitCB(DEMUXER_ERROR_COULD_NOT_PARSE);
1279 // Create demuxer stream entries for each possible AVStream. Each stream
1280 // is examined to determine if it is supported or not (is the codec enabled
1281 // for it in this release?). Unsupported streams are skipped, allowing for
1282 // partial playback. At least one audio or video stream must be playable.
1283 AVFormatContext* format_context = glue_->format_context();
1284 streams_.resize(format_context->nb_streams);
1286 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks());
1288 DCHECK(track_id_to_demux_stream_map_.empty());
1290 // If available, |start_time_| will be set to the lowest stream start time.
1291 start_time_ = kInfiniteDuration;
1293 base::TimeDelta max_duration;
1294 int supported_audio_track_count = 0;
1295 int supported_video_track_count = 0;
1296 bool has_opus_or_vorbis_audio = false;
1297 bool needs_negative_timestamp_fixup = false;
1298 for (size_t i = 0; i < format_context->nb_streams; ++i) {
1299 AVStream* stream = format_context->streams[i];
1300 const AVCodecParameters* codec_parameters = stream->codecpar;
1301 const AVMediaType codec_type = codec_parameters->codec_type;
1302 const AVCodecID codec_id = codec_parameters->codec_id;
1303 // Skip streams which are not properly detected.
1304 if (codec_id == AV_CODEC_ID_NONE) {
1305 stream->discard = AVDISCARD_ALL;
1309 if (codec_type == AVMEDIA_TYPE_AUDIO) {
1310 // Log the codec detected, whether it is supported or not, and whether or
1311 // not we have already detected a supported codec in another stream.
1312 const int32_t codec_hash = HashCodecName(GetCodecName(codec_id));
1313 base::UmaHistogramSparse("Media.DetectedAudioCodecHash", codec_hash);
1314 if (is_local_file_) {
1315 base::UmaHistogramSparse("Media.DetectedAudioCodecHash.Local",
1318 } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
1319 // Log the codec detected, whether it is supported or not, and whether or
1320 // not we have already detected a supported codec in another stream.
1321 const int32_t codec_hash = HashCodecName(GetCodecName(codec_id));
1322 base::UmaHistogramSparse("Media.DetectedVideoCodecHash", codec_hash);
1323 if (is_local_file_) {
1324 base::UmaHistogramSparse("Media.DetectedVideoCodecHash.Local",
1328 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
1329 if (codec_id == AV_CODEC_ID_HEVC) {
1330 // If ffmpeg is built without HEVC parser/decoder support, it will be
1331 // able to demux HEVC based solely on container-provided information,
1332 // but unable to get some of the parameters without parsing the stream
1333 // (e.g. coded size needs to be read from SPS, pixel format is typically
1334 // deduced from decoder config in hvcC box). These are not really needed
1335 // when using external decoder (e.g. hardware decoder), so override them
1336 // to make sure this translates into a valid VideoDecoderConfig. Coded
1337 // size is overridden in AVStreamToVideoDecoderConfig().
1338 if (stream->codecpar->format == AV_PIX_FMT_NONE)
1339 stream->codecpar->format = AV_PIX_FMT_YUV420P;
1342 } else if (codec_type == AVMEDIA_TYPE_SUBTITLE) {
1343 stream->discard = AVDISCARD_ALL;
1346 stream->discard = AVDISCARD_ALL;
1350 // Attempt to create a FFmpegDemuxerStream from the AVStream. This will
1351 // return nullptr if the AVStream is invalid. Validity checks will verify
1352 // things like: codec, channel layout, sample/pixel format, etc...
1353 std::unique_ptr<FFmpegDemuxerStream> demuxer_stream =
1354 FFmpegDemuxerStream::Create(this, stream, media_log_);
1355 if (demuxer_stream.get()) {
1356 streams_[i] = std::move(demuxer_stream);
1358 if (codec_type == AVMEDIA_TYPE_AUDIO) {
1359 MEDIA_LOG(INFO, media_log_)
1361 << ": skipping invalid or unsupported audio track";
1362 } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
1363 MEDIA_LOG(INFO, media_log_)
1365 << ": skipping invalid or unsupported video track";
1368 // This AVStream does not successfully convert.
1372 StreamParser::TrackId track_id =
1373 static_cast<StreamParser::TrackId>(media_tracks->tracks().size() + 1);
1375 MediaTrack::Label(streams_[i]->GetMetadata("handler_name"));
1376 auto track_language =
1377 MediaTrack::Language(streams_[i]->GetMetadata("language"));
1379 // Some metadata is named differently in FFmpeg for webm files.
1380 if (glue_->container() == container_names::CONTAINER_WEBM)
1381 track_label = MediaTrack::Label(streams_[i]->GetMetadata("title"));
1383 if (codec_type == AVMEDIA_TYPE_AUDIO) {
1384 ++supported_audio_track_count;
1385 streams_[i]->SetEnabled(supported_audio_track_count == 1,
1387 } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
1388 ++supported_video_track_count;
1389 streams_[i]->SetEnabled(supported_video_track_count == 1,
1393 // TODO(chcunningham): Remove the IsValidConfig() checks below. If the
1394 // config isn't valid we shouldn't have created a demuxer stream nor
1395 // an entry in |media_tracks|, so the check should always be true.
1396 if ((codec_type == AVMEDIA_TYPE_AUDIO &&
1397 media_tracks->getAudioConfig(track_id).IsValidConfig()) ||
1398 (codec_type == AVMEDIA_TYPE_VIDEO &&
1399 media_tracks->getVideoConfig(track_id).IsValidConfig())) {
1400 MEDIA_LOG(INFO, media_log_)
1402 << ": skipping duplicate media stream id=" << track_id;
1406 // Note when we find our audio/video stream (we only want one of each) and
1407 // record src= playback UMA stats for the stream's decoder config.
1408 MediaTrack* media_track = nullptr;
1409 if (codec_type == AVMEDIA_TYPE_AUDIO) {
1410 AudioDecoderConfig audio_config = streams_[i]->audio_decoder_config();
1411 RecordAudioCodecStats(audio_config);
1413 media_track = media_tracks->AddAudioTrack(audio_config, track_id,
1414 MediaTrack::Kind("main"),
1415 track_label, track_language);
1416 media_track->set_id(MediaTrack::Id(base::NumberToString(track_id)));
1417 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) ==
1418 track_id_to_demux_stream_map_.end());
1419 track_id_to_demux_stream_map_[media_track->id()] = streams_[i].get();
1420 } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
1421 VideoDecoderConfig video_config = streams_[i]->video_decoder_config();
1423 RecordVideoCodecStats(glue_->container(), video_config,
1424 stream->codecpar->color_range, media_log_);
1426 media_track = media_tracks->AddVideoTrack(video_config, track_id,
1427 MediaTrack::Kind("main"),
1428 track_label, track_language);
1429 media_track->set_id(MediaTrack::Id(base::NumberToString(track_id)));
1430 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) ==
1431 track_id_to_demux_stream_map_.end());
1432 track_id_to_demux_stream_map_[media_track->id()] = streams_[i].get();
1435 max_duration = std::max(max_duration, streams_[i]->duration());
1437 base::TimeDelta start_time = ExtractStartTime(stream);
1439 // Note: This value is used for seeking, so we must take the true value and
1440 // not the one possibly clamped to zero below.
1441 if (start_time != kNoTimestamp && start_time < start_time_)
1442 start_time_ = start_time;
1444 const bool is_opus_or_vorbis =
1445 codec_id == AV_CODEC_ID_OPUS || codec_id == AV_CODEC_ID_VORBIS;
1446 if (!has_opus_or_vorbis_audio)
1447 has_opus_or_vorbis_audio = is_opus_or_vorbis;
1449 if (codec_type == AVMEDIA_TYPE_AUDIO && start_time.is_negative() &&
1450 is_opus_or_vorbis) {
1451 needs_negative_timestamp_fixup = true;
1453 // Fixup the seeking information to avoid selecting the audio stream
1454 // simply because it has a lower starting time.
1455 start_time = base::TimeDelta();
1458 streams_[i]->set_start_time(start_time);
1461 if (media_tracks->tracks().empty()) {
1462 MEDIA_LOG(ERROR, media_log_) << GetDisplayName()
1463 << ": no supported streams";
1464 RunInitCB(DEMUXER_ERROR_NO_SUPPORTED_STREAMS);
1468 if (format_context->duration != kNoFFmpegTimestamp) {
1469 // If there is a duration value in the container use that to find the
1470 // maximum between it and the duration from A/V streams.
1471 const AVRational av_time_base = {1, AV_TIME_BASE};
1473 std::max(max_duration,
1474 ConvertFromTimeBase(av_time_base, format_context->duration));
1476 // The duration is unknown, in which case this is likely a live stream.
1477 max_duration = kInfiniteDuration;
1480 // Chained ogg is only allowed on single track audio only opus/vorbis media.
1481 const bool needs_chained_ogg_fixup =
1482 glue_->container() == container_names::CONTAINER_OGG &&
1483 supported_audio_track_count == 1 && !supported_video_track_count &&
1484 has_opus_or_vorbis_audio;
1486 // FFmpeg represents audio data marked as before the beginning of stream as
1487 // having negative timestamps. This data must be discarded after it has been
1488 // decoded, not before since it is used to warmup the decoder. There are
1489 // currently two known cases for this: vorbis in ogg and opus.
1491 // For API clarity, it was decided that the rest of the media pipeline should
1492 // not be exposed to negative timestamps. Which means we need to rebase these
1493 // negative timestamps and mark them for discard post decoding.
1495 // Post-decode frame dropping for packets with negative timestamps is outlined
1496 // in section A.2 in the Ogg Vorbis spec:
1497 // http://xiph.org/vorbis/doc/Vorbis_I_spec.html
1499 // FFmpeg's use of negative timestamps for opus pre-skip is nonstandard, but
1500 // for more information on pre-skip see section 4.2 of the Ogg Opus spec:
1501 // https://tools.ietf.org/html/draft-ietf-codec-oggopus-08#section-4.2
1502 if (needs_negative_timestamp_fixup || needs_chained_ogg_fixup) {
1503 for (auto& stream : streams_) {
1506 if (needs_negative_timestamp_fixup)
1507 stream->enable_negative_timestamp_fixups();
1508 if (needs_chained_ogg_fixup)
1509 stream->enable_chained_ogg_fixups();
1513 // If no start time could be determined, default to zero.
1514 if (start_time_ == kInfiniteDuration)
1515 start_time_ = base::TimeDelta();
1517 // MPEG-4 B-frames cause grief for a simple container like AVI. Enable PTS
1518 // generation so we always get timestamps, see http://crbug.com/169570
1519 if (glue_->container() == container_names::CONTAINER_AVI)
1520 format_context->flags |= AVFMT_FLAG_GENPTS;
1522 // FFmpeg will incorrectly adjust the start time of MP3 files into the future
1523 // based on discard samples. We were unable to fix this upstream without
1524 // breaking ffmpeg functionality. https://crbug.com/1062037
1525 if (glue_->container() == container_names::CONTAINER_MP3)
1526 start_time_ = base::TimeDelta();
1528 // For testing purposes, don't overwrite the timeline offset if set already.
1529 if (timeline_offset_.is_null()) {
1531 ExtractTimelineOffset(glue_->container(), format_context);
1534 // Since we're shifting the externally visible start time to zero, we need to
1535 // adjust the timeline offset to compensate.
1536 if (!timeline_offset_.is_null() && start_time_.is_negative())
1537 timeline_offset_ += start_time_;
1539 if (max_duration == kInfiniteDuration && !timeline_offset_.is_null()) {
1540 SetLiveness(StreamLiveness::kLive);
1541 } else if (max_duration != kInfiniteDuration) {
1542 SetLiveness(StreamLiveness::kRecorded);
1544 SetLiveness(StreamLiveness::kUnknown);
1547 // Good to go: set the duration and bitrate and notify we're done
1549 host_->SetDuration(max_duration);
1550 duration_ = max_duration;
1551 duration_known_ = (max_duration != kInfiniteDuration);
1553 int64_t filesize_in_bytes = 0;
1554 url_protocol_->GetSize(&filesize_in_bytes);
1555 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes);
1557 data_source_->SetBitrate(bitrate_);
1559 LogMetadata(format_context, max_duration);
1560 media_tracks_updated_cb_.Run(std::move(media_tracks));
1562 RunInitCB(PIPELINE_OK);
1565 void FFmpegDemuxer::LogMetadata(AVFormatContext* avctx,
1566 base::TimeDelta max_duration) {
1567 std::vector<AudioDecoderConfig> audio_tracks;
1568 std::vector<VideoDecoderConfig> video_tracks;
1570 DCHECK_EQ(avctx->nb_streams, streams_.size());
1572 for (auto const& stream : streams_) {
1575 if (stream->type() == DemuxerStream::AUDIO) {
1576 audio_tracks.push_back(stream->audio_decoder_config());
1577 } else if (stream->type() == DemuxerStream::VIDEO) {
1578 video_tracks.push_back(stream->video_decoder_config());
1581 media_log_->SetProperty<MediaLogProperty::kAudioTracks>(audio_tracks);
1582 media_log_->SetProperty<MediaLogProperty::kVideoTracks>(video_tracks);
1583 media_log_->SetProperty<MediaLogProperty::kMaxDuration>(max_duration);
1584 media_log_->SetProperty<MediaLogProperty::kStartTime>(start_time_);
1585 media_log_->SetProperty<MediaLogProperty::kBitrate>(bitrate_);
1588 FFmpegDemuxerStream* FFmpegDemuxer::FindStreamWithLowestStartTimestamp(
1590 FFmpegDemuxerStream* lowest_start_time_stream = nullptr;
1591 for (const auto& stream : streams_) {
1592 if (!stream || stream->IsEnabled() != enabled)
1594 if (av_stream_get_first_dts(stream->av_stream()) == kInvalidPTSMarker)
1596 if (!lowest_start_time_stream ||
1597 stream->start_time() < lowest_start_time_stream->start_time()) {
1598 lowest_start_time_stream = stream.get();
1601 return lowest_start_time_stream;
1604 FFmpegDemuxerStream* FFmpegDemuxer::FindPreferredStreamForSeeking(
1605 base::TimeDelta seek_time) {
1606 // If we have a selected/enabled video stream and its start time is lower
1607 // than the |seek_time| or unknown, then always prefer it for seeking.
1608 for (const auto& stream : streams_) {
1612 if (stream->type() != DemuxerStream::VIDEO)
1615 if (av_stream_get_first_dts(stream->av_stream()) == kInvalidPTSMarker)
1618 if (!stream->IsEnabled())
1621 if (stream->start_time() <= seek_time)
1622 return stream.get();
1625 // If video stream is not present or |seek_time| is lower than the video start
1626 // time, then try to find an enabled stream with the lowest start time.
1627 FFmpegDemuxerStream* lowest_start_time_enabled_stream =
1628 FindStreamWithLowestStartTimestamp(true);
1629 if (lowest_start_time_enabled_stream &&
1630 lowest_start_time_enabled_stream->start_time() <= seek_time) {
1631 return lowest_start_time_enabled_stream;
1634 // If there's no enabled streams to consider from, try a disabled stream with
1635 // the lowest known start time.
1636 FFmpegDemuxerStream* lowest_start_time_disabled_stream =
1637 FindStreamWithLowestStartTimestamp(false);
1638 if (lowest_start_time_disabled_stream &&
1639 lowest_start_time_disabled_stream->start_time() <= seek_time) {
1640 return lowest_start_time_disabled_stream;
1643 // Otherwise fall back to any other stream.
1644 for (const auto& stream : streams_) {
1646 return stream.get();
1653 void FFmpegDemuxer::OnSeekFrameSuccess() {
1654 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1655 DCHECK(pending_seek_cb_);
1658 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1659 RunPendingSeekCB(PIPELINE_ERROR_ABORT);
1663 // Tell streams to flush buffers due to seeking.
1664 for (const auto& stream : streams_) {
1666 stream->FlushBuffers(false);
1669 // Resume reading until capacity.
1670 ReadFrameIfNeeded();
1672 // Notify we're finished seeking.
1673 RunPendingSeekCB(PIPELINE_OK);
1676 void FFmpegDemuxer::FindAndEnableProperTracks(
1677 const std::vector<MediaTrack::Id>& track_ids,
1678 base::TimeDelta curr_time,
1679 DemuxerStream::Type track_type,
1680 TrackChangeCB change_completed_cb) {
1681 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1683 std::set<FFmpegDemuxerStream*> enabled_streams;
1684 for (const auto& id : track_ids) {
1685 auto it = track_id_to_demux_stream_map_.find(id);
1686 if (it == track_id_to_demux_stream_map_.end())
1688 FFmpegDemuxerStream* stream = it->second;
1689 DCHECK_EQ(track_type, stream->type());
1690 // TODO(servolk): Remove after multiple enabled audio tracks are supported
1691 // by the media::RendererImpl.
1692 if (!enabled_streams.empty()) {
1693 MEDIA_LOG(INFO, media_log_)
1694 << "Only one enabled audio track is supported, ignoring track " << id;
1697 enabled_streams.insert(stream);
1698 stream->SetEnabled(true, curr_time);
1701 // First disable all streams that need to be disabled and then enable streams
1702 // that are enabled.
1703 for (const auto& stream : streams_) {
1704 if (stream && stream->type() == track_type &&
1705 enabled_streams.find(stream.get()) == enabled_streams.end()) {
1706 DVLOG(1) << __func__ << ": disabling stream " << stream.get();
1707 stream->SetEnabled(false, curr_time);
1711 std::vector<DemuxerStream*> streams(enabled_streams.begin(),
1712 enabled_streams.end());
1713 std::move(change_completed_cb).Run(track_type, streams);
1716 void FFmpegDemuxer::OnEnabledAudioTracksChanged(
1717 const std::vector<MediaTrack::Id>& track_ids,
1718 base::TimeDelta curr_time,
1719 TrackChangeCB change_completed_cb) {
1720 FindAndEnableProperTracks(track_ids, curr_time, DemuxerStream::AUDIO,
1721 std::move(change_completed_cb));
1724 void FFmpegDemuxer::OnVideoSeekedForTrackChange(
1725 DemuxerStream* video_stream,
1726 base::OnceClosure seek_completed_cb) {
1727 static_cast<FFmpegDemuxerStream*>(video_stream)->FlushBuffers(true);
1728 std::move(seek_completed_cb).Run();
1731 void FFmpegDemuxer::SeekOnVideoTrackChange(
1732 base::TimeDelta seek_to_time,
1733 TrackChangeCB seek_completed_cb,
1734 DemuxerStream::Type stream_type,
1735 const std::vector<DemuxerStream*>& streams) {
1736 DCHECK_EQ(stream_type, DemuxerStream::VIDEO);
1737 if (streams.size() != 1u) {
1738 // If FFmpegDemuxer::FindAndEnableProperTracks() was not able to find the
1739 // selected streams in the ID->DemuxerStream map, then its possible for
1740 // this vector to be empty. If that's the case, we don't want to bother
1741 // with seeking, and just call the callback immediately.
1742 std::move(seek_completed_cb).Run(stream_type, streams);
1745 SeekInternal(seek_to_time,
1746 base::BindOnce(&FFmpegDemuxer::OnVideoSeekedForTrackChange,
1747 weak_factory_.GetWeakPtr(), streams[0],
1748 base::BindOnce(std::move(seek_completed_cb),
1749 DemuxerStream::VIDEO, streams)));
1752 void FFmpegDemuxer::OnSelectedVideoTrackChanged(
1753 const std::vector<MediaTrack::Id>& track_ids,
1754 base::TimeDelta curr_time,
1755 TrackChangeCB change_completed_cb) {
1756 // Find tracks -> Seek track -> run callback.
1757 FindAndEnableProperTracks(
1758 track_ids, curr_time, DemuxerStream::VIDEO,
1759 track_ids.empty() ? std::move(change_completed_cb)
1760 : base::BindOnce(&FFmpegDemuxer::SeekOnVideoTrackChange,
1761 weak_factory_.GetWeakPtr(), curr_time,
1762 std::move(change_completed_cb)));
1765 void FFmpegDemuxer::ReadFrameIfNeeded() {
1766 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1768 // Make sure we have work to do before reading.
1769 if (stopped_ || !StreamsHaveAvailableCapacity() || pending_read_ ||
1774 // Allocate and read an AVPacket from the media. Save |packet_ptr| since
1775 // evaluation order of packet.get() and std::move(&packet) is
1777 auto packet = ScopedAVPacket::Allocate();
1778 AVPacket* packet_ptr = packet.get();
1780 pending_read_ = true;
1781 base::PostTaskAndReplyWithResult(
1782 blocking_task_runner_.get(), FROM_HERE,
1783 base::BindOnce(&ReadFrameAndDiscardEmpty, glue_->format_context(),
1785 base::BindOnce(&FFmpegDemuxer::OnReadFrameDone,
1786 weak_factory_.GetWeakPtr(), std::move(packet)));
1789 void FFmpegDemuxer::OnReadFrameDone(ScopedAVPacket packet, int result) {
1790 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1791 DCHECK(pending_read_);
1792 pending_read_ = false;
1794 if (stopped_ || pending_seek_cb_)
1797 // Consider the stream as ended if:
1798 // - either underlying ffmpeg returned an error
1799 // - or FFMpegDemuxer reached the maximum allowed memory usage.
1800 if (result < 0 || IsMaxMemoryUsageReached()) {
1802 MEDIA_LOG(DEBUG, media_log_)
1804 << ": av_read_frame(): " << AVErrorToString(result);
1806 MEDIA_LOG(DEBUG, media_log_)
1807 << GetDisplayName() << ": memory limit exceeded";
1810 // Update the duration based on the highest elapsed time across all streams.
1811 base::TimeDelta max_duration;
1812 for (const auto& stream : streams_) {
1816 base::TimeDelta duration = stream->duration();
1817 if (duration != kNoTimestamp && duration > max_duration)
1818 max_duration = duration;
1821 if (duration_ == kInfiniteDuration || max_duration > duration_) {
1822 host_->SetDuration(max_duration);
1823 duration_known_ = true;
1824 duration_ = max_duration;
1827 // If we have reached the end of stream, tell the downstream filters about
1833 // Queue the packet with the appropriate stream; we must defend against ffmpeg
1834 // giving us a bad stream index. See http://crbug.com/698549 for example.
1835 if (packet->stream_index >= 0 &&
1836 static_cast<size_t>(packet->stream_index) < streams_.size()) {
1837 // This is ensured by ReadFrameAndDiscardEmpty.
1838 DCHECK(packet->data);
1839 DCHECK(packet->size);
1841 if (auto& demuxer_stream = streams_[packet->stream_index]) {
1842 if (demuxer_stream->IsEnabled())
1843 demuxer_stream->EnqueuePacket(std::move(packet));
1845 // If duration estimate was incorrect, update it and tell higher layers.
1846 if (duration_known_) {
1847 const base::TimeDelta duration = demuxer_stream->duration();
1848 if (duration != kNoTimestamp && duration > duration_) {
1849 duration_ = duration;
1850 host_->SetDuration(duration_);
1856 // Keep reading until we've reached capacity.
1857 ReadFrameIfNeeded();
1860 bool FFmpegDemuxer::StreamsHaveAvailableCapacity() {
1861 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1862 for (const auto& stream : streams_) {
1863 if (stream && stream->IsEnabled() && stream->HasAvailableCapacity())
1869 bool FFmpegDemuxer::IsMaxMemoryUsageReached() const {
1870 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1872 size_t memory_left =
1873 GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kFFmpegDemuxer);
1874 for (const auto& stream : streams_) {
1878 size_t stream_memory_usage = stream->MemoryUsage();
1879 if (stream_memory_usage > memory_left)
1881 memory_left -= stream_memory_usage;
1886 void FFmpegDemuxer::StreamHasEnded() {
1887 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1888 for (const auto& stream : streams_) {
1890 stream->SetEndOfStream();
1894 void FFmpegDemuxer::OnDataSourceError() {
1895 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": data source error";
1896 host_->OnDemuxerError(PIPELINE_ERROR_READ);
1899 void FFmpegDemuxer::NotifyDemuxerError(PipelineStatus status) {
1900 MEDIA_LOG(ERROR, media_log_) << GetDisplayName()
1901 << ": demuxer error: " << status;
1902 host_->OnDemuxerError(status);
1905 void FFmpegDemuxer::SetLiveness(StreamLiveness liveness) {
1906 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1907 for (const auto& stream : streams_) {
1909 stream->SetLiveness(liveness);
1913 void FFmpegDemuxer::RunInitCB(PipelineStatus status) {
1914 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1916 TRACE_EVENT_ASYNC_END1("media", "FFmpegDemuxer::Initialize", this, "status",
1917 PipelineStatusToString(status));
1918 std::move(init_cb_).Run(status);
1921 void FFmpegDemuxer::RunPendingSeekCB(PipelineStatus status) {
1922 DCHECK(task_runner_->RunsTasksInCurrentSequence());
1923 DCHECK(pending_seek_cb_);
1924 TRACE_EVENT_ASYNC_END1("media", "FFmpegDemuxer::Seek", this, "status",
1925 PipelineStatusToString(status));
1926 std::move(pending_seek_cb_).Run(status);
1929 } // namespace media