Hey Guys,

I was hoping to get more work done on this but haven't had the chance
to work on it any further.  This patch switches Record to use the WebM
video format as specified by google.  It should work on our F14
builds.  The videos will playback in Record, but you will have to
patch your mimetypes files to add support to other programs.  In
particular you should add video/webm to the
/usr/share/sugar/data/mime.defaults file.

I do know that one thing that needs to be fixed is the preview image
shown while the recording is being encoded is displayed in greyscale
instead of color.  Other than that I am quite happy with the recording
quality.  You will still notice an audio hiccup at  between 14 and 20
seconds of the start of the recording.  This is where we would
previously lose audio sync.  With this patch the sync re-adjusts
itself but leaves a small hiccup in the audio track.

Hope this is useful to someone.

-Jon
From 42c66aaf17686be5b5320698c7d258e11164812d Mon Sep 17 00:00:00 2001
From: Jon Nettleton <[email protected]>
Date: Fri, 8 Apr 2011 05:50:25 -0700
Subject: [PATCH] Convert to using WebM video format

This switches Record to use vp8 video and ogg audio
in a matroska container.  This is the standard that
makes up the WebM video format.  The encoder quality
and performance seems to be better than the existing
ogg/theora combination.
---
 constants.py |    4 +-
 glive.py     |   59 +++++++++++++++++++++++++++++----------------------------
 2 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/constants.py b/constants.py
index 9b0ed4a..2381029 100644
--- a/constants.py
+++ b/constants.py
@@ -26,8 +26,8 @@ MEDIA_INFO[TYPE_PHOTO] = {
 
 MEDIA_INFO[TYPE_VIDEO] = {
     'name' : 'video',
-    'mime' : 'video/ogg',
-    'ext' : 'ogg',
+    'mime' : 'video/webm',
+    'ext' : 'webm',
     'istr' : _('Video')
 }
 
diff --git a/glive.py b/glive.py
index 07d187b..14288cf 100644
--- a/glive.py
+++ b/glive.py
@@ -38,9 +38,9 @@ import utils
 
 logger = logging.getLogger('glive')
 
-OGG_TRAITS = {
-        0: { 'width': 160, 'height': 120, 'quality': 16 },
-        1: { 'width': 400, 'height': 300, 'quality': 16 } }
+WEBM_TRAITS = {
+        0: { 'width': 160, 'height': 120, 'quality': 5 },
+        1: { 'width': 400, 'height': 300, 'quality': 5 } }
 
 THUMB_STUB = gtk.gdk.pixbuf_new_from_file(
     os.path.join(get_bundle_path(), 'gfx', 'stub.png'))
@@ -180,13 +180,14 @@ class Glive:
 
         colorspace = gst.element_factory_make("ffmpegcolorspace", "vbcolorspace")
 
-        enc = gst.element_factory_make("theoraenc", "vbenc")
-        enc.set_property("quality", 16)
+        enc = gst.element_factory_make("vp8enc", "vbenc")
+        enc.set_property("quality", 5)
+        enc.set_property("speed", 2)
 
-        mux = gst.element_factory_make("oggmux", "vbmux")
+        mux = gst.element_factory_make("matroskamux", "vbmux")
 
         sink = gst.element_factory_make("filesink", "vbfile")
-        sink.set_property("location", os.path.join(Instance.instancePath, "output.ogg"))
+        sink.set_property("location", os.path.join(Instance.instancePath, "output.webm"))
 
         self._videobin = gst.Bin("videobin")
         self._videobin.add(queue, scale, scalecapsfilter, colorspace, enc, mux, sink)
@@ -217,7 +218,7 @@ class Glive:
 
     def _config_videobin(self, quality, width, height):
         vbenc = self._videobin.get_by_name("vbenc")
-        vbenc.set_property("quality", 16)
+        vbenc.set_property("quality", 5)
         scaps = self._videobin.get_by_name("scalecaps")
         scaps.set_property("caps", gst.Caps("video/x-raw-yuv,width=%d,height=%d" % (width, height)))
 
@@ -366,7 +367,7 @@ class Glive:
 
         self.model.still_ready(self._audio_pixbuf)
 
-        line = 'filesrc location=' + audio_path + ' name=audioFilesrc ! wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! vorbisenc name=audioVorbisenc ! oggmux name=audioOggmux ! filesink name=audioFilesink'
+        line = 'filesrc location=' + audio_path + ' name=audioFilesrc ! wavparse name=audioWavparse ! audioconvert name=audioAudioconvert ! vorbisenc name=audioVorbisenc ! matroskamux name=audioOggmux ! filesink name=audioFilesink'
         audioline = gst.parse_launch(line)
 
         taglist = self._get_tags(constants.TYPE_AUDIO)
@@ -376,7 +377,7 @@ class Glive:
         vorbis_enc.merge_tags(taglist, gst.TAG_MERGE_REPLACE_ALL)
 
         audioFilesink = audioline.get_by_name('audioFilesink')
-        audioOggFilepath = os.path.join(Instance.instancePath, "output.ogg")
+        audioOggFilepath = os.path.join(Instance.instancePath, "output.webm")
         audioFilesink.set_property("location", audioOggFilepath)
 
         audioBus = audioline.get_bus()
@@ -448,10 +449,10 @@ class Glive:
         if not self._has_camera:
             return
 
-        self._ogg_quality = quality
-        self._config_videobin(OGG_TRAITS[quality]['quality'],
-            OGG_TRAITS[quality]['width'],
-            OGG_TRAITS[quality]['height'])
+        self._webm_quality = quality
+        self._config_videobin(WEBM_TRAITS[quality]['quality'],
+            WEBM_TRAITS[quality]['width'],
+            WEBM_TRAITS[quality]['height'])
 
         # If we use pad blocking and adjust the pipeline on-the-fly, the
         # resultant video has bad A/V sync :(
@@ -501,12 +502,12 @@ class Glive:
             thumbline = self._thumb_pipes[-1]
             thumbline.get_by_name('thumb_fakesink').disconnect(self._thumb_handoff_handler)
 
-        ogg_path = os.path.join(Instance.instancePath, "output.ogg") #ogv
-        if not os.path.exists(ogg_path) or os.path.getsize(ogg_path) <= 0:
+        webm_path = os.path.join(Instance.instancePath, "output.webm") #ogv
+        if not os.path.exists(webm_path) or os.path.getsize(webm_path) <= 0:
             # FIXME: inform model of failure?
             return
 
-        line = 'filesrc location=' + ogg_path + ' name=thumbFilesrc ! oggdemux name=thumbOggdemux ! theoradec name=thumbTheoradec ! tee name=thumb_tee ! queue name=thumb_queue ! ffmpegcolorspace name=thumbFfmpegcolorspace ! jpegenc name=thumbJPegenc ! fakesink name=thumb_fakesink'
+        line = 'filesrc location=' + webm_path + ' name=thumbFilesrc ! matroskademux name=thumbOggdemux ! vp8dec name=thumbTheoradec ! tee name=thumb_tee ! queue name=thumb_queue ! ffmpegcolorspace name=thumbFfmpegcolorspace ! jpegenc name=thumbJPegenc ! fakesink name=thumb_fakesink'
         thumbline = gst.parse_launch(line)
         thumb_queue = thumbline.get_by_name('thumb_queue')
         thumb_queue.set_property("leaky", True)
@@ -532,11 +533,11 @@ class Glive:
 
         self._thumb_element('thumb_tee').unlink(self._thumb_element('thumb_queue'))
 
-        oggFilepath = os.path.join(Instance.instancePath, "output.ogg") #ogv
+        webmFilepath = os.path.join(Instance.instancePath, "output.webm") #ogv
         wavFilepath = os.path.join(Instance.instancePath, "output.wav")
-        muxFilepath = os.path.join(Instance.instancePath, "mux.ogg") #ogv
+        muxFilepath = os.path.join(Instance.instancePath, "mux.webm") #ogv
 
-        muxline = gst.parse_launch('filesrc location=' + str(oggFilepath) + ' name=muxVideoFilesrc ! oggdemux name=muxOggdemux ! theoraparse ! oggmux name=muxOggmux ! filesink location=' + str(muxFilepath) + ' name=muxFilesink filesrc location=' + str(wavFilepath) + ' name=muxAudioFilesrc ! wavparse name=muxWavparse ! audioconvert name=muxAudioconvert ! vorbisenc name=muxVorbisenc ! muxOggmux.')
+        muxline = gst.parse_launch('filesrc location=' + str(webmFilepath) + ' name=muxVideoFilesrc ! matroskademux name=muxMatroskademux ! matroskamux name=muxMatroskamux ! filesink location=' + str(muxFilepath) + ' name=muxFilesink filesrc location=' + str(wavFilepath) + ' name=muxAudioFilesrc ! wavparse name=muxWavparse ! audioconvert name=muxAudioconvert ! vorbisenc name=muxVorbisenc ! muxMatroskamux.')
         taglist = self._get_tags(constants.TYPE_VIDEO)
         vorbis_enc = muxline.get_by_name('muxVorbisenc')
         vorbis_enc.merge_tags(taglist, gst.TAG_MERGE_REPLACE_ALL)
@@ -583,10 +584,10 @@ class Glive:
         pipe.get_bus().disable_sync_message_emission()
 
         wavFilepath = os.path.join(Instance.instancePath, "output.wav")
-        oggFilepath = os.path.join(Instance.instancePath, "output.ogg") #ogv
-        muxFilepath = os.path.join(Instance.instancePath, "mux.ogg") #ogv
+        webmFilepath = os.path.join(Instance.instancePath, "output.webm") #ogv
+        muxFilepath = os.path.join(Instance.instancePath, "mux.webm") #ogv
         os.remove( wavFilepath )
-        os.remove( oggFilepath )
+        os.remove( webmFilepath )
         self.model.save_video(muxFilepath, self.thumbBuf)
         return False
 
@@ -603,9 +604,9 @@ class Glive:
         pipe.get_bus().disable_sync_message_emission()
 
         wavFilepath = os.path.join(Instance.instancePath, "output.wav")
-        oggFilepath = os.path.join(Instance.instancePath, "output.ogg")
+        webmFilepath = os.path.join(Instance.instancePath, "output.webm")
         os.remove( wavFilepath )
-        self.model.save_audio(oggFilepath, self._audio_pixbuf)
+        self.model.save_audio(webmFilepath, self._audio_pixbuf)
         return False
 
     def _bus_message_handler(self, bus, message):
@@ -637,10 +638,10 @@ class Glive:
         wav_path = os.path.join(Instance.instancePath, "output.wav")
         if os.path.exists(wav_path):
             os.remove(wav_path)
-        ogg_path = os.path.join(Instance.instancePath, "output.ogg") #ogv
-        if os.path.exists(ogg_path):
-            os.remove(ogg_path)
-        mux_path = os.path.join(Instance.instancePath, "mux.ogg") #ogv
+        webm_path = os.path.join(Instance.instancePath, "output.webm") #ogv
+        if os.path.exists(webm_path):
+            os.remove(webm_path)
+        mux_path = os.path.join(Instance.instancePath, "mux.webm") #ogv
         if os.path.exists(mux_path):
             os.remove(mux_path)
 
-- 
1.7.4.2

_______________________________________________
Devel mailing list
[email protected]
http://lists.laptop.org/listinfo/devel

Reply via email to