Merge b2g-inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 27 Jan 2014 15:05:03 -0500
changeset 181398 ab2609380aff727a2dc86650bea74246d1cabe34
parent 181353 431612fab17e3d05cc4b2f976ac3f6f517051f70 (current diff)
parent 181397 5ed4e9c491545b1bdf04b708adc02c8a5deb8027 (diff)
child 181399 07021aa58289a55967b56ad1ffd87d72031c0803
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge b2g-inbound to m-c.
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -6,29 +6,30 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="1342fd7b4b000ac3e76a5dfe111a0de9d710b4c8"/>
+  <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="1b26ad444462ccbd97f6319565b4735f7bd779e5"/>
   <project name="device/common" path="device/common" revision="4e1a38704dcfadef60ed2da3cfeba02a56b069d2"/>
   <project name="device/sample" path="device/sample" revision="b045905b46c8b4ee630d0c2aee7db63eaec722d9"/>
   <project name="platform/abi/cpp" path="abi/cpp" revision="fa873799be5cf200f1d1d32a63953949c9dcdda8"/>
   <project name="platform/bionic" path="bionic" revision="0d910c2a305f6b223b7b879a4532df1d0ec73030"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="b279a60d33785df6d08065a2b082eeecb64af759"/>
   <project name="platform/external/aac" path="external/aac" revision="67e322018c4ae56213dec4083f1e37cf7e087a05"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="72573746f78ed1bce49e93737f33d0248ee6da97"/>
   <project name="platform/external/bison" path="external/bison" revision="28effbb752100922ad6c80a98c8bb10e133a4d2a"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "c5f8db7e1e71a9bfe0d29665d2b4cf3ae773094e", 
+    "revision": "1150c11d1e6f0f78df3552dfca8c53d5ed5c173d", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -5,17 +5,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -6,29 +6,30 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="1342fd7b4b000ac3e76a5dfe111a0de9d710b4c8"/>
+  <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="1b26ad444462ccbd97f6319565b4735f7bd779e5"/>
   <project name="device/common" path="device/common" revision="4e1a38704dcfadef60ed2da3cfeba02a56b069d2"/>
   <project name="device/sample" path="device/sample" revision="b045905b46c8b4ee630d0c2aee7db63eaec722d9"/>
   <project name="platform/abi/cpp" path="abi/cpp" revision="fa873799be5cf200f1d1d32a63953949c9dcdda8"/>
   <project name="platform/bionic" path="bionic" revision="0d910c2a305f6b223b7b879a4532df1d0ec73030"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="b279a60d33785df6d08065a2b082eeecb64af759"/>
   <project name="platform/external/aac" path="external/aac" revision="67e322018c4ae56213dec4083f1e37cf7e087a05"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="72573746f78ed1bce49e93737f33d0248ee6da97"/>
   <project name="platform/external/bison" path="external/bison" revision="28effbb752100922ad6c80a98c8bb10e133a4d2a"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="75ea7d07cdb590722634016410e12819faf82e5a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6586d2b8b43c6997be5cf5895bbdf3dd20490725"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -59,11 +59,12 @@ if test "$OS_TARGET" = "WINNT" -o "$OS_T
   MOZ_FOLD_LIBS=1
 fi
 MOZ_WEBGL_CONFORMANT=1
 # Enable navigator.mozPay
 MOZ_PAY=1
 # Enable activities. These are used for FxOS developers currently.
 MOZ_ACTIVITIES=1
 MOZ_JSDOWNLOADS=1
+MOZ_WEBM_ENCODER=1
 # Enable exact rooting on desktop.
 JSGC_USE_EXACT_ROOTING=1
 
--- a/config/external/moz.build
+++ b/config/external/moz.build
@@ -22,16 +22,19 @@ if CONFIG['MOZ_TREMOR']:
     external_dirs += ['media/libtremor']
 
 if CONFIG['MOZ_OPUS']:
     external_dirs += ['media/libopus']
 
 if CONFIG['MOZ_WEBM']:
     external_dirs += ['media/libnestegg']
 
+if CONFIG['MOZ_WEBM_ENCODER']:
+    external_dirs += ['media/libmkv']
+
 if CONFIG['MOZ_VPX'] and not CONFIG['MOZ_NATIVE_LIBVPX']:
     external_dirs += ['media/libvpx']
 
 if CONFIG['MOZ_OGG']:
     external_dirs += ['media/libogg', 'media/libtheora']
 
 if not CONFIG['MOZ_NATIVE_PNG']:
     external_dirs += ['media/libpng']
--- a/configure.in
+++ b/configure.in
@@ -5541,16 +5541,21 @@ fi
 if test -n "$MOZ_TREMOR"; then
     AC_DEFINE(MOZ_TREMOR)
 fi
 
 if test -n "$MOZ_OPUS"; then
     AC_DEFINE(MOZ_OPUS)
 fi
 
+if test -n "$MOZ_WEBM_ENCODER"; then
+    AC_DEFINE(MOZ_WEBM_ENCODER)
+fi
+AC_SUBST(MOZ_WEBM_ENCODER)
+
 dnl ==================================
 dnl = Check alsa availability on Linux
 dnl ==================================
 
 dnl If using Linux, ensure that the alsa library is available
 if test "$OS_TARGET" = "Linux"; then
     MOZ_ALSA=1
 fi
--- a/content/media/MediaRecorder.cpp
+++ b/content/media/MediaRecorder.cpp
@@ -225,28 +225,30 @@ public:
   void Stop()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     CleanupStreams();
     nsContentUtils::UnregisterShutdownObserver(this);
   }
 
-  void Pause()
+  nsresult Pause()
   {
-    MOZ_ASSERT(NS_IsMainThread() && mTrackUnionStream);
+    NS_ENSURE_TRUE(NS_IsMainThread() && mTrackUnionStream, NS_ERROR_FAILURE);
+    mTrackUnionStream->ChangeExplicitBlockerCount(-1);
 
-    mTrackUnionStream->ChangeExplicitBlockerCount(-1);
+    return NS_OK;
   }
 
