Commit febc8a07 authored by Stefan Westerfeld's avatar Stefan Westerfeld

Integrate "hls-add" command into audiowmark binary.

Started new argument parser class to properly support shared options between
commands in the future.
Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent 77987aba
......@@ -9,7 +9,7 @@ COMMON_SRC = utils.hh utils.cc convcode.hh convcode.cc random.hh random.cc wavda
audiobuffer.hh
COMMON_LIBS = $(SNDFILE_LIBS) $(FFTW_LIBS) $(LIBGCRYPT_LIBS) $(LIBMPG123_LIBS) $(FFMPEG_LIBS)
audiowmark_SOURCES = audiowmark.cc wmget.cc wmadd.cc $(COMMON_SRC)
audiowmark_SOURCES = audiowmark.cc wmget.cc wmadd.cc hls.cc $(COMMON_SRC)
audiowmark_LDFLAGS = $(COMMON_LIBS)
noinst_PROGRAMS = testconvcode testrandom testmp3 teststream testlimiter testshortcode testmpegts testhls
......@@ -35,5 +35,5 @@ testshortcode_LDFLAGS = $(COMMON_LIBS)
testmpegts_SOURCES = testmpegts.cc $(COMMON_SRC)
testmpegts_LDFLAGS = $(COMMON_LIBS)
testhls_SOURCES = testhls.cc wmadd.cc $(COMMON_SRC)
testhls_SOURCES = testhls.cc wmadd.cc hls.cc $(COMMON_SRC)
testhls_LDFLAGS = $(COMMON_LIBS)
......@@ -27,6 +27,7 @@
#include "random.hh"
#include "wmcommon.hh"
#include "shortcode.hh"
#include "hls.hh"
#include <assert.h>
......@@ -531,9 +532,86 @@ gen_key (const string& outfile)
return 0;
}
class ArgParser
{
vector<string> m_args;
bool
starts_with (const string& s, const string& start)
{
return s.substr (0, start.size()) == start;
}
public:
ArgParser (int argc, char **argv)
{
for (int i = 1; i < argc; i++)
m_args.push_back (argv[i]);
}
bool
parse_cmd (const string& cmd)
{
for (auto it = m_args.begin(); it != m_args.end(); it++)
{
if (!it->empty() && (*it)[0] != '-')
{
if (*it == cmd)
{
m_args.erase (it);
return true;
}
else /* first positional arg is not cmd */
{
return false;
}
}
}
return false;
}
bool
parse_opt (const string& option, int& out)
{
bool found_option = false;
auto it = m_args.begin();
while (it != m_args.end())
{
auto next_it = it + 1;
if (*it == option && next_it != m_args.end()) /* --option 12345 */
{
out = atoi (next_it->c_str());
next_it = m_args.erase (it, it + 2);
found_option = true;
}
else if (starts_with (*it, (option + "="))) /* --option=12345 */
{
out = atoi (it->substr (option.size() + 1).c_str());
next_it = m_args.erase (it);
found_option = true;
}
it = next_it;
}
return found_option;
}
vector<string>
args()
{
return m_args;
}
};
int
main (int argc, char **argv)
{
ArgParser ap (argc, argv);
if (ap.parse_cmd ("hls-add"))
{
ap.parse_opt ("--bit-rate", Params::hls_bit_rate);
auto args = ap.args();
if (args.size() == 3)
return hls_add (args[0], args[1], args[2]);
error ("ARG FAIL!\n");
return 1;
}
parse_options (&argc, &argv);
if (Params::have_key > 1)
......
/*
* Copyright (C) 2018-2020 Stefan Westerfeld
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include "utils.hh"
#include "mpegts.hh"
#include "sfinputstream.hh"
#include "hlsoutputstream.hh"
#include "wmcommon.hh"
using std::string;
using std::map;
using std::min;
int
hls_add (const string& infile, const string& outfile, const string& bits)
{
double start_time = get_time();
TSReader reader;
Error err = reader.load (infile);
if (err)
{
error ("hls_mark: %s\n", err.message());
return 1;
}
info ("hls_elapsed_load %f\n", (get_time() - start_time) * 1000 /* ms */);
double start_time1 = get_time();
const TSReader::Entry *full_flac = reader.find ("full.flac");
if (!full_flac)
{
error ("hls_mark: no embedded context found in %s\n", infile.c_str());
return 1;
}
SFInputStream in_stream;
err = in_stream.open (&full_flac->data);
if (err)
{
error ("hls_mark: %s\n", err.message());
return 1;
}
for (auto entry : reader.entries())
info ("%s %zd\n", entry.filename.c_str(), entry.data.size());
map<string, string> vars = reader.parse_vars ("vars");
for (auto kv : vars)
info ("|| %s=%s\n", kv.first.c_str(), kv.second.c_str());
size_t start_pos = atoi (vars["start_pos"].c_str());
size_t prev_size = atoi (vars["prev_size"].c_str());
size_t next_size = atoi (vars["next_size"].c_str());
size_t size = atoi (vars["size"].c_str());
double pts_start = atof (vars["pts_start"].c_str());
size_t prev_ctx = min<size_t> (1024 * 3, prev_size);
info ("hls_time_elapsed_decode %f\n", (get_time() - start_time1) * 1000 /* ms */);
start_time1 = get_time();
HLSOutputStream out_stream (in_stream.n_channels(), in_stream.sample_rate(), in_stream.bit_depth());
int bit_rate = Params::hls_bit_rate ? Params::hls_bit_rate : 256000;
out_stream.set_bit_rate (Params::hls_bit_rate ? Params::hls_bit_rate : 256000);
info ("n_frames = %zd\n", in_stream.n_frames() - prev_size - next_size);
const size_t shift = 1024;
const size_t cut_aac_frames = (prev_ctx + shift) / 1024;
const size_t delete_input_start = prev_size - prev_ctx;
const size_t keep_aac_frames = size / 1024;
err = out_stream.open (outfile, cut_aac_frames, keep_aac_frames, pts_start, delete_input_start);
if (err)
{
error ("audiowmark: error opening HLS output stream %s: %s\n", outfile.c_str(), err.message());
return 1;
}
int zrc = add_stream_watermark (&in_stream, &out_stream, bits, start_pos - prev_size);
if (zrc != 0)
{
info ("hls_time_abort_enc %f\n", (get_time() - start_time1) * 1000 /* ms */);
double end_time = get_time();
info ("hls_time_abort %f %f\n", start_pos / double (out_stream.sample_rate()), (end_time - start_time) * 1000 /* ms */);
return zrc;
}
info ("AAC Bitrate: %d\n", bit_rate);
info ("hls_time_elapsed_aac_enc %f\n", (get_time() - start_time1) * 1000 /* ms */);
double end_time = get_time();
info ("hls_time %f %f\n", start_pos / double (out_stream.sample_rate()), (end_time - start_time) * 1000 /* ms */);
return 0;
}
/*
* Copyright (C) 2018-2020 Stefan Westerfeld
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AUDIOWMARK_MPEGTS_HH
#define AUDIOWMARK_MPEGTS_HH
#include <string>
int hls_add (const std::string& infile, const std::string& outfile, const std::string& bits);
#endif /* AUDIOWMARK_MPEGTS_HH */
......@@ -53,6 +53,12 @@ HLSOutputStream::HLSOutputStream (int n_channels, int sample_rate, int bit_depth
{
}
void
HLSOutputStream::set_bit_rate (int bit_rate)
{
m_bit_rate = bit_rate;
}
HLSOutputStream::~HLSOutputStream()
{
close();
......@@ -81,7 +87,7 @@ HLSOutputStream::add_stream (AVCodec **codec, enum AVCodecID codec_id)
return Error ("codec type must be audio");
m_enc->sample_fmt = (*codec)->sample_fmts ? (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
m_enc->bit_rate = 128000;
m_enc->bit_rate = m_bit_rate;
m_enc->sample_rate = m_sample_rate;
if ((*codec)->supported_samplerates)
{
......
......@@ -56,6 +56,7 @@ class HLSOutputStream : public AudioOutputStream {
int m_n_channels = 0;
AudioBuffer m_audio_buffer;
size_t m_delete_input_start = 0;
int m_bit_rate = 0;
enum class State {
NEW,
......@@ -81,6 +82,7 @@ public:
HLSOutputStream (int n_channels, int sample_rate, int bit_depth);
~HLSOutputStream();
void set_bit_rate (int bit_rate);
Error open (const std::string& output_filename, size_t cut_aac_frames, size_t keep_aac_frames, double pts_start, size_t delete_input_start);
int bit_depth() const override;
int sample_rate() const override;
......
......@@ -18,6 +18,8 @@
#ifndef AUDIOWMARK_MPEGTS_HH
#define AUDIOWMARK_MPEGTS_HH
#include <map>
class TSReader
{
public:
......
......@@ -319,87 +319,6 @@ mark_zexpand (WavData& wav_data, size_t zero_frames, const string& bits)
return 0;
}
int
hls_mark (const string& infile, const string& outfile, const string& bits)
{
double start_time = get_time();
TSReader reader;
Error err = reader.load (infile);
if (err)
{
error ("hls_mark: %s\n", err.message());
return 1;
}
info ("hls_elapsed_load %f\n", (get_time() - start_time) * 1000 /* ms */);
double start_time1 = get_time();
const TSReader::Entry *full_flac = reader.find ("full.flac");
if (!full_flac)
{
error ("hls_mark: no embedded context found in %s\n", infile.c_str());
return 1;
}
SFInputStream in_stream;
err = in_stream.open (&full_flac->data);
if (err)
{
error ("hls_mark: %s\n", err.message());
return 1;
}
for (auto entry : reader.entries())
info ("%s %zd\n", entry.filename.c_str(), entry.data.size());
map<string, string> vars = reader.parse_vars ("vars");
for (auto kv : vars)
info ("|| %s=%s\n", kv.first.c_str(), kv.second.c_str());
size_t start_pos = atoi (vars["start_pos"].c_str());
size_t prev_size = atoi (vars["prev_size"].c_str());
size_t next_size = atoi (vars["next_size"].c_str());
size_t size = atoi (vars["size"].c_str());
double pts_start = atof (vars["pts_start"].c_str());
size_t prev_ctx = min<size_t> (1024 * 3, prev_size);
info ("hls_time_elapsed_decode %f\n", (get_time() - start_time1) * 1000 /* ms */);
start_time1 = get_time();
HLSOutputStream out_stream (in_stream.n_channels(), in_stream.sample_rate(), in_stream.bit_depth());
info ("n_frames = %zd\n", in_stream.n_frames() - prev_size - next_size);
const size_t shift = 1024;
const size_t cut_aac_frames = (prev_ctx + shift) / 1024;
const size_t delete_input_start = prev_size - prev_ctx;
const size_t keep_aac_frames = size / 1024;
err = out_stream.open (outfile, cut_aac_frames, keep_aac_frames, pts_start, delete_input_start);
if (err)
{
error ("audiowmark: error opening HLS output stream %s: %s\n", outfile.c_str(), err.message());
return 1;
}
int zrc = add_stream_watermark (&in_stream, &out_stream, bits, start_pos - prev_size);
if (zrc != 0)
{
info ("hls_time_abort_enc %f\n", (get_time() - start_time1) * 1000 /* ms */);
double end_time = get_time();
info ("hls_time_abort %f %f\n", start_pos / double (out_stream.sample_rate()), (end_time - start_time) * 1000 /* ms */);
return zrc;
}
info ("hls_time_elapsed_aac_enc %f\n", (get_time() - start_time1) * 1000 /* ms */);
double end_time = get_time();
info ("hls_time %f %f\n", start_pos / double (out_stream.sample_rate()), (end_time - start_time) * 1000 /* ms */);
return 0;
}
int
test_seek (const string& in, const string& out, int pos, const string& bits)
{
......@@ -464,10 +383,6 @@ main (int argc, char **argv)
info ("hls-embed-context: in_dir=%s out_dir=%s m3u8=%s audio_master=%s\n", argv[2], argv[3], argv[4], argv[5]);
return hls_embed_context (argv[2], argv[3], argv[4], argv[5]);
}
else if (argc == 5 && strcmp (argv[1], "hls-mark") == 0)
{
return hls_mark (argv[2], argv[3], argv[4]);
}
else if (argc == 6 && strcmp (argv[1], "test-seek") == 0)
{
return test_seek (argv[2], argv[3], atoi (argv[4]), argv[5]);
......
......@@ -39,6 +39,8 @@ Format Params::output_format = Format::AUTO;
RawFormat Params::raw_input_format;
RawFormat Params::raw_output_format;
int Params::hls_bit_rate = 0;
std::string Params::input_label;
std::string Params::output_label;
......
......@@ -69,6 +69,8 @@ public:
static RawFormat raw_input_format;
static RawFormat raw_output_format;
static int hls_bit_rate;
// input/output labels can be set for pretty output for videowmark add
static std::string input_label;
static std::string output_label;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment