[Jackrtp-cvs] jackrtp/src JackSink.cpp,NONE,1.1 jackrtp_receive.cpp,NONE,1.1 JThread.c,1.1.1.1,1.2 M
Status: Alpha
Brought to you by:
p_tisserand
|
From: Francois D. <dec...@us...> - 2004-07-29 13:05:26
|
Update of /cvsroot/jackrtp/jackrtp/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32623/src Modified Files: JThread.c Makefile.am Added Files: JackSink.cpp jackrtp_receive.cpp Log Message: Merged receive part, which was in a separate source tree. --- NEW FILE: jackrtp_receive.cpp --- /* jackRtp Copyright (C) 2004 by IRCAM-Centre Georges Pompidou, Paris, France. This file is part of jackRtp. jackRtp 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. jackRtp 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 jackRtp; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <stdio.h> #include <iostream> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <pthread.h> #include <liveMedia.hh> #include <BasicUsageEnvironment.hh> #include <GroupsockHelper.hh> #include <jacklive/JackSink.hh> #include <jacklive/threadinfo.h> //the default ringbuffersize #define DEFAULT_RB_SIZE 16384 const size_t sample_size = sizeof(jack_default_audio_sample_t); extern "C" { /*our unique client pointer*/ jack_client_t *client = NULL; /*jack functions*/ int process (jack_nframes_t nframes, void *args); void jack_shutdown (void *arg); void setup_ports(jack_thread_info_t *info); }; struct sessionState_t { FramedSource* source; RTCPInstance* rtcpInstance; } sessionState; void jacklive_usage() { fprintf(stderr,"usage : jackrtp_receive [multicast-address] [rtp-port]\n" " [multicast-address] you want to send to (destination)\n" " [rtp-port] you want to send to, the rtcp-port will be (rtp-port+1)\n" " example: jackrtp_receive 239.255.85.136 6669\n"); } int main (int argc, char *argv[]) { /*Jack*/ jack_thread_info_t thread_info; /*Live*/ UsageEnvironment* env; const unsigned char ttl = 217; unsigned long jackSinkBufferSize = 3000; if(argc != 3) { jacklive_usage(); } else { /* if we have more than one jackrtp_receive application connected to the jack server */ char clientName[50]; sprintf(clientName, "jackrtp_receive-%d", getpid()); if ((client = jack_client_new (clientName)) == 0) { fprintf (stderr, "We need the jack server to connect us as client.\n"); fprintf (stderr, "Do you have the jack server running?\n"); exit (1); } /*setup the jack client*/ memset(&thread_info, 0, sizeof(thread_info)); /*we need those control variables to know when we can start to run the jackprocess*/ thread_info.can_process = 0; thread_info.can_read = 0; /*set the callback for our client*/ jack_set_process_callback (client, process, &thread_info); jack_on_shutdown (client, jack_shutdown, &thread_info); /*get and set the nframes - by default it is 1024*/ thread_info.nframes = jack_get_buffer_size(client); /*create a ringbuffer for exchange of audio data between live and jack jack will write into the ringbuffer and live will read it and put the data into RTP packets*/ thread_info.ringbuffer = jack_ringbuffer_create(DEFAULT_RB_SIZE); /*setup live - Begin by setting up our Usage Environment*/ TaskScheduler* scheduler = BasicTaskScheduler::createNew(); env = BasicUsageEnvironment::createNew(*scheduler); /*now we set up the address*/ char* destinationAddressStr = argv[1]; const unsigned short rtpPortNum = atoi(argv[2]); const unsigned short rtcpPortNum = rtpPortNum+1; struct in_addr destinationAddress; destinationAddress.s_addr = our_inet_addr(destinationAddressStr); const Port rtpPort(rtpPortNum); const Port rtcpPort(rtcpPortNum); /*create our groupsocks*/ Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl); Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl); RTPSource* rtpSource; unsigned char rtpPayloadFormat = 96; char const* mimeType = "L8"; rtpSource = SimpleRTPSource::createNew(*env, &rtpGroupsock, rtpPayloadFormat, 0, mimeType, 0, True); // Create (and start) a 'RTCP instance' for the RTP source: const unsigned totalSessionBandwidth = 160; // in kbps; for RTCP b/w share const unsigned maxCNAMElen = 100; unsigned char CNAME[maxCNAMElen+1]; gethostname((char*)CNAME, maxCNAMElen); CNAME[maxCNAMElen] = '\0'; // just in case sessionState.rtcpInstance = RTCPInstance::createNew(*env, &rtcpGroupsock, totalSessionBandwidth, CNAME, NULL /* we're a client */, rtpSource); /// unsigned m_num_mebers = sessionState.rtcpInstance->numMembers(); *env <<"num_members : "<<m_num_mebers<<"\n"; /// // Note: This starts RTCP running automatically thread_info.channels = 2; /*Setup the Jack outputports*/ setup_ports(&thread_info); /*Activate the jackclient*/ if(jack_activate (client)) *env <<"cannot activate client!\n"; else *env <<"We got the Jack client activated!\n"; /*Create JackSink */ JackSink *jackSink; jackSink = JackSink::createNew(*env, &thread_info ,jackSinkBufferSize); if (NULL == jackSink) { *env << "Failed to create JackSink for \"" << "\": " << env->getResultMsg() << "\n"; } else { *env <<"Outputting data to the ringbuffer\n"; } jackSink->startPlaying(*rtpSource,NULL,NULL); *env << "We play the subsession now\n"; env->taskScheduler().doEventLoop(); /* does not return*/ sleep (100); /*Close the Media*/ Medium::close(jackSink); //Medium::close(sessionState.source); Medium::close(sessionState.rtcpInstance); /*Close the JackClient*/ jack_client_close (client); jack_ringbuffer_free (thread_info.ringbuffer); fprintf (stderr, "jlclientThe jack server shutdown\n"); /*terminates the process which calls this function - 0 means normal termination*/ exit(0); } return 0; } Index: Makefile.am =================================================================== RCS file: /cvsroot/jackrtp/jackrtp/src/Makefile.am,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** Makefile.am 29 Jul 2004 11:37:07 -0000 1.1.1.1 --- Makefile.am 29 Jul 2004 13:04:58 -0000 1.2 *************** *** 1,6 **** ! bin_PROGRAMS = jackrtp_send ! jackrtp_send_SOURCES = jackrtp_send.cpp \ ! JThread.c \ ! JackSource.cpp INCLUDES=@LIVE_MEDIA_INCLUDES@ -I$(top_srcdir)/include @JACK_CFLAGS@ --- 1,13 ---- ! bin_PROGRAMS = jackrtp_send jackrtp_receive ! ! jackrtp_send_SOURCES = \ ! jackrtp_send.cpp \ ! JThread.c \ ! JackSource.cpp ! ! jackrtp_receive_SOURCES = \ ! jackrtp_receive.cpp \ ! JThread.c \ ! JackSink.cpp INCLUDES=@LIVE_MEDIA_INCLUDES@ -I$(top_srcdir)/include @JACK_CFLAGS@ Index: JThread.c =================================================================== RCS file: /cvsroot/jackrtp/jackrtp/src/JThread.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** JThread.c 29 Jul 2004 11:37:07 -0000 1.1.1.1 --- JThread.c 29 Jul 2004 13:04:58 -0000 1.2 *************** *** 32,35 **** --- 32,36 ---- /*You may only access it using the API provided*/ static jack_default_audio_sample_t **in; + static jack_default_audio_sample_t **out; *************** *** 48,52 **** ! int process(jack_nframes_t nframes, jack_thread_info_t *info) { int chn; --- 49,53 ---- ! int process_in(jack_nframes_t nframes, jack_thread_info_t *info) { int chn; *************** *** 76,88 **** } ! void setup_ports(jack_thread_info_t *info) { unsigned int i; ! size_t in_size; /* Allocate data structures that depend on the number of ports. */ ports = (jack_port_t **) malloc (sizeof (jack_port_t *) * info->channels); ! in_size = info->channels * sizeof (jack_default_audio_sample_t *); ! in = (jack_default_audio_sample_t **) malloc (in_size); /* When JACK is running realtime, jack_activate() will have --- 77,122 ---- } ! int process_out(jack_nframes_t nframes, jack_thread_info_t *info) ! { ! size_t chn; ! size_t i; ! size_t nb_byte_read = 0; ! size_t bytes_available = 0; ! ! /* Do nothing until we're ready to begin. */ ! if ((!info->can_process) || (!info->can_read)) ! return 0; ! ! /* This returns a pointer to the memory area associated with the specified port.*/ ! for (chn = 0; chn < info->channels; chn++) ! out[chn] = jack_port_get_buffer (ports[chn], nframes); ! ! bytes_available = jack_ringbuffer_read_space(info->ringbuffer); ! ! if(bytes_available >= (nframes * info->channels)) ! { ! ///we got interleaved data in the ringbuffer -> we can read the nframes * number of channels in one time ! for(i = 0; i < nframes; i++) ! { ! for(chn = 0; chn < info->channels; chn++) ! { ! nb_byte_read = jack_ringbuffer_read(info->ringbuffer,(char *) (out[chn]+i), sizeof(float)); ! if(nb_byte_read < sizeof(float)) ! overruns++; ! } ! } ! } ! return 0; ! } ! ! void setup_ports(jack_thread_info_t *info, int is_input) { unsigned int i; ! size_t size; /* Allocate data structures that depend on the number of ports. */ ports = (jack_port_t **) malloc (sizeof (jack_port_t *) * info->channels); ! size = info->channels * sizeof (jack_default_audio_sample_t *); ! in = (jack_default_audio_sample_t **) malloc (size); /* When JACK is running realtime, jack_activate() will have *************** *** 92,108 **** * create a delay that would force JACK to shut us down. */ ! memset(in, 0, in_size); //fills the n-bytes(in_size) of the pointed memory area(in) //with that byte(0) ->in this case we initialize with zero ! memset(info->ringbuffer->buf, 0, info->ringbuffer->size); //same here for (i = 0; i < info->channels; i++) { ! char name[64]; ! sprintf (name, "input%d", i+1); ! if ((ports[i] = jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) { ! fprintf (stderr, "cannot register input port \"%s\"!\n", name); jack_client_close (client); exit (1); --- 126,156 ---- * create a delay that would force JACK to shut us down. */ ! if (is_input) ! memset(in, 0, size); //fills the n-bytes(size) of the pointed memory area(in) ! else ! memset(out, 0, size); //fills the n-bytes(size) of the pointed memory area(in) ! //with that byte(0) ->in this case we initialize with zero ! memset( info->ringbuffer->buf, 0, info->ringbuffer->size); //same here for (i = 0; i < info->channels; i++) { ! char name[64]; ! const char *port_dir; ! if (is_input) ! { ! sprintf (name, "input%d", i+1); ! port_dir = JackPortIsInput; ! } ! else ! { ! sprintf (name, "output%d", i+1); ! port_dir = JackPortIsOutput; ! } ! if ((ports[i] = jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, port_dir, 0)) == 0) { ! fprintf (stderr, "cannot register port \"%s\"!\n", name); jack_client_close (client); exit (1); --- NEW FILE: JackSink.cpp --- /* jackRtp Copyright (C) 2004 by IRCAM-Centre Georges Pompidou, Paris, France. This file is part of jackRtp. jackRtp 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. jackRtp 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 jackRtp; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define MAX_RTP_PACKET_SIZE 1400 // maximun length for a RTP packet #include <iostream> #include <liveMedia.hh> #include <jacklive/threadinfo.h> #include <jacklive/JackSink.hh> #include <GroupsockHelper.hh> ////////// JackSink ////////// JackSink::JackSink(UsageEnvironment& env, jack_thread_info_t* thread_info, unsigned long bufferSize) : MediaSink(env), m_thread_info(thread_info), fBufferSize(bufferSize) { fBuffer = new unsigned char[bufferSize]; debugFile = fopen( "/net/store/u.worksta/agnula/schampij/test/OUT", "w"); } JackSink::~JackSink() { delete[] fBuffer; fclose(debugFile); } JackSink* JackSink::createNew(UsageEnvironment& env, jack_thread_info_t* thread_info, unsigned long bufferSize) { JackSink* newSink; do { newSink = NULL; newSink = new JackSink(env, thread_info, bufferSize); if (newSink == NULL) break; return newSink; } while (0); delete newSink; return NULL; } Boolean JackSink::continuePlaying() { m_thread_info->can_read = 1; short sample; float *fsample; fsample = new float[1]; size_t space_for_writing = 0; size_t nbytes_write = 0; const float fScaler16 = (float)(1.0f / 0x7FFFL); if(fSource == NULL) return False; fSource->getNextFrame(fBuffer, fBufferSize, afterGettingFrame, this, onSourceClosure, this); ///check for the space for writing in the ringbuffer space_for_writing = jack_ringbuffer_write_space(m_thread_info->ringbuffer); if(space_for_writing >= MAX_RTP_PACKET_SIZE*2) { /*bring the data we got from the RTP packets into little endian byte order*/ for(int i = 0; i < (MAX_RTP_PACKET_SIZE); i+=2) { unsigned char *p = (unsigned char *)&sample; p[0] = fBuffer[i+1]; p[1] = fBuffer[i]; /*convert our sample from short to float - how samples are represented in JACK in audio applications we use floats in the range from [-1;1] -> so we have to divide*/ *fsample = static_cast<float>(sample) * fScaler16; /*and write it to the ringbuffer*/ nbytes_write = jack_ringbuffer_write(m_thread_info->ringbuffer, (const char*)fsample, sizeof(float)); } } delete[] fsample; return True; } void JackSink::afterGettingFrame(void* clientData, unsigned frameSize, unsigned /*numTruncatedBytes*/, struct timeval presentationTime, unsigned /*durationInMicroseconds*/) { JackSink* sink = (JackSink*)clientData; sink->afterGettingFrame1(frameSize, presentationTime); } void JackSink::afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) { // Then try getting the next frame: continuePlaying(); } |