webm_file: Implement HasAccurateClusterDuration()

Iterate through all the Clusters and check if Duration is set on
the last frame of each Cluster (except for the last Cluster which
is ignored).

Change-Id: Ifdbdcb9e1d57afbd995d4377fcd6118e947c1540
diff --git a/shared/webm_file.cc b/shared/webm_file.cc
index a2428cb..7fb8db9 100644
--- a/shared/webm_file.cc
+++ b/shared/webm_file.cc
@@ -693,6 +693,45 @@
   return true;
 }
 
+bool WebMFile::HasAccurateClusterDuration() const {
+  if (state_ <= kParsingHeader)
+    return false;
+
+  const mkvparser::Cluster* cluster = segment_->GetFirst();
+  map<int64, bool> track_has_duration;
+  // Iterate through all the Clusters and check if the last frame in each of
+  // them has Duration set.
+  while (cluster != NULL && !cluster->EOS()) {
+    // This check is done at the beginning of the loop because we don't care
+    // about the last Cluster.
+    for (map<int64, bool>::const_iterator it = track_has_duration.begin();
+         it != track_has_duration.end(); ++it) {
+      if (!it->second)
+        return false;
+    }
+    track_has_duration.clear();
+    const mkvparser::BlockEntry* block_entry;
+    if (cluster->GetFirst(block_entry))
+      return false;
+
+    while (block_entry != NULL && !block_entry->EOS()) {
+      const int64 track_number = block_entry->GetBlock()->GetTrackNumber();
+      if (block_entry->GetKind() == mkvparser::BlockEntry::kBlockGroup) {
+        const mkvparser::BlockGroup* const block_group =
+            reinterpret_cast<const mkvparser::BlockGroup* const>(block_entry);
+        track_has_duration[track_number] =
+            (block_group->GetDurationTimeCode() > 0);
+      } else {
+        track_has_duration[track_number] = false;
+      }
+      if (cluster->GetNext(block_entry, block_entry))
+        return false;
+    }
+    cluster = segment_->GetNext(cluster);
+  }
+  return true;
+}
+
 bool WebMFile::CheckForCues() const {
   if (state_ <= kParsingHeader)
     return false;
diff --git a/shared/webm_file.h b/shared/webm_file.h
index b8b407c..c2689c2 100644
--- a/shared/webm_file.h
+++ b/shared/webm_file.h
@@ -196,6 +196,12 @@
   // output to be valid.
   bool CuesFirstInCluster(TrackTypes type) const;
 
+  // Returns true if the file has accurate cluster duration for all the
+  // Clusters. The last Cluster is not checked. By convention it is still
+  // considered to have accurate cluster duration irrespective of the last
+  // Cluster.
+  bool HasAccurateClusterDuration() const;
+
   // Returns the display width of the first video track. Returns 0 if there
   // is no video track. Parser state must be >= kParsingClusters for output to
   // be valid.