File: aresample.ml

package info (click to toggle)
ocaml-ffmpeg 1.2.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 908 kB
  • sloc: ansic: 6,412; ml: 6,166; makefile: 3
file content (124 lines) | stat: -rw-r--r-- 3,668 bytes parent folder | download | duplicates (2)
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 ()