File: encoding.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 (137 lines) | stat: -rw-r--r-- 3,874 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
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 ()