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

Unified Diff: media/formats/webm/webm_cluster_parser.cc

Issue 1018373003: Improving WebM video duration estimation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding limited media log (10 times max) for WebM duration estimates. Created 5 years, 9 months 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 side-by-side diff with in-line comments
Download patch
Index: media/formats/webm/webm_cluster_parser.cc
diff --git a/media/formats/webm/webm_cluster_parser.cc b/media/formats/webm/webm_cluster_parser.cc
index 7dacd7102c7b7f24d3fc6ba27de9df9a4c484504..aed07ef862648c77e234e2c4a855f565deb41a31 100644
--- a/media/formats/webm/webm_cluster_parser.cc
+++ b/media/formats/webm/webm_cluster_parser.cc
@@ -25,7 +25,10 @@ const uint16_t WebMClusterParser::kOpusFrameDurationsMu[] = {
enum {
// Limits the number of MEDIA_LOG() calls in the path of reading encoded
// duration to avoid spamming for corrupted data.
- kMaxDurationLogs = 10,
+ kMaxDurationErrorLogs = 10,
+ // Limits the number of MEDIA_LOG() calls warning the user that a buffer
+ // durations have been estimated.
wolenetz 2015/03/28 00:26:06 nit: regrammarize "a buffer durations have" ;)
chcunningham 2015/04/13 23:25:18 Done.
+ kMaxDurationEstimateLogs = 10,
};
WebMClusterParser::WebMClusterParser(
@@ -185,7 +188,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
base::TimeDelta::FromMilliseconds(120);
if (size < 1) {
- LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
+ LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationErrorLogs)
<< "Invalid zero-byte Opus packet; demuxed block duration may be "
"imprecise.";
return kNoTimestamp();
@@ -206,7 +209,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
case 3:
// Type 3 indicates an arbitrary frame count described in the next byte.
if (size < 2) {
- LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
+ LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationErrorLogs)
<< "Second byte missing from 'Code 3' Opus packet; demuxed block "
"duration may be imprecise.";
return kNoTimestamp();
@@ -215,7 +218,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
frame_count = data[1] & kFrameCountMask;
if (frame_count == 0) {
- LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
+ LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationErrorLogs)
<< "Illegal 'Code 3' Opus packet with frame count zero; demuxed "
"block duration may be imprecise.";
return kNoTimestamp();
@@ -223,7 +226,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
break;
default:
- LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
+ LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationErrorLogs)
<< "Unexpected Opus frame count type: " << frame_count_type << "; "
<< "demuxed block duration may be imprecise.";
return kNoTimestamp();
@@ -241,7 +244,7 @@ base::TimeDelta WebMClusterParser::ReadOpusDuration(const uint8_t* data,
// Intentionally allowing packet to pass through for now. Decoder should
// either handle or fail gracefully. MEDIA_LOG as breadcrumbs in case
// things go sideways.
- LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
+ LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationErrorLogs)
<< "Warning, demuxed Opus packet with encoded duration: " << duration
<< ". Should be no greater than " << kPacketDurationMax;
}
@@ -558,7 +561,7 @@ bool WebMClusterParser::OnBlock(bool is_simple_block,
const auto kWarnDurationDiff =
base::TimeDelta::FromMicroseconds(timecode_multiplier_ * 2);
if (duration_difference.magnitude() > kWarnDurationDiff) {
- LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationLogs)
+ LIMITED_MEDIA_LOG(log_cb_, num_duration_errors_, kMaxDurationErrorLogs)
<< "BlockDuration "
<< "(" << block_duration_time_delta << ") "
<< "differs significantly from encoded duration "
@@ -585,7 +588,8 @@ WebMClusterParser::Track::Track(int track_num,
bool is_video,
base::TimeDelta default_duration,
const LogCB& log_cb)
- : track_num_(track_num),
+ : num_duration_estimates_(0),
+ track_num_(track_num),
is_video_(is_video),
default_duration_(default_duration),
estimated_next_frame_duration_(kNoTimestamp()),
@@ -678,7 +682,17 @@ void WebMClusterParser::Track::ApplyDurationEstimateIfNeeded() {
if (!last_added_buffer_missing_duration_.get())
return;
- last_added_buffer_missing_duration_->set_duration(GetDurationEstimate());
+ base::TimeDelta estimated_duration = GetDurationEstimate();
+ last_added_buffer_missing_duration_->set_duration(estimated_duration);
+
+ // Exposing estimation so splicing/overlap frame processing can make informed
+ // decisions downstream.
+ last_added_buffer_missing_duration_->set_is_duration_estimated(true);
+
+ LIMITED_MEDIA_LOG(log_cb_, num_duration_estimates_, kMaxDurationEstimateLogs)
+ << "Estimating duration to be " << estimated_duration << " for the "
+ << "last (Simple)Block in the Cluster. Use BlockDuration at the end of "
wolenetz 2015/03/28 00:26:06 nit: "in the Cluster for this Track". And "Instead
chcunningham 2015/04/13 23:25:18 Done.
+ << "Clusters to avoid estimation.";
DVLOG(2) << "ApplyDurationEstimateIfNeeded() : new dur : "
<< " ts "
@@ -746,16 +760,35 @@ bool WebMClusterParser::Track::QueueBuffer(
return false;
}
- // The estimated frame duration is the minimum non-zero duration since the
- // last initialization segment. The minimum is used to ensure frame durations
- // aren't overestimated.
+ // The estimated frame duration is the minimum (for audio) or the maximum
+ // (for video) non-zero duration since the last initialization segment. The
+ // minimum is used for audio to ensure frame durations aren't overestimated,
+ // triggering unnecessary frame splicing. For video, splicing does not apply,
+ // so maximum is used and overlap is is simply resolved by showing the
wolenetz 2015/03/28 00:26:06 nit: is is
chcunningham 2015/04/13 23:25:18 Done.
+ // later of the overlapping frames at its given PTS, effectively trimming down
+ // the over-estimated duration of the previous frame.
+ // TODO(chcunningham): Use max for audio and disable splicing whenever
+ // estimated buffers are encountered.
if (duration > base::TimeDelta()) {
+ base::TimeDelta orig_duration_estimate = estimated_next_frame_duration_;
if (estimated_next_frame_duration_ == kNoTimestamp()) {
estimated_next_frame_duration_ = duration;
+ } else if (is_video_) {
+ estimated_next_frame_duration_ =
+ std::max(duration, estimated_next_frame_duration_);
} else {
estimated_next_frame_duration_ =
std::min(duration, estimated_next_frame_duration_);
}
+
+ if (orig_duration_estimate != estimated_next_frame_duration_) {
+ DVLOG(3) << "Updated duration estimate:"
+ << orig_duration_estimate
+ << " -> "
+ << estimated_next_frame_duration_
+ << " at dts: "
wolenetz 2015/03/28 00:26:06 nit: webm doesn't differentiate dts/pts. s/dts/tim
chcunningham 2015/04/13 23:25:18 Done. Re-cleanup: so you'd like a bug to change al
wolenetz 2015/04/15 02:55:23 Thanks. IIRC, WebM container doesn't mention PTS o
+ << buffer->GetDecodeTimestamp().InSecondsF();
+ }
}
buffers_.push_back(buffer);

Powered by Google App Engine
This is Rietveld 408576698