summaryrefslogtreecommitdiff
path: root/sample_muxer_metadata.h
blob: d76ccf54aac15f91ebbe4eb3736b08ac36604d2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS.  All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.

#ifndef SAMPLE_MUXER_METADATA_H_  // NOLINT
#define SAMPLE_MUXER_METADATA_H_

#include <stdint.h>

#include <list>
#include <set>
#include <string>

#include "webvtt/webvttparser.h"

namespace mkvmuxer {
class Chapter;
class Frame;
class Segment;
class Track;
}  // namespace mkvmuxer

class SampleMuxerMetadata {
 public:
  enum Kind { kSubtitles, kCaptions, kDescriptions, kMetadata, kChapters };

  SampleMuxerMetadata();

  // Bind this metadata object to the muxer instance.  Returns false
  // if segment equals NULL, or Init has already been called.
  bool Init(mkvmuxer::Segment* segment);

  // Parse the WebVTT file |filename| having the indicated |kind|, and
  // create a corresponding track (or chapters element) in the
  // segment.  Returns false on error.
  bool Load(const char* filename, Kind kind);

  bool AddChapters();

  // Write any WebVTT cues whose time is less or equal to |time_ns| as
  // a metadata block in its corresponding track.  If |time_ns| is
  // negative, write all remaining cues. Returns false on error.
  bool Write(int64_t time_ns);

 private:
  typedef libwebvtt::Cue cue_t;

  // Used to sort cues as they are loaded.
  struct SortableCue {
    bool operator>(int64_t time_ns) const {
      // Cue start time expressed in milliseconds
      const int64_t start_ms = cue.start_time.presentation();

      // Cue start time expressed in nanoseconds (MKV time)
      const int64_t start_ns = start_ms * 1000000;

      return (start_ns > time_ns);
    }

    bool operator<(const SortableCue& rhs) const {
      if (cue.start_time < rhs.cue.start_time)
        return true;

      if (cue.start_time > rhs.cue.start_time)
        return false;

      return (track_num < rhs.track_num);
    }

    // Write this cue as a metablock to |segment|.  Returns false on
    // error.
    bool Write(mkvmuxer::Segment* segment) const;

    uint64_t track_num;
    cue_t cue;
  };

  typedef std::multiset<SortableCue> cues_set_t;
  typedef std::list<cue_t> cue_list_t;

  // Parse the WebVTT cues in the named |file|, returning false on
  // error.  We handle chapters as a special case, because they are
  // stored in their own, dedicated level-1 element.
  bool LoadChapters(const char* file);

  // Parse the WebVTT chapters in |file| to populate |cues|.  Returns
  // false on error.
  static bool ParseChapters(const char* file, cue_list_t* cues);

  // Adds WebVTT cue |chapter| to the chapters element of the output
  // file's segment element.  Returns false on error.
  bool AddChapter(const cue_t& chapter);

  // Add a metadata track to the segment having the indicated |kind|,
  // returning the |track_num| that has been chosen for this track.
  // Returns false on error.
  bool AddTrack(Kind kind, uint64_t* track_num);

  // Parse the WebVTT |file| having the indicated |kind| and
  // |track_num|, adding each parsed cue to cues set.  Returns false
  // on error.
  bool Parse(const char* file, Kind kind, uint64_t track_num);

  // Converts a WebVTT cue to a Matroska metadata block.
  static void MakeFrame(const cue_t& cue, std::string* frame);

  // Populate the cue identifier part of the metadata block.
  static void WriteCueIdentifier(const std::string& identifier,
                                 std::string* frame);

  // Populate the cue settings part of the metadata block.
  static void WriteCueSettings(const cue_t::settings_t& settings,
                               std::string* frame);

  // Populate the payload part of the metadata block.
  static void WriteCuePayload(const cue_t::payload_t& payload,
                              std::string* frame);

  mkvmuxer::Segment* segment_;

  // Set of cues ordered by time and then by track number.
  cues_set_t cues_set_;

  // The cues that will be used to populate the Chapters level-1
  // element of the output file.
  cue_list_t chapter_cues_;

  // Disable copy ctor and copy assign.
  SampleMuxerMetadata(const SampleMuxerMetadata&);
  SampleMuxerMetadata& operator=(const SampleMuxerMetadata&);
};

#endif  // SAMPLE_MUXER_METADATA_H_  // NOLINT