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 125 126 127 128 129 130 131 132 133 134 135 136 137
|
open Avutil
module Resampler = Swresample.Make (Swresample.FloatArray) (Swresample.Frame)
let fill_image_y width height frame_index planes =
(* Y *)
let data, linesize = planes.(0) in
for y = 0 to height - 1 do
let off = y * linesize in
for x = 0 to width - 1 do
data.{x + off} <- x + y + (frame_index * 3)
done
done
let fill_image_on width height frame_index planes =
fill_image_y width height frame_index planes;
(* Cb and Cr *)
let data_cb, _ = planes.(1) in
let data_cr, linesize = planes.(2) in
for y = 0 to (height / 2) - 1 do
let off = y * linesize in
for x = 0 to (width / 2) - 1 do
data_cb.{x + off} <- 128 + y + (frame_index * 2);
data_cr.{x + off} <- 64 + x + (frame_index * 5)
done
done
let fill_image_off width height frame_index planes =
fill_image_y width height frame_index planes;
(* Cb and Cr *)
let data_cb, _ = planes.(1) in
let data_cr, linesize = planes.(2) in
for y = 0 to (height / 2) - 1 do
let off = y * linesize in
for x = 0 to (width / 2) - 1 do
data_cb.{x + off} <- 128;
data_cr.{x + off} <- 128
done
done
let () =
if Array.length Sys.argv < 5 then (
Printf.printf
"Usage: %s <output file> <audio codec> <video codec> <subtitle codec>\n"
Sys.argv.(0);
exit 1);
Avutil.Log.set_level `Debug;
Avutil.Log.set_callback print_string;
let dst = Av.open_output Sys.argv.(1) in
Av.set_output_metadata dst [("Title", "On Off")];
let pi = 4.0 *. atan 1.0 in
let sample_rate = 44100 in
let codec = Avcodec.Audio.find_encoder_by_name Sys.argv.(2) in
let time_base = { Avutil.num = 1; den = sample_rate } in
let audio_pts = ref 0L in
let sample_format = Avcodec.Audio.find_best_sample_format codec `Dbl in
let oas =
Av.new_audio_stream ~channel_layout:Avutil.Channel_layout.stereo ~time_base
~sample_rate ~sample_format ~codec dst
in
let params = Av.get_codec_params oas in
let audio_frame_size = Av.get_frame_size oas in
Av.set_metadata oas [("Media", "Audio")];
let rsp = Resampler.to_codec Avutil.Channel_layout.mono sample_rate params in
let c = 2. *. pi *. 440. /. float_of_int sample_rate in
let audio_on_off =
[|
Array.init audio_frame_size (fun t -> sin (float_of_int t *. c));
Array.make audio_frame_size 0.;
|]
in
let width = 352 in
let height = 288 in
let pixel_format = `Yuv420p in
let frate = 25 in
let frame_rate = { Avutil.num = frate; den = 1 } in
let time_base = { Avutil.num = 1; den = frate } in
let video_pts = ref 0L in
let codec = Avcodec.Video.find_encoder_by_name Sys.argv.(3) in
let ovs =
Av.new_video_stream ~time_base ~width ~height ~pixel_format ~frame_rate
~codec dst
in
Av.set_metadata ovs [("Media", "Video")];
let frame = Video.create_frame width height pixel_format in
let video_on_off = [| fill_image_on; fill_image_off |] in
(*
let oss = Av.new_subtitle_stream ~codec_name:Sys.argv.(4) dst in
Av.set_metadata oas ["Media", "Subtitle"];
*)
let duration = 10 in
(*
for i = 0 to duration - 1 do
let s = float_of_int i in
Subtitle_frame.from_lines s (s +. 0.5) [string_of_int i]
|> Av.write oss;
done;
*)
for i = 0 to (frate * duration) - 1 do
let b = i mod frate / 13 in
( audio_on_off.(b) |> Resampler.convert rsp |> fun frame ->
Avutil.Frame.set_pts frame (Some !audio_pts);
audio_pts :=
Int64.add !audio_pts
(Int64.of_int (Avutil.Audio.frame_nb_samples frame));
Av.write_frame oas frame );
Video.frame_visit ~make_writable:true
(video_on_off.(b) width height i)
frame
|> fun frame ->
Avutil.Frame.set_pts frame (Some !video_pts);
video_pts := Int64.succ !video_pts;
Av.write_frame ovs frame
done;
Av.close dst;
Gc.full_major ();
Gc.full_major ()
|