gstreamer 快速转码
编辑 使用解决方案更新代码
我需要将amr转码为mp3,所以我在gstreamer-java中编写了一个gstreamer管道。它看起来像这样:(
src ! amrparse ! amrnbdec ! lamemp3enc ! sink
当然,实际上是用java API构建的),我开始转码
Bus.connect(EOS, fn(){Gst.quit();});
setState(PLAYING);
Gst.main();
它工作正常,除了它花费的时间等于音频长度,这是不可接受的。 等效的
gst-launch
转码速度为机器速度。
那么我需要如何设置管道才能获得机器速度转码?
这是完整的源代码,适合熟悉 clojure 的人
(ns audio
(:import [org.gstreamer Gst Pipeline Bin Element ElementFactory State
StateChangeReturn Bus$EOS Bus$ERROR Bus$STATE_CHANGED]
[org.gstreamer.io InputStreamSrc 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)))
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 InputStreamSrc 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)))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试
.setSync(false)
作为您的输出。在普通 gstreamer 中,同步流尝试跟踪时间,而异步流则尽可能快。也许您的输出流正在尝试实时工作。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.