2 # Copyright (C) 2013 Google Inc. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 This is a script that generates the content and HTML files for Media Source
32 codec config change LayoutTests.
38 MEDIA_FORMATS
= ['webm', 'mp4']
42 {'fs': '320x240', 'fr': 24, 'kfr': 8, 'c': '#ff0000', 'vbr': 128, 'abr': 0, 'asr': 0, 'ach': 0, 'afreq': 0},
43 {'fs': '320x240', 'fr': 30, 'kfr': 10, 'c': '#ff0000', 'vbr': 128, 'abr': 0, 'asr': 0, 'ach': 0, 'afreq': 0},
45 {'fs': '640x480', 'fr': 30, 'kfr': 10, 'c': '#00ff00', 'vbr': 128, 'abr': 0, 'asr': 0, 'ach': 0, 'afreq': 0},
47 {'fs': '320x240', 'fr': 30, 'kfr': 10, 'c': '#ff00ff', 'vbr': 256, 'abr': 0, 'asr': 0, 'ach': 0, 'afreq': 0},
50 # Bitrate/Codebook changes
51 {'fs': '0x0', 'fr': 0, 'kfr': 0, 'c': '#000000', 'vbr': 0, 'abr': 128, 'asr': 44100, 'ach': 1, 'afreq': 2000},
52 {'fs': '0x0', 'fr': 0, 'kfr': 0, 'c': '#000000', 'vbr': 0, 'abr': 192, 'asr': 44100, 'ach': 1, 'afreq': 4000},
56 {'fs': '320x240', 'fr': 30, 'kfr': 10, 'c': '#ff0000', 'vbr': 256, 'abr': 128, 'asr': 44100, 'ach': 1, 'afreq': 2000},
57 {'fs': '640x480', 'fr': 30, 'kfr': 10, 'c': '#00ff00', 'vbr': 256, 'abr': 128, 'asr': 44100, 'ach': 1, 'afreq': 2000},
58 # Audio bitrate change.
59 {'fs': '640x480', 'fr': 30, 'kfr': 10, 'c': '#00ff00', 'vbr': 256, 'abr': 192, 'asr': 44100, 'ach': 1, 'afreq': 4000},
60 # Video bitrate change.
61 {'fs': '640x480', 'fr': 30, 'kfr': 10, 'c': '#00ffff', 'vbr': 512, 'abr': 128, 'asr': 44100, 'ach': 1, 'afreq': 2000},
64 CONFIG_CHANGE_TESTS
= [
65 ["v-framerate", 0, 1, "Tests %s video-only frame rate changes."],
66 ["v-framesize", 1, 2, "Tests %s video-only frame size changes."],
67 ["v-bitrate", 1, 3, "Tests %s video-only bitrate changes."],
68 ["a-bitrate", 4, 5, "Tests %s audio-only bitrate changes."],
69 ["av-framesize", 6, 7, "Tests %s frame size changes in multiplexed content."],
70 ["av-audio-bitrate", 7, 8, "Tests %s audio bitrate changes in multiplexed content."],
71 ["av-video-bitrate", 7, 9, "Tests %s video bitrate changes in multiplexed content."]
75 "mp4": {"audio": "mp4a.40.2", "video": "avc1.4D4001"},
76 "webm": {"audio": "vorbis", "video": "vp8"}
79 HTML_TEMPLATE
= """<!DOCTYPE html>
82 <script src="/w3c/resources/testharness.js"></script>
83 <script src="/w3c/resources/testharnessreport.js"></script>
84 <script src="mediasource-util.js"></script>
85 <script src="mediasource-config-changes.js"></script>
90 mediaSourceConfigChangeTest("%(media_format)s", "%(idA)s", "%(idB)s", "%(description)s");
97 os
.system(" ".join(cmd_line
))
99 def generate_manifest(filename
, media_filename
, media_format
, has_audio
, has_video
):
106 codecs
.append(CODEC_INFO
[media_format
]["video"])
109 codecs
.append(CODEC_INFO
[media_format
]["audio"])
111 mimetype
= "%s/%s;codecs=\"%s\"" % (major_type
, media_format
, ",".join(codecs
))
113 manifest
= { 'url': media_filename
, 'type': mimetype
}
115 f
= open(filename
, "wb")
116 f
.write(json
.dumps(manifest
, indent
=4, separators
=(',', ': ')))
119 def generate_test_html(media_format
, config_change_tests
, encoding_ids
):
120 for test_info
in config_change_tests
:
121 filename
= "../../media-source/mediasource-config-change-%s-%s.html" % (media_format
, test_info
[0])
122 html
= HTML_TEMPLATE
% {'media_format': media_format
,
123 'idA': encoding_ids
[test_info
[1]],
124 'idB': encoding_ids
[test_info
[2]],
125 'description': test_info
[3] % (media_format
)}
126 f
= open(filename
, "wb")
134 for media_format
in MEDIA_FORMATS
:
135 run(["mkdir ", media_format
])
137 for settings
in ENCODE_SETTINGS
:
138 video_bitrate
= settings
['vbr']
139 has_video
= (video_bitrate
> 0)
141 audio_bitrate
= settings
['abr']
142 has_audio
= (audio_bitrate
> 0)
143 bitrate
= video_bitrate
+ audio_bitrate
145 frame_size
= settings
['fs']
146 frame_rate
= settings
['fr']
147 keyframe_rate
= settings
['kfr']
148 color
= settings
['c']
150 sample_rate
= settings
['asr']
151 channels
= settings
['ach']
152 frequency
= settings
['afreq']
154 cmdline
= ["ffmpeg", "-y"]
160 id_params
+= "-%sHz-%sch" % (sample_rate
, channels
)
162 channel_layout
= "FC"
163 sin_func
= "sin(%s*2*PI*t)" % frequency
166 channel_layout
+= "|BC"
167 func
+= "|" + sin_func
169 cmdline
+= ["-f", "lavfi", "-i", "aevalsrc=\"%s:s=%s:c=%s:d=%s\"" % (func
, sample_rate
, channel_layout
, DURATION
)]
173 id_params
+= "-%s-%sfps-%skfr" % (frame_size
, frame_rate
, keyframe_rate
)
175 cmdline
+= ["-f", "lavfi", "-i", "color=%s:duration=%s:size=%s:rate=%s" % (color
, DURATION
, frame_size
, frame_rate
)]
178 cmdline
+= ["-b:a", "%sk" % audio_bitrate
]
181 cmdline
+= ["-b:v", "%sk" % video_bitrate
]
182 cmdline
+= ["-keyint_min", "%s" % keyframe_rate
]
183 cmdline
+= ["-g", "%s" % keyframe_rate
]
186 textOverlayInfo
= "'drawtext=fontfile=Mono:fontsize=32:text=Time\\\\:\\\\ %{pts}"
187 textOverlayInfo
+= ",drawtext=fontfile=Mono:fontsize=32:y=32:text=Size\\\\:\\\\ %s" % (frame_size
)
188 textOverlayInfo
+= ",drawtext=fontfile=Mono:fontsize=32:y=64:text=Bitrate\\\\:\\\\ %s" % (bitrate
)
189 textOverlayInfo
+= ",drawtext=fontfile=Mono:fontsize=32:y=96:text=FrameRate\\\\:\\\\ %s" % (frame_rate
)
190 textOverlayInfo
+= ",drawtext=fontfile=Mono:fontsize=32:y=128:text=KeyFrameRate\\\\:\\\\ %s" % (keyframe_rate
)
193 textOverlayInfo
+= ",drawtext=fontfile=Mono:fontsize=32:y=160:text=SampleRate\\\\:\\\\ %s" % (sample_rate
)
194 textOverlayInfo
+= ",drawtext=fontfile=Mono:fontsize=32:y=192:text=Channels\\\\:\\\\ %s" % (channels
)
196 textOverlayInfo
+= "'"
197 cmdline
+= ["-vf", textOverlayInfo
]
199 encoding_id
= "%s-%sk%s" % (id_prefix
, bitrate
, id_params
)
201 if len(encoding_ids
) < len(ENCODE_SETTINGS
):
202 encoding_ids
.append(encoding_id
)
204 filename_base
= "%s/test-%s" % (media_format
, encoding_id
)
205 media_filename
= filename_base
+ "." + media_format
206 manifest_filename
= filename_base
+ "-manifest.json"
208 cmdline
.append(media_filename
)
211 # Remux file so it conforms to MSE bytestream requirements.
212 if media_format
== "webm":
213 tmp_filename
= media_filename
+ ".tmp"
214 run(["mse_webm_remuxer", media_filename
, tmp_filename
])
215 run(["mv", tmp_filename
, media_filename
])
216 elif media_format
== "mp4":
217 run(["MP4Box", "-dash", "250", "-rap", media_filename
])
218 run(["mv", filename_base
+ "_dash.mp4", media_filename
])
219 run(["rm", filename_base
+ "_dash.mpd"])
221 generate_manifest(manifest_filename
, media_filename
, media_format
, has_audio
, has_video
)
222 generate_test_html(media_format
, CONFIG_CHANGE_TESTS
, encoding_ids
)
224 if '__main__' == __name__
: