VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/EbmlWriter.h@ 52312

最後變更 在這個檔案從52312是 52312,由 vboxsync 提交於 11 年 前

6219: New parameters related to file size / recording time limitation for VM Video Capture have been added (vcpmaxtime, vcpmaxsize and vcpoptions - special codec options in key=value format). EbmlWriter has been refactored. Removed some redundant code.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
  • 屬性 svn:mergeinfo 設為 (切換已刪除的分支)
    /branches/VBox-3.0/src/VBox/Frontends/VBoxHeadless/VideoCapture/EbmlWriter.h58652,​70973
    /branches/VBox-3.2/src/VBox/Frontends/VBoxHeadless/VideoCapture/EbmlWriter.h66309,​66318
    /branches/VBox-4.0/src/VBox/Frontends/VBoxHeadless/VideoCapture/EbmlWriter.h70873
    /branches/VBox-4.1/src/VBox/Frontends/VBoxHeadless/VideoCapture/EbmlWriter.h74233
    /branches/VBox-4.2/src/VBox/Main/src-client/EbmlWriter.h91503-91504,​91506-91508,​91510,​91514-91515,​91521
    /branches/VBox-4.3/src/VBox/Main/src-client/EbmlWriter.h91223
    /branches/VBox-4.3/trunk/src/VBox/Main/src-client/EbmlWriter.h91223
    /branches/dsen/gui/src/VBox/Frontends/VBoxHeadless/VideoCapture/EbmlWriter.h79076-79078,​79089,​79109-79110,​79112-79113,​79127-79130,​79134,​79141,​79151,​79155,​79157-79159,​79193,​79197
    /branches/dsen/gui2/src/VBox/Frontends/VBoxHeadless/VideoCapture/EbmlWriter.h79224,​79228,​79233,​79235,​79258,​79262-79263,​79273,​79341,​79345,​79354,​79357,​79387-79388,​79559-79569,​79572-79573,​79578,​79581-79582,​79590-79591,​79598-79599,​79602-79603,​79605-79606,​79632,​79635,​79637,​79644
    /branches/dsen/gui3/src/VBox/Frontends/VBoxHeadless/VideoCapture/EbmlWriter.h79645-79692
檔案大小: 17.4 KB
 
1/* $Id: EbmlWriter.h 52312 2014-08-07 12:54:38Z vboxsync $ */
2/** @file
3 * EbmlWriter.h - EBML writer + WebM container.
4 */
5
6/*
7 * Copyright (C) 2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*
19 * This code is based on:
20 *
21 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
22 *
23 * Use of this source code is governed by a BSD-style license
24 * that can be found in the LICENSE file in the root of the source
25 * tree. An additional intellectual property rights grant can be found
26 * in the file PATENTS. All contributing project authors may
27 * be found in the AUTHORS file in the root of the source tree.
28 */
29
30#ifndef ____EBMLWRITER
31#define ____EBMLWRITER
32
33#include <iprt/file.h>
34#include <iprt/cdefs.h>
35#include <iprt/asm.h>
36#include <iprt/mem.h>
37#include <iprt/string.h>
38#include <VBox/log.h>
39#include <vpx/vpx_encoder.h>
40
41#include <stack>
42#include <list>
43#include <limits>
44
45class Ebml
46{
47public:
48 typedef uint32_t EbmlClassId;
49
50private:
51
52 struct EbmlSubElement
53 {
54 uint64_t offset;
55 EbmlClassId classId;
56 EbmlSubElement(uint64_t offs, EbmlClassId cid) : offset(offs), classId(cid) {}
57 };
58
59 std::stack<EbmlSubElement> m_Elements;
60 RTFILE m_File;
61
62public:
63 template<EbmlClassId, typename T>
64 struct Var
65 {
66 T value;
67 explicit Var(const T &v) : value(v) {}
68 };
69
70 template<EbmlClassId classId> struct SignedInteger : Var<classId, int64_t> { SignedInteger(int64_t v) : Var<classId, int64_t>(v) {} };
71 template<EbmlClassId classId> struct UnsignedInteger : Var<classId, uint64_t> { UnsignedInteger(int64_t v) : Var<classId, uint64_t>(v) {} };
72 template<EbmlClassId classId> struct Float : Var<classId, double> { Float(double v) : Var<classId, double>(v) {}};
73 template<EbmlClassId classId> struct String : Var<classId, const char *> { String(const char *v) : Var<classId, const char *>(v) {}};
74 /* Master-element block */
75 template<EbmlClassId classId> struct SubStart {};
76 /* End of master-element block, a pseudo type */
77 template<EbmlClassId classId> struct SubEnd {};
78 /* Not an EBML type, used for optimization purposes */
79 template<EbmlClassId classId, EbmlClassId id> struct Const {};
80
81 Ebml();
82
83 void init(const RTFILE &a_File);
84
85 template<EbmlClassId classId>
86 inline Ebml &operator<<(const SubStart<classId> &dummy)
87 {
88 serializeConst<classId>();
89 m_Elements.push(EbmlSubElement(RTFileTell(m_File), classId));
90 write<uint64_t>(UINT64_C(0x01FFFFFFFFFFFFFF));
91 return *this;
92 }
93
94 template<EbmlClassId classId>
95 inline Ebml &operator<<(const SubEnd<classId> &dummy)
96 {
97 if(m_Elements.empty() || m_Elements.top().classId != classId) throw VERR_INTERNAL_ERROR;
98
99 uint64_t uPos = RTFileTell(m_File);
100 uint64_t uSize = uPos - m_Elements.top().offset - 8;
101 RTFileSeek(m_File, m_Elements.top().offset, RTFILE_SEEK_BEGIN, NULL);
102
103 // make sure that size will be serialized as uint64
104 write<uint64_t>(uSize | UINT64_C(0x0100000000000000));
105 RTFileSeek(m_File, uPos, RTFILE_SEEK_BEGIN, NULL);
106 m_Elements.pop();
107 return *this;
108 }
109
110 template<EbmlClassId classId, typename T>
111 inline Ebml &operator<<(const Var<classId, T> &value)
112 {
113 serializeConst<classId>();
114 serializeConstEbml<sizeof(T)>();
115 write(value.value);
116 return *this;
117 }
118
119 template<EbmlClassId classId>
120 inline Ebml &operator<<(const String<classId> &str)
121 {
122 serializeConst<classId>();
123 uint64_t size = strlen(str.value);
124 serializeInteger(size);
125 write(str.value, size);
126 return *this;
127 }
128
129 template<EbmlClassId classId>
130 inline Ebml &operator<<(const SignedInteger<classId> &parm)
131 {
132 serializeConst<classId>();
133 size_t size = getSizeOfInt(parm.value);
134 serializeInteger(size);
135 int64_t value = RT_H2BE_U64(parm.value);
136 write(reinterpret_cast<uint8_t*>(&value) + 8 - size, size);
137 return *this;
138 }
139
140 template<EbmlClassId classId>
141 inline Ebml &operator<<(const UnsignedInteger<classId> &parm)
142 {
143 serializeConst<classId>();
144 size_t size = getSizeOfUInt(parm.value);
145 serializeInteger(size);
146 uint64_t value = RT_H2BE_U64(parm.value);
147 write(reinterpret_cast<uint8_t*>(&value) + 8 - size, size);
148 return *this;
149 }
150
151 template<EbmlClassId classId>
152 inline Ebml &operator<<(const Float<classId> &parm)
153 {
154 return operator<<(Var<classId, uint64_t>(*reinterpret_cast<const uint64_t *>(&parm.value)));
155 }
156
157 template<EbmlClassId classId, EbmlClassId id>
158 inline Ebml &operator<<(const Const<classId, id> &)
159 {
160 serializeConst<classId>();
161 serializeConstEbml<SizeOfConst<id>::value>();
162 serializeInteger(id);
163 serializeConst<id>();
164 return *this;
165 }
166
167 void write(const void *data, size_t size);
168
169 template <typename T>
170 void write(const T &data)
171 {
172 if (std::numeric_limits<T>::is_integer)
173 {
174 T tmp;
175 switch(sizeof(T))
176 {
177 case 2:
178 tmp = RT_H2BE_U16(data);
179 break;
180 case 4:
181 tmp = RT_H2BE_U32(data);
182 break;
183 case 8:
184 tmp = RT_H2BE_U64(data);
185 break;
186 default:
187 tmp = data;
188 }
189 write(&tmp, sizeof(T));
190 }
191 else write(&data, sizeof(T));
192 }
193
194 template<uint64_t parm>
195 inline void serializeConst()
196 {
197 static const uint64_t mask = RT_BIT_64(SizeOfConst<parm>::value * 8 - 1);
198 uint64_t value = RT_H2BE_U64((parm &
199 (((mask << 1) - 1) >> SizeOfConst<parm>::value)) |
200 (mask >> (SizeOfConst<parm>::value - 1)));
201
202 write(reinterpret_cast<uint8_t *>(&value) + (8 - SizeOfConst<parm>::value),
203 SizeOfConst<parm>::value);
204 }
205
206 template<uint64_t parm>
207 inline void serializeConstEbml()
208 {
209 static const uint64_t mask = RT_BIT_64(SizeOfConst<parm>::ebmlValue * 8 - 1);
210 uint64_t value = RT_H2BE_U64((parm &
211 (((mask << 1) - 1) >> SizeOfConst<parm>::ebmlValue)) |
212 (mask >> (SizeOfConst<parm>::ebmlValue - 1)));
213
214 write(reinterpret_cast<uint8_t *>(&value) + (8 - SizeOfConst<parm>::ebmlValue),
215 SizeOfConst<parm>::ebmlValue);
216 }
217
218 inline void serializeInteger(uint64_t parm)
219 {
220 const size_t size = 8 - ! (parm & (UINT64_MAX << 49)) - ! (parm & (UINT64_MAX << 42)) -
221 ! (parm & (UINT64_MAX << 35)) - ! (parm & (UINT64_MAX << 28)) -
222 ! (parm & (UINT64_MAX << 21)) - ! (parm & (UINT64_MAX << 14)) -
223 ! (parm & (UINT64_MAX << 7));
224
225 uint64_t mask = RT_BIT_64(size * 8 - 1);
226 uint64_t value = RT_H2BE_U64((parm &
227 (((mask << 1) - 1) >> size)) |
228 (mask >> (size - 1)));
229
230 write(reinterpret_cast<uint8_t *>(&value) + (8 - size),
231 size);
232 }
233
234 /* runtime calculation */
235 static inline size_t getSizeOfUInt(uint64_t arg)
236 {
237 return 8 - ! (arg & (UINT64_MAX << 56)) - ! (arg & (UINT64_MAX << 48)) -
238 ! (arg & (UINT64_MAX << 40)) - ! (arg & (UINT64_MAX << 32)) -
239 ! (arg & (UINT64_MAX << 24)) - ! (arg & (UINT64_MAX << 16)) -
240 ! (arg & (UINT64_MAX << 8));
241 }
242
243 static inline size_t getSizeOfInt(int64_t arg)
244 {
245 return 8 - ! (arg & (INT64_C(-1) << 56)) - ! (~arg & (INT64_C(-1) << 56)) -
246 ! (arg & (INT64_C(-1) << 48)) - ! (~arg & (INT64_C(-1) << 48)) -
247 ! (arg & (INT64_C(-1) << 40)) - ! (~arg & (INT64_C(-1) << 40)) -
248 ! (arg & (INT64_C(-1) << 32)) - ! (~arg & (INT64_C(-1) << 32)) -
249 ! (arg & (INT64_C(-1) << 24)) - ! (~arg & (INT64_C(-1) << 24)) -
250 ! (arg & (INT64_C(-1) << 16)) - ! (~arg & (INT64_C(-1) << 16)) -
251 ! (arg & (INT64_C(-1) << 8)) - ! (~arg & (INT64_C(-1) << 8));
252 }
253
254
255 /* Compile-time calculation for constants */
256 template<uint64_t arg>
257 struct SizeOfConst
258 {
259 static const size_t value = 8 -
260 ! (arg & (UINT64_MAX << 56)) - ! (arg & (UINT64_MAX << 48)) -
261 ! (arg & (UINT64_MAX << 40)) - ! (arg & (UINT64_MAX << 32)) -
262 ! (arg & (UINT64_MAX << 24)) - ! (arg & (UINT64_MAX << 16)) -
263 ! (arg & (UINT64_MAX << 8));
264
265 static const size_t ebmlValue = 8 -
266 ! (arg & (UINT64_MAX << 49)) - ! (arg & (UINT64_MAX << 42)) -
267 ! (arg & (UINT64_MAX << 35)) - ! (arg & (UINT64_MAX << 28)) -
268 ! (arg & (UINT64_MAX << 21)) - ! (arg & (UINT64_MAX << 14)) -
269 ! (arg & (UINT64_MAX << 7));
270 };
271
272private:
273 Ebml(const Ebml &);
274 void operator=(const Ebml &);
275
276};
277
278class WebMWriter
279{
280
281 enum Mkv
282 {
283 EBML = 0x1A45DFA3,
284 EBMLVersion = 0x4286,
285 EBMLReadVersion = 0x42F7,
286 EBMLMaxIDLength = 0x42F2,
287 EBMLMaxSizeLength = 0x42F3,
288 DocType = 0x4282,
289 DocTypeVersion = 0x4287,
290 DocTypeReadVersion = 0x4285,
291 // CRC_32 = 0xBF,
292 Void = 0xEC,
293 SignatureSlot = 0x1B538667,
294 SignatureAlgo = 0x7E8A,
295 SignatureHash = 0x7E9A,
296 SignaturePublicKey = 0x7EA5,
297 Signature = 0x7EB5,
298 SignatureElements = 0x7E5B,
299 SignatureElementList = 0x7E7B,
300 SignedElement = 0x6532,
301 //segment
302 Segment = 0x18538067,
303 //Meta Seek Information
304 SeekHead = 0x114D9B74,
305 Seek = 0x4DBB,
306 SeekID = 0x53AB,
307 SeekPosition = 0x53AC,
308 //Segment Information
309 Info = 0x1549A966,
310 // SegmentUID = 0x73A4,
311 // SegmentFilename = 0x7384,
312 // PrevUID = 0x3CB923,
313 // PrevFilename = 0x3C83AB,
314 // NextUID = 0x3EB923,
315 // NextFilename = 0x3E83BB,
316 // SegmentFamily = 0x4444,
317 // ChapterTranslate = 0x6924,
318 // ChapterTranslateEditionUID = 0x69FC,
319 // ChapterTranslateCodec = 0x69BF,
320 // ChapterTranslateID = 0x69A5,
321 TimecodeScale = 0x2AD7B1,
322 Segment_Duration = 0x4489,
323 DateUTC = 0x4461,
324 // Title = 0x7BA9,
325 MuxingApp = 0x4D80,
326 WritingApp = 0x5741,
327 //Cluster
328 Cluster = 0x1F43B675,
329 Timecode = 0xE7,
330 // SilentTracks = 0x5854,
331 // SilentTrackNumber = 0x58D7,
332 // Position = 0xA7,
333 PrevSize = 0xAB,
334 BlockGroup = 0xA0,
335 Block = 0xA1,
336 // BlockVirtual = 0xA2,
337 // BlockAdditions = 0x75A1,
338 // BlockMore = 0xA6,
339 // BlockAddID = 0xEE,
340 // BlockAdditional = 0xA5,
341 BlockDuration = 0x9B,
342 // ReferencePriority = 0xFA,
343 ReferenceBlock = 0xFB,
344 // ReferenceVirtual = 0xFD,
345 // CodecState = 0xA4,
346 // Slices = 0x8E,
347 // TimeSlice = 0xE8,
348 LaceNumber = 0xCC,
349 // FrameNumber = 0xCD,
350 // BlockAdditionID = 0xCB,
351 // MkvDelay = 0xCE,
352 // Cluster_Duration = 0xCF,
353 SimpleBlock = 0xA3,
354 // EncryptedBlock = 0xAF,
355 //Track
356 Tracks = 0x1654AE6B,
357 TrackEntry = 0xAE,
358 TrackNumber = 0xD7,
359 TrackUID = 0x73C5,
360 TrackType = 0x83,
361 FlagEnabled = 0xB9,
362 FlagDefault = 0x88,
363 FlagForced = 0x55AA,
364 FlagLacing = 0x9C,
365 // MinCache = 0x6DE7,
366 // MaxCache = 0x6DF8,
367 DefaultDuration = 0x23E383,
368 // TrackTimecodeScale = 0x23314F,
369 // TrackOffset = 0x537F,
370 // MaxBlockAdditionID = 0x55EE,
371 Name = 0x536E,
372 Language = 0x22B59C,
373 CodecID = 0x86,
374 CodecPrivate = 0x63A2,
375 CodecName = 0x258688,
376 // AttachmentLink = 0x7446,
377 // CodecSettings = 0x3A9697,
378 // CodecInfoURL = 0x3B4040,
379 // CodecDownloadURL = 0x26B240,
380 // CodecDecodeAll = 0xAA,
381 // TrackOverlay = 0x6FAB,
382 // TrackTranslate = 0x6624,
383 // TrackTranslateEditionUID = 0x66FC,
384 // TrackTranslateCodec = 0x66BF,
385 // TrackTranslateTrackID = 0x66A5,
386 //video
387 Video = 0xE0,
388 FlagInterlaced = 0x9A,
389 // StereoMode = 0x53B8,
390 PixelWidth = 0xB0,
391 PixelHeight = 0xBA,
392 PixelCropBottom = 0x54AA,
393 PixelCropTop = 0x54BB,
394 PixelCropLeft = 0x54CC,
395 PixelCropRight = 0x54DD,
396 DisplayWidth = 0x54B0,
397 DisplayHeight = 0x54BA,
398 DisplayUnit = 0x54B2,
399 AspectRatioType = 0x54B3,
400 // ColourSpace = 0x2EB524,
401 // GammaValue = 0x2FB523,
402 FrameRate = 0x2383E3,
403 //end video
404 //audio
405 Audio = 0xE1,
406 SamplingFrequency = 0xB5,
407 OutputSamplingFrequency = 0x78B5,
408 Channels = 0x9F,
409 // ChannelPositions = 0x7D7B,
410 BitDepth = 0x6264,
411 //end audio
412 //content encoding
413 // ContentEncodings = 0x6d80,
414 // ContentEncoding = 0x6240,
415 // ContentEncodingOrder = 0x5031,
416 // ContentEncodingScope = 0x5032,
417 // ContentEncodingType = 0x5033,
418 // ContentCompression = 0x5034,
419 // ContentCompAlgo = 0x4254,
420 // ContentCompSettings = 0x4255,
421 // ContentEncryption = 0x5035,
422 // ContentEncAlgo = 0x47e1,
423 // ContentEncKeyID = 0x47e2,
424 // ContentSignature = 0x47e3,
425 // ContentSigKeyID = 0x47e4,
426 // ContentSigAlgo = 0x47e5,
427 // ContentSigHashAlgo = 0x47e6,
428 //end content encoding
429 //Cueing Data
430 Cues = 0x1C53BB6B,
431 CuePoint = 0xBB,
432 CueTime = 0xB3,
433 CueTrackPositions = 0xB7,
434 CueTrack = 0xF7,
435 CueClusterPosition = 0xF1,
436 CueBlockNumber = 0x5378
437 // CueCodecState = 0xEA,
438 // CueReference = 0xDB,
439 // CueRefTime = 0x96,
440 // CueRefCluster = 0x97,
441 // CueRefNumber = 0x535F,
442 // CueRefCodecState = 0xEB,
443 //Attachment
444 // Attachments = 0x1941A469,
445 // AttachedFile = 0x61A7,
446 // FileDescription = 0x467E,
447 // FileName = 0x466E,
448 // FileMimeType = 0x4660,
449 // FileData = 0x465C,
450 // FileUID = 0x46AE,
451 // FileReferral = 0x4675,
452 //Chapters
453 // Chapters = 0x1043A770,
454 // EditionEntry = 0x45B9,
455 // EditionUID = 0x45BC,
456 // EditionFlagHidden = 0x45BD,
457 // EditionFlagDefault = 0x45DB,
458 // EditionFlagOrdered = 0x45DD,
459 // ChapterAtom = 0xB6,
460 // ChapterUID = 0x73C4,
461 // ChapterTimeStart = 0x91,
462 // ChapterTimeEnd = 0x92,
463 // ChapterFlagHidden = 0x98,
464 // ChapterFlagEnabled = 0x4598,
465 // ChapterSegmentUID = 0x6E67,
466 // ChapterSegmentEditionUID = 0x6EBC,
467 // ChapterPhysicalEquiv = 0x63C3,
468 // ChapterTrack = 0x8F,
469 // ChapterTrackNumber = 0x89,
470 // ChapterDisplay = 0x80,
471 // ChapString = 0x85,
472 // ChapLanguage = 0x437C,
473 // ChapCountry = 0x437E,
474 // ChapProcess = 0x6944,
475 // ChapProcessCodecID = 0x6955,
476 // ChapProcessPrivate = 0x450D,
477 // ChapProcessCommand = 0x6911,
478 // ChapProcessTime = 0x6922,
479 // ChapProcessData = 0x6933,
480 //Tagging
481 // Tags = 0x1254C367,
482 // Tag = 0x7373,
483 // Targets = 0x63C0,
484 // TargetTypeValue = 0x68CA,
485 // TargetType = 0x63CA,
486 // Tagging_TrackUID = 0x63C5,
487 // Tagging_EditionUID = 0x63C9,
488 // Tagging_ChapterUID = 0x63C4,
489 // AttachmentUID = 0x63C6,
490 // SimpleTag = 0x67C8,
491 // TagName = 0x45A3,
492 // TagLanguage = 0x447A,
493 // TagDefault = 0x4484,
494 // TagString = 0x4487,
495 // TagBinary = 0x4485,
496 };
497
498 struct CueEntry
499 {
500 uint32_t time;
501 uint64_t loc;
502 CueEntry(uint32_t t, uint64_t l) : time(t), loc(l) {}
503 };
504
505 bool m_bDebug;
506 int64_t m_iLastPtsMs;
507 vpx_rational_t m_Framerate;
508
509 uint64_t m_uPositionReference;
510 uint64_t m_uSeekInfoPos;
511 uint64_t m_uSegmentInfoPos;
512 uint64_t m_uTrackPos;
513 uint64_t m_uCuePos;
514 uint64_t m_uClusterPos;
515
516 uint64_t m_uTrackIdPos;
517
518 uint64_t m_uStartSegment;
519
520 uint32_t m_uClusterTimecode;
521 bool m_bClusterOpen;
522 std::list<CueEntry> m_CueList;
523
524 void writeSeekInfo();
525
526 Ebml m_Ebml;
527 RTFILE m_File;
528
529public:
530 WebMWriter();
531 int create(const char *a_pszFilename);
532 void close();
533 int writeHeader(const vpx_codec_enc_cfg_t *a_pCfg, const vpx_rational *a_pFps);
534 int writeBlock(const vpx_codec_enc_cfg_t *a_pCfg, const vpx_codec_cx_pkt_t *a_pPkt);
535 int writeFooter(uint32_t a_u64Hash);
536 uint64_t getFileSize();
537
538 struct SimpleBlockData
539 {
540 uint32_t trackNumber;
541 int16_t timeCode;
542 uint8_t flags;
543 const void *data;
544 size_t dataSize;
545
546 SimpleBlockData(uint32_t tn, int16_t tc, uint8_t f, const void *d, size_t ds) :
547 trackNumber(tn),
548 timeCode(tc),
549 flags(f),
550 data(d),
551 dataSize(ds) {}
552 };
553
554private:
555 void operator=(const WebMWriter &);
556 WebMWriter(const WebMWriter &);
557 friend Ebml &operator<<(Ebml &a_Ebml, const SimpleBlockData &a_Data);
558};
559
560#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette