Skip to content

Adapt to new ogg API. #4291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/scripts/build-posix.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ echo "::group::Setting up specific dependencies"

opam install -y xml-light

git clone https://github.com/savonet/ocaml-xiph.git
cd ocaml-xiph
opam install -y .

cd /tmp/liquidsoap-full/liquidsoap

./.github/scripts/checkout-deps.sh
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Fixed:

- Fixed request resolution loop when enabling both `autocue`
and `replaygain` metadata resolvers (#4245, fixed in #4246)
- Fixed `flac` encoding segfault (#4286, #4274)
- Fixed source `last_metadata` not being properly updated (#4262)
- Convert all ICY (icecast) metadata from `input.http` to `utf8`.
- Fixed `inotify` unwatching due to GC cleanup (#4275)
Expand Down
10 changes: 5 additions & 5 deletions dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -117,29 +117,29 @@
(fdkaac (< 0.3.1))
(ffmpeg (< 1.2.0))
(ffmpeg-avutil (< 1.2.0))
(flac (< 0.3.0))
(flac (< 1.0.0))
(frei0r (< 0.1.0))
(inotify (< 1.0))
(ladspa (< 0.2.0))
(lame (< 0.3.7))
(lo (< 0.2.0))
(mad (< 0.5.0))
(magic (< 0.6))
(ogg (< 0.7.4))
(ogg (< 1.0.0))
(opus (< 0.2.0))
(portaudio (< 0.2.0))
(posix-time2 (< 2.0.2))
(pulseaudio (< 0.1.4))
(samplerate (< 0.1.5))
(shine (< 0.2.0))
(soundtouch (< 0.1.9))
(speex (< 0.4.0))
(speex (< 1.0.0))
(srt (< 0.3.0))
(ssl (< 0.7.0))
(tls (< 1.0.2))
(sdl-liquidsoap (< 2))
(theora (< 0.4.0))
(vorbis (< 0.8.0))
(theora (< 1.0.0))
(vorbis (< 1.0.0))
(xmlplaylist (< 0.1.3)))
(synopsis "Liquidsoap core library and binary"))

Expand Down
10 changes: 5 additions & 5 deletions liquidsoap-core.opam
Original file line number Diff line number Diff line change
Expand Up @@ -83,29 +83,29 @@ conflicts: [
"fdkaac" {< "0.3.1"}
"ffmpeg" {< "1.2.0"}
"ffmpeg-avutil" {< "1.2.0"}
"flac" {< "0.3.0"}
"flac" {< "1.0.0"}
"frei0r" {< "0.1.0"}
"inotify" {< "1.0"}
"ladspa" {< "0.2.0"}
"lame" {< "0.3.7"}
"lo" {< "0.2.0"}
"mad" {< "0.5.0"}
"magic" {< "0.6"}
"ogg" {< "0.7.4"}
"ogg" {< "1.0.0"}
"opus" {< "0.2.0"}
"portaudio" {< "0.2.0"}
"posix-time2" {< "2.0.2"}
"pulseaudio" {< "0.1.4"}
"samplerate" {< "0.1.5"}
"shine" {< "0.2.0"}
"soundtouch" {< "0.1.9"}
"speex" {< "0.4.0"}
"speex" {< "1.0.0"}
"srt" {< "0.3.0"}
"ssl" {< "0.7.0"}
"tls" {< "1.0.2"}
"sdl-liquidsoap" {< "2"}
"theora" {< "0.4.0"}
"vorbis" {< "0.8.0"}
"theora" {< "1.0.0"}
"vorbis" {< "1.0.0"}
"xmlplaylist" {< "0.1.3"}
]
build: [
Expand Down
41 changes: 20 additions & 21 deletions src/core/decoder/liq_flac_decoder.ml
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,14 @@ let create_decoder input =
| Some f -> Some (fun () -> Int64.of_int (f ()))
| None -> None
in
let dummy_c =
Flac.Decoder.get_callbacks ?seek ?tell ?length read (fun _ -> ())
let write_ref = ref (fun _ -> ()) in
let write v =
let fn = !write_ref in
fn v
in
let decoder, info, _ =
Flac.Decoder.create ?seek ?tell ?length ~read ~write ()
in
let decoder = Flac.Decoder.create dummy_c in
let decoder, info, _ = Flac.Decoder.init decoder dummy_c in
let samplerate, _ =
(info.Flac.Decoder.sample_rate, info.Flac.Decoder.channels)
in
Expand All @@ -60,33 +63,29 @@ let create_decoder input =
let duration = Frame.seconds_of_main ticks in
let samples = Int64.of_float (duration *. float samplerate) in
let pos = Int64.add !processed samples in
let c =
Flac.Decoder.get_callbacks ?seek ?tell ?length read (fun _ -> ())
in
let ret = Flac.Decoder.seek decoder c pos in
let ret = Flac.Decoder.seek decoder pos in
if ret = true then (
processed := pos;
ticks)
else (
match Flac.Decoder.state decoder c with
match Flac.Decoder.state decoder with
| `Seek_error ->
if Flac.Decoder.flush decoder c then 0
if Flac.Decoder.flush decoder then 0
else
(* Flushing failed, we are in an unknown state.. *)
raise End_of_stream
| _ -> 0));
decode =
(fun buffer ->
let c =
Flac.Decoder.get_callbacks ?seek ?tell ?length read (fun data ->
let len = try Audio.length data with _ -> 0 in
processed := Int64.add !processed (Int64.of_int len);
buffer.Decoder.put_pcm ~samplerate data)
in
match Flac.Decoder.state decoder c with
(write_ref :=
fun data ->
let len = try Audio.length data with _ -> 0 in
processed := Int64.add !processed (Int64.of_int len);
buffer.Decoder.put_pcm ~samplerate data);
match Flac.Decoder.state decoder with
| `Search_for_metadata | `Read_metadata | `Search_for_frame_sync
| `Read_frame ->
Flac.Decoder.process decoder c
Flac.Decoder.process decoder
| _ -> raise End_of_stream);
eof = (fun _ -> ());
close = (fun _ -> ());
Expand Down Expand Up @@ -118,7 +117,7 @@ let file_type filename =
~finally:(fun () -> Unix.close fd)
(fun () ->
let write _ = () in
let h = Flac.Decoder.File.create_from_fd write fd in
let h = Flac.Decoder.File.create_from_fd ~write fd in
let info = h.Flac.Decoder.File.info in
let rate, channels =
(info.Flac.Decoder.sample_rate, info.Flac.Decoder.channels)
Expand Down Expand Up @@ -161,7 +160,7 @@ let get_tags ~metadata:_ ~extension ~mime file =
~finally:(fun () -> Unix.close fd)
(fun () ->
let write _ = () in
let h = Flac.Decoder.File.create_from_fd write fd in
let h = Flac.Decoder.File.create_from_fd ~write fd in
match h.Flac.Decoder.File.comments with Some (_, m) -> m | None -> [])

let metadata_decoder_priority =
Expand Down Expand Up @@ -191,7 +190,7 @@ let dresolver ~metadata:_ file =
~finally:(fun () -> Unix.close fd)
(fun () ->
let write _ = () in
let h = Flac.Decoder.File.create_from_fd write fd in
let h = Flac.Decoder.File.create_from_fd ~write fd in
let info = h.Flac.Decoder.File.info in
match info.Flac.Decoder.total_samples with
| x when x = Int64.zero -> raise Not_found
Expand Down
14 changes: 3 additions & 11 deletions src/core/decoder/ogg_flac_duration.ml
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,14 @@ let dresolver ~metadata:_ file =
let serial = Ogg.Page.serialno page in
let os = Ogg.Stream.create ~serial () in
Ogg.Stream.put_page os page;
let packet = Ogg.Stream.get_packet os in
let packet = Ogg.Stream.peek_packet os in
(* Test header. Do not catch anything, first page should be sufficient *)
if not (Flac_ogg.Decoder.check_packet packet) then raise Not_found;
let fill () =
let page = Ogg.Sync.read sync in
if Ogg.Page.serialno page = serial then Ogg.Stream.put_page os page
in
let callbacks = Flac_ogg.Decoder.get_callbacks os (fun _ -> ()) in
let dec = Flac.Decoder.create callbacks in
let rec info () =
try Flac.Decoder.init dec callbacks
with Ogg.Not_enough_data ->
fill ();
info ()
in
info ()
Flac_ogg.Decoder.create ~fill ~write:(fun _ -> ()) os
in
(* Now find a flac stream *)
let rec init () = try test_flac () with Not_found -> init () in
Expand All @@ -64,7 +56,7 @@ let dresolver ~metadata:_ file =
samples /. float info.Flac.Decoder.sample_rate)

let () =
Plug.register Request.dresolvers "ogg/flac" ~doc:""
Plug.register Request.dresolvers "ogg_flac" ~doc:""
{
dpriority = (fun () -> Liq_ogg_decoder.priority#get);
file_extensions = (fun () -> Liq_ogg_decoder.file_extensions#get);
Expand Down
7 changes: 3 additions & 4 deletions src/core/encoder/encoders/flac_encoder.ml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ let encoder flac meta =
in
let buf = Strings.Mutable.empty () in
let write chunk = Strings.Mutable.add_bytes buf chunk in
let cb = Flac.Encoder.get_callbacks write in
let enc = Flac.Encoder.create ~comments p cb in
let enc = Flac.Encoder.create ~comments ~write p in
let enc = ref enc in
let encode frame =
let b = AFrame.pcm frame in
Expand All @@ -55,11 +54,11 @@ let encoder flac meta =
(dst_freq /. src_freq) b 0 len
in
let b = Audio.sub b start len in
Flac.Encoder.process !enc cb b;
Flac.Encoder.process !enc b;
Strings.Mutable.flush buf
in
let stop () =
Flac.Encoder.finish !enc cb;
Flac.Encoder.finish !enc;
Strings.Mutable.flush buf
in
{
Expand Down
3 changes: 1 addition & 2 deletions src/core/encoder/encoders/ogg_encoder.ml
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ let encoder ~pos { Ogg_format.audio; video } =
and ogg_stop () =
let f track = track.id <- None in
List.iter f tracks;
if Ogg_muxer.state ogg_enc = Ogg_muxer.Streaming then
Ogg_muxer.end_of_stream ogg_enc
Ogg_muxer.end_of_stream ogg_enc
and stop () =
ogg_stop ();
Ogg_muxer.get_data ogg_enc
Expand Down
12 changes: 6 additions & 6 deletions src/core/ogg_formats/ogg_flac_encoder.ml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ let create_encoder ~flac ~comments () =
| None ->
let x =
Flac_ogg.Encoder.create ~comments ~serialno:(Ogg.Stream.serialno os)
p write_cb
~write:write_cb p
in
enc := Some x;
x
Expand Down Expand Up @@ -80,8 +80,8 @@ let create_encoder ~flac ~comments () =
(data.Ogg_muxer.data, data.Ogg_muxer.offset, data.Ogg_muxer.length)
in
let b = Array.map (fun x -> Array.sub x ofs len) b in
let { Flac_ogg.Encoder.encoder; callbacks } = get_enc os in
Flac.Encoder.process encoder callbacks b;
let { Flac_ogg.Encoder.encoder } = get_enc os in
Flac.Encoder.process encoder b;
List.iter write_page (flush_pages ())
in
let end_of_page p =
Expand All @@ -90,12 +90,12 @@ let create_encoder ~flac ~comments () =
else Ogg_muxer.Time (Int64.to_float granulepos /. float samplerate)
in
let end_of_stream os =
let { Flac_ogg.Encoder.encoder; callbacks } = get_enc os in
let { Flac_ogg.Encoder.encoder } = get_enc os in
(* Assert that at least some data was encoded.. *)
if not !started then (
let b = empty_data () in
Flac.Encoder.process encoder callbacks b);
Flac.Encoder.finish encoder callbacks;
Flac.Encoder.process encoder b);
Flac.Encoder.finish encoder;
set_stream_eos os;
flush_pages ()
in
Expand Down
4 changes: 1 addition & 3 deletions src/core/ogg_formats/ogg_muxer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,7 @@ let register_track ?fill encoder track_encoder =

(** Start streams, set state to Streaming. *)
let streams_start encoder =
if Hashtbl.length encoder.tracks = 0 then
log#info "%s: Starting stream with no ogg track.." encoder.id;
log#info "%s: Starting all streams" encoder.id;
log#info "%s: Starting %d track(s)" encoder.id (Hashtbl.length encoder.tracks);

(* Add skeleton information first. *)
begin
Expand Down
16 changes: 16 additions & 0 deletions tests/regression/dune.inc
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,22 @@
(:run_test ../run_test.exe))
(action (run %{run_test} external-encoder.liq liquidsoap %{test_liq} external-encoder.liq)))

(rule
(alias citest)
(package liquidsoap)
(deps
fallible_ogg.liq
../media/all_media_files
../../src/bin/liquidsoap.exe
../streams/file1.png
../streams/file1.mp3
./theora-test.mp4
(package liquidsoap)
(source_tree ../../src/libs)
(:test_liq ../test.liq)
(:run_test ../run_test.exe))
(action (run %{run_test} fallible_ogg.liq liquidsoap %{test_liq} fallible_ogg.liq)))

(rule
(alias citest)
(package liquidsoap)
Expand Down
9 changes: 9 additions & 0 deletions tests/regression/fallible_ogg.liq
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
port = 9301

s = playlist("../media")

output.icecast(fallible=true, port=port, mount="test.flac", %ogg(%flac), s)

s = input.harbor("test.flac", buffer=1., port=port)

output.dummy(on_start=test.pass, fallible=true, s)
Loading