mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-18 19:46:14 +02:00
sample format in codec
git-svn-id: svn://elaine/murooma/trunk@226 d8a302eb-03bc-478d-80e4-98257eca68ef
This commit is contained in:
parent
192aa6fd9e
commit
b7e63a91c8
7 changed files with 48 additions and 31 deletions
|
@ -2,7 +2,6 @@
|
||||||
#define DECODER_H
|
#define DECODER_H
|
||||||
#include "common/chunk.h"
|
#include "common/chunk.h"
|
||||||
|
|
||||||
|
|
||||||
class Decoder
|
class Decoder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,13 +1,24 @@
|
||||||
#ifndef ENCODER_H
|
#ifndef ENCODER_H
|
||||||
#define ENCODER_H
|
#define ENCODER_H
|
||||||
#include "common/chunk.h"
|
#include "common/chunk.h"
|
||||||
|
#include "common/sampleFormat.h"
|
||||||
|
|
||||||
|
|
||||||
class Encoder
|
class Encoder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Encoder();
|
Encoder(const SampleFormat& format) : sampleFormat(format)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual double encode(Chunk* chunk) = 0;
|
virtual double encode(Chunk* chunk) = 0;
|
||||||
|
virtual WireChunk* getHeader()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SampleFormat sampleFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,21 +5,16 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
OggEncoder::OggEncoder()
|
OggEncoder::OggEncoder(const SampleFormat& format) : Encoder(format), headerChunk(NULL)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
lastGranulepos = -1;
|
lastGranulepos = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool OggEncoder::getHeader(Chunk* chunk)
|
WireChunk* OggEncoder::getHeader()
|
||||||
{
|
{
|
||||||
WireChunk* wireChunk = chunk->wireChunk;
|
return headerChunk;
|
||||||
wireChunk->type = chunk_type::header;
|
|
||||||
wireChunk->payload = (char*)realloc(wireChunk->payload, oggHeaderLen);
|
|
||||||
memcpy(wireChunk->payload, oggHeader, oggHeaderLen);
|
|
||||||
wireChunk->length = oggHeaderLen;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,7 +132,7 @@ void OggEncoder::init()
|
||||||
|
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
ret=vorbis_encode_init_vbr(&vi,2,48000,0.7);
|
ret=vorbis_encode_init_vbr(&vi, sampleFormat.channels, sampleFormat.rate, 0.9);
|
||||||
|
|
||||||
/* do not continue if setup failed; this can happen if we ask for a
|
/* do not continue if setup failed; this can happen if we ask for a
|
||||||
mode that libVorbis does not support (eg, too low a bitrate, etc,
|
mode that libVorbis does not support (eg, too low a bitrate, etc,
|
||||||
|
@ -176,21 +171,22 @@ void OggEncoder::init()
|
||||||
*/
|
*/
|
||||||
// while(!eos){
|
// while(!eos){
|
||||||
size_t pos(0);
|
size_t pos(0);
|
||||||
oggHeader = (char*)malloc(0);
|
headerChunk = Chunk::makeChunk(chunk_type::header, 0);
|
||||||
oggHeaderLen = 0;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
int result=ogg_stream_flush(&os,&og);
|
int result=ogg_stream_flush(&os,&og);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
break;
|
break;
|
||||||
oggHeaderLen += og.header_len + og.body_len;
|
headerChunk->length += og.header_len + og.body_len;
|
||||||
oggHeader = (char*)realloc(oggHeader, oggHeaderLen);
|
headerChunk->payload = (char*)realloc(headerChunk->payload, headerChunk->length);
|
||||||
cout << "HeadLen: " << og.header_len << ", bodyLen: " << og.body_len << ", result: " << result << "\n";
|
cout << "HeadLen: " << og.header_len << ", bodyLen: " << og.body_len << ", result: " << result << "\n";
|
||||||
memcpy(oggHeader + pos, og.header, og.header_len);
|
memcpy(headerChunk->payload + pos, og.header, og.header_len);
|
||||||
pos += og.header_len;
|
pos += og.header_len;
|
||||||
memcpy(oggHeader + pos, og.body, og.body_len);
|
memcpy(headerChunk->payload + pos, og.body, og.body_len);
|
||||||
pos += og.body_len;
|
pos += og.body_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// fwrite(og.header,1,og.header_len,stdout);
|
// fwrite(og.header,1,og.header_len,stdout);
|
||||||
// fwrite(og.body,1,og.body_len,stdout);
|
// fwrite(og.body,1,og.body_len,stdout);
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
#include <vorbis/vorbisenc.h>
|
#include <vorbis/vorbisenc.h>
|
||||||
|
|
||||||
|
|
||||||
class OggEncoder
|
class OggEncoder : public Encoder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OggEncoder();
|
OggEncoder(const SampleFormat& format);
|
||||||
virtual double encode(Chunk* chunk);
|
virtual double encode(Chunk* chunk);
|
||||||
virtual bool getHeader(Chunk* chunk);
|
virtual WireChunk* getHeader();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
@ -31,11 +31,10 @@ private:
|
||||||
ogg_packet header_code;
|
ogg_packet header_code;
|
||||||
|
|
||||||
ogg_int64_t lastGranulepos;
|
ogg_int64_t lastGranulepos;
|
||||||
|
WireChunk* headerChunk;
|
||||||
|
|
||||||
int eos=0,ret;
|
int eos=0,ret;
|
||||||
int i, founddata;
|
int i, founddata;
|
||||||
char* oggHeader;
|
|
||||||
int oggHeaderLen;
|
|
||||||
|
|
||||||
int32_t tv_sec;
|
int32_t tv_sec;
|
||||||
int32_t tv_usec;
|
int32_t tv_usec;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "pcmEncoder.h"
|
#include "pcmEncoder.h"
|
||||||
|
|
||||||
PcmEncoder::PcmEncoder()
|
PcmEncoder::PcmEncoder(const SampleFormat& format) : Encoder(format)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
#include "encoder.h"
|
#include "encoder.h"
|
||||||
|
|
||||||
|
|
||||||
class PcmEncoder
|
class PcmEncoder : public Encoder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PcmEncoder();
|
PcmEncoder(const SampleFormat& format);
|
||||||
virtual double encode(Chunk* chunk);
|
virtual double encode(Chunk* chunk);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,8 @@ cout << "Sending header: " << headerChunk->wireChunk->length << "\n";
|
||||||
|
|
||||||
void setHeader(shared_ptr<Chunk> chunk)
|
void setHeader(shared_ptr<Chunk> chunk)
|
||||||
{
|
{
|
||||||
headerChunk = chunk;
|
if (chunk && (chunk->wireChunk != NULL))
|
||||||
|
headerChunk = shared_ptr<Chunk>(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(shared_ptr<Chunk> chunk)
|
void send(shared_ptr<Chunk> chunk)
|
||||||
|
@ -220,13 +221,15 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
size_t port;
|
size_t port;
|
||||||
string fifoName;
|
string fifoName;
|
||||||
|
string codec;
|
||||||
bool runAsDaemon;
|
bool runAsDaemon;
|
||||||
|
|
||||||
po::options_description desc("Allowed options");
|
po::options_description desc("Allowed options");
|
||||||
desc.add_options()
|
desc.add_options()
|
||||||
("help,h", "produce help message")
|
("help,h", "produce help message")
|
||||||
("port,p", po::value<size_t>(&port)->default_value(98765), "port to listen on")
|
("port,p", po::value<size_t>(&port)->default_value(98765), "port to listen on")
|
||||||
("sampleformat,f", po::value<string>(&sampleFormat)->default_value("48000:16:2"), "sample format")
|
("sampleformat,s", po::value<string>(&sampleFormat)->default_value("48000:16:2"), "sample format")
|
||||||
|
("codec,c", po::value<string>(&codec)->default_value("ogg"), "transport codec [ogg|pcm]")
|
||||||
("fifo,f", po::value<string>(&fifoName)->default_value("/tmp/snapfifo"), "name of fifo file")
|
("fifo,f", po::value<string>(&fifoName)->default_value("/tmp/snapfifo"), "name of fifo file")
|
||||||
("daemon,d", po::bool_switch(&runAsDaemon)->default_value(false), "daemonize")
|
("daemon,d", po::bool_switch(&runAsDaemon)->default_value(false), "daemonize")
|
||||||
;
|
;
|
||||||
|
@ -276,9 +279,18 @@ int main(int argc, char* argv[])
|
||||||
size_t duration = 50;
|
size_t duration = 50;
|
||||||
|
|
||||||
SampleFormat format(sampleFormat);
|
SampleFormat format(sampleFormat);
|
||||||
OggEncoder encoder;
|
std::auto_ptr<Encoder> encoder;
|
||||||
shared_ptr<Chunk> header(new Chunk(format, Chunk::makeChunk(chunk_type::header, 0)));
|
if (codec == "ogg")
|
||||||
encoder.getHeader(header.get());
|
encoder.reset(new OggEncoder(sampleFormat));
|
||||||
|
else if (codec == "pcm")
|
||||||
|
encoder.reset(new PcmEncoder(sampleFormat));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cout << "unknown codec: " << codec << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<Chunk> header(new Chunk(format, encoder->getHeader()));
|
||||||
server->setHeader(header);
|
server->setHeader(header);
|
||||||
|
|
||||||
while (!g_terminated)
|
while (!g_terminated)
|
||||||
|
@ -307,7 +319,7 @@ size_t duration = 50;
|
||||||
|
|
||||||
wireChunk->tv_sec = tvChunk.tv_sec;
|
wireChunk->tv_sec = tvChunk.tv_sec;
|
||||||
wireChunk->tv_usec = tvChunk.tv_usec;
|
wireChunk->tv_usec = tvChunk.tv_usec;
|
||||||
double chunkDuration = encoder.encode(chunk.get());
|
double chunkDuration = encoder->encode(chunk.get());
|
||||||
if (chunkDuration > 0)
|
if (chunkDuration > 0)
|
||||||
server->send(chunk);
|
server->send(chunk);
|
||||||
//cout << wireChunk->tv_sec << ", " << wireChunk->tv_usec / 1000 << "\n";
|
//cout << wireChunk->tv_sec << ", " << wireChunk->tv_usec / 1000 << "\n";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue