1cabdff1aSopenharmony_ci#!/usr/bin/env perl
2cabdff1aSopenharmony_ci
3cabdff1aSopenharmony_ci# Copyright (c) 2012 Nicolas George
4cabdff1aSopenharmony_ci#
5cabdff1aSopenharmony_ci# This file is part of FFmpeg.
6cabdff1aSopenharmony_ci#
7cabdff1aSopenharmony_ci# FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci# modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci# License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci# version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci#
12cabdff1aSopenharmony_ci# FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci# but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15cabdff1aSopenharmony_ci# See the GNU Lesser General Public License for more details.
16cabdff1aSopenharmony_ci#
17cabdff1aSopenharmony_ci# You should have received a copy of the GNU Lesser General Public License
18cabdff1aSopenharmony_ci# along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
19cabdff1aSopenharmony_ci# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci=head1 NAME
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_cimake_chlayout_test - produce a multichannel test file with the channels
24cabdff1aSopenharmony_ciclearly identified
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci=head1 SYNOPSIS
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_citools/make_chlayout_test I<channels> I<out_options>
29cabdff1aSopenharmony_ci
30cabdff1aSopenharmony_ci=head1 DESCRIPTION
31cabdff1aSopenharmony_ci
32cabdff1aSopenharmony_ciThis script uses B<ffmpeg> and B<libflite> to produce a file with audio
33cabdff1aSopenharmony_cichannels clearly identified by their name. The resulting file can be used to
34cabdff1aSopenharmony_cicheck that the layout and order of channels is correctly handled by a piece
35cabdff1aSopenharmony_ciof software, either a part of B<FFmpeg> or not.
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ciI<channels> is a list of channels or channel layouts, separated by '+'.
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ciI<out_options> is a list of valid ffmpeg outout options, including the
40cabdff1aSopenharmony_cioutput file.
41cabdff1aSopenharmony_ci
42cabdff1aSopenharmony_ciNote that some output codecs or formats can not handle arbitrary channel
43cabdff1aSopenharmony_cilayout.
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ciThis script requires a B<ffmpeg> binary, either in the source tree or in the
46cabdff1aSopenharmony_cisearch path; it must have the flite audio source enabled.
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_ci=head1 EXAMPLES
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_ciCheck that the speakers are correctly plugged:
51cabdff1aSopenharmony_ci
52cabdff1aSopenharmony_ci  tools/make_chlayout_test FL+FR -f alsa default
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ciProduce a 5.1 FLAC file:
55cabdff1aSopenharmony_ci
56cabdff1aSopenharmony_ci  tools/make_chlayout_test 5.1 surround.flac
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci=cut
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_ciuse strict;
61cabdff1aSopenharmony_ciuse warnings;
62cabdff1aSopenharmony_ciuse Getopt::Long ":config" => "require_order";
63cabdff1aSopenharmony_ciuse Pod::Usage;
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_ciGetOptions (
66cabdff1aSopenharmony_ci  "help|usage|?|h" => sub { pod2usage({ -verbose => 1, -exitval => 0 }) },
67cabdff1aSopenharmony_ci  "manpage|m"      => sub { pod2usage({ -verbose => 2, -exitval => 0 }) },
68cabdff1aSopenharmony_ci) and @ARGV >= 2 or pod2usage({ -verbose => 1, -exitval => 1 });
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_cimy $channels = shift @ARGV;
71cabdff1aSopenharmony_cimy @out_options = @ARGV;
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_cimy $ffmpeg = exists $ENV{FFMPEG} ? $ENV{FFMPEG} :
74cabdff1aSopenharmony_ci             $0 =~ /(.*)\// && -e "$1/../ffmpeg" ? "$1/../ffmpeg" :
75cabdff1aSopenharmony_ci             "ffmpeg";
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_cimy %channel_label_to_descr;
78cabdff1aSopenharmony_cimy %layout_to_channels;
79cabdff1aSopenharmony_ci
80cabdff1aSopenharmony_ci{
81cabdff1aSopenharmony_ci  open my $stderr, ">&STDERR";
82cabdff1aSopenharmony_ci  open STDERR, ">", "/dev/null";
83cabdff1aSopenharmony_ci  open my $f, "-|", $ffmpeg, "-layouts" or die "$ffmpeg: $!\n";
84cabdff1aSopenharmony_ci  open STDERR, ">&", $stderr;
85cabdff1aSopenharmony_ci  while (<$f>) {
86cabdff1aSopenharmony_ci    chomp;
87cabdff1aSopenharmony_ci    next if /^NAME/ or /:$/ or /^$/; # skip headings
88cabdff1aSopenharmony_ci    my ($name, $descr) = split " ", $_, 2;
89cabdff1aSopenharmony_ci    next unless $descr;
90cabdff1aSopenharmony_ci    if ($descr =~ /^[[:upper:]]+(?:\+[[:upper:]]+)*$/) {
91cabdff1aSopenharmony_ci      $layout_to_channels{$name} = [ split /\+/, $descr ];
92cabdff1aSopenharmony_ci    } else {
93cabdff1aSopenharmony_ci      $channel_label_to_descr{$name} = $descr;
94cabdff1aSopenharmony_ci    }
95cabdff1aSopenharmony_ci  }
96cabdff1aSopenharmony_ci}
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_cimy @channels = map { @{$layout_to_channels{$_} // [$_]} } split /\+/, $channels;
99cabdff1aSopenharmony_ci
100cabdff1aSopenharmony_cimy $layout = join "+", @channels;
101cabdff1aSopenharmony_cimy $graph = "";
102cabdff1aSopenharmony_cimy $concat_in = "";
103cabdff1aSopenharmony_cifor my $i (0 .. $#channels) {
104cabdff1aSopenharmony_ci  my $label = $channels[$i];
105cabdff1aSopenharmony_ci  my $descr = $channel_label_to_descr{$label}
106cabdff1aSopenharmony_ci    or die "Channel $label not found\n";
107cabdff1aSopenharmony_ci  $graph .= "flite=text='${descr}', aformat=channel_layouts=mono, " .
108cabdff1aSopenharmony_ci            "pan=${layout}:${label}=c0 [ch$i] ;\n";
109cabdff1aSopenharmony_ci  $concat_in .= "[ch$i] ";
110cabdff1aSopenharmony_ci}
111cabdff1aSopenharmony_ci$graph .= "${concat_in}concat=v=0:a=1:n=" . scalar(@channels);
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_ciexec $ffmpeg, "-f", "lavfi", "-i", $graph, @out_options
114cabdff1aSopenharmony_ci  or die "$ffmpeg: $!\n";
115