Skip to content

Commit 3327fbe

Browse files
authored
Merge pull request #314 from avTranscoder/dev/add_audio_phase_meter_app
Add audio phase meter application
2 parents 2e4a8fe + 51704a9 commit 3327fbe

File tree

3 files changed

+173
-0
lines changed

3 files changed

+173
-0
lines changed

app/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# C++ apps
2+
add_subdirectory(avAudioPhaseMeter)
23
add_subdirectory(avInfo)
34
add_subdirectory(avMeta)
45
add_subdirectory(avPlayer)

app/avAudioPhaseMeter/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
### cpp/avProcessor
2+
3+
# Load custom cmake utilities
4+
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
5+
include(AvTranscoderMacros)
6+
7+
# Build app
8+
add_executable(avaudiophasemeter avAudioPhaseMeter.cpp)
9+
set_target_properties(avaudiophasemeter PROPERTIES VERSION ${AVTRANSCODER_VERSION})
10+
target_link_libraries(avaudiophasemeter avtranscoder-shared)
11+
12+
# Install app
13+
if(WIN32)
14+
set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter.exe")
15+
else()
16+
set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter" "${CMAKE_CURRENT_BINARY_DIR}/avaudiophasemeter-${AVTRANSCODER_VERSION}")
17+
endif()
18+
19+
install(
20+
FILES ${BINARY_FILES}
21+
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE
22+
DESTINATION "bin/"
23+
OPTIONAL
24+
)
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include <AvTranscoder/transcoder/Transcoder.hpp>
2+
#include <AvTranscoder/file/OutputFile.hpp>
3+
#include <AvTranscoder/progress/ConsoleProgress.hpp>
4+
5+
#include <iostream>
6+
#include <iomanip>
7+
#include <vector>
8+
#include <fstream>
9+
#include <sstream>
10+
#include <cstdlib>
11+
12+
std::vector<avtranscoder::InputStreamDesc> parseConfigFile(const std::string& configFilename)
13+
{
14+
std::vector<avtranscoder::InputStreamDesc> result;
15+
16+
std::ifstream configFile(configFilename.c_str(), std::ifstream::in);
17+
18+
std::string line;
19+
size_t countLines = 0;
20+
while(std::getline(configFile, line))
21+
{
22+
if(++countLines > 2)
23+
{
24+
throw std::runtime_error("Audio phase analysis can only be done on a stereo pair, i.e. two channels (see usage).");
25+
}
26+
27+
std::istringstream is_line(line);
28+
std::string filename;
29+
if(std::getline(is_line, filename, '='))
30+
{
31+
std::string stream;
32+
std::getline(is_line, stream);
33+
34+
std::stringstream ss(stream);
35+
size_t streamIndex = 0;
36+
char separator;
37+
int channelIndex = -1;
38+
ss >> streamIndex;
39+
ss >> separator;
40+
if(separator == '.')
41+
{
42+
ss >> channelIndex;
43+
}
44+
45+
bool newInputDescAdded = false;
46+
// if we already have an input description with the same filename/streamIndex, add only the new channelIndex
47+
for(std::vector<avtranscoder::InputStreamDesc>::iterator it = result.begin(); it != result.end(); ++it)
48+
{
49+
if(it->_filename == filename && it->_streamIndex == streamIndex)
50+
{
51+
it->_channelIndexArray.push_back(channelIndex);
52+
newInputDescAdded = true;
53+
break;
54+
}
55+
}
56+
if(!newInputDescAdded)
57+
{
58+
result.push_back(avtranscoder::InputStreamDesc(filename, streamIndex, channelIndex));
59+
}
60+
}
61+
}
62+
63+
configFile.close();
64+
65+
return result;
66+
}
67+
68+
void displayUsage(const std::string& program)
69+
{
70+
std::cout << "Usage: " << program << " CONFIG OUTPUT [OPTIONS]" << std::endl << std::endl;
71+
std::cout << "\tCONFIG: input configuration file" << std::endl;
72+
std::cout << "\t\tEach line represents one audio stream analysed." << std::endl;
73+
std::cout << "\t\tPattern of each line is:" << std::endl;
74+
std::cout << "\t\t[inputFile]=STREAM_INDEX.CHANNEL_INDEX" << std::endl;
75+
std::cout << "\t\tWARNING: audio phase analyser only support stereo layout, i.e. two lines in this configuration." << std::endl << std::endl;
76+
std::cout << "\tOUTPUT: metadata output file" << std::endl;
77+
std::cout << "\t\tPattern for each frame is:" << std::endl;
78+
std::cout << "\t\t `frame:[FRAME_ID] pts:[PTS] pts_time:[PTS_TIME]" << std::endl;
79+
std::cout << "\t\t lavfi.aphasemeter.phase=[PHASE_VALUE]`" << std::endl << std::endl;
80+
std::cout << "\tOPTIONS:" << std::endl;
81+
std::cout << "\t\t--info set log level to AV_LOG_INFO" << std::endl;
82+
std::cout << "\t\t--debug set log level to AV_LOG_DEBUG" << std::endl;
83+
std::cout << "\t\t--help display this help" << std::endl << std::endl;
84+
}
85+
86+
int main(int argc, char** argv)
87+
{
88+
// Preload FFmpeg context
89+
avtranscoder::preloadCodecsAndFormats();
90+
avtranscoder::Logger::setLogLevel(AV_LOG_QUIET);
91+
92+
if(argc < 3)
93+
{
94+
displayUsage(argv[0]);
95+
}
96+
97+
// List command line arguments
98+
std::vector<std::string> arguments;
99+
for(int argument = 1; argument < argc; ++argument)
100+
{
101+
arguments.push_back(argv[argument]);
102+
}
103+
for(size_t argument = 0; argument < arguments.size(); ++argument)
104+
{
105+
if(arguments.at(argument) == "--help")
106+
{
107+
displayUsage(argv[0]);
108+
return 0;
109+
}
110+
else if(arguments.at(argument) == "--debug")
111+
{
112+
avtranscoder::Logger::setLogLevel(AV_LOG_DEBUG);
113+
}
114+
else if(arguments.at(argument) == "--info")
115+
{
116+
avtranscoder::Logger::setLogLevel(AV_LOG_INFO);
117+
}
118+
}
119+
120+
try
121+
{
122+
std::string configFilePath(arguments.at(0));
123+
std::string outputFilePath(arguments.at(1));
124+
std::vector<avtranscoder::InputStreamDesc> inputStreamsToAnalyse = parseConfigFile(configFilePath);
125+
126+
avtranscoder::OutputFile outputFile(outputFilePath, "null"); // the output file will be overwritten by the extracted metadata
127+
128+
avtranscoder::Transcoder transcoder(outputFile);
129+
transcoder.setProcessMethod(avtranscoder::eProcessMethodBasedOnStream, 0);
130+
transcoder.addStream(inputStreamsToAnalyse);
131+
132+
avtranscoder::StreamTranscoder& streamTranscoder = transcoder.getStreamTranscoder(0);
133+
avtranscoder::FilterGraph* filterGraph = streamTranscoder.getFilterGraph();
134+
filterGraph->addFilter("aphasemeter", "video=0");
135+
filterGraph->addFilter("ametadata", "mode=print:file=" + outputFilePath);
136+
137+
avtranscoder::ConsoleProgress progress;
138+
transcoder.process(progress);
139+
}
140+
catch(std::exception& e)
141+
{
142+
std::cerr << "ERROR: during process, an error occured: " << e.what() << std::endl;
143+
}
144+
catch(...)
145+
{
146+
std::cerr << "ERROR: during process, an unknown error occured" << std::endl;
147+
}
148+
}

0 commit comments

Comments
 (0)