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 <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 return base::Time(); | 62 return base::Time(); |
63 } | 63 } |
64 | 64 |
65 static base::TimeDelta FramesToTimeDelta(int frames, double sample_rate) { | 65 static base::TimeDelta FramesToTimeDelta(int frames, double sample_rate) { |
66 return base::TimeDelta::FromMicroseconds( | 66 return base::TimeDelta::FromMicroseconds( |
67 frames * base::Time::kMicrosecondsPerSecond / sample_rate); | 67 frames * base::Time::kMicrosecondsPerSecond / sample_rate); |
68 } | 68 } |
69 | 69 |
70 static base::TimeDelta ExtractStartTime(AVStream* stream, | 70 static base::TimeDelta ExtractStartTime(AVStream* stream, |
71 base::TimeDelta start_time_estimate) { | 71 base::TimeDelta start_time_estimate) { |
72 DCHECK(start_time_estimate != kNoTimestamp()); | 72 DCHECK(start_time_estimate != kNoTimestamp); |
73 if (stream->start_time == static_cast<int64_t>(AV_NOPTS_VALUE)) { | 73 if (stream->start_time == static_cast<int64_t>(AV_NOPTS_VALUE)) { |
74 return start_time_estimate == kInfiniteDuration() ? kNoTimestamp() | 74 return start_time_estimate == kInfiniteDuration ? kNoTimestamp |
75 : start_time_estimate; | 75 : start_time_estimate; |
76 } | 76 } |
77 | 77 |
78 // First try the lower of the estimate and the |start_time| value. | 78 // First try the lower of the estimate and the |start_time| value. |
79 base::TimeDelta start_time = | 79 base::TimeDelta start_time = |
80 std::min(ConvertFromTimeBase(stream->time_base, stream->start_time), | 80 std::min(ConvertFromTimeBase(stream->time_base, stream->start_time), |
81 start_time_estimate); | 81 start_time_estimate); |
82 | 82 |
83 // Next see if the first buffered pts value is usable. | 83 // Next see if the first buffered pts value is usable. |
84 if (stream->pts_buffer[0] != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 84 if (stream->pts_buffer[0] != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
85 const base::TimeDelta buffered_pts = | 85 const base::TimeDelta buffered_pts = |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 return context->codec_descriptor->name; | 187 return context->codec_descriptor->name; |
188 const AVCodecDescriptor* codec_descriptor = | 188 const AVCodecDescriptor* codec_descriptor = |
189 avcodec_descriptor_get(context->codec_id); | 189 avcodec_descriptor_get(context->codec_id); |
190 // If the codec name can't be determined, return none for tracking. | 190 // If the codec name can't be determined, return none for tracking. |
191 return codec_descriptor ? codec_descriptor->name : kCodecNone; | 191 return codec_descriptor ? codec_descriptor->name : kCodecNone; |
192 } | 192 } |
193 | 193 |
194 static void SetTimeProperty(MediaLogEvent* event, | 194 static void SetTimeProperty(MediaLogEvent* event, |
195 const std::string& key, | 195 const std::string& key, |
196 base::TimeDelta value) { | 196 base::TimeDelta value) { |
197 if (value == kInfiniteDuration()) | 197 if (value == kInfiniteDuration) |
198 event->params.SetString(key, "kInfiniteDuration"); | 198 event->params.SetString(key, "kInfiniteDuration"); |
199 else if (value == kNoTimestamp()) | 199 else if (value == kNoTimestamp) |
200 event->params.SetString(key, "kNoTimestamp"); | 200 event->params.SetString(key, "kNoTimestamp"); |
201 else | 201 else |
202 event->params.SetDouble(key, value.InSecondsF()); | 202 event->params.SetDouble(key, value.InSecondsF()); |
203 } | 203 } |
204 | 204 |
205 std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create( | 205 std::unique_ptr<FFmpegDemuxerStream> FFmpegDemuxerStream::Create( |
206 FFmpegDemuxer* demuxer, | 206 FFmpegDemuxer* demuxer, |
207 AVStream* stream, | 207 AVStream* stream, |
208 const scoped_refptr<MediaLog>& media_log) { | 208 const scoped_refptr<MediaLog>& media_log) { |
209 if (!demuxer || !stream) | 209 if (!demuxer || !stream) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 std::unique_ptr<AudioDecoderConfig> audio_config, | 262 std::unique_ptr<AudioDecoderConfig> audio_config, |
263 std::unique_ptr<VideoDecoderConfig> video_config) | 263 std::unique_ptr<VideoDecoderConfig> video_config) |
264 : demuxer_(demuxer), | 264 : demuxer_(demuxer), |
265 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 265 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
266 stream_(stream), | 266 stream_(stream), |
267 audio_config_(audio_config.release()), | 267 audio_config_(audio_config.release()), |
268 video_config_(video_config.release()), | 268 video_config_(video_config.release()), |
269 type_(UNKNOWN), | 269 type_(UNKNOWN), |
270 liveness_(LIVENESS_UNKNOWN), | 270 liveness_(LIVENESS_UNKNOWN), |
271 end_of_stream_(false), | 271 end_of_stream_(false), |
272 last_packet_timestamp_(kNoTimestamp()), | 272 last_packet_timestamp_(kNoTimestamp), |
273 last_packet_duration_(kNoTimestamp()), | 273 last_packet_duration_(kNoTimestamp), |
274 video_rotation_(VIDEO_ROTATION_0), | 274 video_rotation_(VIDEO_ROTATION_0), |
275 is_enabled_(true), | 275 is_enabled_(true), |
276 waiting_for_keyframe_(false), | 276 waiting_for_keyframe_(false), |
277 fixup_negative_timestamps_(false) { | 277 fixup_negative_timestamps_(false) { |
278 DCHECK(demuxer_); | 278 DCHECK(demuxer_); |
279 | 279 |
280 bool is_encrypted = false; | 280 bool is_encrypted = false; |
281 int rotation = 0; | 281 int rotation = 0; |
282 AVDictionaryEntry* rotation_entry = NULL; | 282 AVDictionaryEntry* rotation_entry = NULL; |
283 | 283 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 const uint32_t* skip_samples_ptr = | 433 const uint32_t* skip_samples_ptr = |
434 reinterpret_cast<const uint32_t*>(av_packet_get_side_data( | 434 reinterpret_cast<const uint32_t*>(av_packet_get_side_data( |
435 packet.get(), AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); | 435 packet.get(), AV_PKT_DATA_SKIP_SAMPLES, &skip_samples_size)); |
436 const int kSkipSamplesValidSize = 10; | 436 const int kSkipSamplesValidSize = 10; |
437 const int kSkipEndSamplesOffset = 1; | 437 const int kSkipEndSamplesOffset = 1; |
438 if (skip_samples_size >= kSkipSamplesValidSize) { | 438 if (skip_samples_size >= kSkipSamplesValidSize) { |
439 // Because FFmpeg rolls codec delay and skip samples into one we can only | 439 // Because FFmpeg rolls codec delay and skip samples into one we can only |
440 // allow front discard padding on the first buffer. Otherwise the discard | 440 // allow front discard padding on the first buffer. Otherwise the discard |
441 // helper can't figure out which data to discard. See AudioDiscardHelper. | 441 // helper can't figure out which data to discard. See AudioDiscardHelper. |
442 int discard_front_samples = base::ByteSwapToLE32(*skip_samples_ptr); | 442 int discard_front_samples = base::ByteSwapToLE32(*skip_samples_ptr); |
443 if (last_packet_timestamp_ != kNoTimestamp() && discard_front_samples) { | 443 if (last_packet_timestamp_ != kNoTimestamp && discard_front_samples) { |
444 DLOG(ERROR) << "Skip samples are only allowed for the first packet."; | 444 DLOG(ERROR) << "Skip samples are only allowed for the first packet."; |
445 discard_front_samples = 0; | 445 discard_front_samples = 0; |
446 } | 446 } |
447 | 447 |
448 const int discard_end_samples = | 448 const int discard_end_samples = |
449 base::ByteSwapToLE32(*(skip_samples_ptr + kSkipEndSamplesOffset)); | 449 base::ByteSwapToLE32(*(skip_samples_ptr + kSkipEndSamplesOffset)); |
450 const int samples_per_second = | 450 const int samples_per_second = |
451 audio_decoder_config().samples_per_second(); | 451 audio_decoder_config().samples_per_second(); |
452 buffer->set_discard_padding(std::make_pair( | 452 buffer->set_discard_padding(std::make_pair( |
453 FramesToTimeDelta(discard_front_samples, samples_per_second), | 453 FramesToTimeDelta(discard_front_samples, samples_per_second), |
454 FramesToTimeDelta(discard_end_samples, samples_per_second))); | 454 FramesToTimeDelta(discard_end_samples, samples_per_second))); |
455 } | 455 } |
456 | 456 |
457 if (decrypt_config) | 457 if (decrypt_config) |
458 buffer->set_decrypt_config(std::move(decrypt_config)); | 458 buffer->set_decrypt_config(std::move(decrypt_config)); |
459 } | 459 } |
460 | 460 |
461 if (packet->duration >= 0) { | 461 if (packet->duration >= 0) { |
462 buffer->set_duration( | 462 buffer->set_duration( |
463 ConvertStreamTimestamp(stream_->time_base, packet->duration)); | 463 ConvertStreamTimestamp(stream_->time_base, packet->duration)); |
464 } else { | 464 } else { |
465 // TODO(wolenetz): Remove when FFmpeg stops returning negative durations. | 465 // TODO(wolenetz): Remove when FFmpeg stops returning negative durations. |
466 // https://crbug.com/394418 | 466 // https://crbug.com/394418 |
467 DVLOG(1) << "FFmpeg returned a buffer with a negative duration! " | 467 DVLOG(1) << "FFmpeg returned a buffer with a negative duration! " |
468 << packet->duration; | 468 << packet->duration; |
469 buffer->set_duration(kNoTimestamp()); | 469 buffer->set_duration(kNoTimestamp); |
470 } | 470 } |
471 | 471 |
472 // Note: If pts is AV_NOPTS_VALUE, stream_timestamp will be kNoTimestamp(). | 472 // Note: If pts is AV_NOPTS_VALUE, stream_timestamp will be kNoTimestamp. |
473 const base::TimeDelta stream_timestamp = | 473 const base::TimeDelta stream_timestamp = |
474 ConvertStreamTimestamp(stream_->time_base, packet->pts); | 474 ConvertStreamTimestamp(stream_->time_base, packet->pts); |
475 | 475 |
476 if (stream_timestamp != kNoTimestamp()) { | 476 if (stream_timestamp != kNoTimestamp) { |
477 const bool is_audio = type() == AUDIO; | 477 const bool is_audio = type() == AUDIO; |
478 | 478 |
479 // If this file has negative timestamps don't rebase any other stream types | 479 // If this file has negative timestamps don't rebase any other stream types |
480 // against the negative starting time. | 480 // against the negative starting time. |
481 base::TimeDelta start_time = demuxer_->start_time(); | 481 base::TimeDelta start_time = demuxer_->start_time(); |
482 if (fixup_negative_timestamps_ && !is_audio && | 482 if (fixup_negative_timestamps_ && !is_audio && |
483 start_time < base::TimeDelta()) { | 483 start_time < base::TimeDelta()) { |
484 start_time = base::TimeDelta(); | 484 start_time = base::TimeDelta(); |
485 } | 485 } |
486 | 486 |
487 // Don't rebase timestamps for positive start times, the HTML Media Spec | 487 // Don't rebase timestamps for positive start times, the HTML Media Spec |
488 // details this in section "4.8.10.6 Offsets into the media resource." We | 488 // details this in section "4.8.10.6 Offsets into the media resource." We |
489 // will still need to rebase timestamps before seeking with FFmpeg though. | 489 // will still need to rebase timestamps before seeking with FFmpeg though. |
490 if (start_time > base::TimeDelta()) | 490 if (start_time > base::TimeDelta()) |
491 start_time = base::TimeDelta(); | 491 start_time = base::TimeDelta(); |
492 | 492 |
493 buffer->set_timestamp(stream_timestamp - start_time); | 493 buffer->set_timestamp(stream_timestamp - start_time); |
494 | 494 |
495 // If enabled, and no codec delay is present, mark audio packets with | 495 // If enabled, and no codec delay is present, mark audio packets with |
496 // negative timestamps for post-decode discard. | 496 // negative timestamps for post-decode discard. |
497 if (fixup_negative_timestamps_ && is_audio && | 497 if (fixup_negative_timestamps_ && is_audio && |
498 stream_timestamp < base::TimeDelta() && | 498 stream_timestamp < base::TimeDelta() && |
499 buffer->duration() != kNoTimestamp()) { | 499 buffer->duration() != kNoTimestamp) { |
500 if (!stream_->codec->delay) { | 500 if (!stream_->codec->delay) { |
501 DCHECK_EQ(buffer->discard_padding().first, base::TimeDelta()); | 501 DCHECK_EQ(buffer->discard_padding().first, base::TimeDelta()); |
502 | 502 |
503 if (stream_timestamp + buffer->duration() < base::TimeDelta()) { | 503 if (stream_timestamp + buffer->duration() < base::TimeDelta()) { |
504 DCHECK_EQ(buffer->discard_padding().second, base::TimeDelta()); | 504 DCHECK_EQ(buffer->discard_padding().second, base::TimeDelta()); |
505 | 505 |
506 // Discard the entire packet if it's entirely before zero. | 506 // Discard the entire packet if it's entirely before zero. |
507 buffer->set_discard_padding( | 507 buffer->set_discard_padding( |
508 std::make_pair(kInfiniteDuration(), base::TimeDelta())); | 508 std::make_pair(kInfiniteDuration, base::TimeDelta())); |
509 } else { | 509 } else { |
510 // Only discard part of the frame if it overlaps zero. | 510 // Only discard part of the frame if it overlaps zero. |
511 buffer->set_discard_padding(std::make_pair( | 511 buffer->set_discard_padding(std::make_pair( |
512 -stream_timestamp, buffer->discard_padding().second)); | 512 -stream_timestamp, buffer->discard_padding().second)); |
513 } | 513 } |
514 } else { | 514 } else { |
515 // Verify that codec delay would cover discard and that we don't need to | 515 // Verify that codec delay would cover discard and that we don't need to |
516 // mark the packet for post decode discard. Since timestamps may be in | 516 // mark the packet for post decode discard. Since timestamps may be in |
517 // milliseconds and codec delay in nanosecond precision, round up to the | 517 // milliseconds and codec delay in nanosecond precision, round up to the |
518 // nearest millisecond. See enable_negative_timestamp_fixups(). | 518 // nearest millisecond. See enable_negative_timestamp_fixups(). |
519 DCHECK_LE(-std::ceil(FramesToTimeDelta( | 519 DCHECK_LE(-std::ceil(FramesToTimeDelta( |
520 audio_decoder_config().codec_delay(), | 520 audio_decoder_config().codec_delay(), |
521 audio_decoder_config().samples_per_second()) | 521 audio_decoder_config().samples_per_second()) |
522 .InMillisecondsF()), | 522 .InMillisecondsF()), |
523 stream_timestamp.InMillisecondsF()); | 523 stream_timestamp.InMillisecondsF()); |
524 } | 524 } |
525 } | 525 } |
526 } else { | 526 } else { |
527 // If this happens on the first packet, decoders will throw an error. | 527 // If this happens on the first packet, decoders will throw an error. |
528 buffer->set_timestamp(kNoTimestamp()); | 528 buffer->set_timestamp(kNoTimestamp); |
529 } | 529 } |
530 | 530 |
531 if (last_packet_timestamp_ != kNoTimestamp()) { | 531 if (last_packet_timestamp_ != kNoTimestamp) { |
532 // FFmpeg doesn't support chained ogg correctly. Instead of guaranteeing | 532 // FFmpeg doesn't support chained ogg correctly. Instead of guaranteeing |
533 // continuity across links in the chain it uses the timestamp information | 533 // continuity across links in the chain it uses the timestamp information |
534 // from each link directly. Doing so can lead to timestamps which appear to | 534 // from each link directly. Doing so can lead to timestamps which appear to |
535 // go backwards in time. | 535 // go backwards in time. |
536 // | 536 // |
537 // If the new link starts with a negative timestamp or a timestamp less than | 537 // If the new link starts with a negative timestamp or a timestamp less than |
538 // the original (positive) |start_time|, we will get a negative timestamp | 538 // the original (positive) |start_time|, we will get a negative timestamp |
539 // here. It's also possible FFmpeg returns kNoTimestamp() here if it's not | 539 // here. It's also possible FFmpeg returns kNoTimestamp here if it's not |
540 // able to work out a timestamp using the previous link and the next. | 540 // able to work out a timestamp using the previous link and the next. |
541 // | 541 // |
542 // Fixing chained ogg is non-trivial, so for now just reuse the last good | 542 // Fixing chained ogg is non-trivial, so for now just reuse the last good |
543 // timestamp. The decoder will rewrite the timestamps to be sample accurate | 543 // timestamp. The decoder will rewrite the timestamps to be sample accurate |
544 // later. See http://crbug.com/396864. | 544 // later. See http://crbug.com/396864. |
545 if (fixup_negative_timestamps_ && | 545 if (fixup_negative_timestamps_ && |
546 (buffer->timestamp() == kNoTimestamp() || | 546 (buffer->timestamp() == kNoTimestamp || |
547 buffer->timestamp() < last_packet_timestamp_)) { | 547 buffer->timestamp() < last_packet_timestamp_)) { |
548 buffer->set_timestamp(last_packet_timestamp_ + | 548 buffer->set_timestamp(last_packet_timestamp_ + |
549 (last_packet_duration_ != kNoTimestamp() | 549 (last_packet_duration_ != kNoTimestamp |
550 ? last_packet_duration_ | 550 ? last_packet_duration_ |
551 : base::TimeDelta::FromMicroseconds(1))); | 551 : base::TimeDelta::FromMicroseconds(1))); |
552 } | 552 } |
553 | 553 |
554 // The demuxer should always output positive timestamps. | 554 // The demuxer should always output positive timestamps. |
555 DCHECK(buffer->timestamp() >= base::TimeDelta()); | 555 DCHECK(buffer->timestamp() >= base::TimeDelta()); |
556 DCHECK(buffer->timestamp() != kNoTimestamp()); | 556 DCHECK(buffer->timestamp() != kNoTimestamp); |
557 | 557 |
558 if (last_packet_timestamp_ < buffer->timestamp()) { | 558 if (last_packet_timestamp_ < buffer->timestamp()) { |
559 buffered_ranges_.Add(last_packet_timestamp_, buffer->timestamp()); | 559 buffered_ranges_.Add(last_packet_timestamp_, buffer->timestamp()); |
560 demuxer_->NotifyBufferingChanged(); | 560 demuxer_->NotifyBufferingChanged(); |
561 } | 561 } |
562 } | 562 } |
563 | 563 |
564 if (packet.get()->flags & AV_PKT_FLAG_KEY) | 564 if (packet.get()->flags & AV_PKT_FLAG_KEY) |
565 buffer->set_is_key_frame(true); | 565 buffer->set_is_key_frame(true); |
566 | 566 |
(...skipping 14 matching lines...) Expand all Loading... |
581 DCHECK(task_runner_->BelongsToCurrentThread()); | 581 DCHECK(task_runner_->BelongsToCurrentThread()); |
582 DCHECK(read_cb_.is_null()) << "There should be no pending read"; | 582 DCHECK(read_cb_.is_null()) << "There should be no pending read"; |
583 | 583 |
584 // H264 and AAC require that we resend the header after flush. | 584 // H264 and AAC require that we resend the header after flush. |
585 // Reset bitstream for converter to do so. | 585 // Reset bitstream for converter to do so. |
586 // This is related to chromium issue 140371 (http://crbug.com/140371). | 586 // This is related to chromium issue 140371 (http://crbug.com/140371). |
587 ResetBitstreamConverter(); | 587 ResetBitstreamConverter(); |
588 | 588 |
589 buffer_queue_.Clear(); | 589 buffer_queue_.Clear(); |
590 end_of_stream_ = false; | 590 end_of_stream_ = false; |
591 last_packet_timestamp_ = kNoTimestamp(); | 591 last_packet_timestamp_ = kNoTimestamp; |
592 last_packet_duration_ = kNoTimestamp(); | 592 last_packet_duration_ = kNoTimestamp; |
593 } | 593 } |
594 | 594 |
595 void FFmpegDemuxerStream::Stop() { | 595 void FFmpegDemuxerStream::Stop() { |
596 DCHECK(task_runner_->BelongsToCurrentThread()); | 596 DCHECK(task_runner_->BelongsToCurrentThread()); |
597 buffer_queue_.Clear(); | 597 buffer_queue_.Clear(); |
598 if (!read_cb_.is_null()) { | 598 if (!read_cb_.is_null()) { |
599 base::ResetAndReturn(&read_cb_).Run( | 599 base::ResetAndReturn(&read_cb_).Run( |
600 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); | 600 DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()); |
601 } | 601 } |
602 demuxer_ = NULL; | 602 demuxer_ = NULL; |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 const AVDictionaryEntry* entry = | 794 const AVDictionaryEntry* entry = |
795 av_dict_get(stream_->metadata, key, NULL, 0); | 795 av_dict_get(stream_->metadata, key, NULL, 0); |
796 return (entry == NULL || entry->value == NULL) ? "" : entry->value; | 796 return (entry == NULL || entry->value == NULL) ? "" : entry->value; |
797 } | 797 } |
798 | 798 |
799 // static | 799 // static |
800 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( | 800 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( |
801 const AVRational& time_base, | 801 const AVRational& time_base, |
802 int64_t timestamp) { | 802 int64_t timestamp) { |
803 if (timestamp == static_cast<int64_t>(AV_NOPTS_VALUE)) | 803 if (timestamp == static_cast<int64_t>(AV_NOPTS_VALUE)) |
804 return kNoTimestamp(); | 804 return kNoTimestamp; |
805 | 805 |
806 return ConvertFromTimeBase(time_base, timestamp); | 806 return ConvertFromTimeBase(time_base, timestamp); |
807 } | 807 } |
808 | 808 |
809 // | 809 // |
810 // FFmpegDemuxer | 810 // FFmpegDemuxer |
811 // | 811 // |
812 FFmpegDemuxer::FFmpegDemuxer( | 812 FFmpegDemuxer::FFmpegDemuxer( |
813 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 813 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
814 DataSource* data_source, | 814 DataSource* data_source, |
815 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, | 815 const EncryptedMediaInitDataCB& encrypted_media_init_data_cb, |
816 const MediaTracksUpdatedCB& media_tracks_updated_cb, | 816 const MediaTracksUpdatedCB& media_tracks_updated_cb, |
817 const scoped_refptr<MediaLog>& media_log) | 817 const scoped_refptr<MediaLog>& media_log) |
818 : host_(NULL), | 818 : host_(NULL), |
819 task_runner_(task_runner), | 819 task_runner_(task_runner), |
820 blocking_thread_("FFmpegDemuxer"), | 820 blocking_thread_("FFmpegDemuxer"), |
821 pending_read_(false), | 821 pending_read_(false), |
822 pending_seek_(false), | 822 pending_seek_(false), |
823 data_source_(data_source), | 823 data_source_(data_source), |
824 media_log_(media_log), | 824 media_log_(media_log), |
825 bitrate_(0), | 825 bitrate_(0), |
826 start_time_(kNoTimestamp()), | 826 start_time_(kNoTimestamp), |
827 preferred_stream_for_seeking_(-1, kNoTimestamp()), | 827 preferred_stream_for_seeking_(-1, kNoTimestamp), |
828 fallback_stream_for_seeking_(-1, kNoTimestamp()), | 828 fallback_stream_for_seeking_(-1, kNoTimestamp), |
829 text_enabled_(false), | 829 text_enabled_(false), |
830 duration_known_(false), | 830 duration_known_(false), |
831 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), | 831 encrypted_media_init_data_cb_(encrypted_media_init_data_cb), |
832 media_tracks_updated_cb_(media_tracks_updated_cb), | 832 media_tracks_updated_cb_(media_tracks_updated_cb), |
833 weak_factory_(this) { | 833 weak_factory_(this) { |
834 DCHECK(task_runner_.get()); | 834 DCHECK(task_runner_.get()); |
835 DCHECK(data_source_); | 835 DCHECK(data_source_); |
836 DCHECK(!media_tracks_updated_cb_.is_null()); | 836 DCHECK(!media_tracks_updated_cb_.is_null()); |
837 } | 837 } |
838 | 838 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 | 943 |
944 // Choose the seeking stream based on whether it contains the seek time, if no | 944 // Choose the seeking stream based on whether it contains the seek time, if no |
945 // match can be found prefer the preferred stream. | 945 // match can be found prefer the preferred stream. |
946 // | 946 // |
947 // TODO(dalecurtis): Currently FFmpeg does not ensure that all streams in a | 947 // TODO(dalecurtis): Currently FFmpeg does not ensure that all streams in a |
948 // given container will demux all packets after the seek point. Instead it | 948 // given container will demux all packets after the seek point. Instead it |
949 // only guarantees that all packets after the file position of the seek will | 949 // only guarantees that all packets after the file position of the seek will |
950 // be demuxed. It's an open question whether FFmpeg should fix this: | 950 // be demuxed. It's an open question whether FFmpeg should fix this: |
951 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html | 951 // http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2014-June/159212.html |
952 // Tracked by http://crbug.com/387996. | 952 // Tracked by http://crbug.com/387996. |
953 DCHECK(preferred_stream_for_seeking_.second != kNoTimestamp()); | 953 DCHECK(preferred_stream_for_seeking_.second != kNoTimestamp); |
954 const int stream_index = | 954 const int stream_index = |
955 seek_time < preferred_stream_for_seeking_.second && | 955 seek_time < preferred_stream_for_seeking_.second && |
956 seek_time >= fallback_stream_for_seeking_.second | 956 seek_time >= fallback_stream_for_seeking_.second |
957 ? fallback_stream_for_seeking_.first | 957 ? fallback_stream_for_seeking_.first |
958 : preferred_stream_for_seeking_.first; | 958 : preferred_stream_for_seeking_.first; |
959 DCHECK_NE(stream_index, -1); | 959 DCHECK_NE(stream_index, -1); |
960 | 960 |
961 const AVStream* seeking_stream = | 961 const AVStream* seeking_stream = |
962 glue_->format_context()->streams[stream_index]; | 962 glue_->format_context()->streams[stream_index]; |
963 | 963 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1071 int bitrate = 0; | 1071 int bitrate = 0; |
1072 for (size_t i = 0; i < format_context->nb_streams; ++i) { | 1072 for (size_t i = 0; i < format_context->nb_streams; ++i) { |
1073 AVCodecContext* codec_context = format_context->streams[i]->codec; | 1073 AVCodecContext* codec_context = format_context->streams[i]->codec; |
1074 bitrate += codec_context->bit_rate; | 1074 bitrate += codec_context->bit_rate; |
1075 } | 1075 } |
1076 if (bitrate > 0) | 1076 if (bitrate > 0) |
1077 return bitrate; | 1077 return bitrate; |
1078 | 1078 |
1079 // See if we can approximate the bitrate as long as we have a filesize and | 1079 // See if we can approximate the bitrate as long as we have a filesize and |
1080 // valid duration. | 1080 // valid duration. |
1081 if (duration.InMicroseconds() <= 0 || | 1081 if (duration.InMicroseconds() <= 0 || duration == kInfiniteDuration || |
1082 duration == kInfiniteDuration() || | |
1083 filesize_in_bytes == 0) { | 1082 filesize_in_bytes == 0) { |
1084 return 0; | 1083 return 0; |
1085 } | 1084 } |
1086 | 1085 |
1087 // Do math in floating point as we'd overflow an int64_t if the filesize was | 1086 // Do math in floating point as we'd overflow an int64_t if the filesize was |
1088 // larger than ~1073GB. | 1087 // larger than ~1073GB. |
1089 double bytes = filesize_in_bytes; | 1088 double bytes = filesize_in_bytes; |
1090 double duration_us = duration.InMicroseconds(); | 1089 double duration_us = duration.InMicroseconds(); |
1091 return bytes * 8000000.0 / duration_us; | 1090 return bytes * 8000000.0 / duration_us; |
1092 } | 1091 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 AVFormatContext* format_context = glue_->format_context(); | 1140 AVFormatContext* format_context = glue_->format_context(); |
1142 streams_.resize(format_context->nb_streams); | 1141 streams_.resize(format_context->nb_streams); |
1143 | 1142 |
1144 // Estimate the start time for each stream by looking through the packets | 1143 // Estimate the start time for each stream by looking through the packets |
1145 // buffered during avformat_find_stream_info(). These values will be | 1144 // buffered during avformat_find_stream_info(). These values will be |
1146 // considered later when determining the actual stream start time. | 1145 // considered later when determining the actual stream start time. |
1147 // | 1146 // |
1148 // These packets haven't been completely processed yet, so only look through | 1147 // These packets haven't been completely processed yet, so only look through |
1149 // these values if the AVFormatContext has a valid start time. | 1148 // these values if the AVFormatContext has a valid start time. |
1150 // | 1149 // |
1151 // If no estimate is found, the stream entry will be kInfiniteDuration(). | 1150 // If no estimate is found, the stream entry will be kInfiniteDuration. |
1152 std::vector<base::TimeDelta> start_time_estimates(format_context->nb_streams, | 1151 std::vector<base::TimeDelta> start_time_estimates(format_context->nb_streams, |
1153 kInfiniteDuration()); | 1152 kInfiniteDuration); |
1154 const AVFormatInternal* internal = format_context->internal; | 1153 const AVFormatInternal* internal = format_context->internal; |
1155 if (internal && internal->packet_buffer && | 1154 if (internal && internal->packet_buffer && |
1156 format_context->start_time != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 1155 format_context->start_time != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
1157 struct AVPacketList* packet_buffer = internal->packet_buffer; | 1156 struct AVPacketList* packet_buffer = internal->packet_buffer; |
1158 while (packet_buffer != internal->packet_buffer_end) { | 1157 while (packet_buffer != internal->packet_buffer_end) { |
1159 DCHECK_LT(static_cast<size_t>(packet_buffer->pkt.stream_index), | 1158 DCHECK_LT(static_cast<size_t>(packet_buffer->pkt.stream_index), |
1160 start_time_estimates.size()); | 1159 start_time_estimates.size()); |
1161 const AVStream* stream = | 1160 const AVStream* stream = |
1162 format_context->streams[packet_buffer->pkt.stream_index]; | 1161 format_context->streams[packet_buffer->pkt.stream_index]; |
1163 if (packet_buffer->pkt.pts != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 1162 if (packet_buffer->pkt.pts != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
1164 const base::TimeDelta packet_pts = | 1163 const base::TimeDelta packet_pts = |
1165 ConvertFromTimeBase(stream->time_base, packet_buffer->pkt.pts); | 1164 ConvertFromTimeBase(stream->time_base, packet_buffer->pkt.pts); |
1166 if (packet_pts < start_time_estimates[stream->index]) | 1165 if (packet_pts < start_time_estimates[stream->index]) |
1167 start_time_estimates[stream->index] = packet_pts; | 1166 start_time_estimates[stream->index] = packet_pts; |
1168 } | 1167 } |
1169 packet_buffer = packet_buffer->next; | 1168 packet_buffer = packet_buffer->next; |
1170 } | 1169 } |
1171 } | 1170 } |
1172 | 1171 |
1173 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks()); | 1172 std::unique_ptr<MediaTracks> media_tracks(new MediaTracks()); |
1174 AVStream* audio_stream = NULL; | 1173 AVStream* audio_stream = NULL; |
1175 AudioDecoderConfig audio_config; | 1174 AudioDecoderConfig audio_config; |
1176 AVStream* video_stream = NULL; | 1175 AVStream* video_stream = NULL; |
1177 VideoDecoderConfig video_config; | 1176 VideoDecoderConfig video_config; |
1178 | 1177 |
1179 DCHECK(track_id_to_demux_stream_map_.empty()); | 1178 DCHECK(track_id_to_demux_stream_map_.empty()); |
1180 | 1179 |
1181 // If available, |start_time_| will be set to the lowest stream start time. | 1180 // If available, |start_time_| will be set to the lowest stream start time. |
1182 start_time_ = kInfiniteDuration(); | 1181 start_time_ = kInfiniteDuration; |
1183 | 1182 |
1184 base::TimeDelta max_duration; | 1183 base::TimeDelta max_duration; |
1185 int detected_audio_track_count = 0; | 1184 int detected_audio_track_count = 0; |
1186 int detected_video_track_count = 0; | 1185 int detected_video_track_count = 0; |
1187 int detected_text_track_count = 0; | 1186 int detected_text_track_count = 0; |
1188 for (size_t i = 0; i < format_context->nb_streams; ++i) { | 1187 for (size_t i = 0; i < format_context->nb_streams; ++i) { |
1189 AVStream* stream = format_context->streams[i]; | 1188 AVStream* stream = format_context->streams[i]; |
1190 const AVCodecContext* codec_context = stream->codec; | 1189 const AVCodecContext* codec_context = stream->codec; |
1191 const AVMediaType codec_type = codec_context->codec_type; | 1190 const AVMediaType codec_type = codec_context->codec_type; |
1192 | 1191 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1309 media_track->set_id(base::UintToString(track_id)); | 1308 media_track->set_id(base::UintToString(track_id)); |
1310 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == | 1309 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == |
1311 track_id_to_demux_stream_map_.end()); | 1310 track_id_to_demux_stream_map_.end()); |
1312 track_id_to_demux_stream_map_[media_track->id()] = streams_[i]; | 1311 track_id_to_demux_stream_map_[media_track->id()] = streams_[i]; |
1313 } | 1312 } |
1314 | 1313 |
1315 max_duration = std::max(max_duration, streams_[i]->duration()); | 1314 max_duration = std::max(max_duration, streams_[i]->duration()); |
1316 | 1315 |
1317 const base::TimeDelta start_time = | 1316 const base::TimeDelta start_time = |
1318 ExtractStartTime(stream, start_time_estimates[i]); | 1317 ExtractStartTime(stream, start_time_estimates[i]); |
1319 const bool has_start_time = start_time != kNoTimestamp(); | 1318 const bool has_start_time = start_time != kNoTimestamp; |
1320 | 1319 |
1321 // Always prefer the video stream for seeking. If none exists, we'll swap | 1320 // Always prefer the video stream for seeking. If none exists, we'll swap |
1322 // the fallback stream with the preferred stream below. | 1321 // the fallback stream with the preferred stream below. |
1323 if (codec_type == AVMEDIA_TYPE_VIDEO) { | 1322 if (codec_type == AVMEDIA_TYPE_VIDEO) { |
1324 preferred_stream_for_seeking_ = | 1323 preferred_stream_for_seeking_ = |
1325 StreamSeekInfo(i, has_start_time ? start_time : base::TimeDelta()); | 1324 StreamSeekInfo(i, has_start_time ? start_time : base::TimeDelta()); |
1326 } | 1325 } |
1327 | 1326 |
1328 if (!has_start_time) | 1327 if (!has_start_time) |
1329 continue; | 1328 continue; |
(...skipping 23 matching lines...) Expand all Loading... |
1353 | 1352 |
1354 if (format_context->duration != static_cast<int64_t>(AV_NOPTS_VALUE)) { | 1353 if (format_context->duration != static_cast<int64_t>(AV_NOPTS_VALUE)) { |
1355 // If there is a duration value in the container use that to find the | 1354 // If there is a duration value in the container use that to find the |
1356 // maximum between it and the duration from A/V streams. | 1355 // maximum between it and the duration from A/V streams. |
1357 const AVRational av_time_base = {1, AV_TIME_BASE}; | 1356 const AVRational av_time_base = {1, AV_TIME_BASE}; |
1358 max_duration = | 1357 max_duration = |
1359 std::max(max_duration, | 1358 std::max(max_duration, |
1360 ConvertFromTimeBase(av_time_base, format_context->duration)); | 1359 ConvertFromTimeBase(av_time_base, format_context->duration)); |
1361 } else { | 1360 } else { |
1362 // The duration is unknown, in which case this is likely a live stream. | 1361 // The duration is unknown, in which case this is likely a live stream. |
1363 max_duration = kInfiniteDuration(); | 1362 max_duration = kInfiniteDuration; |
1364 } | 1363 } |
1365 | 1364 |
1366 // FFmpeg represents audio data marked as before the beginning of stream as | 1365 // FFmpeg represents audio data marked as before the beginning of stream as |
1367 // having negative timestamps. This data must be discarded after it has been | 1366 // having negative timestamps. This data must be discarded after it has been |
1368 // decoded, not before since it is used to warmup the decoder. There are | 1367 // decoded, not before since it is used to warmup the decoder. There are |
1369 // currently two known cases for this: vorbis in ogg and opus in ogg and webm. | 1368 // currently two known cases for this: vorbis in ogg and opus in ogg and webm. |
1370 // | 1369 // |
1371 // For API clarity, it was decided that the rest of the media pipeline should | 1370 // For API clarity, it was decided that the rest of the media pipeline should |
1372 // not be exposed to negative timestamps. Which means we need to rebase these | 1371 // not be exposed to negative timestamps. Which means we need to rebase these |
1373 // negative timestamps and mark them for discard post decoding. | 1372 // negative timestamps and mark them for discard post decoding. |
(...skipping 17 matching lines...) Expand all Loading... |
1391 // because it has a lower starting time. | 1390 // because it has a lower starting time. |
1392 if (fallback_stream_for_seeking_.first == audio_stream->index && | 1391 if (fallback_stream_for_seeking_.first == audio_stream->index && |
1393 fallback_stream_for_seeking_.second < base::TimeDelta()) { | 1392 fallback_stream_for_seeking_.second < base::TimeDelta()) { |
1394 fallback_stream_for_seeking_.second = base::TimeDelta(); | 1393 fallback_stream_for_seeking_.second = base::TimeDelta(); |
1395 } | 1394 } |
1396 } | 1395 } |
1397 | 1396 |
1398 // If no start time could be determined, default to zero and prefer the video | 1397 // If no start time could be determined, default to zero and prefer the video |
1399 // stream over the audio stream for seeking. E.g., The WAV demuxer does not | 1398 // stream over the audio stream for seeking. E.g., The WAV demuxer does not |
1400 // put timestamps on its frames. | 1399 // put timestamps on its frames. |
1401 if (start_time_ == kInfiniteDuration()) { | 1400 if (start_time_ == kInfiniteDuration) { |
1402 start_time_ = base::TimeDelta(); | 1401 start_time_ = base::TimeDelta(); |
1403 preferred_stream_for_seeking_ = StreamSeekInfo( | 1402 preferred_stream_for_seeking_ = StreamSeekInfo( |
1404 video_stream ? video_stream->index : audio_stream->index, start_time_); | 1403 video_stream ? video_stream->index : audio_stream->index, start_time_); |
1405 } else if (!video_stream) { | 1404 } else if (!video_stream) { |
1406 // If no video stream exists, use the audio or text stream found above. | 1405 // If no video stream exists, use the audio or text stream found above. |
1407 preferred_stream_for_seeking_ = fallback_stream_for_seeking_; | 1406 preferred_stream_for_seeking_ = fallback_stream_for_seeking_; |
1408 } | 1407 } |
1409 | 1408 |
1410 // MPEG-4 B-frames cause grief for a simple container like AVI. Enable PTS | 1409 // MPEG-4 B-frames cause grief for a simple container like AVI. Enable PTS |
1411 // generation so we always get timestamps, see http://crbug.com/169570 | 1410 // generation so we always get timestamps, see http://crbug.com/169570 |
1412 if (strcmp(format_context->iformat->name, "avi") == 0) | 1411 if (strcmp(format_context->iformat->name, "avi") == 0) |
1413 format_context->flags |= AVFMT_FLAG_GENPTS; | 1412 format_context->flags |= AVFMT_FLAG_GENPTS; |
1414 | 1413 |
1415 // For testing purposes, don't overwrite the timeline offset if set already. | 1414 // For testing purposes, don't overwrite the timeline offset if set already. |
1416 if (timeline_offset_.is_null()) | 1415 if (timeline_offset_.is_null()) |
1417 timeline_offset_ = ExtractTimelineOffset(format_context); | 1416 timeline_offset_ = ExtractTimelineOffset(format_context); |
1418 | 1417 |
1419 // Since we're shifting the externally visible start time to zero, we need to | 1418 // Since we're shifting the externally visible start time to zero, we need to |
1420 // adjust the timeline offset to compensate. | 1419 // adjust the timeline offset to compensate. |
1421 if (!timeline_offset_.is_null() && start_time_ < base::TimeDelta()) | 1420 if (!timeline_offset_.is_null() && start_time_ < base::TimeDelta()) |
1422 timeline_offset_ += start_time_; | 1421 timeline_offset_ += start_time_; |
1423 | 1422 |
1424 if (max_duration == kInfiniteDuration() && !timeline_offset_.is_null()) { | 1423 if (max_duration == kInfiniteDuration && !timeline_offset_.is_null()) { |
1425 SetLiveness(DemuxerStream::LIVENESS_LIVE); | 1424 SetLiveness(DemuxerStream::LIVENESS_LIVE); |
1426 } else if (max_duration != kInfiniteDuration()) { | 1425 } else if (max_duration != kInfiniteDuration) { |
1427 SetLiveness(DemuxerStream::LIVENESS_RECORDED); | 1426 SetLiveness(DemuxerStream::LIVENESS_RECORDED); |
1428 } else { | 1427 } else { |
1429 SetLiveness(DemuxerStream::LIVENESS_UNKNOWN); | 1428 SetLiveness(DemuxerStream::LIVENESS_UNKNOWN); |
1430 } | 1429 } |
1431 | 1430 |
1432 // Good to go: set the duration and bitrate and notify we're done | 1431 // Good to go: set the duration and bitrate and notify we're done |
1433 // initializing. | 1432 // initializing. |
1434 host_->SetDuration(max_duration); | 1433 host_->SetDuration(max_duration); |
1435 duration_known_ = (max_duration != kInfiniteDuration()); | 1434 duration_known_ = (max_duration != kInfiniteDuration); |
1436 | 1435 |
1437 int64_t filesize_in_bytes = 0; | 1436 int64_t filesize_in_bytes = 0; |
1438 url_protocol_->GetSize(&filesize_in_bytes); | 1437 url_protocol_->GetSize(&filesize_in_bytes); |
1439 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); | 1438 bitrate_ = CalculateBitrate(format_context, max_duration, filesize_in_bytes); |
1440 if (bitrate_ > 0) | 1439 if (bitrate_ > 0) |
1441 data_source_->SetBitrate(bitrate_); | 1440 data_source_->SetBitrate(bitrate_); |
1442 | 1441 |
1443 // Use a single MediaLogEvent to batch all parameter updates at once; this | 1442 // Use a single MediaLogEvent to batch all parameter updates at once; this |
1444 // prevents throttling of events due to the large number of updates here. | 1443 // prevents throttling of events due to the large number of updates here. |
1445 std::unique_ptr<MediaLogEvent> metadata_event = | 1444 std::unique_ptr<MediaLogEvent> metadata_event = |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1599 if (!duration_known_) { | 1598 if (!duration_known_) { |
1600 base::TimeDelta max_duration; | 1599 base::TimeDelta max_duration; |
1601 | 1600 |
1602 for (StreamVector::iterator iter = streams_.begin(); | 1601 for (StreamVector::iterator iter = streams_.begin(); |
1603 iter != streams_.end(); | 1602 iter != streams_.end(); |
1604 ++iter) { | 1603 ++iter) { |
1605 if (!*iter) | 1604 if (!*iter) |
1606 continue; | 1605 continue; |
1607 | 1606 |
1608 base::TimeDelta duration = (*iter)->GetElapsedTime(); | 1607 base::TimeDelta duration = (*iter)->GetElapsedTime(); |
1609 if (duration != kNoTimestamp() && duration > max_duration) | 1608 if (duration != kNoTimestamp && duration > max_duration) |
1610 max_duration = duration; | 1609 max_duration = duration; |
1611 } | 1610 } |
1612 | 1611 |
1613 if (max_duration > base::TimeDelta()) { | 1612 if (max_duration > base::TimeDelta()) { |
1614 host_->SetDuration(max_duration); | 1613 host_->SetDuration(max_duration); |
1615 duration_known_ = true; | 1614 duration_known_ = true; |
1616 } | 1615 } |
1617 } | 1616 } |
1618 // If we have reached the end of stream, tell the downstream filters about | 1617 // If we have reached the end of stream, tell the downstream filters about |
1619 // the event. | 1618 // the event. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1697 | 1696 |
1698 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { | 1697 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { |
1699 DCHECK(task_runner_->BelongsToCurrentThread()); | 1698 DCHECK(task_runner_->BelongsToCurrentThread()); |
1700 for (auto* stream : streams_) { | 1699 for (auto* stream : streams_) { |
1701 if (stream) | 1700 if (stream) |
1702 stream->SetLiveness(liveness); | 1701 stream->SetLiveness(liveness); |
1703 } | 1702 } |
1704 } | 1703 } |
1705 | 1704 |
1706 } // namespace media | 1705 } // namespace media |
OLD | NEW |