xref: /aosp_15_r20/external/libwebm/sample_muxer_metadata.cc (revision 103e46e4cd4b6efcf6001f23fa8665fb110abf8d)
1*103e46e4SHarish Mahendrakar // Copyright (c) 2012 The WebM project authors. All Rights Reserved.
2*103e46e4SHarish Mahendrakar //
3*103e46e4SHarish Mahendrakar // Use of this source code is governed by a BSD-style license
4*103e46e4SHarish Mahendrakar // that can be found in the LICENSE file in the root of the source
5*103e46e4SHarish Mahendrakar // tree. An additional intellectual property rights grant can be found
6*103e46e4SHarish Mahendrakar // in the file PATENTS.  All contributing project authors may
7*103e46e4SHarish Mahendrakar // be found in the AUTHORS file in the root of the source tree.
8*103e46e4SHarish Mahendrakar //
9*103e46e4SHarish Mahendrakar // This sample application demonstrates how to use the matroska parser
10*103e46e4SHarish Mahendrakar // library, which allows clients to handle a matroska format file.
11*103e46e4SHarish Mahendrakar 
12*103e46e4SHarish Mahendrakar #include "sample_muxer_metadata.h"
13*103e46e4SHarish Mahendrakar 
14*103e46e4SHarish Mahendrakar #include <cstdio>
15*103e46e4SHarish Mahendrakar #include <string>
16*103e46e4SHarish Mahendrakar 
17*103e46e4SHarish Mahendrakar #include "mkvmuxer/mkvmuxer.h"
18*103e46e4SHarish Mahendrakar #include "webvtt/vttreader.h"
19*103e46e4SHarish Mahendrakar 
SampleMuxerMetadata()20*103e46e4SHarish Mahendrakar SampleMuxerMetadata::SampleMuxerMetadata() : segment_(NULL) {}
21*103e46e4SHarish Mahendrakar 
Init(mkvmuxer::Segment * segment)22*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::Init(mkvmuxer::Segment* segment) {
23*103e46e4SHarish Mahendrakar   if (segment == NULL || segment_ != NULL)
24*103e46e4SHarish Mahendrakar     return false;
25*103e46e4SHarish Mahendrakar 
26*103e46e4SHarish Mahendrakar   segment_ = segment;
27*103e46e4SHarish Mahendrakar   return true;
28*103e46e4SHarish Mahendrakar }
29*103e46e4SHarish Mahendrakar 
Load(const char * file,Kind kind)30*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::Load(const char* file, Kind kind) {
31*103e46e4SHarish Mahendrakar   if (kind == kChapters)
32*103e46e4SHarish Mahendrakar     return LoadChapters(file);
33*103e46e4SHarish Mahendrakar 
34*103e46e4SHarish Mahendrakar   uint64_t track_num;
35*103e46e4SHarish Mahendrakar 
36*103e46e4SHarish Mahendrakar   if (!AddTrack(kind, &track_num)) {
37*103e46e4SHarish Mahendrakar     printf("Unable to add track for WebVTT file \"%s\"\n", file);
38*103e46e4SHarish Mahendrakar     return false;
39*103e46e4SHarish Mahendrakar   }
40*103e46e4SHarish Mahendrakar 
41*103e46e4SHarish Mahendrakar   return Parse(file, kind, track_num);
42*103e46e4SHarish Mahendrakar }
43*103e46e4SHarish Mahendrakar 
AddChapters()44*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::AddChapters() {
45*103e46e4SHarish Mahendrakar   typedef cue_list_t::const_iterator iter_t;
46*103e46e4SHarish Mahendrakar   iter_t i = chapter_cues_.begin();
47*103e46e4SHarish Mahendrakar   const iter_t j = chapter_cues_.end();
48*103e46e4SHarish Mahendrakar 
49*103e46e4SHarish Mahendrakar   while (i != j) {
50*103e46e4SHarish Mahendrakar     const cue_t& chapter = *i++;
51*103e46e4SHarish Mahendrakar 
52*103e46e4SHarish Mahendrakar     if (!AddChapter(chapter))
53*103e46e4SHarish Mahendrakar       return false;
54*103e46e4SHarish Mahendrakar   }
55*103e46e4SHarish Mahendrakar 
56*103e46e4SHarish Mahendrakar   return true;
57*103e46e4SHarish Mahendrakar }
58*103e46e4SHarish Mahendrakar 
Write(int64_t time_ns)59*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::Write(int64_t time_ns) {
60*103e46e4SHarish Mahendrakar   typedef cues_set_t::iterator iter_t;
61*103e46e4SHarish Mahendrakar 
62*103e46e4SHarish Mahendrakar   iter_t i = cues_set_.begin();
63*103e46e4SHarish Mahendrakar   const iter_t j = cues_set_.end();
64*103e46e4SHarish Mahendrakar 
65*103e46e4SHarish Mahendrakar   while (i != j) {
66*103e46e4SHarish Mahendrakar     const cues_set_t::value_type& v = *i;
67*103e46e4SHarish Mahendrakar 
68*103e46e4SHarish Mahendrakar     if (time_ns >= 0 && v > time_ns)
69*103e46e4SHarish Mahendrakar       return true;  // nothing else to do just yet
70*103e46e4SHarish Mahendrakar 
71*103e46e4SHarish Mahendrakar     if (!v.Write(segment_)) {
72*103e46e4SHarish Mahendrakar       printf("\nCould not add metadata.\n");
73*103e46e4SHarish Mahendrakar       return false;  // error
74*103e46e4SHarish Mahendrakar     }
75*103e46e4SHarish Mahendrakar 
76*103e46e4SHarish Mahendrakar     cues_set_.erase(i++);
77*103e46e4SHarish Mahendrakar   }
78*103e46e4SHarish Mahendrakar 
79*103e46e4SHarish Mahendrakar   return true;
80*103e46e4SHarish Mahendrakar }
81*103e46e4SHarish Mahendrakar 
LoadChapters(const char * file)82*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::LoadChapters(const char* file) {
83*103e46e4SHarish Mahendrakar   if (!chapter_cues_.empty()) {
84*103e46e4SHarish Mahendrakar     printf("Support for more than one chapters file is not yet implemented\n");
85*103e46e4SHarish Mahendrakar     return false;
86*103e46e4SHarish Mahendrakar   }
87*103e46e4SHarish Mahendrakar 
88*103e46e4SHarish Mahendrakar   cue_list_t cues;
89*103e46e4SHarish Mahendrakar 
90*103e46e4SHarish Mahendrakar   if (!ParseChapters(file, &cues))
91*103e46e4SHarish Mahendrakar     return false;
92*103e46e4SHarish Mahendrakar 
93*103e46e4SHarish Mahendrakar   // TODO(matthewjheaney): support more than one chapters file
94*103e46e4SHarish Mahendrakar   chapter_cues_.swap(cues);
95*103e46e4SHarish Mahendrakar 
96*103e46e4SHarish Mahendrakar   return true;
97*103e46e4SHarish Mahendrakar }
98*103e46e4SHarish Mahendrakar 
ParseChapters(const char * file,cue_list_t * cues_ptr)99*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::ParseChapters(const char* file,
100*103e46e4SHarish Mahendrakar                                         cue_list_t* cues_ptr) {
101*103e46e4SHarish Mahendrakar   cue_list_t& cues = *cues_ptr;
102*103e46e4SHarish Mahendrakar   cues.clear();
103*103e46e4SHarish Mahendrakar 
104*103e46e4SHarish Mahendrakar   libwebvtt::VttReader r;
105*103e46e4SHarish Mahendrakar   int e = r.Open(file);
106*103e46e4SHarish Mahendrakar 
107*103e46e4SHarish Mahendrakar   if (e) {
108*103e46e4SHarish Mahendrakar     printf("Unable to open WebVTT file: \"%s\"\n", file);
109*103e46e4SHarish Mahendrakar     return false;
110*103e46e4SHarish Mahendrakar   }
111*103e46e4SHarish Mahendrakar 
112*103e46e4SHarish Mahendrakar   libwebvtt::Parser p(&r);
113*103e46e4SHarish Mahendrakar   e = p.Init();
114*103e46e4SHarish Mahendrakar 
115*103e46e4SHarish Mahendrakar   if (e < 0) {  // error
116*103e46e4SHarish Mahendrakar     printf("Error parsing WebVTT file: \"%s\"\n", file);
117*103e46e4SHarish Mahendrakar     return false;
118*103e46e4SHarish Mahendrakar   }
119*103e46e4SHarish Mahendrakar 
120*103e46e4SHarish Mahendrakar   libwebvtt::Time t;
121*103e46e4SHarish Mahendrakar   t.hours = -1;
122*103e46e4SHarish Mahendrakar 
123*103e46e4SHarish Mahendrakar   for (;;) {
124*103e46e4SHarish Mahendrakar     cue_t c;
125*103e46e4SHarish Mahendrakar     e = p.Parse(&c);
126*103e46e4SHarish Mahendrakar 
127*103e46e4SHarish Mahendrakar     if (e < 0) {  // error
128*103e46e4SHarish Mahendrakar       printf("Error parsing WebVTT file: \"%s\"\n", file);
129*103e46e4SHarish Mahendrakar       return false;
130*103e46e4SHarish Mahendrakar     }
131*103e46e4SHarish Mahendrakar 
132*103e46e4SHarish Mahendrakar     if (e > 0)  // EOF
133*103e46e4SHarish Mahendrakar       return true;
134*103e46e4SHarish Mahendrakar 
135*103e46e4SHarish Mahendrakar     if (c.start_time < t) {
136*103e46e4SHarish Mahendrakar       printf("bad WebVTT cue timestamp (out-of-order)\n");
137*103e46e4SHarish Mahendrakar       return false;
138*103e46e4SHarish Mahendrakar     }
139*103e46e4SHarish Mahendrakar 
140*103e46e4SHarish Mahendrakar     if (c.stop_time < c.start_time) {
141*103e46e4SHarish Mahendrakar       printf("bad WebVTT cue timestamp (stop < start)\n");
142*103e46e4SHarish Mahendrakar       return false;
143*103e46e4SHarish Mahendrakar     }
144*103e46e4SHarish Mahendrakar 
145*103e46e4SHarish Mahendrakar     t = c.start_time;
146*103e46e4SHarish Mahendrakar     cues.push_back(c);
147*103e46e4SHarish Mahendrakar   }
148*103e46e4SHarish Mahendrakar }
149*103e46e4SHarish Mahendrakar 
AddChapter(const cue_t & cue)150*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::AddChapter(const cue_t& cue) {
151*103e46e4SHarish Mahendrakar   // TODO(matthewjheaney): support language and country
152*103e46e4SHarish Mahendrakar 
153*103e46e4SHarish Mahendrakar   mkvmuxer::Chapter* const chapter = segment_->AddChapter();
154*103e46e4SHarish Mahendrakar 
155*103e46e4SHarish Mahendrakar   if (chapter == NULL) {
156*103e46e4SHarish Mahendrakar     printf("Unable to add chapter\n");
157*103e46e4SHarish Mahendrakar     return false;
158*103e46e4SHarish Mahendrakar   }
159*103e46e4SHarish Mahendrakar 
160*103e46e4SHarish Mahendrakar   if (cue.identifier.empty()) {
161*103e46e4SHarish Mahendrakar     chapter->set_id(NULL);
162*103e46e4SHarish Mahendrakar   } else {
163*103e46e4SHarish Mahendrakar     const char* const id = cue.identifier.c_str();
164*103e46e4SHarish Mahendrakar     if (!chapter->set_id(id)) {
165*103e46e4SHarish Mahendrakar       printf("Unable to set chapter id\n");
166*103e46e4SHarish Mahendrakar       return false;
167*103e46e4SHarish Mahendrakar     }
168*103e46e4SHarish Mahendrakar   }
169*103e46e4SHarish Mahendrakar 
170*103e46e4SHarish Mahendrakar   typedef libwebvtt::presentation_t time_ms_t;
171*103e46e4SHarish Mahendrakar   const time_ms_t start_time_ms = cue.start_time.presentation();
172*103e46e4SHarish Mahendrakar   const time_ms_t stop_time_ms = cue.stop_time.presentation();
173*103e46e4SHarish Mahendrakar 
174*103e46e4SHarish Mahendrakar   enum { kNsPerMs = 1000000 };
175*103e46e4SHarish Mahendrakar   const uint64_t start_time_ns = start_time_ms * kNsPerMs;
176*103e46e4SHarish Mahendrakar   const uint64_t stop_time_ns = stop_time_ms * kNsPerMs;
177*103e46e4SHarish Mahendrakar 
178*103e46e4SHarish Mahendrakar   chapter->set_time(*segment_, start_time_ns, stop_time_ns);
179*103e46e4SHarish Mahendrakar 
180*103e46e4SHarish Mahendrakar   typedef libwebvtt::Cue::payload_t::const_iterator iter_t;
181*103e46e4SHarish Mahendrakar   iter_t i = cue.payload.begin();
182*103e46e4SHarish Mahendrakar   const iter_t j = cue.payload.end();
183*103e46e4SHarish Mahendrakar 
184*103e46e4SHarish Mahendrakar   std::string title;
185*103e46e4SHarish Mahendrakar 
186*103e46e4SHarish Mahendrakar   for (;;) {
187*103e46e4SHarish Mahendrakar     title += *i++;
188*103e46e4SHarish Mahendrakar 
189*103e46e4SHarish Mahendrakar     if (i == j)
190*103e46e4SHarish Mahendrakar       break;
191*103e46e4SHarish Mahendrakar 
192*103e46e4SHarish Mahendrakar     enum { kLF = '\x0A' };
193*103e46e4SHarish Mahendrakar     title += kLF;
194*103e46e4SHarish Mahendrakar   }
195*103e46e4SHarish Mahendrakar 
196*103e46e4SHarish Mahendrakar   if (!chapter->add_string(title.c_str(), NULL, NULL)) {
197*103e46e4SHarish Mahendrakar     printf("Unable to set chapter title\n");
198*103e46e4SHarish Mahendrakar     return false;
199*103e46e4SHarish Mahendrakar   }
200*103e46e4SHarish Mahendrakar 
201*103e46e4SHarish Mahendrakar   return true;
202*103e46e4SHarish Mahendrakar }
203*103e46e4SHarish Mahendrakar 
AddTrack(Kind kind,uint64_t * track_num)204*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::AddTrack(Kind kind, uint64_t* track_num) {
205*103e46e4SHarish Mahendrakar   *track_num = 0;
206*103e46e4SHarish Mahendrakar 
207*103e46e4SHarish Mahendrakar   // Track number value 0 means "let muxer choose track number"
208*103e46e4SHarish Mahendrakar   mkvmuxer::Track* const track = segment_->AddTrack(0);
209*103e46e4SHarish Mahendrakar 
210*103e46e4SHarish Mahendrakar   if (track == NULL)  // error
211*103e46e4SHarish Mahendrakar     return false;
212*103e46e4SHarish Mahendrakar 
213*103e46e4SHarish Mahendrakar   // Return the track number value chosen by the muxer
214*103e46e4SHarish Mahendrakar   *track_num = track->number();
215*103e46e4SHarish Mahendrakar 
216*103e46e4SHarish Mahendrakar   int type;
217*103e46e4SHarish Mahendrakar   const char* codec_id;
218*103e46e4SHarish Mahendrakar 
219*103e46e4SHarish Mahendrakar   switch (kind) {
220*103e46e4SHarish Mahendrakar     case kSubtitles:
221*103e46e4SHarish Mahendrakar       type = 0x11;
222*103e46e4SHarish Mahendrakar       codec_id = "D_WEBVTT/SUBTITLES";
223*103e46e4SHarish Mahendrakar       break;
224*103e46e4SHarish Mahendrakar 
225*103e46e4SHarish Mahendrakar     case kCaptions:
226*103e46e4SHarish Mahendrakar       type = 0x11;
227*103e46e4SHarish Mahendrakar       codec_id = "D_WEBVTT/CAPTIONS";
228*103e46e4SHarish Mahendrakar       break;
229*103e46e4SHarish Mahendrakar 
230*103e46e4SHarish Mahendrakar     case kDescriptions:
231*103e46e4SHarish Mahendrakar       type = 0x21;
232*103e46e4SHarish Mahendrakar       codec_id = "D_WEBVTT/DESCRIPTIONS";
233*103e46e4SHarish Mahendrakar       break;
234*103e46e4SHarish Mahendrakar 
235*103e46e4SHarish Mahendrakar     case kMetadata:
236*103e46e4SHarish Mahendrakar       type = 0x21;
237*103e46e4SHarish Mahendrakar       codec_id = "D_WEBVTT/METADATA";
238*103e46e4SHarish Mahendrakar       break;
239*103e46e4SHarish Mahendrakar 
240*103e46e4SHarish Mahendrakar     default:
241*103e46e4SHarish Mahendrakar       return false;
242*103e46e4SHarish Mahendrakar   }
243*103e46e4SHarish Mahendrakar 
244*103e46e4SHarish Mahendrakar   track->set_type(type);
245*103e46e4SHarish Mahendrakar   track->set_codec_id(codec_id);
246*103e46e4SHarish Mahendrakar 
247*103e46e4SHarish Mahendrakar   // TODO(matthewjheaney): set name and language
248*103e46e4SHarish Mahendrakar 
249*103e46e4SHarish Mahendrakar   return true;
250*103e46e4SHarish Mahendrakar }
251*103e46e4SHarish Mahendrakar 
Parse(const char * file,Kind,uint64_t track_num)252*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::Parse(const char* file, Kind /* kind */,
253*103e46e4SHarish Mahendrakar                                 uint64_t track_num) {
254*103e46e4SHarish Mahendrakar   libwebvtt::VttReader r;
255*103e46e4SHarish Mahendrakar   int e = r.Open(file);
256*103e46e4SHarish Mahendrakar 
257*103e46e4SHarish Mahendrakar   if (e) {
258*103e46e4SHarish Mahendrakar     printf("Unable to open WebVTT file: \"%s\"\n", file);
259*103e46e4SHarish Mahendrakar     return false;
260*103e46e4SHarish Mahendrakar   }
261*103e46e4SHarish Mahendrakar 
262*103e46e4SHarish Mahendrakar   libwebvtt::Parser p(&r);
263*103e46e4SHarish Mahendrakar 
264*103e46e4SHarish Mahendrakar   e = p.Init();
265*103e46e4SHarish Mahendrakar 
266*103e46e4SHarish Mahendrakar   if (e < 0) {  // error
267*103e46e4SHarish Mahendrakar     printf("Error parsing WebVTT file: \"%s\"\n", file);
268*103e46e4SHarish Mahendrakar     return false;
269*103e46e4SHarish Mahendrakar   }
270*103e46e4SHarish Mahendrakar 
271*103e46e4SHarish Mahendrakar   SortableCue cue;
272*103e46e4SHarish Mahendrakar   cue.track_num = track_num;
273*103e46e4SHarish Mahendrakar 
274*103e46e4SHarish Mahendrakar   libwebvtt::Time t;
275*103e46e4SHarish Mahendrakar   t.hours = -1;
276*103e46e4SHarish Mahendrakar 
277*103e46e4SHarish Mahendrakar   for (;;) {
278*103e46e4SHarish Mahendrakar     cue_t& c = cue.cue;
279*103e46e4SHarish Mahendrakar     e = p.Parse(&c);
280*103e46e4SHarish Mahendrakar 
281*103e46e4SHarish Mahendrakar     if (e < 0) {  // error
282*103e46e4SHarish Mahendrakar       printf("Error parsing WebVTT file: \"%s\"\n", file);
283*103e46e4SHarish Mahendrakar       return false;
284*103e46e4SHarish Mahendrakar     }
285*103e46e4SHarish Mahendrakar 
286*103e46e4SHarish Mahendrakar     if (e > 0)  // EOF
287*103e46e4SHarish Mahendrakar       return true;
288*103e46e4SHarish Mahendrakar 
289*103e46e4SHarish Mahendrakar     if (c.start_time >= t) {
290*103e46e4SHarish Mahendrakar       t = c.start_time;
291*103e46e4SHarish Mahendrakar     } else {
292*103e46e4SHarish Mahendrakar       printf("bad WebVTT cue timestamp (out-of-order)\n");
293*103e46e4SHarish Mahendrakar       return false;
294*103e46e4SHarish Mahendrakar     }
295*103e46e4SHarish Mahendrakar 
296*103e46e4SHarish Mahendrakar     if (c.stop_time < c.start_time) {
297*103e46e4SHarish Mahendrakar       printf("bad WebVTT cue timestamp (stop < start)\n");
298*103e46e4SHarish Mahendrakar       return false;
299*103e46e4SHarish Mahendrakar     }
300*103e46e4SHarish Mahendrakar 
301*103e46e4SHarish Mahendrakar     cues_set_.insert(cue);
302*103e46e4SHarish Mahendrakar   }
303*103e46e4SHarish Mahendrakar }
304*103e46e4SHarish Mahendrakar 
MakeFrame(const cue_t & c,std::string * pf)305*103e46e4SHarish Mahendrakar void SampleMuxerMetadata::MakeFrame(const cue_t& c, std::string* pf) {
306*103e46e4SHarish Mahendrakar   pf->clear();
307*103e46e4SHarish Mahendrakar   WriteCueIdentifier(c.identifier, pf);
308*103e46e4SHarish Mahendrakar   WriteCueSettings(c.settings, pf);
309*103e46e4SHarish Mahendrakar   WriteCuePayload(c.payload, pf);
310*103e46e4SHarish Mahendrakar }
311*103e46e4SHarish Mahendrakar 
WriteCueIdentifier(const std::string & identifier,std::string * pf)312*103e46e4SHarish Mahendrakar void SampleMuxerMetadata::WriteCueIdentifier(const std::string& identifier,
313*103e46e4SHarish Mahendrakar                                              std::string* pf) {
314*103e46e4SHarish Mahendrakar   pf->append(identifier);
315*103e46e4SHarish Mahendrakar   pf->push_back('\x0A');  // LF
316*103e46e4SHarish Mahendrakar }
317*103e46e4SHarish Mahendrakar 
WriteCueSettings(const cue_t::settings_t & settings,std::string * pf)318*103e46e4SHarish Mahendrakar void SampleMuxerMetadata::WriteCueSettings(const cue_t::settings_t& settings,
319*103e46e4SHarish Mahendrakar                                            std::string* pf) {
320*103e46e4SHarish Mahendrakar   if (settings.empty()) {
321*103e46e4SHarish Mahendrakar     pf->push_back('\x0A');  // LF
322*103e46e4SHarish Mahendrakar     return;
323*103e46e4SHarish Mahendrakar   }
324*103e46e4SHarish Mahendrakar 
325*103e46e4SHarish Mahendrakar   typedef cue_t::settings_t::const_iterator iter_t;
326*103e46e4SHarish Mahendrakar 
327*103e46e4SHarish Mahendrakar   iter_t i = settings.begin();
328*103e46e4SHarish Mahendrakar   const iter_t j = settings.end();
329*103e46e4SHarish Mahendrakar 
330*103e46e4SHarish Mahendrakar   for (;;) {
331*103e46e4SHarish Mahendrakar     const libwebvtt::Setting& setting = *i++;
332*103e46e4SHarish Mahendrakar 
333*103e46e4SHarish Mahendrakar     pf->append(setting.name);
334*103e46e4SHarish Mahendrakar     pf->push_back(':');
335*103e46e4SHarish Mahendrakar     pf->append(setting.value);
336*103e46e4SHarish Mahendrakar 
337*103e46e4SHarish Mahendrakar     if (i == j)
338*103e46e4SHarish Mahendrakar       break;
339*103e46e4SHarish Mahendrakar 
340*103e46e4SHarish Mahendrakar     pf->push_back(' ');  // separate settings with whitespace
341*103e46e4SHarish Mahendrakar   }
342*103e46e4SHarish Mahendrakar 
343*103e46e4SHarish Mahendrakar   pf->push_back('\x0A');  // LF
344*103e46e4SHarish Mahendrakar }
345*103e46e4SHarish Mahendrakar 
WriteCuePayload(const cue_t::payload_t & payload,std::string * pf)346*103e46e4SHarish Mahendrakar void SampleMuxerMetadata::WriteCuePayload(const cue_t::payload_t& payload,
347*103e46e4SHarish Mahendrakar                                           std::string* pf) {
348*103e46e4SHarish Mahendrakar   typedef cue_t::payload_t::const_iterator iter_t;
349*103e46e4SHarish Mahendrakar 
350*103e46e4SHarish Mahendrakar   iter_t i = payload.begin();
351*103e46e4SHarish Mahendrakar   const iter_t j = payload.end();
352*103e46e4SHarish Mahendrakar 
353*103e46e4SHarish Mahendrakar   while (i != j) {
354*103e46e4SHarish Mahendrakar     const std::string& line = *i++;
355*103e46e4SHarish Mahendrakar     pf->append(line);
356*103e46e4SHarish Mahendrakar     pf->push_back('\x0A');  // LF
357*103e46e4SHarish Mahendrakar   }
358*103e46e4SHarish Mahendrakar }
359*103e46e4SHarish Mahendrakar 
Write(mkvmuxer::Segment * segment) const360*103e46e4SHarish Mahendrakar bool SampleMuxerMetadata::SortableCue::Write(mkvmuxer::Segment* segment) const {
361*103e46e4SHarish Mahendrakar   // Cue start time expressed in milliseconds
362*103e46e4SHarish Mahendrakar   const int64_t start_ms = cue.start_time.presentation();
363*103e46e4SHarish Mahendrakar 
364*103e46e4SHarish Mahendrakar   // Cue start time expressed in nanoseconds (MKV time)
365*103e46e4SHarish Mahendrakar   const int64_t start_ns = start_ms * 1000000;
366*103e46e4SHarish Mahendrakar 
367*103e46e4SHarish Mahendrakar   // Cue stop time expressed in milliseconds
368*103e46e4SHarish Mahendrakar   const int64_t stop_ms = cue.stop_time.presentation();
369*103e46e4SHarish Mahendrakar 
370*103e46e4SHarish Mahendrakar   // Cue stop time expressed in nanonseconds
371*103e46e4SHarish Mahendrakar   const int64_t stop_ns = stop_ms * 1000000;
372*103e46e4SHarish Mahendrakar 
373*103e46e4SHarish Mahendrakar   // Metadata blocks always specify the block duration.
374*103e46e4SHarish Mahendrakar   const int64_t duration_ns = stop_ns - start_ns;
375*103e46e4SHarish Mahendrakar 
376*103e46e4SHarish Mahendrakar   std::string frame;
377*103e46e4SHarish Mahendrakar   MakeFrame(cue, &frame);
378*103e46e4SHarish Mahendrakar 
379*103e46e4SHarish Mahendrakar   typedef const uint8_t* data_t;
380*103e46e4SHarish Mahendrakar   const data_t buf = reinterpret_cast<data_t>(frame.data());
381*103e46e4SHarish Mahendrakar   const uint64_t len = frame.length();
382*103e46e4SHarish Mahendrakar 
383*103e46e4SHarish Mahendrakar   mkvmuxer::Frame muxer_frame;
384*103e46e4SHarish Mahendrakar   if (!muxer_frame.Init(buf, len))
385*103e46e4SHarish Mahendrakar     return 0;
386*103e46e4SHarish Mahendrakar   muxer_frame.set_track_number(track_num);
387*103e46e4SHarish Mahendrakar   muxer_frame.set_timestamp(start_ns);
388*103e46e4SHarish Mahendrakar   muxer_frame.set_duration(duration_ns);
389*103e46e4SHarish Mahendrakar   muxer_frame.set_is_key(true);  // All metadata frames are keyframes.
390*103e46e4SHarish Mahendrakar   return segment->AddGenericFrame(&muxer_frame);
391*103e46e4SHarish Mahendrakar }