-  void Resume()
+  nsresult Resume()
   {
-    MOZ_ASSERT(NS_IsMainThread() && mTrackUnionStream);
+    NS_ENSURE_TRUE(NS_IsMainThread() && mTrackUnionStream, NS_ERROR_FAILURE);
+    mTrackUnionStream->ChangeExplicitBlockerCount(1);
 
-    mTrackUnionStream->ChangeExplicitBlockerCount(1);
+    return NS_OK;
   }
 
   already_AddRefed<nsIDOMBlob> GetEncodedData()
   {
     nsString mimeType;
     mRecorder->GetMimeType(mimeType);
 
     return mEncodedBufferCache->ExtractBlob(mimeType);
@@ -494,36 +496,42 @@ MediaRecorder::Stop(ErrorResult& aResult
 void
 MediaRecorder::Pause(ErrorResult& aResult)
 {
   if (mState != RecordingState::Recording) {
     aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
-  mState = RecordingState::Paused;
-
   MOZ_ASSERT(mSession != nullptr);
   if (mSession) {
-    mSession->Pause();
+    nsresult rv = mSession->Pause();
+    if (NS_FAILED(rv)) {
+      NotifyError(rv);
+      return;
+    }
     mState = RecordingState::Paused;
   }
 }
 
 void
 MediaRecorder::Resume(ErrorResult& aResult)
 {
   if (mState != RecordingState::Paused) {
     aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   MOZ_ASSERT(mSession != nullptr);
   if (mSession) {
-    mSession->Resume();
+    nsresult rv = mSession->Resume();
+    if (NS_FAILED(rv)) {
+      NotifyError(rv);
+      return;
+    }
     mState = RecordingState::Recording;
   }
 }
 
 void
 MediaRecorder::RequestData(ErrorResult& aResult)
 {
   if (mState != RecordingState::Recording) {
--- a/content/media/encoder/MediaEncoder.cpp
+++ b/content/media/encoder/MediaEncoder.cpp
@@ -9,16 +9,21 @@
 #include "prlog.h"
 #include "mozilla/Preferences.h"
 
 #ifdef MOZ_OGG
 #include "OggWriter.h"
 #endif
 #ifdef MOZ_OPUS
 #include "OpusTrackEncoder.h"
+
+#endif
+
+#ifdef MOZ_VORBIS
+#include "VorbisTrackEncoder.h"
 #endif
 #ifdef MOZ_WEBM_ENCODER
 #include "VorbisTrackEncoder.h"
 #include "VP8TrackEncoder.h"
 #include "WebMWriter.h"
 #endif
 #ifdef MOZ_OMX_ENCODER
 #include "OmxTrackEncoder.h"
--- a/content/media/encoder/TrackEncoder.cpp
+++ b/content/media/encoder/TrackEncoder.cpp
@@ -123,16 +123,30 @@ AudioTrackEncoder::InterleaveTrackData(A
                          aChunk.mVolume, aOutputChannels, aOutput);
   } else {
     InterleaveAndConvertBuffer(aChunk.mChannelData.Elements(),
                                aChunk.mBufferFormat, aDuration, aChunk.mVolume,
                                aOutputChannels, aOutput);
   }
 }
 
+/*static*/
+void
+AudioTrackEncoder::DeInterleaveTrackData(AudioDataValue* aInput,
+                                         int32_t aDuration,
+                                         int32_t aChannels,
+                                         AudioDataValue* aOutput)
+{
+  for (int32_t i = 0; i < aChannels; ++i) {
+    for(int32_t j = 0; j < aDuration; ++j) {
+      aOutput[i * aDuration + j] = aInput[i + j * aChannels];
+    }
+  }
+}
+
 void
 VideoTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
                                             TrackID aID,
                                             TrackRate aTrackRate,
                                             TrackTicks aTrackOffset,
                                             uint32_t aTrackEvents,
                                             const MediaSegment& aQueuedMedia)
 {
--- a/content/media/encoder/TrackEncoder.h
+++ b/content/media/encoder/TrackEncoder.h
@@ -153,16 +153,23 @@ public:
    * to up-mix or down-mix the channel data if the channels number of this chunk
    * is different from aOutputChannels. The channel data from aChunk might be
    * modified by up-mixing.
    */
   static void InterleaveTrackData(AudioChunk& aChunk, int32_t aDuration,
                                   uint32_t aOutputChannels,
                                   AudioDataValue* aOutput);
 
+  /**
+   * De-interleaves the aInput data and stores the result into aOutput.
+   * No up-mix or down-mix operations inside.
+   */
+  static void DeInterleaveTrackData(AudioDataValue* aInput, int32_t aDuration,
+                                    int32_t aChannels, AudioDataValue* aOutput);
+
 protected:
   /**
    * Number of samples per channel in a pcm buffer. This is also the value of
    * frame size required by audio encoder, and mReentrantMonitor will be
    * notified when at least this much data has been added to mRawSegment.
    */
   virtual int GetPacketDuration() { return 0; }
 
--- a/content/media/encoder/TrackMetadataBase.h
+++ b/content/media/encoder/TrackMetadataBase.h
@@ -13,16 +13,17 @@ namespace mozilla {
 // A class represent meta data for various codec format. Only support one track information.
 class TrackMetadataBase
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackMetadataBase)
   enum MetadataKind {
     METADATA_OPUS,    // Represent the Opus metadata
     METADATA_VP8,
+    METADATA_VORBIS,
     METADATA_AVC,
     METADATA_AAC,
     METADATA_UNKNOWN  // Metadata Kind not set
   };
   virtual ~TrackMetadataBase() {}
   // Return the specific metadata kind
   virtual MetadataKind GetKind() const = 0;
 };
new file mode 100644
--- /dev/null
+++ b/content/media/encoder/VP8TrackEncoder.cpp
@@ -0,0 +1,472 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VP8TrackEncoder.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+#include "VideoUtils.h"
+#include "prsystem.h"
+#include "WebMWriter.h"
+
+namespace mozilla {
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* gVP8TrackEncoderLog;
+#define VP8LOG(msg, ...) PR_LOG(gVP8TrackEncoderLog, PR_LOG_DEBUG, \
+                                  (msg, ##__VA_ARGS__))
+// Debug logging macro with object pointer and class name.
+#else
+#define VP8LOG(msg, ...)
+#endif
+
+#define DEFAULT_BITRATE 2500 // in kbit/s
+#define DEFAULT_ENCODE_FRAMERATE 30
+
+VP8TrackEncoder::VP8TrackEncoder()
+  : VideoTrackEncoder()
+  , mEncodedFrameDuration(0)
+  , mEncodedTimestamp(0)
+  , mRemainingTicks(0)
+  , mVPXContext(new vpx_codec_ctx_t())
+  , mVPXImageWrapper(new vpx_image_t())
+{
+  MOZ_COUNT_CTOR(VP8TrackEncoder);
+#ifdef PR_LOGGING
+  if (!gVP8TrackEncoderLog) {
+    gVP8TrackEncoderLog = PR_NewLogModule("VP8TrackEncoder");
+  }
+#endif
+}
+
+VP8TrackEncoder::~VP8TrackEncoder()
+{
+  if (mInitialized) {
+    vpx_codec_destroy(mVPXContext);
+  }
+
+  if (mVPXImageWrapper) {
+    vpx_img_free(mVPXImageWrapper);
+  }
+  MOZ_COUNT_DTOR(VP8TrackEncoder);
+}
+
+nsresult
+VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, TrackRate aTrackRate)
+{
+  if (aWidth < 1 || aHeight < 1 || aTrackRate <= 0) {
+    return NS_ERROR_FAILURE;
+  }
+
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+  mTrackRate = aTrackRate;
+  mEncodedFrameRate = DEFAULT_ENCODE_FRAMERATE;
+  mEncodedFrameDuration = mTrackRate / mEncodedFrameRate;
+  mFrameWidth = aWidth;
+  mFrameHeight = aHeight;
+
+  // Encoder configuration structure.
+  vpx_codec_enc_cfg_t config;
+  memset(&config, 0, sizeof(vpx_codec_enc_cfg_t));
+  if (vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config, 0)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // Creating a wrapper to the image - setting image data to NULL. Actual
+  // pointer will be set in encode. Setting align to 1, as it is meaningless
+  // (actual memory is not allocated).
+  vpx_img_wrap(mVPXImageWrapper, IMG_FMT_I420,
+               mFrameWidth, mFrameHeight, 1, nullptr);
+
+  config.g_w = mFrameWidth;
+  config.g_h = mFrameHeight;
+  // TODO: Maybe we should have various aFrameRate bitrate pair for each devices?
+  // or for different platform
+  config.rc_target_bitrate = DEFAULT_BITRATE; // in kbit/s
+
+  // Setting the time base of the codec
+  config.g_timebase.num = 1;
+  config.g_timebase.den = mTrackRate;
+
+  config.g_error_resilient = 0;
+
+  config.g_lag_in_frames = 0; // 0- no frame lagging
+
+  int32_t number_of_cores = PR_GetNumberOfProcessors();
+  if (mFrameWidth * mFrameHeight > 1280 * 960 && number_of_cores >= 6) {
+    config.g_threads = 3; // 3 threads for 1080p.
+  } else if (mFrameWidth * mFrameHeight > 640 * 480 && number_of_cores >= 3) {
+    config.g_threads = 2; // 2 threads for qHD/HD.
+  } else {
+    config.g_threads = 1; // 1 thread for VGA or less
+  }
+
+  // rate control settings
+  config.rc_dropframe_thresh = 0;
+  config.rc_end_usage = VPX_CBR;
+  config.g_pass = VPX_RC_ONE_PASS;
+  config.rc_resize_allowed = 1;
+  config.rc_undershoot_pct = 100;
+  config.rc_overshoot_pct = 15;
+  config.rc_buf_initial_sz = 500;
+  config.rc_buf_optimal_sz = 600;
+  config.rc_buf_sz = 1000;
+
+  config.kf_mode = VPX_KF_AUTO;
+  // Ensure that we can output one I-frame per second.
+  config.kf_max_dist = mEncodedFrameRate;
+
+  vpx_codec_flags_t flags = 0;
+  flags |= VPX_CODEC_USE_OUTPUT_PARTITION;
+  if (vpx_codec_enc_init(mVPXContext, vpx_codec_vp8_cx(), &config, flags)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  vpx_codec_control(mVPXContext, VP8E_SET_STATIC_THRESHOLD, 1);
+  vpx_codec_control(mVPXContext, VP8E_SET_CPUUSED, -6);
+  vpx_codec_control(mVPXContext, VP8E_SET_TOKEN_PARTITIONS,
+                    VP8_ONE_TOKENPARTITION);
+
+  mInitialized = true;
+  mon.NotifyAll();
+
+  return NS_OK;
+}
+
+already_AddRefed<TrackMetadataBase>
+VP8TrackEncoder::GetMetadata()
+{
+  {
+    // Wait if mEncoder is not initialized.
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    while (!mCanceled && !mInitialized) {
+      mon.Wait();
+    }
+  }
+
+  if (mCanceled || mEncodingComplete) {
+    return nullptr;
+  }
+
+  nsRefPtr<VP8Metadata> meta = new VP8Metadata();
+  meta->mWidth = mFrameWidth;
+  meta->mHeight = mFrameHeight;
+  meta->mEncodedFrameRate = mEncodedFrameRate;
+
+  return meta.forget();
+}
+
+nsresult
+VP8TrackEncoder::GetEncodedPartitions(EncodedFrameContainer& aData)
+{
+  vpx_codec_iter_t iter = nullptr;
+  EncodedFrame::FrameType frameType = EncodedFrame::P_FRAME;
+  nsTArray<uint8_t> frameData;
+  const vpx_codec_cx_pkt_t *pkt = nullptr;
+  while ((pkt = vpx_codec_get_cx_data(mVPXContext, &iter)) != nullptr) {
+    switch (pkt->kind) {
+      case VPX_CODEC_CX_FRAME_PKT: {
+        // Copy the encoded data from libvpx to frameData
+        frameData.AppendElements((uint8_t*)pkt->data.frame.buf,
+                                 pkt->data.frame.sz);
+        break;
+      }
+      default: {
+        break;
+      }
+    }
+    // End of frame
+    if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) {
+      if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
+        frameType = EncodedFrame::I_FRAME;
+      }
+      break;
+    }
+  }
+
+  if (!frameData.IsEmpty() &&
+      (pkt->data.frame.pts == mEncodedTimestamp)) {
+    // Copy the encoded data to aData.
+    EncodedFrame* videoData = new EncodedFrame();
+    videoData->SetFrameType(frameType);
+    // Convert the timestamp and duration to Usecs.
+    CheckedInt64 timestamp = FramesToUsecs(mEncodedTimestamp, mTrackRate);
+    if (timestamp.isValid()) {
+      videoData->SetTimeStamp(
+        (uint64_t)FramesToUsecs(mEncodedTimestamp, mTrackRate).value());
+    }
+    CheckedInt64 duration = FramesToUsecs(pkt->data.frame.duration, mTrackRate);
+    if (duration.isValid()) {
+      videoData->SetDuration(
+        (uint64_t)FramesToUsecs(pkt->data.frame.duration, mTrackRate).value());
+    }
+    videoData->SetFrameData(&frameData);
+    VP8LOG("GetEncodedPartitions TimeStamp %lld Duration %lld\n",
+           videoData->GetTimeStamp(), videoData->GetDuration());
+    VP8LOG("frameType %d\n", videoData->GetFrameType());
+    aData.AppendEncodedFrame(videoData);
+  }
+
+  return NS_OK;
+}
+
+void VP8TrackEncoder::PrepareMutedFrame()
+{
+  if (mMuteFrame.IsEmpty()) {
+    CreateMutedFrame(&mMuteFrame);
+  }
+
+  uint32_t yPlanSize = mFrameWidth * mFrameHeight;
+  uint32_t halfWidth = (mFrameWidth + 1) / 2;
+  uint32_t halfHeight = (mFrameHeight + 1) / 2;
+  uint32_t uvPlanSize = halfWidth * halfHeight;
+
+  MOZ_ASSERT(mMuteFrame.Length() >= (yPlanSize + uvPlanSize));
+  uint8_t *y = mMuteFrame.Elements();
+  uint8_t *cb = mMuteFrame.Elements() + yPlanSize;
+  uint8_t *cr = mMuteFrame.Elements() + yPlanSize + uvPlanSize;
+
+  mVPXImageWrapper->planes[PLANE_Y] = y;
+  mVPXImageWrapper->planes[PLANE_U] = cb;
+  mVPXImageWrapper->planes[PLANE_V] = cr;
+  mVPXImageWrapper->stride[VPX_PLANE_Y] = mFrameWidth;
+  mVPXImageWrapper->stride[VPX_PLANE_U] = halfWidth;
+  mVPXImageWrapper->stride[VPX_PLANE_V] = halfWidth;
+}
+
+nsresult VP8TrackEncoder::PrepareRawFrame(VideoChunk &aChunk)
+{
+  if (aChunk.mFrame.GetForceBlack()) {
+    PrepareMutedFrame();
+  } else {
+    layers::Image* img = aChunk.mFrame.GetImage();
+    if (NS_WARN_IF(!img)) {
+      return NS_ERROR_NULL_POINTER;
+    }
+    ImageFormat format = img->GetFormat();
+    if (format != PLANAR_YCBCR) {
+      VP8LOG("Unsupported video format\n");
+      return NS_ERROR_FAILURE;
+    }
+
+    // Cast away constness b/c some of the accessors are non-const
+    layers::PlanarYCbCrImage* yuv =
+    const_cast<layers::PlanarYCbCrImage *>(static_cast<const layers::PlanarYCbCrImage *>(img));
+    // Big-time assumption here that this is all contiguous data coming
+    // from getUserMedia or other sources.
+    MOZ_ASSERT(yuv);
+    const layers::PlanarYCbCrImage::Data *data = yuv->GetData();
+
+    mVPXImageWrapper->planes[PLANE_Y] = data->mYChannel;
+    mVPXImageWrapper->planes[PLANE_U] = data->mCbChannel;
+    mVPXImageWrapper->planes[PLANE_V] = data->mCrChannel;
+    mVPXImageWrapper->stride[VPX_PLANE_Y] = data->mYStride;
+    mVPXImageWrapper->stride[VPX_PLANE_U] = data->mCbCrStride;
+    mVPXImageWrapper->stride[VPX_PLANE_V] = data->mCbCrStride;
+  }
+  return NS_OK;
+}
+
+// These two define value used in GetNextEncodeOperation to determine the
+// EncodeOperation for next target frame.
+#define I_FRAME_RATIO (0.5)
+#define SKIP_FRAME_RATIO (0.75)
+
+/**
+ * Compares the elapsed time from the beginning of GetEncodedTrack and
+ * the processed frame duration in mSourceSegment
+ * in order to set the nextEncodeOperation for next target frame.
+ */
+VP8TrackEncoder::EncodeOperation
+VP8TrackEncoder::GetNextEncodeOperation(TimeDuration aTimeElapsed,
+                                        TrackTicks aProcessedDuration)
+{
+  int64_t durationInUsec =
+    FramesToUsecs(aProcessedDuration + mEncodedFrameDuration,
+                  mTrackRate).value();
+  if (aTimeElapsed.ToMicroseconds() > (durationInUsec * SKIP_FRAME_RATIO)) {
+    // The encoder is too slow.
+    // We should skip next frame to consume the mSourceSegment.
+    return SKIP_FRAME;
+  } else if (aTimeElapsed.ToMicroseconds() > (durationInUsec * I_FRAME_RATIO)) {
+    // The encoder is a little slow.
+    // We force the encoder to encode an I-frame to accelerate.
+    return ENCODE_I_FRAME;
+  } else {
+    return ENCODE_NORMAL_FRAME;
+  }
+}
+
+TrackTicks
+VP8TrackEncoder::CalculateRemainingTicks(TrackTicks aDurationCopied,
+                                         TrackTicks aEncodedDuration)
+{
+  return mRemainingTicks + aEncodedDuration - aDurationCopied;
+}
+
+// Try to extend the encodedDuration as long as possible if the target frame
+// has a long duration.
+TrackTicks
+VP8TrackEncoder::CalculateEncodedDuration(TrackTicks aDurationCopied)
+{
+  TrackTicks temp64 = aDurationCopied;
+  TrackTicks encodedDuration = mEncodedFrameDuration;
+  temp64 -= mRemainingTicks;
+  while (temp64 > mEncodedFrameDuration) {
+    temp64 -= mEncodedFrameDuration;
+    encodedDuration += mEncodedFrameDuration;
+  }
+  return encodedDuration;
+}
+
+/**
+ * Encoding flow in GetEncodedTrack():
+ * 1: Check the mInitialized state and the packet duration.
+ * 2: Move the data from mRawSegment to mSourceSegment.
+ * 3: Encode the video chunks in mSourceSegment in a for-loop.
+ * 3.1: Pick the video chunk by mRemainingTicks.
+ * 3.2: Calculate the encoding duration for the parameter of vpx_codec_encode().
+ *      The encoding duration is a multiple of mEncodedFrameDuration.
+ * 3.3: Setup the video chunk to mVPXImageWrapper by PrepareRawFrame().
+ * 3.4: Send frame into vp8 encoder by vpx_codec_encode().
+ * 3.5: Get the output frame from encoder by calling GetEncodedPartitions().
+ * 3.6: Calculate the mRemainingTicks for next target frame.
+ * 3.7: Set the nextEncodeOperation for the next target frame.
+ *      There is a heuristic: If the frame duration we have processed in
+ *      mSourceSegment is 100ms, means that we can't spend more than 100ms to
+ *      encode it.
+ * 4. Remove the encoded chunks in mSourceSegment after for-loop.
+ *
+ * Ex1: Input frame rate is 100 => input frame duration is 10ms for each.
+ *     mEncodedFrameRate is 30 => output frame duration is 33ms.
+ *     In this case, the frame duration in mSourceSegment will be:
+ *     1st : 0~10ms
+ *     2nd : 10~20ms
+ *     3rd : 20~30ms
+ *     4th : 30~40ms
+ *     ...
+ *     The VP8 encoder will take the 1st and 4th frames to encode. At beginning
+ *     mRemainingTicks is 0 for 1st frame, then the mRemainingTicks is set
+ *     to 23 to pick the 4th frame. (mEncodedFrameDuration - 1st frame duration)
+ *
+ * Ex2: Input frame rate is 25 => frame duration is 40ms for each.
+ *     mEncodedFrameRate is 30 => output frame duration is 33ms.
+ *     In this case, the frame duration in mSourceSegment will be:
+ *     1st : 0~40ms
+ *     2nd : 40~80ms
+ *     3rd : 80~120ms
+ *     4th : 120~160ms
+ *     ...
+ *     Because the input frame duration is 40ms larger than 33ms, so the first
+ *     encoded frame duration will be 66ms by calling CalculateEncodedDuration.
+ *     And the mRemainingTicks will be set to 26
+ *     (CalculateRemainingTicks 0+66-40) in order to pick the next frame(2nd)
+ *     in mSourceSegment.
+ */
+nsresult
+VP8TrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
+{
+  {
+    // Move all the samples from mRawSegment to mSourceSegment. We only hold
+    // the monitor in this block.
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    // Wait if mEncoder is not initialized, or when not enough raw data, but is
+    // not the end of stream nor is being canceled.
+    while (!mCanceled && (!mInitialized ||
+           (mRawSegment.GetDuration() + mSourceSegment.GetDuration() <
+            mEncodedFrameDuration && !mEndOfStream))) {
+      mon.Wait();
+    }
+    if (mCanceled || mEncodingComplete) {
+      return NS_ERROR_FAILURE;
+    }
+    mSourceSegment.AppendFrom(&mRawSegment);
+  }
+
+  VideoSegment::ChunkIterator iter(mSourceSegment);
+  TrackTicks durationCopied = 0;
+  TrackTicks totalProcessedDuration = 0;
+  TimeStamp timebase = TimeStamp::Now();
+  EncodeOperation nextEncodeOperation = ENCODE_NORMAL_FRAME;
+
+  for (; !iter.IsEnded(); iter.Next()) {
+    VideoChunk &chunk = *iter;
+    // Accumulate chunk's duration to durationCopied until it reaches
+    // mRemainingTicks.
+    durationCopied += chunk.GetDuration();
+    MOZ_ASSERT(mRemainingTicks <= mEncodedFrameDuration);
+    VP8LOG("durationCopied %lld mRemainingTicks %lld\n",
+           durationCopied, mRemainingTicks);
+    if (durationCopied >= mRemainingTicks) {
+      VP8LOG("nextEncodeOperation is %d\n",nextEncodeOperation);
+      // Calculate encodedDuration for this target frame.
+      TrackTicks encodedDuration = CalculateEncodedDuration(durationCopied);
+
+      // Encode frame.
+      if (nextEncodeOperation != SKIP_FRAME) {
+        nsresult rv = PrepareRawFrame(chunk);
+        NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
+
+        // Encode the data with VP8 encoder
+        int flags = (nextEncodeOperation == ENCODE_NORMAL_FRAME) ?
+                    0 : VPX_EFLAG_FORCE_KF;
+        if (vpx_codec_encode(mVPXContext, mVPXImageWrapper, mEncodedTimestamp,
+                             (unsigned long)encodedDuration, flags,
+                             VPX_DL_REALTIME)) {
+          return NS_ERROR_FAILURE;
+        }
+        // Get the encoded data from VP8 encoder.
+        GetEncodedPartitions(aData);
+      } else {
+        // SKIP_FRAME
+        // Extend the duration of the last encoded data in aData
+        // because this frame will be skip.
+        nsRefPtr<EncodedFrame> last = nullptr;
+        last = aData.GetEncodedFrames().LastElement();
+        if (last) {
+          last->SetDuration(last->GetDuration() + encodedDuration);
+        }
+      }
+      // Move forward the mEncodedTimestamp.
+      mEncodedTimestamp += encodedDuration;
+      totalProcessedDuration += durationCopied;
+      // Calculate mRemainingTicks for next target frame.
+      mRemainingTicks = CalculateRemainingTicks(durationCopied,
+                                                encodedDuration);
+
+      // Check the remain data is enough for next target frame.
+      if (mSourceSegment.GetDuration() - totalProcessedDuration
+          >= mEncodedFrameDuration) {
+        TimeDuration elapsedTime = TimeStamp::Now() - timebase;
+        nextEncodeOperation = GetNextEncodeOperation(elapsedTime,
+                                                     totalProcessedDuration);
+        // Reset durationCopied for next iteration.
+        durationCopied = 0;
+      } else {
+        // Process done, there is no enough data left for next iteration,
+        // break the for-loop.
+        break;
+      }
+    }
+  }
+  // Remove the chunks we have processed.
+  mSourceSegment.RemoveLeading(totalProcessedDuration);
+  VP8LOG("RemoveLeading %lld\n",totalProcessedDuration);
+
+  // End of stream, pull the rest frames in encoder.
+  if (mEndOfStream) {
+    VP8LOG("mEndOfStream is true\n");
+    mEncodingComplete = true;
+    if (vpx_codec_encode(mVPXContext, nullptr, mEncodedTimestamp,
+                         mEncodedFrameDuration, 0, VPX_DL_REALTIME)) {
+      return NS_ERROR_FAILURE;
+    }
+    GetEncodedPartitions(aData);
+  }
+
+  return NS_OK ;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/encoder/VP8TrackEncoder.h
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef VP8TrackEncoder_h_
+#define VP8TrackEncoder_h_
+
+#include "TrackEncoder.h"
+#include "vpx/vpx_codec.h"
+
+namespace mozilla {
+
+typedef struct vpx_codec_ctx vpx_codec_ctx_t;
+typedef struct vpx_codec_enc_cfg vpx_codec_enc_cfg_t;
+typedef struct vpx_image vpx_image_t;
+
+/**
+ * VP8TrackEncoder implements VideoTrackEncoder by using libvpx library.
+ * We implement a realtime and fixed FPS encoder. In order to achieve that,
+ * there is a pick target frame and drop frame encoding policy implemented in
+ * GetEncodedTrack.
+ */
+class VP8TrackEncoder : public VideoTrackEncoder
+{
+  enum EncodeOperation {
+    ENCODE_NORMAL_FRAME, // VP8 track encoder works normally.
+    ENCODE_I_FRAME, // The next frame will be encoded as I-Frame.
+    SKIP_FRAME, // Skip the next frame.
+  };
+public:
+  VP8TrackEncoder();
+  virtual ~VP8TrackEncoder();
+
+  already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_FINAL MOZ_OVERRIDE;
+
+  nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_FINAL MOZ_OVERRIDE;
+
+protected:
+  nsresult Init(int32_t aWidth, int32_t aHeight,
+                TrackRate aTrackRate) MOZ_FINAL MOZ_OVERRIDE;
+
+private:
+  // Calculate the target frame's encoded duration.
+  TrackTicks CalculateEncodedDuration(TrackTicks aDurationCopied);
+
+  // Calculate the mRemainingTicks for next target frame.
+  TrackTicks CalculateRemainingTicks(TrackTicks aDurationCopied,
+                                     TrackTicks aEncodedDuration);
+
+  // Get the EncodeOperation for next target frame.
+  EncodeOperation GetNextEncodeOperation(TimeDuration aTimeElapsed,
+                                         TrackTicks aProcessedDuration);
+
+  // Get the encoded data from encoder to aData.
+  nsresult GetEncodedPartitions(EncodedFrameContainer& aData);
+
+  // Prepare the input data to the mVPXImageWrapper for encoding.
+  nsresult PrepareRawFrame(VideoChunk &aChunk);
+
+  // Prepare the muted frame data to the mVPXImageWrapper for encoding.
+  void PrepareMutedFrame();
+
+  // Output frame rate.
+  uint32_t mEncodedFrameRate;
+  // Duration for the output frame, reciprocal to mEncodedFrameRate.
+  TrackTicks mEncodedFrameDuration;
+  // Encoded timestamp.
+  TrackTicks mEncodedTimestamp;
+  // Duration to the next encode frame.
+  TrackTicks mRemainingTicks;
+
+  // Muted frame, we only create it once.
+  nsTArray<uint8_t> mMuteFrame;
+
+  /**
+   * A local segment queue which takes the raw data out from mRawSegment in the
+   * call of GetEncodedTrack(). Since we implement the fixed FPS encoding
+   * policy, it needs to be global in order to store the leftover segments
+   * taken from mRawSegment.
+   */
+  VideoSegment mSourceSegment;
+
+  // VP8 relative members.
+  // Codec context structure.
+  nsAutoPtr<vpx_codec_ctx_t> mVPXContext;
+  // Image Descriptor.
+  nsAutoPtr<vpx_image_t> mVPXImageWrapper;
+};
+
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/media/encoder/VorbisTrackEncoder.cpp
@@ -0,0 +1,238 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "VorbisTrackEncoder.h"
+#include <ogg/ogg.h>
+#include <vorbis/vorbisenc.h>
+#include "WebMWriter.h"
+
+// One actually used: Encoding using a VBR quality mode. The usable range is -.1
+// (lowest quality, smallest file) to 1. (highest quality, largest file).
+// Example quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR
+// ret = vorbis_encode_init_vbr(&vi,2,44100,.4);
+static const float BASE_QUALITY = 0.4f;
+
+namespace mozilla {
+
+#undef LOG
+#ifdef PR_LOGGING
+PRLogModuleInfo* gVorbisTrackEncoderLog;
+#define VORBISLOG(msg, ...) PR_LOG(gVorbisTrackEncoderLog, PR_LOG_DEBUG, \
+                             (msg, ##__VA_ARGS__))
+#else
+#define VORBISLOG(msg, ...)
+#endif
+
+VorbisTrackEncoder::VorbisTrackEncoder()
+  : AudioTrackEncoder()
+{
+  MOZ_COUNT_CTOR(VorbisTrackEncoder);
+#ifdef PR_LOGGING
+  if (!gVorbisTrackEncoderLog) {
+    gVorbisTrackEncoderLog = PR_NewLogModule("VorbisTrackEncoder");
+  }
+#endif
+}
+
+VorbisTrackEncoder::~VorbisTrackEncoder()
+{
+  MOZ_COUNT_DTOR(VorbisTrackEncoder);
+  if (mInitialized) {
+    vorbis_block_clear(&mVorbisBlock);
+    vorbis_dsp_clear(&mVorbisDsp);
+    vorbis_info_clear(&mVorbisInfo);
+  }
+}
+
+nsresult
+VorbisTrackEncoder::Init(int aChannels, int aSamplingRate)
+{
+  if (aChannels <= 0 || aChannels > 8) {
+    VORBISLOG("aChannels <= 0 || aChannels > 8");
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  // This monitor is used to wake up other methods that are waiting for encoder
+  // to be completely initialized.
+  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+  mChannels = aChannels;
+  mSamplingRate = aSamplingRate;
+
+  int ret = 0;
+  vorbis_info_init(&mVorbisInfo);
+
+  ret = vorbis_encode_init_vbr(&mVorbisInfo, mChannels, mSamplingRate,
+                               BASE_QUALITY);
+
+  mInitialized = (ret == 0);
+
+  if (mInitialized) {
+    // Set up the analysis state and auxiliary encoding storage
+    vorbis_analysis_init(&mVorbisDsp, &mVorbisInfo);
+    vorbis_block_init(&mVorbisDsp, &mVorbisBlock);
+  }
+
+  mon.NotifyAll();
+
+  return ret == 0 ? NS_OK : NS_ERROR_FAILURE;
+}
+
+void VorbisTrackEncoder::WriteLacing(nsTArray<uint8_t> *aOutput, int32_t aLacing)
+{
+  while (aLacing > 255) {
+    aLacing -= 255;
+    aOutput->AppendElement(255);
+  }
+  aOutput->AppendElement((uint8_t)aLacing);
+}
+
+already_AddRefed<TrackMetadataBase>
+VorbisTrackEncoder::GetMetadata()
+{
+  {
+    // Wait if encoder is not initialized.
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+    while (!mCanceled && !mInitialized) {
+      mon.Wait();
+    }
+  }
+
+  if (mCanceled || mEncodingComplete) {
+    return nullptr;
+  }
+
+  // Vorbis codec specific data
+  // http://matroska.org/technical/specs/codecid/index.html
+  nsRefPtr<VorbisMetadata> meta = new VorbisMetadata();
+  meta->mBitDepth = 32; // float for desktop
+  meta->mChannels = mChannels;
+  meta->mSamplingFrequency = mSamplingRate;
+  ogg_packet header;
+  ogg_packet header_comm;
+  ogg_packet header_code;
+  // Add comment
+  vorbis_comment vorbisComment;
+  vorbis_comment_init(&vorbisComment);
+  vorbis_comment_add_tag(&vorbisComment, "ENCODER",
+    NS_LITERAL_CSTRING("Mozilla VorbisTrackEncoder " MOZ_APP_UA_VERSION).get());
+  vorbis_analysis_headerout(&mVorbisDsp, &vorbisComment,
+                            &header,&header_comm, &header_code);
+  vorbis_comment_clear(&vorbisComment);
+  // number of distinct packets - 1
+  meta->mData.AppendElement(2);
+  // Xiph-style lacing header.bytes, header_comm.bytes
+  WriteLacing(&(meta->mData), header.bytes);
+  WriteLacing(&(meta->mData), header_comm.bytes);
+
+  // Append the three packets
+  meta->mData.AppendElements(header.packet, header.bytes);
+  meta->mData.AppendElements(header_comm.packet, header_comm.bytes);
+  meta->mData.AppendElements(header_code.packet, header_code.bytes);
+
+  return meta.forget();
+}
+
+void
+VorbisTrackEncoder::GetEncodedFrames(EncodedFrameContainer& aData)
+{
+  // vorbis does some data preanalysis, then divvies up blocks for
+  // more involved (potentially parallel) processing. Get a single
+  // block for encoding now.
+  while (vorbis_analysis_blockout(&mVorbisDsp, &mVorbisBlock) == 1) {
+    ogg_packet oggPacket;
+    if (vorbis_analysis(&mVorbisBlock, &oggPacket) == 0) {
+      VORBISLOG("vorbis_analysis_blockout block size %d", oggPacket.bytes);
+      EncodedFrame* audiodata = new EncodedFrame();
+      audiodata->SetFrameType(EncodedFrame::AUDIO_FRAME);
+      nsTArray<uint8_t> frameData;
+      frameData.AppendElements(oggPacket.packet, oggPacket.bytes);
+      audiodata->SetFrameData(&frameData);
+      aData.AppendEncodedFrame(audiodata);
+    }
+  }
+}
+
+nsresult
+VorbisTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
+{
+  if (mEosSetInEncoder) {
+    return NS_OK;
+  }
+
+  nsAutoPtr<AudioSegment> sourceSegment;
+  sourceSegment = new AudioSegment();
+  {
+    // Move all the samples from mRawSegment to sourceSegment. We only hold
+    // the monitor in this block.
+    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+    // Wait if mEncoder is not initialized, or when not enough raw data, but is
+    // not the end of stream nor is being canceled.
+    while (!mCanceled && mRawSegment.GetDuration() < GetPacketDuration() &&
+           !mEndOfStream) {
+      mon.Wait();
+    }
+    VORBISLOG("GetEncodedTrack passes wait, duration is %lld\n",
+      mRawSegment.GetDuration());
+    if (mCanceled || mEncodingComplete) {
+      return NS_ERROR_FAILURE;
+    }
+
+    sourceSegment->AppendFrom(&mRawSegment);
+  }
+
+  if (mEndOfStream && (sourceSegment->GetDuration() == 0)
+      && !mEosSetInEncoder) {
+    mEncodingComplete = true;
+    mEosSetInEncoder = true;
+    VORBISLOG("[Vorbis] Done encoding.");
+    vorbis_analysis_wrote(&mVorbisDsp, 0);
+    GetEncodedFrames(aData);
+
+    return NS_OK;
+  }
+
+  // Start encoding data.
+  AudioSegment::ChunkIterator iter(*sourceSegment);
+
+  AudioDataValue **vorbisBuffer =
+    vorbis_analysis_buffer(&mVorbisDsp, (int)sourceSegment->GetDuration());
+
+  int framesCopied = 0;
+  nsAutoTArray<AudioDataValue, 9600> interleavedPcm;
+  nsAutoTArray<AudioDataValue, 9600> nonInterleavedPcm;
+  interleavedPcm.SetLength(sourceSegment->GetDuration() * mChannels);
+  nonInterleavedPcm.SetLength(sourceSegment->GetDuration() * mChannels);
+  while (!iter.IsEnded()) {
+    AudioChunk chunk = *iter;
+    int frameToCopy = chunk.GetDuration();
+    if (!chunk.IsNull()) {
+      InterleaveTrackData(chunk, frameToCopy, mChannels,
+                          interleavedPcm.Elements() + framesCopied * mChannels);
+    } else { // empty data
+      memset(interleavedPcm.Elements() + framesCopied * mChannels, 0,
+             frameToCopy * mChannels * sizeof(AudioDataValue));
+    }
+    framesCopied += frameToCopy;
+    iter.Next();
+  }
+  // De-interleave the interleavedPcm.
+  DeInterleaveTrackData(interleavedPcm.Elements(), framesCopied, mChannels,
+                        nonInterleavedPcm.Elements());
+  // Copy the nonInterleavedPcm to vorbis buffer.
+  for(uint8_t i = 0; i < mChannels; ++i) {
+    memcpy(vorbisBuffer[i], nonInterleavedPcm.Elements() + framesCopied * i,
+           framesCopied * sizeof(AudioDataValue));
+  }
+
+  // Now the vorbisBuffer contain the all data in non-interleaved.
+  // Tell the library how much we actually submitted.
+  vorbis_analysis_wrote(&mVorbisDsp, framesCopied);
+  VORBISLOG("vorbis_analysis_wrote framesCopied %d\n", framesCopied);
+  GetEncodedFrames(aData);
+
+  return NS_OK;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/encoder/VorbisTrackEncoder.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef VorbisTrackEncoder_h_
+#define VorbisTrackEncoder_h_
+
+#include "TrackEncoder.h"
+#include "nsCOMPtr.h"
+#include <vorbis/codec.h>
+
+namespace mozilla {
+
+class VorbisTrackEncoder : public AudioTrackEncoder
+{
+public:
+  VorbisTrackEncoder();
+  virtual ~VorbisTrackEncoder();
+
+  already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_FINAL MOZ_OVERRIDE;
+
+  nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_FINAL MOZ_OVERRIDE;
+
+protected:
+  /**
+   * http://xiph.org/vorbis/doc/libvorbis/vorbis_analysis_buffer.html
+   * We use 1024 samples for the write buffer; libvorbis will construct packets
+   * with the appropriate duration for the encoding mode internally.
+   */
+  int GetPacketDuration() MOZ_FINAL MOZ_OVERRIDE {
+    return 1024;
+  }
+
+  nsresult Init(int aChannels, int aSamplingRate) MOZ_FINAL MOZ_OVERRIDE;
+
+private:
+  // Write Xiph-style lacing to aOutput.
+  void WriteLacing(nsTArray<uint8_t> *aOutput, int32_t aLacing);
+
+  // Get the encoded data from vorbis encoder and append into aData.
+  void GetEncodedFrames(EncodedFrameContainer& aData);
+
+  // vorbis codec members
+  // Struct that stores all the static vorbis bitstream settings.
+  vorbis_info mVorbisInfo;
+  // Central working state for the PCM->packet encoder.
+  vorbis_dsp_state mVorbisDsp;
+  // Local working space for PCM->packet encode.
+  vorbis_block mVorbisBlock;
+};
+
+}
+#endif
--- a/content/media/encoder/moz.build
+++ b/content/media/encoder/moz.build
@@ -15,21 +15,29 @@ EXPORTS += [
     'TrackMetadataBase.h',
 ]
 
 UNIFIED_SOURCES += [
     'MediaEncoder.cpp',
     'TrackEncoder.cpp',
 ]
 
+if CONFIG['MOZ_OMX_ENCODER']:
+    EXPORTS += ['OmxTrackEncoder.h']
+    UNIFIED_SOURCES += ['OmxTrackEncoder.cpp']
+
 if CONFIG['MOZ_OPUS']:
     EXPORTS += ['OpusTrackEncoder.h']
     UNIFIED_SOURCES += ['OpusTrackEncoder.cpp']
 
-if CONFIG['MOZ_OMX_ENCODER']:
-    EXPORTS += ['OmxTrackEncoder.h']
-    UNIFIED_SOURCES += ['OmxTrackEncoder.cpp']
+if CONFIG['MOZ_WEBM_ENCODER']:
+    EXPORTS += ['VorbisTrackEncoder.h',
+                'VP8TrackEncoder.h',
+    ]
+    UNIFIED_SOURCES += ['VorbisTrackEncoder.cpp',
+                        'VP8TrackEncoder.cpp',
+    ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'gklayout'
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/content/media/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -251,16 +251,17 @@ support-files =
 [test_mozHasAudio.html]
 [test_source_media.html]
 [test_autoplay_contentEditable.html]
 [test_decoder_disable.html]
 [test_mediarecorder_record_no_timeslice.html]
 [test_mediarecorder_reload_crash.html]
 [test_mediarecorder_record_immediate_stop.html]
 [test_mediarecorder_record_session.html]
+[test_mediarecorder_unsupported_src.html]
 [test_playback.html]
 [test_seekLies.html]
 [test_media_sniffer.html]
 [test_streams_srcObject.html]
 [test_reset_src.html]
 [test_streams_autoplay.html]
 [test_streams_element_capture.html]
 [test_streams_element_capture_reset.html]
new file mode 100644
--- /dev/null
+++ b/content/media/test/test_mediarecorder_unsupported_src.html
@@ -0,0 +1,90 @@
+<html>
+<head>
+  <title>Bug 957439 - Media Recording - Assertion fail at Pause if unsupported input stream.</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=957439">Mozilla Bug 957439</a>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function startTest() {
+  navigator.mozGetUserMedia({audio: false, video: true, fake: true},
+    function(stream) {
+
+      // Expected callback sequence should be:
+      // 1. onerror (from start)
+      // 2. onerror (from pause)
+      // 3. ondataavailable
+      // 4. onstop
+      var callbackStep = 0;
+      var mediaRecorder = new MediaRecorder(stream);
+
+      is(mediaRecorder.stream, stream, 'Stream should be provided on creation');
+
+      mediaRecorder.onerror = function (e) {
+        callbackStep++;
+        ok(callbackStep < 3, 'onerror callback fired as expected.');
+        is(e.name, 'GenericError', 'Error name should be GenericError.');
+        is(mediaRecorder.mimeType, '', 'mimetype should be empty');
+        is(mediaRecorder.state, 'recording', 'state is recording');
+        info('onerror callback fired');
+      }
+
+      mediaRecorder.onwarning = function () {
+        ok(false, 'Unexpected onwarning callback fired.');
+      };
+
+      mediaRecorder.ondataavailable = function (evt) {
+        callbackStep++;
+        info('ondataavailable callback fired');
+        is(callbackStep, 3, 'should fired ondataavailable callback');
+        is(evt.data.size, 0, 'data size should be zero');
+        ok(evt instanceof BlobEvent,
+           'Events fired from ondataavailable should be BlobEvent');
+        is(evt.data.type, '', 'encoder start fail, blob miemType should be empty');
+      };
+
+      mediaRecorder.onstop = function() {
+        callbackStep++;
+        info('onstop callback fired');
+        is(mediaRecorder.state, 'inactive', 'state should be inactive');
+        is(callbackStep, 4, 'should fired onstop callback');
+        SimpleTest.finish();
+      };
+
+      try {
+        mediaRecorder.start();
+      } catch(e) {
+        ok(false, 'Should not get exception in start call.');
+      }
+
+      try {
+        mediaRecorder.pause();
+      } catch(e) {
+        ok(false, 'Should not get exception in pause call.');
+      }
+    },
+    function(err) {
+      ok(false, 'Unexpected error fired with: ' + err);
+      SimpleTest.finish();
+    }
+  );
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// In order to generate an "unsupported stream", pref off video encoding to
+// make the platform support audio encoding only.
+SpecialPowers.pushPrefEnv(
+  {
+    "set": [
+      ["media.encoder.webm.enabled", false]
+    ]
+  }, startTest);
+
+</script>
+</head>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/media/webm/EbmlComposer.cpp
@@ -0,0 +1,177 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "EbmlComposer.h"
+#include "libmkv/EbmlIDs.h"
+#include "libmkv/EbmlWriter.h"
+#include "libmkv/WebMElement.h"
+#include "prtime.h"
+
+namespace mozilla {
+
+// Timecode scale in nanoseconds
+static const unsigned long TIME_CODE_SCALE = 1000000;
+// The WebM header size without audio CodecPrivateData
+static const int32_t DEFAULT_HEADER_SIZE = 1024;
+
+void EbmlComposer::GenerateHeader()
+{
+  // Write the EBML header.
+  EbmlGlobal ebml;
+  // The WEbM header default size usually smaller than 1k.
+  nsAutoArrayPtr<uint8_t> buffer(new uint8_t[DEFAULT_HEADER_SIZE +
+                                             mCodecPrivateData.Length()]);
+  ebml.buf = buffer.get();
+  ebml.offset = 0;
+  writeHeader(&ebml);
+  {
+    EbmlLoc segEbmlLoc, ebmlLocseg, ebmlLoc;
+    Ebml_StartSubElement(&ebml, &segEbmlLoc, Segment);
+    {
+      Ebml_StartSubElement(&ebml, &ebmlLocseg, SeekHead);
+      // Todo: We don't know the exact sizes of encoded data and ignore this section.
+      Ebml_EndSubElement(&ebml, &ebmlLocseg);
+      writeSegmentInformation(&ebml, &ebmlLoc, TIME_CODE_SCALE, 0);
+      {
+        EbmlLoc trackLoc;
+        Ebml_StartSubElement(&ebml, &trackLoc, Tracks);
+        {
+          char cid_string[8];
+          // Video
+          if (mWidth > 0 && mHeight > 0) {
+            strcpy(cid_string, "V_VP8");
+            writeVideoTrack(&ebml, 0x1, 0, cid_string,
+                            mWidth, mHeight, mFrameRate);
+          }
+          // Audio
+          if (mCodecPrivateData.Length() > 0) {
+            strcpy(cid_string, "A_VORBIS");
+            writeAudioTrack(&ebml, 0x2, 0x0, cid_string, mSampleFreq,
+                            mChannels, mCodecPrivateData.Elements(),
+                            mCodecPrivateData.Length());
+          }
+        }
+        Ebml_EndSubElement(&ebml, &trackLoc);
+      }
+    }
+    // The Recording length is unknow and ignore write the whole Segment element size
+  }
+  MOZ_ASSERT_IF(ebml.offset > DEFAULT_HEADER_SIZE + mCodecPrivateData.Length(),
+                "write more data > EBML_BUFFER_SIZE");
+  mClusterBuffs.AppendElement();
+  mClusterBuffs.LastElement().SetLength(ebml.offset);
+  memcpy(mClusterBuffs.LastElement().Elements(), ebml.buf, ebml.offset);
+}
+
+void EbmlComposer::FinishCluster()
+{
+  MOZ_ASSERT(mClusterLengthLoc > 0 );
+  MOZ_ASSERT(mClusterHeaderIndex > 0);
+  for (uint32_t i = 0; i < mClusterBuffs.Length(); i ++ ) {
+    mClusterCanFlushBuffs.AppendElement()->SwapElements(mClusterBuffs[i]);
+  }
+  mClusterBuffs.Clear();
+  EbmlGlobal ebml;
+  EbmlLoc ebmlLoc;
+  ebmlLoc.offset = mClusterLengthLoc;
+  ebml.offset = mClusterCanFlushBuffs[mClusterHeaderIndex].Length();
+  ebml.buf = mClusterCanFlushBuffs[mClusterHeaderIndex].Elements();
+  Ebml_EndSubElement(&ebml, &ebmlLoc);
+  mClusterHeaderIndex = 0;
+  mClusterLengthLoc = 0;
+}
+
+void
+EbmlComposer::WriteSimpleBlock(EncodedFrame* aFrame)
+{
+  EbmlGlobal ebml;
+  ebml.offset = 0;
+
+  if (aFrame->GetFrameType() == EncodedFrame::FrameType::I_FRAME && mClusterHeaderIndex > 0) {
+    FinishCluster();
+  }
+
+  mClusterBuffs.AppendElement();
+  mClusterBuffs.LastElement().SetLength(aFrame->GetFrameData().Length() + DEFAULT_HEADER_SIZE);
+  ebml.buf = mClusterBuffs.LastElement().Elements();
+
+  if (aFrame->GetFrameType() == EncodedFrame::FrameType::I_FRAME) {
+    EbmlLoc ebmlLoc;
+    Ebml_StartSubElement(&ebml, &ebmlLoc, Cluster);
+    mClusterHeaderIndex = mClusterBuffs.Length() - 1; // current cluster header array index
+    mClusterLengthLoc = ebmlLoc.offset;
+    if (aFrame->GetFrameType() != EncodedFrame::FrameType::AUDIO_FRAME) {
+      mClusterTimecode = aFrame->GetTimeStamp() / PR_USEC_PER_MSEC;
+    }
+    Ebml_SerializeUnsigned(&ebml, Timecode, mClusterTimecode);
+  }
+
+  if (aFrame->GetFrameType() != EncodedFrame::FrameType::AUDIO_FRAME) {
+    short timeCode = aFrame->GetTimeStamp() / PR_USEC_PER_MSEC - mClusterTimecode;
+    writeSimpleBlock(&ebml, 0x1, timeCode, aFrame->GetFrameType() ==
+                     EncodedFrame::FrameType::I_FRAME,
+                     0, 0, (unsigned char*)aFrame->GetFrameData().Elements(),
+                     aFrame->GetFrameData().Length());
+  } else {
+    writeSimpleBlock(&ebml, 0x2, 0, false,
+                     0, 0, (unsigned char*)aFrame->GetFrameData().Elements(),
+                     aFrame->GetFrameData().Length());
+  }
+  MOZ_ASSERT_IF(ebml.offset > DEFAULT_HEADER_SIZE + aFrame->GetFrameData().Length(),
+                "write more data > EBML_BUFFER_SIZE");
+  mClusterBuffs.LastElement().SetLength(ebml.offset);
+}
+
+void
+EbmlComposer::SetVideoConfig(uint32_t aWidth, uint32_t aHeight,
+                             float aFrameRate)
+{
+  MOZ_ASSERT(aWidth > 0, "Width should > 0");
+  MOZ_ASSERT(aHeight > 0, "Height should > 0");
+  MOZ_ASSERT(aFrameRate > 0, "FrameRate should > 0");
+  mWidth = aWidth;
+  mHeight = aHeight;
+  mFrameRate = aFrameRate;
+}
+
+void
+EbmlComposer::SetAudioConfig(uint32_t aSampleFreq, uint32_t aChannels,
+                             uint32_t aBitDepth)
+{
+  MOZ_ASSERT(aSampleFreq > 0, "SampleFreq should > 0");
+  MOZ_ASSERT(aBitDepth > 0, "BitDepth should > 0");
+  MOZ_ASSERT(aChannels > 0, "Channels should > 0");
+  mSampleFreq = aSampleFreq;
+  mBitDepth = aBitDepth;
+  mChannels = aChannels;
+}
+
+void
+EbmlComposer::ExtractBuffer(nsTArray<nsTArray<uint8_t> >* aDestBufs,
+                            uint32_t aFlag)
+{
+  if ((aFlag & ContainerWriter::FLUSH_NEEDED) && mClusterHeaderIndex > 0) {
+    FinishCluster();
+  }
+  // aDestBufs may have some element
+  for (uint32_t i = 0; i < mClusterCanFlushBuffs.Length(); i ++ ) {
+    aDestBufs->AppendElement()->SwapElements(mClusterCanFlushBuffs[i]);
+  }
+  mClusterCanFlushBuffs.Clear();
+}
+
+EbmlComposer::EbmlComposer()
+  : mClusterHeaderIndex(0)
+  , mClusterLengthLoc(0)
+  , mClusterTimecode(0)
+  , mWidth(0)
+  , mHeight(0)
+  , mFrameRate(0)
+  , mSampleFreq(0)
+  , mBitDepth(0)
+  , mChannels(0)
+{}
+
+}
new file mode 100644
--- /dev/null
+++ b/content/media/webm/EbmlComposer.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef EbmlComposer_h_
+#define EbmlComposer_h_
+#include "nsTArray.h"
+#include "ContainerWriter.h"
+
+namespace mozilla {
+
+/*
+ * A WebM muxer helper for package the valid WebM format.
+ */
+class EbmlComposer {
+public:
+  EbmlComposer();
+  /*
+   * Assign the parameter which header required.
+   */
+  void SetVideoConfig(uint32_t aWidth, uint32_t aHeight, float aFrameRate);
+
+  void SetAudioConfig(uint32_t aSampleFreq, uint32_t aChannels,
+                      uint32_t bitDepth);
+  /*
+   * Set the CodecPrivateData for writing in header.
+   */
+  void SetAudioCodecPrivateData(nsTArray<uint8_t>& aBufs)
+  {
+    mCodecPrivateData.AppendElements(aBufs);
+  }
+  /*
+   * Generate the whole WebM header and output to mBuff.
+   */
+  void GenerateHeader();
+  /*
+   * Insert media encoded buffer into muxer and it would be package
+   * into SimpleBlock. If no cluster is opened, new cluster will start for writing.
+   */
+  void WriteSimpleBlock(EncodedFrame* aFrame);
+  /*
+   * Get valid cluster data.
+   */
+  void ExtractBuffer(nsTArray<nsTArray<uint8_t> >* aDestBufs,
+                     uint32_t aFlag = 0);
+private:
+  // Close current cluster and move data to mClusterCanFlushBuffs.
+  void FinishCluster();
+  // The temporary storage for cluster data.
+  nsTArray<nsTArray<uint8_t> > mClusterBuffs;
+  // The storage which contain valid cluster data.
+  nsTArray<nsTArray<uint8_t> > mClusterCanFlushBuffs;
+  // Indicate the header index in mClusterBuffs.
+  uint32_t mClusterHeaderIndex;
+  // The cluster length position.
+  uint64_t mClusterLengthLoc;
+  // Audio codec specific header data.
+  nsTArray<uint8_t> mCodecPrivateData;
+
+  // The timecode of the cluster.
+  uint64_t mClusterTimecode;
+
+  // Video configuration
+  int mWidth;
+  int mHeight;
+  float mFrameRate;
+  // Audio configuration
+  float mSampleFreq;
+  int mBitDepth;
+  int mChannels;
+};
+
+}
+#endif
new file mode 100644
--- /dev/null
+++ b/content/media/webm/WebMWriter.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WebMWriter.h"
+#include "EbmlComposer.h"
+
+namespace mozilla {
+
+WebMWriter::WebMWriter(uint32_t aTrackTypes) : ContainerWriter()
+{
+  mMetadataRequiredFlag = aTrackTypes;
+  mEbmlComposer = new EbmlComposer();
+}
+
+nsresult
+WebMWriter::WriteEncodedTrack(const EncodedFrameContainer& aData,
+                              uint32_t aFlags)
+{
+  for (uint32_t i = 0 ; i < aData.GetEncodedFrames().Length(); i++) {
+    mEbmlComposer->WriteSimpleBlock(aData.GetEncodedFrames().ElementAt(i).get());
+  }
+  return NS_OK;
+}
+
+nsresult
+WebMWriter::GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
+                             uint32_t aFlags)
+{
+  mEbmlComposer->ExtractBuffer(aOutputBufs, aFlags);
+  if (aFlags & ContainerWriter::FLUSH_NEEDED) {
+    mIsWritingComplete = true;
+  }
+  return NS_OK;
+}
+
+nsresult
+WebMWriter::SetMetadata(TrackMetadataBase* aMetadata)
+{
+  MOZ_ASSERT(aMetadata);
+  if (aMetadata->GetKind() == TrackMetadataBase::METADATA_VP8) {
+    VP8Metadata* meta = static_cast<VP8Metadata*>(aMetadata);
+    MOZ_ASSERT(meta, "Cannot find vp8 encoder metadata");
+    mEbmlComposer->SetVideoConfig(meta->mWidth, meta->mHeight,
+                                  meta->mEncodedFrameRate);
+    mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::HAS_VIDEO;
+  }
+
+  if (aMetadata->GetKind() == TrackMetadataBase::METADATA_VORBIS) {
+    VorbisMetadata* meta = static_cast<VorbisMetadata*>(aMetadata);
+    MOZ_ASSERT(meta, "Cannot find vorbis encoder metadata");
+    mEbmlComposer->SetAudioConfig(meta->mSamplingFrequency, meta->mChannels, meta->mBitDepth);
+    mEbmlComposer->SetAudioCodecPrivateData(meta->mData);
+    mMetadataRequiredFlag = mMetadataRequiredFlag & ~ContainerWriter::HAS_AUDIO;
+  }
+
+  if (!mMetadataRequiredFlag) {
+    mEbmlComposer->GenerateHeader();
+  }
+  return NS_OK;
+}
+
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/content/media/webm/WebMWriter.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WebMWriter_h_
+#define WebMWriter_h_
+
+#include "ContainerWriter.h"
+
+namespace mozilla {
+
+class EbmlComposer;
+
+// Vorbis meta data structure
+class VorbisMetadata : public TrackMetadataBase
+{
+public:
+  nsTArray<uint8_t> mData;
+  int32_t mChannels;
+  int32_t mBitDepth;
+  float mSamplingFrequency;
+  MetadataKind GetKind() const MOZ_OVERRIDE { return METADATA_VORBIS; }
+};
+
+// VP8 meta data structure
+class VP8Metadata : public TrackMetadataBase
+{
+public:
+  int32_t mWidth;
+  int32_t mHeight;
+  int32_t mEncodedFrameRate;
+  MetadataKind GetKind() const MOZ_OVERRIDE { return METADATA_VP8; }
+};
+
+/**
+ * WebM writer helper
+ * This class accepts encoder to set audio or video meta data or
+ * encoded data to ebml Composer, and get muxing data through GetContainerData.
+ * The ctor/dtor run in the MediaRecorder thread, others run in MediaEncoder thread.
+ */
+class WebMWriter : public ContainerWriter
+{
+public:
+  // aTrackTypes indicate this muxer should multiplex into Video only or A/V foramt.
+  // Run in MediaRecorder thread
+  WebMWriter(uint32_t aTrackTypes);
+  // WriteEncodedTrack inserts raw packets into WebM stream.
+  nsresult WriteEncodedTrack(const EncodedFrameContainer &aData,
+                             uint32_t aFlags = 0) MOZ_OVERRIDE;
+
+  // GetContainerData outputs multiplexing data.
+  // aFlags indicates the muxer should enter into finished stage and flush out
+  // queue data.
+  nsresult GetContainerData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
+                            uint32_t aFlags = 0) MOZ_OVERRIDE;
+
+  // Assign metadata into muxer
+  nsresult SetMetadata(TrackMetadataBase* aMetadata) MOZ_OVERRIDE;
+
+private:
+  nsAutoPtr<EbmlComposer> mEbmlComposer;
+
+  // Indicate what kind of meta data needed in the writer.
+  // If this value become 0, it means writer can start to generate header.
+  uint8_t mMetadataRequiredFlag;
+};
+
+}
+#endif
--- a/content/media/webm/moz.build
+++ b/content/media/webm/moz.build
@@ -10,11 +10,17 @@ EXPORTS += [
 ]
 
 UNIFIED_SOURCES += [
     'WebMBufferedParser.cpp',
     'WebMDecoder.cpp',
     'WebMReader.cpp',
 ]
 
+if CONFIG['MOZ_WEBM_ENCODER']:
+    EXPORTS += ['WebMWriter.h']
+    UNIFIED_SOURCES += ['EbmlComposer.cpp',
+                        'WebMWriter.cpp',
+    ]
+
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'gklayout'
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/b2g_bdroid_buildcfg.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef B2G_BDROID_BUILDCFG_H
+#define B2G_BDROID_BUILDCFG_H
+
+/**
+ * This header defines B2G common bluedroid build configuration.
+ *
+ * This header is included by
+ *   $(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR)/bdroid_buildcfg.h,
+ * which applies external configuration onto bluedroid.
+ */
+
+/******************************************************************************
+**
+** HSP, HFP
+**
+******************************************************************************/
+/* AG feature masks */
+#define BTIF_HF_FEATURES   ( BTA_AG_FEAT_3WAY | \
+                             BTA_AG_FEAT_REJECT | \
+                             BTA_AG_FEAT_ECS    | \
+                             BTA_AG_FEAT_EXTERR)
+
+/* CHLD values */
+#define BTA_AG_CHLD_VAL    "(0,1,2)"
+
+#endif /* B2G_BDROID_BUILDCFG_H */
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -3652,18 +3652,18 @@ let RIL = {
   _handleDisconnectedCall: function(disconnectedCall) {
     let message = {rilMessageType: "callDisconnected",
                    call: disconnectedCall};
     this.sendChromeMessage(message);
   },
 
   _sendCallError: function(callIndex, errorMsg) {
     this.sendChromeMessage({rilMessageType: "callError",
-                           callIndex: callIndex,
-                           errorMsg: errorMsg});
+                            callIndex: callIndex,
+                            errorMsg: errorMsg});
   },
 
   _sendDataCallError: function(message, errorCode) {
     // Should not include token for unsolicited response.
     delete message.rilMessageToken;
     message.rilMessageType = "datacallerror";
     if (errorCode == ERROR_GENERIC_FAILURE) {
       message.errorMsg = RIL_ERROR_TO_GECKO_ERROR[errorCode];
@@ -5090,18 +5090,17 @@ RIL[REQUEST_GET_CURRENT_CALLS] = functio
     calls[call.callIndex] = call;
   }
   this._processCalls(calls);
 };
 RIL[REQUEST_DIAL] = function REQUEST_DIAL(length, options) {
   if (options.rilRequestError) {
     // The connection is not established yet.
     options.callIndex = -1;
-    this._sendCallError(options.callIndex,
-                        RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]);
+    this.getFailCauseCode(options);
   }
 };
 RIL[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.iccInfoPrivate.imsi = Buf.readString();
@@ -9661,16 +9660,23 @@ let ICCPDUHelper = {
     }
 
     return number;
   },
 
   writeNumberWithLength: function(number) {
     if (number) {
       let numStart = number[0] == "+" ? 1 : 0;
+      number = number.substring(0, numStart) +
+               number.substring(numStart)
+                     .replace(/[^0-9*#,]/g, "")
+                     .replace(/\*/g, "a")
+                     .replace(/\#/g, "b")
+                     .replace(/\,/g, "c");
+
       let numDigits = number.length - numStart;
       if (numDigits > ADN_MAX_NUMBER_DIGITS) {
         number = number.substring(0, ADN_MAX_NUMBER_DIGITS + numStart);
         numDigits = number.length - numStart;
       }
 
       // +1 for TON/NPI
       let numLen = Math.ceil(numDigits / 2) + 1;
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc.js
@@ -491,37 +491,45 @@ add_test(function test_read_number_with_
 /**
  * Verify ICCPDUHelper.writeNumberWithLength
  */
 add_test(function test_write_number_with_length() {
   let worker = newUint8Worker();
   let helper = worker.GsmPDUHelper;
   let iccHelper = worker.ICCPDUHelper;
 
+  function test(number, expectedNumber) {
+    expectedNumber = expectedNumber || number;
+    iccHelper.writeNumberWithLength(number);
+    let numLen = helper.readHexOctet();
+    do_check_eq(expectedNumber, iccHelper.readDiallingNumber(numLen));
+    for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
+      do_check_eq(0xff, helper.readHexOctet());
+    }
+  }
+
   // without +
-  let number_1 = "123456789";
-  iccHelper.writeNumberWithLength(number_1);
-  let numLen = helper.readHexOctet();
-  do_check_eq(number_1, iccHelper.readDiallingNumber(numLen));
-  for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
-    do_check_eq(0xff, helper.readHexOctet());
-  }
+  test("123456789");
 
   // with +
-  let number_2 = "+987654321";
-  iccHelper.writeNumberWithLength(number_2);
-  numLen = helper.readHexOctet();
-  do_check_eq(number_2, iccHelper.readDiallingNumber(numLen));
-  for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
-    do_check_eq(0xff, helper.readHexOctet());
-  }
+  test("+987654321");
+
+  // extended BCD coding
+  test("1*2#3,4*5#6,");
+
+  // with + and extended BCD coding
+  test("+1*2#3,4*5#6,");
+
+  // non-supported characters should not be written.
+  test("(1)23-456+789", "123456789");
+
+  test("++(01)2*3-4#5,6+7(8)9*0#1,", "+012*34#5,6789*0#1,");
 
   // null
-  let number_3;
-  iccHelper.writeNumberWithLength(number_3);
+  iccHelper.writeNumberWithLength(null);
   for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES + 1); i++) {
     do_check_eq(0xff, helper.readHexOctet());
   }
 
   run_next_test();
 });
 
 /**
--- a/layout/media/symbols.def.in
+++ b/layout/media/symbols.def.in
@@ -24,16 +24,27 @@ nestegg_track_count
 nestegg_get_cue_point
 nestegg_track_seek
 nestegg_track_type
 nestegg_track_video_params
 nestegg_tstamp_scale
 nestegg_has_cues
 nestegg_sniff
 #endif
+#ifdef MOZ_WEBM_ENCODER
+writeSimpleBlock
+writeHeader
+writeSegmentInformation
+writeVideoTrack
+writeAudioTrack
+Ebml_Serialize
+Ebml_SerializeUnsigned
+Ebml_StartSubElement
+Ebml_EndSubElement
+#endif
 #ifdef MOZ_VPX
 #ifndef MOZ_NATIVE_LIBVPX
 vpx_codec_control_
 vpx_codec_dec_init_ver
 vpx_codec_decode
 vpx_codec_destroy
 vpx_codec_get_frame
 vpx_codec_peek_stream_info
new file mode 100644
--- /dev/null
+++ b/media/libmkv/AUTHORS
@@ -0,0 +1,100 @@
+# This file is automatically generated from the git commit history
+# by tools/gen_authors.sh.
+
+Aaron Watry <awatry@gmail.com>
+Abo Talib Mahfoodh <ab.mahfoodh@gmail.com>
+Adrian Grange <agrange@google.com>
+Ahmad Sharif <asharif@google.com>
+Alexander Voronov <avoronov@graphics.cs.msu.ru>
+Alex Converse <alex.converse@gmail.com>
+Alexis Ballier <aballier@gentoo.org>
+Alok Ahuja <waveletcoeff@gmail.com>
+Alpha Lam <hclam@google.com>
+A.Mahfoodh <ab.mahfoodh@gmail.com>
+Ami Fischman <fischman@chromium.org>
+Andoni Morales Alastruey <ylatuya@gmail.com>
+Andres Mejia <mcitadel@gmail.com>
+Aron Rosenberg <arosenberg@logitech.com>
+Attila Nagy <attilanagy@google.com>
+changjun.yang <changjun.yang@intel.com>
+chm <chm@rock-chips.com>
+Christian Duvivier <cduvivier@google.com>
+Daniel Kang <ddkang@google.com>
+Deb Mukherjee <debargha@google.com>
+Dmitry Kovalev <dkovalev@google.com>
+Dragan Mrdjan <dmrdjan@mips.com>
+Erik Niemeyer <erik.a.niemeyer@gmail.com>
+Fabio Pedretti <fabio.ped@libero.it>
+Frank Galligan <fgalligan@google.com>
+Fredrik Söderquist <fs@opera.com>
+Fritz Koenig <frkoenig@google.com>
+Gaute Strokkenes <gaute.strokkenes@broadcom.com>
+Giuseppe Scrivano <gscrivano@gnu.org>
+Guillaume Martres <gmartres@google.com>
+Guillermo Ballester Valor <gbvalor@gmail.com>
+Hangyu Kuang <hkuang@google.com>
+Henrik Lundin <hlundin@google.com>
+Hui Su <huisu@google.com>
+Ivan Maltz <ivanmaltz@google.com>
+James Berry <jamesberry@google.com>
+James Zern <jzern@google.com>
+Jan Kratochvil <jan.kratochvil@redhat.com>
+Janne Salonen <jsalonen@google.com>
+Jeff Faust <jfaust@google.com>
+Jeff Muizelaar <jmuizelaar@mozilla.com>
+Jeff Petkau <jpet@chromium.org>
+Jim Bankoski <jimbankoski@google.com>
+Jingning Han <jingning@google.com>
+Johann Koenig <johannkoenig@google.com>
+John Koleszar <jkoleszar@google.com>
+Joshua Bleecher Snyder <josh@treelinelabs.com>
+Joshua Litt <joshualitt@google.com>
+Justin Clift <justin@salasaga.org>
+Justin Lebar <justin.lebar@gmail.com>
+KO Myung-Hun <komh@chollian.net>
+Lou Quillio <louquillio@google.com>
+Luca Barbato <lu_zero@gentoo.org>
+Makoto Kato <makoto.kt@gmail.com>
+Mans Rullgard <mans@mansr.com>
+Marco Paniconi <marpan@google.com>
+Mark Mentovai <mark@chromium.org>
+Martin Ettl <ettl.martin78@googlemail.com>
+Martin Storsjo <martin@martin.st>
+Matthew Heaney <matthewjheaney@chromium.org>
+Michael Kohler <michaelkohler@live.com>
+Mike Frysinger <vapier@chromium.org>
+Mike Hommey <mhommey@mozilla.com>
+Mikhal Shemer <mikhal@google.com>
+Morton Jonuschat <yabawock@gmail.com>
+Parag Salasakar <img.mips1@gmail.com>
+Pascal Massimino <pascal.massimino@gmail.com>
+Patrik Westin <patrik.westin@gmail.com>
+Paul Wilkins <paulwilkins@google.com>
+Pavol Rusnak <stick@gk2.sk>
+Paweł Hajdan <phajdan@google.com>
+Philip Jägenstedt <philipj@opera.com>
+Priit Laes <plaes@plaes.org>
+Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
+Rafaël Carré <funman@videolan.org>
+Ralph Giles <giles@xiph.org>
+Rob Bradford <rob@linux.intel.com>
+Ronald S. Bultje <rbultje@google.com>
+Sami Pietilä <samipietila@google.com>
+Scott Graham <scottmg@chromium.org>
+Scott LaVarnway <slavarnway@google.com>
+Shimon Doodkin <helpmepro1@gmail.com>
+Stefan Holmer <holmer@google.com>
+Suman Sunkara <sunkaras@google.com>
+Taekhyun Kim <takim@nvidia.com>
+Takanori MATSUURA <t.matsuu@gmail.com>
+Tamar Levy <tamar.levy@intel.com>
+Tero Rintaluoma <teror@google.com>
+Thijs Vermeir <thijsvermeir@gmail.com>
+Timothy B. Terriberry <tterribe@xiph.org>
+Tom Finegan <tomfinegan@google.com>
+Vignesh Venkatasubramanian <vigneshv@google.com>
+Yaowu Xu <yaowu@google.com>
+Yunqing Wang <yunqingwang@google.com>
+Google Inc.
+The Mozilla Foundation
+The Xiph.Org Foundation
new file mode 100644
--- /dev/null
+++ b/media/libmkv/EbmlBufferWriter.c
@@ -0,0 +1,79 @@
+// #include <strmif.h>
+#include "EbmlBufferWriter.h"
+#include "EbmlWriter.h"
+// #include <cassert>
+// #include <limits>
+// #include <malloc.h>  //_alloca
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+
+void
+Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, int buffer_size, unsigned long len)
+{
+  /* buffer_size:
+   * 1 - int8_t;
+   * 2 - int16_t;
+   * 3 - int32_t;
+   * 4 - int64_t;
+   */
+  long i;
+  for(i = len-1; i >= 0; i--) {
+    unsigned char x;
+    if (buffer_size == 1) {
+      x = (char)(*(const int8_t *)buffer_in >> (i * 8));
+	} else if (buffer_size == 2) {
+      x = (char)(*(const int16_t *)buffer_in >> (i * 8));
+	} else if (buffer_size == 4) {
+      x = (char)(*(const int32_t *)buffer_in >> (i * 8));
+	} else if (buffer_size == 8) {
+      x = (char)(*(const int64_t *)buffer_in >> (i * 8));
+	}
+    Ebml_Write(glob, &x, 1);
+  }
+}
+
+void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len) {
+  unsigned char *src = glob->buf;
+  src += glob->offset;
+  memcpy(src, buffer_in, len);
+  glob->offset += len;
+}
+
+static void _Serialize(EbmlGlobal *glob, const unsigned char *p, const unsigned char *q) {
+  while (q != p) {
+    --q;
+
+    memcpy(&(glob->buf[glob->offset]), q, 1);
+    glob->offset++;
+  }
+}
+
+/*
+void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, unsigned long len) {
+  // assert(buf);
+
+  const unsigned char *const p = (const unsigned char *)(buffer_in);
+  const unsigned char *const q = p + len;
+
+  _Serialize(glob, p, q);
+}
+*/
+
+void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id) {
+  unsigned long long unknownLen = 0x01FFFFFFFFFFFFFFLL;
+  Ebml_WriteID(glob, class_id);
+  ebmlLoc->offset = glob->offset;
+  // todo this is always taking 8 bytes, this may need later optimization
+  Ebml_Serialize(glob, (void *)&unknownLen,sizeof(unknownLen), 8); // this is a key that says lenght unknown
+}
+
+void Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc) {
+  unsigned long long size = glob->offset - ebmlLoc->offset - 8;
+  unsigned long long curOffset = glob->offset;
+  glob->offset = ebmlLoc->offset;
+  size |=  0x0100000000000000LL;
+  Ebml_Serialize(glob, &size,sizeof(size), 8);
+  glob->offset = curOffset;
+}
+
new file mode 100644
--- /dev/null
+++ b/media/libmkv/EbmlBufferWriter.h
@@ -0,0 +1,20 @@
+#ifndef EBMLBUFFERWRITER_HPP
+#define EBMLBUFFERWRITER_HPP
+
+typedef struct {
+  unsigned long long offset;
+} EbmlLoc;
+
+typedef struct {
+  unsigned char *buf;
+  unsigned int length;
+  unsigned int offset;
+} EbmlGlobal;
+
+void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len);
+void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in,
+                    int buffer_size, unsigned long len);
+void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id);
+void Ebml_EndSubElement(EbmlGlobal *glob,  EbmlLoc *ebmlLoc);
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/libmkv/EbmlIDs.h
@@ -0,0 +1,231 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef MKV_DEFS_HPP
+#define MKV_DEFS_HPP 1
+
+/* Commenting out values not available in webm, but available in matroska */
+
+enum mkv {
+  EBML = 0x1A45DFA3,
+  EBMLVersion = 0x4286,
+  EBMLReadVersion = 0x42F7,
+  EBMLMaxIDLength = 0x42F2,
+  EBMLMaxSizeLength = 0x42F3,
+  DocType = 0x4282,
+  DocTypeVersion = 0x4287,
+  DocTypeReadVersion = 0x4285,
+/* CRC_32 = 0xBF, */
+  Void = 0xEC,
+  SignatureSlot = 0x1B538667,
+  SignatureAlgo = 0x7E8A,
+  SignatureHash = 0x7E9A,
+  SignaturePublicKey = 0x7EA5,
+  Signature = 0x7EB5,
+  SignatureElements = 0x7E5B,
+  SignatureElementList = 0x7E7B,
+  SignedElement = 0x6532,
+  /* segment */
+  Segment = 0x18538067,
+  /* Meta Seek Information */
+  SeekHead = 0x114D9B74,
+  Seek = 0x4DBB,
+  SeekID = 0x53AB,
+  SeekPosition = 0x53AC,
+  /* Segment Information */
+  Info = 0x1549A966,
+/* SegmentUID = 0x73A4, */
+/* SegmentFilename = 0x7384, */
+/* PrevUID = 0x3CB923, */
+/* PrevFilename = 0x3C83AB, */
+/* NextUID = 0x3EB923, */
+/* NextFilename = 0x3E83BB, */
+/* SegmentFamily = 0x4444, */
+/* ChapterTranslate = 0x6924, */
+/* ChapterTranslateEditionUID = 0x69FC, */
+/* ChapterTranslateCodec = 0x69BF, */
+/* ChapterTranslateID = 0x69A5, */
+  TimecodeScale = 0x2AD7B1,
+  Segment_Duration = 0x4489,
+  DateUTC = 0x4461,
+/* Title = 0x7BA9, */
+  MuxingApp = 0x4D80,
+  WritingApp = 0x5741,
+  /* Cluster */
+  Cluster = 0x1F43B675,
+  Timecode = 0xE7,
+/* SilentTracks = 0x5854, */
+/* SilentTrackNumber = 0x58D7, */
+/* Position = 0xA7, */
+  PrevSize = 0xAB,
+  BlockGroup = 0xA0,
+  Block = 0xA1,
+/* BlockVirtual = 0xA2, */
+  BlockAdditions = 0x75A1,
+  BlockMore = 0xA6,
+  BlockAddID = 0xEE,
+  BlockAdditional = 0xA5,
+  BlockDuration = 0x9B,
+/* ReferencePriority = 0xFA, */
+  ReferenceBlock = 0xFB,
+/* ReferenceVirtual = 0xFD, */
+/* CodecState = 0xA4, */
+/* Slices = 0x8E, */
+/* TimeSlice = 0xE8, */
+  LaceNumber = 0xCC,
+/* FrameNumber = 0xCD, */
+/* BlockAdditionID = 0xCB, */
+/* MkvDelay = 0xCE, */
+/* Cluster_Duration = 0xCF, */
+  SimpleBlock = 0xA3,
+/* EncryptedBlock = 0xAF, */
+  /* Track */
+  Tracks = 0x1654AE6B,
+  TrackEntry = 0xAE,
+  TrackNumber = 0xD7,
+  TrackUID = 0x73C5,
+  TrackType = 0x83,
+  FlagEnabled = 0xB9,
+  FlagDefault = 0x88,
+  FlagForced = 0x55AA,
+  FlagLacing = 0x9C,
+/* MinCache = 0x6DE7, */
+/* MaxCache = 0x6DF8, */
+  DefaultDuration = 0x23E383,
+/* TrackTimecodeScale = 0x23314F, */
+/* TrackOffset = 0x537F, */
+  MaxBlockAdditionID = 0x55EE,
+  Name = 0x536E,
+  Language = 0x22B59C,
+  CodecID = 0x86,
+  CodecPrivate = 0x63A2,
+  CodecName = 0x258688,
+/* AttachmentLink = 0x7446, */
+/* CodecSettings = 0x3A9697, */
+/* CodecInfoURL = 0x3B4040, */
+/* CodecDownloadURL = 0x26B240, */
+/* CodecDecodeAll = 0xAA, */
+/* TrackOverlay = 0x6FAB, */
+/* TrackTranslate = 0x6624, */
+/* TrackTranslateEditionUID = 0x66FC, */
+/* TrackTranslateCodec = 0x66BF, */
+/* TrackTranslateTrackID = 0x66A5, */
+  /* video */
+  Video = 0xE0,
+  FlagInterlaced = 0x9A,
+  WEBM_StereoMode = 0x53B8,
+  AlphaMode = 0x53C0,
+  PixelWidth = 0xB0,
+  PixelHeight = 0xBA,
+  PixelCropBottom = 0x54AA,
+  PixelCropTop = 0x54BB,
+  PixelCropLeft = 0x54CC,
+  PixelCropRight = 0x54DD,
+  DisplayWidth = 0x54B0,
+  DisplayHeight = 0x54BA,
+  DisplayUnit = 0x54B2,
+  AspectRatioType = 0x54B3,
+/* ColourSpace = 0x2EB524, */
+/* GammaValue = 0x2FB523, */
+  FrameRate = 0x2383E3,
+  /* end video */
+  /* audio */
+  Audio = 0xE1,
+  SamplingFrequency = 0xB5,
+  OutputSamplingFrequency = 0x78B5,
+  Channels = 0x9F,
+/* ChannelPositions = 0x7D7B, */
+  BitDepth = 0x6264,
+  /* end audio */
+  /* content encoding */
+/* ContentEncodings = 0x6d80, */
+/* ContentEncoding = 0x6240, */
+/* ContentEncodingOrder = 0x5031, */
+/* ContentEncodingScope = 0x5032, */
+/* ContentEncodingType = 0x5033, */
+/* ContentCompression = 0x5034, */
+/* ContentCompAlgo = 0x4254, */
+/* ContentCompSettings = 0x4255, */
+/* ContentEncryption = 0x5035, */
+/* ContentEncAlgo = 0x47e1, */
+/* ContentEncKeyID = 0x47e2, */
+/* ContentSignature = 0x47e3, */
+/* ContentSigKeyID = 0x47e4, */
+/* ContentSigAlgo = 0x47e5, */
+/* ContentSigHashAlgo = 0x47e6, */
+  /* end content encoding */
+  /* Cueing Data */
+  Cues = 0x1C53BB6B,
+  CuePoint = 0xBB,
+  CueTime = 0xB3,
+  CueTrackPositions = 0xB7,
+  CueTrack = 0xF7,
+  CueClusterPosition = 0xF1,
+  CueBlockNumber = 0x5378
+/* CueCodecState = 0xEA, */
+/* CueReference = 0xDB, */
+/* CueRefTime = 0x96, */
+/* CueRefCluster = 0x97, */
+/* CueRefNumber = 0x535F, */
+/* CueRefCodecState = 0xEB, */
+  /* Attachment */
+/* Attachments = 0x1941A469, */
+/* AttachedFile = 0x61A7, */
+/* FileDescription = 0x467E, */
+/* FileName = 0x466E, */
+/* FileMimeType = 0x4660, */
+/* FileData = 0x465C, */
+/* FileUID = 0x46AE, */
+/* FileReferral = 0x4675, */
+  /* Chapters */
+/* Chapters = 0x1043A770, */
+/* EditionEntry = 0x45B9, */
+/* EditionUID = 0x45BC, */
+/* EditionFlagHidden = 0x45BD, */
+/* EditionFlagDefault = 0x45DB, */
+/* EditionFlagOrdered = 0x45DD, */
+/* ChapterAtom = 0xB6, */
+/* ChapterUID = 0x73C4, */
+/* ChapterTimeStart = 0x91, */
+/* ChapterTimeEnd = 0x92, */
+/* ChapterFlagHidden = 0x98, */
+/* ChapterFlagEnabled = 0x4598, */
+/* ChapterSegmentUID = 0x6E67, */
+/* ChapterSegmentEditionUID = 0x6EBC, */
+/* ChapterPhysicalEquiv = 0x63C3, */
+/* ChapterTrack = 0x8F, */
+/* ChapterTrackNumber = 0x89, */
+/* ChapterDisplay = 0x80, */
+/* ChapString = 0x85, */
+/* ChapLanguage = 0x437C, */
+/* ChapCountry = 0x437E, */
+/* ChapProcess = 0x6944, */
+/* ChapProcessCodecID = 0x6955, */
+/* ChapProcessPrivate = 0x450D, */
+/* ChapProcessCommand = 0x6911, */
+/* ChapProcessTime = 0x6922, */
+/* ChapProcessData = 0x6933, */
+  /* Tagging */
+/* Tags = 0x1254C367, */
+/* Tag = 0x7373, */
+/* Targets = 0x63C0, */
+/* TargetTypeValue = 0x68CA, */
+/* TargetType = 0x63CA, */
+/* Tagging_TrackUID = 0x63C5, */
+/* Tagging_EditionUID = 0x63C9, */
+/* Tagging_ChapterUID = 0x63C4, */
+/* AttachmentUID = 0x63C6, */
+/* SimpleTag = 0x67C8, */
+/* TagName = 0x45A3, */
+/* TagLanguage = 0x447A, */
+/* TagDefault = 0x4484, */
+/* TagString = 0x4487, */
+/* TagBinary = 0x4485, */
+};
+#endif
new file mode 100644
--- /dev/null
+++ b/media/libmkv/EbmlWriter.c
@@ -0,0 +1,165 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "EbmlWriter.h"
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+#include <limits.h>
+#include "EbmlBufferWriter.h"
+#if defined(_MSC_VER)
+#define LITERALU64(n) n
+#else
+#define LITERALU64(n) n##LLU
+#endif
+
+void Ebml_WriteLen(EbmlGlobal *glob, int64_t val) {
+  /* TODO check and make sure we are not > than 0x0100000000000000LLU */
+  unsigned char size = 8; /* size in bytes to output */
+
+  /* mask to compare for byte size */
+  int64_t minVal = 0xff;
+
+  for (size = 1; size < 8; size ++) {
+    if (val < minVal)
+      break;
+
+    minVal = (minVal << 7);
+  }
+
+  val |= (((uint64_t)0x80) << ((size - 1) * 7));
+
+  Ebml_Serialize(glob, (void *) &val, sizeof(val), size);
+}
+
+void Ebml_WriteString(EbmlGlobal *glob, const char *str) {
+  const size_t size_ = strlen(str);
+  const uint64_t  size = size_;
+  Ebml_WriteLen(glob, size);
+  /* TODO: it's not clear from the spec whether the nul terminator
+   * should be serialized too.  For now we omit the null terminator.
+   */
+  Ebml_Write(glob, str, (unsigned long)size);
+}
+
+void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr) {
+  const size_t strlen = wcslen(wstr);
+
+  /* TODO: it's not clear from the spec whether the nul terminator
+   * should be serialized too.  For now we include it.
+   */
+  const uint64_t  size = strlen;
+
+  Ebml_WriteLen(glob, size);
+  Ebml_Write(glob, wstr, (unsigned long)size);
+}
+
+void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id) {
+  int len;
+
+  if (class_id >= 0x01000000)
+    len = 4;
+  else if (class_id >= 0x00010000)
+    len = 3;
+  else if (class_id >= 0x00000100)
+    len = 2;
+  else
+    len = 1;
+
+  Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len);
+}
+
+void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint32_t ui) {
+  unsigned char sizeSerialized = 8 | 0x80;
+  Ebml_WriteID(glob, class_id);
+  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
+  Ebml_Serialize(glob, &ui, sizeof(ui), 4);
+}
+
+void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) {
+  unsigned char sizeSerialized = 8 | 0x80;
+  Ebml_WriteID(glob, class_id);
+  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
+  Ebml_Serialize(glob, &ui, sizeof(ui), 8);
+}
+
+void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui) {
+  unsigned char size = 8; /* size in bytes to output */
+  unsigned char sizeSerialized = 0;
+  unsigned long minVal;
+
+  Ebml_WriteID(glob, class_id);
+  minVal = 0x7fLU; /* mask to compare for byte size */
+
+  for (size = 1; size < 4; size ++) {
+    if (ui < minVal) {
+      break;
+    }
+
+    minVal <<= 7;
+  }
+
+  sizeSerialized = 0x80 | size;
+  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
+  Ebml_Serialize(glob, &ui, sizeof(ui), size);
+}
+/* TODO: perhaps this is a poor name for this id serializer helper function */
+void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long bin) {
+  int size;
+  for (size = 4; size > 1; size--) {
+    if (bin & (unsigned int)0x000000ff << ((size - 1) * 8))
+      break;
+  }
+  Ebml_WriteID(glob, class_id);
+  Ebml_WriteLen(glob, size);
+  Ebml_WriteID(glob, bin);
+}
+
+void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d) {
+  unsigned char len = 0x88;
+
+  Ebml_WriteID(glob, class_id);
+  Ebml_Serialize(glob, &len, sizeof(len), 1);
+  Ebml_Serialize(glob,  &d, sizeof(d), 8);
+}
+
+void Ebml_WriteSigned16(EbmlGlobal *glob, short val) {
+  signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8;
+  Ebml_Serialize(glob, &out, sizeof(out), 3);
+}
+
+void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s) {
+  Ebml_WriteID(glob, class_id);
+  Ebml_WriteString(glob, s);
+}
+
+void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s) {
+  Ebml_WriteID(glob,  class_id);
+  Ebml_WriteUTF8(glob,  s);
+}
+
+void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length) {
+  Ebml_WriteID(glob, class_id);
+  Ebml_WriteLen(glob, data_length);
+  Ebml_Write(glob,  data, data_length);
+}
+
+void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize) {
+  unsigned char tmp = 0;
+  unsigned long i = 0;
+
+  Ebml_WriteID(glob, 0xEC);
+  Ebml_WriteLen(glob, vSize);
+
+  for (i = 0; i < vSize; i++) {
+    Ebml_Write(glob, &tmp, 1);
+  }
+}
+
+/* TODO Serialize Date */
new file mode 100644
--- /dev/null
+++ b/media/libmkv/EbmlWriter.h
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef EBMLWRITER_HPP
+#define EBMLWRITER_HPP
+#include <stddef.h>
+#include "vpx/vpx_integer.h"
+#include "EbmlBufferWriter.h"
+
+/* note: you must define write and serialize functions as well as your own
+ * EBML_GLOBAL
+ *
+ * These functions MUST be implemented
+ */
+
+// typedef struct EbmlGlobal EbmlGlobal;
+// void  Ebml_Serialize(EbmlGlobal *glob, const void *, int, unsigned long);
+// void  Ebml_Write(EbmlGlobal *glob, const void *, unsigned long);
+
+/*****/
+
+void Ebml_WriteLen(EbmlGlobal *glob, int64_t val);
+void Ebml_WriteString(EbmlGlobal *glob, const char *str);
+void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr);
+void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id);
+void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint32_t ui);
+void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui);
+void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
+void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
+void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d);
+/* TODO make this more generic to signed */
+void Ebml_WriteSigned16(EbmlGlobal *glob, short val);
+void Ebml_SerializeString(EbmlGlobal *glob, unsigned long class_id, const char *s);
+void Ebml_SerializeUTF8(EbmlGlobal *glob, unsigned long class_id, wchar_t *s);
+void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char *data, unsigned long data_length);
+void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize);
+/* TODO need date function */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
new file mode 100644
--- /dev/null
+++ b/media/libmkv/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2010, The WebM Project authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  * Neither the name of Google, nor the WebM Project, nor the names
+    of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written
+    permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
new file mode 100644
--- /dev/null
+++ b/media/libmkv/README
@@ -0,0 +1,139 @@
+vpx Multi-Format Codec SDK
+README - 1 August 2013
+
+Welcome to the WebM VP8/VP9 Codec SDK!
+
+COMPILING THE APPLICATIONS/LIBRARIES:
+  The build system used is similar to autotools. Building generally consists of
+  "configuring" with your desired build options, then using GNU make to build
+  the application.
+
+  1. Prerequisites
+
+    * All x86 targets require the Yasm[1] assembler be installed.
+    * All Windows builds require that Cygwin[2] be installed.
+    * Building the documentation requires PHP[3] and Doxygen[4]. If you do not
+      have these packages, you must pass --disable-install-docs to the
+      configure script.
+    * Downloading the data for the unit tests requires curl[5] and sha1sum.
+      sha1sum is provided via the GNU coreutils, installed by default on
+      many *nix platforms, as well as MinGW and Cygwin. If coreutils is not
+      available, a compatible version of sha1sum can be built from
+      source[6]. These requirements are optional if not running the unit
+      tests.
+
+    [1]: http://www.tortall.net/projects/yasm
+    [2]: http://www.cygwin.com
+    [3]: http://php.net
+    [4]: http://www.doxygen.org
+    [5]: http://curl.haxx.se
+    [6]: http://www.microbrew.org/tools/md5sha1sum/
+
+  2. Out-of-tree builds
+  Out of tree builds are a supported method of building the application. For
+  an out of tree build, the source tree is kept separate from the object
+  files produced during compilation. For instance:
+
+    $ mkdir build
+    $ cd build
+    $ ../libvpx/configure <options>
+    $ make
+
+  3. Configuration options
+  The 'configure' script supports a number of options. The --help option can be
+  used to get a list of supported options:
+    $ ../libvpx/configure --help
+
+  4. Cross development
+  For cross development, the most notable option is the --target option. The
+  most up-to-date list of supported targets can be found at the bottom of the
+  --help output of the configure script. As of this writing, the list of
+  available targets is:
+
+    armv5te-android-gcc
+    armv5te-linux-rvct
+    armv5te-linux-gcc
+    armv5te-none-rvct
+    armv6-darwin-gcc
+    armv6-linux-rvct
+    armv6-linux-gcc
+    armv6-none-rvct
+    armv7-android-gcc
+    armv7-darwin-gcc
+    armv7-linux-rvct
+    armv7-linux-gcc
+    armv7-none-rvct
+    armv7-win32-vs11
+    armv7-win32-vs12
+    mips32-linux-gcc
+    ppc32-darwin8-gcc
+    ppc32-darwin9-gcc
+    ppc32-linux-gcc
+    ppc64-darwin8-gcc
+    ppc64-darwin9-gcc
+    ppc64-linux-gcc
+    sparc-solaris-gcc
+    x86-android-gcc
+    x86-darwin8-gcc
+    x86-darwin8-icc
+    x86-darwin9-gcc
+    x86-darwin9-icc
+    x86-darwin10-gcc
+    x86-darwin11-gcc
+    x86-darwin12-gcc
+    x86-darwin13-gcc
+    x86-linux-gcc
+    x86-linux-icc
+    x86-os2-gcc
+    x86-solaris-gcc
+    x86-win32-gcc
+    x86-win32-vs7
+    x86-win32-vs8
+    x86-win32-vs9
+    x86-win32-vs10
+    x86-win32-vs11
+    x86-win32-vs12
+    x86_64-darwin9-gcc
+    x86_64-darwin10-gcc
+    x86_64-darwin11-gcc
+    x86_64-darwin12-gcc
+    x86_64-darwin13-gcc
+    x86_64-linux-gcc
+    x86_64-linux-icc
+    x86_64-solaris-gcc
+    x86_64-win64-gcc
+    x86_64-win64-vs8
+    x86_64-win64-vs9
+    x86_64-win64-vs10
+    x86_64-win64-vs11
+    x86_64-win64-vs12
+    universal-darwin8-gcc
+    universal-darwin9-gcc
+    universal-darwin10-gcc
+    universal-darwin11-gcc
+    universal-darwin12-gcc
+    universal-darwin13-gcc
+    generic-gnu
+
+  The generic-gnu target, in conjunction with the CROSS environment variable,
+  can be used to cross compile architectures that aren't explicitly listed, if
+  the toolchain is a cross GNU (gcc/binutils) toolchain. Other POSIX toolchains
+  will likely work as well. For instance, to build using the mipsel-linux-uclibc
+  toolchain, the following command could be used (note, POSIX SH syntax, adapt
+  to your shell as necessary):
+
+    $ CROSS=mipsel-linux-uclibc- ../libvpx/configure
+
+  In addition, the executables to be invoked can be overridden by specifying the
+  environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be
+  passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS.
+
+  5. Configuration errors
+  If the configuration step fails, the first step is to look in the error log.
+  This defaults to config.log. This should give a good indication of what went
+  wrong. If not, contact us for support.
+
+SUPPORT
+  This library is an open source project supported by its community. Please
+  please email webm-discuss@webmproject.org for help.
+
new file mode 100644
--- /dev/null
+++ b/media/libmkv/README_MOZILLA
@@ -0,0 +1,6 @@
+The source from this directory was copied from the libvpx/third_party/libmkv
+git repository using the update.sh script.
+
+The libvpx git repository is: http://git.chromium.org/webm/libvpx.git
+
+The git commit ID used was c5aaf923d80e9f71e0c93d7d99dc1e2f83d7acbf.
new file mode 100644
--- /dev/null
+++ b/media/libmkv/WebMElement.c
@@ -0,0 +1,219 @@
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS.  All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#include "EbmlIDs.h"
+#include "WebMElement.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define kVorbisPrivateMaxSize  4000
+#define UInt64 uint64_t
+
+void writeHeader(EbmlGlobal *glob) {
+  EbmlLoc start;
+  Ebml_StartSubElement(glob, &start, EBML);
+  Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
+  Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); // EBML Read Version
+  Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); // EBML Max ID Length
+  Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); // EBML Max Size Length
+  Ebml_SerializeString(glob, DocType, "webm"); // Doc Type
+  Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); // Doc Type Version
+  Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); // Doc Type Read Version
+  Ebml_EndSubElement(glob, &start);
+}
+
+void writeSimpleBlock(EbmlGlobal *glob, unsigned char trackNumber, short timeCode,
+                      int isKeyframe, unsigned char lacingFlag, int discardable,
+                      unsigned char *data, unsigned long dataLength) {
+  unsigned long blockLength = 4 + dataLength;
+  unsigned char flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable;
+  Ebml_WriteID(glob, SimpleBlock);
+  blockLength |= 0x10000000; // TODO check length < 0x0FFFFFFFF
+  Ebml_Serialize(glob, &blockLength, sizeof(blockLength), 4);
+  trackNumber |= 0x80;  // TODO check track nubmer < 128
+  Ebml_Write(glob, &trackNumber, 1);
+  // Ebml_WriteSigned16(glob, timeCode,2); //this is 3 bytes
+  Ebml_Serialize(glob, &timeCode, sizeof(timeCode), 2);
+  flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable;
+  Ebml_Write(glob, &flags, 1);
+  Ebml_Write(glob, data, dataLength);
+}
+
+static UInt64 generateTrackID(unsigned int trackNumber) {
+  UInt64 t = time(NULL) * trackNumber;
+  UInt64 r = rand();
+  r = r << 32;
+  r +=  rand();
+//  UInt64 rval = t ^ r;
+  return t ^ r;
+}
+
+void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                     char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+                     double frameRate) {
+  EbmlLoc start;
+  UInt64 trackID;
+  Ebml_StartSubElement(glob, &start, TrackEntry);
+  Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
+  trackID = generateTrackID(trackNumber);
+  Ebml_SerializeUnsigned(glob, TrackUID, trackID);
+  Ebml_SerializeString(glob, CodecName, "VP8");  // TODO shouldn't be fixed
+
+  Ebml_SerializeUnsigned(glob, TrackType, 1); // video is always 1
+  Ebml_SerializeString(glob, CodecID, codecId);
+  {
+    EbmlLoc videoStart;
+    Ebml_StartSubElement(glob, &videoStart, Video);
+    Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
+    Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
+    Ebml_SerializeFloat(glob, FrameRate, frameRate);
+    Ebml_EndSubElement(glob, &videoStart); // Video
+  }
+  Ebml_EndSubElement(glob, &start); // Track Entry
+}
+void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                     char *codecId, double samplingFrequency, unsigned int channels,
+                     unsigned char *private, unsigned long privateSize) {
+  EbmlLoc start;
+  UInt64 trackID;
+  Ebml_StartSubElement(glob, &start, TrackEntry);
+  Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
+  trackID = generateTrackID(trackNumber);
+  Ebml_SerializeUnsigned(glob, TrackUID, trackID);
+  Ebml_SerializeUnsigned(glob, TrackType, 2); // audio is always 2
+  // I am using defaults for thesed required fields
+  /*  Ebml_SerializeUnsigned(glob, FlagEnabled, 1);
+      Ebml_SerializeUnsigned(glob, FlagDefault, 1);
+      Ebml_SerializeUnsigned(glob, FlagForced, 1);
+      Ebml_SerializeUnsigned(glob, FlagLacing, flagLacing);*/
+  Ebml_SerializeString(glob, CodecID, codecId);
+  Ebml_SerializeData(glob, CodecPrivate, private, privateSize);
+
+  Ebml_SerializeString(glob, CodecName, "VORBIS");  // fixed for now
+  {
+    EbmlLoc AudioStart;
+    Ebml_StartSubElement(glob, &AudioStart, Audio);
+    Ebml_SerializeFloat(glob, SamplingFrequency, samplingFrequency);
+    Ebml_SerializeUnsigned(glob, Channels, channels);
+    Ebml_EndSubElement(glob, &AudioStart);
+  }
+  Ebml_EndSubElement(glob, &start);
+}
+void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo, unsigned long timeCodeScale, double duration) {
+  Ebml_StartSubElement(ebml, startInfo, Info);
+  Ebml_SerializeUnsigned(ebml, TimecodeScale, timeCodeScale);
+  Ebml_SerializeFloat(ebml, Segment_Duration, duration * 1000.0); // Currently fixed to using milliseconds
+  Ebml_SerializeString(ebml, 0x4D80, "QTmuxingAppLibWebM-0.0.1");
+  Ebml_SerializeString(ebml, 0x5741, "QTwritingAppLibWebM-0.0.1");
+  Ebml_EndSubElement(ebml, startInfo);
+}
+
+/*
+void Mkv_InitializeSegment(Ebml& ebml_out, EbmlLoc& ebmlLoc)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x18538067);
+}
+
+void Mkv_InitializeSeek(Ebml& ebml_out, EbmlLoc& ebmlLoc)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x114d9b74);
+}
+void Mkv_WriteSeekInformation(Ebml& ebml_out, SeekStruct& seekInformation)
+{
+    EbmlLoc ebmlLoc;
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x4dbb);
+    Ebml_SerializeString(ebml_out, 0x53ab, seekInformation.SeekID);
+    Ebml_SerializeUnsigned(ebml_out, 0x53ac, seekInformation.SeekPosition);
+    Ebml_EndSubElement(ebml_out, ebmlLoc);
+}
+
+void Mkv_WriteSegmentInformation(Ebml& ebml_out, SegmentInformationStruct& segmentInformation)
+{
+    Ebml_SerializeUnsigned(ebml_out, 0x73a4, segmentInformation.segmentUID);
+    if (segmentInformation.filename != 0)
+        Ebml_SerializeString(ebml_out, 0x7384, segmentInformation.filename);
+    Ebml_SerializeUnsigned(ebml_out, 0x2AD7B1, segmentInformation.TimecodeScale);
+    Ebml_SerializeUnsigned(ebml_out, 0x4489, segmentInformation.Duration);
+    // TODO date
+    Ebml_SerializeWString(ebml_out, 0x4D80, L"MKVMUX");
+    Ebml_SerializeWString(ebml_out, 0x5741, segmentInformation.WritingApp);
+}
+
+void Mkv_InitializeTrack(Ebml& ebml_out, EbmlLoc& ebmlLoc)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x1654AE6B);
+}
+
+static void Mkv_WriteGenericTrackData(Ebml& ebml_out, TrackStruct& track)
+{
+    Ebml_SerializeUnsigned(ebml_out, 0xD7, track.TrackNumber);
+    Ebml_SerializeUnsigned(ebml_out, 0x73C5, track.TrackUID);
+    Ebml_SerializeUnsigned(ebml_out, 0x83, track.TrackType);
+    Ebml_SerializeUnsigned(ebml_out, 0xB9, track.FlagEnabled ? 1 :0);
+    Ebml_SerializeUnsigned(ebml_out, 0x88, track.FlagDefault ? 1 :0);
+    Ebml_SerializeUnsigned(ebml_out, 0x55AA, track.FlagForced ? 1 :0);
+    if (track.Language != 0)
+        Ebml_SerializeString(ebml_out, 0x22B59C, track.Language);
+    if (track.CodecID != 0)
+        Ebml_SerializeString(ebml_out, 0x86, track.CodecID);
+    if (track.CodecPrivate != 0)
+        Ebml_SerializeData(ebml_out, 0x63A2, track.CodecPrivate, track.CodecPrivateLength);
+    if (track.CodecName != 0)
+        Ebml_SerializeWString(ebml_out, 0x258688, track.CodecName);
+}
+
+void Mkv_WriteVideoTrack(Ebml& ebml_out, TrackStruct & track, VideoTrackStruct& video)
+{
+    EbmlLoc trackHeadLoc, videoHeadLoc;
+    Ebml_StartSubElement(ebml_out, trackHeadLoc, 0xAE);  // start Track
+    Mkv_WriteGenericTrackData(ebml_out, track);
+    Ebml_StartSubElement(ebml_out, videoHeadLoc, 0xE0);  // start Video
+    Ebml_SerializeUnsigned(ebml_out, 0x9A, video.FlagInterlaced ? 1 :0);
+    Ebml_SerializeUnsigned(ebml_out, 0xB0, video.PixelWidth);
+    Ebml_SerializeUnsigned(ebml_out, 0xBA, video.PixelHeight);
+    Ebml_SerializeUnsigned(ebml_out, 0x54B0, video.PixelDisplayWidth);
+    Ebml_SerializeUnsigned(ebml_out, 0x54BA, video.PixelDisplayHeight);
+    Ebml_SerializeUnsigned(ebml_out, 0x54B2, video.displayUnit);
+    Ebml_SerializeFloat(ebml_out, 0x2383E3, video.FrameRate);
+    Ebml_EndSubElement(ebml_out, videoHeadLoc);
+    Ebml_EndSubElement(ebml_out, trackHeadLoc);
+
+}
+
+void Mkv_WriteAudioTrack(Ebml& ebml_out, TrackStruct & track, AudioTrackStruct& video)
+{
+    EbmlLoc trackHeadLoc, audioHeadLoc;
+    Ebml_StartSubElement(ebml_out, trackHeadLoc, 0xAE);
+    Mkv_WriteGenericTrackData(ebml_out, track);
+    Ebml_StartSubElement(ebml_out, audioHeadLoc, 0xE0);  // start Audio
+    Ebml_SerializeFloat(ebml_out, 0xB5, video.SamplingFrequency);
+    Ebml_SerializeUnsigned(ebml_out, 0x9F, video.Channels);
+    Ebml_SerializeUnsigned(ebml_out, 0x6264, video.BitDepth);
+    Ebml_EndSubElement(ebml_out, audioHeadLoc); // end audio
+    Ebml_EndSubElement(ebml_out, trackHeadLoc);
+}
+
+void Mkv_WriteEbmlClusterHead(Ebml& ebml_out,  EbmlLoc& ebmlLoc, ClusterHeadStruct & clusterHead)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0x1F43B675);
+    Ebml_SerializeUnsigned(ebml_out, 0x6264, clusterHead.TimeCode);
+}
+
+void Mkv_WriteSimpleBlockHead(Ebml& ebml_out,  EbmlLoc& ebmlLoc, SimpleBlockStruct& block)
+{
+    Ebml_StartSubElement(ebml_out, ebmlLoc, 0xA3);
+    Ebml_Write1UInt(ebml_out, block.TrackNumber);
+    Ebml_WriteSigned16(ebml_out,block.TimeCode);
+    unsigned char flags = 0x00 | (block.iskey ? 0x80:0x00) | (block.lacing << 1) | block.discardable;
+    Ebml_Write1UInt(ebml_out, flags);  // TODO this may be the wrong function
+    Ebml_Serialize(ebml_out, block.data, block.dataLength);
+    Ebml_EndSubElement(ebml_out,ebmlLoc);
+}
+*/
new file mode 100644
--- /dev/null
+++ b/media/libmkv/WebMElement.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+//
+// Use of this source code is governed by a BSD-style license
+// that can be found in the LICENSE file in the root of the source
+// tree. An additional intellectual property rights grant can be found
+// in the file PATENTS.  All contributing project authors may
+// be found in the AUTHORS file in the root of the source tree.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MKV_CONTEXT_HPP
+#define MKV_CONTEXT_HPP 1
+
+#include "EbmlWriter.h"
+
+// these are helper functions
+void writeHeader(EbmlGlobal *ebml);
+void writeSegmentInformation(EbmlGlobal *ebml, EbmlLoc *startInfo, unsigned long timeCodeScale, double duration);
+// this function is a helper only, it assumes a lot of defaults
+void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
+                     char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+                     double frameRate);
+void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                     char *codecId, double samplingFrequency, unsigned int channels,
+                     unsigned char *private_, unsigned long privateSize);
+
+void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber, short timeCode,
+                      int isKeyframe, unsigned char lacingFlag, int discardable,
+                      unsigned char *data, unsigned long dataLength);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
new file mode 100644
--- /dev/null
+++ b/media/libmkv/gecko_fix.patch
@@ -0,0 +1,133 @@
+diff --git a/EbmlBufferWriter.h b/EbmlBufferWriter.h
+index c135f29..d5116ce 100644
+--- a/EbmlBufferWriter.h
++++ b/EbmlBufferWriter.h
+@@ -11,6 +11,9 @@ typedef struct {
+   unsigned int offset;
+ } EbmlGlobal;
+ 
++void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len);
++void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in,
++                    int buffer_size, unsigned long len);
+ void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id);
+ void Ebml_EndSubElement(EbmlGlobal *glob,  EbmlLoc *ebmlLoc);
+ 
+diff --git a/EbmlIDs.h b/EbmlIDs.h
+index 44d4385..3b5da19 100644
+--- a/EbmlIDs.h
++++ b/EbmlIDs.h
+@@ -119,7 +119,7 @@ enum mkv {
+   /* video */
+   Video = 0xE0,
+   FlagInterlaced = 0x9A,
+-  StereoMode = 0x53B8,
++  WEBM_StereoMode = 0x53B8,
+   AlphaMode = 0x53C0,
+   PixelWidth = 0xB0,
+   PixelHeight = 0xBA,
+diff --git a/EbmlWriter.c b/EbmlWriter.c
+index ebefc1a..087e817 100644
+--- a/EbmlWriter.c
++++ b/EbmlWriter.c
+@@ -12,6 +12,7 @@
+ #include <wchar.h>
+ #include <string.h>
+ #include <limits.h>
++#include "EbmlBufferWriter.h"
+ #if defined(_MSC_VER)
+ #define LITERALU64(n) n
+ #else
+diff --git a/EbmlWriter.h b/EbmlWriter.h
+index a0a848b..3aee2b3 100644
+--- a/EbmlWriter.h
++++ b/EbmlWriter.h
+@@ -7,10 +7,16 @@
+  *  in the file PATENTS.  All contributing project authors may
+  *  be found in the AUTHORS file in the root of the source tree.
+  */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
+ #ifndef EBMLWRITER_HPP
+ #define EBMLWRITER_HPP
+ #include <stddef.h>
+ #include "vpx/vpx_integer.h"
++#include "EbmlBufferWriter.h"
+ 
+ /* note: you must define write and serialize functions as well as your own
+  * EBML_GLOBAL
+@@ -18,9 +24,9 @@
+  * These functions MUST be implemented
+  */
+ 
+-typedef struct EbmlGlobal EbmlGlobal;
+-void  Ebml_Serialize(EbmlGlobal *glob, const void *, int, unsigned long);
+-void  Ebml_Write(EbmlGlobal *glob, const void *, unsigned long);
++// typedef struct EbmlGlobal EbmlGlobal;
++// void  Ebml_Serialize(EbmlGlobal *glob, const void *, int, unsigned long);
++// void  Ebml_Write(EbmlGlobal *glob, const void *, unsigned long);
+ 
+ /*****/
+ 
+@@ -41,3 +47,7 @@ void Ebml_SerializeData(EbmlGlobal *glob, unsigned long class_id, unsigned char
+ void Ebml_WriteVoid(EbmlGlobal *glob, unsigned long vSize);
+ /* TODO need date function */
+ #endif
++
++#ifdef __cplusplus
++}
++#endif
+diff --git a/WebMElement.c b/WebMElement.c
+index 02eefa4..0d5056d 100644
+--- a/WebMElement.c
++++ b/WebMElement.c
+@@ -6,8 +6,6 @@
+ // in the file PATENTS.  All contributing project authors may
+ // be found in the AUTHORS file in the root of the source tree.
+ 
+-
+-#include "EbmlBufferWriter.h"
+ #include "EbmlIDs.h"
+ #include "WebMElement.h"
+ #include <stdio.h>
+diff --git a/WebMElement.h b/WebMElement.h
+index d9ad0a0..987582a 100644
+--- a/WebMElement.h
++++ b/WebMElement.h
+@@ -6,10 +6,15 @@
+ // in the file PATENTS.  All contributing project authors may
+ // be found in the AUTHORS file in the root of the source tree.
+ 
++#ifdef __cplusplus
++extern "C" {
++#endif
+ 
+ #ifndef MKV_CONTEXT_HPP
+ #define MKV_CONTEXT_HPP 1
+ 
++#include "EbmlWriter.h"
++
+ void writeSimpleBock(EbmlGlobal *ebml, unsigned char trackNumber, unsigned short timeCode,
+                      int isKeyframe, unsigned char lacingFlag, int  discardable,
+                      unsigned char *data, unsigned long dataLength);
+@@ -24,12 +29,14 @@ void writeVideoTrack(EbmlGlobal *ebml, unsigned int trackNumber, int flagLacing,
+                      double frameRate);
+ void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                      char *codecId, double samplingFrequency, unsigned int channels,
+-                     unsigned char *private, unsigned long privateSize);
++                     unsigned char *private_, unsigned long privateSize);
+ 
+ void writeSimpleBlock(EbmlGlobal *ebml, unsigned char trackNumber, short timeCode,
+                       int isKeyframe, unsigned char lacingFlag, int discardable,
+                       unsigned char *data, unsigned long dataLength);
+ 
++#endif
+ 
+-
+-#endif
+\ No newline at end of file
++#ifdef __cplusplus
++}
++#endif
new file mode 100644
--- /dev/null
+++ b/media/libmkv/moz.build
@@ -0,0 +1,27 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXPORTS.libmkv += [
+    'EbmlBufferWriter.h',
+    'EbmlIDs.h',
+    'EbmlWriter.h',
+    'WebMElement.h',
+]
+
+UNIFIED_SOURCES += [
+]
+
+# These files can't be unified because of function redefinitions.
+SOURCES += [
+    'EbmlBufferWriter.c',
+    'EbmlWriter.c',
+    'WebMElement.c',
+]
+
+if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
+    NO_VISIBILITY_FLAGS = True
+
+FINAL_LIBRARY = 'gkmedias'
new file mode 100644
--- /dev/null
+++ b/media/libmkv/source_fix.patch
@@ -0,0 +1,193 @@
+diff --git a/EbmlBufferWriter.c b/EbmlBufferWriter.c
+index 574e478..8c26e80 100644
+--- a/EbmlBufferWriter.c
++++ b/EbmlBufferWriter.c
+@@ -8,6 +8,31 @@
+ #include <wchar.h>
+ #include <string.h>
+ 
++void
++Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, int buffer_size, unsigned long len)
++{
++  /* buffer_size:
++   * 1 - int8_t;
++   * 2 - int16_t;
++   * 3 - int32_t;
++   * 4 - int64_t;
++   */
++  long i;
++  for(i = len-1; i >= 0; i--) {
++    unsigned char x;
++    if (buffer_size == 1) {
++      x = (char)(*(const int8_t *)buffer_in >> (i * 8));
++	} else if (buffer_size == 2) {
++      x = (char)(*(const int16_t *)buffer_in >> (i * 8));
++	} else if (buffer_size == 4) {
++      x = (char)(*(const int32_t *)buffer_in >> (i * 8));
++	} else if (buffer_size == 8) {
++      x = (char)(*(const int64_t *)buffer_in >> (i * 8));
++	}
++    Ebml_Write(glob, &x, 1);
++  }
++}
++
+ void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len) {
+   unsigned char *src = glob->buf;
+   src += glob->offset;
+@@ -19,12 +44,12 @@ static void _Serialize(EbmlGlobal *glob, const unsigned char *p, const unsigned
+   while (q != p) {
+     --q;
+ 
+-    unsigned long cbWritten;
+     memcpy(&(glob->buf[glob->offset]), q, 1);
+     glob->offset++;
+   }
+ }
+ 
++/*
+ void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, unsigned long len) {
+   // assert(buf);
+ 
+@@ -33,22 +58,22 @@ void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
+ 
+   _Serialize(glob, p, q);
+ }
+-
++*/
+ 
+ void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id) {
++  unsigned long long unknownLen = 0x01FFFFFFFFFFFFFFLL;
+   Ebml_WriteID(glob, class_id);
+   ebmlLoc->offset = glob->offset;
+   // todo this is always taking 8 bytes, this may need later optimization
+-  unsigned long long unknownLen =  0x01FFFFFFFFFFFFFFLLU;
+-  Ebml_Serialize(glob, (void *)&unknownLen, 8); // this is a key that says lenght unknown
++  Ebml_Serialize(glob, (void *)&unknownLen,sizeof(unknownLen), 8); // this is a key that says lenght unknown
+ }
+ 
+ void Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc) {
+   unsigned long long size = glob->offset - ebmlLoc->offset - 8;
+   unsigned long long curOffset = glob->offset;
+   glob->offset = ebmlLoc->offset;
+-  size |=  0x0100000000000000LLU;
+-  Ebml_Serialize(glob, &size, 8);
++  size |=  0x0100000000000000LL;
++  Ebml_Serialize(glob, &size,sizeof(size), 8);
+   glob->offset = curOffset;
+ }
+ 
+diff --git a/EbmlBufferWriter.h b/EbmlBufferWriter.h
+index acd5c2a..c135f29 100644
+--- a/EbmlBufferWriter.h
++++ b/EbmlBufferWriter.h
+@@ -11,9 +11,7 @@ typedef struct {
+   unsigned int offset;
+ } EbmlGlobal;
+ 
+-
+ void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id);
+ void Ebml_EndSubElement(EbmlGlobal *glob,  EbmlLoc *ebmlLoc);
+ 
+-
+ #endif
+diff --git a/EbmlWriter.c b/EbmlWriter.c
+index 27cfe86..ebefc1a 100644
+--- a/EbmlWriter.c
++++ b/EbmlWriter.c
+@@ -74,6 +74,13 @@ void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id) {
+   Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len);
+ }
+ 
++void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint32_t ui) {
++  unsigned char sizeSerialized = 8 | 0x80;
++  Ebml_WriteID(glob, class_id);
++  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
++  Ebml_Serialize(glob, &ui, sizeof(ui), 4);
++}
++
+ void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui) {
+   unsigned char sizeSerialized = 8 | 0x80;
+   Ebml_WriteID(glob, class_id);
+diff --git a/EbmlWriter.h b/EbmlWriter.h
+index b94f757..a0a848b 100644
+--- a/EbmlWriter.h
++++ b/EbmlWriter.h
+@@ -28,6 +28,7 @@ void Ebml_WriteLen(EbmlGlobal *glob, int64_t val);
+ void Ebml_WriteString(EbmlGlobal *glob, const char *str);
+ void Ebml_WriteUTF8(EbmlGlobal *glob, const wchar_t *wstr);
+ void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id);
++void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint32_t ui);
+ void Ebml_SerializeUnsigned64(EbmlGlobal *glob, unsigned long class_id, uint64_t ui);
+ void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
+ void Ebml_SerializeBinary(EbmlGlobal *glob, unsigned long class_id, unsigned long ui);
+diff --git a/WebMElement.c b/WebMElement.c
+index 2f79a3c..02eefa4 100644
+--- a/WebMElement.c
++++ b/WebMElement.c
+@@ -11,8 +11,12 @@
+ #include "EbmlIDs.h"
+ #include "WebMElement.h"
+ #include <stdio.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <time.h>
+ 
+ #define kVorbisPrivateMaxSize  4000
++#define UInt64 uint64_t
+ 
+ void writeHeader(EbmlGlobal *glob) {
+   EbmlLoc start;
+@@ -30,15 +34,16 @@ void writeHeader(EbmlGlobal *glob) {
+ void writeSimpleBlock(EbmlGlobal *glob, unsigned char trackNumber, short timeCode,
+                       int isKeyframe, unsigned char lacingFlag, int discardable,
+                       unsigned char *data, unsigned long dataLength) {
+-  Ebml_WriteID(glob, SimpleBlock);
+   unsigned long blockLength = 4 + dataLength;
++  unsigned char flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable;
++  Ebml_WriteID(glob, SimpleBlock);
+   blockLength |= 0x10000000; // TODO check length < 0x0FFFFFFFF
+   Ebml_Serialize(glob, &blockLength, sizeof(blockLength), 4);
+   trackNumber |= 0x80;  // TODO check track nubmer < 128
+   Ebml_Write(glob, &trackNumber, 1);
+   // Ebml_WriteSigned16(glob, timeCode,2); //this is 3 bytes
+   Ebml_Serialize(glob, &timeCode, sizeof(timeCode), 2);
+-  unsigned char flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable;
++  flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable;
+   Ebml_Write(glob, &flags, 1);
+   Ebml_Write(glob, data, dataLength);
+ }
+@@ -48,17 +53,18 @@ static UInt64 generateTrackID(unsigned int trackNumber) {
+   UInt64 r = rand();
+   r = r << 32;
+   r +=  rand();
+-  UInt64 rval = t ^ r;
+-  return rval;
++//  UInt64 rval = t ^ r;
++  return t ^ r;
+ }
+ 
+ void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                      char *codecId, unsigned int pixelWidth, unsigned int pixelHeight,
+                      double frameRate) {
+   EbmlLoc start;
++  UInt64 trackID;
+   Ebml_StartSubElement(glob, &start, TrackEntry);
+   Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
+-  UInt64 trackID = generateTrackID(trackNumber);
++  trackID = generateTrackID(trackNumber);
+   Ebml_SerializeUnsigned(glob, TrackUID, trackID);
+   Ebml_SerializeString(glob, CodecName, "VP8");  // TODO shouldn't be fixed
+ 
+@@ -78,9 +84,10 @@ void writeAudioTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing,
+                      char *codecId, double samplingFrequency, unsigned int channels,
+                      unsigned char *private, unsigned long privateSize) {
+   EbmlLoc start;
++  UInt64 trackID;
+   Ebml_StartSubElement(glob, &start, TrackEntry);
+   Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
+-  UInt64 trackID = generateTrackID(trackNumber);
++  trackID = generateTrackID(trackNumber);
+   Ebml_SerializeUnsigned(glob, TrackUID, trackID);
+   Ebml_SerializeUnsigned(glob, TrackType, 2); // audio is always 2
+   // I am using defaults for thesed required fields
+
new file mode 100644
--- /dev/null
+++ b/media/libmkv/update.sh
@@ -0,0 +1,33 @@
+# Usage: sh update.sh <upstream_src_directory>
+set -e
+echo "copy source from libvpx"
+
+cp $1/third_party/libmkv/EbmlBufferWriter.c .
+cp $1/third_party/libmkv/WebMElement.c .
+cp $1/third_party/libmkv/EbmlWriter.c .
+cp $1/third_party/libmkv/EbmlWriter.h .
+cp $1/third_party/libmkv/EbmlBufferWriter.h .
+cp $1/third_party/libmkv/WebMElement.h .
+cp $1/third_party/libmkv/EbmlIDs.h .
+
+cp $1/LICENSE .
+cp $1/README .
+cp $1/AUTHORS .
+if [ -d $1/.git ]; then
+  rev=$(cd $1 && git rev-parse --verify HEAD)
+  dirty=$(cd $1 && git diff-index --name-only HEAD)
+fi
+
+if [ -n "$rev" ]; then
+  version=$rev
+  if [ -n "$dirty" ]; then
+    version=$version-dirty
+    echo "WARNING: updating from a dirty git repository."
+  fi
+  sed -i.bak -e "/The git commit ID used was/ s/[0-9a-f]\{40\}\(-dirty\)\{0,1\}\./$version./" README_MOZILLA
+  rm README_MOZILLA.bak
+else
+  echo "Remember to update README_MOZILLA with the version details."
+fi
+
+echo "please apply source_fix.patch and gecko_fix.patch"