Skip to content

Commit b899eab

Browse files
committed
Add AvAudioPhaseMeter application
1 parent b49c7c0 commit b899eab

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-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: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
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+
throw std::runtime_error("Audio phase analysis can only be done on a stereo pair, i.e. two channels (see usage).");
24+
25+
std::istringstream is_line(line);
26+
std::string filename;
27+
if(std::getline(is_line, filename, '='))
28+
{
29+
std::string stream;
30+
std::getline(is_line, stream);
31+
32+
std::stringstream ss(stream);
33+
size_t streamIndex = 0;
34+
char separator;
35+
int channelIndex = -1;
36+
ss >> streamIndex;
37+
ss >> separator;
38+
if(separator == '.')
39+
ss >> channelIndex;
40+
41+
bool newInputDescAdded = false;
42+
// if we already have an input description with the same filename/streamIndex, add only the new channelIndex
43+
for(std::vector<avtranscoder::InputStreamDesc>::iterator it = result.begin(); it != result.end(); ++it)
44+
{
45+
if(it->_filename == filename && it->_streamIndex == streamIndex)
46+
{
47+
it->_channelIndexArray.push_back(channelIndex);
48+
newInputDescAdded = true;
49+
break;
50+
}
51+
}
52+
if(! newInputDescAdded)
53+
result.push_back(avtranscoder::InputStreamDesc(filename, streamIndex, channelIndex));
54+
}
55+
}
56+
57+
configFile.close();
58+
59+
return result;
60+
}
61+
62+
void displayUsage(const std::string& program)
63+
{
64+
std::cout << "Usage: " << program << " CONFIG OUTPUT [OPTIONS]" << std::endl << std::endl;
65+
std::cout << "\tCONFIG: input configuration file" << std::endl;
66+
std::cout << "\t\tEach line represents one audio stream analysed." << std::endl;
67+
std::cout << "\t\tPattern of each line is:" << std::endl;
68+
std::cout << "\t\t[inputFile]=STREAM_INDEX.CHANNEL_INDEX" << std::endl;
69+
std::cout << "\t\tWARNING: audio phase analyser only support stereo layout, i.e. two lines in this configuration." << std::endl << std::endl;
70+
std::cout << "\tOUTPUT: metadata output file" << std::endl;
71+
std::cout << "\t\tPattern for each frame is:" << std::endl;
72+
std::cout << "\t\t `frame:[FRAME_ID] pts:[PTS] pts_time:[PTS_TIME]" << std::endl;
73+
std::cout << "\t\t lavfi.aphasemeter.phase=[PHASE_VALUE]`" << std::endl << std::endl;
74+
std::cout << "\tOPTIONS:" << std::endl;
75+
std::cout << "\t\t--info set log level to AV_LOG_INFO" << std::endl;
76+
std::cout << "\t\t--debug set log level to AV_LOG_DEBUG" << std::endl;
77+
std::cout << "\t\t--help display this help" << std::endl << std::endl;
78+
}
79+
80+
int main(int argc, char** argv)
81+
{
82+
// Preload FFmpeg context
83+
avtranscoder::preloadCodecsAndFormats();
84+
avtranscoder::Logger::setLogLevel(AV_LOG_QUIET);
85+
86+
if(argc < 3) {
87+
displayUsage(argv[0]);
88+
}
89+
90+
// List command line arguments
91+
std::vector<std::string> arguments;
92+
for(int argument = 1; argument < argc; ++argument)
93+
{
94+
arguments.push_back(argv[argument]);
95+
}
96+
for(size_t argument = 0; argument < arguments.size(); ++argument)
97+
{
98+
if(arguments.at(argument) == "--help")
99+
{
100+
displayUsage(argv[0]);
101+
return 0;
102+
}
103+
else if(arguments.at(argument) == "--debug")
104+
{
105+
avtranscoder::Logger::setLogLevel(AV_LOG_DEBUG);
106+
}
107+
else if(arguments.at(argument) == "--info")
108+
{
109+
avtranscoder::Logger::setLogLevel(AV_LOG_INFO);
110+
}
111+
}
112+
113+
try
114+
{
115+
std::string configFilePath(arguments.at(0));
116+
std::string outputFilePath(arguments.at(1));
117+
std::vector<avtranscoder::InputStreamDesc> inputStreamsToAnalyse = parseConfigFile(configFilePath);
118+
119+
avtranscoder::OutputFile outputFile(outputFilePath, "null"); // the output file will be overwritten by the extracted metadata
120+
121+
avtranscoder::Transcoder transcoder(outputFile);
122+
transcoder.setProcessMethod(avtranscoder::eProcessMethodBasedOnStream, 0);
123+
transcoder.addStream(inputStreamsToAnalyse);
124+
125+
avtranscoder::StreamTranscoder& streamTranscoder = transcoder.getStreamTranscoder(0);
126+
avtranscoder::FilterGraph* filterGraph = streamTranscoder.getFilterGraph();
127+
filterGraph->addFilter("aphasemeter", "video=0");
128+
filterGraph->addFilter("ametadata", "mode=print:file=" + outputFilePath);
129+
130+
avtranscoder::ConsoleProgress progress;
131+
transcoder.process(progress);
132+
}
133+
catch(std::exception& e)
134+
{
135+
std::cerr << "ERROR: during process, an error occured: " << e.what() << std::endl;
136+
}
137+
catch(...)
138+
{
139+
std::cerr << "ERROR: during process, an unknown error occured" << std::endl;
140+
}
141+
}

0 commit comments

Comments
 (0)