Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: media/filters/ffmpeg_demuxer.cc

Issue 2549263002: FFmpegDemuxer should fall back to disabled streams for seeking (Closed)
Patch Set: Set start time to 0 for streams with unknown start time Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/filters/ffmpeg_demuxer.h" 5 #include "media/filters/ffmpeg_demuxer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <memory> 8 #include <memory>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 67
68 static base::TimeDelta FramesToTimeDelta(int frames, double sample_rate) { 68 static base::TimeDelta FramesToTimeDelta(int frames, double sample_rate) {
69 return base::TimeDelta::FromMicroseconds( 69 return base::TimeDelta::FromMicroseconds(
70 frames * base::Time::kMicrosecondsPerSecond / sample_rate); 70 frames * base::Time::kMicrosecondsPerSecond / sample_rate);
71 } 71 }
72 72
73 static base::TimeDelta ExtractStartTime(AVStream* stream, 73 static base::TimeDelta ExtractStartTime(AVStream* stream,
74 base::TimeDelta start_time_estimate) { 74 base::TimeDelta start_time_estimate) {
75 DCHECK(start_time_estimate != kNoTimestamp); 75 DCHECK(start_time_estimate != kNoTimestamp);
76 if (stream->start_time == static_cast<int64_t>(AV_NOPTS_VALUE)) { 76 if (stream->start_time == static_cast<int64_t>(AV_NOPTS_VALUE)) {
77 return start_time_estimate == kInfiniteDuration ? kNoTimestamp 77 return start_time_estimate == kInfiniteDuration ? base::TimeDelta()
78 : start_time_estimate; 78 : start_time_estimate;
79 } 79 }
80 80
81 // First try the lower of the estimate and the |start_time| value. 81 // First try the lower of the estimate and the |start_time| value.
82 base::TimeDelta start_time = 82 base::TimeDelta start_time =
83 std::min(ConvertFromTimeBase(stream->time_base, stream->start_time), 83 std::min(ConvertFromTimeBase(stream->time_base, stream->start_time),
84 start_time_estimate); 84 start_time_estimate);
85 85
86 // Next see if the first buffered pts value is usable. 86 // Next see if the first buffered pts value is usable.
87 if (stream->pts_buffer[0] != static_cast<int64_t>(AV_NOPTS_VALUE)) { 87 if (stream->pts_buffer[0] != static_cast<int64_t>(AV_NOPTS_VALUE)) {
(...skipping 1244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 media_track->set_id(base::UintToString(track_id)); 1332 media_track->set_id(base::UintToString(track_id));
1333 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) == 1333 DCHECK(track_id_to_demux_stream_map_.find(media_track->id()) ==
1334 track_id_to_demux_stream_map_.end()); 1334 track_id_to_demux_stream_map_.end());
1335 track_id_to_demux_stream_map_[media_track->id()] = streams_[i].get(); 1335 track_id_to_demux_stream_map_[media_track->id()] = streams_[i].get();
1336 } 1336 }
1337 1337
1338 max_duration = std::max(max_duration, streams_[i]->duration()); 1338 max_duration = std::max(max_duration, streams_[i]->duration());
1339 1339
1340 const base::TimeDelta start_time = 1340 const base::TimeDelta start_time =
1341 ExtractStartTime(stream, start_time_estimates[i]); 1341 ExtractStartTime(stream, start_time_estimates[i]);
1342 const bool has_start_time = start_time != kNoTimestamp;
1343
1344 if (!has_start_time)
1345 continue;
1346
1347 streams_[i]->set_start_time(start_time); 1342 streams_[i]->set_start_time(start_time);
1348 if (start_time < start_time_) { 1343 if (start_time < start_time_) {
1349 start_time_ = start_time; 1344 start_time_ = start_time;
1350 } 1345 }
1351 } 1346 }
1352 1347
1353 RecordDetectedTrackTypeStats(detected_audio_track_count, 1348 RecordDetectedTrackTypeStats(detected_audio_track_count,
1354 detected_video_track_count, 1349 detected_video_track_count,
1355 detected_text_track_count); 1350 detected_text_track_count);
1356 1351
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 } 1511 }
1517 } 1512 }
1518 params.SetBoolean("found_audio_stream", (audio_track_count > 0)); 1513 params.SetBoolean("found_audio_stream", (audio_track_count > 0));
1519 params.SetBoolean("found_video_stream", (video_track_count > 0)); 1514 params.SetBoolean("found_video_stream", (video_track_count > 0));
1520 SetTimeProperty(metadata_event.get(), "max_duration", max_duration); 1515 SetTimeProperty(metadata_event.get(), "max_duration", max_duration);
1521 SetTimeProperty(metadata_event.get(), "start_time", start_time_); 1516 SetTimeProperty(metadata_event.get(), "start_time", start_time_);
1522 metadata_event->params.SetInteger("bitrate", bitrate_); 1517 metadata_event->params.SetInteger("bitrate", bitrate_);
1523 media_log_->AddEvent(std::move(metadata_event)); 1518 media_log_->AddEvent(std::move(metadata_event));
1524 } 1519 }
1525 1520
1521 FFmpegDemuxerStream* FFmpegDemuxer::FindStreamWithLowestStartTimestamp(
1522 bool enabled) {
1523 FFmpegDemuxerStream* lowest_start_time_stream = nullptr;
1524 for (const auto& stream : streams_) {
1525 if (!stream || stream->enabled() != enabled)
1526 continue;
1527 if (!lowest_start_time_stream ||
1528 stream->start_time() < lowest_start_time_stream->start_time()) {
1529 lowest_start_time_stream = stream.get();
1530 }
1531 }
1532 return lowest_start_time_stream;
1533 }
1534
1526 FFmpegDemuxerStream* FFmpegDemuxer::FindPreferredStreamForSeeking( 1535 FFmpegDemuxerStream* FFmpegDemuxer::FindPreferredStreamForSeeking(
1527 base::TimeDelta seek_time) { 1536 base::TimeDelta seek_time) {
1528 // If we have a selected/enabled video stream and its start time is lower 1537 // If we have a selected/enabled video stream and its start time is lower
1529 // than the |seek_time| or unknown, then always prefer it for seeking. 1538 // than the |seek_time| or unknown, then always prefer it for seeking.
1530 FFmpegDemuxerStream* video_stream = nullptr; 1539 FFmpegDemuxerStream* video_stream = nullptr;
1531 for (const auto& stream : streams_) { 1540 for (const auto& stream : streams_) {
1532 if (stream && stream->type() == DemuxerStream::VIDEO && stream->enabled()) { 1541 if (stream && stream->type() == DemuxerStream::VIDEO && stream->enabled()) {
1533 video_stream = stream.get(); 1542 video_stream = stream.get();
1534 if (video_stream->start_time() == kNoTimestamp || 1543 if (video_stream->start_time() <= seek_time) {
1535 video_stream->start_time() <= seek_time) {
1536 return video_stream; 1544 return video_stream;
1537 } 1545 }
1538 break; 1546 break;
1539 } 1547 }
1540 } 1548 }
1541 1549
1542 // If video stream is not present or |seek_time| is lower than the video start 1550 // If video stream is not present or |seek_time| is lower than the video start
1543 // time, then try to find an enabled stream with the lowest start time. 1551 // time, then try to find an enabled stream with the lowest start time.
1544 FFmpegDemuxerStream* lowest_start_time_stream = nullptr; 1552 FFmpegDemuxerStream* lowest_start_time_enabled_stream =
1545 for (const auto& stream : streams_) { 1553 FindStreamWithLowestStartTimestamp(true);
1546 if (!stream || !stream->enabled() || stream->start_time() == kNoTimestamp) 1554 if (lowest_start_time_enabled_stream &&
1547 continue; 1555 lowest_start_time_enabled_stream->start_time() <= seek_time) {
1548 if (!lowest_start_time_stream || 1556 return lowest_start_time_enabled_stream;
1549 stream->start_time() < lowest_start_time_stream->start_time()) {
1550 lowest_start_time_stream = stream.get();
1551 }
1552 }
1553 // If we found a stream with start time lower than |seek_time|, then use it.
1554 if (lowest_start_time_stream &&
1555 lowest_start_time_stream->start_time() <= seek_time) {
1556 return lowest_start_time_stream;
1557 } 1557 }
1558 1558
1559 // If we couldn't find any streams with the start time lower than |seek_time| 1559 // If there's no enabled streams to consider from, try a disabled stream with
1560 // then use either video (if one exists) or any audio stream. 1560 // the lowest known start time.
1561 return video_stream ? video_stream : static_cast<FFmpegDemuxerStream*>( 1561 FFmpegDemuxerStream* lowest_start_time_disabled_stream =
1562 GetStream(DemuxerStream::AUDIO)); 1562 FindStreamWithLowestStartTimestamp(false);
1563 if (lowest_start_time_disabled_stream &&
1564 lowest_start_time_disabled_stream->start_time() <= seek_time) {
1565 return lowest_start_time_disabled_stream;
1566 }
1567
1568 // Otherwise fall back to any other stream.
1569 for (const auto& stream : streams_) {
1570 if (stream)
1571 return stream.get();
1572 }
1573
1574 NOTREACHED();
1575 return nullptr;
1563 } 1576 }
1564 1577
1565 void FFmpegDemuxer::OnSeekFrameDone(int result) { 1578 void FFmpegDemuxer::OnSeekFrameDone(int result) {
1566 DCHECK(task_runner_->BelongsToCurrentThread()); 1579 DCHECK(task_runner_->BelongsToCurrentThread());
1567 CHECK(!pending_seek_cb_.is_null()); 1580 CHECK(!pending_seek_cb_.is_null());
1568 1581
1569 if (!blocking_thread_.IsRunning()) { 1582 if (!blocking_thread_.IsRunning()) {
1570 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state"; 1583 MEDIA_LOG(ERROR, media_log_) << GetDisplayName() << ": bad state";
1571 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT); 1584 base::ResetAndReturn(&pending_seek_cb_).Run(PIPELINE_ERROR_ABORT);
1572 return; 1585 return;
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1783 1796
1784 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) { 1797 void FFmpegDemuxer::SetLiveness(DemuxerStream::Liveness liveness) {
1785 DCHECK(task_runner_->BelongsToCurrentThread()); 1798 DCHECK(task_runner_->BelongsToCurrentThread());
1786 for (const auto& stream : streams_) { 1799 for (const auto& stream : streams_) {
1787 if (stream) 1800 if (stream)
1788 stream->SetLiveness(liveness); 1801 stream->SetLiveness(liveness);
1789 } 1802 }
1790 } 1803 }
1791 1804
1792 } // namespace media 1805 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698