70
69
// Get attributes of the audio source:
71
unsigned char const bitsPerSample = pcmSource->bitsPerSample();
72
if (bitsPerSample != 8 && bitsPerSample != 16) {
73
*env << "The input file contains " << bitsPerSample
74
<< " bit-per-sample audio, which we don't handle\n";
70
unsigned char audioFormat = wavSource->getAudioFormat();
71
unsigned char const bitsPerSample = wavSource->bitsPerSample();
72
// We handle only 4,8,16,20,24 bits-per-sample audio:
73
if (bitsPerSample%4 != 0 || bitsPerSample < 4 || bitsPerSample > 24 || bitsPerSample == 12) {
74
*env << "The input file contains " << bitsPerSample << " bit-per-sample audio, which we don't handle\n";
77
sessionState.source = pcmSource;
78
unsigned const samplingFrequency = pcmSource->samplingFrequency();
79
unsigned char const numChannels = pcmSource->numChannels();
80
unsigned bitsPerSecond
81
= samplingFrequency*bitsPerSample*numChannels;
77
unsigned const samplingFrequency = wavSource->samplingFrequency();
78
unsigned char const numChannels = wavSource->numChannels();
79
unsigned bitsPerSecond = samplingFrequency*bitsPerSample*numChannels;
82
80
*env << "Audio source parameters:\n\t" << samplingFrequency << " Hz, ";
83
81
*env << bitsPerSample << " bits-per-sample, ";
84
82
*env << numChannels << " channels => ";
85
83
*env << bitsPerSecond << " bits-per-second\n";
86
unsigned char payloadFormatCode = 96; // by default, unless a static RTP payload type can be used
87
88
// Add in any filter necessary to transform the data prior to streaming.
88
89
// (This is where any audio compression would get added.)
90
unsigned char payloadFormatCode;
91
if (bitsPerSample == 16) {
90
sessionState.source = wavSource; // by default
91
if (audioFormat == WA_PCM) {
92
if (bitsPerSample == 16) {
93
// Note that samples in the WAV audio file are in little-endian order.
92
94
#ifdef CONVERT_TO_ULAW
93
// Add a filter that converts from raw 16-bit PCM audio (in little-endian order)
94
// to 8-bit u-law audio:
96
= uLawFromPCMAudioSource::createNew(*env, pcmSource, 1/*little-endian*/);
97
if (sessionState.source == NULL) {
98
*env << "Unable to create a u-law filter from the PCM audio source: "
99
<< env->getResultMsg() << "\n";
104
if (samplingFrequency == 8000 && numChannels == 1) {
105
payloadFormatCode = 0; // a static RTP payload type
107
payloadFormatCode = 96; // a dynamic RTP payload type
109
*env << "Converting to 8-bit u-law audio for streaming => "
110
<< bitsPerSecond << " bits-per-second\n";
95
// Add a filter that converts from raw 16-bit PCM audio (in little-endian order) to 8-bit u-law audio:
96
sessionState.source = uLawFromPCMAudioSource::createNew(*env, wavSource, 1/*little-endian*/);
97
if (sessionState.source == NULL) {
98
*env << "Unable to create a u-law filter from the PCM audio source: " << env->getResultMsg() << "\n";
101
*env << "Converting to 8-bit u-law audio for streaming => " << bitsPerSecond << " bits-per-second\n";
104
if (samplingFrequency == 8000 && numChannels == 1) {
105
payloadFormatCode = 0; // a static RTP payload type
112
// The 16-bit samples in WAV files are in little-endian order.
113
// Add a filter that converts them to network (i.e., big-endian) order:
114
sessionState.source = EndianSwap16::createNew(*env, pcmSource);
115
if (sessionState.source == NULL) {
116
*env << "Unable to create a little->bit-endian order filter from the PCM audio source: "
117
<< env->getResultMsg() << "\n";
121
if (samplingFrequency == 44100 && numChannels == 2) {
122
payloadFormatCode = 10; // a static RTP payload type
123
} else if (samplingFrequency == 44100 && numChannels == 1) {
124
payloadFormatCode = 11; // a static RTP payload type
126
payloadFormatCode = 96; // a dynamic RTP payload type
128
*env << "Converting to network byte order for streaming\n";
108
// Add a filter that converts from little-endian to network (big-endian) order:
109
sessionState.source = EndianSwap16::createNew(*env, wavSource);
110
if (sessionState.source == NULL) {
111
*env << "Unable to create a little->bit-endian order filter from the PCM audio source: " << env->getResultMsg() << "\n";
114
*env << "Converting to network byte order for streaming\n";
116
if (samplingFrequency == 44100 && numChannels == 2) {
117
payloadFormatCode = 10; // a static RTP payload type
118
} else if (samplingFrequency == 44100 && numChannels == 1) {
119
payloadFormatCode = 11; // a static RTP payload type
130
} else { // bitsPerSample == 8
131
// Don't do any transformation; send the 8-bit PCM data 'as is':
133
payloadFormatCode = 96; // a dynamic RTP payload type
122
} else if (bitsPerSample == 20 || bitsPerSample == 24) {
123
// Add a filter that converts from little-endian to network (big-endian) order:
124
sessionState.source = EndianSwap24::createNew(*env, wavSource);
125
if (sessionState.source == NULL) {
126
*env << "Unable to create a little->bit-endian order filter from the PCM audio source: " << env->getResultMsg() << "\n";
129
*env << "Converting to network byte order for streaming\n";
130
mimeType = bitsPerSample == 20 ? "L20" : "L24";
131
} else { // bitsPerSample == 8 (we assume that bitsPerSample == 4 is only for WA_IMA_ADPCM)
132
// Don't do any transformation; send the 8-bit PCM data 'as is':
135
} else if (audioFormat == WA_PCMU) {
137
if (samplingFrequency == 8000 && numChannels == 1) {
138
payloadFormatCode = 0; // a static RTP payload type
140
} else if (audioFormat == WA_PCMA) {
142
if (samplingFrequency == 8000 && numChannels == 1) {
143
payloadFormatCode = 8; // a static RTP payload type
145
} else if (audioFormat == WA_IMA_ADPCM) {
147
// Use a static payload type, if one is defined:
148
if (numChannels == 1) {
149
if (samplingFrequency == 8000) {
150
payloadFormatCode = 5; // a static RTP payload type
151
} else if (samplingFrequency == 16000) {
152
payloadFormatCode = 6; // a static RTP payload type
153
} else if (samplingFrequency == 11025) {
154
payloadFormatCode = 16; // a static RTP payload type
155
} else if (samplingFrequency == 22050) {
156
payloadFormatCode = 17; // a static RTP payload type
159
} else { //unknown format
160
*env << "Unknown audio format code \"" << audioFormat << "\" in WAV file header\n";
136
164
// Create 'groupsocks' for RTP and RTCP:
137
165
struct in_addr destinationAddress;
138
166
destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
139
167
// Note: This is a multicast address. If you wish instead to stream
140
// using unicast, then you should use the "testOnDemandRTSPServer"
141
// test program - not this test program - as a model.
168
// using unicast, then you should use the "testOnDemandRTSPServer" demo application,
169
// or the "LIVE555 Media Server" - not this application - as a model.
143
171
const unsigned short rtpPortNum = 2222;
144
172
const unsigned short rtcpPortNum = rtpPortNum+1;