shaka-packager/docs/da/d88/mp4__muxer_8cc_source.html

113 lines
91 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Shaka Packager SDK: packager/media/formats/mp4/mp4_muxer.cc Source File</title>
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">Shaka Packager SDK
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
initMenu('../../',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><a class="el" href="../../dir_3f8eec2fc361645de4b1ec14c19fffc7.html">packager</a></li><li class="navelem"><a class="el" href="../../dir_f99dae54fe7170f791f339b952d5067a.html">media</a></li><li class="navelem"><a class="el" href="../../dir_375ba2cfd8fd5b05c50b92d996b9d386.html">formats</a></li><li class="navelem"><a class="el" href="../../dir_ae142483ff91a68c468a97c037f98d4d.html">mp4</a></li> </ul>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle">
<div class="title">mp4_muxer.cc</div> </div>
</div><!--header-->
<div class="contents">
<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span>&#160;<span class="comment">// Copyright 2014 Google Inc. All rights reserved.</span></div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>&#160;<span class="comment">//</span></div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>&#160;<span class="comment">// Use of this source code is governed by a BSD-style</span></div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>&#160;<span class="comment">// license that can be found in the LICENSE file or at</span></div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>&#160;<span class="comment">// https://developers.google.com/open-source/licenses/bsd</span></div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span>&#160;</div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>&#160;<span class="preprocessor">#include &quot;packager/media/formats/mp4/mp4_muxer.h&quot;</span></div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span>&#160;</div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>&#160;<span class="preprocessor">#include &quot;packager/base/time/clock.h&quot;</span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;<span class="preprocessor">#include &quot;packager/base/time/time.h&quot;</span></div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="preprocessor">#include &quot;packager/file/file.h&quot;</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/aes_encryptor.h&quot;</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/audio_stream_info.h&quot;</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/fourccs.h&quot;</span></div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/key_source.h&quot;</span></div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/media_sample.h&quot;</span></div><div class="line"><a name="l00017"></a><span class="lineno"> 17</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/text_stream_info.h&quot;</span></div><div class="line"><a name="l00018"></a><span class="lineno"> 18</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/video_stream_info.h&quot;</span></div><div class="line"><a name="l00019"></a><span class="lineno"> 19</span>&#160;<span class="preprocessor">#include &quot;packager/media/codecs/es_descriptor.h&quot;</span></div><div class="line"><a name="l00020"></a><span class="lineno"> 20</span>&#160;<span class="preprocessor">#include &quot;packager/media/event/muxer_listener.h&quot;</span></div><div class="line"><a name="l00021"></a><span class="lineno"> 21</span>&#160;<span class="preprocessor">#include &quot;packager/media/formats/mp4/box_definitions.h&quot;</span></div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#include &quot;packager/media/formats/mp4/multi_segment_segmenter.h&quot;</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#include &quot;packager/media/formats/mp4/single_segment_segmenter.h&quot;</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;</div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="keyword">namespace </span><a class="code" href="../../d8/daf/namespaceshaka.html">shaka</a> {</div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;<span class="keyword">namespace </span>media {</div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;<span class="keyword">namespace </span>mp4 {</div><div class="line"><a name="l00028"></a><span class="lineno"> 28</span>&#160;</div><div class="line"><a name="l00029"></a><span class="lineno"> 29</span>&#160;<span class="keyword">namespace </span>{</div><div class="line"><a name="l00030"></a><span class="lineno"> 30</span>&#160;</div><div class="line"><a name="l00031"></a><span class="lineno"> 31</span>&#160;<span class="comment">// Sets the range start and end value from offset and size.</span></div><div class="line"><a name="l00032"></a><span class="lineno"> 32</span>&#160;<span class="comment">// |start| and |end| are for byte-range-spec specified in RFC2616.</span></div><div class="line"><a name="l00033"></a><span class="lineno"> 33</span>&#160;<span class="keywordtype">void</span> SetStartAndEndFromOffsetAndSize(<span class="keywordtype">size_t</span> offset,</div><div class="line"><a name="l00034"></a><span class="lineno"> 34</span>&#160; <span class="keywordtype">size_t</span> size,</div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span>&#160; Range* range) {</div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160; DCHECK(range);</div><div class="line"><a name="l00037"></a><span class="lineno"> 37</span>&#160; range-&gt;start = <span class="keyword">static_cast&lt;</span>uint32_t<span class="keyword">&gt;</span>(offset);</div><div class="line"><a name="l00038"></a><span class="lineno"> 38</span>&#160; <span class="comment">// Note that ranges are inclusive. So we need - 1.</span></div><div class="line"><a name="l00039"></a><span class="lineno"> 39</span>&#160; range-&gt;end = range-&gt;start + <span class="keyword">static_cast&lt;</span>uint32_t<span class="keyword">&gt;</span>(size) - 1;</div><div class="line"><a name="l00040"></a><span class="lineno"> 40</span>&#160;}</div><div class="line"><a name="l00041"></a><span class="lineno"> 41</span>&#160;</div><div class="line"><a name="l00042"></a><span class="lineno"> 42</span>&#160;FourCC CodecToFourCC(Codec codec, H26xStreamFormat h26x_stream_format) {</div><div class="line"><a name="l00043"></a><span class="lineno"> 43</span>&#160; <span class="keywordflow">switch</span> (codec) {</div><div class="line"><a name="l00044"></a><span class="lineno"> 44</span>&#160; <span class="keywordflow">case</span> kCodecH264:</div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160; <span class="keywordflow">return</span> h26x_stream_format ==</div><div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160; H26xStreamFormat::kNalUnitStreamWithParameterSetNalus</div><div class="line"><a name="l00047"></a><span class="lineno"> 47</span>&#160; ? FOURCC_avc3</div><div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160; : FOURCC_avc1;</div><div class="line"><a name="l00049"></a><span class="lineno"> 49</span>&#160; <span class="keywordflow">case</span> kCodecH265:</div><div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160; <span class="keywordflow">return</span> h26x_stream_format ==</div><div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160; H26xStreamFormat::kNalUnitStreamWithParameterSetNalus</div><div class="line"><a name="l00052"></a><span class="lineno"> 52</span>&#160; ? FOURCC_hev1</div><div class="line"><a name="l00053"></a><span class="lineno"> 53</span>&#160; : FOURCC_hvc1;</div><div class="line"><a name="l00054"></a><span class="lineno"> 54</span>&#160; <span class="keywordflow">case</span> kCodecVP8:</div><div class="line"><a name="l00055"></a><span class="lineno"> 55</span>&#160; <span class="keywordflow">return</span> FOURCC_vp08;</div><div class="line"><a name="l00056"></a><span class="lineno"> 56</span>&#160; <span class="keywordflow">case</span> kCodecVP9:</div><div class="line"><a name="l00057"></a><span class="lineno"> 57</span>&#160; <span class="keywordflow">return</span> FOURCC_vp09;</div><div class="line"><a name="l00058"></a><span class="lineno"> 58</span>&#160; <span class="keywordflow">case</span> kCodecVP10:</div><div class="line"><a name="l00059"></a><span class="lineno"> 59</span>&#160; <span class="keywordflow">return</span> FOURCC_vp10;</div><div class="line"><a name="l00060"></a><span class="lineno"> 60</span>&#160; <span class="keywordflow">case</span> kCodecAAC:</div><div class="line"><a name="l00061"></a><span class="lineno"> 61</span>&#160; <span class="keywordflow">return</span> FOURCC_mp4a;</div><div class="line"><a name="l00062"></a><span class="lineno"> 62</span>&#160; <span class="keywordflow">case</span> kCodecAC3:</div><div class="line"><a name="l00063"></a><span class="lineno"> 63</span>&#160; <span class="keywordflow">return</span> FOURCC_ac_3;</div><div class="line"><a name="l00064"></a><span class="lineno"> 64</span>&#160; <span class="keywordflow">case</span> kCodecDTSC:</div><div class="line"><a name="l00065"></a><span class="lineno"> 65</span>&#160; <span class="keywordflow">return</span> FOURCC_dtsc;</div><div class="line"><a name="l00066"></a><span class="lineno"> 66</span>&#160; <span class="keywordflow">case</span> kCodecDTSH:</div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span>&#160; <span class="keywordflow">return</span> FOURCC_dtsh;</div><div class="line"><a name="l00068"></a><span class="lineno"> 68</span>&#160; <span class="keywordflow">case</span> kCodecDTSL:</div><div class="line"><a name="l00069"></a><span class="lineno"> 69</span>&#160; <span class="keywordflow">return</span> FOURCC_dtsl;</div><div class="line"><a name="l00070"></a><span class="lineno"> 70</span>&#160; <span class="keywordflow">case</span> kCodecDTSE:</div><div class="line"><a name="l00071"></a><span class="lineno"> 71</span>&#160; <span class="keywordflow">return</span> FOURCC_dtse;</div><div class="line"><a name="l00072"></a><span class="lineno"> 72</span>&#160; <span class="keywordflow">case</span> kCodecDTSM:</div><div class="line"><a name="l00073"></a><span class="lineno"> 73</span>&#160; <span class="keywordflow">return</span> FOURCC_dtsm;</div><div class="line"><a name="l00074"></a><span class="lineno"> 74</span>&#160; <span class="keywordflow">case</span> kCodecEAC3:</div><div class="line"><a name="l00075"></a><span class="lineno"> 75</span>&#160; <span class="keywordflow">return</span> FOURCC_ec_3;</div><div class="line"><a name="l00076"></a><span class="lineno"> 76</span>&#160; <span class="keywordflow">case</span> kCodecOpus:</div><div class="line"><a name="l00077"></a><span class="lineno"> 77</span>&#160; <span class="keywordflow">return</span> FOURCC_Opus;</div><div class="line"><a name="l00078"></a><span class="lineno"> 78</span>&#160; <span class="keywordflow">default</span>:</div><div class="line"><a name="l00079"></a><span class="lineno"> 79</span>&#160; <span class="keywordflow">return</span> FOURCC_NULL;</div><div class="line"><a name="l00080"></a><span class="lineno"> 80</span>&#160; }</div><div class="line"><a name="l00081"></a><span class="lineno"> 81</span>&#160;}</div><div class="line"><a name="l00082"></a><span class="lineno"> 82</span>&#160;</div><div class="line"><a name="l00083"></a><span class="lineno"> 83</span>&#160;<span class="keywordtype">void</span> GenerateSinf(FourCC old_type,</div><div class="line"><a name="l00084"></a><span class="lineno"> 84</span>&#160; <span class="keyword">const</span> EncryptionConfig&amp; encryption_config,</div><div class="line"><a name="l00085"></a><span class="lineno"> 85</span>&#160; ProtectionSchemeInfo* sinf) {</div><div class="line"><a name="l00086"></a><span class="lineno"> 86</span>&#160; sinf-&gt;format.format = old_type;</div><div class="line"><a name="l00087"></a><span class="lineno"> 87</span>&#160;</div><div class="line"><a name="l00088"></a><span class="lineno"> 88</span>&#160; DCHECK_NE(encryption_config.protection_scheme, FOURCC_NULL);</div><div class="line"><a name="l00089"></a><span class="lineno"> 89</span>&#160; sinf-&gt;type.type = encryption_config.protection_scheme;</div><div class="line"><a name="l00090"></a><span class="lineno"> 90</span>&#160;</div><div class="line"><a name="l00091"></a><span class="lineno"> 91</span>&#160; <span class="comment">// The version of cenc implemented here. CENC 4.</span></div><div class="line"><a name="l00092"></a><span class="lineno"> 92</span>&#160; <span class="keyword">const</span> <span class="keywordtype">int</span> kCencSchemeVersion = 0x00010000;</div><div class="line"><a name="l00093"></a><span class="lineno"> 93</span>&#160; sinf-&gt;type.version = kCencSchemeVersion;</div><div class="line"><a name="l00094"></a><span class="lineno"> 94</span>&#160;</div><div class="line"><a name="l00095"></a><span class="lineno"> 95</span>&#160; <span class="keyword">auto</span>&amp; track_encryption = sinf-&gt;info.track_encryption;</div><div class="line"><a name="l00096"></a><span class="lineno"> 96</span>&#160; track_encryption.default_is_protected = 1;</div><div class="line"><a name="l00097"></a><span class="lineno"> 97</span>&#160;</div><div class="line"><a name="l00098"></a><span class="lineno"> 98</span>&#160; track_encryption.default_crypt_byte_block =</div><div class="line"><a name="l00099"></a><span class="lineno"> 99</span>&#160; encryption_config.crypt_byte_block;</div><div class="line"><a name="l00100"></a><span class="lineno"> 100</span>&#160; track_encryption.default_skip_byte_block = encryption_config.skip_byte_block;</div><div class="line"><a name="l00101"></a><span class="lineno"> 101</span>&#160; <span class="keywordflow">switch</span> (encryption_config.protection_scheme) {</div><div class="line"><a name="l00102"></a><span class="lineno"> 102</span>&#160; <span class="keywordflow">case</span> FOURCC_cenc:</div><div class="line"><a name="l00103"></a><span class="lineno"> 103</span>&#160; <span class="keywordflow">case</span> FOURCC_cbc1:</div><div class="line"><a name="l00104"></a><span class="lineno"> 104</span>&#160; DCHECK_EQ(track_encryption.default_crypt_byte_block, 0u);</div><div class="line"><a name="l00105"></a><span class="lineno"> 105</span>&#160; DCHECK_EQ(track_encryption.default_skip_byte_block, 0u);</div><div class="line"><a name="l00106"></a><span class="lineno"> 106</span>&#160; <span class="comment">// CENCv3 10.1 cenc AES-CTR scheme and 10.2 cbc1 AES-CBC scheme:</span></div><div class="line"><a name="l00107"></a><span class="lineno"> 107</span>&#160; <span class="comment">// The version of the Track Encryption Box (tenc) SHALL be 0.</span></div><div class="line"><a name="l00108"></a><span class="lineno"> 108</span>&#160; track_encryption.version = 0;</div><div class="line"><a name="l00109"></a><span class="lineno"> 109</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00110"></a><span class="lineno"> 110</span>&#160; <span class="keywordflow">case</span> FOURCC_cbcs:</div><div class="line"><a name="l00111"></a><span class="lineno"> 111</span>&#160; <span class="keywordflow">case</span> FOURCC_cens:</div><div class="line"><a name="l00112"></a><span class="lineno"> 112</span>&#160; <span class="keywordflow">if</span> (track_encryption.default_skip_byte_block == 0) {</div><div class="line"><a name="l00113"></a><span class="lineno"> 113</span>&#160; <span class="comment">// Some clients, e.g. Safari v11.0.3 does not like having</span></div><div class="line"><a name="l00114"></a><span class="lineno"> 114</span>&#160; <span class="comment">// crypt_byte_block as a non-zero value when skip_byte_block is zero.</span></div><div class="line"><a name="l00115"></a><span class="lineno"> 115</span>&#160; track_encryption.default_crypt_byte_block = 0;</div><div class="line"><a name="l00116"></a><span class="lineno"> 116</span>&#160; }</div><div class="line"><a name="l00117"></a><span class="lineno"> 117</span>&#160; <span class="comment">// CENCv3 10.3 cens AES-CTR subsample pattern encryption scheme and</span></div><div class="line"><a name="l00118"></a><span class="lineno"> 118</span>&#160; <span class="comment">// 10.4 cbcs AES-CBC subsample pattern encryption scheme:</span></div><div class="line"><a name="l00119"></a><span class="lineno"> 119</span>&#160; <span class="comment">// The version of the Track Encryption Box (tenc) SHALL be 1.</span></div><div class="line"><a name="l00120"></a><span class="lineno"> 120</span>&#160; track_encryption.version = 1;</div><div class="line"><a name="l00121"></a><span class="lineno"> 121</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00122"></a><span class="lineno"> 122</span>&#160; <span class="keywordflow">default</span>:</div><div class="line"><a name="l00123"></a><span class="lineno"> 123</span>&#160; NOTREACHED() &lt;&lt; <span class="stringliteral">&quot;Unexpected protection scheme &quot;</span></div><div class="line"><a name="l00124"></a><span class="lineno"> 124</span>&#160; &lt;&lt; encryption_config.protection_scheme;</div><div class="line"><a name="l00125"></a><span class="lineno"> 125</span>&#160; }</div><div class="line"><a name="l00126"></a><span class="lineno"> 126</span>&#160;</div><div class="line"><a name="l00127"></a><span class="lineno"> 127</span>&#160; track_encryption.default_per_sample_iv_size =</div><div class="line"><a name="l00128"></a><span class="lineno"> 128</span>&#160; encryption_config.per_sample_iv_size;</div><div class="line"><a name="l00129"></a><span class="lineno"> 129</span>&#160; track_encryption.default_constant_iv = encryption_config.constant_iv;</div><div class="line"><a name="l00130"></a><span class="lineno"> 130</span>&#160; track_encryption.default_kid = encryption_config.key_id;</div><div class="line"><a name="l00131"></a><span class="lineno"> 131</span>&#160;}</div><div class="line"><a name="l00132"></a><span class="lineno"> 132</span>&#160;</div><div class="line"><a name="l00133"></a><span class="lineno"> 133</span>&#160;} <span class="comment">// namespace</span></div><div class="line"><a name="l00134"></a><span class="lineno"> 134</span>&#160;</div><div class="line"><a name="l00135"></a><span class="lineno"><a class="line" href="../../db/d30/classshaka_1_1media_1_1mp4_1_1MP4Muxer.html#a5b6a878865250e3e17268c011a361497"> 135</a></span>&#160;<a class="code" href="../../db/d30/classshaka_1_1media_1_1mp4_1_1MP4Muxer.html#a5b6a878865250e3e17268c011a361497">MP4Muxer::MP4Muxer</a>(<span class="keyword">const</span> <a class="code" href="../../d0/d27/structshaka_1_1media_1_1MuxerOptions.html">MuxerOptions</a>&amp; options) : <a class="code" href="../../df/d46/classshaka_1_1media_1_1Muxer.html">Muxer</a>(options) {}</div><div class="line"><a name="l00136"></a><span class="lineno"> 136</span>&#160;MP4Muxer::~MP4Muxer() {}</div><div class="line"><a name="l00137"></a><span class="lineno"> 137</span>&#160;</div><div class="line"><a name="l00138"></a><span class="lineno"> 138</span>&#160;<a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> MP4Muxer::InitializeMuxer() {</div><div class="line"><a name="l00139"></a><span class="lineno"> 139</span>&#160; DCHECK(!streams().empty());</div><div class="line"><a name="l00140"></a><span class="lineno"> 140</span>&#160;</div><div class="line"><a name="l00141"></a><span class="lineno"> 141</span>&#160; std::unique_ptr&lt;FileType&gt; ftyp(<span class="keyword">new</span> <a class="code" href="../../d5/d03/structshaka_1_1media_1_1mp4_1_1FileType.html">FileType</a>);</div><div class="line"><a name="l00142"></a><span class="lineno"> 142</span>&#160; std::unique_ptr&lt;Movie&gt; moov(<span class="keyword">new</span> <a class="code" href="../../d0/d9a/structshaka_1_1media_1_1mp4_1_1Movie.html">Movie</a>);</div><div class="line"><a name="l00143"></a><span class="lineno"> 143</span>&#160;</div><div class="line"><a name="l00144"></a><span class="lineno"> 144</span>&#160; ftyp-&gt;major_brand = FOURCC_isom;</div><div class="line"><a name="l00145"></a><span class="lineno"> 145</span>&#160; ftyp-&gt;compatible_brands.push_back(FOURCC_iso8);</div><div class="line"><a name="l00146"></a><span class="lineno"> 146</span>&#160; ftyp-&gt;compatible_brands.push_back(FOURCC_mp41);</div><div class="line"><a name="l00147"></a><span class="lineno"> 147</span>&#160; ftyp-&gt;compatible_brands.push_back(FOURCC_dash);</div><div class="line"><a name="l00148"></a><span class="lineno"> 148</span>&#160;</div><div class="line"><a name="l00149"></a><span class="lineno"> 149</span>&#160; <span class="keywordflow">if</span> (streams().size() == 1) {</div><div class="line"><a name="l00150"></a><span class="lineno"> 150</span>&#160; FourCC codec_fourcc = FOURCC_NULL;</div><div class="line"><a name="l00151"></a><span class="lineno"> 151</span>&#160; <span class="keywordflow">if</span> (streams()[0]-&gt;stream_type() == kStreamVideo) {</div><div class="line"><a name="l00152"></a><span class="lineno"> 152</span>&#160; codec_fourcc =</div><div class="line"><a name="l00153"></a><span class="lineno"> 153</span>&#160; CodecToFourCC(streams()[0]-&gt;codec(),</div><div class="line"><a name="l00154"></a><span class="lineno"> 154</span>&#160; static_cast&lt;const VideoStreamInfo*&gt;(streams()[0].<span class="keyword">get</span>())</div><div class="line"><a name="l00155"></a><span class="lineno"> 155</span>&#160; -&gt;h26x_stream_format());</div><div class="line"><a name="l00156"></a><span class="lineno"> 156</span>&#160; <span class="keywordflow">if</span> (codec_fourcc != FOURCC_NULL)</div><div class="line"><a name="l00157"></a><span class="lineno"> 157</span>&#160; ftyp-&gt;compatible_brands.push_back(codec_fourcc);</div><div class="line"><a name="l00158"></a><span class="lineno"> 158</span>&#160; }</div><div class="line"><a name="l00159"></a><span class="lineno"> 159</span>&#160;</div><div class="line"><a name="l00160"></a><span class="lineno"> 160</span>&#160; <span class="comment">// CMAF allows only one track/stream per file.</span></div><div class="line"><a name="l00161"></a><span class="lineno"> 161</span>&#160; <span class="comment">// CMAF requires single initialization switching for AVC3/HEV1, which is not</span></div><div class="line"><a name="l00162"></a><span class="lineno"> 162</span>&#160; <span class="comment">// supported yet.</span></div><div class="line"><a name="l00163"></a><span class="lineno"> 163</span>&#160; <span class="keywordflow">if</span> (codec_fourcc != FOURCC_avc3 &amp;&amp; codec_fourcc != FOURCC_hev1)</div><div class="line"><a name="l00164"></a><span class="lineno"> 164</span>&#160; ftyp-&gt;compatible_brands.push_back(FOURCC_cmfc);</div><div class="line"><a name="l00165"></a><span class="lineno"> 165</span>&#160; }</div><div class="line"><a name="l00166"></a><span class="lineno"> 166</span>&#160;</div><div class="line"><a name="l00167"></a><span class="lineno"> 167</span>&#160; moov-&gt;header.creation_time = IsoTimeNow();</div><div class="line"><a name="l00168"></a><span class="lineno"> 168</span>&#160; moov-&gt;header.modification_time = IsoTimeNow();</div><div class="line"><a name="l00169"></a><span class="lineno"> 169</span>&#160; moov-&gt;header.next_track_id = <span class="keyword">static_cast&lt;</span>uint32_t<span class="keyword">&gt;</span>(streams().size()) + 1;</div><div class="line"><a name="l00170"></a><span class="lineno"> 170</span>&#160;</div><div class="line"><a name="l00171"></a><span class="lineno"> 171</span>&#160; moov-&gt;tracks.resize(streams().size());</div><div class="line"><a name="l00172"></a><span class="lineno"> 172</span>&#160; moov-&gt;extends.tracks.resize(streams().size());</div><div class="line"><a name="l00173"></a><span class="lineno"> 173</span>&#160;</div><div class="line"><a name="l00174"></a><span class="lineno"> 174</span>&#160; <span class="comment">// Initialize tracks.</span></div><div class="line"><a name="l00175"></a><span class="lineno"> 175</span>&#160; <span class="keywordflow">for</span> (uint32_t i = 0; i &lt; streams().size(); ++i) {</div><div class="line"><a name="l00176"></a><span class="lineno"> 176</span>&#160; <a class="code" href="../../d3/db5/structshaka_1_1media_1_1mp4_1_1Track.html">Track</a>&amp; trak = moov-&gt;tracks[i];</div><div class="line"><a name="l00177"></a><span class="lineno"> 177</span>&#160; trak.header.track_id = i + 1;</div><div class="line"><a name="l00178"></a><span class="lineno"> 178</span>&#160;</div><div class="line"><a name="l00179"></a><span class="lineno"> 179</span>&#160; <a class="code" href="../../de/d29/structshaka_1_1media_1_1mp4_1_1TrackExtends.html">TrackExtends</a>&amp; trex = moov-&gt;extends.tracks[i];</div><div class="line"><a name="l00180"></a><span class="lineno"> 180</span>&#160; trex.track_id = trak.header.track_id;</div><div class="line"><a name="l00181"></a><span class="lineno"> 181</span>&#160; trex.default_sample_description_index = 1;</div><div class="line"><a name="l00182"></a><span class="lineno"> 182</span>&#160;</div><div class="line"><a name="l00183"></a><span class="lineno"> 183</span>&#160; <span class="keywordflow">switch</span> (streams()[i]-&gt;stream_type()) {</div><div class="line"><a name="l00184"></a><span class="lineno"> 184</span>&#160; <span class="keywordflow">case</span> kStreamVideo:</div><div class="line"><a name="l00185"></a><span class="lineno"> 185</span>&#160; GenerateVideoTrak(</div><div class="line"><a name="l00186"></a><span class="lineno"> 186</span>&#160; static_cast&lt;const VideoStreamInfo*&gt;(streams()[i].<span class="keyword">get</span>()),</div><div class="line"><a name="l00187"></a><span class="lineno"> 187</span>&#160; &amp;trak,</div><div class="line"><a name="l00188"></a><span class="lineno"> 188</span>&#160; i + 1);</div><div class="line"><a name="l00189"></a><span class="lineno"> 189</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00190"></a><span class="lineno"> 190</span>&#160; <span class="keywordflow">case</span> kStreamAudio:</div><div class="line"><a name="l00191"></a><span class="lineno"> 191</span>&#160; GenerateAudioTrak(</div><div class="line"><a name="l00192"></a><span class="lineno"> 192</span>&#160; static_cast&lt;const AudioStreamInfo*&gt;(streams()[i].<span class="keyword">get</span>()),</div><div class="line"><a name="l00193"></a><span class="lineno"> 193</span>&#160; &amp;trak,</div><div class="line"><a name="l00194"></a><span class="lineno"> 194</span>&#160; i + 1);</div><div class="line"><a name="l00195"></a><span class="lineno"> 195</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00196"></a><span class="lineno"> 196</span>&#160; <span class="keywordflow">case</span> kStreamText:</div><div class="line"><a name="l00197"></a><span class="lineno"> 197</span>&#160; GenerateTextTrak(</div><div class="line"><a name="l00198"></a><span class="lineno"> 198</span>&#160; static_cast&lt;const TextStreamInfo*&gt;(streams()[i].<span class="keyword">get</span>()),</div><div class="line"><a name="l00199"></a><span class="lineno"> 199</span>&#160; &amp;trak,</div><div class="line"><a name="l00200"></a><span class="lineno"> 200</span>&#160; i + 1);</div><div class="line"><a name="l00201"></a><span class="lineno"> 201</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00202"></a><span class="lineno"> 202</span>&#160; <span class="keywordflow">default</span>:</div><div class="line"><a name="l00203"></a><span class="lineno"> 203</span>&#160; NOTIMPLEMENTED() &lt;&lt; <span class="stringliteral">&quot;Not implemented for stream type: &quot;</span></div><div class="line"><a name="l00204"></a><span class="lineno"> 204</span>&#160; &lt;&lt; streams()[i]-&gt;stream_type();</div><div class="line"><a name="l00205"></a><span class="lineno"> 205</span>&#160; }</div><div class="line"><a name="l00206"></a><span class="lineno"> 206</span>&#160;</div><div class="line"><a name="l00207"></a><span class="lineno"> 207</span>&#160; <span class="keywordflow">if</span> (streams()[i]-&gt;is_encrypted() &amp;&amp;</div><div class="line"><a name="l00208"></a><span class="lineno"> 208</span>&#160; options().mp4_params.include_pssh_in_stream) {</div><div class="line"><a name="l00209"></a><span class="lineno"> 209</span>&#160; <span class="keyword">const</span> <span class="keyword">auto</span>&amp; key_system_info =</div><div class="line"><a name="l00210"></a><span class="lineno"> 210</span>&#160; streams()[i]-&gt;encryption_config().key_system_info;</div><div class="line"><a name="l00211"></a><span class="lineno"> 211</span>&#160; moov-&gt;pssh.resize(key_system_info.size());</div><div class="line"><a name="l00212"></a><span class="lineno"> 212</span>&#160; <span class="keywordflow">for</span> (<span class="keywordtype">size_t</span> j = 0; j &lt; key_system_info.size(); j++)</div><div class="line"><a name="l00213"></a><span class="lineno"> 213</span>&#160; moov-&gt;pssh[j].raw_box = key_system_info[j].CreateBox();</div><div class="line"><a name="l00214"></a><span class="lineno"> 214</span>&#160; }</div><div class="line"><a name="l00215"></a><span class="lineno"> 215</span>&#160; }</div><div class="line"><a name="l00216"></a><span class="lineno"> 216</span>&#160;</div><div class="line"><a name="l00217"></a><span class="lineno"> 217</span>&#160; <span class="keywordflow">if</span> (options().segment_template.empty()) {</div><div class="line"><a name="l00218"></a><span class="lineno"> 218</span>&#160; segmenter_.reset(<span class="keyword">new</span> <a class="code" href="../../d0/dab/classshaka_1_1media_1_1mp4_1_1SingleSegmentSegmenter.html">SingleSegmentSegmenter</a>(options(), std::move(ftyp),</div><div class="line"><a name="l00219"></a><span class="lineno"> 219</span>&#160; std::move(moov)));</div><div class="line"><a name="l00220"></a><span class="lineno"> 220</span>&#160; } <span class="keywordflow">else</span> {</div><div class="line"><a name="l00221"></a><span class="lineno"> 221</span>&#160; segmenter_.reset(</div><div class="line"><a name="l00222"></a><span class="lineno"> 222</span>&#160; <span class="keyword">new</span> <a class="code" href="../../d8/db7/classshaka_1_1media_1_1mp4_1_1MultiSegmentSegmenter.html">MultiSegmentSegmenter</a>(options(), std::move(ftyp), std::move(moov)));</div><div class="line"><a name="l00223"></a><span class="lineno"> 223</span>&#160; }</div><div class="line"><a name="l00224"></a><span class="lineno"> 224</span>&#160;</div><div class="line"><a name="l00225"></a><span class="lineno"> 225</span>&#160; <span class="keyword">const</span> <a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> segmenter_initialized =</div><div class="line"><a name="l00226"></a><span class="lineno"> 226</span>&#160; segmenter_-&gt;Initialize(streams(), muxer_listener(), progress_listener());</div><div class="line"><a name="l00227"></a><span class="lineno"> 227</span>&#160; <span class="keywordflow">if</span> (!segmenter_initialized.ok())</div><div class="line"><a name="l00228"></a><span class="lineno"> 228</span>&#160; <span class="keywordflow">return</span> segmenter_initialized;</div><div class="line"><a name="l00229"></a><span class="lineno"> 229</span>&#160;</div><div class="line"><a name="l00230"></a><span class="lineno"> 230</span>&#160; FireOnMediaStartEvent();</div><div class="line"><a name="l00231"></a><span class="lineno"> 231</span>&#160; <span class="keywordflow">return</span> Status::OK;</div><div class="line"><a name="l00232"></a><span class="lineno"> 232</span>&#160;}</div><div class="line"><a name="l00233"></a><span class="lineno"> 233</span>&#160;</div><div class="line"><a name="l00234"></a><span class="lineno"> 234</span>&#160;<a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> MP4Muxer::Finalize() {</div><div class="line"><a name="l00235"></a><span class="lineno"> 235</span>&#160; DCHECK(segmenter_);</div><div class="line"><a name="l00236"></a><span class="lineno"> 236</span>&#160; <a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> segmenter_finalized = segmenter_-&gt;Finalize();</div><div class="line"><a name="l00237"></a><span class="lineno"> 237</span>&#160;</div><div class="line"><a name="l00238"></a><span class="lineno"> 238</span>&#160; <span class="keywordflow">if</span> (!segmenter_finalized.ok())</div><div class="line"><a name="l00239"></a><span class="lineno"> 239</span>&#160; <span class="keywordflow">return</span> segmenter_finalized;</div><div class="line"><a name="l00240"></a><span class="lineno"> 240</span>&#160;</div><div class="line"><a name="l00241"></a><span class="lineno"> 241</span>&#160; FireOnMediaEndEvent();</div><div class="line"><a name="l00242"></a><span class="lineno"> 242</span>&#160; LOG(INFO) &lt;&lt; <span class="stringliteral">&quot;MP4 file &#39;&quot;</span> &lt;&lt; options().<a class="code" href="../../d0/d27/structshaka_1_1media_1_1MuxerOptions.html#a5397ee8759a663aea68261600e528d82">output_file_name</a> &lt;&lt; <span class="stringliteral">&quot;&#39; finalized.&quot;</span>;</div><div class="line"><a name="l00243"></a><span class="lineno"> 243</span>&#160; <span class="keywordflow">return</span> Status::OK;</div><div class="line"><a name="l00244"></a><span class="lineno"> 244</span>&#160;}</div><div class="line"><a name="l00245"></a><span class="lineno"> 245</span>&#160;</div><div class="line"><a name="l00246"></a><span class="lineno"> 246</span>&#160;<a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> MP4Muxer::AddSample(<span class="keywordtype">size_t</span> stream_id, <span class="keyword">const</span> <a class="code" href="../../d7/d6d/classshaka_1_1media_1_1MediaSample.html">MediaSample</a>&amp; sample) {</div><div class="line"><a name="l00247"></a><span class="lineno"> 247</span>&#160; DCHECK(segmenter_);</div><div class="line"><a name="l00248"></a><span class="lineno"> 248</span>&#160; <span class="keywordflow">return</span> segmenter_-&gt;AddSample(stream_id, sample);</div><div class="line"><a name="l00249"></a><span class="lineno"> 249</span>&#160;}</div><div class="line"><a name="l00250"></a><span class="lineno"> 250</span>&#160;</div><div class="line"><a name="l00251"></a><span class="lineno"> 251</span>&#160;<a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> MP4Muxer::FinalizeSegment(<span class="keywordtype">size_t</span> stream_id,</div><div class="line"><a name="l00252"></a><span class="lineno"> 252</span>&#160; <span class="keyword">const</span> <a class="code" href="../../d0/dc0/structshaka_1_1media_1_1SegmentInfo.html">SegmentInfo</a>&amp; segment_info) {</div><div class="line"><a name="l00253"></a><span class="lineno"> 253</span>&#160; DCHECK(segmenter_);</div><div class="line"><a name="l00254"></a><span class="lineno"> 254</span>&#160; VLOG(3) &lt;&lt; <span class="stringliteral">&quot;Finalize &quot;</span> &lt;&lt; (segment_info.is_subsegment ? <span class="stringliteral">&quot;sub&quot;</span> : <span class="stringliteral">&quot;&quot;</span>)</div><div class="line"><a name="l00255"></a><span class="lineno"> 255</span>&#160; &lt;&lt; <span class="stringliteral">&quot;segment &quot;</span> &lt;&lt; segment_info.start_timestamp &lt;&lt; <span class="stringliteral">&quot; duration &quot;</span></div><div class="line"><a name="l00256"></a><span class="lineno"> 256</span>&#160; &lt;&lt; segment_info.duration;</div><div class="line"><a name="l00257"></a><span class="lineno"> 257</span>&#160; <span class="keywordflow">return</span> segmenter_-&gt;FinalizeSegment(stream_id, segment_info);</div><div class="line"><a name="l00258"></a><span class="lineno"> 258</span>&#160;}</div><div class="line"><a name="l00259"></a><span class="lineno"> 259</span>&#160;</div><div class="line"><a name="l00260"></a><span class="lineno"> 260</span>&#160;<span class="keywordtype">void</span> MP4Muxer::InitializeTrak(<span class="keyword">const</span> <a class="code" href="../../d5/db1/classshaka_1_1media_1_1StreamInfo.html">StreamInfo</a>* info, <a class="code" href="../../d3/db5/structshaka_1_1media_1_1mp4_1_1Track.html">Track</a>* trak) {</div><div class="line"><a name="l00261"></a><span class="lineno"> 261</span>&#160; int64_t now = IsoTimeNow();</div><div class="line"><a name="l00262"></a><span class="lineno"> 262</span>&#160; trak-&gt;header.creation_time = now;</div><div class="line"><a name="l00263"></a><span class="lineno"> 263</span>&#160; trak-&gt;header.modification_time = now;</div><div class="line"><a name="l00264"></a><span class="lineno"> 264</span>&#160; trak-&gt;header.duration = 0;</div><div class="line"><a name="l00265"></a><span class="lineno"> 265</span>&#160; trak-&gt;media.header.creation_time = now;</div><div class="line"><a name="l00266"></a><span class="lineno"> 266</span>&#160; trak-&gt;media.header.modification_time = now;</div><div class="line"><a name="l00267"></a><span class="lineno"> 267</span>&#160; trak-&gt;media.header.timescale = info-&gt;time_scale();</div><div class="line"><a name="l00268"></a><span class="lineno"> 268</span>&#160; trak-&gt;media.header.duration = 0;</div><div class="line"><a name="l00269"></a><span class="lineno"> 269</span>&#160; <span class="keywordflow">if</span> (!info-&gt;language().empty()) {</div><div class="line"><a name="l00270"></a><span class="lineno"> 270</span>&#160; <span class="comment">// Strip off the subtag, if any.</span></div><div class="line"><a name="l00271"></a><span class="lineno"> 271</span>&#160; std::string main_language = info-&gt;language();</div><div class="line"><a name="l00272"></a><span class="lineno"> 272</span>&#160; <span class="keywordtype">size_t</span> dash = main_language.find(<span class="charliteral">&#39;-&#39;</span>);</div><div class="line"><a name="l00273"></a><span class="lineno"> 273</span>&#160; <span class="keywordflow">if</span> (dash != std::string::npos) {</div><div class="line"><a name="l00274"></a><span class="lineno"> 274</span>&#160; main_language.erase(dash);</div><div class="line"><a name="l00275"></a><span class="lineno"> 275</span>&#160; }</div><div class="line"><a name="l00276"></a><span class="lineno"> 276</span>&#160;</div><div class="line"><a name="l00277"></a><span class="lineno"> 277</span>&#160; <span class="comment">// ISO-639-2/T main language code should be 3 characters.</span></div><div class="line"><a name="l00278"></a><span class="lineno"> 278</span>&#160; <span class="keywordflow">if</span> (main_language.size() != 3) {</div><div class="line"><a name="l00279"></a><span class="lineno"> 279</span>&#160; LOG(WARNING) &lt;&lt; <span class="stringliteral">&quot;&#39;&quot;</span> &lt;&lt; main_language &lt;&lt; <span class="stringliteral">&quot;&#39; is not a valid ISO-639-2 &quot;</span></div><div class="line"><a name="l00280"></a><span class="lineno"> 280</span>&#160; &lt;&lt; <span class="stringliteral">&quot;language code, ignoring.&quot;</span>;</div><div class="line"><a name="l00281"></a><span class="lineno"> 281</span>&#160; } <span class="keywordflow">else</span> {</div><div class="line"><a name="l00282"></a><span class="lineno"> 282</span>&#160; trak-&gt;media.header.language.code = main_language;</div><div class="line"><a name="l00283"></a><span class="lineno"> 283</span>&#160; }</div><div class="line"><a name="l00284"></a><span class="lineno"> 284</span>&#160; }</div><div class="line"><a name="l00285"></a><span class="lineno"> 285</span>&#160;}</div><div class="line"><a name="l00286"></a><span class="lineno"> 286</span>&#160;</div><div class="line"><a name="l00287"></a><span class="lineno"> 287</span>&#160;<span class="keywordtype">void</span> MP4Muxer::GenerateVideoTrak(<span class="keyword">const</span> <a class="code" href="../../d6/db1/classshaka_1_1media_1_1VideoStreamInfo.html">VideoStreamInfo</a>* video_info,</div><div class="line"><a name="l00288"></a><span class="lineno"> 288</span>&#160; <a class="code" href="../../d3/db5/structshaka_1_1media_1_1mp4_1_1Track.html">Track</a>* trak,</div><div class="line"><a name="l00289"></a><span class="lineno"> 289</span>&#160; uint32_t track_id) {</div><div class="line"><a name="l00290"></a><span class="lineno"> 290</span>&#160; InitializeTrak(video_info, trak);</div><div class="line"><a name="l00291"></a><span class="lineno"> 291</span>&#160;</div><div class="line"><a name="l00292"></a><span class="lineno"> 292</span>&#160; <span class="comment">// width and height specify the track&#39;s visual presentation size as</span></div><div class="line"><a name="l00293"></a><span class="lineno"> 293</span>&#160; <span class="comment">// fixed-point 16.16 values.</span></div><div class="line"><a name="l00294"></a><span class="lineno"> 294</span>&#160; uint32_t pixel_width = video_info-&gt;<a class="code" href="../../d6/db1/classshaka_1_1media_1_1VideoStreamInfo.html#ac0356f4786e3cc2699c13a253c5f3cb5">pixel_width</a>();</div><div class="line"><a name="l00295"></a><span class="lineno"> 295</span>&#160; uint32_t pixel_height = video_info-&gt;<a class="code" href="../../d6/db1/classshaka_1_1media_1_1VideoStreamInfo.html#a40b2e26c533904ff890f4ea8086d7f71">pixel_height</a>();</div><div class="line"><a name="l00296"></a><span class="lineno"> 296</span>&#160; <span class="keywordflow">if</span> (pixel_width == 0 || pixel_height == 0) {</div><div class="line"><a name="l00297"></a><span class="lineno"> 297</span>&#160; LOG(WARNING) &lt;&lt; <span class="stringliteral">&quot;pixel width/height are not set. Assuming 1:1.&quot;</span>;</div><div class="line"><a name="l00298"></a><span class="lineno"> 298</span>&#160; pixel_width = 1;</div><div class="line"><a name="l00299"></a><span class="lineno"> 299</span>&#160; pixel_height = 1;</div><div class="line"><a name="l00300"></a><span class="lineno"> 300</span>&#160; }</div><div class="line"><a name="l00301"></a><span class="lineno"> 301</span>&#160; <span class="keyword">const</span> <span class="keywordtype">double</span> sample_aspect_ratio =</div><div class="line"><a name="l00302"></a><span class="lineno"> 302</span>&#160; <span class="keyword">static_cast&lt;</span><span class="keywordtype">double</span><span class="keyword">&gt;</span>(pixel_width) / pixel_height;</div><div class="line"><a name="l00303"></a><span class="lineno"> 303</span>&#160; trak-&gt;header.width = video_info-&gt;width() * sample_aspect_ratio * 0x10000;</div><div class="line"><a name="l00304"></a><span class="lineno"> 304</span>&#160; trak-&gt;header.height = video_info-&gt;height() * 0x10000;</div><div class="line"><a name="l00305"></a><span class="lineno"> 305</span>&#160;</div><div class="line"><a name="l00306"></a><span class="lineno"> 306</span>&#160; <a class="code" href="../../d0/d73/structshaka_1_1media_1_1mp4_1_1VideoSampleEntry.html">VideoSampleEntry</a> video;</div><div class="line"><a name="l00307"></a><span class="lineno"> 307</span>&#160; video.format =</div><div class="line"><a name="l00308"></a><span class="lineno"> 308</span>&#160; CodecToFourCC(video_info-&gt;codec(), video_info-&gt;h26x_stream_format());</div><div class="line"><a name="l00309"></a><span class="lineno"> 309</span>&#160; video.width = video_info-&gt;width();</div><div class="line"><a name="l00310"></a><span class="lineno"> 310</span>&#160; video.height = video_info-&gt;height();</div><div class="line"><a name="l00311"></a><span class="lineno"> 311</span>&#160; video.codec_configuration.data = video_info-&gt;codec_config();</div><div class="line"><a name="l00312"></a><span class="lineno"> 312</span>&#160; <span class="keywordflow">if</span> (pixel_width != 1 || pixel_height != 1) {</div><div class="line"><a name="l00313"></a><span class="lineno"> 313</span>&#160; video.pixel_aspect.h_spacing = pixel_width;</div><div class="line"><a name="l00314"></a><span class="lineno"> 314</span>&#160; video.pixel_aspect.v_spacing = pixel_height;</div><div class="line"><a name="l00315"></a><span class="lineno"> 315</span>&#160; }</div><div class="line"><a name="l00316"></a><span class="lineno"> 316</span>&#160;</div><div class="line"><a name="l00317"></a><span class="lineno"> 317</span>&#160; <a class="code" href="../../da/df5/structshaka_1_1media_1_1mp4_1_1SampleDescription.html">SampleDescription</a>&amp; sample_description =</div><div class="line"><a name="l00318"></a><span class="lineno"> 318</span>&#160; trak-&gt;media.information.sample_table.description;</div><div class="line"><a name="l00319"></a><span class="lineno"> 319</span>&#160; sample_description.type = kVideo;</div><div class="line"><a name="l00320"></a><span class="lineno"> 320</span>&#160; sample_description.video_entries.push_back(video);</div><div class="line"><a name="l00321"></a><span class="lineno"> 321</span>&#160;</div><div class="line"><a name="l00322"></a><span class="lineno"> 322</span>&#160; <span class="keywordflow">if</span> (video_info-&gt;is_encrypted()) {</div><div class="line"><a name="l00323"></a><span class="lineno"> 323</span>&#160; <span class="keywordflow">if</span> (video_info-&gt;has_clear_lead()) {</div><div class="line"><a name="l00324"></a><span class="lineno"> 324</span>&#160; <span class="comment">// Add a second entry for clear content.</span></div><div class="line"><a name="l00325"></a><span class="lineno"> 325</span>&#160; sample_description.video_entries.push_back(video);</div><div class="line"><a name="l00326"></a><span class="lineno"> 326</span>&#160; }</div><div class="line"><a name="l00327"></a><span class="lineno"> 327</span>&#160; <span class="comment">// Convert the first entry to an encrypted entry.</span></div><div class="line"><a name="l00328"></a><span class="lineno"> 328</span>&#160; <a class="code" href="../../d0/d73/structshaka_1_1media_1_1mp4_1_1VideoSampleEntry.html">VideoSampleEntry</a>&amp; entry = sample_description.video_entries[0];</div><div class="line"><a name="l00329"></a><span class="lineno"> 329</span>&#160; GenerateSinf(entry.format, video_info-&gt;encryption_config(), &amp;entry.sinf);</div><div class="line"><a name="l00330"></a><span class="lineno"> 330</span>&#160; entry.format = FOURCC_encv;</div><div class="line"><a name="l00331"></a><span class="lineno"> 331</span>&#160; }</div><div class="line"><a name="l00332"></a><span class="lineno"> 332</span>&#160;}</div><div class="line"><a name="l00333"></a><span class="lineno"> 333</span>&#160;</div><div class="line"><a name="l00334"></a><span class="lineno"> 334</span>&#160;<span class="keywordtype">void</span> MP4Muxer::GenerateAudioTrak(<span class="keyword">const</span> <a class="code" href="../../da/d4e/classshaka_1_1media_1_1AudioStreamInfo.html">AudioStreamInfo</a>* audio_info,</div><div class="line"><a name="l00335"></a><span class="lineno"> 335</span>&#160; <a class="code" href="../../d3/db5/structshaka_1_1media_1_1mp4_1_1Track.html">Track</a>* trak,</div><div class="line"><a name="l00336"></a><span class="lineno"> 336</span>&#160; uint32_t track_id) {</div><div class="line"><a name="l00337"></a><span class="lineno"> 337</span>&#160; InitializeTrak(audio_info, trak);</div><div class="line"><a name="l00338"></a><span class="lineno"> 338</span>&#160;</div><div class="line"><a name="l00339"></a><span class="lineno"> 339</span>&#160; trak-&gt;header.volume = 0x100;</div><div class="line"><a name="l00340"></a><span class="lineno"> 340</span>&#160;</div><div class="line"><a name="l00341"></a><span class="lineno"> 341</span>&#160; <a class="code" href="../../d8/d5b/structshaka_1_1media_1_1mp4_1_1AudioSampleEntry.html">AudioSampleEntry</a> audio;</div><div class="line"><a name="l00342"></a><span class="lineno"> 342</span>&#160; audio.format =</div><div class="line"><a name="l00343"></a><span class="lineno"> 343</span>&#160; CodecToFourCC(audio_info-&gt;codec(), H26xStreamFormat::kUnSpecified);</div><div class="line"><a name="l00344"></a><span class="lineno"> 344</span>&#160; <span class="keywordflow">switch</span>(audio_info-&gt;codec()){</div><div class="line"><a name="l00345"></a><span class="lineno"> 345</span>&#160; <span class="keywordflow">case</span> kCodecAAC:</div><div class="line"><a name="l00346"></a><span class="lineno"> 346</span>&#160; audio.esds.es_descriptor.set_object_type(kISO_14496_3); <span class="comment">// MPEG4 AAC.</span></div><div class="line"><a name="l00347"></a><span class="lineno"> 347</span>&#160; audio.esds.es_descriptor.set_esid(track_id);</div><div class="line"><a name="l00348"></a><span class="lineno"> 348</span>&#160; audio.esds.es_descriptor.set_decoder_specific_info(</div><div class="line"><a name="l00349"></a><span class="lineno"> 349</span>&#160; audio_info-&gt;codec_config());</div><div class="line"><a name="l00350"></a><span class="lineno"> 350</span>&#160; audio.esds.es_descriptor.set_max_bitrate(audio_info-&gt;max_bitrate());</div><div class="line"><a name="l00351"></a><span class="lineno"> 351</span>&#160; audio.esds.es_descriptor.set_avg_bitrate(audio_info-&gt;avg_bitrate());</div><div class="line"><a name="l00352"></a><span class="lineno"> 352</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00353"></a><span class="lineno"> 353</span>&#160; <span class="keywordflow">case</span> kCodecDTSC:</div><div class="line"><a name="l00354"></a><span class="lineno"> 354</span>&#160; <span class="keywordflow">case</span> kCodecDTSH:</div><div class="line"><a name="l00355"></a><span class="lineno"> 355</span>&#160; <span class="keywordflow">case</span> kCodecDTSL:</div><div class="line"><a name="l00356"></a><span class="lineno"> 356</span>&#160; <span class="keywordflow">case</span> kCodecDTSE:</div><div class="line"><a name="l00357"></a><span class="lineno"> 357</span>&#160; <span class="keywordflow">case</span> kCodecDTSM:</div><div class="line"><a name="l00358"></a><span class="lineno"> 358</span>&#160; audio.ddts.extra_data = audio_info-&gt;codec_config();</div><div class="line"><a name="l00359"></a><span class="lineno"> 359</span>&#160; audio.ddts.max_bitrate = audio_info-&gt;max_bitrate();</div><div class="line"><a name="l00360"></a><span class="lineno"> 360</span>&#160; audio.ddts.avg_bitrate = audio_info-&gt;avg_bitrate();</div><div class="line"><a name="l00361"></a><span class="lineno"> 361</span>&#160; audio.ddts.sampling_frequency = audio_info-&gt;sampling_frequency();</div><div class="line"><a name="l00362"></a><span class="lineno"> 362</span>&#160; audio.ddts.pcm_sample_depth = audio_info-&gt;sample_bits();</div><div class="line"><a name="l00363"></a><span class="lineno"> 363</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00364"></a><span class="lineno"> 364</span>&#160; <span class="keywordflow">case</span> kCodecAC3:</div><div class="line"><a name="l00365"></a><span class="lineno"> 365</span>&#160; audio.dac3.data = audio_info-&gt;codec_config();</div><div class="line"><a name="l00366"></a><span class="lineno"> 366</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00367"></a><span class="lineno"> 367</span>&#160; <span class="keywordflow">case</span> kCodecEAC3:</div><div class="line"><a name="l00368"></a><span class="lineno"> 368</span>&#160; audio.dec3.data = audio_info-&gt;codec_config();</div><div class="line"><a name="l00369"></a><span class="lineno"> 369</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00370"></a><span class="lineno"> 370</span>&#160; <span class="keywordflow">case</span> kCodecOpus:</div><div class="line"><a name="l00371"></a><span class="lineno"> 371</span>&#160; audio.dops.opus_identification_header = audio_info-&gt;codec_config();</div><div class="line"><a name="l00372"></a><span class="lineno"> 372</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00373"></a><span class="lineno"> 373</span>&#160; <span class="keywordflow">default</span>:</div><div class="line"><a name="l00374"></a><span class="lineno"> 374</span>&#160; NOTIMPLEMENTED();</div><div class="line"><a name="l00375"></a><span class="lineno"> 375</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00376"></a><span class="lineno"> 376</span>&#160; }</div><div class="line"><a name="l00377"></a><span class="lineno"> 377</span>&#160;</div><div class="line"><a name="l00378"></a><span class="lineno"> 378</span>&#160; <span class="keywordflow">if</span> (audio_info-&gt;codec() == kCodecAC3 || audio_info-&gt;codec() == kCodecEAC3) {</div><div class="line"><a name="l00379"></a><span class="lineno"> 379</span>&#160; <span class="comment">// AC3 and EC3 does not fill in actual channel count and sample size in</span></div><div class="line"><a name="l00380"></a><span class="lineno"> 380</span>&#160; <span class="comment">// sample description entry. Instead, two constants are used.</span></div><div class="line"><a name="l00381"></a><span class="lineno"> 381</span>&#160; audio.channelcount = 2;</div><div class="line"><a name="l00382"></a><span class="lineno"> 382</span>&#160; audio.samplesize = 16;</div><div class="line"><a name="l00383"></a><span class="lineno"> 383</span>&#160; } <span class="keywordflow">else</span> {</div><div class="line"><a name="l00384"></a><span class="lineno"> 384</span>&#160; audio.channelcount = audio_info-&gt;num_channels();</div><div class="line"><a name="l00385"></a><span class="lineno"> 385</span>&#160; audio.samplesize = audio_info-&gt;sample_bits();</div><div class="line"><a name="l00386"></a><span class="lineno"> 386</span>&#160; }</div><div class="line"><a name="l00387"></a><span class="lineno"> 387</span>&#160; audio.samplerate = audio_info-&gt;sampling_frequency();</div><div class="line"><a name="l00388"></a><span class="lineno"> 388</span>&#160; <a class="code" href="../../d1/dee/structshaka_1_1media_1_1mp4_1_1SampleTable.html">SampleTable</a>&amp; sample_table = trak-&gt;media.information.sample_table;</div><div class="line"><a name="l00389"></a><span class="lineno"> 389</span>&#160; <a class="code" href="../../da/df5/structshaka_1_1media_1_1mp4_1_1SampleDescription.html">SampleDescription</a>&amp; sample_description = sample_table.description;</div><div class="line"><a name="l00390"></a><span class="lineno"> 390</span>&#160; sample_description.type = kAudio;</div><div class="line"><a name="l00391"></a><span class="lineno"> 391</span>&#160; sample_description.audio_entries.push_back(audio);</div><div class="line"><a name="l00392"></a><span class="lineno"> 392</span>&#160;</div><div class="line"><a name="l00393"></a><span class="lineno"> 393</span>&#160; <span class="keywordflow">if</span> (audio_info-&gt;is_encrypted()) {</div><div class="line"><a name="l00394"></a><span class="lineno"> 394</span>&#160; <span class="keywordflow">if</span> (audio_info-&gt;has_clear_lead()) {</div><div class="line"><a name="l00395"></a><span class="lineno"> 395</span>&#160; <span class="comment">// Add a second entry for clear content.</span></div><div class="line"><a name="l00396"></a><span class="lineno"> 396</span>&#160; sample_description.audio_entries.push_back(audio);</div><div class="line"><a name="l00397"></a><span class="lineno"> 397</span>&#160; }</div><div class="line"><a name="l00398"></a><span class="lineno"> 398</span>&#160; <span class="comment">// Convert the first entry to an encrypted entry.</span></div><div class="line"><a name="l00399"></a><span class="lineno"> 399</span>&#160; <a class="code" href="../../d8/d5b/structshaka_1_1media_1_1mp4_1_1AudioSampleEntry.html">AudioSampleEntry</a>&amp; entry = sample_description.audio_entries[0];</div><div class="line"><a name="l00400"></a><span class="lineno"> 400</span>&#160; GenerateSinf(entry.format, audio_info-&gt;encryption_config(), &amp;entry.sinf);</div><div class="line"><a name="l00401"></a><span class="lineno"> 401</span>&#160; entry.format = FOURCC_enca;</div><div class="line"><a name="l00402"></a><span class="lineno"> 402</span>&#160; }</div><div class="line"><a name="l00403"></a><span class="lineno"> 403</span>&#160;</div><div class="line"><a name="l00404"></a><span class="lineno"> 404</span>&#160; <span class="comment">// Opus requires at least one sample group description box and at least one</span></div><div class="line"><a name="l00405"></a><span class="lineno"> 405</span>&#160; <span class="comment">// sample to group box with grouping type &#39;roll&#39; within sample table box.</span></div><div class="line"><a name="l00406"></a><span class="lineno"> 406</span>&#160; <span class="keywordflow">if</span> (audio_info-&gt;codec() == kCodecOpus) {</div><div class="line"><a name="l00407"></a><span class="lineno"> 407</span>&#160; sample_table.sample_group_descriptions.resize(1);</div><div class="line"><a name="l00408"></a><span class="lineno"> 408</span>&#160; <a class="code" href="../../d7/d01/structshaka_1_1media_1_1mp4_1_1SampleGroupDescription.html">SampleGroupDescription</a>&amp; sample_group_description =</div><div class="line"><a name="l00409"></a><span class="lineno"> 409</span>&#160; sample_table.sample_group_descriptions.back();</div><div class="line"><a name="l00410"></a><span class="lineno"> 410</span>&#160; sample_group_description.grouping_type = FOURCC_roll;</div><div class="line"><a name="l00411"></a><span class="lineno"> 411</span>&#160; sample_group_description.audio_roll_recovery_entries.resize(1);</div><div class="line"><a name="l00412"></a><span class="lineno"> 412</span>&#160; <span class="comment">// The roll distance is expressed in sample units and always takes negative</span></div><div class="line"><a name="l00413"></a><span class="lineno"> 413</span>&#160; <span class="comment">// values.</span></div><div class="line"><a name="l00414"></a><span class="lineno"> 414</span>&#160; <span class="keyword">const</span> uint64_t kNanosecondsPerSecond = 1000000000ull;</div><div class="line"><a name="l00415"></a><span class="lineno"> 415</span>&#160; sample_group_description.audio_roll_recovery_entries[0].roll_distance =</div><div class="line"><a name="l00416"></a><span class="lineno"> 416</span>&#160; (0 - (audio_info-&gt;seek_preroll_ns() * audio.samplerate +</div><div class="line"><a name="l00417"></a><span class="lineno"> 417</span>&#160; kNanosecondsPerSecond / 2)) /</div><div class="line"><a name="l00418"></a><span class="lineno"> 418</span>&#160; kNanosecondsPerSecond;</div><div class="line"><a name="l00419"></a><span class="lineno"> 419</span>&#160;</div><div class="line"><a name="l00420"></a><span class="lineno"> 420</span>&#160; sample_table.sample_to_groups.resize(1);</div><div class="line"><a name="l00421"></a><span class="lineno"> 421</span>&#160; <a class="code" href="../../d0/d7c/structshaka_1_1media_1_1mp4_1_1SampleToGroup.html">SampleToGroup</a>&amp; sample_to_group = sample_table.sample_to_groups.back();</div><div class="line"><a name="l00422"></a><span class="lineno"> 422</span>&#160; sample_to_group.grouping_type = FOURCC_roll;</div><div class="line"><a name="l00423"></a><span class="lineno"> 423</span>&#160;</div><div class="line"><a name="l00424"></a><span class="lineno"> 424</span>&#160; sample_to_group.entries.resize(1);</div><div class="line"><a name="l00425"></a><span class="lineno"> 425</span>&#160; <a class="code" href="../../d7/de0/structshaka_1_1media_1_1mp4_1_1SampleToGroupEntry.html">SampleToGroupEntry</a>&amp; sample_to_group_entry = sample_to_group.entries.back();</div><div class="line"><a name="l00426"></a><span class="lineno"> 426</span>&#160; <span class="comment">// All samples are in track fragments.</span></div><div class="line"><a name="l00427"></a><span class="lineno"> 427</span>&#160; sample_to_group_entry.sample_count = 0;</div><div class="line"><a name="l00428"></a><span class="lineno"> 428</span>&#160; sample_to_group_entry.group_description_index =</div><div class="line"><a name="l00429"></a><span class="lineno"> 429</span>&#160; SampleToGroupEntry::kTrackGroupDescriptionIndexBase + 1;</div><div class="line"><a name="l00430"></a><span class="lineno"> 430</span>&#160; } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (audio_info-&gt;seek_preroll_ns() != 0) {</div><div class="line"><a name="l00431"></a><span class="lineno"> 431</span>&#160; LOG(WARNING) &lt;&lt; <span class="stringliteral">&quot;Unexpected seek preroll for codec &quot;</span> &lt;&lt; audio_info-&gt;codec();</div><div class="line"><a name="l00432"></a><span class="lineno"> 432</span>&#160; <span class="keywordflow">return</span>;</div><div class="line"><a name="l00433"></a><span class="lineno"> 433</span>&#160; }</div><div class="line"><a name="l00434"></a><span class="lineno"> 434</span>&#160;}</div><div class="line"><a name="l00435"></a><span class="lineno"> 435</span>&#160;</div><div class="line"><a name="l00436"></a><span class="lineno"> 436</span>&#160;<span class="keywordtype">void</span> MP4Muxer::GenerateTextTrak(<span class="keyword">const</span> <a class="code" href="../../db/dab/classshaka_1_1media_1_1TextStreamInfo.html">TextStreamInfo</a>* text_info,</div><div class="line"><a name="l00437"></a><span class="lineno"> 437</span>&#160; <a class="code" href="../../d3/db5/structshaka_1_1media_1_1mp4_1_1Track.html">Track</a>* trak,</div><div class="line"><a name="l00438"></a><span class="lineno"> 438</span>&#160; uint32_t track_id) {</div><div class="line"><a name="l00439"></a><span class="lineno"> 439</span>&#160; InitializeTrak(text_info, trak);</div><div class="line"><a name="l00440"></a><span class="lineno"> 440</span>&#160;</div><div class="line"><a name="l00441"></a><span class="lineno"> 441</span>&#160; <span class="keywordflow">if</span> (text_info-&gt;codec_string() == <span class="stringliteral">&quot;wvtt&quot;</span>) {</div><div class="line"><a name="l00442"></a><span class="lineno"> 442</span>&#160; <span class="comment">// Handle WebVTT.</span></div><div class="line"><a name="l00443"></a><span class="lineno"> 443</span>&#160; <a class="code" href="../../d7/dc3/structshaka_1_1media_1_1mp4_1_1TextSampleEntry.html">TextSampleEntry</a> webvtt;</div><div class="line"><a name="l00444"></a><span class="lineno"> 444</span>&#160; webvtt.format = FOURCC_wvtt;</div><div class="line"><a name="l00445"></a><span class="lineno"> 445</span>&#160; webvtt.config.config.assign(text_info-&gt;codec_config().begin(),</div><div class="line"><a name="l00446"></a><span class="lineno"> 446</span>&#160; text_info-&gt;codec_config().end());</div><div class="line"><a name="l00447"></a><span class="lineno"> 447</span>&#160; <span class="comment">// TODO(rkuroiwa): This should be the source file URI(s). Putting bogus</span></div><div class="line"><a name="l00448"></a><span class="lineno"> 448</span>&#160; <span class="comment">// string for now so that the box will be there for samples with overlapping</span></div><div class="line"><a name="l00449"></a><span class="lineno"> 449</span>&#160; <span class="comment">// cues.</span></div><div class="line"><a name="l00450"></a><span class="lineno"> 450</span>&#160; webvtt.label.source_label = <span class="stringliteral">&quot;source_label&quot;</span>;</div><div class="line"><a name="l00451"></a><span class="lineno"> 451</span>&#160; <a class="code" href="../../da/df5/structshaka_1_1media_1_1mp4_1_1SampleDescription.html">SampleDescription</a>&amp; sample_description =</div><div class="line"><a name="l00452"></a><span class="lineno"> 452</span>&#160; trak-&gt;media.information.sample_table.description;</div><div class="line"><a name="l00453"></a><span class="lineno"> 453</span>&#160; sample_description.type = kText;</div><div class="line"><a name="l00454"></a><span class="lineno"> 454</span>&#160; sample_description.text_entries.push_back(webvtt);</div><div class="line"><a name="l00455"></a><span class="lineno"> 455</span>&#160; <span class="keywordflow">return</span>;</div><div class="line"><a name="l00456"></a><span class="lineno"> 456</span>&#160; }</div><div class="line"><a name="l00457"></a><span class="lineno"> 457</span>&#160; NOTIMPLEMENTED() &lt;&lt; text_info-&gt;codec_string()</div><div class="line"><a name="l00458"></a><span class="lineno"> 458</span>&#160; &lt;&lt; <span class="stringliteral">&quot; handling not implemented yet.&quot;</span>;</div><div class="line"><a name="l00459"></a><span class="lineno"> 459</span>&#160;}</div><div class="line"><a name="l00460"></a><span class="lineno"> 460</span>&#160;</div><div class="line"><a name="l00461"></a><span class="lineno"> 461</span>&#160;base::Optional&lt;Range&gt; MP4Muxer::GetInitRangeStartAndEnd() {</div><div class="line"><a name="l00462"></a><span class="lineno"> 462</span>&#160; <span class="keywordtype">size_t</span> range_offset = 0;</div><div class="line"><a name="l00463"></a><span class="lineno"> 463</span>&#160; <span class="keywordtype">size_t</span> range_size = 0;</div><div class="line"><a name="l00464"></a><span class="lineno"> 464</span>&#160; <span class="keyword">const</span> <span class="keywordtype">bool</span> has_range = segmenter_-&gt;GetInitRange(&amp;range_offset, &amp;range_size);</div><div class="line"><a name="l00465"></a><span class="lineno"> 465</span>&#160;</div><div class="line"><a name="l00466"></a><span class="lineno"> 466</span>&#160; <span class="keywordflow">if</span> (!has_range)</div><div class="line"><a name="l00467"></a><span class="lineno"> 467</span>&#160; <span class="keywordflow">return</span> base::nullopt;</div><div class="line"><a name="l00468"></a><span class="lineno"> 468</span>&#160;</div><div class="line"><a name="l00469"></a><span class="lineno"> 469</span>&#160; <a class="code" href="../../d9/de0/structshaka_1_1media_1_1Range.html">Range</a> range;</div><div class="line"><a name="l00470"></a><span class="lineno"> 470</span>&#160; SetStartAndEndFromOffsetAndSize(range_offset, range_size, &amp;range);</div><div class="line"><a name="l00471"></a><span class="lineno"> 471</span>&#160; <span class="keywordflow">return</span> range;</div><div class="line"><a name="l00472"></a><span class="lineno"> 472</span>&#160;}</div><div class="line"><a name="l00473"></a><span class="lineno"> 473</span>&#160;</div><div class="line"><a name="l00474"></a><span class="lineno"> 474</span>&#160;base::Optional&lt;Range&gt; MP4Muxer::GetIndexRangeStartAndEnd() {</div><div class="line"><a name="l00475"></a><span class="lineno"> 475</span>&#160; <span class="keywordtype">size_t</span> range_offset = 0;</div><div class="line"><a name="l00476"></a><span class="lineno"> 476</span>&#160; <span class="keywordtype">size_t</span> range_size = 0;</div><div class="line"><a name="l00477"></a><span class="lineno"> 477</span>&#160; <span class="keyword">const</span> <span class="keywordtype">bool</span> has_range = segmenter_-&gt;GetIndexRange(&amp;range_offset, &amp;range_size);</div><div class="line"><a name="l00478"></a><span class="lineno"> 478</span>&#160;</div><div class="line"><a name="l00479"></a><span class="lineno"> 479</span>&#160; <span class="keywordflow">if</span> (!has_range)</div><div class="line"><a name="l00480"></a><span class="lineno"> 480</span>&#160; <span class="keywordflow">return</span> base::nullopt;</div><div class="line"><a name="l00481"></a><span class="lineno"> 481</span>&#160;</div><div class="line"><a name="l00482"></a><span class="lineno"> 482</span>&#160; <a class="code" href="../../d9/de0/structshaka_1_1media_1_1Range.html">Range</a> range;</div><div class="line"><a name="l00483"></a><span class="lineno"> 483</span>&#160; SetStartAndEndFromOffsetAndSize(range_offset, range_size, &amp;range);</div><div class="line"><a name="l00484"></a><span class="lineno"> 484</span>&#160; <span class="keywordflow">return</span> range;</div><div class="line"><a name="l00485"></a><span class="lineno"> 485</span>&#160;}</div><div class="line"><a name="l00486"></a><span class="lineno"> 486</span>&#160;</div><div class="line"><a name="l00487"></a><span class="lineno"> 487</span>&#160;<span class="keywordtype">void</span> MP4Muxer::FireOnMediaStartEvent() {</div><div class="line"><a name="l00488"></a><span class="lineno"> 488</span>&#160; <span class="keywordflow">if</span> (!muxer_listener())</div><div class="line"><a name="l00489"></a><span class="lineno"> 489</span>&#160; <span class="keywordflow">return</span>;</div><div class="line"><a name="l00490"></a><span class="lineno"> 490</span>&#160;</div><div class="line"><a name="l00491"></a><span class="lineno"> 491</span>&#160; <span class="keywordflow">if</span> (streams().size() &gt; 1) {</div><div class="line"><a name="l00492"></a><span class="lineno"> 492</span>&#160; LOG(ERROR) &lt;&lt; <span class="stringliteral">&quot;MuxerListener cannot take more than 1 stream.&quot;</span>;</div><div class="line"><a name="l00493"></a><span class="lineno"> 493</span>&#160; <span class="keywordflow">return</span>;</div><div class="line"><a name="l00494"></a><span class="lineno"> 494</span>&#160; }</div><div class="line"><a name="l00495"></a><span class="lineno"> 495</span>&#160; DCHECK(!streams().empty()) &lt;&lt; <span class="stringliteral">&quot;Media started without a stream.&quot;</span>;</div><div class="line"><a name="l00496"></a><span class="lineno"> 496</span>&#160;</div><div class="line"><a name="l00497"></a><span class="lineno"> 497</span>&#160; <span class="keyword">const</span> uint32_t timescale = segmenter_-&gt;GetReferenceTimeScale();</div><div class="line"><a name="l00498"></a><span class="lineno"> 498</span>&#160; muxer_listener()-&gt;<a class="code" href="../../dd/d7a/classshaka_1_1media_1_1MuxerListener.html#a31536ec385a7ec22f323a42b872b499a">OnMediaStart</a>(options(), *streams().front(), timescale,</div><div class="line"><a name="l00499"></a><span class="lineno"> 499</span>&#160; MuxerListener::kContainerMp4);</div><div class="line"><a name="l00500"></a><span class="lineno"> 500</span>&#160;}</div><div class="line"><a name="l00501"></a><span class="lineno"> 501</span>&#160;</div><div class="line"><a name="l00502"></a><span class="lineno"> 502</span>&#160;<span class="keywordtype">void</span> MP4Muxer::FireOnMediaEndEvent() {</div><div class="line"><a name="l00503"></a><span class="lineno"> 503</span>&#160; <span class="keywordflow">if</span> (!muxer_listener())</div><div class="line"><a name="l00504"></a><span class="lineno"> 504</span>&#160; <span class="keywordflow">return</span>;</div><div class="line"><a name="l00505"></a><span class="lineno"> 505</span>&#160;</div><div class="line"><a name="l00506"></a><span class="lineno"> 506</span>&#160; <a class="code" href="../../d1/d03/structshaka_1_1media_1_1MuxerListener_1_1MediaRanges.html">MuxerListener::MediaRanges</a> media_range;</div><div class="line"><a name="l00507"></a><span class="lineno"> 507</span>&#160; media_range.<a class="code" href="../../d1/d03/structshaka_1_1media_1_1MuxerListener_1_1MediaRanges.html#a6070da9ce7fab251c82b25a4020373c0">init_range</a> = GetInitRangeStartAndEnd();</div><div class="line"><a name="l00508"></a><span class="lineno"> 508</span>&#160; media_range.<a class="code" href="../../d1/d03/structshaka_1_1media_1_1MuxerListener_1_1MediaRanges.html#aa15231fb064efc4b56800df24b074b29">index_range</a> = GetIndexRangeStartAndEnd();</div><div class="line"><a name="l00509"></a><span class="lineno"> 509</span>&#160; media_range.<a class="code" href="../../d1/d03/structshaka_1_1media_1_1MuxerListener_1_1MediaRanges.html#a836626da601a9f6ea54502c7e5bdd7c9">subsegment_ranges</a> = segmenter_-&gt;GetSegmentRanges();</div><div class="line"><a name="l00510"></a><span class="lineno"> 510</span>&#160;</div><div class="line"><a name="l00511"></a><span class="lineno"> 511</span>&#160; <span class="keyword">const</span> <span class="keywordtype">float</span> duration_seconds = <span class="keyword">static_cast&lt;</span><span class="keywordtype">float</span><span class="keyword">&gt;</span>(segmenter_-&gt;GetDuration());</div><div class="line"><a name="l00512"></a><span class="lineno"> 512</span>&#160; muxer_listener()-&gt;<a class="code" href="../../dd/d7a/classshaka_1_1media_1_1MuxerListener.html#a11d4301cd53ab421f524bfa143eac21a">OnMediaEnd</a>(media_range, duration_seconds);</div><div class="line"><a name="l00513"></a><span class="lineno"> 513</span>&#160;}</div><div class="line"><a name="l00514"></a><span class="lineno"> 514</span>&#160;</div><div class="line"><a name="l00515"></a><span class="lineno"> 515</span>&#160;uint64_t MP4Muxer::IsoTimeNow() {</div><div class="line"><a name="l00516"></a><span class="lineno"> 516</span>&#160; <span class="comment">// Time in seconds from Jan. 1, 1904 to epoch time, i.e. Jan. 1, 1970.</span></div><div class="line"><a name="l00517"></a><span class="lineno"> 517</span>&#160; <span class="keyword">const</span> uint64_t kIsomTimeOffset = 2082844800l;</div><div class="line"><a name="l00518"></a><span class="lineno"> 518</span>&#160; <span class="keywordflow">return</span> kIsomTimeOffset +</div><div class="line"><a name="l00519"></a><span class="lineno"> 519</span>&#160; (clock() ? clock()-&gt;Now() : base::Time::Now()).ToDoubleT();</div><div class="line"><a name="l00520"></a><span class="lineno"> 520</span>&#160;}</div><div class="line"><a name="l00521"></a><span class="lineno"> 521</span>&#160;</div><div class="line"><a name="l00522"></a><span class="lineno"> 522</span>&#160;} <span class="comment">// namespace mp4</span></div><div class="line"><a name="l00523"></a><span class="lineno"> 523</span>&#160;} <span class="comment">// namespace media</span></div><div class="line"><a name="l00524"></a><span class="lineno"> 524</span>&#160;} <span class="comment">// namespace shaka</span></div><div class="ttc" id="structshaka_1_1media_1_1MuxerListener_1_1MediaRanges_html_a6070da9ce7fab251c82b25a4020373c0"><div class="ttname"><a href="../../d1/d03/structshaka_1_1media_1_1MuxerListener_1_1MediaRanges.html#a6070da9ce7fab251c82b25a4020373c0">shaka::media::MuxerListener::MediaRanges::init_range</a></div><div class="ttdeci">base::Optional&lt; Range &gt; init_range</div><div class="ttdoc">Range of the initialization section of a segment. </div><div class="ttdef"><b>Definition:</b> <a href="../../de/dfa/muxer__listener_8h_source.html#l00047">muxer_listener.h:47</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1StreamInfo_html"><div class="ttname"><a href="../../d5/db1/classshaka_1_1media_1_1StreamInfo.html">shaka::media::StreamInfo</a></div><div class="ttdoc">Abstract class holds stream information. </div><div class="ttdef"><b>Definition:</b> <a href="../../d8/daa/stream__info_8h_source.html#l00058">stream_info.h:58</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1SampleToGroupEntry_html"><div class="ttname"><a href="../../d7/de0/structshaka_1_1media_1_1mp4_1_1SampleToGroupEntry.html">shaka::media::mp4::SampleToGroupEntry</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00522">box_definitions.h:522</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1FileType_html"><div class="ttname"><a href="../../d5/d03/structshaka_1_1media_1_1mp4_1_1FileType.html">shaka::media::mp4::FileType</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00045">box_definitions.h:45</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1SegmentInfo_html"><div class="ttname"><a href="../../d0/dc0/structshaka_1_1media_1_1SegmentInfo.html">shaka::media::SegmentInfo</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d3/d93/media__handler_8h_source.html#l00053">media_handler.h:53</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1MuxerListener_1_1MediaRanges_html_aa15231fb064efc4b56800df24b074b29"><div class="ttname"><a href="../../d1/d03/structshaka_1_1media_1_1MuxerListener_1_1MediaRanges.html#aa15231fb064efc4b56800df24b074b29">shaka::media::MuxerListener::MediaRanges::index_range</a></div><div class="ttdeci">base::Optional&lt; Range &gt; index_range</div><div class="ttdoc">Range of the index section of a segment. </div><div class="ttdef"><b>Definition:</b> <a href="../../de/dfa/muxer__listener_8h_source.html#l00049">muxer_listener.h:49</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1AudioSampleEntry_html"><div class="ttname"><a href="../../d8/d5b/structshaka_1_1media_1_1mp4_1_1AudioSampleEntry.html">shaka::media::mp4::AudioSampleEntry</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00345">box_definitions.h:345</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1MuxerOptions_html_a5397ee8759a663aea68261600e528d82"><div class="ttname"><a href="../../d0/d27/structshaka_1_1media_1_1MuxerOptions.html#a5397ee8759a663aea68261600e528d82">shaka::media::MuxerOptions::output_file_name</a></div><div class="ttdeci">std::string output_file_name</div><div class="ttdef"><b>Definition:</b> <a href="../../d0/d0e/muxer__options_8h_source.html#l00030">muxer_options.h:30</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1MuxerListener_1_1MediaRanges_html_a836626da601a9f6ea54502c7e5bdd7c9"><div class="ttname"><a href="../../d1/d03/structshaka_1_1media_1_1MuxerListener_1_1MediaRanges.html#a836626da601a9f6ea54502c7e5bdd7c9">shaka::media::MuxerListener::MediaRanges::subsegment_ranges</a></div><div class="ttdeci">std::vector&lt; Range &gt; subsegment_ranges</div><div class="ttdef"><b>Definition:</b> <a href="../../de/dfa/muxer__listener_8h_source.html#l00053">muxer_listener.h:53</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1TextSampleEntry_html"><div class="ttname"><a href="../../d7/dc3/structshaka_1_1media_1_1mp4_1_1TextSampleEntry.html">shaka::media::mp4::TextSampleEntry</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00377">box_definitions.h:377</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1mp4_1_1MP4Muxer_html_a5b6a878865250e3e17268c011a361497"><div class="ttname"><a href="../../db/d30/classshaka_1_1media_1_1mp4_1_1MP4Muxer.html#a5b6a878865250e3e17268c011a361497">shaka::media::mp4::MP4Muxer::MP4Muxer</a></div><div class="ttdeci">MP4Muxer(const MuxerOptions &amp;options)</div><div class="ttdoc">Create a MP4Muxer object from MuxerOptions. </div><div class="ttdef"><b>Definition:</b> <a href="../../da/d88/mp4__muxer_8cc_source.html#l00135">mp4_muxer.cc:135</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1TrackExtends_html"><div class="ttname"><a href="../../de/d29/structshaka_1_1media_1_1mp4_1_1TrackExtends.html">shaka::media::mp4::TrackExtends</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00639">box_definitions.h:639</a></div></div>
<div class="ttc" id="namespaceshaka_html"><div class="ttname"><a href="../../d8/daf/namespaceshaka.html">shaka</a></div><div class="ttdoc">All the methods that are virtual are virtual for mocking. </div><div class="ttdef"><b>Definition:</b> <a href="../../d4/d15/gflags__hex__bytes_8cc_source.html#l00011">gflags_hex_bytes.cc:11</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1MuxerOptions_html"><div class="ttname"><a href="../../d0/d27/structshaka_1_1media_1_1MuxerOptions.html">shaka::media::MuxerOptions</a></div><div class="ttdoc">This structure contains the list of configuration options for Muxer. </div><div class="ttdef"><b>Definition:</b> <a href="../../d0/d0e/muxer__options_8h_source.html#l00020">muxer_options.h:20</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1Track_html"><div class="ttname"><a href="../../d3/db5/structshaka_1_1media_1_1mp4_1_1Track.html">shaka::media::mp4::Track</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00624">box_definitions.h:624</a></div></div>
<div class="ttc" id="classshaka_1_1Status_html"><div class="ttname"><a href="../../d2/d20/classshaka_1_1Status.html">shaka::Status</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d1/d13/status_8h_source.html#l00110">status.h:110</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1SampleDescription_html"><div class="ttname"><a href="../../da/df5/structshaka_1_1media_1_1mp4_1_1SampleDescription.html">shaka::media::mp4::SampleDescription</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00392">box_definitions.h:392</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1Movie_html"><div class="ttname"><a href="../../d0/d9a/structshaka_1_1media_1_1mp4_1_1Movie.html">shaka::media::mp4::Movie</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00656">box_definitions.h:656</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1MuxerListener_1_1MediaRanges_html"><div class="ttname"><a href="../../d1/d03/structshaka_1_1media_1_1MuxerListener_1_1MediaRanges.html">shaka::media::MuxerListener::MediaRanges</a></div><div class="ttdef"><b>Definition:</b> <a href="../../de/dfa/muxer__listener_8h_source.html#l00045">muxer_listener.h:45</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1VideoStreamInfo_html_a40b2e26c533904ff890f4ea8086d7f71"><div class="ttname"><a href="../../d6/db1/classshaka_1_1media_1_1VideoStreamInfo.html#a40b2e26c533904ff890f4ea8086d7f71">shaka::media::VideoStreamInfo::pixel_height</a></div><div class="ttdeci">uint32_t pixel_height() const</div><div class="ttdef"><b>Definition:</b> <a href="../../d7/d87/video__stream__info_8h_source.html#l00064">video_stream_info.h:64</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1MuxerListener_html_a11d4301cd53ab421f524bfa143eac21a"><div class="ttname"><a href="../../dd/d7a/classshaka_1_1media_1_1MuxerListener.html#a11d4301cd53ab421f524bfa143eac21a">shaka::media::MuxerListener::OnMediaEnd</a></div><div class="ttdeci">virtual void OnMediaEnd(const MediaRanges &amp;media_ranges, float duration_seconds)=0</div></div>
<div class="ttc" id="classshaka_1_1media_1_1MediaSample_html"><div class="ttname"><a href="../../d7/d6d/classshaka_1_1media_1_1MediaSample.html">shaka::media::MediaSample</a></div><div class="ttdoc">Class to hold a media sample. </div><div class="ttdef"><b>Definition:</b> <a href="../../dd/d80/media__sample_8h_source.html#l00022">media_sample.h:22</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1mp4_1_1SingleSegmentSegmenter_html"><div class="ttname"><a href="../../d0/dab/classshaka_1_1media_1_1mp4_1_1SingleSegmentSegmenter.html">shaka::media::mp4::SingleSegmentSegmenter</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d9/d01/mp4_2single__segment__segmenter_8h_source.html#l00029">single_segment_segmenter.h:29</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1Muxer_html"><div class="ttname"><a href="../../df/d46/classshaka_1_1media_1_1Muxer.html">shaka::media::Muxer</a></div><div class="ttdef"><b>Definition:</b> <a href="../../db/df6/muxer_8h_source.html#l00030">muxer.h:30</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1MuxerListener_html_a31536ec385a7ec22f323a42b872b499a"><div class="ttname"><a href="../../dd/d7a/classshaka_1_1media_1_1MuxerListener.html#a31536ec385a7ec22f323a42b872b499a">shaka::media::MuxerListener::OnMediaStart</a></div><div class="ttdeci">virtual void OnMediaStart(const MuxerOptions &amp;muxer_options, const StreamInfo &amp;stream_info, uint32_t time_scale, ContainerType container_type)=0</div></div>
<div class="ttc" id="structshaka_1_1media_1_1Range_html"><div class="ttname"><a href="../../d9/de0/structshaka_1_1media_1_1Range.html">shaka::media::Range</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d1/d12/range_8h_source.html#l00019">range.h:19</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1SampleGroupDescription_html"><div class="ttname"><a href="../../d7/d01/structshaka_1_1media_1_1mp4_1_1SampleGroupDescription.html">shaka::media::mp4::SampleGroupDescription</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00508">box_definitions.h:508</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1SampleToGroup_html"><div class="ttname"><a href="../../d0/d7c/structshaka_1_1media_1_1mp4_1_1SampleToGroup.html">shaka::media::mp4::SampleToGroup</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00532">box_definitions.h:532</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1TextStreamInfo_html"><div class="ttname"><a href="../../db/dab/classshaka_1_1media_1_1TextStreamInfo.html">shaka::media::TextStreamInfo</a></div><div class="ttdef"><b>Definition:</b> <a href="../../da/d2a/text__stream__info_8h_source.html#l00017">text_stream_info.h:17</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1VideoStreamInfo_html_ac0356f4786e3cc2699c13a253c5f3cb5"><div class="ttname"><a href="../../d6/db1/classshaka_1_1media_1_1VideoStreamInfo.html#ac0356f4786e3cc2699c13a253c5f3cb5">shaka::media::VideoStreamInfo::pixel_width</a></div><div class="ttdeci">uint32_t pixel_width() const</div><div class="ttdef"><b>Definition:</b> <a href="../../d7/d87/video__stream__info_8h_source.html#l00061">video_stream_info.h:61</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1VideoSampleEntry_html"><div class="ttname"><a href="../../d0/d73/structshaka_1_1media_1_1mp4_1_1VideoSampleEntry.html">shaka::media::mp4::VideoSampleEntry</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00289">box_definitions.h:289</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1VideoStreamInfo_html"><div class="ttname"><a href="../../d6/db1/classshaka_1_1media_1_1VideoStreamInfo.html">shaka::media::VideoStreamInfo</a></div><div class="ttdoc">Holds video stream information. </div><div class="ttdef"><b>Definition:</b> <a href="../../d7/d87/video__stream__info_8h_source.html#l00023">video_stream_info.h:23</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1mp4_1_1MultiSegmentSegmenter_html"><div class="ttname"><a href="../../d8/db7/classshaka_1_1media_1_1mp4_1_1MultiSegmentSegmenter.html">shaka::media::mp4::MultiSegmentSegmenter</a></div><div class="ttdef"><b>Definition:</b> <a href="../../da/d41/mp4_2multi__segment__segmenter_8h_source.html#l00031">multi_segment_segmenter.h:31</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1SampleTable_html"><div class="ttname"><a href="../../d1/dee/structshaka_1_1media_1_1mp4_1_1SampleTable.html">shaka::media::mp4::SampleTable</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00540">box_definitions.h:540</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1AudioStreamInfo_html"><div class="ttname"><a href="../../da/d4e/classshaka_1_1media_1_1AudioStreamInfo.html">shaka::media::AudioStreamInfo</a></div><div class="ttdoc">Holds audio stream information. </div><div class="ttdef"><b>Definition:</b> <a href="../../df/d32/audio__stream__info_8h_source.html#l00018">audio_stream_info.h:18</a></div></div>
</div><!-- fragment --></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Sat Feb 10 2018 15:36:43 for Shaka Packager SDK by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
</body>
</html>