-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathtranscode_aac.ml
117 lines (102 loc) · 3.67 KB
/
transcode_aac.ml
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
let () =
if Array.length Sys.argv < 3 then (
Printf.eprintf "Usage: %s <input_file> <output_file>.mp4\n" Sys.argv.(0);
exit 1);
if Array.length Sys.argv = 4 && Sys.argv.(3) = "macosx" then exit 0;
Avutil.Log.set_level `Verbose;
let src = Av.open_input Sys.argv.(1) in
let idx, istream, params = Av.find_best_audio_stream src in
let () =
match Avcodec.descriptor params with
| Some { name = d; _ } ->
Printf.printf
"Input format: %s (channel layout: %s, sample format: %s, sample \
rate: %d)\n\
%!"
d
(Avutil.Channel_layout.get_description
(Avcodec.Audio.get_channel_layout params))
(Option.value ~default:"(unknown)"
(Avutil.Sample_format.get_name
(Avcodec.Audio.get_sample_format params)))
(Avcodec.Audio.get_sample_rate params)
| _ -> Printf.printf "Unknown input format..\n!"
in
let codec = Avcodec.Audio.find_encoder_by_name "aac" in
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
let ostream =
Av.open_output Sys.argv.(2)
|> Av.new_audio_stream ~channel_layout ~sample_format ~sample_rate
~time_base ~codec
in
let () =
match Avcodec.descriptor (Av.get_codec_params ostream) with
| Some { name = d; _ } ->
Printf.printf
"Output format: %s (channel layout: %s, sample format: %s, sample \
rate: %d)\n\
%!"
d
(Avutil.Channel_layout.get_description
(Avcodec.Audio.get_channel_layout params))
(Option.value ~default:"(unknown)"
(Avutil.Sample_format.get_name
(Avcodec.Audio.get_sample_format params)))
(Avcodec.Audio.get_sample_rate params)
| _ -> Printf.printf "Unknown output format..\n!"
in
let filter = ref None in
let get_filter frame =
match !filter with
| Some f -> f
| None ->
let in_params =
{
Avfilter.Utils.sample_rate =
Avutil.Audio.frame_get_sample_rate frame;
channel_layout = Avutil.Audio.frame_get_channel_layout frame;
sample_format = Avutil.Audio.frame_get_sample_format frame;
}
in
let in_time_base = { Avutil.num = 1; den = sample_rate } in
let out_frame_size =
if List.mem `Variable_frame_size (Avcodec.capabilities codec) then
512
else Av.get_frame_size ostream
in
let out_params =
{ Avfilter.Utils.sample_rate; sample_format; channel_layout }
in
let f =
Avfilter.Utils.init_audio_converter ~in_params ~in_time_base
~out_params ~out_frame_size ()
in
filter := Some f;
f
in
let pts = ref 0L in
let on_frame frame =
Avutil.Frame.set_pts frame (Some !pts);
pts := Int64.add !pts (Int64.of_int (Avutil.Audio.frame_nb_samples frame));
Av.write_frame ostream frame
in
let write_frame frame =
let filter = get_filter frame in
Avfilter.Utils.convert_audio filter on_frame (`Frame frame)
in
let rec f () =
match Av.read_input ~audio_frame:[istream] src with
| `Audio_frame (i, frame) when i = idx ->
write_frame frame;
f ()
| exception Avutil.Error `Eof -> ()
| _ -> f ()
in
f ();
Av.get_input istream |> Av.close;
Av.get_output ostream |> Av.close;
Gc.full_major ();
Gc.full_major ()