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/webm/webm_info_parser.h"
6 
7 #include "base/logging.h"
8 #include "media/formats/webm/webm_constants.h"
9 
10 namespace media {
11 
12 // Default timecode scale, in nanoseconds, if the TimecodeScale element is not
13 // specified in the INFO element.
14 static const int kWebMDefaultTimecodeScale = 1000000;
15 
WebMInfoParser()16 WebMInfoParser::WebMInfoParser() : timecode_scale_ns_(-1), duration_(-1) {}
17 
18 WebMInfoParser::~WebMInfoParser() = default;
19 
Parse(const uint8_t * buf,int size)20 int WebMInfoParser::Parse(const uint8_t* buf, int size) {
21   timecode_scale_ns_ = -1;
22   duration_ = -1;
23 
24   WebMListParser parser(kWebMIdInfo, this);
25   int result = parser.Parse(buf, size);
26 
27   if (result <= 0)
28     return result;
29 
30   // For now we do all or nothing parsing.
31   return parser.IsParsingComplete() ? result : 0;
32 }
33 
OnListStart(int id)34 WebMParserClient* WebMInfoParser::OnListStart(int id) { return this; }
35 
OnListEnd(int id)36 bool WebMInfoParser::OnListEnd(int id) {
37   if (id == kWebMIdInfo && timecode_scale_ns_ == -1) {
38     // Set timecode scale to default value if it isn't present in
39     // the Info element.
40     timecode_scale_ns_ = kWebMDefaultTimecodeScale;
41   }
42   return true;
43 }
44 
OnUInt(int id,int64_t val)45 bool WebMInfoParser::OnUInt(int id, int64_t val) {
46   if (id != kWebMIdTimecodeScale)
47     return true;
48 
49   if (val <= 0) {
50     DVLOG(1) << "TimeCodeScale of " << val << " is invalid. Must be > 0.";
51     return false;
52   }
53 
54   if (timecode_scale_ns_ != -1) {
55     DVLOG(1) << "Multiple values for id " << std::hex << id << " specified";
56     return false;
57   }
58 
59   timecode_scale_ns_ = val;
60   return true;
61 }
62 
OnFloat(int id,double val)63 bool WebMInfoParser::OnFloat(int id, double val) {
64   if (id != kWebMIdDuration) {
65     DVLOG(1) << "Unexpected float for id" << std::hex << id;
66     return false;
67   }
68 
69   if (duration_ != -1) {
70     DVLOG(1) << "Multiple values for duration.";
71     return false;
72   }
73 
74   duration_ = val;
75   return true;
76 }
77 
OnBinary(int id,const uint8_t * data,int size)78 bool WebMInfoParser::OnBinary(int id, const uint8_t* data, int size) {
79   if (id == kWebMIdDateUTC) {
80     if (size != 8)
81       return false;
82 
83     int64_t date_in_nanoseconds = 0;
84     for (int i = 0; i < size; ++i)
85       date_in_nanoseconds = (date_in_nanoseconds << 8) | data[i];
86 
87     base::Time::Exploded exploded_epoch;
88     exploded_epoch.year = 2001;
89     exploded_epoch.month = 1;
90     exploded_epoch.day_of_month = 1;
91     exploded_epoch.day_of_week = 1;
92     exploded_epoch.hour = 0;
93     exploded_epoch.minute = 0;
94     exploded_epoch.second = 0;
95     exploded_epoch.millisecond = 0;
96     base::Time out_time;
97     if (!base::Time::FromUTCExploded(exploded_epoch, &out_time))
98       return false;
99     date_utc_ = out_time +
100                 base::TimeDelta::FromMicroseconds(date_in_nanoseconds / 1000);
101   }
102   return true;
103 }
104 
OnString(int id,const std::string & str)105 bool WebMInfoParser::OnString(int id, const std::string& str) {
106   return true;
107 }
108 
109 }  // namespace media
110