summaryrefslogtreecommitdiffstats
path: root/plugins/recording/encoder_ogg.cpp
diff options
context:
space:
mode:
authorMichele Calgaro <michele.calgaro@yahoo.it>2022-05-30 19:40:31 +0900
committerMichele Calgaro <michele.calgaro@yahoo.it>2022-05-31 01:17:58 +0900
commitd95a4fea540b371fa86493d069fdbd54f33c5b40 (patch)
tree079b038ab559439eb7ded40a07bd79fd92926b3b /plugins/recording/encoder_ogg.cpp
parente54890e0480e5adee69f5220a7c6dd072bbd75ea (diff)
downloadtderadio-d95a4fea540b371fa86493d069fdbd54f33c5b40.tar.gz
tderadio-d95a4fea540b371fa86493d069fdbd54f33c5b40.zip
Standardize folder structure.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'plugins/recording/encoder_ogg.cpp')
-rw-r--r--plugins/recording/encoder_ogg.cpp250
1 files changed, 250 insertions, 0 deletions
diff --git a/plugins/recording/encoder_ogg.cpp b/plugins/recording/encoder_ogg.cpp
new file mode 100644
index 0000000..ca093b9
--- /dev/null
+++ b/plugins/recording/encoder_ogg.cpp
@@ -0,0 +1,250 @@
+/***************************************************************************
+ encoder_ogg.cpp
+ -------------------
+ begin : Sat Aug 20 2005
+ copyright : (C) 2005 by Martin Witte
+ email : witte@kawo1.rwth-aachen.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "encoder_ogg.h"
+
+#include <tdelocale.h>
+#include <stdlib.h>
+
+RecordingEncodingOgg::RecordingEncodingOgg(TQObject *parent, SoundStreamID ssid,
+ const RecordingConfig &cfg, const RadioStation *rs,
+ const TQString &filename)
+ : RecordingEncoding(parent, ssid, cfg, rs, filename)
+#ifdef HAVE_OGG
+ ,
+ m_OggOutput(NULL),
+ m_OggExportBuffer(NULL),
+ m_OggExportBufferSize(0)
+#endif
+{
+ m_config.m_OutputFormat = RecordingConfig::outputOGG;
+ m_config.m_SoundFormat.m_Encoding = "ogg";
+ openOutput(filename);
+}
+
+
+RecordingEncodingOgg::~RecordingEncodingOgg()
+{
+ closeOutput();
+}
+
+void RecordingEncodingOgg::encode(const char *_buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size)
+{
+ if (m_error)
+ return;
+
+#ifdef HAVE_OGG
+ SoundFormat &sf = m_config.m_SoundFormat;
+ ogg_page ogg_pg;
+ ogg_packet ogg_pkt;
+
+ size_t samples = buffer_size / sf.frameSize();
+
+ // buffer[channel][sample], normalized to -1..0..+1
+ float **buffer = vorbis_analysis_buffer(&m_VorbisDSP, (samples < 512 ? 512 : samples));
+
+ sf.convertSamplesToFloat(_buffer, buffer, samples);
+
+ /* Tell the library how many samples (per channel) we wrote
+ into the supplied buffer */
+ vorbis_analysis_wrote(&m_VorbisDSP, samples);
+
+ /* While we can get enough data from the library to analyse, one
+ block at a time... */
+
+ bool eos = false;
+ while(!m_error && !eos && vorbis_analysis_blockout(&m_VorbisDSP, &m_VorbisBlock) == 1) {
+
+ /* Do the main analysis, creating a packet */
+ vorbis_analysis(&m_VorbisBlock, NULL);
+ vorbis_bitrate_addblock(&m_VorbisBlock);
+
+ while(!m_error && vorbis_bitrate_flushpacket(&m_VorbisDSP, &ogg_pkt)) {
+ /* Add packet to bitstream */
+ ogg_stream_packetin(&m_OggStream,&ogg_pkt);
+
+ /* If we've gone over a page boundary, we can do actual output,
+ so do so (for however many pages are available) */
+
+ while(!m_error && !eos) {
+ int result = ogg_stream_pageout(&m_OggStream, &ogg_pg);
+ if (!result) break;
+
+ int n = fwrite(ogg_pg.header, 1, ogg_pg.header_len, m_OggOutput);
+ n += fwrite(ogg_pg.body, 1, ogg_pg.body_len, m_OggOutput);
+
+ m_encodedSize += n;
+
+ if (n != (ogg_pg.header_len + ogg_pg.body_len)) {
+ m_error = true;
+ m_errorString += i18n("Failed writing data to ogg/vorbis output stream. ");
+ break;
+ } else {
+
+ if (m_OggExportBufferSize < export_buffer_size + n) {
+ m_OggExportBuffer = (char*)realloc(m_OggExportBuffer, m_OggExportBufferSize + 2 * n);
+ m_OggExportBufferSize += 2 * n;
+ }
+
+ memcpy (m_OggExportBuffer + export_buffer_size, ogg_pg.header, ogg_pg.header_len);
+ export_buffer_size += ogg_pg.header_len;
+ memcpy (m_OggExportBuffer + export_buffer_size, ogg_pg.body, ogg_pg.body_len);
+ export_buffer_size += ogg_pg.body_len;
+
+ }
+ if (ogg_page_eos(&ogg_pg))
+ eos = 1;
+ }
+ }
+ }
+
+ export_buffer = m_OggExportBuffer;
+#endif
+}
+
+
+#ifdef HAVE_OGG
+static void vorbis_comment_add_tag_new(vorbis_comment *vc, const TQString &tag, const TQString &value)
+{
+ char *stag = strdup(tag.ascii());
+ char *svalue = strdup(value.utf8());
+ vorbis_comment_add_tag(vc, stag, svalue);
+ delete stag;
+ delete svalue;
+}
+#endif
+
+bool RecordingEncodingOgg::openOutput(const TQString &output)
+{
+#ifdef HAVE_OGG
+ m_OggOutput = fopen(output.ascii(), "wb+");
+ if (!m_OggOutput) {
+ m_errorString += i18n("Cannot open Ogg/Vorbis output file %1. ").arg(output);
+ m_error = true;
+ }
+
+ m_OggExportBuffer = (char*)malloc(m_OggExportBufferSize = 65536); // start with a 64k buffer
+
+
+ /* Have vorbisenc choose a mode for us */
+ vorbis_info_init(&m_VorbisInfo);
+
+ SoundFormat &sf = m_config.m_SoundFormat;
+ if (vorbis_encode_setup_vbr(&m_VorbisInfo, sf.m_Channels, sf.m_SampleRate, m_config.m_oggQuality)) {
+ m_error = true;
+ m_errorString = i18n("Ogg/Vorbis Mode initialisation failed: invalid parameters for quality\n");
+ vorbis_info_clear(&m_VorbisInfo);
+ return false;
+ }
+
+ /* Turn off management entirely (if it was turned on). */
+ vorbis_encode_ctl(&m_VorbisInfo, OV_ECTL_RATEMANAGE_SET, NULL);
+ vorbis_encode_setup_init(&m_VorbisInfo);
+
+ /* Now, set up the analysis engine, stream encoder, and other
+ preparation before the encoding begins.
+ */
+
+ vorbis_analysis_init(&m_VorbisDSP, &m_VorbisInfo);
+ vorbis_block_init(&m_VorbisDSP, &m_VorbisBlock);
+
+ ogg_stream_init (&m_OggStream, m_SoundStreamID.getID());
+
+ /* Now, build the three header packets and send through to the stream
+ output stage (but defer actual file output until the main encode loop) */
+
+ ogg_packet header_main;
+ ogg_packet header_comments;
+ ogg_packet header_codebooks;
+
+ /* Build the packets */
+ vorbis_comment vc;
+ vorbis_comment_init (&vc);
+ vorbis_comment_add_tag_new(&vc, "creator", "TDERadio" VERSION);
+ vorbis_comment_add_tag_new(&vc, "title", m_RadioStation->longName().utf8());
+ vorbis_comment_add_tag_new(&vc, "date", TQDateTime::currentDateTime().toString(Qt::ISODate));
+
+ vorbis_analysis_headerout(&m_VorbisDSP, &vc,
+ &header_main, &header_comments, &header_codebooks);
+
+ /* And stream them out */
+ ogg_stream_packetin(&m_OggStream, &header_main);
+ ogg_stream_packetin(&m_OggStream, &header_comments);
+ ogg_stream_packetin(&m_OggStream, &header_codebooks);
+
+ int result;
+ ogg_page ogg_page;
+ while((result = ogg_stream_flush(&m_OggStream, &ogg_page))) {
+
+ if (!result) break;
+
+ int n = fwrite(ogg_page.header, 1, ogg_page.header_len, m_OggOutput);
+ n += fwrite(ogg_page.body, 1, ogg_page.body_len, m_OggOutput);
+
+ if(n != ogg_page.header_len + ogg_page.body_len) {
+ m_error = true;
+ m_errorString += i18n("Failed writing Ogg/Vorbis header to output stream\n");
+ break;
+ }
+ }
+
+ vorbis_comment_clear (&vc);
+
+ if (m_error) {
+ if (m_OggOutput) fclose (m_OggOutput);
+ m_OggOutput = NULL;
+ free(m_OggExportBuffer);
+ m_OggExportBuffer = NULL;
+ m_OggExportBufferSize = 0;
+
+ ogg_stream_clear(&m_OggStream);
+ vorbis_block_clear(&m_VorbisBlock);
+ vorbis_dsp_clear(&m_VorbisDSP);
+ vorbis_info_clear(&m_VorbisInfo);
+ }
+
+ return !m_error;
+#endif
+}
+
+
+void RecordingEncodingOgg::closeOutput()
+{
+#ifdef HAVE_OGG
+ if (m_OggOutput) {
+
+ char *tmp_buf = NULL;
+ size_t tmp_size = 0;
+ // flush buffer
+ encode(tmp_buf, tmp_size, tmp_buf, tmp_size);
+
+ fclose(m_OggOutput);
+ m_OggOutput = NULL;
+
+ free(m_OggExportBuffer);
+ m_OggExportBuffer = NULL;
+ m_OggExportBufferSize = 0;
+
+ ogg_stream_clear(&m_OggStream);
+ vorbis_block_clear(&m_VorbisBlock);
+ vorbis_dsp_clear(&m_VorbisDSP);
+ vorbis_info_clear(&m_VorbisInfo);
+ }
+#endif
+}
+
+