Commit 0e847611 authored by Stefan Westerfeld's avatar Stefan Westerfeld

HLS: support non-stereo channel layout

Signed-off-by: Stefan Westerfeld's avatarStefan Westerfeld <stefan@space.twc.de>
parent a520fdbc
......@@ -249,6 +249,8 @@ hls_add (const string& infile, const string& outfile, const string& bits)
int bit_rate = atoi (get_var ("bit_rate"));
size_t prev_ctx = min<size_t> (1024 * 3, prev_size);
string channel_layout = get_var ("channel_layout");
if (missing_vars)
return 1;
......@@ -258,6 +260,7 @@ hls_add (const string& infile, const string& outfile, const string& bits)
HLSOutputStream out_stream (in_stream.n_channels(), in_stream.sample_rate(), in_stream.bit_depth());
out_stream.set_bit_rate (bit_rate);
out_stream.set_channel_layout (channel_layout);
const size_t shift = 1024;
const size_t cut_aac_frames = (prev_ctx + shift) / 1024;
......@@ -326,7 +329,7 @@ load_audio_master (const string& filename, WavData& audio_master_data)
}
Error
validate_input_segment (const string& filename)
probe_input_segment (const string& filename, map<string, string>& params)
{
TSReader reader;
......@@ -353,8 +356,6 @@ validate_input_segment (const string& filename)
for (auto o : format_out)
{
/* parse assignments stream|index=0|codec_name=aac|... */
map<string, string> params;
string key, value;
bool in_key = true;
for (char c : '|' + o + '|')
......@@ -378,18 +379,6 @@ validate_input_segment (const string& filename)
value += c;
}
}
/* now the actual validation */
if (atoi (params["index"].c_str()) != 0)
{
error ("audiowmark: hls segment '%s' contains more than one stream\n", filename.c_str());
return Error ("failed to validate input segment");
}
if (params["codec_name"] != "aac")
{
error ("audiowmark hls segment '%s' is not encoded using AAC\n", filename.c_str());
return Error ("failed to validate input segment");
}
}
return Error::Code::NONE;
}
......@@ -473,12 +462,34 @@ hls_prepare (const string& in_dir, const string& out_dir, const string& filename
}
for (auto& segment : segments)
{
Error err = validate_input_segment (in_dir + "/" + segment.name);
map<string, string> params;
string segname = in_dir + "/" + segment.name;
Error err = probe_input_segment (segname, params);
if (err)
{
error ("audiowmark: hls: %s\n", err.message());
return 1;
}
/* validate input segment */
if (atoi (params["index"].c_str()) != 0)
{
error ("audiowmark: hls segment '%s' contains more than one stream\n", segname.c_str());
return 1;
}
if (params["codec_name"] != "aac")
{
error ("audiowmark hls segment '%s' is not encoded using AAC\n", segname.c_str());
return 1;
}
/* get segment parameters */
if (params["channel_layout"].empty())
{
error ("audiowmark hls segment '%s' has no channel_layout entry\n", segname.c_str());
return 1;
}
segment.vars["channel_layout"] = params["channel_layout"];
}
/* find bitrate for AAC encoder */
......
......@@ -63,6 +63,12 @@ HLSOutputStream::set_bit_rate (int bit_rate)
m_bit_rate = bit_rate;
}
void
HLSOutputStream::set_channel_layout (const string& channel_layout)
{
m_channel_layout = channel_layout;
}
HLSOutputStream::~HLSOutputStream()
{
close();
......@@ -107,18 +113,22 @@ HLSOutputStream::add_stream (AVCodec **codec, enum AVCodecID codec_id)
if (!match)
return Error (string_printf ("no codec support for sample rate %d", m_sample_rate));
}
m_enc->channels = av_get_channel_layout_nb_channels (m_enc->channel_layout);
m_enc->channel_layout = AV_CH_LAYOUT_STEREO;
uint64_t want_layout = av_get_channel_layout (m_channel_layout.c_str());
if (!want_layout)
return Error (string_printf ("bad channel layout '%s'", m_channel_layout.c_str()));
m_enc->channel_layout = want_layout;
if ((*codec)->channel_layouts)
{
m_enc->channel_layout = (*codec)->channel_layouts[0];
for (int i = 0; (*codec)->channel_layouts[i]; i++)
{
if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO)
m_enc->channel_layout = AV_CH_LAYOUT_STEREO;
if ((*codec)->channel_layouts[i] == want_layout)
m_enc->channel_layout = want_layout;
}
}
m_enc->channels = av_get_channel_layout_nb_channels (m_enc->channel_layout);
if (want_layout != m_enc->channel_layout)
return Error (string_printf ("codec: unsupported channel layout '%s'", m_channel_layout.c_str()));
m_enc->channels = av_get_channel_layout_nb_channels (m_enc->channel_layout);
m_st->time_base = (AVRational){ 1, m_enc->sample_rate };
/* Some formats want stream headers to be separate. */
......
......@@ -55,6 +55,7 @@ class HLSOutputStream : public AudioOutputStream {
AudioBuffer m_audio_buffer;
size_t m_delete_input_start = 0;
int m_bit_rate = 0;
std::string m_channel_layout;
enum class State {
NEW,
......@@ -81,6 +82,8 @@ public:
~HLSOutputStream();
void set_bit_rate (int bit_rate);
void set_channel_layout (const std::string& channel_layout);
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;
......
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