1/*
2 * Copyright (C) 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "ISOVTTCue.h"
28
29#include "Logging.h"
30#include <JavaScriptCore/DataView.h>
31#include <wtf/JSONValues.h>
32#include <wtf/URL.h>
33
34using JSC::DataView;
35
36namespace WebCore {
37
38class ISOStringBox : public ISOBox {
39public:
40 const String& contents() { return m_contents; }
41
42protected:
43 bool parse(JSC::DataView& view, unsigned& offset) override
44 {
45 unsigned localOffset = offset;
46 if (!ISOBox::parse(view, localOffset))
47 return false;
48
49 auto characterCount = m_size - (localOffset - offset);
50 if (!characterCount) {
51 m_contents = emptyString();
52 return true;
53 }
54
55 Vector<LChar> characters;
56 characters.reserveInitialCapacity(static_cast<size_t>(characterCount));
57 while (characterCount--) {
58 int8_t character = 0;
59 if (!checkedRead<int8_t>(character, view, localOffset, BigEndian))
60 return false;
61 characters.uncheckedAppend(character);
62 }
63
64 m_contents = String::fromUTF8(characters);
65 offset = localOffset;
66 return true;
67 }
68 String m_contents;
69};
70
71static FourCC vttIdBoxType() { return "iden"; }
72static FourCC vttSettingsBoxType() { return "sttg"; }
73static FourCC vttPayloadBoxType() { return "payl"; }
74static FourCC vttCurrentTimeBoxType() { return "ctim"; }
75static FourCC vttCueSourceIDBoxType() { return "vsid"; }
76
77ISOWebVTTCue::ISOWebVTTCue(const MediaTime& presentationTime, const MediaTime& duration)
78 : m_presentationTime(presentationTime)
79 , m_duration(duration)
80{
81}
82
83bool ISOWebVTTCue::parse(DataView& view, unsigned& offset)
84{
85 if (!ISOBox::parse(view, offset))
86 return false;
87
88 ISOStringBox stringBox;
89
90 while (stringBox.read(view, offset)) {
91 if (stringBox.boxType() == vttCueSourceIDBoxType())
92 m_sourceID = stringBox.contents();
93 else if (stringBox.boxType() == vttIdBoxType())
94 m_identifier = stringBox.contents();
95 else if (stringBox.boxType() == vttCurrentTimeBoxType())
96 m_originalStartTime = stringBox.contents();
97 else if (stringBox.boxType() == vttSettingsBoxType())
98 m_settings = stringBox.contents();
99 else if (stringBox.boxType() == vttPayloadBoxType())
100 m_cueText = stringBox.contents();
101 else
102 LOG(Media, "ISOWebVTTCue::ISOWebVTTCue - skipping box id = \"%s\", size = %zu", stringBox.boxType().toString().utf8().data(), (size_t)stringBox.size());
103 }
104 return true;
105}
106
107String ISOWebVTTCue::toJSONString() const
108{
109 auto object = JSON::Object::create();
110
111#if !LOG_DISABLED
112 object->setString("text"_s, m_cueText);
113#endif
114 object->setString("sourceId"_s, encodeWithURLEscapeSequences(m_sourceID));
115 object->setString("id"_s, encodeWithURLEscapeSequences(m_identifier));
116
117 object->setString("originalStartTime"_s, encodeWithURLEscapeSequences(m_originalStartTime));
118 object->setString("settings"_s, encodeWithURLEscapeSequences(m_settings));
119
120 object->setDouble("presentationTime"_s, m_presentationTime.toDouble());
121 object->setDouble("duration"_s, m_duration.toDouble());
122
123 return object->toJSONString();
124}
125
126} // namespace WebCore
127