Skip to content

Commit 2e4a8fe

Browse files
Merge pull request #313 from avTranscoder/dev/support_external_encoder
Support external encoder
2 parents b919a15 + 6671f36 commit 2e4a8fe

File tree

11 files changed

+460
-2
lines changed

11 files changed

+460
-2
lines changed

app/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ add_subdirectory(avInfo)
33
add_subdirectory(avMeta)
44
add_subdirectory(avPlayer)
55
add_subdirectory(avProcessor)
6+
add_subdirectory(customEncoder)
67

78
# Python apps
89
add_subdirectory(pyProcessor)

app/customEncoder/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
### cpp/customEncoder
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(custom-encoder customEncoder.cpp)
9+
set_target_properties(custom-encoder PROPERTIES VERSION ${AVTRANSCODER_VERSION})
10+
target_link_libraries(custom-encoder avtranscoder-shared)
11+
12+
# Install app
13+
if(WIN32)
14+
set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder.exe")
15+
else()
16+
set(BINARY_FILES "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder" "${CMAKE_CURRENT_BINARY_DIR}/custom-encoder-${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+
)

app/customEncoder/customEncoder.cpp

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
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+
void parseConfigFile(const std::string& configFilename, avtranscoder::Transcoder& transcoder)
13+
{
14+
std::ifstream configFile(configFilename.c_str(), std::ifstream::in);
15+
16+
std::string line;
17+
while(std::getline(configFile, line))
18+
{
19+
std::istringstream is_line(line);
20+
std::string filename;
21+
if(std::getline(is_line, filename, '='))
22+
{
23+
std::string streamId;
24+
if(std::getline(is_line, streamId, ':'))
25+
{
26+
std::string transcodeProfile;
27+
std::getline(is_line, transcodeProfile);
28+
29+
std::stringstream ss(streamId);
30+
size_t streamIndex = 0;
31+
char separator = 'x';
32+
std::vector<size_t> channelIndexArray;
33+
ss >> streamIndex;
34+
ss >> separator;
35+
if(separator == '.')
36+
{
37+
int subStreamIndex = -1;
38+
ss >> subStreamIndex;
39+
channelIndexArray.push_back(subStreamIndex);
40+
}
41+
42+
// generated stream
43+
if(!filename.length())
44+
transcoder.addGenerateStream(transcodeProfile);
45+
else
46+
{
47+
avtranscoder::InputStreamDesc inputDesc(filename, streamIndex, channelIndexArray);
48+
transcoder.addStream(inputDesc, transcodeProfile);
49+
}
50+
}
51+
}
52+
}
53+
54+
configFile.close();
55+
}
56+
57+
58+
59+
class AvExport CustomCodec
60+
: public avtranscoder::ICodec
61+
{
62+
public:
63+
CustomCodec()
64+
: avtranscoder::ICodec(avtranscoder::eCodecTypeEncoder, AV_CODEC_ID_PCM_S24LE)
65+
{
66+
}
67+
68+
void openCodec(){}
69+
void closeCodec(){}
70+
71+
std::string getCodecName() const { return "Custom Encoder"; };
72+
AVCodecID getCodecId() const { return AV_CODEC_ID_PCM_S24LE; }
73+
avtranscoder::ECodecType getCodecType() const { return avtranscoder::eCodecTypeEncoder; }
74+
int getLatency() const { return 0; }
75+
76+
avtranscoder::OptionArray getOptions() {
77+
std::vector<avtranscoder::Option> options;
78+
return options;
79+
}
80+
};
81+
82+
83+
class AvExport CustomEncoder
84+
: public avtranscoder::IEncoder
85+
{
86+
public:
87+
CustomEncoder()
88+
: _codec()
89+
{}
90+
/**
91+
* @brief Setup the encoder
92+
* @param profile: set encoder parameters from the given profile
93+
* @note Open the encoder.
94+
*/
95+
void setupEncoder(const avtranscoder::ProfileLoader::Profile& profile = avtranscoder::ProfileLoader::Profile()) {
96+
return;
97+
};
98+
99+
/**
100+
* @brief Encode a new frame, and get coded frame
101+
* @param sourceFrame: frame that needs to be encoded
102+
* @param codedFrame: output encoded coded data (first frames can be delayed)
103+
* @return status of encoding
104+
* @throw runtime_error if the encoded process failed.
105+
*/
106+
bool encodeFrame(const avtranscoder::IFrame& sourceFrame, avtranscoder::CodedData& codedFrame) {
107+
codedFrame.assign(5760, 0);
108+
return true;
109+
};
110+
111+
/**
112+
* @brief Get the frames remaining into the encoder
113+
* @param codedFrame: output encoded data
114+
* @return status of encoding
115+
* @throw runtime_error if the encoded process failed.
116+
*/
117+
bool encodeFrame(avtranscoder::CodedData& codedFrame) {
118+
return false;
119+
};
120+
121+
/**
122+
* @brief Get codec used for encoding.
123+
* @return a reference to the codec
124+
*/
125+
avtranscoder::ICodec& getCodec() {
126+
return _codec;
127+
};
128+
129+
private:
130+
CustomCodec _codec;
131+
};
132+
133+
134+
int main(int argc, char** argv)
135+
{
136+
std::string help;
137+
help += "Usage\n";
138+
help += "\tavprocessor INPUT_FILE_NAME OUTPUT_FILE_NAME [--verbose] [--logFile] [--help]\n";
139+
help += "Command line options\n";
140+
help += "\t--verbose: set log level to AV_LOG_DEBUG\n";
141+
help += "\t--logFile: put log in 'avtranscoder.log' file\n";
142+
help += "\t--help: display this help\n";
143+
144+
// Preload FFmpeg context
145+
avtranscoder::preloadCodecsAndFormats();
146+
avtranscoder::Logger::setLogLevel(AV_LOG_QUIET);
147+
148+
// List command line arguments
149+
std::vector<std::string> arguments;
150+
for(int argument = 1; argument < argc; ++argument)
151+
{
152+
arguments.push_back(argv[argument]);
153+
}
154+
for(size_t argument = 0; argument < arguments.size(); ++argument)
155+
{
156+
if(arguments.at(argument) == "--help")
157+
{
158+
std::cout << help << std::endl;
159+
return 0;
160+
}
161+
else if(arguments.at(argument) == "--verbose")
162+
{
163+
avtranscoder::Logger::setLogLevel(AV_LOG_DEBUG);
164+
}
165+
else if(arguments.at(argument) == "--logFile")
166+
{
167+
avtranscoder::Logger::logInFile();
168+
}
169+
}
170+
171+
// Check required arguments
172+
if(argc < 3)
173+
{
174+
std::cout << "avprocessor can rewrap or transcode inputs to create an output media file." << std::endl;
175+
std::cout << "Use option --help to display help" << std::endl;
176+
return (-1);
177+
}
178+
179+
try
180+
{
181+
std::string output_format = "s24le";
182+
avtranscoder::OutputFile outputFile(argv[2], output_format);
183+
184+
avtranscoder::Transcoder transcoder(outputFile);
185+
transcoder.setProcessMethod(avtranscoder::eProcessMethodBasedOnStream);
186+
187+
CustomEncoder* customEncoder = new CustomEncoder;
188+
avtranscoder::InputStreamDesc inputDescLeft(argv[1], 1, 0);
189+
avtranscoder::InputStreamDesc inputDescRight(argv[1], 2, 0);
190+
191+
std::vector<avtranscoder::InputStreamDesc> inputDescriptors;
192+
inputDescriptors.push_back(avtranscoder::InputStreamDesc(argv[1], 1, 0));
193+
inputDescriptors.push_back(avtranscoder::InputStreamDesc(argv[1], 2, 0));
194+
195+
transcoder.addStream(inputDescriptors, customEncoder);
196+
197+
avtranscoder::ConsoleProgress progress;
198+
transcoder.process(progress);
199+
}
200+
catch(std::exception& e)
201+
{
202+
std::cerr << "ERROR: during process, an error occured: " << e.what() << std::endl;
203+
}
204+
catch(...)
205+
{
206+
std::cerr << "ERROR: during process, an unknown error occured" << std::endl;
207+
}
208+
}

