1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
let () = Printexc.record_backtrace true
let () =
if Array.length Sys.argv < 3 then (
Printf.printf "usage: %s input_file output_file\n" Sys.argv.(0);
exit 1);
Avutil.Log.set_level `Debug;
Avutil.Log.set_callback print_string;
let src = Av.open_input Sys.argv.(1) in
let dst = Av.open_output Sys.argv.(2) in
let audio_codec = Avcodec.Audio.find_encoder_by_name "ac3" in
let audio_params, audio_input, idx, oass =
Av.find_best_audio_stream src |> fun (i, audio_input, params) ->
let channel_layout = Avcodec.Audio.get_channel_layout params in
let sample_format = Avcodec.Audio.get_sample_format params in
let sample_rate = Avcodec.Audio.get_sample_rate params in
let time_base = { Avutil.num = 1; den = sample_rate } in
( params,
audio_input,
i,
Av.new_audio_stream ~channel_layout ~sample_format ~sample_rate ~time_base
~codec:audio_codec dst )
in
let frame_size =
if List.mem `Variable_frame_size (Avcodec.capabilities audio_codec) then 512
else Av.get_frame_size oass
in
let filter =
let config = Avfilter.init () in
let abuffer =
let time_base = Av.get_time_base audio_input in
let sample_rate = Avcodec.Audio.get_sample_rate audio_params in
let sample_format =
Avutil.Sample_format.get_id
(Avcodec.Audio.get_sample_format audio_params)
in
let channel_layout =
Avutil.Channel_layout.get_description
(Avcodec.Audio.get_channel_layout audio_params)
in
let args =
[
`Pair ("time_base", `Rational time_base);
`Pair ("sample_rate", `Int sample_rate);
`Pair ("sample_fmt", `Int sample_format);
`Pair ("channel_layout", `String channel_layout);
]
in
{
Avfilter.node_name = "in";
node_args = Some args;
node_pad = List.hd Avfilter.(abuffer.io.outputs.audio);
}
in
let outputs = { Avfilter.audio = [abuffer]; video = [] } in
let sink =
{
Avfilter.node_name = "out";
node_args = None;
node_pad = List.hd Avfilter.(abuffersink.io.inputs.audio);
}
in
let inputs = { Avfilter.audio = [sink]; video = [] } in
let _ =
Avfilter.parse { inputs; outputs }
"aresample=22050,aformat=channel_layouts=stereo" config
in
Avfilter.launch config
in
let _, output = List.hd Avfilter.(filter.outputs.audio) in
let context = output.context in
Avfilter.set_frame_size context frame_size;
let time_base = Avfilter.time_base context in
Printf.printf
"Sink info:\n\
time_base: %d/%d\n\
channels: %d\n\
channel_layout: %s\n\
sample_rate: %d\n"
time_base.Avutil.num time_base.Avutil.den
(Avfilter.channels context)
(Avutil.Channel_layout.get_description (Avfilter.channel_layout context))
(Avfilter.sample_rate context);
let process_audio i frm =
try
assert (i = idx);
let _, input = List.hd Avfilter.(filter.inputs.audio) in
input frm;
let rec flush () =
try
Av.write_frame oass (output.handler ());
flush ()
with Avutil.Error `Eagain -> ()
in
flush ()
with Not_found -> ()
in
Gc.full_major ();
Gc.full_major ();
let rec f () =
match Av.read_input ~audio_frame:[audio_input] src with
| `Audio_frame (i, frame) ->
process_audio i (`Frame frame);
f ()
| exception Avutil.Error `Eof -> (
try process_audio idx `Flush with Avutil.Error `Eof -> ())
| _ -> f ()
in
f ();
Av.close src;
Av.close dst;
Gc.full_major ();
Gc.full_major ()
|