EDIT Updated code with solution
I need to transcode amr to mp3, so i wrote a gstreamer pipeline in gstreamer-java. It looks like this:
src ! amrparse ! amrnbdec ! lamemp3enc ! sink
(actually built with the java API, of course), i start the transcode with
Bus.connect(EOS, fn(){Gst.quit();});
setState(PLAYING);
Gst.main();
It works fine, except the time it takes is equal to the audio length, which is not acceptable. The equivalent
gst-launch
transcodes at machine speed.
So how do I need to setup the pipeline, to get machine speed transcoding?
Here is the full source, for people fluent with clojure
(ns audio
(:import [org.gstreamer Gst Pipeline Bin Element ElementFactory State
StateChangeReturn Bus$EOS Bus$ERROR Bus$STATE_CHANGED]
[org.gstreamer.io InputStre开发者_JAVA百科amSrc OutputStreamSink]
[java.io InputStream OutputStream])
(:use clojure.contrib.logging))
(Gst/init)
(defn transcode [^InputStream in ^OutputStream out]
(let [id (gensym (quote transcode))
src (InputStreamSrc. in (str "in stream " id))
dec0 (ElementFactory/make "amrparse" (str "amr parser " id))
dec1 (ElementFactory/make "amrnbdec" (str "amr decoder " id))
enc (doto (ElementFactory/make "lamemp3enc" (str "mp3 encoder " id))
(.set "mono" true)
(.set "target" 0)
(.set "quality" 2))
out (doto (OutputStreamSink. out (str "out stream " id))
(.setSync false))
pipe (doto (Pipeline. (str "transcoder pipe " id))
(.add src)
(.add dec0)
(.add dec1)
(.add enc)
(.add out))
clean (fn []
(.setState src nil)
(.setState dec0 nil)
(.setState dec1 nil)
(.setState enc nil)
(.setState out nil)
(.setState pipe nil))]
(prn "starting transcode " id)
(.link src dec0)
(.link dec0 dec1)
(.link dec1 enc)
(.link enc out)
(doto (.getBus pipe)
(.connect
(reify Bus$EOS
(endOfStream [this src]
(prn "Bus finished " src)
(clean)
(Gst/quit))))
(.connect
(reify Bus$ERROR
(errorMessage [this src code msg]
(prn "Bus Error " src code msg)
(clean)
(Gst/quit))))
(.connect
(reify Bus$STATE_CHANGED
(stateChanged [this src old now pending]
(prn "Bus State change " src old now pending)))))
(.setState pipe State/PLAYING)
(Gst/main)))
Try .setSync(false)
for your output. In normal gstreamer a synchronous stream tries to keep track of the time, while an asynchronous stream goes as fast as it can. Maybe your output stream is trying to work in real time.
精彩评论