Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / formats / mp2t / timestamp_unroller.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/formats/mp2t/timestamp_unroller.h"
6
7 #include "base/logging.h"
8
9 namespace media {
10 namespace mp2t {
11
12 TimestampUnroller::TimestampUnroller()
13     : is_previous_timestamp_valid_(false),
14       previous_unrolled_timestamp_(0) {
15 }
16
17 TimestampUnroller::~TimestampUnroller() {
18 }
19
20 int64 TimestampUnroller::GetUnrolledTimestamp(int64 timestamp) {
21   // Mpeg2 TS timestamps have an accuracy of 33 bits.
22   const int nbits = 33;
23
24   // |timestamp| has a precision of |nbits|
25   // so make sure the highest bits are set to 0.
26   DCHECK_EQ((timestamp >> nbits), 0);
27
28   if (!is_previous_timestamp_valid_) {
29     previous_unrolled_timestamp_ = timestamp;
30     is_previous_timestamp_valid_ = true;
31     return timestamp;
32   }
33
34   // |timestamp| is known modulo 2^33, so estimate the highest bits
35   // to minimize the discontinuity with the previous unrolled timestamp.
36   // Three possibilities are considered to estimate the missing high bits
37   // of |timestamp|. If the bits of the previous unrolled timestamp are
38   // {b63, b62, ..., b0} and bits of |timestamp| are {0, ..., 0, a32, ..., a0}
39   // then the 3 possibilities are:
40   // 1) t1 = {b63, ..., b33, a32, ..., a0} (apply the same offset multiple
41   //    of 2^33 as the one used for the previous timestamp)
42   // 2) t0 = t1 - 2^33
43   // 3) t2 = t1 + 2^33
44   //
45   // A few remarks:
46   // - the purpose of the timestamp unroller is only to unroll timestamps
47   // in such a way timestamp continuity is satisfied. It can generate negative
48   // values during that process.
49   // - possible overflows are not considered here since 64 bits on a 90kHz
50   // timescale is way enough to represent several years of playback.
51   int64 previous_unrolled_time_high =
52       (previous_unrolled_timestamp_ >> nbits);
53   int64 time0 = ((previous_unrolled_time_high - 1) << nbits) | timestamp;
54   int64 time1 = ((previous_unrolled_time_high + 0) << nbits) | timestamp;
55   int64 time2 = ((previous_unrolled_time_high + 1) << nbits) | timestamp;
56
57   // Select the min absolute difference with the current time
58   // so as to ensure time continuity.
59   int64 diff0 = time0 - previous_unrolled_timestamp_;
60   int64 diff1 = time1 - previous_unrolled_timestamp_;
61   int64 diff2 = time2 - previous_unrolled_timestamp_;
62   if (diff0 < 0)
63     diff0 = -diff0;
64   if (diff1 < 0)
65     diff1 = -diff1;
66   if (diff2 < 0)
67     diff2 = -diff2;
68
69   int64 unrolled_time;
70   int64 min_diff;
71   if (diff1 < diff0) {
72     unrolled_time = time1;
73     min_diff = diff1;
74   } else {
75     unrolled_time = time0;
76     min_diff = diff0;
77   }
78   if (diff2 < min_diff)
79     unrolled_time = time2;
80
81   // Update the state of the timestamp unroller.
82   previous_unrolled_timestamp_ = unrolled_time;
83
84   return unrolled_time;
85 }
86
87 void TimestampUnroller::Reset() {
88   is_previous_timestamp_valid_ = false;
89   previous_unrolled_timestamp_ = 0;
90 }
91
92 }  // namespace mp2t
93 }  // namespace media