src/AvTranscoder/file/IOutputFile.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,15 @@ class AvExport IOutputFile
5151
throw std::logic_error("function is not implemented");
5252
}
5353

54+
/**
55+
* @brief Add a custom output stream
56+
* @param iCodecDesc description of output codec
57+
**/
58+
virtual IOutputStream& addCustomStream(const ICodec& iCodecDesc)
59+
{
60+
throw std::logic_error("function is not implemented");
61+
}
62+
5463
/**
5564
* @brief Write the header of file (if necessary)
5665
**/

src/AvTranscoder/file/OutputFile.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,25 @@ IOutputStream& OutputFile::addAudioStream(const AudioCodec& audioDesc)
8888
return *outputStream;
8989
}
9090

91+
IOutputStream& OutputFile::addCustomStream(const ICodec& iCodecDesc)
92+
{
93+
AVStream& stream = _formatContext.addAVStream(iCodecDesc.getAVCodec());
94+
95+
stream.codec->sample_rate = 48000;
96+
stream.codec->channels = 1;
97+
stream.codec->channel_layout = AV_CH_LAYOUT_MONO;
98+
stream.codec->sample_fmt = AV_SAMPLE_FMT_S32;
99+
stream.codec->frame_size = 1920;
100+
101+
// need to set the time_base on the AVCodecContext of the AVStream
102+
av_reduce(&stream.codec->time_base.num, &stream.codec->time_base.den, 1, 1, INT_MAX);
103+
104+
OutputStream* outputStream = new OutputStream(*this, _formatContext.getNbStreams() - 1);
105+
_outputStreams.push_back(outputStream);
106+
107+
return *outputStream;
108+
}
109+
91110
IOutputStream& OutputFile::addDataStream(const DataCodec& dataDesc)
92111
{
93112
_formatContext.addAVStream(dataDesc.getAVCodec());

src/AvTranscoder/file/OutputFile.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class AvExport OutputFile : public IOutputFile
3737
IOutputStream& addVideoStream(const VideoCodec& videoDesc);
3838
IOutputStream& addAudioStream(const AudioCodec& audioDesc);
3939
IOutputStream& addDataStream(const DataCodec& dataDesc);
40+
IOutputStream& addCustomStream(const ICodec& iCodecDesc);
4041

4142
/**
4243
* @brief Open ressource, write header, and setup specific wrapping options given when call setupWrapping.

0 commit comments

Comments
 (0)