1 // Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // =============================================================================
15
16 #include "tensorflow/contrib/ffmpeg/ffmpeg_lib.h"
17
18 #include <stdlib.h>
19 #include <vector>
20
21 #include "tensorflow/core/lib/io/path.h"
22 #include "tensorflow/core/lib/strings/str_util.h"
23 #include "tensorflow/core/platform/env.h"
24 #include "tensorflow/core/platform/mutex.h"
25 #include "tensorflow/core/platform/test.h"
26 #include "tensorflow/core/platform/thread_annotations.h"
27 #include "tensorflow/core/util/command_line_flags.h"
28
29 using tensorflow::testing::TensorFlowSrcRoot;
30
31 namespace tensorflow {
32 namespace ffmpeg {
33 namespace {
34
35 const char kTestWavFilename[] = "contrib/ffmpeg/testdata/mono_10khz.wav";
36 const char kTestMp3Filename[] = "contrib/ffmpeg/testdata/test_sound1.mp3";
37
38 // Set to true via a command line flag iff the test is expected to have FFmpeg
39 // installed.
40 mutex mu(LINKER_INITIALIZED);
41 bool should_ffmpeg_be_installed GUARDED_BY(mu) = false;
42
ParseTestFlags(int * argc,char ** argv)43 string ParseTestFlags(int* argc, char** argv) {
44 mutex_lock l(mu);
45 std::vector<Flag> flag_list = {
46 Flag("should_ffmpeg_be_installed", &should_ffmpeg_be_installed,
47 "indicates that ffmpeg should be installed")};
48 string usage = Flags::Usage(argv[0], flag_list);
49 if (!Flags::Parse(argc, argv, flag_list)) {
50 LOG(ERROR) << "\n" << usage;
51 exit(2);
52 }
53 return usage;
54 }
55
TEST(FfmpegLibTest,TestUninstalled)56 TEST(FfmpegLibTest, TestUninstalled) {
57 {
58 mutex_lock l(mu);
59 if (should_ffmpeg_be_installed) {
60 return;
61 }
62 LOG(INFO) << "Assuming FFmpeg is uninstalled.";
63 }
64
65 string filename = io::JoinPath(TensorFlowSrcRoot(), kTestMp3Filename);
66 std::vector<float> output_samples;
67 Status status = ReadAudioFile(filename, "mp3", 5000, 1, &output_samples);
68 ASSERT_EQ(status.code(), error::Code::NOT_FOUND);
69 }
70
TEST(FfmpegLibTest,TestInstalled)71 TEST(FfmpegLibTest, TestInstalled) {
72 {
73 mutex_lock l(mu);
74 if (!should_ffmpeg_be_installed) {
75 return;
76 }
77 LOG(INFO) << "Assuming FFmpeg is installed.";
78 }
79
80 string filename = io::JoinPath(TensorFlowSrcRoot(), kTestMp3Filename);
81 std::vector<float> output_samples;
82 Status status = ReadAudioFile(filename, "mp3", 5000, 1, &output_samples);
83 ASSERT_TRUE(status.ok());
84 }
85
TEST(FfmpegLibTest,TestRoundTripGeneratedWav)86 TEST(FfmpegLibTest, TestRoundTripGeneratedWav) {
87 {
88 mutex_lock l(mu);
89 if (!should_ffmpeg_be_installed) {
90 return;
91 }
92 }
93
94 std::vector<float> sine_wave;
95 sine_wave.reserve(20000);
96 for (int i = 0; i < 20000; ++i) {
97 sine_wave.push_back(std::sin(6.28 * 440.0 * i / 20000.0));
98 }
99 string content;
100 ASSERT_TRUE(CreateAudioFile("wav", 0, 20000, 1, sine_wave, &content).ok());
101 string temp_filename = GetTempFilename("wav");
102 ASSERT_TRUE(WriteStringToFile(Env::Default(), temp_filename, content).ok());
103 std::vector<float> roundtrip_data;
104 ASSERT_TRUE(
105 ReadAudioFile(temp_filename, "wav", 20000, 1, &roundtrip_data).ok());
106 EXPECT_EQ(sine_wave.size(), roundtrip_data.size());
107 size_t min_size = std::min(sine_wave.size(), roundtrip_data.size());
108 for (size_t i = 0; i < min_size; ++i) {
109 EXPECT_NEAR(sine_wave[i], roundtrip_data[i], 0.01);
110 EXPECT_LE(roundtrip_data[i], 1.0);
111 EXPECT_LE(-1.0, roundtrip_data[i]);
112 }
113 }
114
TEST(FfmpegLibTest,TestRoundTripWav)115 TEST(FfmpegLibTest, TestRoundTripWav) {
116 {
117 mutex_lock l(mu);
118 if (!should_ffmpeg_be_installed) {
119 return;
120 }
121 }
122
123 string filename = io::JoinPath(TensorFlowSrcRoot(), kTestWavFilename);
124 std::vector<float> output_samples;
125 ASSERT_TRUE(ReadAudioFile(filename, "wav", 10000, 1, &output_samples).ok());
126 string original_audio;
127 ASSERT_TRUE(ReadFileToString(Env::Default(), filename, &original_audio).ok());
128
129 string written_audio;
130 ASSERT_TRUE(
131 CreateAudioFile("wav", 0, 10000, 1, output_samples, &written_audio).ok());
132
133 EXPECT_EQ(original_audio, written_audio);
134 }
135
136 } // namespace
137 } // namespace ffmpeg
138 } // namespace tensorflow
139
main(int argc,char ** argv)140 int main(int argc, char** argv) {
141 tensorflow::string usage = tensorflow::ffmpeg::ParseTestFlags(&argc, argv);
142 testing::InitGoogleTest(&argc, argv);
143 if (argc != 1) {
144 LOG(ERROR) << usage;
145 return 2;
146 }
147 return RUN_ALL_TESTS();
148 }
149