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

117 lines
111 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 &lt;algorithm&gt;</span></div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>&#160;</div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span>&#160;<span class="preprocessor">#include &quot;packager/base/strings/string_number_conversions.h&quot;</span></div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>&#160;<span class="preprocessor">#include &quot;packager/base/time/clock.h&quot;</span></div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>&#160;<span class="preprocessor">#include &quot;packager/base/time/time.h&quot;</span></div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>&#160;<span class="preprocessor">#include &quot;packager/file/file.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/aes_encryptor.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/audio_stream_info.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/fourccs.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/key_source.h&quot;</span></div><div class="line"><a name="l00019"></a><span class="lineno"> 19</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/media_sample.h&quot;</span></div><div class="line"><a name="l00020"></a><span class="lineno"> 20</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/text_stream_info.h&quot;</span></div><div class="line"><a name="l00021"></a><span class="lineno"> 21</span>&#160;<span class="preprocessor">#include &quot;packager/media/base/video_stream_info.h&quot;</span></div><div class="line"><a name="l00022"></a><span class="lineno"> 22</span>&#160;<span class="preprocessor">#include &quot;packager/media/codecs/es_descriptor.h&quot;</span></div><div class="line"><a name="l00023"></a><span class="lineno"> 23</span>&#160;<span class="preprocessor">#include &quot;packager/media/event/muxer_listener.h&quot;</span></div><div class="line"><a name="l00024"></a><span class="lineno"> 24</span>&#160;<span class="preprocessor">#include &quot;packager/media/formats/mp4/box_definitions.h&quot;</span></div><div class="line"><a name="l00025"></a><span class="lineno"> 25</span>&#160;<span class="preprocessor">#include &quot;packager/media/formats/mp4/multi_segment_segmenter.h&quot;</span></div><div class="line"><a name="l00026"></a><span class="lineno"> 26</span>&#160;<span class="preprocessor">#include &quot;packager/media/formats/mp4/single_segment_segmenter.h&quot;</span></div><div class="line"><a name="l00027"></a><span class="lineno"> 27</span>&#160;<span class="preprocessor">#include &quot;packager/status_macros.h&quot;</span></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><a class="code" href="../../d8/daf/namespaceshaka.html">shaka</a> {</div><div class="line"><a name="l00030"></a><span class="lineno"> 30</span>&#160;<span class="keyword">namespace </span>media {</div><div class="line"><a name="l00031"></a><span class="lineno"> 31</span>&#160;<span class="keyword">namespace </span>mp4 {</div><div class="line"><a name="l00032"></a><span class="lineno"> 32</span>&#160;</div><div class="line"><a name="l00033"></a><span class="lineno"> 33</span>&#160;<span class="keyword">namespace </span>{</div><div class="line"><a name="l00034"></a><span class="lineno"> 34</span>&#160;</div><div class="line"><a name="l00035"></a><span class="lineno"> 35</span>&#160;<span class="comment">// Sets the range start and end value from offset and size.</span></div><div class="line"><a name="l00036"></a><span class="lineno"> 36</span>&#160;<span class="comment">// |start| and |end| are for byte-range-spec specified in RFC2616.</span></div><div class="line"><a name="l00037"></a><span class="lineno"> 37</span>&#160;<span class="keywordtype">void</span> SetStartAndEndFromOffsetAndSize(<span class="keywordtype">size_t</span> offset,</div><div class="line"><a name="l00038"></a><span class="lineno"> 38</span>&#160; <span class="keywordtype">size_t</span> size,</div><div class="line"><a name="l00039"></a><span class="lineno"> 39</span>&#160; Range* range) {</div><div class="line"><a name="l00040"></a><span class="lineno"> 40</span>&#160; DCHECK(range);</div><div class="line"><a name="l00041"></a><span class="lineno"> 41</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="l00042"></a><span class="lineno"> 42</span>&#160; <span class="comment">// Note that ranges are inclusive. So we need - 1.</span></div><div class="line"><a name="l00043"></a><span class="lineno"> 43</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="l00044"></a><span class="lineno"> 44</span>&#160;}</div><div class="line"><a name="l00045"></a><span class="lineno"> 45</span>&#160;</div><div class="line"><a name="l00046"></a><span class="lineno"> 46</span>&#160;FourCC CodecToFourCC(Codec codec, H26xStreamFormat h26x_stream_format) {</div><div class="line"><a name="l00047"></a><span class="lineno"> 47</span>&#160; <span class="keywordflow">switch</span> (codec) {</div><div class="line"><a name="l00048"></a><span class="lineno"> 48</span>&#160; <span class="keywordflow">case</span> kCodecAV1:</div><div class="line"><a name="l00049"></a><span class="lineno"> 49</span>&#160; <span class="keywordflow">return</span> FOURCC_av01;</div><div class="line"><a name="l00050"></a><span class="lineno"> 50</span>&#160; <span class="keywordflow">case</span> kCodecH264:</div><div class="line"><a name="l00051"></a><span class="lineno"> 51</span>&#160; <span class="keywordflow">return</span> h26x_stream_format ==</div><div class="line"><a name="l00052"></a><span class="lineno"> 52</span>&#160; H26xStreamFormat::kNalUnitStreamWithParameterSetNalus</div><div class="line"><a name="l00053"></a><span class="lineno"> 53</span>&#160; ? FOURCC_avc3</div><div class="line"><a name="l00054"></a><span class="lineno"> 54</span>&#160; : FOURCC_avc1;</div><div class="line"><a name="l00055"></a><span class="lineno"> 55</span>&#160; <span class="keywordflow">case</span> kCodecH265:</div><div class="line"><a name="l00056"></a><span class="lineno"> 56</span>&#160; <span class="keywordflow">return</span> h26x_stream_format ==</div><div class="line"><a name="l00057"></a><span class="lineno"> 57</span>&#160; H26xStreamFormat::kNalUnitStreamWithParameterSetNalus</div><div class="line"><a name="l00058"></a><span class="lineno"> 58</span>&#160; ? FOURCC_hev1</div><div class="line"><a name="l00059"></a><span class="lineno"> 59</span>&#160; : FOURCC_hvc1;</div><div class="line"><a name="l00060"></a><span class="lineno"> 60</span>&#160; <span class="keywordflow">case</span> kCodecH265DolbyVision:</div><div class="line"><a name="l00061"></a><span class="lineno"> 61</span>&#160; <span class="keywordflow">return</span> h26x_stream_format ==</div><div class="line"><a name="l00062"></a><span class="lineno"> 62</span>&#160; H26xStreamFormat::kNalUnitStreamWithParameterSetNalus</div><div class="line"><a name="l00063"></a><span class="lineno"> 63</span>&#160; ? FOURCC_dvhe</div><div class="line"><a name="l00064"></a><span class="lineno"> 64</span>&#160; : FOURCC_dvh1;</div><div class="line"><a name="l00065"></a><span class="lineno"> 65</span>&#160; <span class="keywordflow">case</span> kCodecVP8:</div><div class="line"><a name="l00066"></a><span class="lineno"> 66</span>&#160; <span class="keywordflow">return</span> FOURCC_vp08;</div><div class="line"><a name="l00067"></a><span class="lineno"> 67</span>&#160; <span class="keywordflow">case</span> kCodecVP9:</div><div class="line"><a name="l00068"></a><span class="lineno"> 68</span>&#160; <span class="keywordflow">return</span> FOURCC_vp09;</div><div class="line"><a name="l00069"></a><span class="lineno"> 69</span>&#160; <span class="keywordflow">case</span> kCodecAAC:</div><div class="line"><a name="l00070"></a><span class="lineno"> 70</span>&#160; <span class="keywordflow">return</span> FOURCC_mp4a;</div><div class="line"><a name="l00071"></a><span class="lineno"> 71</span>&#160; <span class="keywordflow">case</span> kCodecAC3:</div><div class="line"><a name="l00072"></a><span class="lineno"> 72</span>&#160; <span class="keywordflow">return</span> FOURCC_ac_3;</div><div class="line"><a name="l00073"></a><span class="lineno"> 73</span>&#160; <span class="keywordflow">case</span> kCodecDTSC:</div><div class="line"><a name="l00074"></a><span class="lineno"> 74</span>&#160; <span class="keywordflow">return</span> FOURCC_dtsc;</div><div class="line"><a name="l00075"></a><span class="lineno"> 75</span>&#160; <span class="keywordflow">case</span> kCodecDTSH:</div><div class="line"><a name="l00076"></a><span class="lineno"> 76</span>&#160; <span class="keywordflow">return</span> FOURCC_dtsh;</div><div class="line"><a name="l00077"></a><span class="lineno"> 77</span>&#160; <span class="keywordflow">case</span> kCodecDTSL:</div><div class="line"><a name="l00078"></a><span class="lineno"> 78</span>&#160; <span class="keywordflow">return</span> FOURCC_dtsl;</div><div class="line"><a name="l00079"></a><span class="lineno"> 79</span>&#160; <span class="keywordflow">case</span> kCodecDTSE:</div><div class="line"><a name="l00080"></a><span class="lineno"> 80</span>&#160; <span class="keywordflow">return</span> FOURCC_dtse;</div><div class="line"><a name="l00081"></a><span class="lineno"> 81</span>&#160; <span class="keywordflow">case</span> kCodecDTSM:</div><div class="line"><a name="l00082"></a><span class="lineno"> 82</span>&#160; <span class="keywordflow">return</span> FOURCC_dtsm;</div><div class="line"><a name="l00083"></a><span class="lineno"> 83</span>&#160; <span class="keywordflow">case</span> kCodecEAC3:</div><div class="line"><a name="l00084"></a><span class="lineno"> 84</span>&#160; <span class="keywordflow">return</span> FOURCC_ec_3;</div><div class="line"><a name="l00085"></a><span class="lineno"> 85</span>&#160; <span class="keywordflow">case</span> kCodecFlac:</div><div class="line"><a name="l00086"></a><span class="lineno"> 86</span>&#160; <span class="keywordflow">return</span> FOURCC_fLaC;</div><div class="line"><a name="l00087"></a><span class="lineno"> 87</span>&#160; <span class="keywordflow">case</span> kCodecOpus:</div><div class="line"><a name="l00088"></a><span class="lineno"> 88</span>&#160; <span class="keywordflow">return</span> FOURCC_Opus;</div><div class="line"><a name="l00089"></a><span class="lineno"> 89</span>&#160; <span class="keywordflow">default</span>:</div><div class="line"><a name="l00090"></a><span class="lineno"> 90</span>&#160; <span class="keywordflow">return</span> FOURCC_NULL;</div><div class="line"><a name="l00091"></a><span class="lineno"> 91</span>&#160; }</div><div class="line"><a name="l00092"></a><span class="lineno"> 92</span>&#160;}</div><div class="line"><a name="l00093"></a><span class="lineno"> 93</span>&#160;</div><div class="line"><a name="l00094"></a><span class="lineno"> 94</span>&#160;<span class="keywordtype">void</span> GenerateSinf(FourCC old_type,</div><div class="line"><a name="l00095"></a><span class="lineno"> 95</span>&#160; <span class="keyword">const</span> EncryptionConfig&amp; encryption_config,</div><div class="line"><a name="l00096"></a><span class="lineno"> 96</span>&#160; ProtectionSchemeInfo* sinf) {</div><div class="line"><a name="l00097"></a><span class="lineno"> 97</span>&#160; sinf-&gt;format.format = old_type;</div><div class="line"><a name="l00098"></a><span class="lineno"> 98</span>&#160;</div><div class="line"><a name="l00099"></a><span class="lineno"> 99</span>&#160; DCHECK_NE(encryption_config.protection_scheme, FOURCC_NULL);</div><div class="line"><a name="l00100"></a><span class="lineno"> 100</span>&#160; sinf-&gt;type.type = encryption_config.protection_scheme;</div><div class="line"><a name="l00101"></a><span class="lineno"> 101</span>&#160;</div><div class="line"><a name="l00102"></a><span class="lineno"> 102</span>&#160; <span class="comment">// The version of cenc implemented here. CENC 4.</span></div><div class="line"><a name="l00103"></a><span class="lineno"> 103</span>&#160; <span class="keyword">const</span> <span class="keywordtype">int</span> kCencSchemeVersion = 0x00010000;</div><div class="line"><a name="l00104"></a><span class="lineno"> 104</span>&#160; sinf-&gt;type.version = kCencSchemeVersion;</div><div class="line"><a name="l00105"></a><span class="lineno"> 105</span>&#160;</div><div class="line"><a name="l00106"></a><span class="lineno"> 106</span>&#160; <span class="keyword">auto</span>&amp; track_encryption = sinf-&gt;info.track_encryption;</div><div class="line"><a name="l00107"></a><span class="lineno"> 107</span>&#160; track_encryption.default_is_protected = 1;</div><div class="line"><a name="l00108"></a><span class="lineno"> 108</span>&#160;</div><div class="line"><a name="l00109"></a><span class="lineno"> 109</span>&#160; track_encryption.default_crypt_byte_block =</div><div class="line"><a name="l00110"></a><span class="lineno"> 110</span>&#160; encryption_config.crypt_byte_block;</div><div class="line"><a name="l00111"></a><span class="lineno"> 111</span>&#160; track_encryption.default_skip_byte_block = encryption_config.skip_byte_block;</div><div class="line"><a name="l00112"></a><span class="lineno"> 112</span>&#160; <span class="keywordflow">switch</span> (encryption_config.protection_scheme) {</div><div class="line"><a name="l00113"></a><span class="lineno"> 113</span>&#160; <span class="keywordflow">case</span> FOURCC_cenc:</div><div class="line"><a name="l00114"></a><span class="lineno"> 114</span>&#160; <span class="keywordflow">case</span> FOURCC_cbc1:</div><div class="line"><a name="l00115"></a><span class="lineno"> 115</span>&#160; DCHECK_EQ(track_encryption.default_crypt_byte_block, 0u);</div><div class="line"><a name="l00116"></a><span class="lineno"> 116</span>&#160; DCHECK_EQ(track_encryption.default_skip_byte_block, 0u);</div><div class="line"><a name="l00117"></a><span class="lineno"> 117</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="l00118"></a><span class="lineno"> 118</span>&#160; <span class="comment">// The version of the Track Encryption Box (tenc) SHALL be 0.</span></div><div class="line"><a name="l00119"></a><span class="lineno"> 119</span>&#160; track_encryption.version = 0;</div><div class="line"><a name="l00120"></a><span class="lineno"> 120</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00121"></a><span class="lineno"> 121</span>&#160; <span class="keywordflow">case</span> FOURCC_cbcs:</div><div class="line"><a name="l00122"></a><span class="lineno"> 122</span>&#160; <span class="keywordflow">case</span> FOURCC_cens:</div><div class="line"><a name="l00123"></a><span class="lineno"> 123</span>&#160; <span class="comment">// CENCv3 10.3 cens AES-CTR subsample pattern encryption scheme and</span></div><div class="line"><a name="l00124"></a><span class="lineno"> 124</span>&#160; <span class="comment">// 10.4 cbcs AES-CBC subsample pattern encryption scheme:</span></div><div class="line"><a name="l00125"></a><span class="lineno"> 125</span>&#160; <span class="comment">// The version of the Track Encryption Box (tenc) SHALL be 1.</span></div><div class="line"><a name="l00126"></a><span class="lineno"> 126</span>&#160; track_encryption.version = 1;</div><div class="line"><a name="l00127"></a><span class="lineno"> 127</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00128"></a><span class="lineno"> 128</span>&#160; <span class="keywordflow">default</span>:</div><div class="line"><a name="l00129"></a><span class="lineno"> 129</span>&#160; NOTREACHED() &lt;&lt; <span class="stringliteral">&quot;Unexpected protection scheme &quot;</span></div><div class="line"><a name="l00130"></a><span class="lineno"> 130</span>&#160; &lt;&lt; encryption_config.protection_scheme;</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; track_encryption.default_per_sample_iv_size =</div><div class="line"><a name="l00134"></a><span class="lineno"> 134</span>&#160; encryption_config.per_sample_iv_size;</div><div class="line"><a name="l00135"></a><span class="lineno"> 135</span>&#160; track_encryption.default_constant_iv = encryption_config.constant_iv;</div><div class="line"><a name="l00136"></a><span class="lineno"> 136</span>&#160; track_encryption.default_kid = encryption_config.key_id;</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;</div><div class="line"><a name="l00139"></a><span class="lineno"> 139</span>&#160;<span class="comment">// The roll distance is expressed in sample units and always takes negative</span></div><div class="line"><a name="l00140"></a><span class="lineno"> 140</span>&#160;<span class="comment">// values.</span></div><div class="line"><a name="l00141"></a><span class="lineno"> 141</span>&#160;int16_t GetRollDistance(uint64_t seek_preroll_ns, uint32_t sampling_frequency) {</div><div class="line"><a name="l00142"></a><span class="lineno"> 142</span>&#160; <span class="keyword">const</span> <span class="keywordtype">double</span> kNanosecondsPerSecond = 1000000000;</div><div class="line"><a name="l00143"></a><span class="lineno"> 143</span>&#160; <span class="keyword">const</span> <span class="keywordtype">double</span> preroll_in_samples =</div><div class="line"><a name="l00144"></a><span class="lineno"> 144</span>&#160; seek_preroll_ns / kNanosecondsPerSecond * sampling_frequency;</div><div class="line"><a name="l00145"></a><span class="lineno"> 145</span>&#160; <span class="comment">// Round to closest integer.</span></div><div class="line"><a name="l00146"></a><span class="lineno"> 146</span>&#160; <span class="keywordflow">return</span> -<span class="keyword">static_cast&lt;</span>int16_t<span class="keyword">&gt;</span>(preroll_in_samples + 0.5);</div><div class="line"><a name="l00147"></a><span class="lineno"> 147</span>&#160;}</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="comment">// namespace</span></div><div class="line"><a name="l00150"></a><span class="lineno"> 150</span>&#160;</div><div class="line"><a name="l00151"></a><span class="lineno"><a class="line" href="../../db/d30/classshaka_1_1media_1_1mp4_1_1MP4Muxer.html#a5b6a878865250e3e17268c011a361497"> 151</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="l00152"></a><span class="lineno"> 152</span>&#160;MP4Muxer::~MP4Muxer() {}</div><div class="line"><a name="l00153"></a><span class="lineno"> 153</span>&#160;</div><div class="line"><a name="l00154"></a><span class="lineno"> 154</span>&#160;<a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> MP4Muxer::InitializeMuxer() {</div><div class="line"><a name="l00155"></a><span class="lineno"> 155</span>&#160; <span class="comment">// Muxer will be delay-initialized after seeing the first sample.</span></div><div class="line"><a name="l00156"></a><span class="lineno"> 156</span>&#160; to_be_initialized_ = <span class="keyword">true</span>;</div><div class="line"><a name="l00157"></a><span class="lineno"> 157</span>&#160; <span class="keywordflow">return</span> Status::OK;</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;<a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> MP4Muxer::Finalize() {</div><div class="line"><a name="l00161"></a><span class="lineno"> 161</span>&#160; <span class="comment">// This happens on streams that are not initialized, i.e. not going through</span></div><div class="line"><a name="l00162"></a><span class="lineno"> 162</span>&#160; <span class="comment">// DelayInitializeMuxer, which can only happen if there are no samples from</span></div><div class="line"><a name="l00163"></a><span class="lineno"> 163</span>&#160; <span class="comment">// the stream.</span></div><div class="line"><a name="l00164"></a><span class="lineno"> 164</span>&#160; <span class="keywordflow">if</span> (!segmenter_) {</div><div class="line"><a name="l00165"></a><span class="lineno"> 165</span>&#160; DCHECK(to_be_initialized_);</div><div class="line"><a name="l00166"></a><span class="lineno"> 166</span>&#160; LOG(INFO) &lt;&lt; <span class="stringliteral">&quot;Skip stream &#39;&quot;</span> &lt;&lt; options().<a class="code" href="../../d0/d27/structshaka_1_1media_1_1MuxerOptions.html#a5397ee8759a663aea68261600e528d82">output_file_name</a></div><div class="line"><a name="l00167"></a><span class="lineno"> 167</span>&#160; &lt;&lt; <span class="stringliteral">&quot;&#39; which does not contain any sample.&quot;</span>;</div><div class="line"><a name="l00168"></a><span class="lineno"> 168</span>&#160; <span class="keywordflow">return</span> Status::OK;</div><div class="line"><a name="l00169"></a><span class="lineno"> 169</span>&#160; }</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; <a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> segmenter_finalized = segmenter_-&gt;Finalize();</div><div class="line"><a name="l00172"></a><span class="lineno"> 172</span>&#160;</div><div class="line"><a name="l00173"></a><span class="lineno"> 173</span>&#160; <span class="keywordflow">if</span> (!segmenter_finalized.ok())</div><div class="line"><a name="l00174"></a><span class="lineno"> 174</span>&#160; <span class="keywordflow">return</span> segmenter_finalized;</div><div class="line"><a name="l00175"></a><span class="lineno"> 175</span>&#160;</div><div class="line"><a name="l00176"></a><span class="lineno"> 176</span>&#160; FireOnMediaEndEvent();</div><div class="line"><a name="l00177"></a><span class="lineno"> 177</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="l00178"></a><span class="lineno"> 178</span>&#160; <span class="keywordflow">return</span> Status::OK;</div><div class="line"><a name="l00179"></a><span class="lineno"> 179</span>&#160;}</div><div class="line"><a name="l00180"></a><span class="lineno"> 180</span>&#160;</div><div class="line"><a name="l00181"></a><span class="lineno"> 181</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="l00182"></a><span class="lineno"> 182</span>&#160; <span class="keywordflow">if</span> (to_be_initialized_) {</div><div class="line"><a name="l00183"></a><span class="lineno"> 183</span>&#160; RETURN_IF_ERROR(UpdateEditListOffsetFromSample(sample));</div><div class="line"><a name="l00184"></a><span class="lineno"> 184</span>&#160; RETURN_IF_ERROR(DelayInitializeMuxer());</div><div class="line"><a name="l00185"></a><span class="lineno"> 185</span>&#160; to_be_initialized_ = <span class="keyword">false</span>;</div><div class="line"><a name="l00186"></a><span class="lineno"> 186</span>&#160; }</div><div class="line"><a name="l00187"></a><span class="lineno"> 187</span>&#160; DCHECK(segmenter_);</div><div class="line"><a name="l00188"></a><span class="lineno"> 188</span>&#160; <span class="keywordflow">return</span> segmenter_-&gt;AddSample(stream_id, sample);</div><div class="line"><a name="l00189"></a><span class="lineno"> 189</span>&#160;}</div><div class="line"><a name="l00190"></a><span class="lineno"> 190</span>&#160;</div><div class="line"><a name="l00191"></a><span class="lineno"> 191</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="l00192"></a><span class="lineno"> 192</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="l00193"></a><span class="lineno"> 193</span>&#160; DCHECK(segmenter_);</div><div class="line"><a name="l00194"></a><span class="lineno"> 194</span>&#160; VLOG(3) &lt;&lt; <span class="stringliteral">&quot;Finalizing &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="l00195"></a><span class="lineno"> 195</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="l00196"></a><span class="lineno"> 196</span>&#160; &lt;&lt; segment_info.duration;</div><div class="line"><a name="l00197"></a><span class="lineno"> 197</span>&#160; <span class="keywordflow">return</span> segmenter_-&gt;FinalizeSegment(stream_id, segment_info);</div><div class="line"><a name="l00198"></a><span class="lineno"> 198</span>&#160;}</div><div class="line"><a name="l00199"></a><span class="lineno"> 199</span>&#160;</div><div class="line"><a name="l00200"></a><span class="lineno"> 200</span>&#160;<a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a> MP4Muxer::DelayInitializeMuxer() {</div><div class="line"><a name="l00201"></a><span class="lineno"> 201</span>&#160; DCHECK(!streams().empty());</div><div class="line"><a name="l00202"></a><span class="lineno"> 202</span>&#160;</div><div class="line"><a name="l00203"></a><span class="lineno"> 203</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="l00204"></a><span class="lineno"> 204</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="l00205"></a><span class="lineno"> 205</span>&#160;</div><div class="line"><a name="l00206"></a><span class="lineno"> 206</span>&#160; ftyp-&gt;major_brand = FOURCC_isom;</div><div class="line"><a name="l00207"></a><span class="lineno"> 207</span>&#160; ftyp-&gt;compatible_brands.push_back(FOURCC_iso8);</div><div class="line"><a name="l00208"></a><span class="lineno"> 208</span>&#160; ftyp-&gt;compatible_brands.push_back(FOURCC_mp41);</div><div class="line"><a name="l00209"></a><span class="lineno"> 209</span>&#160; ftyp-&gt;compatible_brands.push_back(FOURCC_dash);</div><div class="line"><a name="l00210"></a><span class="lineno"> 210</span>&#160;</div><div class="line"><a name="l00211"></a><span class="lineno"> 211</span>&#160; <span class="keywordflow">if</span> (streams().size() == 1) {</div><div class="line"><a name="l00212"></a><span class="lineno"> 212</span>&#160; FourCC codec_fourcc = FOURCC_NULL;</div><div class="line"><a name="l00213"></a><span class="lineno"> 213</span>&#160; <span class="keywordflow">if</span> (streams()[0]-&gt;stream_type() == kStreamVideo) {</div><div class="line"><a name="l00214"></a><span class="lineno"> 214</span>&#160; codec_fourcc =</div><div class="line"><a name="l00215"></a><span class="lineno"> 215</span>&#160; CodecToFourCC(streams()[0]-&gt;codec(),</div><div class="line"><a name="l00216"></a><span class="lineno"> 216</span>&#160; static_cast&lt;const VideoStreamInfo*&gt;(streams()[0].<span class="keyword">get</span>())</div><div class="line"><a name="l00217"></a><span class="lineno"> 217</span>&#160; -&gt;h26x_stream_format());</div><div class="line"><a name="l00218"></a><span class="lineno"> 218</span>&#160; <span class="keywordflow">if</span> (codec_fourcc != FOURCC_NULL)</div><div class="line"><a name="l00219"></a><span class="lineno"> 219</span>&#160; ftyp-&gt;compatible_brands.push_back(codec_fourcc);</div><div class="line"><a name="l00220"></a><span class="lineno"> 220</span>&#160; }</div><div class="line"><a name="l00221"></a><span class="lineno"> 221</span>&#160;</div><div class="line"><a name="l00222"></a><span class="lineno"> 222</span>&#160; <span class="comment">// CMAF allows only one track/stream per file.</span></div><div class="line"><a name="l00223"></a><span class="lineno"> 223</span>&#160; <span class="comment">// CMAF requires single initialization switching for AVC3/HEV1, which is not</span></div><div class="line"><a name="l00224"></a><span class="lineno"> 224</span>&#160; <span class="comment">// supported yet.</span></div><div class="line"><a name="l00225"></a><span class="lineno"> 225</span>&#160; <span class="keywordflow">if</span> (codec_fourcc != FOURCC_avc3 &amp;&amp; codec_fourcc != FOURCC_hev1)</div><div class="line"><a name="l00226"></a><span class="lineno"> 226</span>&#160; ftyp-&gt;compatible_brands.push_back(FOURCC_cmfc);</div><div class="line"><a name="l00227"></a><span class="lineno"> 227</span>&#160; }</div><div class="line"><a name="l00228"></a><span class="lineno"> 228</span>&#160;</div><div class="line"><a name="l00229"></a><span class="lineno"> 229</span>&#160; moov-&gt;header.creation_time = IsoTimeNow();</div><div class="line"><a name="l00230"></a><span class="lineno"> 230</span>&#160; moov-&gt;header.modification_time = IsoTimeNow();</div><div class="line"><a name="l00231"></a><span class="lineno"> 231</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="l00232"></a><span class="lineno"> 232</span>&#160;</div><div class="line"><a name="l00233"></a><span class="lineno"> 233</span>&#160; moov-&gt;tracks.resize(streams().size());</div><div class="line"><a name="l00234"></a><span class="lineno"> 234</span>&#160; moov-&gt;extends.tracks.resize(streams().size());</div><div class="line"><a name="l00235"></a><span class="lineno"> 235</span>&#160;</div><div class="line"><a name="l00236"></a><span class="lineno"> 236</span>&#160; <span class="comment">// Initialize tracks.</span></div><div class="line"><a name="l00237"></a><span class="lineno"> 237</span>&#160; <span class="keywordflow">for</span> (uint32_t i = 0; i &lt; streams().size(); ++i) {</div><div class="line"><a name="l00238"></a><span class="lineno"> 238</span>&#160; <span class="keyword">const</span> <a class="code" href="../../d5/db1/classshaka_1_1media_1_1StreamInfo.html">StreamInfo</a>* stream = streams()[i].get();</div><div class="line"><a name="l00239"></a><span class="lineno"> 239</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="l00240"></a><span class="lineno"> 240</span>&#160; trak.header.track_id = i + 1;</div><div class="line"><a name="l00241"></a><span class="lineno"> 241</span>&#160;</div><div class="line"><a name="l00242"></a><span class="lineno"> 242</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="l00243"></a><span class="lineno"> 243</span>&#160; trex.track_id = trak.header.track_id;</div><div class="line"><a name="l00244"></a><span class="lineno"> 244</span>&#160; trex.default_sample_description_index = 1;</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; <span class="keywordtype">bool</span> generate_trak_result = <span class="keyword">false</span>;</div><div class="line"><a name="l00247"></a><span class="lineno"> 247</span>&#160; <span class="keywordflow">switch</span> (stream-&gt;stream_type()) {</div><div class="line"><a name="l00248"></a><span class="lineno"> 248</span>&#160; <span class="keywordflow">case</span> kStreamVideo:</div><div class="line"><a name="l00249"></a><span class="lineno"> 249</span>&#160; generate_trak_result = GenerateVideoTrak(</div><div class="line"><a name="l00250"></a><span class="lineno"> 250</span>&#160; static_cast&lt;const VideoStreamInfo*&gt;(stream), &amp;trak, i + 1);</div><div class="line"><a name="l00251"></a><span class="lineno"> 251</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00252"></a><span class="lineno"> 252</span>&#160; <span class="keywordflow">case</span> kStreamAudio:</div><div class="line"><a name="l00253"></a><span class="lineno"> 253</span>&#160; generate_trak_result = GenerateAudioTrak(</div><div class="line"><a name="l00254"></a><span class="lineno"> 254</span>&#160; static_cast&lt;const AudioStreamInfo*&gt;(stream), &amp;trak, i + 1);</div><div class="line"><a name="l00255"></a><span class="lineno"> 255</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00256"></a><span class="lineno"> 256</span>&#160; <span class="keywordflow">case</span> kStreamText:</div><div class="line"><a name="l00257"></a><span class="lineno"> 257</span>&#160; generate_trak_result = GenerateTextTrak(</div><div class="line"><a name="l00258"></a><span class="lineno"> 258</span>&#160; static_cast&lt;const TextStreamInfo*&gt;(stream), &amp;trak, i + 1);</div><div class="line"><a name="l00259"></a><span class="lineno"> 259</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00260"></a><span class="lineno"> 260</span>&#160; <span class="keywordflow">default</span>:</div><div class="line"><a name="l00261"></a><span class="lineno"> 261</span>&#160; NOTIMPLEMENTED() &lt;&lt; <span class="stringliteral">&quot;Not implemented for stream type: &quot;</span></div><div class="line"><a name="l00262"></a><span class="lineno"> 262</span>&#160; &lt;&lt; stream-&gt;stream_type();</div><div class="line"><a name="l00263"></a><span class="lineno"> 263</span>&#160; }</div><div class="line"><a name="l00264"></a><span class="lineno"> 264</span>&#160; <span class="keywordflow">if</span> (!generate_trak_result)</div><div class="line"><a name="l00265"></a><span class="lineno"> 265</span>&#160; <span class="keywordflow">return</span> <a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a>(error::MUXER_FAILURE, <span class="stringliteral">&quot;Failed to generate trak.&quot;</span>);</div><div class="line"><a name="l00266"></a><span class="lineno"> 266</span>&#160;</div><div class="line"><a name="l00267"></a><span class="lineno"> 267</span>&#160; <span class="comment">// Generate EditList if needed. See UpdateEditListOffsetFromSample() for</span></div><div class="line"><a name="l00268"></a><span class="lineno"> 268</span>&#160; <span class="comment">// more information.</span></div><div class="line"><a name="l00269"></a><span class="lineno"> 269</span>&#160; <span class="keywordflow">if</span> (edit_list_offset_.value() &gt; 0) {</div><div class="line"><a name="l00270"></a><span class="lineno"> 270</span>&#160; <a class="code" href="../../d4/d18/structshaka_1_1media_1_1mp4_1_1EditListEntry.html">EditListEntry</a> entry;</div><div class="line"><a name="l00271"></a><span class="lineno"> 271</span>&#160; entry.media_time = edit_list_offset_.value();</div><div class="line"><a name="l00272"></a><span class="lineno"> 272</span>&#160; entry.media_rate_integer = 1;</div><div class="line"><a name="l00273"></a><span class="lineno"> 273</span>&#160; trak.edit.list.edits.push_back(entry);</div><div class="line"><a name="l00274"></a><span class="lineno"> 274</span>&#160; }</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; <span class="keywordflow">if</span> (stream-&gt;is_encrypted() &amp;&amp; options().<a class="code" href="../../d0/d27/structshaka_1_1media_1_1MuxerOptions.html#aa616f5958ea9df2d70f3fe42ff47ff43">mp4_params</a>.<a class="code" href="../../d0/d43/structshaka_1_1Mp4OutputParams.html#abdff0b6ab552e27e275d8d23cc2f60b1">include_pssh_in_stream</a>) {</div><div class="line"><a name="l00277"></a><span class="lineno"> 277</span>&#160; moov-&gt;pssh.clear();</div><div class="line"><a name="l00278"></a><span class="lineno"> 278</span>&#160; <span class="keyword">const</span> <span class="keyword">auto</span>&amp; key_system_info = stream-&gt;encryption_config().key_system_info;</div><div class="line"><a name="l00279"></a><span class="lineno"> 279</span>&#160; <span class="keywordflow">for</span> (<span class="keyword">const</span> <a class="code" href="../../d0/d86/structshaka_1_1media_1_1ProtectionSystemSpecificInfo.html">ProtectionSystemSpecificInfo</a>&amp; system : key_system_info) {</div><div class="line"><a name="l00280"></a><span class="lineno"> 280</span>&#160; <span class="keywordflow">if</span> (system.psshs.empty())</div><div class="line"><a name="l00281"></a><span class="lineno"> 281</span>&#160; <span class="keywordflow">continue</span>;</div><div class="line"><a name="l00282"></a><span class="lineno"> 282</span>&#160; <a class="code" href="../../d0/d3c/structshaka_1_1media_1_1mp4_1_1ProtectionSystemSpecificHeader.html">ProtectionSystemSpecificHeader</a> pssh;</div><div class="line"><a name="l00283"></a><span class="lineno"> 283</span>&#160; pssh.raw_box = system.psshs;</div><div class="line"><a name="l00284"></a><span class="lineno"> 284</span>&#160; moov-&gt;pssh.push_back(pssh);</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; }</div><div class="line"><a name="l00288"></a><span class="lineno"> 288</span>&#160;</div><div class="line"><a name="l00289"></a><span class="lineno"> 289</span>&#160; <span class="keywordflow">if</span> (options().segment_template.empty()) {</div><div class="line"><a name="l00290"></a><span class="lineno"> 290</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="l00291"></a><span class="lineno"> 291</span>&#160; std::move(moov)));</div><div class="line"><a name="l00292"></a><span class="lineno"> 292</span>&#160; } <span class="keywordflow">else</span> {</div><div class="line"><a name="l00293"></a><span class="lineno"> 293</span>&#160; segmenter_.reset(</div><div class="line"><a name="l00294"></a><span class="lineno"> 294</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="l00295"></a><span class="lineno"> 295</span>&#160; }</div><div class="line"><a name="l00296"></a><span class="lineno"> 296</span>&#160;</div><div class="line"><a name="l00297"></a><span class="lineno"> 297</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="l00298"></a><span class="lineno"> 298</span>&#160; segmenter_-&gt;Initialize(streams(), muxer_listener(), progress_listener());</div><div class="line"><a name="l00299"></a><span class="lineno"> 299</span>&#160; <span class="keywordflow">if</span> (!segmenter_initialized.ok())</div><div class="line"><a name="l00300"></a><span class="lineno"> 300</span>&#160; <span class="keywordflow">return</span> segmenter_initialized;</div><div class="line"><a name="l00301"></a><span class="lineno"> 301</span>&#160;</div><div class="line"><a name="l00302"></a><span class="lineno"> 302</span>&#160; FireOnMediaStartEvent();</div><div class="line"><a name="l00303"></a><span class="lineno"> 303</span>&#160; <span class="keywordflow">return</span> Status::OK;</div><div class="line"><a name="l00304"></a><span class="lineno"> 304</span>&#160;}</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="../../d2/d20/classshaka_1_1Status.html">Status</a> MP4Muxer::UpdateEditListOffsetFromSample(<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="l00307"></a><span class="lineno"> 307</span>&#160; <span class="keywordflow">if</span> (edit_list_offset_)</div><div class="line"><a name="l00308"></a><span class="lineno"> 308</span>&#160; <span class="keywordflow">return</span> Status::OK;</div><div class="line"><a name="l00309"></a><span class="lineno"> 309</span>&#160;</div><div class="line"><a name="l00310"></a><span class="lineno"> 310</span>&#160; <span class="keyword">const</span> int64_t pts = sample.pts();</div><div class="line"><a name="l00311"></a><span class="lineno"> 311</span>&#160; <span class="keyword">const</span> int64_t dts = sample.dts();</div><div class="line"><a name="l00312"></a><span class="lineno"> 312</span>&#160; <span class="comment">// An EditList entry is inserted if one of the below conditions occur [4]:</span></div><div class="line"><a name="l00313"></a><span class="lineno"> 313</span>&#160; <span class="comment">// (1) pts &gt; dts for the first sample. Due to Chrome&#39;s dts bug [1], dts is</span></div><div class="line"><a name="l00314"></a><span class="lineno"> 314</span>&#160; <span class="comment">// used in buffered range API, while pts is used elsewhere (players,</span></div><div class="line"><a name="l00315"></a><span class="lineno"> 315</span>&#160; <span class="comment">// manifests, and Chrome&#39;s own appendWindow check etc.), this</span></div><div class="line"><a name="l00316"></a><span class="lineno"> 316</span>&#160; <span class="comment">// inconsistency creates various problems, including possible stalls</span></div><div class="line"><a name="l00317"></a><span class="lineno"> 317</span>&#160; <span class="comment">// during playback. Since Chrome adjusts pts only when seeing EditList</span></div><div class="line"><a name="l00318"></a><span class="lineno"> 318</span>&#160; <span class="comment">// [2], we can insert an EditList with the time equal to difference of pts</span></div><div class="line"><a name="l00319"></a><span class="lineno"> 319</span>&#160; <span class="comment">// and dts to make aligned buffered ranges using pts and dts. This</span></div><div class="line"><a name="l00320"></a><span class="lineno"> 320</span>&#160; <span class="comment">// effectively workarounds the dts bug. It is also recommended by ISO-BMFF</span></div><div class="line"><a name="l00321"></a><span class="lineno"> 321</span>&#160; <span class="comment">// specification [3].</span></div><div class="line"><a name="l00322"></a><span class="lineno"> 322</span>&#160; <span class="comment">// (2) pts == dts and with pts &lt; 0. This happens for some audio codecs where a</span></div><div class="line"><a name="l00323"></a><span class="lineno"> 323</span>&#160; <span class="comment">// negative presentation timestamp signals that the sample is not supposed</span></div><div class="line"><a name="l00324"></a><span class="lineno"> 324</span>&#160; <span class="comment">// to be shown, i.e. for audio priming. EditList is needed to encode</span></div><div class="line"><a name="l00325"></a><span class="lineno"> 325</span>&#160; <span class="comment">// negative timestamps.</span></div><div class="line"><a name="l00326"></a><span class="lineno"> 326</span>&#160; <span class="comment">// [1] https://crbug.com/718641, fixed but behind MseBufferByPts, still not</span></div><div class="line"><a name="l00327"></a><span class="lineno"> 327</span>&#160; <span class="comment">// enabled as of M67.</span></div><div class="line"><a name="l00328"></a><span class="lineno"> 328</span>&#160; <span class="comment">// [2] This is actually a bug, see https://crbug.com/354518. It looks like</span></div><div class="line"><a name="l00329"></a><span class="lineno"> 329</span>&#160; <span class="comment">// Chrome is planning to enable the fix for [1] before addressing this</span></div><div class="line"><a name="l00330"></a><span class="lineno"> 330</span>&#160; <span class="comment">// bug, so we are safe.</span></div><div class="line"><a name="l00331"></a><span class="lineno"> 331</span>&#160; <span class="comment">// [3] ISO 14496-12:2015 8.6.6.1</span></div><div class="line"><a name="l00332"></a><span class="lineno"> 332</span>&#160; <span class="comment">// It is recommended that such an edit be used to establish a presentation</span></div><div class="line"><a name="l00333"></a><span class="lineno"> 333</span>&#160; <span class="comment">// time of 0 for the first presented sample, when composition offsets are</span></div><div class="line"><a name="l00334"></a><span class="lineno"> 334</span>&#160; <span class="comment">// used.</span></div><div class="line"><a name="l00335"></a><span class="lineno"> 335</span>&#160; <span class="comment">// [4] ISO 23009-19:2018 7.5.13</span></div><div class="line"><a name="l00336"></a><span class="lineno"> 336</span>&#160; <span class="comment">// In two cases, an EditBox containing a single EditListBox with the</span></div><div class="line"><a name="l00337"></a><span class="lineno"> 337</span>&#160; <span class="comment">// following constraints may be present in the CMAF header of a CMAF track</span></div><div class="line"><a name="l00338"></a><span class="lineno"> 338</span>&#160; <span class="comment">// to adjust the presentation time of all media samples in the CMAF track.</span></div><div class="line"><a name="l00339"></a><span class="lineno"> 339</span>&#160; <span class="comment">// a) The first case is a video CMAF track file using v0 TrackRunBoxes</span></div><div class="line"><a name="l00340"></a><span class="lineno"> 340</span>&#160; <span class="comment">// with positive composition offsets to reorder video media samples.</span></div><div class="line"><a name="l00341"></a><span class="lineno"> 341</span>&#160; <span class="comment">// b) The second case is an audio CMAF track where each media sample&#39;s</span></div><div class="line"><a name="l00342"></a><span class="lineno"> 342</span>&#160; <span class="comment">// presentation time does not equal its composition time.</span></div><div class="line"><a name="l00343"></a><span class="lineno"> 343</span>&#160; <span class="keyword">const</span> int64_t pts_dts_offset = pts - dts;</div><div class="line"><a name="l00344"></a><span class="lineno"> 344</span>&#160; <span class="keywordflow">if</span> (pts_dts_offset &gt; 0) {</div><div class="line"><a name="l00345"></a><span class="lineno"> 345</span>&#160; <span class="keywordflow">if</span> (pts &lt; 0) {</div><div class="line"><a name="l00346"></a><span class="lineno"> 346</span>&#160; LOG(ERROR) &lt;&lt; <span class="stringliteral">&quot;Negative presentation timestamp (&quot;</span> &lt;&lt; pts</div><div class="line"><a name="l00347"></a><span class="lineno"> 347</span>&#160; &lt;&lt; <span class="stringliteral">&quot;) is not supported when there is an offset between &quot;</span></div><div class="line"><a name="l00348"></a><span class="lineno"> 348</span>&#160; <span class="stringliteral">&quot;presentation timestamp and decoding timestamp (&quot;</span></div><div class="line"><a name="l00349"></a><span class="lineno"> 349</span>&#160; &lt;&lt; dts &lt;&lt; <span class="stringliteral">&quot;).&quot;</span>;</div><div class="line"><a name="l00350"></a><span class="lineno"> 350</span>&#160; <span class="keywordflow">return</span> <a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a>(error::MUXER_FAILURE,</div><div class="line"><a name="l00351"></a><span class="lineno"> 351</span>&#160; <span class="stringliteral">&quot;Unsupported negative pts when there is an offset between &quot;</span></div><div class="line"><a name="l00352"></a><span class="lineno"> 352</span>&#160; <span class="stringliteral">&quot;pts and dts.&quot;</span>);</div><div class="line"><a name="l00353"></a><span class="lineno"> 353</span>&#160; }</div><div class="line"><a name="l00354"></a><span class="lineno"> 354</span>&#160; edit_list_offset_ = pts_dts_offset;</div><div class="line"><a name="l00355"></a><span class="lineno"> 355</span>&#160; <span class="keywordflow">return</span> Status::OK;</div><div class="line"><a name="l00356"></a><span class="lineno"> 356</span>&#160; }</div><div class="line"><a name="l00357"></a><span class="lineno"> 357</span>&#160; <span class="keywordflow">if</span> (pts_dts_offset &lt; 0) {</div><div class="line"><a name="l00358"></a><span class="lineno"> 358</span>&#160; LOG(ERROR) &lt;&lt; <span class="stringliteral">&quot;presentation timestamp (&quot;</span> &lt;&lt; pts</div><div class="line"><a name="l00359"></a><span class="lineno"> 359</span>&#160; &lt;&lt; <span class="stringliteral">&quot;) is not supposed to be greater than decoding timestamp (&quot;</span></div><div class="line"><a name="l00360"></a><span class="lineno"> 360</span>&#160; &lt;&lt; dts &lt;&lt; <span class="stringliteral">&quot;).&quot;</span>;</div><div class="line"><a name="l00361"></a><span class="lineno"> 361</span>&#160; <span class="keywordflow">return</span> <a class="code" href="../../d2/d20/classshaka_1_1Status.html">Status</a>(error::MUXER_FAILURE, <span class="stringliteral">&quot;Not expecting pts &lt; dts.&quot;</span>);</div><div class="line"><a name="l00362"></a><span class="lineno"> 362</span>&#160; }</div><div class="line"><a name="l00363"></a><span class="lineno"> 363</span>&#160; edit_list_offset_ = std::max(-sample.pts(), <span class="keyword">static_cast&lt;</span>int64_t<span class="keyword">&gt;</span>(0));</div><div class="line"><a name="l00364"></a><span class="lineno"> 364</span>&#160; <span class="keywordflow">return</span> Status::OK;</div><div class="line"><a name="l00365"></a><span class="lineno"> 365</span>&#160;}</div><div class="line"><a name="l00366"></a><span class="lineno"> 366</span>&#160;</div><div class="line"><a name="l00367"></a><span class="lineno"> 367</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="l00368"></a><span class="lineno"> 368</span>&#160; int64_t now = IsoTimeNow();</div><div class="line"><a name="l00369"></a><span class="lineno"> 369</span>&#160; trak-&gt;header.creation_time = now;</div><div class="line"><a name="l00370"></a><span class="lineno"> 370</span>&#160; trak-&gt;header.modification_time = now;</div><div class="line"><a name="l00371"></a><span class="lineno"> 371</span>&#160; trak-&gt;header.duration = 0;</div><div class="line"><a name="l00372"></a><span class="lineno"> 372</span>&#160; trak-&gt;media.header.creation_time = now;</div><div class="line"><a name="l00373"></a><span class="lineno"> 373</span>&#160; trak-&gt;media.header.modification_time = now;</div><div class="line"><a name="l00374"></a><span class="lineno"> 374</span>&#160; trak-&gt;media.header.timescale = info-&gt;time_scale();</div><div class="line"><a name="l00375"></a><span class="lineno"> 375</span>&#160; trak-&gt;media.header.duration = 0;</div><div class="line"><a name="l00376"></a><span class="lineno"> 376</span>&#160; <span class="keywordflow">if</span> (!info-&gt;language().empty()) {</div><div class="line"><a name="l00377"></a><span class="lineno"> 377</span>&#160; <span class="comment">// Strip off the subtag, if any.</span></div><div class="line"><a name="l00378"></a><span class="lineno"> 378</span>&#160; std::string main_language = info-&gt;language();</div><div class="line"><a name="l00379"></a><span class="lineno"> 379</span>&#160; <span class="keywordtype">size_t</span> dash = main_language.find(<span class="charliteral">&#39;-&#39;</span>);</div><div class="line"><a name="l00380"></a><span class="lineno"> 380</span>&#160; <span class="keywordflow">if</span> (dash != std::string::npos) {</div><div class="line"><a name="l00381"></a><span class="lineno"> 381</span>&#160; main_language.erase(dash);</div><div class="line"><a name="l00382"></a><span class="lineno"> 382</span>&#160; }</div><div class="line"><a name="l00383"></a><span class="lineno"> 383</span>&#160;</div><div class="line"><a name="l00384"></a><span class="lineno"> 384</span>&#160; <span class="comment">// ISO-639-2/T main language code should be 3 characters.</span></div><div class="line"><a name="l00385"></a><span class="lineno"> 385</span>&#160; <span class="keywordflow">if</span> (main_language.size() != 3) {</div><div class="line"><a name="l00386"></a><span class="lineno"> 386</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="l00387"></a><span class="lineno"> 387</span>&#160; &lt;&lt; <span class="stringliteral">&quot;language code, ignoring.&quot;</span>;</div><div class="line"><a name="l00388"></a><span class="lineno"> 388</span>&#160; } <span class="keywordflow">else</span> {</div><div class="line"><a name="l00389"></a><span class="lineno"> 389</span>&#160; trak-&gt;media.header.language.code = main_language;</div><div class="line"><a name="l00390"></a><span class="lineno"> 390</span>&#160; }</div><div class="line"><a name="l00391"></a><span class="lineno"> 391</span>&#160; }</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;</div><div class="line"><a name="l00394"></a><span class="lineno"> 394</span>&#160;<span class="keywordtype">bool</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="l00395"></a><span class="lineno"> 395</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="l00396"></a><span class="lineno"> 396</span>&#160; uint32_t track_id) {</div><div class="line"><a name="l00397"></a><span class="lineno"> 397</span>&#160; InitializeTrak(video_info, trak);</div><div class="line"><a name="l00398"></a><span class="lineno"> 398</span>&#160;</div><div class="line"><a name="l00399"></a><span class="lineno"> 399</span>&#160; <span class="comment">// width and height specify the track&#39;s visual presentation size as</span></div><div class="line"><a name="l00400"></a><span class="lineno"> 400</span>&#160; <span class="comment">// fixed-point 16.16 values.</span></div><div class="line"><a name="l00401"></a><span class="lineno"> 401</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="l00402"></a><span class="lineno"> 402</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="l00403"></a><span class="lineno"> 403</span>&#160; <span class="keywordflow">if</span> (pixel_width == 0 || pixel_height == 0) {</div><div class="line"><a name="l00404"></a><span class="lineno"> 404</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="l00405"></a><span class="lineno"> 405</span>&#160; pixel_width = 1;</div><div class="line"><a name="l00406"></a><span class="lineno"> 406</span>&#160; pixel_height = 1;</div><div class="line"><a name="l00407"></a><span class="lineno"> 407</span>&#160; }</div><div class="line"><a name="l00408"></a><span class="lineno"> 408</span>&#160; <span class="keyword">const</span> <span class="keywordtype">double</span> sample_aspect_ratio =</div><div class="line"><a name="l00409"></a><span class="lineno"> 409</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="l00410"></a><span class="lineno"> 410</span>&#160; trak-&gt;header.width = video_info-&gt;width() * sample_aspect_ratio * 0x10000;</div><div class="line"><a name="l00411"></a><span class="lineno"> 411</span>&#160; trak-&gt;header.height = video_info-&gt;height() * 0x10000;</div><div class="line"><a name="l00412"></a><span class="lineno"> 412</span>&#160;</div><div class="line"><a name="l00413"></a><span class="lineno"> 413</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="l00414"></a><span class="lineno"> 414</span>&#160; video.format =</div><div class="line"><a name="l00415"></a><span class="lineno"> 415</span>&#160; CodecToFourCC(video_info-&gt;codec(), video_info-&gt;h26x_stream_format());</div><div class="line"><a name="l00416"></a><span class="lineno"> 416</span>&#160; video.width = video_info-&gt;width();</div><div class="line"><a name="l00417"></a><span class="lineno"> 417</span>&#160; video.height = video_info-&gt;height();</div><div class="line"><a name="l00418"></a><span class="lineno"> 418</span>&#160; video.codec_configuration.data = video_info-&gt;codec_config();</div><div class="line"><a name="l00419"></a><span class="lineno"> 419</span>&#160; <span class="keywordflow">if</span> (!video.ParseExtraCodecConfigsVector(video_info-&gt;extra_config())) {</div><div class="line"><a name="l00420"></a><span class="lineno"> 420</span>&#160; LOG(ERROR) &lt;&lt; <span class="stringliteral">&quot;Malformed extra codec configs: &quot;</span></div><div class="line"><a name="l00421"></a><span class="lineno"> 421</span>&#160; &lt;&lt; base::HexEncode(video_info-&gt;extra_config().data(),</div><div class="line"><a name="l00422"></a><span class="lineno"> 422</span>&#160; video_info-&gt;extra_config().size());</div><div class="line"><a name="l00423"></a><span class="lineno"> 423</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"><a name="l00424"></a><span class="lineno"> 424</span>&#160; }</div><div class="line"><a name="l00425"></a><span class="lineno"> 425</span>&#160; <span class="keywordflow">if</span> (pixel_width != 1 || pixel_height != 1) {</div><div class="line"><a name="l00426"></a><span class="lineno"> 426</span>&#160; video.pixel_aspect.h_spacing = pixel_width;</div><div class="line"><a name="l00427"></a><span class="lineno"> 427</span>&#160; video.pixel_aspect.v_spacing = pixel_height;</div><div class="line"><a name="l00428"></a><span class="lineno"> 428</span>&#160; }</div><div class="line"><a name="l00429"></a><span class="lineno"> 429</span>&#160;</div><div class="line"><a name="l00430"></a><span class="lineno"> 430</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="l00431"></a><span class="lineno"> 431</span>&#160; trak-&gt;media.information.sample_table.description;</div><div class="line"><a name="l00432"></a><span class="lineno"> 432</span>&#160; sample_description.type = kVideo;</div><div class="line"><a name="l00433"></a><span class="lineno"> 433</span>&#160; sample_description.video_entries.push_back(video);</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; <span class="keywordflow">if</span> (video_info-&gt;is_encrypted()) {</div><div class="line"><a name="l00436"></a><span class="lineno"> 436</span>&#160; <span class="keywordflow">if</span> (video_info-&gt;has_clear_lead()) {</div><div class="line"><a name="l00437"></a><span class="lineno"> 437</span>&#160; <span class="comment">// Add a second entry for clear content.</span></div><div class="line"><a name="l00438"></a><span class="lineno"> 438</span>&#160; sample_description.video_entries.push_back(video);</div><div class="line"><a name="l00439"></a><span class="lineno"> 439</span>&#160; }</div><div class="line"><a name="l00440"></a><span class="lineno"> 440</span>&#160; <span class="comment">// Convert the first entry to an encrypted entry.</span></div><div class="line"><a name="l00441"></a><span class="lineno"> 441</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="l00442"></a><span class="lineno"> 442</span>&#160; GenerateSinf(entry.format, video_info-&gt;encryption_config(), &amp;entry.sinf);</div><div class="line"><a name="l00443"></a><span class="lineno"> 443</span>&#160; entry.format = FOURCC_encv;</div><div class="line"><a name="l00444"></a><span class="lineno"> 444</span>&#160; }</div><div class="line"><a name="l00445"></a><span class="lineno"> 445</span>&#160; <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line"><a name="l00446"></a><span class="lineno"> 446</span>&#160;}</div><div class="line"><a name="l00447"></a><span class="lineno"> 447</span>&#160;</div><div class="line"><a name="l00448"></a><span class="lineno"> 448</span>&#160;<span class="keywordtype">bool</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="l00449"></a><span class="lineno"> 449</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="l00450"></a><span class="lineno"> 450</span>&#160; uint32_t track_id) {</div><div class="line"><a name="l00451"></a><span class="lineno"> 451</span>&#160; InitializeTrak(audio_info, trak);</div><div class="line"><a name="l00452"></a><span class="lineno"> 452</span>&#160;</div><div class="line"><a name="l00453"></a><span class="lineno"> 453</span>&#160; trak-&gt;header.volume = 0x100;</div><div class="line"><a name="l00454"></a><span class="lineno"> 454</span>&#160;</div><div class="line"><a name="l00455"></a><span class="lineno"> 455</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="l00456"></a><span class="lineno"> 456</span>&#160; audio.format =</div><div class="line"><a name="l00457"></a><span class="lineno"> 457</span>&#160; CodecToFourCC(audio_info-&gt;codec(), H26xStreamFormat::kUnSpecified);</div><div class="line"><a name="l00458"></a><span class="lineno"> 458</span>&#160; <span class="keywordflow">switch</span>(audio_info-&gt;codec()){</div><div class="line"><a name="l00459"></a><span class="lineno"> 459</span>&#160; <span class="keywordflow">case</span> kCodecAAC: {</div><div class="line"><a name="l00460"></a><span class="lineno"> 460</span>&#160; audio.esds.es_descriptor.set_esid(track_id);</div><div class="line"><a name="l00461"></a><span class="lineno"> 461</span>&#160; <a class="code" href="../../d5/d58/classshaka_1_1media_1_1DecoderConfigDescriptor.html">DecoderConfigDescriptor</a>* decoder_config =</div><div class="line"><a name="l00462"></a><span class="lineno"> 462</span>&#160; audio.esds.es_descriptor.mutable_decoder_config_descriptor();</div><div class="line"><a name="l00463"></a><span class="lineno"> 463</span>&#160; decoder_config-&gt;set_object_type(ObjectType::kISO_14496_3); <span class="comment">// MPEG4 AAC.</span></div><div class="line"><a name="l00464"></a><span class="lineno"> 464</span>&#160; decoder_config-&gt;set_max_bitrate(audio_info-&gt;max_bitrate());</div><div class="line"><a name="l00465"></a><span class="lineno"> 465</span>&#160; decoder_config-&gt;set_avg_bitrate(audio_info-&gt;avg_bitrate());</div><div class="line"><a name="l00466"></a><span class="lineno"> 466</span>&#160; decoder_config-&gt;mutable_decoder_specific_info_descriptor()-&gt;set_data(</div><div class="line"><a name="l00467"></a><span class="lineno"> 467</span>&#160; audio_info-&gt;codec_config());</div><div class="line"><a name="l00468"></a><span class="lineno"> 468</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00469"></a><span class="lineno"> 469</span>&#160; }</div><div class="line"><a name="l00470"></a><span class="lineno"> 470</span>&#160; <span class="keywordflow">case</span> kCodecDTSC:</div><div class="line"><a name="l00471"></a><span class="lineno"> 471</span>&#160; <span class="keywordflow">case</span> kCodecDTSH:</div><div class="line"><a name="l00472"></a><span class="lineno"> 472</span>&#160; <span class="keywordflow">case</span> kCodecDTSL:</div><div class="line"><a name="l00473"></a><span class="lineno"> 473</span>&#160; <span class="keywordflow">case</span> kCodecDTSE:</div><div class="line"><a name="l00474"></a><span class="lineno"> 474</span>&#160; <span class="keywordflow">case</span> kCodecDTSM:</div><div class="line"><a name="l00475"></a><span class="lineno"> 475</span>&#160; audio.ddts.extra_data = audio_info-&gt;codec_config();</div><div class="line"><a name="l00476"></a><span class="lineno"> 476</span>&#160; audio.ddts.max_bitrate = audio_info-&gt;max_bitrate();</div><div class="line"><a name="l00477"></a><span class="lineno"> 477</span>&#160; audio.ddts.avg_bitrate = audio_info-&gt;avg_bitrate();</div><div class="line"><a name="l00478"></a><span class="lineno"> 478</span>&#160; audio.ddts.sampling_frequency = audio_info-&gt;sampling_frequency();</div><div class="line"><a name="l00479"></a><span class="lineno"> 479</span>&#160; audio.ddts.pcm_sample_depth = audio_info-&gt;sample_bits();</div><div class="line"><a name="l00480"></a><span class="lineno"> 480</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00481"></a><span class="lineno"> 481</span>&#160; <span class="keywordflow">case</span> kCodecAC3:</div><div class="line"><a name="l00482"></a><span class="lineno"> 482</span>&#160; audio.dac3.data = audio_info-&gt;codec_config();</div><div class="line"><a name="l00483"></a><span class="lineno"> 483</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00484"></a><span class="lineno"> 484</span>&#160; <span class="keywordflow">case</span> kCodecEAC3:</div><div class="line"><a name="l00485"></a><span class="lineno"> 485</span>&#160; audio.dec3.data = audio_info-&gt;codec_config();</div><div class="line"><a name="l00486"></a><span class="lineno"> 486</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00487"></a><span class="lineno"> 487</span>&#160; <span class="keywordflow">case</span> kCodecFlac:</div><div class="line"><a name="l00488"></a><span class="lineno"> 488</span>&#160; audio.dfla.data = audio_info-&gt;codec_config();</div><div class="line"><a name="l00489"></a><span class="lineno"> 489</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00490"></a><span class="lineno"> 490</span>&#160; <span class="keywordflow">case</span> kCodecOpus:</div><div class="line"><a name="l00491"></a><span class="lineno"> 491</span>&#160; audio.dops.opus_identification_header = audio_info-&gt;codec_config();</div><div class="line"><a name="l00492"></a><span class="lineno"> 492</span>&#160; <span class="keywordflow">break</span>;</div><div class="line"><a name="l00493"></a><span class="lineno"> 493</span>&#160; <span class="keywordflow">default</span>:</div><div class="line"><a name="l00494"></a><span class="lineno"> 494</span>&#160; NOTIMPLEMENTED() &lt;&lt; <span class="stringliteral">&quot; Unsupported audio codec &quot;</span> &lt;&lt; audio_info-&gt;codec();</div><div class="line"><a name="l00495"></a><span class="lineno"> 495</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</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;</div><div class="line"><a name="l00498"></a><span class="lineno"> 498</span>&#160; <span class="keywordflow">if</span> (audio_info-&gt;codec() == kCodecAC3 || audio_info-&gt;codec() == kCodecEAC3) {</div><div class="line"><a name="l00499"></a><span class="lineno"> 499</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="l00500"></a><span class="lineno"> 500</span>&#160; <span class="comment">// sample description entry. Instead, two constants are used.</span></div><div class="line"><a name="l00501"></a><span class="lineno"> 501</span>&#160; audio.channelcount = 2;</div><div class="line"><a name="l00502"></a><span class="lineno"> 502</span>&#160; audio.samplesize = 16;</div><div class="line"><a name="l00503"></a><span class="lineno"> 503</span>&#160; } <span class="keywordflow">else</span> {</div><div class="line"><a name="l00504"></a><span class="lineno"> 504</span>&#160; audio.channelcount = audio_info-&gt;num_channels();</div><div class="line"><a name="l00505"></a><span class="lineno"> 505</span>&#160; audio.samplesize = audio_info-&gt;sample_bits();</div><div class="line"><a name="l00506"></a><span class="lineno"> 506</span>&#160; }</div><div class="line"><a name="l00507"></a><span class="lineno"> 507</span>&#160; audio.samplerate = audio_info-&gt;sampling_frequency();</div><div class="line"><a name="l00508"></a><span class="lineno"> 508</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="l00509"></a><span class="lineno"> 509</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="l00510"></a><span class="lineno"> 510</span>&#160; sample_description.type = kAudio;</div><div class="line"><a name="l00511"></a><span class="lineno"> 511</span>&#160; sample_description.audio_entries.push_back(audio);</div><div class="line"><a name="l00512"></a><span class="lineno"> 512</span>&#160;</div><div class="line"><a name="l00513"></a><span class="lineno"> 513</span>&#160; <span class="keywordflow">if</span> (audio_info-&gt;is_encrypted()) {</div><div class="line"><a name="l00514"></a><span class="lineno"> 514</span>&#160; <span class="keywordflow">if</span> (audio_info-&gt;has_clear_lead()) {</div><div class="line"><a name="l00515"></a><span class="lineno"> 515</span>&#160; <span class="comment">// Add a second entry for clear content.</span></div><div class="line"><a name="l00516"></a><span class="lineno"> 516</span>&#160; sample_description.audio_entries.push_back(audio);</div><div class="line"><a name="l00517"></a><span class="lineno"> 517</span>&#160; }</div><div class="line"><a name="l00518"></a><span class="lineno"> 518</span>&#160; <span class="comment">// Convert the first entry to an encrypted entry.</span></div><div class="line"><a name="l00519"></a><span class="lineno"> 519</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="l00520"></a><span class="lineno"> 520</span>&#160; GenerateSinf(entry.format, audio_info-&gt;encryption_config(), &amp;entry.sinf);</div><div class="line"><a name="l00521"></a><span class="lineno"> 521</span>&#160; entry.format = FOURCC_enca;</div><div class="line"><a name="l00522"></a><span class="lineno"> 522</span>&#160; }</div><div class="line"><a name="l00523"></a><span class="lineno"> 523</span>&#160;</div><div class="line"><a name="l00524"></a><span class="lineno"> 524</span>&#160; <span class="keywordflow">if</span> (audio_info-&gt;seek_preroll_ns() &gt; 0) {</div><div class="line"><a name="l00525"></a><span class="lineno"> 525</span>&#160; sample_table.sample_group_descriptions.resize(1);</div><div class="line"><a name="l00526"></a><span class="lineno"> 526</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="l00527"></a><span class="lineno"> 527</span>&#160; sample_table.sample_group_descriptions.back();</div><div class="line"><a name="l00528"></a><span class="lineno"> 528</span>&#160; sample_group_description.grouping_type = FOURCC_roll;</div><div class="line"><a name="l00529"></a><span class="lineno"> 529</span>&#160; sample_group_description.audio_roll_recovery_entries.resize(1);</div><div class="line"><a name="l00530"></a><span class="lineno"> 530</span>&#160; sample_group_description.audio_roll_recovery_entries[0].roll_distance =</div><div class="line"><a name="l00531"></a><span class="lineno"> 531</span>&#160; GetRollDistance(audio_info-&gt;seek_preroll_ns(), audio.samplerate);</div><div class="line"><a name="l00532"></a><span class="lineno"> 532</span>&#160; <span class="comment">// sample to group box is not allowed in the init segment per CMAF</span></div><div class="line"><a name="l00533"></a><span class="lineno"> 533</span>&#160; <span class="comment">// specification. It is put in the fragment instead.</span></div><div class="line"><a name="l00534"></a><span class="lineno"> 534</span>&#160; }</div><div class="line"><a name="l00535"></a><span class="lineno"> 535</span>&#160; <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line"><a name="l00536"></a><span class="lineno"> 536</span>&#160;}</div><div class="line"><a name="l00537"></a><span class="lineno"> 537</span>&#160;</div><div class="line"><a name="l00538"></a><span class="lineno"> 538</span>&#160;<span class="keywordtype">bool</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="l00539"></a><span class="lineno"> 539</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="l00540"></a><span class="lineno"> 540</span>&#160; uint32_t track_id) {</div><div class="line"><a name="l00541"></a><span class="lineno"> 541</span>&#160; InitializeTrak(text_info, trak);</div><div class="line"><a name="l00542"></a><span class="lineno"> 542</span>&#160;</div><div class="line"><a name="l00543"></a><span class="lineno"> 543</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="l00544"></a><span class="lineno"> 544</span>&#160; <span class="comment">// Handle WebVTT.</span></div><div class="line"><a name="l00545"></a><span class="lineno"> 545</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="l00546"></a><span class="lineno"> 546</span>&#160; webvtt.format = FOURCC_wvtt;</div><div class="line"><a name="l00547"></a><span class="lineno"> 547</span>&#160;</div><div class="line"><a name="l00548"></a><span class="lineno"> 548</span>&#160; <span class="comment">// 14496-30:2014 7.5 Web Video Text Tracks Sample entry format.</span></div><div class="line"><a name="l00549"></a><span class="lineno"> 549</span>&#160; <span class="comment">// In the sample entry, a WebVTT configuration box must occur, carrying</span></div><div class="line"><a name="l00550"></a><span class="lineno"> 550</span>&#160; <span class="comment">// exactly the lines of the WebVTT file header, i.e. all text lines up to</span></div><div class="line"><a name="l00551"></a><span class="lineno"> 551</span>&#160; <span class="comment">// but excluding the &#39;two or more line terminators&#39; that end the header.</span></div><div class="line"><a name="l00552"></a><span class="lineno"> 552</span>&#160; webvtt.config.config = <span class="stringliteral">&quot;WEBVTT&quot;</span>;</div><div class="line"><a name="l00553"></a><span class="lineno"> 553</span>&#160; <span class="comment">// The spec does not define a way to carry STYLE and REGION information in</span></div><div class="line"><a name="l00554"></a><span class="lineno"> 554</span>&#160; <span class="comment">// the mp4 container.</span></div><div class="line"><a name="l00555"></a><span class="lineno"> 555</span>&#160; <span class="keywordflow">if</span> (!text_info-&gt;codec_config().empty()) {</div><div class="line"><a name="l00556"></a><span class="lineno"> 556</span>&#160; LOG(INFO) &lt;&lt; <span class="stringliteral">&quot;Skipping possible style / region configuration as the spec &quot;</span></div><div class="line"><a name="l00557"></a><span class="lineno"> 557</span>&#160; <span class="stringliteral">&quot;does not define a way to carry them inside ISO-BMFF files.&quot;</span>;</div><div class="line"><a name="l00558"></a><span class="lineno"> 558</span>&#160; }</div><div class="line"><a name="l00559"></a><span class="lineno"> 559</span>&#160;</div><div class="line"><a name="l00560"></a><span class="lineno"> 560</span>&#160; <span class="comment">// TODO(rkuroiwa): This should be the source file URI(s). Putting bogus</span></div><div class="line"><a name="l00561"></a><span class="lineno"> 561</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="l00562"></a><span class="lineno"> 562</span>&#160; <span class="comment">// cues.</span></div><div class="line"><a name="l00563"></a><span class="lineno"> 563</span>&#160; webvtt.label.source_label = <span class="stringliteral">&quot;source_label&quot;</span>;</div><div class="line"><a name="l00564"></a><span class="lineno"> 564</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="l00565"></a><span class="lineno"> 565</span>&#160; trak-&gt;media.information.sample_table.description;</div><div class="line"><a name="l00566"></a><span class="lineno"> 566</span>&#160; sample_description.type = kText;</div><div class="line"><a name="l00567"></a><span class="lineno"> 567</span>&#160; sample_description.text_entries.push_back(webvtt);</div><div class="line"><a name="l00568"></a><span class="lineno"> 568</span>&#160; <span class="keywordflow">return</span> <span class="keyword">true</span>;</div><div class="line"><a name="l00569"></a><span class="lineno"> 569</span>&#160; }</div><div class="line"><a name="l00570"></a><span class="lineno"> 570</span>&#160; NOTIMPLEMENTED() &lt;&lt; text_info-&gt;codec_string()</div><div class="line"><a name="l00571"></a><span class="lineno"> 571</span>&#160; &lt;&lt; <span class="stringliteral">&quot; handling not implemented yet.&quot;</span>;</div><div class="line"><a name="l00572"></a><span class="lineno"> 572</span>&#160; <span class="keywordflow">return</span> <span class="keyword">false</span>;</div><div class="line"><a name="l00573"></a><span class="lineno"> 573</span>&#160;}</div><div class="line"><a name="l00574"></a><span class="lineno"> 574</span>&#160;</div><div class="line"><a name="l00575"></a><span class="lineno"> 575</span>&#160;base::Optional&lt;Range&gt; MP4Muxer::GetInitRangeStartAndEnd() {</div><div class="line"><a name="l00576"></a><span class="lineno"> 576</span>&#160; <span class="keywordtype">size_t</span> range_offset = 0;</div><div class="line"><a name="l00577"></a><span class="lineno"> 577</span>&#160; <span class="keywordtype">size_t</span> range_size = 0;</div><div class="line"><a name="l00578"></a><span class="lineno"> 578</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="l00579"></a><span class="lineno"> 579</span>&#160;</div><div class="line"><a name="l00580"></a><span class="lineno"> 580</span>&#160; <span class="keywordflow">if</span> (!has_range)</div><div class="line"><a name="l00581"></a><span class="lineno"> 581</span>&#160; <span class="keywordflow">return</span> base::nullopt;</div><div class="line"><a name="l00582"></a><span class="lineno"> 582</span>&#160;</div><div class="line"><a name="l00583"></a><span class="lineno"> 583</span>&#160; <a class="code" href="../../d9/de0/structshaka_1_1media_1_1Range.html">Range</a> range;</div><div class="line"><a name="l00584"></a><span class="lineno"> 584</span>&#160; SetStartAndEndFromOffsetAndSize(range_offset, range_size, &amp;range);</div><div class="line"><a name="l00585"></a><span class="lineno"> 585</span>&#160; <span class="keywordflow">return</span> range;</div><div class="line"><a name="l00586"></a><span class="lineno"> 586</span>&#160;}</div><div class="line"><a name="l00587"></a><span class="lineno"> 587</span>&#160;</div><div class="line"><a name="l00588"></a><span class="lineno"> 588</span>&#160;base::Optional&lt;Range&gt; MP4Muxer::GetIndexRangeStartAndEnd() {</div><div class="line"><a name="l00589"></a><span class="lineno"> 589</span>&#160; <span class="keywordtype">size_t</span> range_offset = 0;</div><div class="line"><a name="l00590"></a><span class="lineno"> 590</span>&#160; <span class="keywordtype">size_t</span> range_size = 0;</div><div class="line"><a name="l00591"></a><span class="lineno"> 591</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="l00592"></a><span class="lineno"> 592</span>&#160;</div><div class="line"><a name="l00593"></a><span class="lineno"> 593</span>&#160; <span class="keywordflow">if</span> (!has_range)</div><div class="line"><a name="l00594"></a><span class="lineno"> 594</span>&#160; <span class="keywordflow">return</span> base::nullopt;</div><div class="line"><a name="l00595"></a><span class="lineno"> 595</span>&#160;</div><div class="line"><a name="l00596"></a><span class="lineno"> 596</span>&#160; <a class="code" href="../../d9/de0/structshaka_1_1media_1_1Range.html">Range</a> range;</div><div class="line"><a name="l00597"></a><span class="lineno"> 597</span>&#160; SetStartAndEndFromOffsetAndSize(range_offset, range_size, &amp;range);</div><div class="line"><a name="l00598"></a><span class="lineno"> 598</span>&#160; <span class="keywordflow">return</span> range;</div><div class="line"><a name="l00599"></a><span class="lineno"> 599</span>&#160;}</div><div class="line"><a name="l00600"></a><span class="lineno"> 600</span>&#160;</div><div class="line"><a name="l00601"></a><span class="lineno"> 601</span>&#160;<span class="keywordtype">void</span> MP4Muxer::FireOnMediaStartEvent() {</div><div class="line"><a name="l00602"></a><span class="lineno"> 602</span>&#160; <span class="keywordflow">if</span> (!muxer_listener())</div><div class="line"><a name="l00603"></a><span class="lineno"> 603</span>&#160; <span class="keywordflow">return</span>;</div><div class="line"><a name="l00604"></a><span class="lineno"> 604</span>&#160;</div><div class="line"><a name="l00605"></a><span class="lineno"> 605</span>&#160; <span class="keywordflow">if</span> (streams().size() &gt; 1) {</div><div class="line"><a name="l00606"></a><span class="lineno"> 606</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="l00607"></a><span class="lineno"> 607</span>&#160; <span class="keywordflow">return</span>;</div><div class="line"><a name="l00608"></a><span class="lineno"> 608</span>&#160; }</div><div class="line"><a name="l00609"></a><span class="lineno"> 609</span>&#160; DCHECK(!streams().empty()) &lt;&lt; <span class="stringliteral">&quot;Media started without a stream.&quot;</span>;</div><div class="line"><a name="l00610"></a><span class="lineno"> 610</span>&#160;</div><div class="line"><a name="l00611"></a><span class="lineno"> 611</span>&#160; <span class="keyword">const</span> uint32_t timescale = segmenter_-&gt;GetReferenceTimeScale();</div><div class="line"><a name="l00612"></a><span class="lineno"> 612</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="l00613"></a><span class="lineno"> 613</span>&#160; MuxerListener::kContainerMp4);</div><div class="line"><a name="l00614"></a><span class="lineno"> 614</span>&#160;}</div><div class="line"><a name="l00615"></a><span class="lineno"> 615</span>&#160;</div><div class="line"><a name="l00616"></a><span class="lineno"> 616</span>&#160;<span class="keywordtype">void</span> MP4Muxer::FireOnMediaEndEvent() {</div><div class="line"><a name="l00617"></a><span class="lineno"> 617</span>&#160; <span class="keywordflow">if</span> (!muxer_listener())</div><div class="line"><a name="l00618"></a><span class="lineno"> 618</span>&#160; <span class="keywordflow">return</span>;</div><div class="line"><a name="l00619"></a><span class="lineno"> 619</span>&#160;</div><div class="line"><a name="l00620"></a><span class="lineno"> 620</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="l00621"></a><span class="lineno"> 621</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="l00622"></a><span class="lineno"> 622</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="l00623"></a><span class="lineno"> 623</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="l00624"></a><span class="lineno"> 624</span>&#160;</div><div class="line"><a name="l00625"></a><span class="lineno"> 625</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="l00626"></a><span class="lineno"> 626</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="l00627"></a><span class="lineno"> 627</span>&#160;}</div><div class="line"><a name="l00628"></a><span class="lineno"> 628</span>&#160;</div><div class="line"><a name="l00629"></a><span class="lineno"> 629</span>&#160;uint64_t MP4Muxer::IsoTimeNow() {</div><div class="line"><a name="l00630"></a><span class="lineno"> 630</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="l00631"></a><span class="lineno"> 631</span>&#160; <span class="keyword">const</span> uint64_t kIsomTimeOffset = 2082844800l;</div><div class="line"><a name="l00632"></a><span class="lineno"> 632</span>&#160; <span class="keywordflow">return</span> kIsomTimeOffset +</div><div class="line"><a name="l00633"></a><span class="lineno"> 633</span>&#160; (clock() ? clock()-&gt;Now() : base::Time::Now()).ToDoubleT();</div><div class="line"><a name="l00634"></a><span class="lineno"> 634</span>&#160;}</div><div class="line"><a name="l00635"></a><span class="lineno"> 635</span>&#160;</div><div class="line"><a name="l00636"></a><span class="lineno"> 636</span>&#160;} <span class="comment">// namespace mp4</span></div><div class="line"><a name="l00637"></a><span class="lineno"> 637</span>&#160;} <span class="comment">// namespace media</span></div><div class="line"><a name="l00638"></a><span class="lineno"> 638</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#l00048">muxer_listener.h:48</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#l00062">stream_info.h:62</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#l00046">box_definitions.h:46</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#l00055">media_handler.h:55</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#l00050">muxer_listener.h:50</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#l00353">box_definitions.h:353</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#l00034">muxer_options.h:34</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#l00054">muxer_listener.h:54</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#l00391">box_definitions.h:391</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#l00151">mp4_muxer.cc:151</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#l00650">box_definitions.h:650</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#l00635">box_definitions.h:635</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_1MuxerOptions_html_aa616f5958ea9df2d70f3fe42ff47ff43"><div class="ttname"><a href="../../d0/d27/structshaka_1_1media_1_1MuxerOptions.html#aa616f5958ea9df2d70f3fe42ff47ff43">shaka::media::MuxerOptions::mp4_params</a></div><div class="ttdeci">Mp4OutputParams mp4_params</div><div class="ttdoc">MP4 (ISO-BMFF) specific parameters. </div><div class="ttdef"><b>Definition:</b> <a href="../../d0/d0e/muxer__options_8h_source.html#l00025">muxer_options.h:25</a></div></div>
<div class="ttc" id="structshaka_1_1media_1_1mp4_1_1EditListEntry_html"><div class="ttname"><a href="../../d4/d18/structshaka_1_1media_1_1mp4_1_1EditListEntry.html">shaka::media::mp4::EditListEntry</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00208">box_definitions.h:208</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#l00409">box_definitions.h:409</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#l00667">box_definitions.h:667</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#l00046">muxer_listener.h:46</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#l00066">video_stream_info.h:66</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_1ProtectionSystemSpecificHeader_html"><div class="ttname"><a href="../../d0/d3c/structshaka_1_1media_1_1mp4_1_1ProtectionSystemSpecificHeader.html">shaka::media::mp4::ProtectionSystemSpecificHeader</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d5/d7b/box__definitions_8h_source.html#l00058">box_definitions.h:58</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#l00519">box_definitions.h:519</a></div></div>
<div class="ttc" id="structshaka_1_1Mp4OutputParams_html_abdff0b6ab552e27e275d8d23cc2f60b1"><div class="ttname"><a href="../../d0/d43/structshaka_1_1Mp4OutputParams.html#abdff0b6ab552e27e275d8d23cc2f60b1">shaka::Mp4OutputParams::include_pssh_in_stream</a></div><div class="ttdeci">bool include_pssh_in_stream</div><div class="ttdef"><b>Definition:</b> <a href="../../d6/dbe/mp4__output__params_8h_source.html#l00018">mp4_output_params.h:18</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#l00063">video_stream_info.h:63</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#l00277">box_definitions.h:277</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#l00023">multi_segment_segmenter.h:23</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#l00551">box_definitions.h:551</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 class="ttc" id="structshaka_1_1media_1_1ProtectionSystemSpecificInfo_html"><div class="ttname"><a href="../../d0/d86/structshaka_1_1media_1_1ProtectionSystemSpecificInfo.html">shaka::media::ProtectionSystemSpecificInfo</a></div><div class="ttdef"><b>Definition:</b> <a href="../../d6/d59/protection__system__specific__info_8h_source.html#l00026">protection_system_specific_info.h:26</a></div></div>
<div class="ttc" id="classshaka_1_1media_1_1DecoderConfigDescriptor_html"><div class="ttname"><a href="../../d5/d58/classshaka_1_1media_1_1DecoderConfigDescriptor.html">shaka::media::DecoderConfigDescriptor</a></div><div class="ttdef"><b>Definition:</b> <a href="../../da/dcb/es__descriptor_8h_source.html#l00103">es_descriptor.h:103</a></div></div>
</div><!-- fragment --></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Tue Jan 21 2020 16:58:51 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>