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