mkvmuxer.cc 118 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196
  1. // Copyright (c) 2012 The WebM project authors. All Rights Reserved.
  2. //
  3. // Use of this source code is governed by a BSD-style license
  4. // that can be found in the LICENSE file in the root of the source
  5. // tree. An additional intellectual property rights grant can be found
  6. // in the file PATENTS. All contributing project authors may
  7. // be found in the AUTHORS file in the root of the source tree.
  8. #include "mkvmuxer/mkvmuxer.h"
  9. #include <cfloat>
  10. #include <climits>
  11. #include <cstdio>
  12. #include <cstdlib>
  13. #include <cstring>
  14. #include <ctime>
  15. #include <memory>
  16. #include <new>
  17. #include <string>
  18. #include <vector>
  19. #include "common/webmids.h"
  20. #include "mkvmuxer/mkvmuxerutil.h"
  21. #include "mkvmuxer/mkvwriter.h"
  22. #include "mkvparser/mkvparser.h"
  23. // disable deprecation warnings for auto_ptr
  24. #if defined(__GNUC__) && __GNUC__ >= 5
  25. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  26. #endif
  27. namespace mkvmuxer {
  28. const float PrimaryChromaticity::kChromaticityMin = 0.0f;
  29. const float PrimaryChromaticity::kChromaticityMax = 1.0f;
  30. const float MasteringMetadata::kMinLuminance = 0.0f;
  31. const float MasteringMetadata::kMinLuminanceMax = 999.99f;
  32. const float MasteringMetadata::kMaxLuminanceMax = 9999.99f;
  33. const float MasteringMetadata::kValueNotPresent = FLT_MAX;
  34. const uint64_t Colour::kValueNotPresent = UINT64_MAX;
  35. namespace {
  36. const char kDocTypeWebm[] = "webm";
  37. const char kDocTypeMatroska[] = "matroska";
  38. // Deallocate the string designated by |dst|, and then copy the |src|
  39. // string to |dst|. The caller owns both the |src| string and the
  40. // |dst| copy (hence the caller is responsible for eventually
  41. // deallocating the strings, either directly, or indirectly via
  42. // StrCpy). Returns true if the source string was successfully copied
  43. // to the destination.
  44. bool StrCpy(const char* src, char** dst_ptr) {
  45. if (dst_ptr == NULL)
  46. return false;
  47. char*& dst = *dst_ptr;
  48. delete[] dst;
  49. dst = NULL;
  50. if (src == NULL)
  51. return true;
  52. const size_t size = strlen(src) + 1;
  53. dst = new (std::nothrow) char[size]; // NOLINT
  54. if (dst == NULL)
  55. return false;
  56. strcpy(dst, src); // NOLINT
  57. return true;
  58. }
  59. typedef std::auto_ptr<PrimaryChromaticity> PrimaryChromaticityPtr;
  60. bool CopyChromaticity(const PrimaryChromaticity* src,
  61. PrimaryChromaticityPtr* dst) {
  62. if (!dst)
  63. return false;
  64. dst->reset(new (std::nothrow) PrimaryChromaticity(src->x(), src->y()));
  65. if (!dst->get())
  66. return false;
  67. return true;
  68. }
  69. } // namespace
  70. ///////////////////////////////////////////////////////////////
  71. //
  72. // IMkvWriter Class
  73. IMkvWriter::IMkvWriter() {}
  74. IMkvWriter::~IMkvWriter() {}
  75. bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version,
  76. const char* const doc_type) {
  77. // Level 0
  78. uint64_t size =
  79. EbmlElementSize(libwebm::kMkvEBMLVersion, static_cast<uint64>(1));
  80. size += EbmlElementSize(libwebm::kMkvEBMLReadVersion, static_cast<uint64>(1));
  81. size += EbmlElementSize(libwebm::kMkvEBMLMaxIDLength, static_cast<uint64>(4));
  82. size +=
  83. EbmlElementSize(libwebm::kMkvEBMLMaxSizeLength, static_cast<uint64>(8));
  84. size += EbmlElementSize(libwebm::kMkvDocType, doc_type);
  85. size += EbmlElementSize(libwebm::kMkvDocTypeVersion,
  86. static_cast<uint64>(doc_type_version));
  87. size +=
  88. EbmlElementSize(libwebm::kMkvDocTypeReadVersion, static_cast<uint64>(2));
  89. if (!WriteEbmlMasterElement(writer, libwebm::kMkvEBML, size))
  90. return false;
  91. if (!WriteEbmlElement(writer, libwebm::kMkvEBMLVersion,
  92. static_cast<uint64>(1))) {
  93. return false;
  94. }
  95. if (!WriteEbmlElement(writer, libwebm::kMkvEBMLReadVersion,
  96. static_cast<uint64>(1))) {
  97. return false;
  98. }
  99. if (!WriteEbmlElement(writer, libwebm::kMkvEBMLMaxIDLength,
  100. static_cast<uint64>(4))) {
  101. return false;
  102. }
  103. if (!WriteEbmlElement(writer, libwebm::kMkvEBMLMaxSizeLength,
  104. static_cast<uint64>(8))) {
  105. return false;
  106. }
  107. if (!WriteEbmlElement(writer, libwebm::kMkvDocType, doc_type))
  108. return false;
  109. if (!WriteEbmlElement(writer, libwebm::kMkvDocTypeVersion,
  110. static_cast<uint64>(doc_type_version))) {
  111. return false;
  112. }
  113. if (!WriteEbmlElement(writer, libwebm::kMkvDocTypeReadVersion,
  114. static_cast<uint64>(2))) {
  115. return false;
  116. }
  117. return true;
  118. }
  119. bool WriteEbmlHeader(IMkvWriter* writer, uint64_t doc_type_version) {
  120. return WriteEbmlHeader(writer, doc_type_version, kDocTypeWebm);
  121. }
  122. bool WriteEbmlHeader(IMkvWriter* writer) {
  123. return WriteEbmlHeader(writer, mkvmuxer::Segment::kDefaultDocTypeVersion);
  124. }
  125. bool ChunkedCopy(mkvparser::IMkvReader* source, mkvmuxer::IMkvWriter* dst,
  126. int64_t start, int64_t size) {
  127. // TODO(vigneshv): Check if this is a reasonable value.
  128. const uint32_t kBufSize = 2048;
  129. uint8_t* buf = new uint8_t[kBufSize];
  130. int64_t offset = start;
  131. while (size > 0) {
  132. const int64_t read_len = (size > kBufSize) ? kBufSize : size;
  133. if (source->Read(offset, static_cast<long>(read_len), buf))
  134. return false;
  135. dst->Write(buf, static_cast<uint32_t>(read_len));
  136. offset += read_len;
  137. size -= read_len;
  138. }
  139. delete[] buf;
  140. return true;
  141. }
  142. ///////////////////////////////////////////////////////////////
  143. //
  144. // Frame Class
  145. Frame::Frame()
  146. : add_id_(0),
  147. additional_(NULL),
  148. additional_length_(0),
  149. duration_(0),
  150. duration_set_(false),
  151. frame_(NULL),
  152. is_key_(false),
  153. length_(0),
  154. track_number_(0),
  155. timestamp_(0),
  156. discard_padding_(0),
  157. reference_block_timestamp_(0),
  158. reference_block_timestamp_set_(false) {}
  159. Frame::~Frame() {
  160. delete[] frame_;
  161. delete[] additional_;
  162. }
  163. bool Frame::CopyFrom(const Frame& frame) {
  164. delete[] frame_;
  165. frame_ = NULL;
  166. length_ = 0;
  167. if (frame.length() > 0 && frame.frame() != NULL &&
  168. !Init(frame.frame(), frame.length())) {
  169. return false;
  170. }
  171. add_id_ = 0;
  172. delete[] additional_;
  173. additional_ = NULL;
  174. additional_length_ = 0;
  175. if (frame.additional_length() > 0 && frame.additional() != NULL &&
  176. !AddAdditionalData(frame.additional(), frame.additional_length(),
  177. frame.add_id())) {
  178. return false;
  179. }
  180. duration_ = frame.duration();
  181. duration_set_ = frame.duration_set();
  182. is_key_ = frame.is_key();
  183. track_number_ = frame.track_number();
  184. timestamp_ = frame.timestamp();
  185. discard_padding_ = frame.discard_padding();
  186. reference_block_timestamp_ = frame.reference_block_timestamp();
  187. reference_block_timestamp_set_ = frame.reference_block_timestamp_set();
  188. return true;
  189. }
  190. bool Frame::Init(const uint8_t* frame, uint64_t length) {
  191. uint8_t* const data =
  192. new (std::nothrow) uint8_t[static_cast<size_t>(length)]; // NOLINT
  193. if (!data)
  194. return false;
  195. delete[] frame_;
  196. frame_ = data;
  197. length_ = length;
  198. memcpy(frame_, frame, static_cast<size_t>(length_));
  199. return true;
  200. }
  201. bool Frame::AddAdditionalData(const uint8_t* additional, uint64_t length,
  202. uint64_t add_id) {
  203. uint8_t* const data =
  204. new (std::nothrow) uint8_t[static_cast<size_t>(length)]; // NOLINT
  205. if (!data)
  206. return false;
  207. delete[] additional_;
  208. additional_ = data;
  209. additional_length_ = length;
  210. add_id_ = add_id;
  211. memcpy(additional_, additional, static_cast<size_t>(additional_length_));
  212. return true;
  213. }
  214. bool Frame::IsValid() const {
  215. if (length_ == 0 || !frame_) {
  216. return false;
  217. }
  218. if ((additional_length_ != 0 && !additional_) ||
  219. (additional_ != NULL && additional_length_ == 0)) {
  220. return false;
  221. }
  222. if (track_number_ == 0 || track_number_ > kMaxTrackNumber) {
  223. return false;
  224. }
  225. if (!CanBeSimpleBlock() && !is_key_ && !reference_block_timestamp_set_) {
  226. return false;
  227. }
  228. return true;
  229. }
  230. bool Frame::CanBeSimpleBlock() const {
  231. return additional_ == NULL && discard_padding_ == 0 && duration_ == 0;
  232. }
  233. void Frame::set_duration(uint64_t duration) {
  234. duration_ = duration;
  235. duration_set_ = true;
  236. }
  237. void Frame::set_reference_block_timestamp(int64_t reference_block_timestamp) {
  238. reference_block_timestamp_ = reference_block_timestamp;
  239. reference_block_timestamp_set_ = true;
  240. }
  241. ///////////////////////////////////////////////////////////////
  242. //
  243. // CuePoint Class
  244. CuePoint::CuePoint()
  245. : time_(0),
  246. track_(0),
  247. cluster_pos_(0),
  248. block_number_(1),
  249. output_block_number_(true) {}
  250. CuePoint::~CuePoint() {}
  251. bool CuePoint::Write(IMkvWriter* writer) const {
  252. if (!writer || track_ < 1 || cluster_pos_ < 1)
  253. return false;
  254. uint64_t size = EbmlElementSize(libwebm::kMkvCueClusterPosition,
  255. static_cast<uint64>(cluster_pos_));
  256. size += EbmlElementSize(libwebm::kMkvCueTrack, static_cast<uint64>(track_));
  257. if (output_block_number_ && block_number_ > 1)
  258. size += EbmlElementSize(libwebm::kMkvCueBlockNumber,
  259. static_cast<uint64>(block_number_));
  260. const uint64_t track_pos_size =
  261. EbmlMasterElementSize(libwebm::kMkvCueTrackPositions, size) + size;
  262. const uint64_t payload_size =
  263. EbmlElementSize(libwebm::kMkvCueTime, static_cast<uint64>(time_)) +
  264. track_pos_size;
  265. if (!WriteEbmlMasterElement(writer, libwebm::kMkvCuePoint, payload_size))
  266. return false;
  267. const int64_t payload_position = writer->Position();
  268. if (payload_position < 0)
  269. return false;
  270. if (!WriteEbmlElement(writer, libwebm::kMkvCueTime,
  271. static_cast<uint64>(time_))) {
  272. return false;
  273. }
  274. if (!WriteEbmlMasterElement(writer, libwebm::kMkvCueTrackPositions, size))
  275. return false;
  276. if (!WriteEbmlElement(writer, libwebm::kMkvCueTrack,
  277. static_cast<uint64>(track_))) {
  278. return false;
  279. }
  280. if (!WriteEbmlElement(writer, libwebm::kMkvCueClusterPosition,
  281. static_cast<uint64>(cluster_pos_))) {
  282. return false;
  283. }
  284. if (output_block_number_ && block_number_ > 1) {
  285. if (!WriteEbmlElement(writer, libwebm::kMkvCueBlockNumber,
  286. static_cast<uint64>(block_number_))) {
  287. return false;
  288. }
  289. }
  290. const int64_t stop_position = writer->Position();
  291. if (stop_position < 0)
  292. return false;
  293. if (stop_position - payload_position != static_cast<int64_t>(payload_size))
  294. return false;
  295. return true;
  296. }
  297. uint64_t CuePoint::PayloadSize() const {
  298. uint64_t size = EbmlElementSize(libwebm::kMkvCueClusterPosition,
  299. static_cast<uint64>(cluster_pos_));
  300. size += EbmlElementSize(libwebm::kMkvCueTrack, static_cast<uint64>(track_));
  301. if (output_block_number_ && block_number_ > 1)
  302. size += EbmlElementSize(libwebm::kMkvCueBlockNumber,
  303. static_cast<uint64>(block_number_));
  304. const uint64_t track_pos_size =
  305. EbmlMasterElementSize(libwebm::kMkvCueTrackPositions, size) + size;
  306. const uint64_t payload_size =
  307. EbmlElementSize(libwebm::kMkvCueTime, static_cast<uint64>(time_)) +
  308. track_pos_size;
  309. return payload_size;
  310. }
  311. uint64_t CuePoint::Size() const {
  312. const uint64_t payload_size = PayloadSize();
  313. return EbmlMasterElementSize(libwebm::kMkvCuePoint, payload_size) +
  314. payload_size;
  315. }
  316. ///////////////////////////////////////////////////////////////
  317. //
  318. // Cues Class
  319. Cues::Cues()
  320. : cue_entries_capacity_(0),
  321. cue_entries_size_(0),
  322. cue_entries_(NULL),
  323. output_block_number_(true) {}
  324. Cues::~Cues() {
  325. if (cue_entries_) {
  326. for (int32_t i = 0; i < cue_entries_size_; ++i) {
  327. CuePoint* const cue = cue_entries_[i];
  328. delete cue;
  329. }
  330. delete[] cue_entries_;
  331. }
  332. }
  333. bool Cues::AddCue(CuePoint* cue) {
  334. if (!cue)
  335. return false;
  336. if ((cue_entries_size_ + 1) > cue_entries_capacity_) {
  337. // Add more CuePoints.
  338. const int32_t new_capacity =
  339. (!cue_entries_capacity_) ? 2 : cue_entries_capacity_ * 2;
  340. if (new_capacity < 1)
  341. return false;
  342. CuePoint** const cues =
  343. new (std::nothrow) CuePoint*[new_capacity]; // NOLINT
  344. if (!cues)
  345. return false;
  346. for (int32_t i = 0; i < cue_entries_size_; ++i) {
  347. cues[i] = cue_entries_[i];
  348. }
  349. delete[] cue_entries_;
  350. cue_entries_ = cues;
  351. cue_entries_capacity_ = new_capacity;
  352. }
  353. cue->set_output_block_number(output_block_number_);
  354. cue_entries_[cue_entries_size_++] = cue;
  355. return true;
  356. }
  357. CuePoint* Cues::GetCueByIndex(int32_t index) const {
  358. if (cue_entries_ == NULL)
  359. return NULL;
  360. if (index >= cue_entries_size_)
  361. return NULL;
  362. return cue_entries_[index];
  363. }
  364. uint64_t Cues::Size() {
  365. uint64_t size = 0;
  366. for (int32_t i = 0; i < cue_entries_size_; ++i)
  367. size += GetCueByIndex(i)->Size();
  368. size += EbmlMasterElementSize(libwebm::kMkvCues, size);
  369. return size;
  370. }
  371. bool Cues::Write(IMkvWriter* writer) const {
  372. if (!writer)
  373. return false;
  374. uint64_t size = 0;
  375. for (int32_t i = 0; i < cue_entries_size_; ++i) {
  376. const CuePoint* const cue = GetCueByIndex(i);
  377. if (!cue)
  378. return false;
  379. size += cue->Size();
  380. }
  381. if (!WriteEbmlMasterElement(writer, libwebm::kMkvCues, size))
  382. return false;
  383. const int64_t payload_position = writer->Position();
  384. if (payload_position < 0)
  385. return false;
  386. for (int32_t i = 0; i < cue_entries_size_; ++i) {
  387. const CuePoint* const cue = GetCueByIndex(i);
  388. if (!cue->Write(writer))
  389. return false;
  390. }
  391. const int64_t stop_position = writer->Position();
  392. if (stop_position < 0)
  393. return false;
  394. if (stop_position - payload_position != static_cast<int64_t>(size))
  395. return false;
  396. return true;
  397. }
  398. ///////////////////////////////////////////////////////////////
  399. //
  400. // ContentEncAESSettings Class
  401. ContentEncAESSettings::ContentEncAESSettings() : cipher_mode_(kCTR) {}
  402. uint64_t ContentEncAESSettings::Size() const {
  403. const uint64_t payload = PayloadSize();
  404. const uint64_t size =
  405. EbmlMasterElementSize(libwebm::kMkvContentEncAESSettings, payload) +
  406. payload;
  407. return size;
  408. }
  409. bool ContentEncAESSettings::Write(IMkvWriter* writer) const {
  410. const uint64_t payload = PayloadSize();
  411. if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncAESSettings,
  412. payload))
  413. return false;
  414. const int64_t payload_position = writer->Position();
  415. if (payload_position < 0)
  416. return false;
  417. if (!WriteEbmlElement(writer, libwebm::kMkvAESSettingsCipherMode,
  418. static_cast<uint64>(cipher_mode_))) {
  419. return false;
  420. }
  421. const int64_t stop_position = writer->Position();
  422. if (stop_position < 0 ||
  423. stop_position - payload_position != static_cast<int64_t>(payload))
  424. return false;
  425. return true;
  426. }
  427. uint64_t ContentEncAESSettings::PayloadSize() const {
  428. uint64_t size = EbmlElementSize(libwebm::kMkvAESSettingsCipherMode,
  429. static_cast<uint64>(cipher_mode_));
  430. return size;
  431. }
  432. ///////////////////////////////////////////////////////////////
  433. //
  434. // ContentEncoding Class
  435. ContentEncoding::ContentEncoding()
  436. : enc_algo_(5),
  437. enc_key_id_(NULL),
  438. encoding_order_(0),
  439. encoding_scope_(1),
  440. encoding_type_(1),
  441. enc_key_id_length_(0) {}
  442. ContentEncoding::~ContentEncoding() { delete[] enc_key_id_; }
  443. bool ContentEncoding::SetEncryptionID(const uint8_t* id, uint64_t length) {
  444. if (!id || length < 1)
  445. return false;
  446. delete[] enc_key_id_;
  447. enc_key_id_ =
  448. new (std::nothrow) uint8_t[static_cast<size_t>(length)]; // NOLINT
  449. if (!enc_key_id_)
  450. return false;
  451. memcpy(enc_key_id_, id, static_cast<size_t>(length));
  452. enc_key_id_length_ = length;
  453. return true;
  454. }
  455. uint64_t ContentEncoding::Size() const {
  456. const uint64_t encryption_size = EncryptionSize();
  457. const uint64_t encoding_size = EncodingSize(0, encryption_size);
  458. const uint64_t encodings_size =
  459. EbmlMasterElementSize(libwebm::kMkvContentEncoding, encoding_size) +
  460. encoding_size;
  461. return encodings_size;
  462. }
  463. bool ContentEncoding::Write(IMkvWriter* writer) const {
  464. const uint64_t encryption_size = EncryptionSize();
  465. const uint64_t encoding_size = EncodingSize(0, encryption_size);
  466. const uint64_t size =
  467. EbmlMasterElementSize(libwebm::kMkvContentEncoding, encoding_size) +
  468. encoding_size;
  469. const int64_t payload_position = writer->Position();
  470. if (payload_position < 0)
  471. return false;
  472. if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncoding,
  473. encoding_size))
  474. return false;
  475. if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingOrder,
  476. static_cast<uint64>(encoding_order_)))
  477. return false;
  478. if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingScope,
  479. static_cast<uint64>(encoding_scope_)))
  480. return false;
  481. if (!WriteEbmlElement(writer, libwebm::kMkvContentEncodingType,
  482. static_cast<uint64>(encoding_type_)))
  483. return false;
  484. if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncryption,
  485. encryption_size))
  486. return false;
  487. if (!WriteEbmlElement(writer, libwebm::kMkvContentEncAlgo,
  488. static_cast<uint64>(enc_algo_))) {
  489. return false;
  490. }
  491. if (!WriteEbmlElement(writer, libwebm::kMkvContentEncKeyID, enc_key_id_,
  492. enc_key_id_length_))
  493. return false;
  494. if (!enc_aes_settings_.Write(writer))
  495. return false;
  496. const int64_t stop_position = writer->Position();
  497. if (stop_position < 0 ||
  498. stop_position - payload_position != static_cast<int64_t>(size))
  499. return false;
  500. return true;
  501. }
  502. uint64_t ContentEncoding::EncodingSize(uint64_t compresion_size,
  503. uint64_t encryption_size) const {
  504. // TODO(fgalligan): Add support for compression settings.
  505. if (compresion_size != 0)
  506. return 0;
  507. uint64_t encoding_size = 0;
  508. if (encryption_size > 0) {
  509. encoding_size +=
  510. EbmlMasterElementSize(libwebm::kMkvContentEncryption, encryption_size) +
  511. encryption_size;
  512. }
  513. encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingType,
  514. static_cast<uint64>(encoding_type_));
  515. encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingScope,
  516. static_cast<uint64>(encoding_scope_));
  517. encoding_size += EbmlElementSize(libwebm::kMkvContentEncodingOrder,
  518. static_cast<uint64>(encoding_order_));
  519. return encoding_size;
  520. }
  521. uint64_t ContentEncoding::EncryptionSize() const {
  522. const uint64_t aes_size = enc_aes_settings_.Size();
  523. uint64_t encryption_size = EbmlElementSize(libwebm::kMkvContentEncKeyID,
  524. enc_key_id_, enc_key_id_length_);
  525. encryption_size += EbmlElementSize(libwebm::kMkvContentEncAlgo,
  526. static_cast<uint64>(enc_algo_));
  527. return encryption_size + aes_size;
  528. }
  529. ///////////////////////////////////////////////////////////////
  530. //
  531. // Track Class
  532. Track::Track(unsigned int* seed)
  533. : codec_id_(NULL),
  534. codec_private_(NULL),
  535. language_(NULL),
  536. max_block_additional_id_(0),
  537. name_(NULL),
  538. number_(0),
  539. type_(0),
  540. uid_(MakeUID(seed)),
  541. codec_delay_(0),
  542. seek_pre_roll_(0),
  543. default_duration_(0),
  544. codec_private_length_(0),
  545. content_encoding_entries_(NULL),
  546. content_encoding_entries_size_(0) {}
  547. Track::~Track() {
  548. delete[] codec_id_;
  549. delete[] codec_private_;
  550. delete[] language_;
  551. delete[] name_;
  552. if (content_encoding_entries_) {
  553. for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) {
  554. ContentEncoding* const encoding = content_encoding_entries_[i];
  555. delete encoding;
  556. }
  557. delete[] content_encoding_entries_;
  558. }
  559. }
  560. bool Track::AddContentEncoding() {
  561. const uint32_t count = content_encoding_entries_size_ + 1;
  562. ContentEncoding** const content_encoding_entries =
  563. new (std::nothrow) ContentEncoding*[count]; // NOLINT
  564. if (!content_encoding_entries)
  565. return false;
  566. ContentEncoding* const content_encoding =
  567. new (std::nothrow) ContentEncoding(); // NOLINT
  568. if (!content_encoding) {
  569. delete[] content_encoding_entries;
  570. return false;
  571. }
  572. for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) {
  573. content_encoding_entries[i] = content_encoding_entries_[i];
  574. }
  575. delete[] content_encoding_entries_;
  576. content_encoding_entries_ = content_encoding_entries;
  577. content_encoding_entries_[content_encoding_entries_size_] = content_encoding;
  578. content_encoding_entries_size_ = count;
  579. return true;
  580. }
  581. ContentEncoding* Track::GetContentEncodingByIndex(uint32_t index) const {
  582. if (content_encoding_entries_ == NULL)
  583. return NULL;
  584. if (index >= content_encoding_entries_size_)
  585. return NULL;
  586. return content_encoding_entries_[index];
  587. }
  588. uint64_t Track::PayloadSize() const {
  589. uint64_t size =
  590. EbmlElementSize(libwebm::kMkvTrackNumber, static_cast<uint64>(number_));
  591. size += EbmlElementSize(libwebm::kMkvTrackUID, static_cast<uint64>(uid_));
  592. size += EbmlElementSize(libwebm::kMkvTrackType, static_cast<uint64>(type_));
  593. if (codec_id_)
  594. size += EbmlElementSize(libwebm::kMkvCodecID, codec_id_);
  595. if (codec_private_)
  596. size += EbmlElementSize(libwebm::kMkvCodecPrivate, codec_private_,
  597. codec_private_length_);
  598. if (language_)
  599. size += EbmlElementSize(libwebm::kMkvLanguage, language_);
  600. if (name_)
  601. size += EbmlElementSize(libwebm::kMkvName, name_);
  602. if (max_block_additional_id_) {
  603. size += EbmlElementSize(libwebm::kMkvMaxBlockAdditionID,
  604. static_cast<uint64>(max_block_additional_id_));
  605. }
  606. if (codec_delay_) {
  607. size += EbmlElementSize(libwebm::kMkvCodecDelay,
  608. static_cast<uint64>(codec_delay_));
  609. }
  610. if (seek_pre_roll_) {
  611. size += EbmlElementSize(libwebm::kMkvSeekPreRoll,
  612. static_cast<uint64>(seek_pre_roll_));
  613. }
  614. if (default_duration_) {
  615. size += EbmlElementSize(libwebm::kMkvDefaultDuration,
  616. static_cast<uint64>(default_duration_));
  617. }
  618. if (content_encoding_entries_size_ > 0) {
  619. uint64_t content_encodings_size = 0;
  620. for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) {
  621. ContentEncoding* const encoding = content_encoding_entries_[i];
  622. content_encodings_size += encoding->Size();
  623. }
  624. size += EbmlMasterElementSize(libwebm::kMkvContentEncodings,
  625. content_encodings_size) +
  626. content_encodings_size;
  627. }
  628. return size;
  629. }
  630. uint64_t Track::Size() const {
  631. uint64_t size = PayloadSize();
  632. size += EbmlMasterElementSize(libwebm::kMkvTrackEntry, size);
  633. return size;
  634. }
  635. bool Track::Write(IMkvWriter* writer) const {
  636. if (!writer)
  637. return false;
  638. // mandatory elements without a default value.
  639. if (!type_ || !codec_id_)
  640. return false;
  641. // |size| may be bigger than what is written out in this function because
  642. // derived classes may write out more data in the Track element.
  643. const uint64_t payload_size = PayloadSize();
  644. if (!WriteEbmlMasterElement(writer, libwebm::kMkvTrackEntry, payload_size))
  645. return false;
  646. uint64_t size =
  647. EbmlElementSize(libwebm::kMkvTrackNumber, static_cast<uint64>(number_));
  648. size += EbmlElementSize(libwebm::kMkvTrackUID, static_cast<uint64>(uid_));
  649. size += EbmlElementSize(libwebm::kMkvTrackType, static_cast<uint64>(type_));
  650. if (codec_id_)
  651. size += EbmlElementSize(libwebm::kMkvCodecID, codec_id_);
  652. if (codec_private_)
  653. size += EbmlElementSize(libwebm::kMkvCodecPrivate, codec_private_,
  654. static_cast<uint64>(codec_private_length_));
  655. if (language_)
  656. size += EbmlElementSize(libwebm::kMkvLanguage, language_);
  657. if (name_)
  658. size += EbmlElementSize(libwebm::kMkvName, name_);
  659. if (max_block_additional_id_)
  660. size += EbmlElementSize(libwebm::kMkvMaxBlockAdditionID,
  661. static_cast<uint64>(max_block_additional_id_));
  662. if (codec_delay_)
  663. size += EbmlElementSize(libwebm::kMkvCodecDelay,
  664. static_cast<uint64>(codec_delay_));
  665. if (seek_pre_roll_)
  666. size += EbmlElementSize(libwebm::kMkvSeekPreRoll,
  667. static_cast<uint64>(seek_pre_roll_));
  668. if (default_duration_)
  669. size += EbmlElementSize(libwebm::kMkvDefaultDuration,
  670. static_cast<uint64>(default_duration_));
  671. const int64_t payload_position = writer->Position();
  672. if (payload_position < 0)
  673. return false;
  674. if (!WriteEbmlElement(writer, libwebm::kMkvTrackNumber,
  675. static_cast<uint64>(number_)))
  676. return false;
  677. if (!WriteEbmlElement(writer, libwebm::kMkvTrackUID,
  678. static_cast<uint64>(uid_)))
  679. return false;
  680. if (!WriteEbmlElement(writer, libwebm::kMkvTrackType,
  681. static_cast<uint64>(type_)))
  682. return false;
  683. if (max_block_additional_id_) {
  684. if (!WriteEbmlElement(writer, libwebm::kMkvMaxBlockAdditionID,
  685. static_cast<uint64>(max_block_additional_id_))) {
  686. return false;
  687. }
  688. }
  689. if (codec_delay_) {
  690. if (!WriteEbmlElement(writer, libwebm::kMkvCodecDelay,
  691. static_cast<uint64>(codec_delay_)))
  692. return false;
  693. }
  694. if (seek_pre_roll_) {
  695. if (!WriteEbmlElement(writer, libwebm::kMkvSeekPreRoll,
  696. static_cast<uint64>(seek_pre_roll_)))
  697. return false;
  698. }
  699. if (default_duration_) {
  700. if (!WriteEbmlElement(writer, libwebm::kMkvDefaultDuration,
  701. static_cast<uint64>(default_duration_)))
  702. return false;
  703. }
  704. if (codec_id_) {
  705. if (!WriteEbmlElement(writer, libwebm::kMkvCodecID, codec_id_))
  706. return false;
  707. }
  708. if (codec_private_) {
  709. if (!WriteEbmlElement(writer, libwebm::kMkvCodecPrivate, codec_private_,
  710. static_cast<uint64>(codec_private_length_)))
  711. return false;
  712. }
  713. if (language_) {
  714. if (!WriteEbmlElement(writer, libwebm::kMkvLanguage, language_))
  715. return false;
  716. }
  717. if (name_) {
  718. if (!WriteEbmlElement(writer, libwebm::kMkvName, name_))
  719. return false;
  720. }
  721. int64_t stop_position = writer->Position();
  722. if (stop_position < 0 ||
  723. stop_position - payload_position != static_cast<int64_t>(size))
  724. return false;
  725. if (content_encoding_entries_size_ > 0) {
  726. uint64_t content_encodings_size = 0;
  727. for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) {
  728. ContentEncoding* const encoding = content_encoding_entries_[i];
  729. content_encodings_size += encoding->Size();
  730. }
  731. if (!WriteEbmlMasterElement(writer, libwebm::kMkvContentEncodings,
  732. content_encodings_size))
  733. return false;
  734. for (uint32_t i = 0; i < content_encoding_entries_size_; ++i) {
  735. ContentEncoding* const encoding = content_encoding_entries_[i];
  736. if (!encoding->Write(writer))
  737. return false;
  738. }
  739. }
  740. stop_position = writer->Position();
  741. if (stop_position < 0)
  742. return false;
  743. return true;
  744. }
  745. bool Track::SetCodecPrivate(const uint8_t* codec_private, uint64_t length) {
  746. if (!codec_private || length < 1)
  747. return false;
  748. delete[] codec_private_;
  749. codec_private_ =
  750. new (std::nothrow) uint8_t[static_cast<size_t>(length)]; // NOLINT
  751. if (!codec_private_)
  752. return false;
  753. memcpy(codec_private_, codec_private, static_cast<size_t>(length));
  754. codec_private_length_ = length;
  755. return true;
  756. }
  757. void Track::set_codec_id(const char* codec_id) {
  758. if (codec_id) {
  759. delete[] codec_id_;
  760. const size_t length = strlen(codec_id) + 1;
  761. codec_id_ = new (std::nothrow) char[length]; // NOLINT
  762. if (codec_id_) {
  763. #ifdef _MSC_VER
  764. strcpy_s(codec_id_, length, codec_id);
  765. #else
  766. strcpy(codec_id_, codec_id);
  767. #endif
  768. }
  769. }
  770. }
  771. // TODO(fgalligan): Vet the language parameter.
  772. void Track::set_language(const char* language) {
  773. if (language) {
  774. delete[] language_;
  775. const size_t length = strlen(language) + 1;
  776. language_ = new (std::nothrow) char[length]; // NOLINT
  777. if (language_) {
  778. #ifdef _MSC_VER
  779. strcpy_s(language_, length, language);
  780. #else
  781. strcpy(language_, language);
  782. #endif
  783. }
  784. }
  785. }
  786. void Track::set_name(const char* name) {
  787. if (name) {
  788. delete[] name_;
  789. const size_t length = strlen(name) + 1;
  790. name_ = new (std::nothrow) char[length]; // NOLINT
  791. if (name_) {
  792. #ifdef _MSC_VER
  793. strcpy_s(name_, length, name);
  794. #else
  795. strcpy(name_, name);
  796. #endif
  797. }
  798. }
  799. }
  800. ///////////////////////////////////////////////////////////////
  801. //
  802. // Colour and its child elements
  803. uint64_t PrimaryChromaticity::PrimaryChromaticitySize(
  804. libwebm::MkvId x_id, libwebm::MkvId y_id) const {
  805. return EbmlElementSize(x_id, x_) + EbmlElementSize(y_id, y_);
  806. }
  807. bool PrimaryChromaticity::Write(IMkvWriter* writer, libwebm::MkvId x_id,
  808. libwebm::MkvId y_id) const {
  809. if (!Valid()) {
  810. return false;
  811. }
  812. return WriteEbmlElement(writer, x_id, x_) &&
  813. WriteEbmlElement(writer, y_id, y_);
  814. }
  815. bool PrimaryChromaticity::Valid() const {
  816. return (x_ >= kChromaticityMin && x_ <= kChromaticityMax &&
  817. y_ >= kChromaticityMin && y_ <= kChromaticityMax);
  818. }
  819. uint64_t MasteringMetadata::MasteringMetadataSize() const {
  820. uint64_t size = PayloadSize();
  821. if (size > 0)
  822. size += EbmlMasterElementSize(libwebm::kMkvMasteringMetadata, size);
  823. return size;
  824. }
  825. bool MasteringMetadata::Valid() const {
  826. if (luminance_min_ != kValueNotPresent) {
  827. if (luminance_min_ < kMinLuminance || luminance_min_ > kMinLuminanceMax ||
  828. luminance_min_ > luminance_max_) {
  829. return false;
  830. }
  831. }
  832. if (luminance_max_ != kValueNotPresent) {
  833. if (luminance_max_ < kMinLuminance || luminance_max_ > kMaxLuminanceMax ||
  834. luminance_max_ < luminance_min_) {
  835. return false;
  836. }
  837. }
  838. if (r_ && !r_->Valid())
  839. return false;
  840. if (g_ && !g_->Valid())
  841. return false;
  842. if (b_ && !b_->Valid())
  843. return false;
  844. if (white_point_ && !white_point_->Valid())
  845. return false;
  846. return true;
  847. }
  848. bool MasteringMetadata::Write(IMkvWriter* writer) const {
  849. const uint64_t size = PayloadSize();
  850. // Don't write an empty element.
  851. if (size == 0)
  852. return true;
  853. if (!WriteEbmlMasterElement(writer, libwebm::kMkvMasteringMetadata, size))
  854. return false;
  855. if (luminance_max_ != kValueNotPresent &&
  856. !WriteEbmlElement(writer, libwebm::kMkvLuminanceMax, luminance_max_)) {
  857. return false;
  858. }
  859. if (luminance_min_ != kValueNotPresent &&
  860. !WriteEbmlElement(writer, libwebm::kMkvLuminanceMin, luminance_min_)) {
  861. return false;
  862. }
  863. if (r_ &&
  864. !r_->Write(writer, libwebm::kMkvPrimaryRChromaticityX,
  865. libwebm::kMkvPrimaryRChromaticityY)) {
  866. return false;
  867. }
  868. if (g_ &&
  869. !g_->Write(writer, libwebm::kMkvPrimaryGChromaticityX,
  870. libwebm::kMkvPrimaryGChromaticityY)) {
  871. return false;
  872. }
  873. if (b_ &&
  874. !b_->Write(writer, libwebm::kMkvPrimaryBChromaticityX,
  875. libwebm::kMkvPrimaryBChromaticityY)) {
  876. return false;
  877. }
  878. if (white_point_ &&
  879. !white_point_->Write(writer, libwebm::kMkvWhitePointChromaticityX,
  880. libwebm::kMkvWhitePointChromaticityY)) {
  881. return false;
  882. }
  883. return true;
  884. }
  885. bool MasteringMetadata::SetChromaticity(
  886. const PrimaryChromaticity* r, const PrimaryChromaticity* g,
  887. const PrimaryChromaticity* b, const PrimaryChromaticity* white_point) {
  888. PrimaryChromaticityPtr r_ptr(NULL);
  889. if (r) {
  890. if (!CopyChromaticity(r, &r_ptr))
  891. return false;
  892. }
  893. PrimaryChromaticityPtr g_ptr(NULL);
  894. if (g) {
  895. if (!CopyChromaticity(g, &g_ptr))
  896. return false;
  897. }
  898. PrimaryChromaticityPtr b_ptr(NULL);
  899. if (b) {
  900. if (!CopyChromaticity(b, &b_ptr))
  901. return false;
  902. }
  903. PrimaryChromaticityPtr wp_ptr(NULL);
  904. if (white_point) {
  905. if (!CopyChromaticity(white_point, &wp_ptr))
  906. return false;
  907. }
  908. r_ = r_ptr.release();
  909. g_ = g_ptr.release();
  910. b_ = b_ptr.release();
  911. white_point_ = wp_ptr.release();
  912. return true;
  913. }
  914. uint64_t MasteringMetadata::PayloadSize() const {
  915. uint64_t size = 0;
  916. if (luminance_max_ != kValueNotPresent)
  917. size += EbmlElementSize(libwebm::kMkvLuminanceMax, luminance_max_);
  918. if (luminance_min_ != kValueNotPresent)
  919. size += EbmlElementSize(libwebm::kMkvLuminanceMin, luminance_min_);
  920. if (r_) {
  921. size += r_->PrimaryChromaticitySize(libwebm::kMkvPrimaryRChromaticityX,
  922. libwebm::kMkvPrimaryRChromaticityY);
  923. }
  924. if (g_) {
  925. size += g_->PrimaryChromaticitySize(libwebm::kMkvPrimaryGChromaticityX,
  926. libwebm::kMkvPrimaryGChromaticityY);
  927. }
  928. if (b_) {
  929. size += b_->PrimaryChromaticitySize(libwebm::kMkvPrimaryBChromaticityX,
  930. libwebm::kMkvPrimaryBChromaticityY);
  931. }
  932. if (white_point_) {
  933. size += white_point_->PrimaryChromaticitySize(
  934. libwebm::kMkvWhitePointChromaticityX,
  935. libwebm::kMkvWhitePointChromaticityY);
  936. }
  937. return size;
  938. }
  939. uint64_t Colour::ColourSize() const {
  940. uint64_t size = PayloadSize();
  941. if (size > 0)
  942. size += EbmlMasterElementSize(libwebm::kMkvColour, size);
  943. return size;
  944. }
  945. bool Colour::Valid() const {
  946. if (mastering_metadata_ && !mastering_metadata_->Valid())
  947. return false;
  948. if (matrix_coefficients_ != kValueNotPresent &&
  949. !IsMatrixCoefficientsValueValid(matrix_coefficients_)) {
  950. return false;
  951. }
  952. if (chroma_siting_horz_ != kValueNotPresent &&
  953. !IsChromaSitingHorzValueValid(chroma_siting_horz_)) {
  954. return false;
  955. }
  956. if (chroma_siting_vert_ != kValueNotPresent &&
  957. !IsChromaSitingVertValueValid(chroma_siting_vert_)) {
  958. return false;
  959. }
  960. if (range_ != kValueNotPresent && !IsColourRangeValueValid(range_))
  961. return false;
  962. if (transfer_characteristics_ != kValueNotPresent &&
  963. !IsTransferCharacteristicsValueValid(transfer_characteristics_)) {
  964. return false;
  965. }
  966. if (primaries_ != kValueNotPresent && !IsPrimariesValueValid(primaries_))
  967. return false;
  968. return true;
  969. }
  970. bool Colour::Write(IMkvWriter* writer) const {
  971. const uint64_t size = PayloadSize();
  972. // Don't write an empty element.
  973. if (size == 0)
  974. return true;
  975. // Don't write an invalid element.
  976. if (!Valid())
  977. return false;
  978. if (!WriteEbmlMasterElement(writer, libwebm::kMkvColour, size))
  979. return false;
  980. if (matrix_coefficients_ != kValueNotPresent &&
  981. !WriteEbmlElement(writer, libwebm::kMkvMatrixCoefficients,
  982. static_cast<uint64>(matrix_coefficients_))) {
  983. return false;
  984. }
  985. if (bits_per_channel_ != kValueNotPresent &&
  986. !WriteEbmlElement(writer, libwebm::kMkvBitsPerChannel,
  987. static_cast<uint64>(bits_per_channel_))) {
  988. return false;
  989. }
  990. if (chroma_subsampling_horz_ != kValueNotPresent &&
  991. !WriteEbmlElement(writer, libwebm::kMkvChromaSubsamplingHorz,
  992. static_cast<uint64>(chroma_subsampling_horz_))) {
  993. return false;
  994. }
  995. if (chroma_subsampling_vert_ != kValueNotPresent &&
  996. !WriteEbmlElement(writer, libwebm::kMkvChromaSubsamplingVert,
  997. static_cast<uint64>(chroma_subsampling_vert_))) {
  998. return false;
  999. }
  1000. if (cb_subsampling_horz_ != kValueNotPresent &&
  1001. !WriteEbmlElement(writer, libwebm::kMkvCbSubsamplingHorz,
  1002. static_cast<uint64>(cb_subsampling_horz_))) {
  1003. return false;
  1004. }
  1005. if (cb_subsampling_vert_ != kValueNotPresent &&
  1006. !WriteEbmlElement(writer, libwebm::kMkvCbSubsamplingVert,
  1007. static_cast<uint64>(cb_subsampling_vert_))) {
  1008. return false;
  1009. }
  1010. if (chroma_siting_horz_ != kValueNotPresent &&
  1011. !WriteEbmlElement(writer, libwebm::kMkvChromaSitingHorz,
  1012. static_cast<uint64>(chroma_siting_horz_))) {
  1013. return false;
  1014. }
  1015. if (chroma_siting_vert_ != kValueNotPresent &&
  1016. !WriteEbmlElement(writer, libwebm::kMkvChromaSitingVert,
  1017. static_cast<uint64>(chroma_siting_vert_))) {
  1018. return false;
  1019. }
  1020. if (range_ != kValueNotPresent &&
  1021. !WriteEbmlElement(writer, libwebm::kMkvRange,
  1022. static_cast<uint64>(range_))) {
  1023. return false;
  1024. }
  1025. if (transfer_characteristics_ != kValueNotPresent &&
  1026. !WriteEbmlElement(writer, libwebm::kMkvTransferCharacteristics,
  1027. static_cast<uint64>(transfer_characteristics_))) {
  1028. return false;
  1029. }
  1030. if (primaries_ != kValueNotPresent &&
  1031. !WriteEbmlElement(writer, libwebm::kMkvPrimaries,
  1032. static_cast<uint64>(primaries_))) {
  1033. return false;
  1034. }
  1035. if (max_cll_ != kValueNotPresent &&
  1036. !WriteEbmlElement(writer, libwebm::kMkvMaxCLL,
  1037. static_cast<uint64>(max_cll_))) {
  1038. return false;
  1039. }
  1040. if (max_fall_ != kValueNotPresent &&
  1041. !WriteEbmlElement(writer, libwebm::kMkvMaxFALL,
  1042. static_cast<uint64>(max_fall_))) {
  1043. return false;
  1044. }
  1045. if (mastering_metadata_ && !mastering_metadata_->Write(writer))
  1046. return false;
  1047. return true;
  1048. }
  1049. bool Colour::SetMasteringMetadata(const MasteringMetadata& mastering_metadata) {
  1050. std::auto_ptr<MasteringMetadata> mm_ptr(new MasteringMetadata());
  1051. if (!mm_ptr.get())
  1052. return false;
  1053. mm_ptr->set_luminance_max(mastering_metadata.luminance_max());
  1054. mm_ptr->set_luminance_min(mastering_metadata.luminance_min());
  1055. if (!mm_ptr->SetChromaticity(mastering_metadata.r(), mastering_metadata.g(),
  1056. mastering_metadata.b(),
  1057. mastering_metadata.white_point())) {
  1058. return false;
  1059. }
  1060. delete mastering_metadata_;
  1061. mastering_metadata_ = mm_ptr.release();
  1062. return true;
  1063. }
  1064. uint64_t Colour::PayloadSize() const {
  1065. uint64_t size = 0;
  1066. if (matrix_coefficients_ != kValueNotPresent) {
  1067. size += EbmlElementSize(libwebm::kMkvMatrixCoefficients,
  1068. static_cast<uint64>(matrix_coefficients_));
  1069. }
  1070. if (bits_per_channel_ != kValueNotPresent) {
  1071. size += EbmlElementSize(libwebm::kMkvBitsPerChannel,
  1072. static_cast<uint64>(bits_per_channel_));
  1073. }
  1074. if (chroma_subsampling_horz_ != kValueNotPresent) {
  1075. size += EbmlElementSize(libwebm::kMkvChromaSubsamplingHorz,
  1076. static_cast<uint64>(chroma_subsampling_horz_));
  1077. }
  1078. if (chroma_subsampling_vert_ != kValueNotPresent) {
  1079. size += EbmlElementSize(libwebm::kMkvChromaSubsamplingVert,
  1080. static_cast<uint64>(chroma_subsampling_vert_));
  1081. }
  1082. if (cb_subsampling_horz_ != kValueNotPresent) {
  1083. size += EbmlElementSize(libwebm::kMkvCbSubsamplingHorz,
  1084. static_cast<uint64>(cb_subsampling_horz_));
  1085. }
  1086. if (cb_subsampling_vert_ != kValueNotPresent) {
  1087. size += EbmlElementSize(libwebm::kMkvCbSubsamplingVert,
  1088. static_cast<uint64>(cb_subsampling_vert_));
  1089. }
  1090. if (chroma_siting_horz_ != kValueNotPresent) {
  1091. size += EbmlElementSize(libwebm::kMkvChromaSitingHorz,
  1092. static_cast<uint64>(chroma_siting_horz_));
  1093. }
  1094. if (chroma_siting_vert_ != kValueNotPresent) {
  1095. size += EbmlElementSize(libwebm::kMkvChromaSitingVert,
  1096. static_cast<uint64>(chroma_siting_vert_));
  1097. }
  1098. if (range_ != kValueNotPresent) {
  1099. size += EbmlElementSize(libwebm::kMkvRange, static_cast<uint64>(range_));
  1100. }
  1101. if (transfer_characteristics_ != kValueNotPresent) {
  1102. size += EbmlElementSize(libwebm::kMkvTransferCharacteristics,
  1103. static_cast<uint64>(transfer_characteristics_));
  1104. }
  1105. if (primaries_ != kValueNotPresent) {
  1106. size += EbmlElementSize(libwebm::kMkvPrimaries,
  1107. static_cast<uint64>(primaries_));
  1108. }
  1109. if (max_cll_ != kValueNotPresent) {
  1110. size += EbmlElementSize(libwebm::kMkvMaxCLL, static_cast<uint64>(max_cll_));
  1111. }
  1112. if (max_fall_ != kValueNotPresent) {
  1113. size +=
  1114. EbmlElementSize(libwebm::kMkvMaxFALL, static_cast<uint64>(max_fall_));
  1115. }
  1116. if (mastering_metadata_)
  1117. size += mastering_metadata_->MasteringMetadataSize();
  1118. return size;
  1119. }
  1120. ///////////////////////////////////////////////////////////////
  1121. //
  1122. // Projection element
  1123. uint64_t Projection::ProjectionSize() const {
  1124. uint64_t size = PayloadSize();
  1125. if (size > 0)
  1126. size += EbmlMasterElementSize(libwebm::kMkvProjection, size);
  1127. return size;
  1128. }
  1129. bool Projection::Write(IMkvWriter* writer) const {
  1130. const uint64_t size = PayloadSize();
  1131. // Don't write an empty element.
  1132. if (size == 0)
  1133. return true;
  1134. if (!WriteEbmlMasterElement(writer, libwebm::kMkvProjection, size))
  1135. return false;
  1136. if (!WriteEbmlElement(writer, libwebm::kMkvProjectionType,
  1137. static_cast<uint64>(type_))) {
  1138. return false;
  1139. }
  1140. if (private_data_length_ > 0 && private_data_ != NULL &&
  1141. !WriteEbmlElement(writer, libwebm::kMkvProjectionPrivate, private_data_,
  1142. private_data_length_)) {
  1143. return false;
  1144. }
  1145. if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPoseYaw, pose_yaw_))
  1146. return false;
  1147. if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPosePitch,
  1148. pose_pitch_)) {
  1149. return false;
  1150. }
  1151. if (!WriteEbmlElement(writer, libwebm::kMkvProjectionPoseRoll, pose_roll_)) {
  1152. return false;
  1153. }
  1154. return true;
  1155. }
  1156. bool Projection::SetProjectionPrivate(const uint8_t* data,
  1157. uint64_t data_length) {
  1158. if (data == NULL || data_length == 0) {
  1159. return false;
  1160. }
  1161. if (data_length != static_cast<size_t>(data_length)) {
  1162. return false;
  1163. }
  1164. uint8_t* new_private_data =
  1165. new (std::nothrow) uint8_t[static_cast<size_t>(data_length)];
  1166. if (new_private_data == NULL) {
  1167. return false;
  1168. }
  1169. delete[] private_data_;
  1170. private_data_ = new_private_data;
  1171. private_data_length_ = data_length;
  1172. memcpy(private_data_, data, static_cast<size_t>(data_length));
  1173. return true;
  1174. }
  1175. uint64_t Projection::PayloadSize() const {
  1176. uint64_t size =
  1177. EbmlElementSize(libwebm::kMkvProjection, static_cast<uint64>(type_));
  1178. if (private_data_length_ > 0 && private_data_ != NULL) {
  1179. size += EbmlElementSize(libwebm::kMkvProjectionPrivate, private_data_,
  1180. private_data_length_);
  1181. }
  1182. size += EbmlElementSize(libwebm::kMkvProjectionPoseYaw, pose_yaw_);
  1183. size += EbmlElementSize(libwebm::kMkvProjectionPosePitch, pose_pitch_);
  1184. size += EbmlElementSize(libwebm::kMkvProjectionPoseRoll, pose_roll_);
  1185. return size;
  1186. }
  1187. ///////////////////////////////////////////////////////////////
  1188. //
  1189. // VideoTrack Class
  1190. VideoTrack::VideoTrack(unsigned int* seed)
  1191. : Track(seed),
  1192. display_height_(0),
  1193. display_width_(0),
  1194. pixel_height_(0),
  1195. pixel_width_(0),
  1196. crop_left_(0),
  1197. crop_right_(0),
  1198. crop_top_(0),
  1199. crop_bottom_(0),
  1200. frame_rate_(0.0),
  1201. height_(0),
  1202. stereo_mode_(0),
  1203. alpha_mode_(0),
  1204. width_(0),
  1205. colour_(NULL),
  1206. projection_(NULL) {}
  1207. VideoTrack::~VideoTrack() {
  1208. delete colour_;
  1209. delete projection_;
  1210. }
  1211. bool VideoTrack::SetStereoMode(uint64_t stereo_mode) {
  1212. if (stereo_mode != kMono && stereo_mode != kSideBySideLeftIsFirst &&
  1213. stereo_mode != kTopBottomRightIsFirst &&
  1214. stereo_mode != kTopBottomLeftIsFirst &&
  1215. stereo_mode != kSideBySideRightIsFirst)
  1216. return false;
  1217. stereo_mode_ = stereo_mode;
  1218. return true;
  1219. }
  1220. bool VideoTrack::SetAlphaMode(uint64_t alpha_mode) {
  1221. if (alpha_mode != kNoAlpha && alpha_mode != kAlpha)
  1222. return false;
  1223. alpha_mode_ = alpha_mode;
  1224. return true;
  1225. }
  1226. uint64_t VideoTrack::PayloadSize() const {
  1227. const uint64_t parent_size = Track::PayloadSize();
  1228. uint64_t size = VideoPayloadSize();
  1229. size += EbmlMasterElementSize(libwebm::kMkvVideo, size);
  1230. return parent_size + size;
  1231. }
  1232. bool VideoTrack::Write(IMkvWriter* writer) const {
  1233. if (!Track::Write(writer))
  1234. return false;
  1235. const uint64_t size = VideoPayloadSize();
  1236. if (!WriteEbmlMasterElement(writer, libwebm::kMkvVideo, size))
  1237. return false;
  1238. const int64_t payload_position = writer->Position();
  1239. if (payload_position < 0)
  1240. return false;
  1241. if (!WriteEbmlElement(
  1242. writer, libwebm::kMkvPixelWidth,
  1243. static_cast<uint64>((pixel_width_ > 0) ? pixel_width_ : width_)))
  1244. return false;
  1245. if (!WriteEbmlElement(
  1246. writer, libwebm::kMkvPixelHeight,
  1247. static_cast<uint64>((pixel_height_ > 0) ? pixel_height_ : height_)))
  1248. return false;
  1249. if (display_width_ > 0) {
  1250. if (!WriteEbmlElement(writer, libwebm::kMkvDisplayWidth,
  1251. static_cast<uint64>(display_width_)))
  1252. return false;
  1253. }
  1254. if (display_height_ > 0) {
  1255. if (!WriteEbmlElement(writer, libwebm::kMkvDisplayHeight,
  1256. static_cast<uint64>(display_height_)))
  1257. return false;
  1258. }
  1259. if (crop_left_ > 0) {
  1260. if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropLeft,
  1261. static_cast<uint64>(crop_left_)))
  1262. return false;
  1263. }
  1264. if (crop_right_ > 0) {
  1265. if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropRight,
  1266. static_cast<uint64>(crop_right_)))
  1267. return false;
  1268. }
  1269. if (crop_top_ > 0) {
  1270. if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropTop,
  1271. static_cast<uint64>(crop_top_)))
  1272. return false;
  1273. }
  1274. if (crop_bottom_ > 0) {
  1275. if (!WriteEbmlElement(writer, libwebm::kMkvPixelCropBottom,
  1276. static_cast<uint64>(crop_bottom_)))
  1277. return false;
  1278. }
  1279. if (stereo_mode_ > kMono) {
  1280. if (!WriteEbmlElement(writer, libwebm::kMkvStereoMode,
  1281. static_cast<uint64>(stereo_mode_)))
  1282. return false;
  1283. }
  1284. if (alpha_mode_ > kNoAlpha) {
  1285. if (!WriteEbmlElement(writer, libwebm::kMkvAlphaMode,
  1286. static_cast<uint64>(alpha_mode_)))
  1287. return false;
  1288. }
  1289. if (frame_rate_ > 0.0) {
  1290. if (!WriteEbmlElement(writer, libwebm::kMkvFrameRate,
  1291. static_cast<float>(frame_rate_))) {
  1292. return false;
  1293. }
  1294. }
  1295. if (colour_) {
  1296. if (!colour_->Write(writer))
  1297. return false;
  1298. }
  1299. if (projection_) {
  1300. if (!projection_->Write(writer))
  1301. return false;
  1302. }
  1303. const int64_t stop_position = writer->Position();
  1304. if (stop_position < 0 ||
  1305. stop_position - payload_position != static_cast<int64_t>(size)) {
  1306. return false;
  1307. }
  1308. return true;
  1309. }
  1310. bool VideoTrack::SetColour(const Colour& colour) {
  1311. std::auto_ptr<Colour> colour_ptr(new Colour());
  1312. if (!colour_ptr.get())
  1313. return false;
  1314. if (colour.mastering_metadata()) {
  1315. if (!colour_ptr->SetMasteringMetadata(*colour.mastering_metadata()))
  1316. return false;
  1317. }
  1318. colour_ptr->set_matrix_coefficients(colour.matrix_coefficients());
  1319. colour_ptr->set_bits_per_channel(colour.bits_per_channel());
  1320. colour_ptr->set_chroma_subsampling_horz(colour.chroma_subsampling_horz());
  1321. colour_ptr->set_chroma_subsampling_vert(colour.chroma_subsampling_vert());
  1322. colour_ptr->set_cb_subsampling_horz(colour.cb_subsampling_horz());
  1323. colour_ptr->set_cb_subsampling_vert(colour.cb_subsampling_vert());
  1324. colour_ptr->set_chroma_siting_horz(colour.chroma_siting_horz());
  1325. colour_ptr->set_chroma_siting_vert(colour.chroma_siting_vert());
  1326. colour_ptr->set_range(colour.range());
  1327. colour_ptr->set_transfer_characteristics(colour.transfer_characteristics());
  1328. colour_ptr->set_primaries(colour.primaries());
  1329. colour_ptr->set_max_cll(colour.max_cll());
  1330. colour_ptr->set_max_fall(colour.max_fall());
  1331. delete colour_;
  1332. colour_ = colour_ptr.release();
  1333. return true;
  1334. }
  1335. bool VideoTrack::SetProjection(const Projection& projection) {
  1336. std::auto_ptr<Projection> projection_ptr(new Projection());
  1337. if (!projection_ptr.get())
  1338. return false;
  1339. if (projection.private_data()) {
  1340. if (!projection_ptr->SetProjectionPrivate(
  1341. projection.private_data(), projection.private_data_length())) {
  1342. return false;
  1343. }
  1344. }
  1345. projection_ptr->set_type(projection.type());
  1346. projection_ptr->set_pose_yaw(projection.pose_yaw());
  1347. projection_ptr->set_pose_pitch(projection.pose_pitch());
  1348. projection_ptr->set_pose_roll(projection.pose_roll());
  1349. delete projection_;
  1350. projection_ = projection_ptr.release();
  1351. return true;
  1352. }
  1353. uint64_t VideoTrack::VideoPayloadSize() const {
  1354. uint64_t size = EbmlElementSize(
  1355. libwebm::kMkvPixelWidth,
  1356. static_cast<uint64>((pixel_width_ > 0) ? pixel_width_ : width_));
  1357. size += EbmlElementSize(
  1358. libwebm::kMkvPixelHeight,
  1359. static_cast<uint64>((pixel_height_ > 0) ? pixel_height_ : height_));
  1360. if (display_width_ > 0)
  1361. size += EbmlElementSize(libwebm::kMkvDisplayWidth,
  1362. static_cast<uint64>(display_width_));
  1363. if (display_height_ > 0)
  1364. size += EbmlElementSize(libwebm::kMkvDisplayHeight,
  1365. static_cast<uint64>(display_height_));
  1366. if (crop_left_ > 0)
  1367. size += EbmlElementSize(libwebm::kMkvPixelCropLeft,
  1368. static_cast<uint64>(crop_left_));
  1369. if (crop_right_ > 0)
  1370. size += EbmlElementSize(libwebm::kMkvPixelCropRight,
  1371. static_cast<uint64>(crop_right_));
  1372. if (crop_top_ > 0)
  1373. size += EbmlElementSize(libwebm::kMkvPixelCropTop,
  1374. static_cast<uint64>(crop_top_));
  1375. if (crop_bottom_ > 0)
  1376. size += EbmlElementSize(libwebm::kMkvPixelCropBottom,
  1377. static_cast<uint64>(crop_bottom_));
  1378. if (stereo_mode_ > kMono)
  1379. size += EbmlElementSize(libwebm::kMkvStereoMode,
  1380. static_cast<uint64>(stereo_mode_));
  1381. if (alpha_mode_ > kNoAlpha)
  1382. size += EbmlElementSize(libwebm::kMkvAlphaMode,
  1383. static_cast<uint64>(alpha_mode_));
  1384. if (frame_rate_ > 0.0)
  1385. size += EbmlElementSize(libwebm::kMkvFrameRate,
  1386. static_cast<float>(frame_rate_));
  1387. if (colour_)
  1388. size += colour_->ColourSize();
  1389. if (projection_)
  1390. size += projection_->ProjectionSize();
  1391. return size;
  1392. }
  1393. ///////////////////////////////////////////////////////////////
  1394. //
  1395. // AudioTrack Class
  1396. AudioTrack::AudioTrack(unsigned int* seed)
  1397. : Track(seed), bit_depth_(0), channels_(1), sample_rate_(0.0) {}
  1398. AudioTrack::~AudioTrack() {}
  1399. uint64_t AudioTrack::PayloadSize() const {
  1400. const uint64_t parent_size = Track::PayloadSize();
  1401. uint64_t size = EbmlElementSize(libwebm::kMkvSamplingFrequency,
  1402. static_cast<float>(sample_rate_));
  1403. size +=
  1404. EbmlElementSize(libwebm::kMkvChannels, static_cast<uint64>(channels_));
  1405. if (bit_depth_ > 0)
  1406. size +=
  1407. EbmlElementSize(libwebm::kMkvBitDepth, static_cast<uint64>(bit_depth_));
  1408. size += EbmlMasterElementSize(libwebm::kMkvAudio, size);
  1409. return parent_size + size;
  1410. }
  1411. bool AudioTrack::Write(IMkvWriter* writer) const {
  1412. if (!Track::Write(writer))
  1413. return false;
  1414. // Calculate AudioSettings size.
  1415. uint64_t size = EbmlElementSize(libwebm::kMkvSamplingFrequency,
  1416. static_cast<float>(sample_rate_));
  1417. size +=
  1418. EbmlElementSize(libwebm::kMkvChannels, static_cast<uint64>(channels_));
  1419. if (bit_depth_ > 0)
  1420. size +=
  1421. EbmlElementSize(libwebm::kMkvBitDepth, static_cast<uint64>(bit_depth_));
  1422. if (!WriteEbmlMasterElement(writer, libwebm::kMkvAudio, size))
  1423. return false;
  1424. const int64_t payload_position = writer->Position();
  1425. if (payload_position < 0)
  1426. return false;
  1427. if (!WriteEbmlElement(writer, libwebm::kMkvSamplingFrequency,
  1428. static_cast<float>(sample_rate_)))
  1429. return false;
  1430. if (!WriteEbmlElement(writer, libwebm::kMkvChannels,
  1431. static_cast<uint64>(channels_)))
  1432. return false;
  1433. if (bit_depth_ > 0)
  1434. if (!WriteEbmlElement(writer, libwebm::kMkvBitDepth,
  1435. static_cast<uint64>(bit_depth_)))
  1436. return false;
  1437. const int64_t stop_position = writer->Position();
  1438. if (stop_position < 0 ||
  1439. stop_position - payload_position != static_cast<int64_t>(size))
  1440. return false;
  1441. return true;
  1442. }
  1443. ///////////////////////////////////////////////////////////////
  1444. //
  1445. // Tracks Class
  1446. const char Tracks::kOpusCodecId[] = "A_OPUS";
  1447. const char Tracks::kVorbisCodecId[] = "A_VORBIS";
  1448. const char Tracks::kVp8CodecId[] = "V_VP8";
  1449. const char Tracks::kVp9CodecId[] = "V_VP9";
  1450. const char Tracks::kVp10CodecId[] = "V_VP10";
  1451. const char Tracks::kWebVttCaptionsId[] = "D_WEBVTT/CAPTIONS";
  1452. const char Tracks::kWebVttDescriptionsId[] = "D_WEBVTT/DESCRIPTIONS";
  1453. const char Tracks::kWebVttMetadataId[] = "D_WEBVTT/METADATA";
  1454. const char Tracks::kWebVttSubtitlesId[] = "D_WEBVTT/SUBTITLES";
  1455. Tracks::Tracks()
  1456. : track_entries_(NULL), track_entries_size_(0), wrote_tracks_(false) {}
  1457. Tracks::~Tracks() {
  1458. if (track_entries_) {
  1459. for (uint32_t i = 0; i < track_entries_size_; ++i) {
  1460. Track* const track = track_entries_[i];
  1461. delete track;
  1462. }
  1463. delete[] track_entries_;
  1464. }
  1465. }
  1466. bool Tracks::AddTrack(Track* track, int32_t number) {
  1467. if (number < 0 || wrote_tracks_)
  1468. return false;
  1469. // This muxer only supports track numbers in the range [1, 126], in
  1470. // order to be able (to use Matroska integer representation) to
  1471. // serialize the block header (of which the track number is a part)
  1472. // for a frame using exactly 4 bytes.
  1473. if (number > 0x7E)
  1474. return false;
  1475. uint32_t track_num = number;
  1476. if (track_num > 0) {
  1477. // Check to make sure a track does not already have |track_num|.
  1478. for (uint32_t i = 0; i < track_entries_size_; ++i) {
  1479. if (track_entries_[i]->number() == track_num)
  1480. return false;
  1481. }
  1482. }
  1483. const uint32_t count = track_entries_size_ + 1;
  1484. Track** const track_entries = new (std::nothrow) Track*[count]; // NOLINT
  1485. if (!track_entries)
  1486. return false;
  1487. for (uint32_t i = 0; i < track_entries_size_; ++i) {
  1488. track_entries[i] = track_entries_[i];
  1489. }
  1490. delete[] track_entries_;
  1491. // Find the lowest availible track number > 0.
  1492. if (track_num == 0) {
  1493. track_num = count;
  1494. // Check to make sure a track does not already have |track_num|.
  1495. bool exit = false;
  1496. do {
  1497. exit = true;
  1498. for (uint32_t i = 0; i < track_entries_size_; ++i) {
  1499. if (track_entries[i]->number() == track_num) {
  1500. track_num++;
  1501. exit = false;
  1502. break;
  1503. }
  1504. }
  1505. } while (!exit);
  1506. }
  1507. track->set_number(track_num);
  1508. track_entries_ = track_entries;
  1509. track_entries_[track_entries_size_] = track;
  1510. track_entries_size_ = count;
  1511. return true;
  1512. }
  1513. const Track* Tracks::GetTrackByIndex(uint32_t index) const {
  1514. if (track_entries_ == NULL)
  1515. return NULL;
  1516. if (index >= track_entries_size_)
  1517. return NULL;
  1518. return track_entries_[index];
  1519. }
  1520. Track* Tracks::GetTrackByNumber(uint64_t track_number) const {
  1521. const int32_t count = track_entries_size();
  1522. for (int32_t i = 0; i < count; ++i) {
  1523. if (track_entries_[i]->number() == track_number)
  1524. return track_entries_[i];
  1525. }
  1526. return NULL;
  1527. }
  1528. bool Tracks::TrackIsAudio(uint64_t track_number) const {
  1529. const Track* const track = GetTrackByNumber(track_number);
  1530. if (track->type() == kAudio)
  1531. return true;
  1532. return false;
  1533. }
  1534. bool Tracks::TrackIsVideo(uint64_t track_number) const {
  1535. const Track* const track = GetTrackByNumber(track_number);
  1536. if (track->type() == kVideo)
  1537. return true;
  1538. return false;
  1539. }
  1540. bool Tracks::Write(IMkvWriter* writer) const {
  1541. uint64_t size = 0;
  1542. const int32_t count = track_entries_size();
  1543. for (int32_t i = 0; i < count; ++i) {
  1544. const Track* const track = GetTrackByIndex(i);
  1545. if (!track)
  1546. return false;
  1547. size += track->Size();
  1548. }
  1549. if (!WriteEbmlMasterElement(writer, libwebm::kMkvTracks, size))
  1550. return false;
  1551. const int64_t payload_position = writer->Position();
  1552. if (payload_position < 0)
  1553. return false;
  1554. for (int32_t i = 0; i < count; ++i) {
  1555. const Track* const track = GetTrackByIndex(i);
  1556. if (!track->Write(writer))
  1557. return false;
  1558. }
  1559. const int64_t stop_position = writer->Position();
  1560. if (stop_position < 0 ||
  1561. stop_position - payload_position != static_cast<int64_t>(size))
  1562. return false;
  1563. wrote_tracks_ = true;
  1564. return true;
  1565. }
  1566. ///////////////////////////////////////////////////////////////
  1567. //
  1568. // Chapter Class
  1569. bool Chapter::set_id(const char* id) { return StrCpy(id, &id_); }
  1570. void Chapter::set_time(const Segment& segment, uint64_t start_ns,
  1571. uint64_t end_ns) {
  1572. const SegmentInfo* const info = segment.GetSegmentInfo();
  1573. const uint64_t timecode_scale = info->timecode_scale();
  1574. start_timecode_ = start_ns / timecode_scale;
  1575. end_timecode_ = end_ns / timecode_scale;
  1576. }
  1577. bool Chapter::add_string(const char* title, const char* language,
  1578. const char* country) {
  1579. if (!ExpandDisplaysArray())
  1580. return false;
  1581. Display& d = displays_[displays_count_++];
  1582. d.Init();
  1583. if (!d.set_title(title))
  1584. return false;
  1585. if (!d.set_language(language))
  1586. return false;
  1587. if (!d.set_country(country))
  1588. return false;
  1589. return true;
  1590. }
  1591. Chapter::Chapter() {
  1592. // This ctor only constructs the object. Proper initialization is
  1593. // done in Init() (called in Chapters::AddChapter()). The only
  1594. // reason we bother implementing this ctor is because we had to
  1595. // declare it as private (along with the dtor), in order to prevent
  1596. // clients from creating Chapter instances (a privelege we grant
  1597. // only to the Chapters class). Doing no initialization here also
  1598. // means that creating arrays of chapter objects is more efficient,
  1599. // because we only initialize each new chapter object as it becomes
  1600. // active on the array.
  1601. }
  1602. Chapter::~Chapter() {}
  1603. void Chapter::Init(unsigned int* seed) {
  1604. id_ = NULL;
  1605. start_timecode_ = 0;
  1606. end_timecode_ = 0;
  1607. displays_ = NULL;
  1608. displays_size_ = 0;
  1609. displays_count_ = 0;
  1610. uid_ = MakeUID(seed);
  1611. }
  1612. void Chapter::ShallowCopy(Chapter* dst) const {
  1613. dst->id_ = id_;
  1614. dst->start_timecode_ = start_timecode_;
  1615. dst->end_timecode_ = end_timecode_;
  1616. dst->uid_ = uid_;
  1617. dst->displays_ = displays_;
  1618. dst->displays_size_ = displays_size_;
  1619. dst->displays_count_ = displays_count_;
  1620. }
  1621. void Chapter::Clear() {
  1622. StrCpy(NULL, &id_);
  1623. while (displays_count_ > 0) {
  1624. Display& d = displays_[--displays_count_];
  1625. d.Clear();
  1626. }
  1627. delete[] displays_;
  1628. displays_ = NULL;
  1629. displays_size_ = 0;
  1630. }
  1631. bool Chapter::ExpandDisplaysArray() {
  1632. if (displays_size_ > displays_count_)
  1633. return true; // nothing to do yet
  1634. const int size = (displays_size_ == 0) ? 1 : 2 * displays_size_;
  1635. Display* const displays = new (std::nothrow) Display[size]; // NOLINT
  1636. if (displays == NULL)
  1637. return false;
  1638. for (int idx = 0; idx < displays_count_; ++idx) {
  1639. displays[idx] = displays_[idx]; // shallow copy
  1640. }
  1641. delete[] displays_;
  1642. displays_ = displays;
  1643. displays_size_ = size;
  1644. return true;
  1645. }
  1646. uint64_t Chapter::WriteAtom(IMkvWriter* writer) const {
  1647. uint64_t payload_size =
  1648. EbmlElementSize(libwebm::kMkvChapterStringUID, id_) +
  1649. EbmlElementSize(libwebm::kMkvChapterUID, static_cast<uint64>(uid_)) +
  1650. EbmlElementSize(libwebm::kMkvChapterTimeStart,
  1651. static_cast<uint64>(start_timecode_)) +
  1652. EbmlElementSize(libwebm::kMkvChapterTimeEnd,
  1653. static_cast<uint64>(end_timecode_));
  1654. for (int idx = 0; idx < displays_count_; ++idx) {
  1655. const Display& d = displays_[idx];
  1656. payload_size += d.WriteDisplay(NULL);
  1657. }
  1658. const uint64_t atom_size =
  1659. EbmlMasterElementSize(libwebm::kMkvChapterAtom, payload_size) +
  1660. payload_size;
  1661. if (writer == NULL)
  1662. return atom_size;
  1663. const int64_t start = writer->Position();
  1664. if (!WriteEbmlMasterElement(writer, libwebm::kMkvChapterAtom, payload_size))
  1665. return 0;
  1666. if (!WriteEbmlElement(writer, libwebm::kMkvChapterStringUID, id_))
  1667. return 0;
  1668. if (!WriteEbmlElement(writer, libwebm::kMkvChapterUID,
  1669. static_cast<uint64>(uid_)))
  1670. return 0;
  1671. if (!WriteEbmlElement(writer, libwebm::kMkvChapterTimeStart,
  1672. static_cast<uint64>(start_timecode_)))
  1673. return 0;
  1674. if (!WriteEbmlElement(writer, libwebm::kMkvChapterTimeEnd,
  1675. static_cast<uint64>(end_timecode_)))
  1676. return 0;
  1677. for (int idx = 0; idx < displays_count_; ++idx) {
  1678. const Display& d = displays_[idx];
  1679. if (!d.WriteDisplay(writer))
  1680. return 0;
  1681. }
  1682. const int64_t stop = writer->Position();
  1683. if (stop >= start && uint64_t(stop - start) != atom_size)
  1684. return 0;
  1685. return atom_size;
  1686. }
  1687. void Chapter::Display::Init() {
  1688. title_ = NULL;
  1689. language_ = NULL;
  1690. country_ = NULL;
  1691. }
  1692. void Chapter::Display::Clear() {
  1693. StrCpy(NULL, &title_);
  1694. StrCpy(NULL, &language_);
  1695. StrCpy(NULL, &country_);
  1696. }
  1697. bool Chapter::Display::set_title(const char* title) {
  1698. return StrCpy(title, &title_);
  1699. }
  1700. bool Chapter::Display::set_language(const char* language) {
  1701. return StrCpy(language, &language_);
  1702. }
  1703. bool Chapter::Display::set_country(const char* country) {
  1704. return StrCpy(country, &country_);
  1705. }
  1706. uint64_t Chapter::Display::WriteDisplay(IMkvWriter* writer) const {
  1707. uint64_t payload_size = EbmlElementSize(libwebm::kMkvChapString, title_);
  1708. if (language_)
  1709. payload_size += EbmlElementSize(libwebm::kMkvChapLanguage, language_);
  1710. if (country_)
  1711. payload_size += EbmlElementSize(libwebm::kMkvChapCountry, country_);
  1712. const uint64_t display_size =
  1713. EbmlMasterElementSize(libwebm::kMkvChapterDisplay, payload_size) +
  1714. payload_size;
  1715. if (writer == NULL)
  1716. return display_size;
  1717. const int64_t start = writer->Position();
  1718. if (!WriteEbmlMasterElement(writer, libwebm::kMkvChapterDisplay,
  1719. payload_size))
  1720. return 0;
  1721. if (!WriteEbmlElement(writer, libwebm::kMkvChapString, title_))
  1722. return 0;
  1723. if (language_) {
  1724. if (!WriteEbmlElement(writer, libwebm::kMkvChapLanguage, language_))
  1725. return 0;
  1726. }
  1727. if (country_) {
  1728. if (!WriteEbmlElement(writer, libwebm::kMkvChapCountry, country_))
  1729. return 0;
  1730. }
  1731. const int64_t stop = writer->Position();
  1732. if (stop >= start && uint64_t(stop - start) != display_size)
  1733. return 0;
  1734. return display_size;
  1735. }
  1736. ///////////////////////////////////////////////////////////////
  1737. //
  1738. // Chapters Class
  1739. Chapters::Chapters() : chapters_size_(0), chapters_count_(0), chapters_(NULL) {}
  1740. Chapters::~Chapters() {
  1741. while (chapters_count_ > 0) {
  1742. Chapter& chapter = chapters_[--chapters_count_];
  1743. chapter.Clear();
  1744. }
  1745. delete[] chapters_;
  1746. chapters_ = NULL;
  1747. }
  1748. int Chapters::Count() const { return chapters_count_; }
  1749. Chapter* Chapters::AddChapter(unsigned int* seed) {
  1750. if (!ExpandChaptersArray())
  1751. return NULL;
  1752. Chapter& chapter = chapters_[chapters_count_++];
  1753. chapter.Init(seed);
  1754. return &chapter;
  1755. }
  1756. bool Chapters::Write(IMkvWriter* writer) const {
  1757. if (writer == NULL)
  1758. return false;
  1759. const uint64_t payload_size = WriteEdition(NULL); // return size only
  1760. if (!WriteEbmlMasterElement(writer, libwebm::kMkvChapters, payload_size))
  1761. return false;
  1762. const int64_t start = writer->Position();
  1763. if (WriteEdition(writer) == 0) // error
  1764. return false;
  1765. const int64_t stop = writer->Position();
  1766. if (stop >= start && uint64_t(stop - start) != payload_size)
  1767. return false;
  1768. return true;
  1769. }
  1770. bool Chapters::ExpandChaptersArray() {
  1771. if (chapters_size_ > chapters_count_)
  1772. return true; // nothing to do yet
  1773. const int size = (chapters_size_ == 0) ? 1 : 2 * chapters_size_;
  1774. Chapter* const chapters = new (std::nothrow) Chapter[size]; // NOLINT
  1775. if (chapters == NULL)
  1776. return false;
  1777. for (int idx = 0; idx < chapters_count_; ++idx) {
  1778. const Chapter& src = chapters_[idx];
  1779. Chapter* const dst = chapters + idx;
  1780. src.ShallowCopy(dst);
  1781. }
  1782. delete[] chapters_;
  1783. chapters_ = chapters;
  1784. chapters_size_ = size;
  1785. return true;
  1786. }
  1787. uint64_t Chapters::WriteEdition(IMkvWriter* writer) const {
  1788. uint64_t payload_size = 0;
  1789. for (int idx = 0; idx < chapters_count_; ++idx) {
  1790. const Chapter& chapter = chapters_[idx];
  1791. payload_size += chapter.WriteAtom(NULL);
  1792. }
  1793. const uint64_t edition_size =
  1794. EbmlMasterElementSize(libwebm::kMkvEditionEntry, payload_size) +
  1795. payload_size;
  1796. if (writer == NULL) // return size only
  1797. return edition_size;
  1798. const int64_t start = writer->Position();
  1799. if (!WriteEbmlMasterElement(writer, libwebm::kMkvEditionEntry, payload_size))
  1800. return 0; // error
  1801. for (int idx = 0; idx < chapters_count_; ++idx) {
  1802. const Chapter& chapter = chapters_[idx];
  1803. const uint64_t chapter_size = chapter.WriteAtom(writer);
  1804. if (chapter_size == 0) // error
  1805. return 0;
  1806. }
  1807. const int64_t stop = writer->Position();
  1808. if (stop >= start && uint64_t(stop - start) != edition_size)
  1809. return 0;
  1810. return edition_size;
  1811. }
  1812. // Tag Class
  1813. bool Tag::add_simple_tag(const char* tag_name, const char* tag_string) {
  1814. if (!ExpandSimpleTagsArray())
  1815. return false;
  1816. SimpleTag& st = simple_tags_[simple_tags_count_++];
  1817. st.Init();
  1818. if (!st.set_tag_name(tag_name))
  1819. return false;
  1820. if (!st.set_tag_string(tag_string))
  1821. return false;
  1822. return true;
  1823. }
  1824. Tag::Tag() {
  1825. simple_tags_ = NULL;
  1826. simple_tags_size_ = 0;
  1827. simple_tags_count_ = 0;
  1828. }
  1829. Tag::~Tag() {}
  1830. void Tag::ShallowCopy(Tag* dst) const {
  1831. dst->simple_tags_ = simple_tags_;
  1832. dst->simple_tags_size_ = simple_tags_size_;
  1833. dst->simple_tags_count_ = simple_tags_count_;
  1834. }
  1835. void Tag::Clear() {
  1836. while (simple_tags_count_ > 0) {
  1837. SimpleTag& st = simple_tags_[--simple_tags_count_];
  1838. st.Clear();
  1839. }
  1840. delete[] simple_tags_;
  1841. simple_tags_ = NULL;
  1842. simple_tags_size_ = 0;
  1843. }
  1844. bool Tag::ExpandSimpleTagsArray() {
  1845. if (simple_tags_size_ > simple_tags_count_)
  1846. return true; // nothing to do yet
  1847. const int size = (simple_tags_size_ == 0) ? 1 : 2 * simple_tags_size_;
  1848. SimpleTag* const simple_tags = new (std::nothrow) SimpleTag[size]; // NOLINT
  1849. if (simple_tags == NULL)
  1850. return false;
  1851. for (int idx = 0; idx < simple_tags_count_; ++idx) {
  1852. simple_tags[idx] = simple_tags_[idx]; // shallow copy
  1853. }
  1854. delete[] simple_tags_;
  1855. simple_tags_ = simple_tags;
  1856. simple_tags_size_ = size;
  1857. return true;
  1858. }
  1859. uint64_t Tag::Write(IMkvWriter* writer) const {
  1860. uint64_t payload_size = 0;
  1861. for (int idx = 0; idx < simple_tags_count_; ++idx) {
  1862. const SimpleTag& st = simple_tags_[idx];
  1863. payload_size += st.Write(NULL);
  1864. }
  1865. const uint64_t tag_size =
  1866. EbmlMasterElementSize(libwebm::kMkvTag, payload_size) + payload_size;
  1867. if (writer == NULL)
  1868. return tag_size;
  1869. const int64_t start = writer->Position();
  1870. if (!WriteEbmlMasterElement(writer, libwebm::kMkvTag, payload_size))
  1871. return 0;
  1872. for (int idx = 0; idx < simple_tags_count_; ++idx) {
  1873. const SimpleTag& st = simple_tags_[idx];
  1874. if (!st.Write(writer))
  1875. return 0;
  1876. }
  1877. const int64_t stop = writer->Position();
  1878. if (stop >= start && uint64_t(stop - start) != tag_size)
  1879. return 0;
  1880. return tag_size;
  1881. }
  1882. // Tag::SimpleTag
  1883. void Tag::SimpleTag::Init() {
  1884. tag_name_ = NULL;
  1885. tag_string_ = NULL;
  1886. }
  1887. void Tag::SimpleTag::Clear() {
  1888. StrCpy(NULL, &tag_name_);
  1889. StrCpy(NULL, &tag_string_);
  1890. }
  1891. bool Tag::SimpleTag::set_tag_name(const char* tag_name) {
  1892. return StrCpy(tag_name, &tag_name_);
  1893. }
  1894. bool Tag::SimpleTag::set_tag_string(const char* tag_string) {
  1895. return StrCpy(tag_string, &tag_string_);
  1896. }
  1897. uint64_t Tag::SimpleTag::Write(IMkvWriter* writer) const {
  1898. uint64_t payload_size = EbmlElementSize(libwebm::kMkvTagName, tag_name_);
  1899. payload_size += EbmlElementSize(libwebm::kMkvTagString, tag_string_);
  1900. const uint64_t simple_tag_size =
  1901. EbmlMasterElementSize(libwebm::kMkvSimpleTag, payload_size) +
  1902. payload_size;
  1903. if (writer == NULL)
  1904. return simple_tag_size;
  1905. const int64_t start = writer->Position();
  1906. if (!WriteEbmlMasterElement(writer, libwebm::kMkvSimpleTag, payload_size))
  1907. return 0;
  1908. if (!WriteEbmlElement(writer, libwebm::kMkvTagName, tag_name_))
  1909. return 0;
  1910. if (!WriteEbmlElement(writer, libwebm::kMkvTagString, tag_string_))
  1911. return 0;
  1912. const int64_t stop = writer->Position();
  1913. if (stop >= start && uint64_t(stop - start) != simple_tag_size)
  1914. return 0;
  1915. return simple_tag_size;
  1916. }
  1917. // Tags Class
  1918. Tags::Tags() : tags_size_(0), tags_count_(0), tags_(NULL) {}
  1919. Tags::~Tags() {
  1920. while (tags_count_ > 0) {
  1921. Tag& tag = tags_[--tags_count_];
  1922. tag.Clear();
  1923. }
  1924. delete[] tags_;
  1925. tags_ = NULL;
  1926. }
  1927. int Tags::Count() const { return tags_count_; }
  1928. Tag* Tags::AddTag() {
  1929. if (!ExpandTagsArray())
  1930. return NULL;
  1931. Tag& tag = tags_[tags_count_++];
  1932. return &tag;
  1933. }
  1934. bool Tags::Write(IMkvWriter* writer) const {
  1935. if (writer == NULL)
  1936. return false;
  1937. uint64_t payload_size = 0;
  1938. for (int idx = 0; idx < tags_count_; ++idx) {
  1939. const Tag& tag = tags_[idx];
  1940. payload_size += tag.Write(NULL);
  1941. }
  1942. if (!WriteEbmlMasterElement(writer, libwebm::kMkvTags, payload_size))
  1943. return false;
  1944. const int64_t start = writer->Position();
  1945. for (int idx = 0; idx < tags_count_; ++idx) {
  1946. const Tag& tag = tags_[idx];
  1947. const uint64_t tag_size = tag.Write(writer);
  1948. if (tag_size == 0) // error
  1949. return 0;
  1950. }
  1951. const int64_t stop = writer->Position();
  1952. if (stop >= start && uint64_t(stop - start) != payload_size)
  1953. return false;
  1954. return true;
  1955. }
  1956. bool Tags::ExpandTagsArray() {
  1957. if (tags_size_ > tags_count_)
  1958. return true; // nothing to do yet
  1959. const int size = (tags_size_ == 0) ? 1 : 2 * tags_size_;
  1960. Tag* const tags = new (std::nothrow) Tag[size]; // NOLINT
  1961. if (tags == NULL)
  1962. return false;
  1963. for (int idx = 0; idx < tags_count_; ++idx) {
  1964. const Tag& src = tags_[idx];
  1965. Tag* const dst = tags + idx;
  1966. src.ShallowCopy(dst);
  1967. }
  1968. delete[] tags_;
  1969. tags_ = tags;
  1970. tags_size_ = size;
  1971. return true;
  1972. }
  1973. ///////////////////////////////////////////////////////////////
  1974. //
  1975. // Cluster class
  1976. Cluster::Cluster(uint64_t timecode, int64_t cues_pos, uint64_t timecode_scale,
  1977. bool write_last_frame_with_duration, bool fixed_size_timecode)
  1978. : blocks_added_(0),
  1979. finalized_(false),
  1980. fixed_size_timecode_(fixed_size_timecode),
  1981. header_written_(false),
  1982. payload_size_(0),
  1983. position_for_cues_(cues_pos),
  1984. size_position_(-1),
  1985. timecode_(timecode),
  1986. timecode_scale_(timecode_scale),
  1987. write_last_frame_with_duration_(write_last_frame_with_duration),
  1988. writer_(NULL) {}
  1989. Cluster::~Cluster() {
  1990. // Delete any stored frames that are left behind. This will happen if the
  1991. // Cluster was not Finalized for whatever reason.
  1992. while (!stored_frames_.empty()) {
  1993. while (!stored_frames_.begin()->second.empty()) {
  1994. delete stored_frames_.begin()->second.front();
  1995. stored_frames_.begin()->second.pop_front();
  1996. }
  1997. stored_frames_.erase(stored_frames_.begin()->first);
  1998. }
  1999. }
  2000. bool Cluster::Init(IMkvWriter* ptr_writer) {
  2001. if (!ptr_writer) {
  2002. return false;
  2003. }
  2004. writer_ = ptr_writer;
  2005. return true;
  2006. }
  2007. bool Cluster::AddFrame(const Frame* const frame) {
  2008. return QueueOrWriteFrame(frame);
  2009. }
  2010. bool Cluster::AddFrame(const uint8_t* data, uint64_t length,
  2011. uint64_t track_number, uint64_t abs_timecode,
  2012. bool is_key) {
  2013. Frame frame;
  2014. if (!frame.Init(data, length))
  2015. return false;
  2016. frame.set_track_number(track_number);
  2017. frame.set_timestamp(abs_timecode);
  2018. frame.set_is_key(is_key);
  2019. return QueueOrWriteFrame(&frame);
  2020. }
  2021. bool Cluster::AddFrameWithAdditional(const uint8_t* data, uint64_t length,
  2022. const uint8_t* additional,
  2023. uint64_t additional_length,
  2024. uint64_t add_id, uint64_t track_number,
  2025. uint64_t abs_timecode, bool is_key) {
  2026. if (!additional || additional_length == 0) {
  2027. return false;
  2028. }
  2029. Frame frame;
  2030. if (!frame.Init(data, length) ||
  2031. !frame.AddAdditionalData(additional, additional_length, add_id)) {
  2032. return false;
  2033. }
  2034. frame.set_track_number(track_number);
  2035. frame.set_timestamp(abs_timecode);
  2036. frame.set_is_key(is_key);
  2037. return QueueOrWriteFrame(&frame);
  2038. }
  2039. bool Cluster::AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length,
  2040. int64_t discard_padding,
  2041. uint64_t track_number,
  2042. uint64_t abs_timecode, bool is_key) {
  2043. Frame frame;
  2044. if (!frame.Init(data, length))
  2045. return false;
  2046. frame.set_discard_padding(discard_padding);
  2047. frame.set_track_number(track_number);
  2048. frame.set_timestamp(abs_timecode);
  2049. frame.set_is_key(is_key);
  2050. return QueueOrWriteFrame(&frame);
  2051. }
  2052. bool Cluster::AddMetadata(const uint8_t* data, uint64_t length,
  2053. uint64_t track_number, uint64_t abs_timecode,
  2054. uint64_t duration_timecode) {
  2055. Frame frame;
  2056. if (!frame.Init(data, length))
  2057. return false;
  2058. frame.set_track_number(track_number);
  2059. frame.set_timestamp(abs_timecode);
  2060. frame.set_duration(duration_timecode);
  2061. frame.set_is_key(true); // All metadata blocks are keyframes.
  2062. return QueueOrWriteFrame(&frame);
  2063. }
  2064. void Cluster::AddPayloadSize(uint64_t size) { payload_size_ += size; }
  2065. bool Cluster::Finalize() {
  2066. return !write_last_frame_with_duration_ && Finalize(false, 0);
  2067. }
  2068. bool Cluster::Finalize(bool set_last_frame_duration, uint64_t duration) {
  2069. if (!writer_ || finalized_)
  2070. return false;
  2071. if (write_last_frame_with_duration_) {
  2072. // Write out held back Frames. This essentially performs a k-way merge
  2073. // across all tracks in the increasing order of timestamps.
  2074. while (!stored_frames_.empty()) {
  2075. Frame* frame = stored_frames_.begin()->second.front();
  2076. // Get the next frame to write (frame with least timestamp across all
  2077. // tracks).
  2078. for (FrameMapIterator frames_iterator = ++stored_frames_.begin();
  2079. frames_iterator != stored_frames_.end(); ++frames_iterator) {
  2080. if (frames_iterator->second.front()->timestamp() < frame->timestamp()) {
  2081. frame = frames_iterator->second.front();
  2082. }
  2083. }
  2084. // Set the duration if it's the last frame for the track.
  2085. if (set_last_frame_duration &&
  2086. stored_frames_[frame->track_number()].size() == 1 &&
  2087. !frame->duration_set()) {
  2088. frame->set_duration(duration - frame->timestamp());
  2089. if (!frame->is_key() && !frame->reference_block_timestamp_set()) {
  2090. frame->set_reference_block_timestamp(
  2091. last_block_timestamp_[frame->track_number()]);
  2092. }
  2093. }
  2094. // Write the frame and remove it from |stored_frames_|.
  2095. const bool wrote_frame = DoWriteFrame(frame);
  2096. stored_frames_[frame->track_number()].pop_front();
  2097. if (stored_frames_[frame->track_number()].empty()) {
  2098. stored_frames_.erase(frame->track_number());
  2099. }
  2100. delete frame;
  2101. if (!wrote_frame)
  2102. return false;
  2103. }
  2104. }
  2105. if (size_position_ == -1)
  2106. return false;
  2107. if (writer_->Seekable()) {
  2108. const int64_t pos = writer_->Position();
  2109. if (writer_->Position(size_position_))
  2110. return false;
  2111. if (WriteUIntSize(writer_, payload_size(), 8))
  2112. return false;
  2113. if (writer_->Position(pos))
  2114. return false;
  2115. }
  2116. finalized_ = true;
  2117. return true;
  2118. }
  2119. uint64_t Cluster::Size() const {
  2120. const uint64_t element_size =
  2121. EbmlMasterElementSize(libwebm::kMkvCluster, 0xFFFFFFFFFFFFFFFFULL) +
  2122. payload_size_;
  2123. return element_size;
  2124. }
  2125. bool Cluster::PreWriteBlock() {
  2126. if (finalized_)
  2127. return false;
  2128. if (!header_written_) {
  2129. if (!WriteClusterHeader())
  2130. return false;
  2131. }
  2132. return true;
  2133. }
  2134. void Cluster::PostWriteBlock(uint64_t element_size) {
  2135. AddPayloadSize(element_size);
  2136. ++blocks_added_;
  2137. }
  2138. int64_t Cluster::GetRelativeTimecode(int64_t abs_timecode) const {
  2139. const int64_t cluster_timecode = this->Cluster::timecode();
  2140. const int64_t rel_timecode =
  2141. static_cast<int64_t>(abs_timecode) - cluster_timecode;
  2142. if (rel_timecode < 0 || rel_timecode > kMaxBlockTimecode)
  2143. return -1;
  2144. return rel_timecode;
  2145. }
  2146. bool Cluster::DoWriteFrame(const Frame* const frame) {
  2147. if (!frame || !frame->IsValid())
  2148. return false;
  2149. if (!PreWriteBlock())
  2150. return false;
  2151. const uint64_t element_size = WriteFrame(writer_, frame, this);
  2152. if (element_size == 0)
  2153. return false;
  2154. PostWriteBlock(element_size);
  2155. last_block_timestamp_[frame->track_number()] = frame->timestamp();
  2156. return true;
  2157. }
  2158. bool Cluster::QueueOrWriteFrame(const Frame* const frame) {
  2159. if (!frame || !frame->IsValid())
  2160. return false;
  2161. // If |write_last_frame_with_duration_| is not set, then write the frame right
  2162. // away.
  2163. if (!write_last_frame_with_duration_) {
  2164. return DoWriteFrame(frame);
  2165. }
  2166. // Queue the current frame.
  2167. uint64_t track_number = frame->track_number();
  2168. Frame* const frame_to_store = new Frame();
  2169. frame_to_store->CopyFrom(*frame);
  2170. stored_frames_[track_number].push_back(frame_to_store);
  2171. // Iterate through all queued frames in the current track except the last one
  2172. // and write it if it is okay to do so (i.e.) no other track has an held back
  2173. // frame with timestamp <= the timestamp of the frame in question.
  2174. std::vector<std::list<Frame*>::iterator> frames_to_erase;
  2175. for (std::list<Frame *>::iterator
  2176. current_track_iterator = stored_frames_[track_number].begin(),
  2177. end = --stored_frames_[track_number].end();
  2178. current_track_iterator != end; ++current_track_iterator) {
  2179. const Frame* const frame_to_write = *current_track_iterator;
  2180. bool okay_to_write = true;
  2181. for (FrameMapIterator track_iterator = stored_frames_.begin();
  2182. track_iterator != stored_frames_.end(); ++track_iterator) {
  2183. if (track_iterator->first == track_number) {
  2184. continue;
  2185. }
  2186. if (track_iterator->second.front()->timestamp() <
  2187. frame_to_write->timestamp()) {
  2188. okay_to_write = false;
  2189. break;
  2190. }
  2191. }
  2192. if (okay_to_write) {
  2193. const bool wrote_frame = DoWriteFrame(frame_to_write);
  2194. delete frame_to_write;
  2195. if (!wrote_frame)
  2196. return false;
  2197. frames_to_erase.push_back(current_track_iterator);
  2198. } else {
  2199. break;
  2200. }
  2201. }
  2202. for (std::vector<std::list<Frame*>::iterator>::iterator iterator =
  2203. frames_to_erase.begin();
  2204. iterator != frames_to_erase.end(); ++iterator) {
  2205. stored_frames_[track_number].erase(*iterator);
  2206. }
  2207. return true;
  2208. }
  2209. bool Cluster::WriteClusterHeader() {
  2210. if (finalized_)
  2211. return false;
  2212. if (WriteID(writer_, libwebm::kMkvCluster))
  2213. return false;
  2214. // Save for later.
  2215. size_position_ = writer_->Position();
  2216. // Write "unknown" (EBML coded -1) as cluster size value. We need to write 8
  2217. // bytes because we do not know how big our cluster will be.
  2218. if (SerializeInt(writer_, kEbmlUnknownValue, 8))
  2219. return false;
  2220. if (!WriteEbmlElement(writer_, libwebm::kMkvTimecode, timecode(),
  2221. fixed_size_timecode_ ? 8 : 0)) {
  2222. return false;
  2223. }
  2224. AddPayloadSize(EbmlElementSize(libwebm::kMkvTimecode, timecode(),
  2225. fixed_size_timecode_ ? 8 : 0));
  2226. header_written_ = true;
  2227. return true;
  2228. }
  2229. ///////////////////////////////////////////////////////////////
  2230. //
  2231. // SeekHead Class
  2232. SeekHead::SeekHead() : start_pos_(0ULL) {
  2233. for (int32_t i = 0; i < kSeekEntryCount; ++i) {
  2234. seek_entry_id_[i] = 0;
  2235. seek_entry_pos_[i] = 0;
  2236. }
  2237. }
  2238. SeekHead::~SeekHead() {}
  2239. bool SeekHead::Finalize(IMkvWriter* writer) const {
  2240. if (writer->Seekable()) {
  2241. if (start_pos_ == -1)
  2242. return false;
  2243. uint64_t payload_size = 0;
  2244. uint64_t entry_size[kSeekEntryCount];
  2245. for (int32_t i = 0; i < kSeekEntryCount; ++i) {
  2246. if (seek_entry_id_[i] != 0) {
  2247. entry_size[i] = EbmlElementSize(libwebm::kMkvSeekID,
  2248. static_cast<uint64>(seek_entry_id_[i]));
  2249. entry_size[i] += EbmlElementSize(
  2250. libwebm::kMkvSeekPosition, static_cast<uint64>(seek_entry_pos_[i]));
  2251. payload_size +=
  2252. EbmlMasterElementSize(libwebm::kMkvSeek, entry_size[i]) +
  2253. entry_size[i];
  2254. }
  2255. }
  2256. // No SeekHead elements
  2257. if (payload_size == 0)
  2258. return true;
  2259. const int64_t pos = writer->Position();
  2260. if (writer->Position(start_pos_))
  2261. return false;
  2262. if (!WriteEbmlMasterElement(writer, libwebm::kMkvSeekHead, payload_size))
  2263. return false;
  2264. for (int32_t i = 0; i < kSeekEntryCount; ++i) {
  2265. if (seek_entry_id_[i] != 0) {
  2266. if (!WriteEbmlMasterElement(writer, libwebm::kMkvSeek, entry_size[i]))
  2267. return false;
  2268. if (!WriteEbmlElement(writer, libwebm::kMkvSeekID,
  2269. static_cast<uint64>(seek_entry_id_[i])))
  2270. return false;
  2271. if (!WriteEbmlElement(writer, libwebm::kMkvSeekPosition,
  2272. static_cast<uint64>(seek_entry_pos_[i])))
  2273. return false;
  2274. }
  2275. }
  2276. const uint64_t total_entry_size = kSeekEntryCount * MaxEntrySize();
  2277. const uint64_t total_size =
  2278. EbmlMasterElementSize(libwebm::kMkvSeekHead, total_entry_size) +
  2279. total_entry_size;
  2280. const int64_t size_left = total_size - (writer->Position() - start_pos_);
  2281. const uint64_t bytes_written = WriteVoidElement(writer, size_left);
  2282. if (!bytes_written)
  2283. return false;
  2284. if (writer->Position(pos))
  2285. return false;
  2286. }
  2287. return true;
  2288. }
  2289. bool SeekHead::Write(IMkvWriter* writer) {
  2290. const uint64_t entry_size = kSeekEntryCount * MaxEntrySize();
  2291. const uint64_t size =
  2292. EbmlMasterElementSize(libwebm::kMkvSeekHead, entry_size);
  2293. start_pos_ = writer->Position();
  2294. const uint64_t bytes_written = WriteVoidElement(writer, size + entry_size);
  2295. if (!bytes_written)
  2296. return false;
  2297. return true;
  2298. }
  2299. bool SeekHead::AddSeekEntry(uint32_t id, uint64_t pos) {
  2300. for (int32_t i = 0; i < kSeekEntryCount; ++i) {
  2301. if (seek_entry_id_[i] == 0) {
  2302. seek_entry_id_[i] = id;
  2303. seek_entry_pos_[i] = pos;
  2304. return true;
  2305. }
  2306. }
  2307. return false;
  2308. }
  2309. uint32_t SeekHead::GetId(int index) const {
  2310. if (index < 0 || index >= kSeekEntryCount)
  2311. return UINT_MAX;
  2312. return seek_entry_id_[index];
  2313. }
  2314. uint64_t SeekHead::GetPosition(int index) const {
  2315. if (index < 0 || index >= kSeekEntryCount)
  2316. return ULLONG_MAX;
  2317. return seek_entry_pos_[index];
  2318. }
  2319. bool SeekHead::SetSeekEntry(int index, uint32_t id, uint64_t position) {
  2320. if (index < 0 || index >= kSeekEntryCount)
  2321. return false;
  2322. seek_entry_id_[index] = id;
  2323. seek_entry_pos_[index] = position;
  2324. return true;
  2325. }
  2326. uint64_t SeekHead::MaxEntrySize() const {
  2327. const uint64_t max_entry_payload_size =
  2328. EbmlElementSize(libwebm::kMkvSeekID,
  2329. static_cast<uint64>(UINT64_C(0xffffffff))) +
  2330. EbmlElementSize(libwebm::kMkvSeekPosition,
  2331. static_cast<uint64>(UINT64_C(0xffffffffffffffff)));
  2332. const uint64_t max_entry_size =
  2333. EbmlMasterElementSize(libwebm::kMkvSeek, max_entry_payload_size) +
  2334. max_entry_payload_size;
  2335. return max_entry_size;
  2336. }
  2337. ///////////////////////////////////////////////////////////////
  2338. //
  2339. // SegmentInfo Class
  2340. SegmentInfo::SegmentInfo()
  2341. : duration_(-1.0),
  2342. muxing_app_(NULL),
  2343. timecode_scale_(1000000ULL),
  2344. writing_app_(NULL),
  2345. date_utc_(LLONG_MIN),
  2346. duration_pos_(-1) {}
  2347. SegmentInfo::~SegmentInfo() {
  2348. delete[] muxing_app_;
  2349. delete[] writing_app_;
  2350. }
  2351. bool SegmentInfo::Init() {
  2352. int32_t major;
  2353. int32_t minor;
  2354. int32_t build;
  2355. int32_t revision;
  2356. GetVersion(&major, &minor, &build, &revision);
  2357. char temp[256];
  2358. #ifdef _MSC_VER
  2359. sprintf_s(temp, sizeof(temp) / sizeof(temp[0]), "libwebm-%d.%d.%d.%d", major,
  2360. minor, build, revision);
  2361. #else
  2362. snprintf(temp, sizeof(temp) / sizeof(temp[0]), "libwebm-%d.%d.%d.%d", major,
  2363. minor, build, revision);
  2364. #endif
  2365. const size_t app_len = strlen(temp) + 1;
  2366. delete[] muxing_app_;
  2367. muxing_app_ = new (std::nothrow) char[app_len]; // NOLINT
  2368. if (!muxing_app_)
  2369. return false;
  2370. #ifdef _MSC_VER
  2371. strcpy_s(muxing_app_, app_len, temp);
  2372. #else
  2373. strcpy(muxing_app_, temp);
  2374. #endif
  2375. set_writing_app(temp);
  2376. if (!writing_app_)
  2377. return false;
  2378. return true;
  2379. }
  2380. bool SegmentInfo::Finalize(IMkvWriter* writer) const {
  2381. if (!writer)
  2382. return false;
  2383. if (duration_ > 0.0) {
  2384. if (writer->Seekable()) {
  2385. if (duration_pos_ == -1)
  2386. return false;
  2387. const int64_t pos = writer->Position();
  2388. if (writer->Position(duration_pos_))
  2389. return false;
  2390. if (!WriteEbmlElement(writer, libwebm::kMkvDuration,
  2391. static_cast<float>(duration_)))
  2392. return false;
  2393. if (writer->Position(pos))
  2394. return false;
  2395. }
  2396. }
  2397. return true;
  2398. }
  2399. bool SegmentInfo::Write(IMkvWriter* writer) {
  2400. if (!writer || !muxing_app_ || !writing_app_)
  2401. return false;
  2402. uint64_t size = EbmlElementSize(libwebm::kMkvTimecodeScale,
  2403. static_cast<uint64>(timecode_scale_));
  2404. if (duration_ > 0.0)
  2405. size +=
  2406. EbmlElementSize(libwebm::kMkvDuration, static_cast<float>(duration_));
  2407. if (date_utc_ != LLONG_MIN)
  2408. size += EbmlDateElementSize(libwebm::kMkvDateUTC);
  2409. size += EbmlElementSize(libwebm::kMkvMuxingApp, muxing_app_);
  2410. size += EbmlElementSize(libwebm::kMkvWritingApp, writing_app_);
  2411. if (!WriteEbmlMasterElement(writer, libwebm::kMkvInfo, size))
  2412. return false;
  2413. const int64_t payload_position = writer->Position();
  2414. if (payload_position < 0)
  2415. return false;
  2416. if (!WriteEbmlElement(writer, libwebm::kMkvTimecodeScale,
  2417. static_cast<uint64>(timecode_scale_)))
  2418. return false;
  2419. if (duration_ > 0.0) {
  2420. // Save for later
  2421. duration_pos_ = writer->Position();
  2422. if (!WriteEbmlElement(writer, libwebm::kMkvDuration,
  2423. static_cast<float>(duration_)))
  2424. return false;
  2425. }
  2426. if (date_utc_ != LLONG_MIN)
  2427. WriteEbmlDateElement(writer, libwebm::kMkvDateUTC, date_utc_);
  2428. if (!WriteEbmlElement(writer, libwebm::kMkvMuxingApp, muxing_app_))
  2429. return false;
  2430. if (!WriteEbmlElement(writer, libwebm::kMkvWritingApp, writing_app_))
  2431. return false;
  2432. const int64_t stop_position = writer->Position();
  2433. if (stop_position < 0 ||
  2434. stop_position - payload_position != static_cast<int64_t>(size))
  2435. return false;
  2436. return true;
  2437. }
  2438. void SegmentInfo::set_muxing_app(const char* app) {
  2439. if (app) {
  2440. const size_t length = strlen(app) + 1;
  2441. char* temp_str = new (std::nothrow) char[length]; // NOLINT
  2442. if (!temp_str)
  2443. return;
  2444. #ifdef _MSC_VER
  2445. strcpy_s(temp_str, length, app);
  2446. #else
  2447. strcpy(temp_str, app);
  2448. #endif
  2449. delete[] muxing_app_;
  2450. muxing_app_ = temp_str;
  2451. }
  2452. }
  2453. void SegmentInfo::set_writing_app(const char* app) {
  2454. if (app) {
  2455. const size_t length = strlen(app) + 1;
  2456. char* temp_str = new (std::nothrow) char[length]; // NOLINT
  2457. if (!temp_str)
  2458. return;
  2459. #ifdef _MSC_VER
  2460. strcpy_s(temp_str, length, app);
  2461. #else
  2462. strcpy(temp_str, app);
  2463. #endif
  2464. delete[] writing_app_;
  2465. writing_app_ = temp_str;
  2466. }
  2467. }
  2468. ///////////////////////////////////////////////////////////////
  2469. //
  2470. // Segment Class
  2471. Segment::Segment()
  2472. : chunk_count_(0),
  2473. chunk_name_(NULL),
  2474. chunk_writer_cluster_(NULL),
  2475. chunk_writer_cues_(NULL),
  2476. chunk_writer_header_(NULL),
  2477. chunking_(false),
  2478. chunking_base_name_(NULL),
  2479. cluster_list_(NULL),
  2480. cluster_list_capacity_(0),
  2481. cluster_list_size_(0),
  2482. cues_position_(kAfterClusters),
  2483. cues_track_(0),
  2484. force_new_cluster_(false),
  2485. frames_(NULL),
  2486. frames_capacity_(0),
  2487. frames_size_(0),
  2488. has_video_(false),
  2489. header_written_(false),
  2490. last_block_duration_(0),
  2491. last_timestamp_(0),
  2492. max_cluster_duration_(kDefaultMaxClusterDuration),
  2493. max_cluster_size_(0),
  2494. mode_(kFile),
  2495. new_cuepoint_(false),
  2496. output_cues_(true),
  2497. accurate_cluster_duration_(false),
  2498. fixed_size_cluster_timecode_(false),
  2499. estimate_file_duration_(false),
  2500. payload_pos_(0),
  2501. size_position_(0),
  2502. doc_type_version_(kDefaultDocTypeVersion),
  2503. doc_type_version_written_(0),
  2504. duration_(0.0),
  2505. writer_cluster_(NULL),
  2506. writer_cues_(NULL),
  2507. writer_header_(NULL) {
  2508. const time_t curr_time = time(NULL);
  2509. seed_ = static_cast<unsigned int>(curr_time);
  2510. #ifdef _WIN32
  2511. srand(seed_);
  2512. #endif
  2513. }
  2514. Segment::~Segment() {
  2515. if (cluster_list_) {
  2516. for (int32_t i = 0; i < cluster_list_size_; ++i) {
  2517. Cluster* const cluster = cluster_list_[i];
  2518. delete cluster;
  2519. }
  2520. delete[] cluster_list_;
  2521. }
  2522. if (frames_) {
  2523. for (int32_t i = 0; i < frames_size_; ++i) {
  2524. Frame* const frame = frames_[i];
  2525. delete frame;
  2526. }
  2527. delete[] frames_;
  2528. }
  2529. delete[] chunk_name_;
  2530. delete[] chunking_base_name_;
  2531. if (chunk_writer_cluster_) {
  2532. chunk_writer_cluster_->Close();
  2533. delete chunk_writer_cluster_;
  2534. }
  2535. if (chunk_writer_cues_) {
  2536. chunk_writer_cues_->Close();
  2537. delete chunk_writer_cues_;
  2538. }
  2539. if (chunk_writer_header_) {
  2540. chunk_writer_header_->Close();
  2541. delete chunk_writer_header_;
  2542. }
  2543. }
  2544. void Segment::MoveCuesBeforeClustersHelper(uint64_t diff, int32_t index,
  2545. uint64_t* cues_size) {
  2546. CuePoint* const cue_point = cues_.GetCueByIndex(index);
  2547. if (cue_point == NULL)
  2548. return;
  2549. const uint64_t old_cue_point_size = cue_point->Size();
  2550. const uint64_t cluster_pos = cue_point->cluster_pos() + diff;
  2551. cue_point->set_cluster_pos(cluster_pos); // update the new cluster position
  2552. // New size of the cue is computed as follows
  2553. // Let a = current sum of size of all CuePoints
  2554. // Let b = Increase in Cue Point's size due to this iteration
  2555. // Let c = Increase in size of Cues Element's length due to this iteration
  2556. // (This is computed as CodedSize(a + b) - CodedSize(a))
  2557. // Let d = b + c. Now d is the |diff| passed to the next recursive call.
  2558. // Let e = a + b. Now e is the |cues_size| passed to the next recursive
  2559. // call.
  2560. const uint64_t cue_point_size_diff = cue_point->Size() - old_cue_point_size;
  2561. const uint64_t cue_size_diff =
  2562. GetCodedUIntSize(*cues_size + cue_point_size_diff) -
  2563. GetCodedUIntSize(*cues_size);
  2564. *cues_size += cue_point_size_diff;
  2565. diff = cue_size_diff + cue_point_size_diff;
  2566. if (diff > 0) {
  2567. for (int32_t i = 0; i < cues_.cue_entries_size(); ++i) {
  2568. MoveCuesBeforeClustersHelper(diff, i, cues_size);
  2569. }
  2570. }
  2571. }
  2572. void Segment::MoveCuesBeforeClusters() {
  2573. const uint64_t current_cue_size = cues_.Size();
  2574. uint64_t cue_size = 0;
  2575. for (int32_t i = 0; i < cues_.cue_entries_size(); ++i)
  2576. cue_size += cues_.GetCueByIndex(i)->Size();
  2577. for (int32_t i = 0; i < cues_.cue_entries_size(); ++i)
  2578. MoveCuesBeforeClustersHelper(current_cue_size, i, &cue_size);
  2579. // Adjust the Seek Entry to reflect the change in position
  2580. // of Cluster and Cues
  2581. int32_t cluster_index = 0;
  2582. int32_t cues_index = 0;
  2583. for (int32_t i = 0; i < SeekHead::kSeekEntryCount; ++i) {
  2584. if (seek_head_.GetId(i) == libwebm::kMkvCluster)
  2585. cluster_index = i;
  2586. if (seek_head_.GetId(i) == libwebm::kMkvCues)
  2587. cues_index = i;
  2588. }
  2589. seek_head_.SetSeekEntry(cues_index, libwebm::kMkvCues,
  2590. seek_head_.GetPosition(cluster_index));
  2591. seek_head_.SetSeekEntry(cluster_index, libwebm::kMkvCluster,
  2592. cues_.Size() + seek_head_.GetPosition(cues_index));
  2593. }
  2594. bool Segment::Init(IMkvWriter* ptr_writer) {
  2595. if (!ptr_writer) {
  2596. return false;
  2597. }
  2598. writer_cluster_ = ptr_writer;
  2599. writer_cues_ = ptr_writer;
  2600. writer_header_ = ptr_writer;
  2601. memset(&track_frames_written_, 0,
  2602. sizeof(track_frames_written_[0]) * kMaxTrackNumber);
  2603. memset(&last_track_timestamp_, 0,
  2604. sizeof(last_track_timestamp_[0]) * kMaxTrackNumber);
  2605. return segment_info_.Init();
  2606. }
  2607. bool Segment::CopyAndMoveCuesBeforeClusters(mkvparser::IMkvReader* reader,
  2608. IMkvWriter* writer) {
  2609. if (!writer->Seekable() || chunking_)
  2610. return false;
  2611. const int64_t cluster_offset =
  2612. cluster_list_[0]->size_position() - GetUIntSize(libwebm::kMkvCluster);
  2613. // Copy the headers.
  2614. if (!ChunkedCopy(reader, writer, 0, cluster_offset))
  2615. return false;
  2616. // Recompute cue positions and seek entries.
  2617. MoveCuesBeforeClusters();
  2618. // Write cues and seek entries.
  2619. // TODO(vigneshv): As of now, it's safe to call seek_head_.Finalize() for the
  2620. // second time with a different writer object. But the name Finalize() doesn't
  2621. // indicate something we want to call more than once. So consider renaming it
  2622. // to write() or some such.
  2623. if (!cues_.Write(writer) || !seek_head_.Finalize(writer))
  2624. return false;
  2625. // Copy the Clusters.
  2626. if (!ChunkedCopy(reader, writer, cluster_offset,
  2627. cluster_end_offset_ - cluster_offset))
  2628. return false;
  2629. // Update the Segment size in case the Cues size has changed.
  2630. const int64_t pos = writer->Position();
  2631. const int64_t segment_size = writer->Position() - payload_pos_;
  2632. if (writer->Position(size_position_) ||
  2633. WriteUIntSize(writer, segment_size, 8) || writer->Position(pos))
  2634. return false;
  2635. return true;
  2636. }
  2637. bool Segment::Finalize() {
  2638. if (WriteFramesAll() < 0)
  2639. return false;
  2640. // In kLive mode, call Cluster::Finalize only if |accurate_cluster_duration_|
  2641. // is set. In all other modes, always call Cluster::Finalize.
  2642. if ((mode_ == kLive ? accurate_cluster_duration_ : true) &&
  2643. cluster_list_size_ > 0) {
  2644. // Update last cluster's size
  2645. Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1];
  2646. // For the last frame of the last Cluster, we don't write it as a BlockGroup
  2647. // with Duration unless the frame itself has duration set explicitly.
  2648. if (!old_cluster || !old_cluster->Finalize(false, 0))
  2649. return false;
  2650. }
  2651. if (mode_ == kFile) {
  2652. if (chunking_ && chunk_writer_cluster_) {
  2653. chunk_writer_cluster_->Close();
  2654. chunk_count_++;
  2655. }
  2656. double duration =
  2657. (static_cast<double>(last_timestamp_) + last_block_duration_) /
  2658. segment_info_.timecode_scale();
  2659. if (duration_ > 0.0) {
  2660. duration = duration_;
  2661. } else {
  2662. if (last_block_duration_ == 0 && estimate_file_duration_) {
  2663. const int num_tracks = static_cast<int>(tracks_.track_entries_size());
  2664. for (int i = 0; i < num_tracks; ++i) {
  2665. if (track_frames_written_[i] < 2)
  2666. continue;
  2667. // Estimate the duration for the last block of a Track.
  2668. const double nano_per_frame =
  2669. static_cast<double>(last_track_timestamp_[i]) /
  2670. (track_frames_written_[i] - 1);
  2671. const double track_duration =
  2672. (last_track_timestamp_[i] + nano_per_frame) /
  2673. segment_info_.timecode_scale();
  2674. if (track_duration > duration)
  2675. duration = track_duration;
  2676. }
  2677. }
  2678. }
  2679. segment_info_.set_duration(duration);
  2680. if (!segment_info_.Finalize(writer_header_))
  2681. return false;
  2682. if (output_cues_)
  2683. if (!seek_head_.AddSeekEntry(libwebm::kMkvCues, MaxOffset()))
  2684. return false;
  2685. if (chunking_) {
  2686. if (!chunk_writer_cues_)
  2687. return false;
  2688. char* name = NULL;
  2689. if (!UpdateChunkName("cues", &name))
  2690. return false;
  2691. const bool cues_open = chunk_writer_cues_->Open(name);
  2692. delete[] name;
  2693. if (!cues_open)
  2694. return false;
  2695. }
  2696. cluster_end_offset_ = writer_cluster_->Position();
  2697. // Write the seek headers and cues
  2698. if (output_cues_)
  2699. if (!cues_.Write(writer_cues_))
  2700. return false;
  2701. if (!seek_head_.Finalize(writer_header_))
  2702. return false;
  2703. if (writer_header_->Seekable()) {
  2704. if (size_position_ == -1)
  2705. return false;
  2706. const int64_t segment_size = MaxOffset();
  2707. if (segment_size < 1)
  2708. return false;
  2709. const int64_t pos = writer_header_->Position();
  2710. UpdateDocTypeVersion();
  2711. if (doc_type_version_ != doc_type_version_written_) {
  2712. if (writer_header_->Position(0))
  2713. return false;
  2714. const char* const doc_type =
  2715. DocTypeIsWebm() ? kDocTypeWebm : kDocTypeMatroska;
  2716. if (!WriteEbmlHeader(writer_header_, doc_type_version_, doc_type))
  2717. return false;
  2718. if (writer_header_->Position() != ebml_header_size_)
  2719. return false;
  2720. doc_type_version_written_ = doc_type_version_;
  2721. }
  2722. if (writer_header_->Position(size_position_))
  2723. return false;
  2724. if (WriteUIntSize(writer_header_, segment_size, 8))
  2725. return false;
  2726. if (writer_header_->Position(pos))
  2727. return false;
  2728. }
  2729. if (chunking_) {
  2730. // Do not close any writers until the segment size has been written,
  2731. // otherwise the size may be off.
  2732. if (!chunk_writer_cues_ || !chunk_writer_header_)
  2733. return false;
  2734. chunk_writer_cues_->Close();
  2735. chunk_writer_header_->Close();
  2736. }
  2737. }
  2738. return true;
  2739. }
  2740. Track* Segment::AddTrack(int32_t number) {
  2741. Track* const track = new (std::nothrow) Track(&seed_); // NOLINT
  2742. if (!track)
  2743. return NULL;
  2744. if (!tracks_.AddTrack(track, number)) {
  2745. delete track;
  2746. return NULL;
  2747. }
  2748. return track;
  2749. }
  2750. Chapter* Segment::AddChapter() { return chapters_.AddChapter(&seed_); }
  2751. Tag* Segment::AddTag() { return tags_.AddTag(); }
  2752. uint64_t Segment::AddVideoTrack(int32_t width, int32_t height, int32_t number) {
  2753. VideoTrack* const track = new (std::nothrow) VideoTrack(&seed_); // NOLINT
  2754. if (!track)
  2755. return 0;
  2756. track->set_type(Tracks::kVideo);
  2757. track->set_codec_id(Tracks::kVp8CodecId);
  2758. track->set_width(width);
  2759. track->set_height(height);
  2760. if (!tracks_.AddTrack(track, number)) {
  2761. delete track;
  2762. return 0;
  2763. }
  2764. has_video_ = true;
  2765. return track->number();
  2766. }
  2767. bool Segment::AddCuePoint(uint64_t timestamp, uint64_t track) {
  2768. if (cluster_list_size_ < 1)
  2769. return false;
  2770. const Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
  2771. if (!cluster)
  2772. return false;
  2773. CuePoint* const cue = new (std::nothrow) CuePoint(); // NOLINT
  2774. if (!cue)
  2775. return false;
  2776. cue->set_time(timestamp / segment_info_.timecode_scale());
  2777. cue->set_block_number(cluster->blocks_added());
  2778. cue->set_cluster_pos(cluster->position_for_cues());
  2779. cue->set_track(track);
  2780. if (!cues_.AddCue(cue)) {
  2781. delete cue;
  2782. return false;
  2783. }
  2784. new_cuepoint_ = false;
  2785. return true;
  2786. }
  2787. uint64_t Segment::AddAudioTrack(int32_t sample_rate, int32_t channels,
  2788. int32_t number) {
  2789. AudioTrack* const track = new (std::nothrow) AudioTrack(&seed_); // NOLINT
  2790. if (!track)
  2791. return 0;
  2792. track->set_type(Tracks::kAudio);
  2793. track->set_codec_id(Tracks::kVorbisCodecId);
  2794. track->set_sample_rate(sample_rate);
  2795. track->set_channels(channels);
  2796. if (!tracks_.AddTrack(track, number)) {
  2797. delete track;
  2798. return 0;
  2799. }
  2800. return track->number();
  2801. }
  2802. bool Segment::AddFrame(const uint8_t* data, uint64_t length,
  2803. uint64_t track_number, uint64_t timestamp, bool is_key) {
  2804. if (!data)
  2805. return false;
  2806. Frame frame;
  2807. if (!frame.Init(data, length))
  2808. return false;
  2809. frame.set_track_number(track_number);
  2810. frame.set_timestamp(timestamp);
  2811. frame.set_is_key(is_key);
  2812. return AddGenericFrame(&frame);
  2813. }
  2814. bool Segment::AddFrameWithAdditional(const uint8_t* data, uint64_t length,
  2815. const uint8_t* additional,
  2816. uint64_t additional_length,
  2817. uint64_t add_id, uint64_t track_number,
  2818. uint64_t timestamp, bool is_key) {
  2819. if (!data || !additional)
  2820. return false;
  2821. Frame frame;
  2822. if (!frame.Init(data, length) ||
  2823. !frame.AddAdditionalData(additional, additional_length, add_id)) {
  2824. return false;
  2825. }
  2826. frame.set_track_number(track_number);
  2827. frame.set_timestamp(timestamp);
  2828. frame.set_is_key(is_key);
  2829. return AddGenericFrame(&frame);
  2830. }
  2831. bool Segment::AddFrameWithDiscardPadding(const uint8_t* data, uint64_t length,
  2832. int64_t discard_padding,
  2833. uint64_t track_number,
  2834. uint64_t timestamp, bool is_key) {
  2835. if (!data)
  2836. return false;
  2837. Frame frame;
  2838. if (!frame.Init(data, length))
  2839. return false;
  2840. frame.set_discard_padding(discard_padding);
  2841. frame.set_track_number(track_number);
  2842. frame.set_timestamp(timestamp);
  2843. frame.set_is_key(is_key);
  2844. return AddGenericFrame(&frame);
  2845. }
  2846. bool Segment::AddMetadata(const uint8_t* data, uint64_t length,
  2847. uint64_t track_number, uint64_t timestamp_ns,
  2848. uint64_t duration_ns) {
  2849. if (!data)
  2850. return false;
  2851. Frame frame;
  2852. if (!frame.Init(data, length))
  2853. return false;
  2854. frame.set_track_number(track_number);
  2855. frame.set_timestamp(timestamp_ns);
  2856. frame.set_duration(duration_ns);
  2857. frame.set_is_key(true); // All metadata blocks are keyframes.
  2858. return AddGenericFrame(&frame);
  2859. }
  2860. bool Segment::AddGenericFrame(const Frame* frame) {
  2861. if (!frame)
  2862. return false;
  2863. if (!CheckHeaderInfo())
  2864. return false;
  2865. // Check for non-monotonically increasing timestamps.
  2866. if (frame->timestamp() < last_timestamp_)
  2867. return false;
  2868. // Check if the track number is valid.
  2869. if (!tracks_.GetTrackByNumber(frame->track_number()))
  2870. return false;
  2871. if (frame->discard_padding() != 0)
  2872. doc_type_version_ = 4;
  2873. if (cluster_list_size_ > 0) {
  2874. const uint64_t timecode_scale = segment_info_.timecode_scale();
  2875. const uint64_t frame_timecode = frame->timestamp() / timecode_scale;
  2876. const Cluster* const last_cluster = cluster_list_[cluster_list_size_ - 1];
  2877. const uint64_t last_cluster_timecode = last_cluster->timecode();
  2878. const uint64_t rel_timecode = frame_timecode - last_cluster_timecode;
  2879. if (rel_timecode > kMaxBlockTimecode) {
  2880. force_new_cluster_ = true;
  2881. }
  2882. }
  2883. // If the segment has a video track hold onto audio frames to make sure the
  2884. // audio that is associated with the start time of a video key-frame is
  2885. // muxed into the same cluster.
  2886. if (has_video_ && tracks_.TrackIsAudio(frame->track_number()) &&
  2887. !force_new_cluster_) {
  2888. Frame* const new_frame = new (std::nothrow) Frame();
  2889. if (!new_frame || !new_frame->CopyFrom(*frame)) {
  2890. delete new_frame;
  2891. return false;
  2892. }
  2893. if (!QueueFrame(new_frame)) {
  2894. delete new_frame;
  2895. return false;
  2896. }
  2897. track_frames_written_[frame->track_number() - 1]++;
  2898. return true;
  2899. }
  2900. if (!DoNewClusterProcessing(frame->track_number(), frame->timestamp(),
  2901. frame->is_key())) {
  2902. return false;
  2903. }
  2904. if (cluster_list_size_ < 1)
  2905. return false;
  2906. Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
  2907. if (!cluster)
  2908. return false;
  2909. // If the Frame is not a SimpleBlock, then set the reference_block_timestamp
  2910. // if it is not set already.
  2911. bool frame_created = false;
  2912. if (!frame->CanBeSimpleBlock() && !frame->is_key() &&
  2913. !frame->reference_block_timestamp_set()) {
  2914. Frame* const new_frame = new (std::nothrow) Frame();
  2915. if (!new_frame || !new_frame->CopyFrom(*frame)) {
  2916. delete new_frame;
  2917. return false;
  2918. }
  2919. new_frame->set_reference_block_timestamp(
  2920. last_track_timestamp_[frame->track_number() - 1]);
  2921. frame = new_frame;
  2922. frame_created = true;
  2923. }
  2924. if (!cluster->AddFrame(frame))
  2925. return false;
  2926. if (new_cuepoint_ && cues_track_ == frame->track_number()) {
  2927. if (!AddCuePoint(frame->timestamp(), cues_track_))
  2928. return false;
  2929. }
  2930. last_timestamp_ = frame->timestamp();
  2931. last_track_timestamp_[frame->track_number() - 1] = frame->timestamp();
  2932. last_block_duration_ = frame->duration();
  2933. track_frames_written_[frame->track_number() - 1]++;
  2934. if (frame_created)
  2935. delete frame;
  2936. return true;
  2937. }
  2938. void Segment::OutputCues(bool output_cues) { output_cues_ = output_cues; }
  2939. void Segment::AccurateClusterDuration(bool accurate_cluster_duration) {
  2940. accurate_cluster_duration_ = accurate_cluster_duration;
  2941. }
  2942. void Segment::UseFixedSizeClusterTimecode(bool fixed_size_cluster_timecode) {
  2943. fixed_size_cluster_timecode_ = fixed_size_cluster_timecode;
  2944. }
  2945. bool Segment::SetChunking(bool chunking, const char* filename) {
  2946. if (chunk_count_ > 0)
  2947. return false;
  2948. if (chunking) {
  2949. if (!filename)
  2950. return false;
  2951. // Check if we are being set to what is already set.
  2952. if (chunking_ && !strcmp(filename, chunking_base_name_))
  2953. return true;
  2954. const size_t name_length = strlen(filename) + 1;
  2955. char* const temp = new (std::nothrow) char[name_length]; // NOLINT
  2956. if (!temp)
  2957. return false;
  2958. #ifdef _MSC_VER
  2959. strcpy_s(temp, name_length, filename);
  2960. #else
  2961. strcpy(temp, filename);
  2962. #endif
  2963. delete[] chunking_base_name_;
  2964. chunking_base_name_ = temp;
  2965. if (!UpdateChunkName("chk", &chunk_name_))
  2966. return false;
  2967. if (!chunk_writer_cluster_) {
  2968. chunk_writer_cluster_ = new (std::nothrow) MkvWriter(); // NOLINT
  2969. if (!chunk_writer_cluster_)
  2970. return false;
  2971. }
  2972. if (!chunk_writer_cues_) {
  2973. chunk_writer_cues_ = new (std::nothrow) MkvWriter(); // NOLINT
  2974. if (!chunk_writer_cues_)
  2975. return false;
  2976. }
  2977. if (!chunk_writer_header_) {
  2978. chunk_writer_header_ = new (std::nothrow) MkvWriter(); // NOLINT
  2979. if (!chunk_writer_header_)
  2980. return false;
  2981. }
  2982. if (!chunk_writer_cluster_->Open(chunk_name_))
  2983. return false;
  2984. const size_t header_length = strlen(filename) + strlen(".hdr") + 1;
  2985. char* const header = new (std::nothrow) char[header_length]; // NOLINT
  2986. if (!header)
  2987. return false;
  2988. #ifdef _MSC_VER
  2989. strcpy_s(header, header_length - strlen(".hdr"), chunking_base_name_);
  2990. strcat_s(header, header_length, ".hdr");
  2991. #else
  2992. strcpy(header, chunking_base_name_);
  2993. strcat(header, ".hdr");
  2994. #endif
  2995. if (!chunk_writer_header_->Open(header)) {
  2996. delete[] header;
  2997. return false;
  2998. }
  2999. writer_cluster_ = chunk_writer_cluster_;
  3000. writer_cues_ = chunk_writer_cues_;
  3001. writer_header_ = chunk_writer_header_;
  3002. delete[] header;
  3003. }
  3004. chunking_ = chunking;
  3005. return true;
  3006. }
  3007. bool Segment::CuesTrack(uint64_t track_number) {
  3008. const Track* const track = GetTrackByNumber(track_number);
  3009. if (!track)
  3010. return false;
  3011. cues_track_ = track_number;
  3012. return true;
  3013. }
  3014. void Segment::ForceNewClusterOnNextFrame() { force_new_cluster_ = true; }
  3015. Track* Segment::GetTrackByNumber(uint64_t track_number) const {
  3016. return tracks_.GetTrackByNumber(track_number);
  3017. }
  3018. bool Segment::WriteSegmentHeader() {
  3019. UpdateDocTypeVersion();
  3020. const char* const doc_type =
  3021. DocTypeIsWebm() ? kDocTypeWebm : kDocTypeMatroska;
  3022. if (!WriteEbmlHeader(writer_header_, doc_type_version_, doc_type))
  3023. return false;
  3024. doc_type_version_written_ = doc_type_version_;
  3025. ebml_header_size_ = static_cast<int32_t>(writer_header_->Position());
  3026. // Write "unknown" (-1) as segment size value. If mode is kFile, Segment
  3027. // will write over duration when the file is finalized.
  3028. if (WriteID(writer_header_, libwebm::kMkvSegment))
  3029. return false;
  3030. // Save for later.
  3031. size_position_ = writer_header_->Position();
  3032. // Write "unknown" (EBML coded -1) as segment size value. We need to write 8
  3033. // bytes because if we are going to overwrite the segment size later we do
  3034. // not know how big our segment will be.
  3035. if (SerializeInt(writer_header_, kEbmlUnknownValue, 8))
  3036. return false;
  3037. payload_pos_ = writer_header_->Position();
  3038. if (mode_ == kFile && writer_header_->Seekable()) {
  3039. // Set the duration > 0.0 so SegmentInfo will write out the duration. When
  3040. // the muxer is done writing we will set the correct duration and have
  3041. // SegmentInfo upadte it.
  3042. segment_info_.set_duration(1.0);
  3043. if (!seek_head_.Write(writer_header_))
  3044. return false;
  3045. }
  3046. if (!seek_head_.AddSeekEntry(libwebm::kMkvInfo, MaxOffset()))
  3047. return false;
  3048. if (!segment_info_.Write(writer_header_))
  3049. return false;
  3050. if (!seek_head_.AddSeekEntry(libwebm::kMkvTracks, MaxOffset()))
  3051. return false;
  3052. if (!tracks_.Write(writer_header_))
  3053. return false;
  3054. if (chapters_.Count() > 0) {
  3055. if (!seek_head_.AddSeekEntry(libwebm::kMkvChapters, MaxOffset()))
  3056. return false;
  3057. if (!chapters_.Write(writer_header_))
  3058. return false;
  3059. }
  3060. if (tags_.Count() > 0) {
  3061. if (!seek_head_.AddSeekEntry(libwebm::kMkvTags, MaxOffset()))
  3062. return false;
  3063. if (!tags_.Write(writer_header_))
  3064. return false;
  3065. }
  3066. if (chunking_ && (mode_ == kLive || !writer_header_->Seekable())) {
  3067. if (!chunk_writer_header_)
  3068. return false;
  3069. chunk_writer_header_->Close();
  3070. }
  3071. header_written_ = true;
  3072. return true;
  3073. }
  3074. // Here we are testing whether to create a new cluster, given a frame
  3075. // having time frame_timestamp_ns.
  3076. //
  3077. int Segment::TestFrame(uint64_t track_number, uint64_t frame_timestamp_ns,
  3078. bool is_key) const {
  3079. if (force_new_cluster_)
  3080. return 1;
  3081. // If no clusters have been created yet, then create a new cluster
  3082. // and write this frame immediately, in the new cluster. This path
  3083. // should only be followed once, the first time we attempt to write
  3084. // a frame.
  3085. if (cluster_list_size_ <= 0)
  3086. return 1;
  3087. // There exists at least one cluster. We must compare the frame to
  3088. // the last cluster, in order to determine whether the frame is
  3089. // written to the existing cluster, or that a new cluster should be
  3090. // created.
  3091. const uint64_t timecode_scale = segment_info_.timecode_scale();
  3092. const uint64_t frame_timecode = frame_timestamp_ns / timecode_scale;
  3093. const Cluster* const last_cluster = cluster_list_[cluster_list_size_ - 1];
  3094. const uint64_t last_cluster_timecode = last_cluster->timecode();
  3095. // For completeness we test for the case when the frame's timecode
  3096. // is less than the cluster's timecode. Although in principle that
  3097. // is allowed, this muxer doesn't actually write clusters like that,
  3098. // so this indicates a bug somewhere in our algorithm.
  3099. if (frame_timecode < last_cluster_timecode) // should never happen
  3100. return -1;
  3101. // If the frame has a timestamp significantly larger than the last
  3102. // cluster (in Matroska, cluster-relative timestamps are serialized
  3103. // using a 16-bit signed integer), then we cannot write this frame
  3104. // to that cluster, and so we must create a new cluster.
  3105. const int64_t delta_timecode = frame_timecode - last_cluster_timecode;
  3106. if (delta_timecode > kMaxBlockTimecode)
  3107. return 2;
  3108. // We decide to create a new cluster when we have a video keyframe.
  3109. // This will flush queued (audio) frames, and write the keyframe
  3110. // immediately, in the newly-created cluster.
  3111. if (is_key && tracks_.TrackIsVideo(track_number))
  3112. return 1;
  3113. // Create a new cluster if we have accumulated too many frames
  3114. // already, where "too many" is defined as "the total time of frames
  3115. // in the cluster exceeds a threshold".
  3116. const uint64_t delta_ns = delta_timecode * timecode_scale;
  3117. if (max_cluster_duration_ > 0 && delta_ns >= max_cluster_duration_)
  3118. return 1;
  3119. // This is similar to the case above, with the difference that a new
  3120. // cluster is created when the size of the current cluster exceeds a
  3121. // threshold.
  3122. const uint64_t cluster_size = last_cluster->payload_size();
  3123. if (max_cluster_size_ > 0 && cluster_size >= max_cluster_size_)
  3124. return 1;
  3125. // There's no need to create a new cluster, so emit this frame now.
  3126. return 0;
  3127. }
  3128. bool Segment::MakeNewCluster(uint64_t frame_timestamp_ns) {
  3129. const int32_t new_size = cluster_list_size_ + 1;
  3130. if (new_size > cluster_list_capacity_) {
  3131. // Add more clusters.
  3132. const int32_t new_capacity =
  3133. (cluster_list_capacity_ <= 0) ? 1 : cluster_list_capacity_ * 2;
  3134. Cluster** const clusters =
  3135. new (std::nothrow) Cluster*[new_capacity]; // NOLINT
  3136. if (!clusters)
  3137. return false;
  3138. for (int32_t i = 0; i < cluster_list_size_; ++i) {
  3139. clusters[i] = cluster_list_[i];
  3140. }
  3141. delete[] cluster_list_;
  3142. cluster_list_ = clusters;
  3143. cluster_list_capacity_ = new_capacity;
  3144. }
  3145. if (!WriteFramesLessThan(frame_timestamp_ns))
  3146. return false;
  3147. if (cluster_list_size_ > 0) {
  3148. // Update old cluster's size
  3149. Cluster* const old_cluster = cluster_list_[cluster_list_size_ - 1];
  3150. if (!old_cluster || !old_cluster->Finalize(true, frame_timestamp_ns))
  3151. return false;
  3152. }
  3153. if (output_cues_)
  3154. new_cuepoint_ = true;
  3155. if (chunking_ && cluster_list_size_ > 0) {
  3156. chunk_writer_cluster_->Close();
  3157. chunk_count_++;
  3158. if (!UpdateChunkName("chk", &chunk_name_))
  3159. return false;
  3160. if (!chunk_writer_cluster_->Open(chunk_name_))
  3161. return false;
  3162. }
  3163. const uint64_t timecode_scale = segment_info_.timecode_scale();
  3164. const uint64_t frame_timecode = frame_timestamp_ns / timecode_scale;
  3165. uint64_t cluster_timecode = frame_timecode;
  3166. if (frames_size_ > 0) {
  3167. const Frame* const f = frames_[0]; // earliest queued frame
  3168. const uint64_t ns = f->timestamp();
  3169. const uint64_t tc = ns / timecode_scale;
  3170. if (tc < cluster_timecode)
  3171. cluster_timecode = tc;
  3172. }
  3173. Cluster*& cluster = cluster_list_[cluster_list_size_];
  3174. const int64_t offset = MaxOffset();
  3175. cluster = new (std::nothrow)
  3176. Cluster(cluster_timecode, offset, segment_info_.timecode_scale(),
  3177. accurate_cluster_duration_, fixed_size_cluster_timecode_);
  3178. if (!cluster)
  3179. return false;
  3180. if (!cluster->Init(writer_cluster_))
  3181. return false;
  3182. cluster_list_size_ = new_size;
  3183. return true;
  3184. }
  3185. bool Segment::DoNewClusterProcessing(uint64_t track_number,
  3186. uint64_t frame_timestamp_ns, bool is_key) {
  3187. for (;;) {
  3188. // Based on the characteristics of the current frame and current
  3189. // cluster, decide whether to create a new cluster.
  3190. const int result = TestFrame(track_number, frame_timestamp_ns, is_key);
  3191. if (result < 0) // error
  3192. return false;
  3193. // Always set force_new_cluster_ to false after TestFrame.
  3194. force_new_cluster_ = false;
  3195. // A non-zero result means create a new cluster.
  3196. if (result > 0 && !MakeNewCluster(frame_timestamp_ns))
  3197. return false;
  3198. // Write queued (audio) frames.
  3199. const int frame_count = WriteFramesAll();
  3200. if (frame_count < 0) // error
  3201. return false;
  3202. // Write the current frame to the current cluster (if TestFrame
  3203. // returns 0) or to a newly created cluster (TestFrame returns 1).
  3204. if (result <= 1)
  3205. return true;
  3206. // TestFrame returned 2, which means there was a large time
  3207. // difference between the cluster and the frame itself. Do the
  3208. // test again, comparing the frame to the new cluster.
  3209. }
  3210. }
  3211. bool Segment::CheckHeaderInfo() {
  3212. if (!header_written_) {
  3213. if (!WriteSegmentHeader())
  3214. return false;
  3215. if (!seek_head_.AddSeekEntry(libwebm::kMkvCluster, MaxOffset()))
  3216. return false;
  3217. if (output_cues_ && cues_track_ == 0) {
  3218. // Check for a video track
  3219. for (uint32_t i = 0; i < tracks_.track_entries_size(); ++i) {
  3220. const Track* const track = tracks_.GetTrackByIndex(i);
  3221. if (!track)
  3222. return false;
  3223. if (tracks_.TrackIsVideo(track->number())) {
  3224. cues_track_ = track->number();
  3225. break;
  3226. }
  3227. }
  3228. // Set first track found
  3229. if (cues_track_ == 0) {
  3230. const Track* const track = tracks_.GetTrackByIndex(0);
  3231. if (!track)
  3232. return false;
  3233. cues_track_ = track->number();
  3234. }
  3235. }
  3236. }
  3237. return true;
  3238. }
  3239. void Segment::UpdateDocTypeVersion() {
  3240. for (uint32_t index = 0; index < tracks_.track_entries_size(); ++index) {
  3241. const Track* track = tracks_.GetTrackByIndex(index);
  3242. if (track == NULL)
  3243. break;
  3244. if ((track->codec_delay() || track->seek_pre_roll()) &&
  3245. doc_type_version_ < 4) {
  3246. doc_type_version_ = 4;
  3247. break;
  3248. }
  3249. }
  3250. }
  3251. bool Segment::UpdateChunkName(const char* ext, char** name) const {
  3252. if (!name || !ext)
  3253. return false;
  3254. char ext_chk[64];
  3255. #ifdef _MSC_VER
  3256. sprintf_s(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
  3257. #else
  3258. snprintf(ext_chk, sizeof(ext_chk), "_%06d.%s", chunk_count_, ext);
  3259. #endif
  3260. const size_t length = strlen(chunking_base_name_) + strlen(ext_chk) + 1;
  3261. char* const str = new (std::nothrow) char[length]; // NOLINT
  3262. if (!str)
  3263. return false;
  3264. #ifdef _MSC_VER
  3265. strcpy_s(str, length - strlen(ext_chk), chunking_base_name_);
  3266. strcat_s(str, length, ext_chk);
  3267. #else
  3268. strcpy(str, chunking_base_name_);
  3269. strcat(str, ext_chk);
  3270. #endif
  3271. delete[] * name;
  3272. *name = str;
  3273. return true;
  3274. }
  3275. int64_t Segment::MaxOffset() {
  3276. if (!writer_header_)
  3277. return -1;
  3278. int64_t offset = writer_header_->Position() - payload_pos_;
  3279. if (chunking_) {
  3280. for (int32_t i = 0; i < cluster_list_size_; ++i) {
  3281. Cluster* const cluster = cluster_list_[i];
  3282. offset += cluster->Size();
  3283. }
  3284. if (writer_cues_)
  3285. offset += writer_cues_->Position();
  3286. }
  3287. return offset;
  3288. }
  3289. bool Segment::QueueFrame(Frame* frame) {
  3290. const int32_t new_size = frames_size_ + 1;
  3291. if (new_size > frames_capacity_) {
  3292. // Add more frames.
  3293. const int32_t new_capacity = (!frames_capacity_) ? 2 : frames_capacity_ * 2;
  3294. if (new_capacity < 1)
  3295. return false;
  3296. Frame** const frames = new (std::nothrow) Frame*[new_capacity]; // NOLINT
  3297. if (!frames)
  3298. return false;
  3299. for (int32_t i = 0; i < frames_size_; ++i) {
  3300. frames[i] = frames_[i];
  3301. }
  3302. delete[] frames_;
  3303. frames_ = frames;
  3304. frames_capacity_ = new_capacity;
  3305. }
  3306. frames_[frames_size_++] = frame;
  3307. return true;
  3308. }
  3309. int Segment::WriteFramesAll() {
  3310. if (frames_ == NULL)
  3311. return 0;
  3312. if (cluster_list_size_ < 1)
  3313. return -1;
  3314. Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
  3315. if (!cluster)
  3316. return -1;
  3317. for (int32_t i = 0; i < frames_size_; ++i) {
  3318. Frame*& frame = frames_[i];
  3319. // TODO(jzern/vigneshv): using Segment::AddGenericFrame here would limit the
  3320. // places where |doc_type_version_| needs to be updated.
  3321. if (frame->discard_padding() != 0)
  3322. doc_type_version_ = 4;
  3323. if (!cluster->AddFrame(frame))
  3324. return -1;
  3325. if (new_cuepoint_ && cues_track_ == frame->track_number()) {
  3326. if (!AddCuePoint(frame->timestamp(), cues_track_))
  3327. return -1;
  3328. }
  3329. if (frame->timestamp() > last_timestamp_) {
  3330. last_timestamp_ = frame->timestamp();
  3331. last_track_timestamp_[frame->track_number() - 1] = frame->timestamp();
  3332. }
  3333. delete frame;
  3334. frame = NULL;
  3335. }
  3336. const int result = frames_size_;
  3337. frames_size_ = 0;
  3338. return result;
  3339. }
  3340. bool Segment::WriteFramesLessThan(uint64_t timestamp) {
  3341. // Check |cluster_list_size_| to see if this is the first cluster. If it is
  3342. // the first cluster the audio frames that are less than the first video
  3343. // timesatmp will be written in a later step.
  3344. if (frames_size_ > 0 && cluster_list_size_ > 0) {
  3345. if (!frames_)
  3346. return false;
  3347. Cluster* const cluster = cluster_list_[cluster_list_size_ - 1];
  3348. if (!cluster)
  3349. return false;
  3350. int32_t shift_left = 0;
  3351. // TODO(fgalligan): Change this to use the durations of frames instead of
  3352. // the next frame's start time if the duration is accurate.
  3353. for (int32_t i = 1; i < frames_size_; ++i) {
  3354. const Frame* const frame_curr = frames_[i];
  3355. if (frame_curr->timestamp() > timestamp)
  3356. break;
  3357. const Frame* const frame_prev = frames_[i - 1];
  3358. if (frame_prev->discard_padding() != 0)
  3359. doc_type_version_ = 4;
  3360. if (!cluster->AddFrame(frame_prev))
  3361. return false;
  3362. if (new_cuepoint_ && cues_track_ == frame_prev->track_number()) {
  3363. if (!AddCuePoint(frame_prev->timestamp(), cues_track_))
  3364. return false;
  3365. }
  3366. ++shift_left;
  3367. if (frame_prev->timestamp() > last_timestamp_) {
  3368. last_timestamp_ = frame_prev->timestamp();
  3369. last_track_timestamp_[frame_prev->track_number() - 1] =
  3370. frame_prev->timestamp();
  3371. }
  3372. delete frame_prev;
  3373. }
  3374. if (shift_left > 0) {
  3375. if (shift_left >= frames_size_)
  3376. return false;
  3377. const int32_t new_frames_size = frames_size_ - shift_left;
  3378. for (int32_t i = 0; i < new_frames_size; ++i) {
  3379. frames_[i] = frames_[i + shift_left];
  3380. }
  3381. frames_size_ = new_frames_size;
  3382. }
  3383. }
  3384. return true;
  3385. }
  3386. bool Segment::DocTypeIsWebm() const {
  3387. const int kNumCodecIds = 9;
  3388. // TODO(vigneshv): Tweak .clang-format.
  3389. const char* kWebmCodecIds[kNumCodecIds] = {
  3390. Tracks::kOpusCodecId, Tracks::kVorbisCodecId,
  3391. Tracks::kVp8CodecId, Tracks::kVp9CodecId,
  3392. Tracks::kVp10CodecId, Tracks::kWebVttCaptionsId,
  3393. Tracks::kWebVttDescriptionsId, Tracks::kWebVttMetadataId,
  3394. Tracks::kWebVttSubtitlesId};
  3395. const int num_tracks = static_cast<int>(tracks_.track_entries_size());
  3396. for (int track_index = 0; track_index < num_tracks; ++track_index) {
  3397. const Track* const track = tracks_.GetTrackByIndex(track_index);
  3398. const std::string codec_id = track->codec_id();
  3399. bool id_is_webm = false;
  3400. for (int id_index = 0; id_index < kNumCodecIds; ++id_index) {
  3401. if (codec_id == kWebmCodecIds[id_index]) {
  3402. id_is_webm = true;
  3403. break;
  3404. }
  3405. }
  3406. if (!id_is_webm)
  3407. return false;
  3408. }
  3409. return true;
  3410. }
  3411. } // namespace mkvmuxer