Skip to content

Commit 065bb7e

Browse files
committed
Prioritize, use file decoders file extensions when computing request duration. (#4134)
1 parent bfb4b98 commit 065bb7e

File tree

9 files changed

+116
-26
lines changed

9 files changed

+116
-26
lines changed

src/core/decoder/external_decoder.ml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,18 @@ let register_stdin ~name ~doc ~priority ~mimes ~file_extensions ~test process =
120120
stream_decoder = Some (fun ~ctype:_ _ -> create_stream process);
121121
};
122122

123-
let duration ~metadata:_ filename =
123+
let dresolver ~metadata:_ filename =
124124
let process =
125125
Printf.sprintf "cat %s | %s" (Filename.quote filename) process
126126
in
127127
duration process
128128
in
129-
Plug.register Request.dresolvers name ~doc duration
129+
Plug.register Request.dresolvers name ~doc
130+
{
131+
dpriority = (fun () -> priority);
132+
file_extensions = (fun () -> Option.value ~default:[] file_extensions);
133+
dresolver;
134+
}
130135

131136
(** Now an external decoder that directly operates
132137
* on the file. The remaining time in this case
@@ -196,5 +201,10 @@ let register_oblivious ~name ~doc ~priority ~mimes ~file_extensions ~test
196201
stream_decoder = None;
197202
};
198203

199-
let duration ~metadata:_ filename = duration (process filename) in
200-
Plug.register Request.dresolvers name ~doc duration
204+
let dresolver ~metadata:_ filename = duration (process filename) in
205+
Plug.register Request.dresolvers name ~doc
206+
{
207+
dpriority = (fun () -> priority);
208+
file_extensions = (fun () -> Option.value ~default:[] file_extensions);
209+
dresolver;
210+
}

src/core/decoder/ffmpeg_decoder.ml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ let parse_file_decoder_args metadata =
546546
| Some args -> parse_input_args args
547547
| None -> ([], None)
548548

549-
let duration ~metadata file =
549+
let dresolver ~metadata file =
550550
let args, format = parse_file_decoder_args metadata in
551551
let opts = Hashtbl.create 10 in
552552
List.iter (fun (k, v) -> Hashtbl.replace opts k v) args;
@@ -558,10 +558,16 @@ let duration ~metadata file =
558558
Option.map (fun d -> Int64.to_float d /. 1000.) duration)
559559

