Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'gstreamer' into gstreamer_encoder

  • Loading branch information...
commit f178d5fd8e4e96f5236f5c3938d6f1f4ca50fce8 2 parents 9b86465 + 6730050
@smimram smimram authored
View
1  src/Makefile
@@ -247,6 +247,7 @@ $(call conditional_compilation,operators,$(W_GD),operators/video_text_gd.ml)
# GStreamer
$(call conditional_compilation,stream,$(W_GSTREAMER),tools/gstreamer_utils.ml)
$(call conditional_compilation,decoders,$(W_GSTREAMER),decoder/gstreamer_decoder.ml)
+$(call conditional_compilation,encoders,$(W_GSTREAMER),encoder/gstreamer_encoder.ml)
$(call conditional_compilation,operators,$(W_GSTREAMER),operators/video_text_gstreamer.ml)
$(call conditional_compilation,io,$(W_GSTREAMER),io/gstreamer_io.ml)
View
16 src/encoder/encoder.ml
@@ -422,6 +422,17 @@ struct
end
+module GStreamer =
+struct
+ type t = {
+ (* TODO: ... *)
+ dummy : unit;
+ }
+
+ (* TODO *)
+ let to_string m = "%%gstreamer"
+end
+
module Theora =
struct
@@ -535,6 +546,7 @@ type format =
| AACPlus of AACPlus.t
| VoAacEnc of VoAacEnc.t
| External of External.t
+ | GStreamer of GStreamer.t
let kind_of_format = function
| WAV w ->
@@ -576,6 +588,9 @@ let kind_of_format = function
| External e ->
{ Frame.audio = e.External.channels ;
Frame.video = 0 ; Frame.midi = 0 }
+ | GStreamer e ->
+ (* TODO: fill this! *)
+ { Frame.audio = 2; Frame.video = 1; Frame.midi = 0 }
let kind_of_format f =
let k = kind_of_format f in
@@ -592,6 +607,7 @@ let string_of_format = function
| AACPlus w -> AACPlus.to_string w
| VoAacEnc w -> VoAacEnc.to_string w
| External w -> External.to_string w
+ | GStreamer w -> GStreamer.to_string w
(** An encoder, once initialized, is something that consumes
* frames, insert metadata and that you eventually close
View
155 src/encoder/gstreamer_encoder.ml
@@ -0,0 +1,155 @@
+(*****************************************************************************
+
+ Liquidsoap, a programmable audio stream generator.
+ Copyright 2003-2012 Savonet team
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details, fully stated in the COPYING
+ file at the root of the liquidsoap distribution.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ *****************************************************************************)
+
+(** GStreamer encoder *)
+
+open Encoder.GStreamer
+
+module GU = Gstreamer_utils
+module Img = Image.RGBA32
+
+type gst =
+ {
+ bin : Gstreamer.Pipeline.t;
+ audio_src : Gstreamer.App_src.t;
+ video_src : Gstreamer.App_src.t;
+ sink : Gstreamer.App_sink.t;
+ }
+
+let encoder id ext =
+ GU.init ();
+ let channels = 2 in
+
+ let mutex = Mutex.create () in
+ let samples = ref 0 in
+ let decr_samples () =
+ Mutex.lock mutex;
+ decr samples;
+ Mutex.unlock mutex;
+ in
+ let on_sample () =
+ Printf.printf "Got sample!\n%!";
+ (* Will we finally get there????....... *)
+ exit (-1);
+ Mutex.lock mutex;
+ incr samples;
+ Mutex.unlock mutex
+ in
+
+ let gst =
+ let audio_pipeline =
+ Printf.sprintf "%s ! queue ! %s ! lamemp3enc ! muxer."
+ (GU.Pipeline.audio_src ~channels ~block:false "audio_src")
+ (GU.Pipeline.convert_audio ())
+ in
+ let video_pipeline =
+ Printf.sprintf "%s ! queue ! %s ! x264enc ! muxer."
+ (GU.Pipeline.video_src ~block:true "video_src")
+ (GU.Pipeline.convert_video ())
+ in
+ let pipeline =
+ Printf.sprintf "%s %s avimux name=muxer ! appsink name=sink sync=false emit-signals=true"
+ audio_pipeline
+ video_pipeline
+ in
+ Printf.printf "pipeline: %s\n%!" pipeline;
+ let bin = Gstreamer.Pipeline.parse_launch pipeline in
+ let audio_src = Gstreamer.App_src.of_element (Gstreamer.Bin.get_by_name bin "audio_src") in
+ let video_src = Gstreamer.App_src.of_element (Gstreamer.Bin.get_by_name bin "audio_src") in
+ let sink = Gstreamer.App_sink.of_element (Gstreamer.Bin.get_by_name bin "sink") in
+ Gstreamer.App_sink.on_new_sample sink on_sample;
+ ignore (Gstreamer.Element.set_state bin Gstreamer.Element.State_playing);
+ { bin; audio_src; video_src; sink }
+ in
+
+ let stop gst () =
+ let ans = ref "" in
+ (* TODO: send EOS on both appsrc *)
+ ignore (Gstreamer.Element.set_state gst.bin Gstreamer.Element.State_paused);
+ while !samples > 0 do
+ let b = Gstreamer.App_sink.pull_buffer_string gst.sink in
+ decr_samples ();
+ ans := !ans ^ b
+ done;
+ ignore (Gstreamer.Element.set_state gst.bin Gstreamer.Element.State_null);
+ !ans
+ in
+
+ let insert_metadata gst _ =
+ (* TODO? *)
+ ()
+ in
+
+ let now = ref Int64.zero in
+
+ let encode h frame start len =
+ Printf.printf "Encode@%Lu.\n%!" !now;
+ let nanolen = Int64.of_float (Frame.seconds_of_master len *. 1000000000.) in
+ let content = Frame.content_of_type frame start { Frame.audio = channels; video = 1; midi = 0 } in
+ (* Put audio. *)
+ let astart = Frame.audio_of_master start in
+ let alen = Frame.audio_of_master len in
+ let pcm = content.Frame.audio in
+ let data = String.create (2*channels*alen) in
+ Audio.S16LE.of_audio pcm astart data 0 alen;
+ let gstbuf = Gstreamer.Buffer.of_string data 0 (String.length data) in
+ Gstreamer.Buffer.set_presentation_time gstbuf !now;
+ Gstreamer.Buffer.set_duration gstbuf nanolen;
+ Printf.printf "Put audio... %!";
+ Gstreamer.App_src.push_buffer gst.audio_src gstbuf;
+ Printf.printf "done.\n%!";
+ (* Put video. *)
+ let vbuf = content.Frame.video in
+ let vbuf = vbuf.(0) in
+ for i = 0 to Array.length vbuf - 1 do
+ let data = Img.data vbuf.(i) in
+ let gstbuf = Gstreamer.Buffer.of_data data 0 (Bigarray.Array1.dim data) in
+ Gstreamer.Buffer.set_presentation_time gstbuf !now;
+ Gstreamer.Buffer.set_duration gstbuf nanolen;
+ Printf.printf "Put video... %!";
+ Gstreamer.App_src.push_buffer gst.video_src gstbuf;
+ Printf.printf "done.\n%!"
+ done;
+ (* Return result. *)
+ now := Int64.add !now nanolen;
+ if !samples = 0 then
+ ""
+ else
+ let ans = Gstreamer.App_sink.pull_buffer_string gst.sink in
+ decr_samples ();
+ ans
+ in
+
+ {
+ Encoder.
+ insert_metadata = insert_metadata gst;
+ (* TODO: can we get a header? *)
+ header = None;
+ encode = encode gst;
+ stop = stop gst;
+ }
+
+let () =
+ Encoder.plug#register "GSTREAMER"
+ (function
+ | Encoder.GStreamer m -> Some (fun s _ -> encoder s m)
+ | _ -> None)
View
8 src/lang/lang_encoders.ml
@@ -795,3 +795,11 @@ let mk_speex params =
defaults params
in
Encoder.Ogg.Speex speex
+
+let mk_gstreamer params =
+ let defaults =
+ { Encoder.GStreamer.
+ dummy = ();
+ }
+ in
+ mk (Encoder (Encoder.GStreamer defaults))
View
1  src/lang/lang_lexer.mll
@@ -140,6 +140,7 @@ rule token = parse
| "%vorbis.abr" { VORBIS_ABR }
| "%theora" { THEORA }
| "%external" { EXTERNAL }
+ | "%gstreamer" { GSTREAMER }
| "%dirac" { DIRAC }
| "%speex" { SPEEX }
| "%wav" { WAV }
View
3  src/lang/lang_parser.mly
@@ -159,7 +159,7 @@
%token <bool> BOOL
%token <int option list> TIME
%token <int option list * int option list> INTERVAL
-%token OGG FLAC OPUS VORBIS VORBIS_CBR VORBIS_ABR THEORA DIRAC SPEEX
+%token OGG FLAC OPUS VORBIS VORBIS_CBR VORBIS_ABR THEORA DIRAC SPEEX GSTREAMER
%token WAV VOAACENC AACPLUS MP3 MP3_VBR MP3_ABR MP3_FXP EXTERNAL
%token EOF
%token BEGIN END GETS TILD QUESTION
@@ -289,6 +289,7 @@ expr:
| VOAACENC app_opt { mk_voaacenc $2 }
| FLAC app_opt { mk_flac $2 }
| EXTERNAL app_opt { mk_external $2 }
+ | GSTREAMER app_opt { mk_gstreamer $2 }
| WAV app_opt { mk_wav $2 }
| OGG LPAR ogg_items RPAR { mk (Encoder (Encoder.Ogg $3)) }
| top_level_ogg_item { mk (Encoder (Encoder.Ogg [$1])) }
View
5 src/tools/gstreamer_utils.ml
@@ -37,8 +37,11 @@ let init =
)
module Pipeline = struct
+ let convert_audio () =
+ "audioconvert ! audioresample"
+
let decode_audio () =
- "decodebin ! audioconvert ! audioresample"
+ Printf.sprintf "decodebin ! %s" (convert_audio ())
let convert_video () =
let add_borders = add_borders () in
Please sign in to comment.
Something went wrong with that request. Please try again.