560560
let () =
561-
Plug.register Request.dresolvers "ffmepg" ~doc:"" (fun ~metadata fname ->
562-
match duration ~metadata fname with
563-
| None -> raise Not_found
564-
| Some d -> d)
561+
Plug.register Request.dresolvers "ffmepg" ~doc:""
562+
{
563+
dpriority = (fun () -> priority#get);
564+
file_extensions = (fun () -> file_extensions#get);
565+
dresolver =
566+
(fun ~metadata fname ->
567+
match dresolver ~metadata fname with
568+
| None -> raise Not_found
569+
| Some d -> d);
570+
}
565571

566572
let tags_substitutions = [("track", "tracknumber")]
567573

@@ -1087,7 +1093,7 @@ let mk_streams ~ctype ~decode_first_metadata container =
10871093

10881094
let create_decoder ~ctype ~metadata fname =
10891095
let args, format = parse_file_decoder_args metadata in
1090-
let file_duration = duration ~metadata fname in
1096+
let file_duration = dresolver ~metadata fname in
10911097
let remaining = Atomic.make file_duration in
10921098
let set_remaining ~pts ~duration stream =
10931099
let pts =

src/core/decoder/liq_flac_decoder.ml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ let check filename =
184184
true
185185
with _ -> false
186186

187-
let duration ~metadata:_ file =
187+
let dresolver ~metadata:_ file =
188188
if not (check file) then raise Not_found;
189189
let fd = Decoder.openfile file in
190190
Fun.protect
@@ -199,4 +199,8 @@ let duration ~metadata:_ file =
199199

200200
let () =
201201
Plug.register Request.dresolvers "flac" ~doc:"Compute duration of flac files."
202-
duration
202+
{
203+
dpriority = (fun () -> priority#get);
204+
file_extensions = (fun () -> file_extensions#get);
205+
dresolver;
206+
}

src/core/decoder/mad_decoder.ml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,16 @@ let check filename =
189189
true
190190
with _ -> false
191191

192-
let duration ~metadata:_ file =
192+
let dresolver ~metadata:_ file =
193193
if not (check file) then raise Not_found;
194194
let ans = Mad.duration file in
195195
match ans with 0. -> raise Not_found | _ -> ans
196196

197197
let () =
198198
Plug.register Request.dresolvers "mad"
199-
~doc:"Compute duration of mp3 files using MAD library." duration
199+
~doc:"Compute duration of mp3 files using MAD library."
200+
{
201+
dpriority = (fun () -> priority#get);
202+
file_extensions = (fun () -> file_extensions#get);
203+
dresolver;
204+
}

src/core/decoder/ogg_flac_duration.ml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
(** Read duration of ogg/flac files. *)
2424

25-
let duration ~metadata:_ file =
25+
let dresolver ~metadata:_ file =
2626
let sync, fd = Ogg.Sync.create_from_file file in
2727
Fun.protect
2828
~finally:(fun () -> Unix.close fd)
@@ -63,4 +63,10 @@ let duration ~metadata:_ file =
6363
if samples <= 0. then raise Not_found;
6464
samples /. float info.Flac.Decoder.sample_rate)
6565

66-
let () = Plug.register Request.dresolvers "ogg/flac" ~doc:"" duration
66+
let () =
67+
Plug.register Request.dresolvers "ogg/flac" ~doc:""
68+
{
69+
dpriority = (fun () -> Liq_ogg_decoder.priority#get);
70+
file_extensions = (fun () -> Liq_ogg_decoder.file_extensions#get);
71+
dresolver;
72+
}

src/core/decoder/vorbisduration.ml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,16 @@
2222

2323
(** Read duration of ogg/vorbis files. *)
2424

25-
let duration ~metadata:_ file =
25+
let dresolver ~metadata:_ file =
2626
let dec, fd = Vorbis.File.Decoder.openfile file in
2727
Fun.protect
2828
~finally:(fun () -> Unix.close fd)
2929
(fun _ -> Vorbis.File.Decoder.duration dec (-1))
3030

31-
let () = Plug.register Request.dresolvers "vorbis" ~doc:"" duration
31+
let () =
32+
Plug.register Request.dresolvers "vorbis" ~doc:""
33+
{
34+
dpriority = (fun () -> Liq_ogg_decoder.priority#get);
35+
file_extensions = (fun () -> Liq_ogg_decoder.file_extensions#get);
36+
dresolver;
37+
}

src/core/decoder/wav_aiff_decoder.ml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,19 @@ let () =
219219
}
220220

221221
let () =
222-
let duration ~metadata:_ file =
222+
let dresolver ~metadata:_ file =
223223
let w = Wav_aiff.fopen file in
224224
let ret = Wav_aiff.duration w in
225225
Wav_aiff.close w;
226226
ret
227227
in
228228
Plug.register Request.dresolvers "wav/aiff"
229-
~doc:"Native computation of wav and aiff files duration." duration
229+
~doc:"Native computation of wav and aiff files duration."
230+
{
231+
dpriority = (fun () -> aiff_priorities#get);
232+
file_extensions = (fun () -> aiff_file_extensions#get);
233+
dresolver;
234+
}
230235

231236
let basic_mime_types =
232237
Dtools.Conf.list

src/core/request.ml

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,20 +121,59 @@ let status { status } = Atomic.get status
121121
let indicator ?(metadata = Frame.Metadata.empty) ?temporary s =
122122
{ uri = home_unrelate s; temporary = temporary = Some true; metadata }
123123

124-
(** Length *)
124+
type dresolver = {
125+
dpriority : unit -> int;
126+
file_extensions : unit -> string list;
127+
dresolver : metadata:Frame.metadata -> string -> float;
128+
}
129+
125130
let dresolvers_doc = "Methods to extract duration from a file."
126131

127-
let dresolvers = Plug.create ~doc:dresolvers_doc "audio file formats (duration)"
132+
let conf_dresolvers =
133+
Dtools.Conf.list ~p:(conf#plug "dresolvers") ~d:[]
134+
"Methods to extract file duration."
135+
136+
let f c v =
137+
match c#get_d with
138+
| None -> c#set_d (Some [v])
139+
| Some d -> c#set_d (Some (d @ [v]))
140+
141+
let dresolvers =
142+
Plug.create ~doc:dresolvers_doc
143+
~register_hook:(fun name _ -> f conf_dresolvers name)
144+
"audio file formats (duration)"
145+
146+
let get_dresolvers ~file () =
147+
let extension = try Utils.get_ext file with _ -> "" in
148+
let f cur name =
149+
match Plug.get dresolvers name with
150+
| Some ({ file_extensions } as p)
151+
when List.mem extension (file_extensions ()) ->
152+
(name, p) :: cur
153+
| Some _ -> cur
154+
| None ->
155+
log#severe "Cannot find duration resolver %s" name;
156+
cur
157+
in
158+
let resolvers = List.fold_left f [] conf_dresolvers#get in
159+
List.sort
160+
(fun (_, a) (_, b) -> compare (b.dpriority ()) (a.dpriority ()))
161+
resolvers
128162

129163
let compute_duration ~metadata file =
130164
try
131-
Plug.iter dresolvers (fun _ resolver ->
165+
List.iter
166+
(fun (name, { dpriority; dresolver }) ->
132167
try
133-
let ans = resolver ~metadata file in
168+
log#info "Trying duration resolver %s (priority: %d) for file %s.."
169+
name (dpriority ())
170+
(Lang_string.quote_string file);
171+
let ans = dresolver ~metadata file in
134172
raise (Duration ans)
135173
with
136174
| Duration e -> raise (Duration e)
137-
| _ -> ());
175+
| _ -> ())
176+
(get_dresolvers ~file ());
138177
raise Not_found
139178
with Duration d -> d
140179

src/core/request.mli

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ type resolve_flag = [ `Resolved | `Failed | `Timeout ]
113113
(** Metadata resolvers priorities. *)
114114
val conf_metadata_decoder_priorities : Dtools.Conf.ut
115115

116+
(** Read the request's metadata. *)
117+
val read_metadata : t -> unit
118+
116119
(** [resolve request timeout] tries to resolve the request within
117120
[timeout] seconds. *)
118121
val resolve : t -> float -> resolve_flag
@@ -165,8 +168,14 @@ val done_playing : source:Source.source -> t -> unit
165168

166169
(** {1 Plugs} *)
167170

171+
type dresolver = {
172+
dpriority : unit -> int;
173+
file_extensions : unit -> string list;
174+
dresolver : metadata:Frame.metadata -> string -> float;
175+
}
176+
168177
(** Functions for computing duration. *)
169-
val dresolvers : (metadata:Frame.metadata -> string -> float) Plug.t
178+
val dresolvers : dresolver Plug.t
170179

171180
(** Type for a metadata resolver. Resolvers are executed in priority
172181
order and the first returned metadata take precedence over any other

0 commit comments

Comments
 (0)